From 1037d567fdfc7ab9d3e2328e27bdc1300d3fdb1e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 21 Nov 2013 12:38:44 -0200 Subject: ASoC: wm8737: Use IS_ENABLED() macro Using the IS_ENABLED() macro can make the code shorter and simpler. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 2f167a8..22de242 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -644,7 +644,7 @@ static const struct regmap_config wm8737_regmap = { .volatile_reg = wm8737_volatile, }; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) static int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -758,7 +758,7 @@ static struct spi_driver wm8737_spi_driver = { static int __init wm8737_modinit(void) { int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8737_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n", @@ -781,7 +781,7 @@ static void __exit wm8737_exit(void) #if defined(CONFIG_SPI_MASTER) spi_unregister_driver(&wm8737_spi_driver); #endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8737_i2c_driver); #endif } -- cgit v0.10.2 From 060ec80a27bf7a00bafb0c7495bbeec92e7903d3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 21 Nov 2013 12:38:51 -0200 Subject: ASoC: wm8983: Use IS_ENABLED() macro Using the IS_ENABLED() macro can make the code shorter and simpler. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index aa41ba0..3bae71d 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1129,7 +1129,7 @@ static struct spi_driver wm8983_spi_driver = { }; #endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) static int wm8983_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -1182,7 +1182,7 @@ static int __init wm8983_modinit(void) { int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8983_i2c_driver); if (ret) { printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", @@ -1202,7 +1202,7 @@ module_init(wm8983_modinit); static void __exit wm8983_exit(void) { -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8983_i2c_driver); #endif #if defined(CONFIG_SPI_MASTER) -- cgit v0.10.2 From 9848e49a9a9aab075d79c5d2856abb879495f97f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 16 Jan 2014 03:38:58 +0400 Subject: xtensa: fix warning '"CONFIG_OF" is not defined' The warning only shows up when building MMUv3 configuration with OF support disabled. Signed-off-by: Max Filippov diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h index 2a042d4..7494420 100644 --- a/arch/xtensa/include/asm/io.h +++ b/arch/xtensa/include/asm/io.h @@ -25,7 +25,7 @@ #ifdef CONFIG_MMU -#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF +#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF) extern unsigned long xtensa_kio_paddr; static inline unsigned long xtensa_get_kio_paddr(void) diff --git a/arch/xtensa/include/asm/vectors.h b/arch/xtensa/include/asm/vectors.h index 5791b45..f74ddfb 100644 --- a/arch/xtensa/include/asm/vectors.h +++ b/arch/xtensa/include/asm/vectors.h @@ -25,7 +25,7 @@ #define XCHAL_KIO_DEFAULT_PADDR 0xf0000000 #define XCHAL_KIO_SIZE 0x10000000 -#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF +#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF) #define XCHAL_KIO_PADDR xtensa_get_kio_paddr() #else #define XCHAL_KIO_PADDR XCHAL_KIO_DEFAULT_PADDR diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index 36ec171..861203e 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c @@ -39,7 +39,7 @@ void init_mmu(void) set_itlbcfg_register(0); set_dtlbcfg_register(0); #endif -#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF +#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF) /* * Update the IO area mapping in case xtensa_kio_paddr has changed */ -- cgit v0.10.2 From 45ec8860be2f681b2e3e521a3fb4554ec29fbaac Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 19 Jan 2014 20:00:48 +0400 Subject: xtensa: export ccount_freq Now that ccount_freq is used in udelay and ndelay it needs to be exported in order to be available to modules. Signed-off-by: Max Filippov diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 08b769d..2a1823d 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -30,6 +30,7 @@ #include unsigned long ccount_freq; /* ccount Hz */ +EXPORT_SYMBOL(ccount_freq); static cycle_t ccount_read(struct clocksource *cs) { -- cgit v0.10.2 From b2cbb6e1c1544fc889ee7d6c6a6c229c20cd03cd Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 23 Jan 2014 13:02:47 +0800 Subject: ASoC: core: set_tdm_slot() will return -ENOTSUPP if no operation provided Make it easier for generic code to work with set_tdm_slot() by distinguishing between the operation not being supported and an error as is done. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50..393ff06 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3626,7 +3626,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); else - return -EINVAL; + return -ENOTSUPP; } EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); -- cgit v0.10.2 From e2fd1374c705abe4661df3fb6fadb3879c7c1846 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 22 Jan 2014 08:04:43 +0400 Subject: xtensa: introduce spill_registers_kernel macro Most in-kernel users want registers spilled on the kernel stack and don't require PS.EXCM to be set. That means that they don't need fixup routine and could reuse regular window overflow mechanism for that, which makes spill routine very simple. Cc: stable@vger.kernel.org Suggested-by: Chris Zankel Signed-off-by: Max Filippov diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h index 8c194f6..677bfcf 100644 --- a/arch/xtensa/include/asm/traps.h +++ b/arch/xtensa/include/asm/traps.h @@ -23,25 +23,37 @@ void secondary_trap_init(void); static inline void spill_registers(void) { - +#if XCHAL_NUM_AREGS > 16 __asm__ __volatile__ ( - "movi a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t" - "mov a12, a0\n\t" - "rsr a13, sar\n\t" - "xsr a14, ps\n\t" - "movi a0, _spill_registers\n\t" - "rsync\n\t" - "callx0 a0\n\t" - "mov a0, a12\n\t" - "wsr a13, sar\n\t" - "wsr a14, ps\n\t" - : : -#if defined(CONFIG_FRAME_POINTER) - : "a2", "a3", "a4", "a11", "a12", "a13", "a14", "a15", + " call12 1f\n" + " _j 2f\n" + " retw\n" + " .align 4\n" + "1:\n" + " _entry a1, 48\n" + " addi a12, a0, 3\n" +#if XCHAL_NUM_AREGS > 32 + " .rept (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n" + " _entry a1, 48\n" + " mov a12, a0\n" + " .endr\n" +#endif + " _entry a1, 48\n" +#if XCHAL_NUM_AREGS % 12 == 0 + " mov a8, a8\n" +#elif XCHAL_NUM_AREGS % 12 == 4 + " mov a12, a12\n" +#elif XCHAL_NUM_AREGS % 12 == 8 + " mov a4, a4\n" +#endif + " retw\n" + "2:\n" + : : : "a12", "a13", "memory"); #else - : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", + __asm__ __volatile__ ( + " mov a12, a12\n" + : : : "memory"); #endif - "memory"); } #endif /* _XTENSA_TRAPS_H */ diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 21dbe6b..0489918e 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1794,6 +1794,43 @@ ENTRY(system_call) ENDPROC(system_call) +/* + * Spill live registers on the kernel stack macro. + * + * Entry condition: ps.woe is set, ps.excm is cleared + * Exit condition: windowstart has single bit set + * May clobber: a12, a13 + */ + .macro spill_registers_kernel + +#if XCHAL_NUM_AREGS > 16 + call12 1f + _j 2f + retw + .align 4 +1: + _entry a1, 48 + addi a12, a0, 3 +#if XCHAL_NUM_AREGS > 32 + .rept (XCHAL_NUM_AREGS - 32) / 12 + _entry a1, 48 + mov a12, a0 + .endr +#endif + _entry a1, 48 +#if XCHAL_NUM_AREGS % 12 == 0 + mov a8, a8 +#elif XCHAL_NUM_AREGS % 12 == 4 + mov a12, a12 +#elif XCHAL_NUM_AREGS % 12 == 8 + mov a4, a4 +#endif + retw +2: +#else + mov a12, a12 +#endif + .endm /* * Task switch. @@ -1806,21 +1843,20 @@ ENTRY(_switch_to) entry a1, 16 - mov a12, a2 # preserve 'prev' (a2) - mov a13, a3 # and 'next' (a3) + mov a10, a2 # preserve 'prev' (a2) + mov a11, a3 # and 'next' (a3) l32i a4, a2, TASK_THREAD_INFO l32i a5, a3, TASK_THREAD_INFO - save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER + save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER - s32i a0, a12, THREAD_RA # save return address - s32i a1, a12, THREAD_SP # save stack pointer + s32i a0, a10, THREAD_RA # save return address + s32i a1, a10, THREAD_SP # save stack pointer /* Disable ints while we manipulate the stack pointer. */ - movi a14, (1 << PS_EXCM_BIT) | LOCKLEVEL - xsr a14, ps + rsil a14, LOCKLEVEL rsr a3, excsave1 rsync s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */ @@ -1835,7 +1871,7 @@ ENTRY(_switch_to) /* Flush register file. */ - call0 _spill_registers # destroys a3, a4, and SAR + spill_registers_kernel /* Set kernel stack (and leave critical section) * Note: It's save to set it here. The stack will not be overwritten @@ -1851,13 +1887,13 @@ ENTRY(_switch_to) /* restore context of the task 'next' */ - l32i a0, a13, THREAD_RA # restore return address - l32i a1, a13, THREAD_SP # restore stack pointer + l32i a0, a11, THREAD_RA # restore return address + l32i a1, a11, THREAD_SP # restore stack pointer - load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER + load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER wsr a14, ps - mov a2, a12 # return 'prev' + mov a2, a10 # return 'prev' rsync retw -- cgit v0.10.2 From 3251f1e27a5a17f0efd436cfd1e7b9896cfab0a0 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 30 Oct 2013 16:18:25 +0400 Subject: xtensa: save current register frame in fast_syscall_spill_registers_fixup We need it saved because it contains a3 where we track which register windows we still need to spill, and fixup handler may call C exception handlers. Also fix comments. Cc: stable@vger.kernel.org Signed-off-by: Max Filippov diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 0489918e..b61e251 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1117,6 +1117,13 @@ ENDPROC(fast_syscall_spill_registers) * We basically restore WINDOWBASE and WINDOWSTART to the condition when * we entered the spill routine and jump to the user exception handler. * + * Note that we only need to restore the bits in windowstart that have not + * been spilled yet by the _spill_register routine. Luckily, a3 contains a + * rotated windowstart with only those bits set for frames that haven't been + * spilled yet. Because a3 is rotated such that bit 0 represents the register + * frame for the current windowbase - 1, we need to rotate a3 left by the + * value of the current windowbase + 1 and move it to windowstart. + * * a0: value of depc, original value in depc * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE * a3: exctable, original value in excsave1 @@ -1131,10 +1138,15 @@ ENTRY(fast_syscall_spill_registers_fixup) /* We need to make sure the current registers (a0-a3) are preserved. * To do this, we simply set the bit for the current window frame * in WS, so that the exception handlers save them to the task stack. + * + * Note: we use a3 to set the windowbase, so we take a special care + * of it, saving it in the original _spill_registers frame across + * the exception handler call. */ xsr a3, excsave1 # get spill-mask slli a3, a3, 1 # shift left by one + addi a3, a3, 1 # set the bit for the current window frame slli a2, a3, 32-WSBITS src a2, a3, a2 # a2 = xxwww1yyxxxwww1yy...... -- cgit v0.10.2 From 5ad8865b009bc8ad35adcbcb60c0679d437e8036 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 27 Jan 2014 17:37:51 +0200 Subject: ASoC: davinci-evm: Add named clock reference to DT bindings The referenced clock is used to get codec clock rate and the clock is disabled and enabled in startup and shutdown snd_soc_ops call backs. The change is also documented in DT bindigs document. Signed-off-by: Jyri Sarha cc: bcousson@baylibre.com Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt index 865178d..963e100 100644 --- a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt @@ -5,12 +5,19 @@ Required properties: - ti,model : The user-visible name of this sound complex. - ti,audio-codec : The phandle of the TLV320AIC3x audio codec - ti,mcasp-controller : The phandle of the McASP controller -- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec - ti,audio-routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. Valid names for sources and sinks are the codec's pins, and the jacks on the board: +Optional properties: +- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec. +- clocks : Reference to the master clock +- clock-names : The clock should be named "mclk" +- Either codec-clock-rate or the codec-clock reference has to be defined. If + the both are defined the driver attempts to set referenced clock to the + defined rate and takes the rate from the clock reference. + Board connectors: * Headphone Jack diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 70ff377..d3e4cb0 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -30,9 +31,34 @@ #include "davinci-i2s.h" struct snd_soc_card_drvdata_davinci { + struct clk *mclk; unsigned sysclk; }; +static int evm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *soc_card = rtd->codec->card; + struct snd_soc_card_drvdata_davinci *drvdata = + snd_soc_card_get_drvdata(soc_card); + + if (drvdata->mclk) + return clk_prepare_enable(drvdata->mclk); + + return 0; +} + +static void evm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *soc_card = rtd->codec->card; + struct snd_soc_card_drvdata_davinci *drvdata = + snd_soc_card_get_drvdata(soc_card); + + if (drvdata->mclk) + clk_disable_unprepare(drvdata->mclk); +} + static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -59,6 +85,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, } static struct snd_soc_ops evm_ops = { + .startup = evm_startup, + .shutdown = evm_shutdown, .hw_params = evm_hw_params, }; @@ -348,6 +376,7 @@ static int davinci_evm_probe(struct platform_device *pdev) of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; struct snd_soc_card_drvdata_davinci *drvdata = NULL; + struct clk *mclk; int ret = 0; evm_soc_card.dai_link = dai; @@ -367,13 +396,38 @@ static int davinci_evm_probe(struct platform_device *pdev) if (ret) return ret; + mclk = devm_clk_get(&pdev->dev, "mclk"); + if (PTR_ERR(mclk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(mclk)) { + dev_dbg(&pdev->dev, "mclk not found.\n"); + mclk = NULL; + } + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; + drvdata->mclk = mclk; + ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); - if (ret < 0) - return -EINVAL; + + if (ret < 0) { + if (!drvdata->mclk) { + dev_err(&pdev->dev, + "No clock or clock rate defined.\n"); + return -EINVAL; + } + drvdata->sysclk = clk_get_rate(drvdata->mclk); + } else if (drvdata->mclk) { + unsigned int requestd_rate = drvdata->sysclk; + clk_set_rate(drvdata->mclk, drvdata->sysclk); + drvdata->sysclk = clk_get_rate(drvdata->mclk); + if (drvdata->sysclk != requestd_rate) + dev_warn(&pdev->dev, + "Could not get requested rate %u using %u.\n", + requestd_rate, drvdata->sysclk); + } snd_soc_card_set_drvdata(&evm_soc_card, drvdata); ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); -- cgit v0.10.2 From ab8b14b6d841b314434f5817c107572f923fc43d Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 27 Jan 2014 17:37:52 +0200 Subject: ASoC: davinci-mcasp: Set BCLK divider if McASP is BCLK master Make BCLK divider setting implicite in hw_params call if McASP device is the bit clock master on the audio serial bus. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b7858bf..ae328be 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -53,6 +53,9 @@ struct davinci_mcasp { u16 bclk_lrclk_ratio; int streams; + int sysclk_freq; + bool bclk_master; + /* McASP FIFO related */ u8 txnumevt; u8 rxnumevt; @@ -292,6 +295,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); + mcasp->bclk_master = 1; break; case SND_SOC_DAIFMT_CBM_CFS: /* codec is clock master and frame slave */ @@ -303,6 +307,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); + mcasp->bclk_master = 0; break; case SND_SOC_DAIFMT_CBM_CFM: /* codec is clock and frame master */ @@ -314,6 +319,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); + mcasp->bclk_master = 0; break; default: @@ -405,6 +411,8 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX); } + mcasp->sysclk_freq = freq; + return 0; } @@ -607,6 +615,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, int channels; struct snd_interval *pcm_channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + + /* If mcasp is BCLK master we need to set BCLK divider */ + if (mcasp->bclk_master) { + unsigned int bclk_freq = snd_soc_params_to_bclk(params); + if (mcasp->sysclk_freq % bclk_freq != 0) { + dev_err(mcasp->dev, "Can't produce requred BCLK\n"); + return -EINVAL; + } + davinci_mcasp_set_clkdiv( + cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); + } + channels = pcm_channels->min; active_serializers = (channels + slots - 1) / slots; -- cgit v0.10.2 From 29191039e21f66e204acffed63c486674a1918bd Mon Sep 17 00:00:00 2001 From: Yufeng Shen Date: Mon, 27 Jan 2014 18:02:46 -0500 Subject: HID: usbhid: quirk for CY-TM75 75 inch Touch Overlay There is timeout error during initialization: kernel: [ 11.733104] hid-multitouch 0003:1870:0110.0001: usb_submit_urb(ctrl) failed: -1 kernel: [ 11.734093] hid-multitouch 0003:1870:0110.0001: timeout initializing reports Adding quirk HID_QUIRK_NO_INIT_REPORTS can solve the problem. Signed-off-by: Yufeng Shen Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 92b40c0..7b9f79e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -642,6 +642,7 @@ #define USB_VENDOR_ID_NEXIO 0x1870 #define USB_DEVICE_ID_NEXIO_MULTITOUCH_420 0x010d +#define USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750 0x0110 #define USB_VENDOR_ID_NEXTWINDOW 0x1926 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 175ec0a..dbd8387 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -74,6 +74,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, -- cgit v0.10.2 From 117309c51dca42121f70cacec801511b76acf75c Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Tue, 28 Jan 2014 16:17:57 +0100 Subject: HID: microsoft: Add ID's for Surface Type/Touch Cover 2 The Microsoft Surface Type/Touch cover 2 devices have the flag HID_DG_CONTACTID in their reports.This causes the device to bind to the hid-multitouch driver, which doesn't handle generic keyboard/mouse input events. The patch adds the hardware id's of the device to hid-microsoft and to the HID special driver array, which makes the device get handled by hid-generic/hid-input properly. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=64811 Singed-off-by: Reyad Attiyat Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 026ab0f..6ed8f5f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1779,6 +1779,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 7b9f79e..a348ba0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -617,6 +617,8 @@ #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c +#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 +#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index c6ef6ee..404a3a8 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -208,6 +208,10 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), .driver_data = MS_DUPLICATE_USAGES }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), + .driver_data = 0 }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), + .driver_data = 0 }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, -- cgit v0.10.2 From 3db187e7bf76ace626664ef80afbc2e1501172c6 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 23 Jan 2014 16:33:14 -0500 Subject: HID: multitouch: add FocalTech FTxxxx support This is a Win7 device which does not work correctly with the default settings (not the previous default BT). However, the quirk ALWAYS_TRUE makes it working like a charm. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index a348ba0..2f10e6e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -240,6 +240,7 @@ #define USB_VENDOR_ID_CYGNAL 0x10c4 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a +#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH 0x81b9 #define USB_VENDOR_ID_CYPRESS 0x04b4 #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index f134d73..221d503 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1166,6 +1166,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, USB_DEVICE_ID_MULTITOUCH_3200) }, + /* FocalTech Panels */ + { .driver_data = MT_CLS_SERIAL, + MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL, + USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) }, + /* GeneralTouch panel */ { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS, MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, -- cgit v0.10.2 From 6b5a1f74e50170e64104135490dc32b657483594 Mon Sep 17 00:00:00 2001 From: Chris Zankel Date: Tue, 28 Jan 2014 22:09:51 -0800 Subject: xtensa: fix fast_syscall_spill_registers The original implementation could clobber registers under certain conditions. The Xtensa processor architecture uses windowed registers and the original implementation was using a4 as a temporary register, which under certain conditions could be register a0 of the oldest window frame, and didn't always restore the content correctly. By moving the _spill_registers routine inside the fast system call, it frees up one more register (the return address is not required anymore) for the spill routine. Signed-off-by: Chris Zankel diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index b61e251..ef7f499 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1081,34 +1081,202 @@ ENTRY(fast_syscall_spill_registers) rsr a0, sar s32i a3, a2, PT_AREG3 - s32i a4, a2, PT_AREG4 - s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5 + s32i a0, a2, PT_SAR - /* The spill routine might clobber a7, a11, and a15. */ + /* The spill routine might clobber a4, a7, a8, a11, a12, and a15. */ + s32i a4, a2, PT_AREG4 s32i a7, a2, PT_AREG7 + s32i a8, a2, PT_AREG8 s32i a11, a2, PT_AREG11 + s32i a12, a2, PT_AREG12 s32i a15, a2, PT_AREG15 - call0 _spill_registers # destroys a3, a4, and SAR + /* + * Rotate ws so that the current windowbase is at bit 0. + * Assume ws = xxxwww1yy (www1 current window frame). + * Rotate ws right so that a4 = yyxxxwww1. + */ + + rsr a0, windowbase + rsr a3, windowstart # a3 = xxxwww1yy + ssr a0 # holds WB + slli a0, a3, WSBITS + or a3, a3, a0 # a3 = xxxwww1yyxxxwww1yy + srl a3, a3 # a3 = 00xxxwww1yyxxxwww1 + + /* We are done if there are no more than the current register frame. */ + + extui a3, a3, 1, WSBITS-1 # a3 = 0yyxxxwww + movi a0, (1 << (WSBITS-1)) + _beqz a3, .Lnospill # only one active frame? jump + + /* We want 1 at the top, so that we return to the current windowbase */ + + or a3, a3, a0 # 1yyxxxwww + + /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */ + + wsr a3, windowstart # save shifted windowstart + neg a0, a3 + and a3, a0, a3 # first bit set from right: 000010000 + + ffs_ws a0, a3 # a0: shifts to skip empty frames + movi a3, WSBITS + sub a0, a3, a0 # WSBITS-a0:number of 0-bits from right + ssr a0 # save in SAR for later. + + rsr a3, windowbase + add a3, a3, a0 + wsr a3, windowbase + rsync + + rsr a3, windowstart + srl a3, a3 # shift windowstart + + /* WB is now just one frame below the oldest frame in the register + window. WS is shifted so the oldest frame is in bit 0, thus, WB + and WS differ by one 4-register frame. */ + + /* Save frames. Depending what call was used (call4, call8, call12), + * we have to save 4,8. or 12 registers. + */ + + +.Lloop: _bbsi.l a3, 1, .Lc4 + _bbci.l a3, 2, .Lc12 + +.Lc8: s32e a4, a13, -16 + l32e a4, a5, -12 + s32e a8, a4, -32 + s32e a5, a13, -12 + s32e a6, a13, -8 + s32e a7, a13, -4 + s32e a9, a4, -28 + s32e a10, a4, -24 + s32e a11, a4, -20 + srli a11, a3, 2 # shift windowbase by 2 + rotw 2 + _bnei a3, 1, .Lloop + j .Lexit + +.Lc4: s32e a4, a9, -16 + s32e a5, a9, -12 + s32e a6, a9, -8 + s32e a7, a9, -4 + + srli a7, a3, 1 + rotw 1 + _bnei a3, 1, .Lloop + j .Lexit + +.Lc12: _bbci.l a3, 3, .Linvalid_mask # bit 2 shouldn't be zero! + + /* 12-register frame (call12) */ + + l32e a0, a5, -12 + s32e a8, a0, -48 + mov a8, a0 + + s32e a9, a8, -44 + s32e a10, a8, -40 + s32e a11, a8, -36 + s32e a12, a8, -32 + s32e a13, a8, -28 + s32e a14, a8, -24 + s32e a15, a8, -20 + srli a15, a3, 3 + + /* The stack pointer for a4..a7 is out of reach, so we rotate the + * window, grab the stackpointer, and rotate back. + * Alternatively, we could also use the following approach, but that + * makes the fixup routine much more complicated: + * rotw 1 + * s32e a0, a13, -16 + * ... + * rotw 2 + */ + + rotw 1 + mov a4, a13 + rotw -1 + + s32e a4, a8, -16 + s32e a5, a8, -12 + s32e a6, a8, -8 + s32e a7, a8, -4 + + rotw 3 + + _beqi a3, 1, .Lexit + j .Lloop + +.Lexit: + + /* Done. Do the final rotation and set WS */ + + rotw 1 + rsr a3, windowbase + ssl a3 + movi a3, 1 + sll a3, a3 + wsr a3, windowstart +.Lnospill: /* Advance PC, restore registers and SAR, and return from exception. */ - l32i a3, a2, PT_AREG5 - l32i a4, a2, PT_AREG4 + l32i a3, a2, PT_SAR l32i a0, a2, PT_AREG0 wsr a3, sar l32i a3, a2, PT_AREG3 /* Restore clobbered registers. */ + l32i a4, a2, PT_AREG4 l32i a7, a2, PT_AREG7 + l32i a8, a2, PT_AREG8 l32i a11, a2, PT_AREG11 + l32i a12, a2, PT_AREG12 l32i a15, a2, PT_AREG15 movi a2, 0 rfe +.Linvalid_mask: + + /* We get here because of an unrecoverable error in the window + * registers, so set up a dummy frame and kill the user application. + * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer. + */ + + movi a0, 1 + movi a1, 0 + + wsr a0, windowstart + wsr a1, windowbase + rsync + + movi a0, 0 + + rsr a3, excsave1 + l32i a1, a3, EXC_TABLE_KSTK + + movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL + wsr a4, ps + rsync + + movi a6, SIGSEGV + movi a4, do_exit + callx4 a4 + + /* shouldn't return, so panic */ + + wsr a0, excsave1 + movi a0, unrecoverable_exception + callx0 a0 # should not return +1: j 1b + + ENDPROC(fast_syscall_spill_registers) /* Fixup handler. @@ -1232,209 +1400,6 @@ ENTRY(fast_syscall_spill_registers_fixup_return) ENDPROC(fast_syscall_spill_registers_fixup_return) -/* - * spill all registers. - * - * This is not a real function. The following conditions must be met: - * - * - must be called with call0. - * - uses a3, a4 and SAR. - * - the last 'valid' register of each frame are clobbered. - * - the caller must have registered a fixup handler - * (or be inside a critical section) - * - PS_EXCM must be set (PS_WOE cleared?) - */ - -ENTRY(_spill_registers) - - /* - * Rotate ws so that the current windowbase is at bit 0. - * Assume ws = xxxwww1yy (www1 current window frame). - * Rotate ws right so that a4 = yyxxxwww1. - */ - - rsr a4, windowbase - rsr a3, windowstart # a3 = xxxwww1yy - ssr a4 # holds WB - slli a4, a3, WSBITS - or a3, a3, a4 # a3 = xxxwww1yyxxxwww1yy - srl a3, a3 # a3 = 00xxxwww1yyxxxwww1 - - /* We are done if there are no more than the current register frame. */ - - extui a3, a3, 1, WSBITS-1 # a3 = 0yyxxxwww - movi a4, (1 << (WSBITS-1)) - _beqz a3, .Lnospill # only one active frame? jump - - /* We want 1 at the top, so that we return to the current windowbase */ - - or a3, a3, a4 # 1yyxxxwww - - /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */ - - wsr a3, windowstart # save shifted windowstart - neg a4, a3 - and a3, a4, a3 # first bit set from right: 000010000 - - ffs_ws a4, a3 # a4: shifts to skip empty frames - movi a3, WSBITS - sub a4, a3, a4 # WSBITS-a4:number of 0-bits from right - ssr a4 # save in SAR for later. - - rsr a3, windowbase - add a3, a3, a4 - wsr a3, windowbase - rsync - - rsr a3, windowstart - srl a3, a3 # shift windowstart - - /* WB is now just one frame below the oldest frame in the register - window. WS is shifted so the oldest frame is in bit 0, thus, WB - and WS differ by one 4-register frame. */ - - /* Save frames. Depending what call was used (call4, call8, call12), - * we have to save 4,8. or 12 registers. - */ - - _bbsi.l a3, 1, .Lc4 - _bbsi.l a3, 2, .Lc8 - - /* Special case: we have a call12-frame starting at a4. */ - - _bbci.l a3, 3, .Lc12 # bit 3 shouldn't be zero! (Jump to Lc12 first) - - s32e a4, a1, -16 # a1 is valid with an empty spill area - l32e a4, a5, -12 - s32e a8, a4, -48 - mov a8, a4 - l32e a4, a1, -16 - j .Lc12c - -.Lnospill: - ret - -.Lloop: _bbsi.l a3, 1, .Lc4 - _bbci.l a3, 2, .Lc12 - -.Lc8: s32e a4, a13, -16 - l32e a4, a5, -12 - s32e a8, a4, -32 - s32e a5, a13, -12 - s32e a6, a13, -8 - s32e a7, a13, -4 - s32e a9, a4, -28 - s32e a10, a4, -24 - s32e a11, a4, -20 - - srli a11, a3, 2 # shift windowbase by 2 - rotw 2 - _bnei a3, 1, .Lloop - -.Lexit: /* Done. Do the final rotation, set WS, and return. */ - - rotw 1 - rsr a3, windowbase - ssl a3 - movi a3, 1 - sll a3, a3 - wsr a3, windowstart - ret - -.Lc4: s32e a4, a9, -16 - s32e a5, a9, -12 - s32e a6, a9, -8 - s32e a7, a9, -4 - - srli a7, a3, 1 - rotw 1 - _bnei a3, 1, .Lloop - j .Lexit - -.Lc12: _bbci.l a3, 3, .Linvalid_mask # bit 2 shouldn't be zero! - - /* 12-register frame (call12) */ - - l32e a2, a5, -12 - s32e a8, a2, -48 - mov a8, a2 - -.Lc12c: s32e a9, a8, -44 - s32e a10, a8, -40 - s32e a11, a8, -36 - s32e a12, a8, -32 - s32e a13, a8, -28 - s32e a14, a8, -24 - s32e a15, a8, -20 - srli a15, a3, 3 - - /* The stack pointer for a4..a7 is out of reach, so we rotate the - * window, grab the stackpointer, and rotate back. - * Alternatively, we could also use the following approach, but that - * makes the fixup routine much more complicated: - * rotw 1 - * s32e a0, a13, -16 - * ... - * rotw 2 - */ - - rotw 1 - mov a5, a13 - rotw -1 - - s32e a4, a9, -16 - s32e a5, a9, -12 - s32e a6, a9, -8 - s32e a7, a9, -4 - - rotw 3 - - _beqi a3, 1, .Lexit - j .Lloop - -.Linvalid_mask: - - /* We get here because of an unrecoverable error in the window - * registers. If we are in user space, we kill the application, - * however, this condition is unrecoverable in kernel space. - */ - - rsr a0, ps - _bbci.l a0, PS_UM_BIT, 1f - - /* User space: Setup a dummy frame and kill application. - * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer. - */ - - movi a0, 1 - movi a1, 0 - - wsr a0, windowstart - wsr a1, windowbase - rsync - - movi a0, 0 - - rsr a3, excsave1 - l32i a1, a3, EXC_TABLE_KSTK - - movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL - wsr a4, ps - rsync - - movi a6, SIGSEGV - movi a4, do_exit - callx4 a4 - -1: /* Kernel space: PANIC! */ - - wsr a0, excsave1 - movi a0, unrecoverable_exception - callx0 a0 # should not return -1: j 1b - -ENDPROC(_spill_registers) - #ifdef CONFIG_MMU /* * We should never get here. Bail out! -- cgit v0.10.2 From 0475c947d221f9250bbdf430b2604f828b643ee0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 25 Jan 2014 19:46:23 -0200 Subject: ata: pata_imx: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Signed-off-by: Tejun Heo diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 26386f0..b0b18ec 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -119,7 +119,9 @@ static int pata_imx_probe(struct platform_device *pdev) return PTR_ERR(priv->clk); } - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; host = ata_host_alloc(&pdev->dev, 1); if (!host) { @@ -212,7 +214,9 @@ static int pata_imx_resume(struct device *dev) struct ata_host *host = dev_get_drvdata(dev); struct pata_imx_priv *priv = host->private_data; - clk_prepare_enable(priv->clk); + int ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; __raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL); -- cgit v0.10.2 From 49c8f1ffe26ffddfb7244a24db21c0b4a79e1c52 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 22 Jan 2014 20:56:33 +0100 Subject: ATA: SATA_MV: Add missing Kconfig select statememnt SATA_MV depends on GENERIC_PHY. So if SATA_MV is built in, GENERIC_PHY cannot be modular. Fixes build error found by kbuild test robot. Signed-off-by: Andrew Lunn Signed-off-by: Tejun Heo diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 4e73772..868429a 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -247,6 +247,7 @@ config SATA_HIGHBANK config SATA_MV tristate "Marvell SATA support" + select GENERIC_PHY help This option enables support for the Marvell Serial ATA family. Currently supports 88SX[56]0[48][01] PCI(-X) chips, -- cgit v0.10.2 From c0e50d41126e4786d9cf1105bdf783e55c99f915 Mon Sep 17 00:00:00 2001 From: Chris Zankel Date: Tue, 28 Jan 2014 22:09:51 -0800 Subject: xtensa: fix fast_syscall_spill_registers The original implementation could clobber registers under certain conditions. The Xtensa processor architecture uses windowed registers and the original implementation was using a4 as a temporary register, which under certain conditions could be register a0 of the oldest window frame, and didn't always restore the content correctly. By moving the _spill_registers routine inside the fast system call, it frees up one more register (the return address is not required anymore) for the spill routine. Signed-off-by: Chris Zankel diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index cb8fd44..f9e1ec3 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S @@ -235,7 +235,7 @@ ENTRY(_DoubleExceptionVector) /* Check for overflow/underflow exception, jump if overflow. */ - _bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow + bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow /* * Restart window underflow exception. diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 74a60c7..80b33ed 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -122,9 +122,7 @@ EXPORT_SYMBOL(insw); EXPORT_SYMBOL(insl); extern long common_exception_return; -extern long _spill_registers; EXPORT_SYMBOL(common_exception_return); -EXPORT_SYMBOL(_spill_registers); #ifdef CONFIG_FUNCTION_TRACER EXPORT_SYMBOL(_mcount); -- cgit v0.10.2 From efb9e0f4f43780f0ae0c6428d66bd03e805c7539 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 30 Jan 2014 15:20:30 +0400 Subject: ata: enable quirk from jmicron JMB350 for JMB394 Without the patch the kernel generates the following error. ata11.15: SATA link up 1.5 Gbps (SStatus 113 SControl 310) ata11.15: Port Multiplier vendor mismatch '0x197b' != '0x123' ata11.15: PMP revalidation failed (errno=-19) ata11.15: failed to recover PMP after 5 tries, giving up This patch helps to bypass this error and the device becomes functional. Signed-off-by: Denis V. Lunev Signed-off-by: Tejun Heo Cc: Cc: stable@vger.kernel.org diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 20fd337..7ccc084 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -447,8 +447,11 @@ static void sata_pmp_quirks(struct ata_port *ap) * otherwise. Don't try hard to recover it. */ ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY; - } else if (vendor == 0x197b && devid == 0x2352) { - /* chip found in Thermaltake BlackX Duet, jmicron JMB350? */ + } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) { + /* + * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350? + * 0x0325: jmicron JMB394. + */ ata_for_each_link(link, ap, EDGE) { /* SRST breaks detection and disks get misclassified * LPM disabled to avoid potential problems -- cgit v0.10.2 From 0f7d9a635b7d1b120884b13d8763c9499e8a4aca Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:15:24 +0200 Subject: ASoC: davinci-mcasp: Return value handling cleanup for mcasp_common_hw_param() Take the return value from mcasp_common_hw_param() and use that in case of error. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index f662ef2..f837b0a 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -631,8 +631,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, active_serializers = (channels + slots - 1) / slots; - if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL) - return -EINVAL; + ret = mcasp_common_hw_param(mcasp, substream->stream, channels); + if (ret) + return ret; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) fifo_level = mcasp->txnumevt * active_serializers; else -- cgit v0.10.2 From 135014adc6ae5a1ab0f2f20abaf81d1860138d38 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:21:32 +0200 Subject: ASoC: davinci-mcasp: Move pm callbacks from platform device to soc_dai_driver Handle the PM callbacks via the ASoC core instead of device core. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index f837b0a..0518ff2 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -741,6 +741,41 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_sysclk = davinci_mcasp_set_sysclk, }; +#ifdef CONFIG_PM_SLEEP +static int davinci_mcasp_suspend(struct snd_soc_dai *dai) +{ + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + + mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); + mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); + mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); + mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); + mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); + mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); + mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + + return 0; +} + +static int davinci_mcasp_resume(struct snd_soc_dai *dai) +{ + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); + + return 0; +} +#else +#define davinci_mcasp_suspend NULL +#define davinci_mcasp_resume NULL +#endif + #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ @@ -757,6 +792,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", + .suspend = davinci_mcasp_suspend, + .resume = davinci_mcasp_resume, .playback = { .channels_min = 2, .channels_max = 32 * 16, @@ -1149,49 +1186,12 @@ static int davinci_mcasp_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int davinci_mcasp_suspend(struct device *dev) -{ - struct davinci_mcasp *mcasp = dev_get_drvdata(dev); - - mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); - mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); - mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); - mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); - mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); - mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); - mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); - - return 0; -} - -static int davinci_mcasp_resume(struct device *dev) -{ - struct davinci_mcasp *mcasp = dev_get_drvdata(dev); - - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); - - return 0; -} -#endif - -SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops, - davinci_mcasp_suspend, - davinci_mcasp_resume); - static struct platform_driver davinci_mcasp_driver = { .probe = davinci_mcasp_probe, .remove = davinci_mcasp_remove, .driver = { .name = "davinci-mcasp", .owner = THIS_MODULE, - .pm = &davinci_mcasp_pm_ops, .of_match_table = mcasp_dt_ids, }, }; -- cgit v0.10.2 From 9d27f43274e4889249dc42ca1a3989dd75c5edaf Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Sat, 1 Feb 2014 23:23:10 -0500 Subject: HID: fix buffer allocations When using hid_output_report(), the buffer should be allocated by hid_alloc_report_buf(), not a custom malloc. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d50e731..a713e62 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1178,7 +1178,7 @@ static void hidinput_led_worker(struct work_struct *work) /* fall back to generic raw-output-report */ len = ((report->size - 1) >> 3) + 1 + (report->id > 0); - buf = kmalloc(len, GFP_KERNEL); + buf = hid_alloc_report_buf(report, GFP_KERNEL); if (!buf) return; diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index e914f27..ce68a12 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -582,7 +582,7 @@ static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, int ret; int len = i2c_hid_get_report_length(rep) - 2; - buf = kzalloc(len, GFP_KERNEL); + buf = hid_alloc_report_buf(rep, GFP_KERNEL); if (!buf) return; -- cgit v0.10.2 From 2a67e796da38dff41e5b2aa9352c81189407acb9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jan 2014 15:58:06 +0000 Subject: ASoC: wm5102: Improve EQ coefficient controls The EQ coefficient binary controls overlapped with the volume controls for the B4 and B5 volumes, which were controllable from either the coefficient control or the volume control itself. This patch adds controls for the mode and moves the coefficient control to only cover the coefficients. Signed-off-by: Charles Keepax Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index ce9c8e1..5e03a83 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -685,15 +685,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -705,6 +698,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -716,6 +711,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -727,6 +724,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, -- cgit v0.10.2 From 552694c65b1c563dbdbda4082527774a373ae720 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jan 2014 15:58:07 +0000 Subject: ASoC: wm5110: Improve EQ coefficient controls The EQ coefficient binary controls overlapped with the volume controls for the B4 and B5 volumes, which were controllable from either the coefficient control or the volume control itself. This patch adds controls for the mode and moves the coefficient control to only cover the coefficients. Signed-off-by: Charles Keepax Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2c3c962..7c2b0d6 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -247,15 +247,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -267,6 +260,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -278,6 +273,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -289,6 +286,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, -- cgit v0.10.2 From fb0def0ceda7b2a79be978093704c1c71e26ba22 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jan 2014 15:58:08 +0000 Subject: ASoC: wm8997: Improve EQ coefficient controls The EQ coefficient binary controls overlapped with the volume controls for the B4 and B5 volumes, which were controllable from either the coefficient control or the volume control itself. This patch adds controls for the mode and moves the coefficient control to only cover the coefficients. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 555115e..4a38249 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -170,15 +170,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -190,6 +183,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -201,6 +196,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -212,6 +209,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, -- cgit v0.10.2 From ddbc5efed0f9064287acead56bbf0dce3ca28ee2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 22 Jan 2014 10:09:11 +0000 Subject: ASoC: wm_adsp: Add debug print to note that the DSP has shutdown It can be useful for debugging purposes to see at what point the DSP has powered down, so add a message to inform us of this. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 444626f..f9fd564 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1679,6 +1679,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, list_del(&alg_region->list); kfree(alg_region); } + + adsp_dbg(dsp, "Shutdown complete\n"); break; default: -- cgit v0.10.2 From 1371105731a7c72168d0e464a51203fec829390b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 23 Jan 2014 13:45:34 +0000 Subject: ASoC: wm5102: Correct typo in EQ coefficient sizes Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 5e03a83..ebffe81 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -685,7 +685,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -698,7 +698,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -711,7 +711,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -724,7 +724,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), -- cgit v0.10.2 From 3c379ef97e7f6cd305a4873150319c2355b4316d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 23 Jan 2014 13:45:35 +0000 Subject: ASoC: wm5110: Correct type in EQ coefficient sizes Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 7c2b0d6..4de2bf1 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -247,7 +247,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -260,7 +260,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -273,7 +273,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -286,7 +286,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), -- cgit v0.10.2 From 2b14cd3af9d98ce135e503e91e3973bdd5e4baeb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 23 Jan 2014 13:45:36 +0000 Subject: ASoC: wm8997: Correct typo in EQ coefficient sizes Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 4a38249..6107108 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -170,7 +170,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -183,7 +183,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -196,7 +196,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -209,7 +209,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), -- cgit v0.10.2 From 05cf482d7e76bb02138d6b04a94375bc9f86e927 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Mon, 20 Jan 2014 15:27:26 +0800 Subject: ASoC: fsl: use snd_soc_dai_init_dma_data() Signed-off-by: Xiubo Li Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4d075f1..8f36f49 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -911,8 +911,8 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) { struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai); - dai->playback_dma_data = &spdif_private->dma_params_tx; - dai->capture_dma_data = &spdif_private->dma_params_rx; + snd_soc_dai_init_dma_data(dai, &spdif_private->dma_params_tx, + &spdif_private->dma_params_rx); snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); -- cgit v0.10.2 From 0290d2a42cb476358303d05fbe2475dd50889907 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:37:39 -0800 Subject: ASoC: rsnd: tidyup register naming of BUSIF_MODE Gen1:SRU has only 1 BUSIF_MODE, but Gen2:SSIU/SCU has SRCm_BUSIF_MODE, and SSIn_BUSIF_MODE. This patch rename current BUSIF_MODE to SRC_BUSIF_MODE. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index add088b..cbdbbfa 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -317,7 +317,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), - RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), + RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4ca66cd..f62b9eb 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -39,8 +39,8 @@ enum rsnd_reg { RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, - RSND_REG_BUSIF_MODE, RSND_REG_INT_ENABLE, /* for Gen2 */ + RSND_REG_SRC_BUSIF_MODE, RSND_REG_SRC_ROUTE_MODE0, RSND_REG_SRC_SWRSR, RSND_REG_SRC_SRCIR, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 9bb08bb..9b9daa3 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -211,7 +211,7 @@ static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, rsnd_mod_write(mod, SRC_SRCIR, 0); /* use DMA transfer */ - rsnd_mod_write(mod, BUSIF_MODE, 1); + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); return 0; } -- cgit v0.10.2 From 92d9587ede108a7e73f80d0767aedf2c4edb47d8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:08 -0800 Subject: ASoC: rsnd: cleanup debug information method rsnd_mod debug information is implemented in each callback functions now. But, it can be implemented in rsnd_mod_call(), and share this code. This patch adds it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index f62b9eb..faacdcb 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -152,10 +152,19 @@ struct rsnd_mod { #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) +#define __rsnd_mod_call(mod, func, rdai, io) \ +({ \ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ + struct device *dev = rsnd_priv_to_dev(priv); \ + dev_dbg(dev, "%s-%d-%s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + (mod)->ops->func(mod, rdai, io); \ +}) + #define rsnd_mod_call(mod, func, rdai, io) \ (!(mod) ? -ENODEV : \ !((mod)->ops->func) ? 0 : \ - (mod)->ops->func(mod, rdai, io)) + __rsnd_mod_call(mod, func, rdai, io)) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 9b9daa3..e4b82ab 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -300,8 +300,6 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 4b8cf7c..df775f0 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -324,7 +324,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -371,8 +370,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, rsnd_ssi_mode_set(priv, rdai, ssi); - dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } @@ -384,8 +381,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); - dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - if (ssi->err > 0) dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); @@ -450,7 +445,6 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct device *dev = rsnd_priv_to_dev(priv); /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; @@ -461,8 +455,6 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, rsnd_ssi_hw_start(ssi, rdai, io); - dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } @@ -470,12 +462,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - ssi->cr_etc = 0; rsnd_ssi_hw_stop(ssi, rdai); -- cgit v0.10.2 From 6acef1721c1046be8b5f44b839c28817cfbd66c6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:17 -0800 Subject: ASoC: rsnd: remove meaningless rsnd_ssi_non() rsnd_ssi_non_ops callback functions are never called. remove these meaningless callback Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index df775f0..ef3d450 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -555,24 +555,8 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { /* * Non SSI */ -static int rsnd_ssi_non(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); - - dev_dbg(dev, "%s\n", __func__); - - return 0; -} - static struct rsnd_mod_ops rsnd_ssi_non_ops = { .name = "ssi (non)", - .init = rsnd_ssi_non, - .quit = rsnd_ssi_non, - .start = rsnd_ssi_non, - .stop = rsnd_ssi_non, }; /* -- cgit v0.10.2 From 013f38fe260af6f505ad5da5f6b0db3e42ca1fbb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:26 -0800 Subject: ASoC: rsnd: control SCU ops in probe timing SCU will be used if platform requested to use. Current driver is checking it in runtime, but, it can be decided in probe timing. This patch do it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e4b82ab..ab5f1d2 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -270,24 +270,10 @@ static int rsnd_scu_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct device *dev = rsnd_priv_to_dev(priv); int ret; - /* - * SCU will be used if it has RSND_SCU_USE_HPBIF flags - */ - if (!rsnd_scu_hpbif_is_enable(mod)) { - /* it use PIO transter */ - dev_dbg(dev, "%s%d is not used\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - - return 0; - } - clk_enable(scu->clk); - /* it use DMA transter */ - ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); if (ret < 0) return ret; @@ -310,9 +296,6 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - if (!rsnd_scu_hpbif_is_enable(mod)) - return 0; - rsnd_scu_transfer_stop(priv, mod, rdai, io); clk_disable(scu->clk); @@ -326,6 +309,10 @@ static struct rsnd_mod_ops rsnd_scu_ops = { .stop = rsnd_scu_stop, }; +static struct rsnd_mod_ops rsnd_scu_non_ops = { + .name = "scu (non)", +}; + struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) { if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) @@ -340,6 +327,7 @@ int rsnd_scu_probe(struct platform_device *pdev, { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_scu *scu; + struct rsnd_mod_ops *ops; struct clk *clk; char name[RSND_SCU_NAME_SIZE]; int i, nr; @@ -364,11 +352,15 @@ int rsnd_scu_probe(struct platform_device *pdev, if (IS_ERR(clk)) return PTR_ERR(clk); - rsnd_mod_init(priv, &scu->mod, - &rsnd_scu_ops, i); scu->info = &info->scu_info[i]; scu->clk = clk; + ops = &rsnd_scu_non_ops; + if (rsnd_scu_hpbif_is_enable(&scu->mod)) + ops = &rsnd_scu_ops; + + rsnd_mod_init(priv, &scu->mod, ops, i); + dev_dbg(dev, "SCU%d probed\n", i); } dev_dbg(dev, "scu probed\n"); -- cgit v0.10.2 From a204d90c91208d9b63ba309a1c44f582751e58c9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:33 -0800 Subject: ASoC: rsnd: add rsnd_scu_init(), and separate init/start Current scu.c has rsnd_scu_start(), and, operation of initialization/start are implemented in this function. This patch adds new rsnd_scu_init() and separates rsnd_scu_start(), since rsnd_mod_ops has .init/.start callbacks. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ab5f1d2..e1e0873 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -264,7 +264,7 @@ bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) return !!(flags & RSND_SCU_USE_HPBIF); } -static int rsnd_scu_start(struct rsnd_mod *mod, +static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { @@ -282,13 +282,30 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_transfer_start(priv, mod, rdai, io); - if (ret < 0) - return ret; + return 0; +} + +static int rsnd_scu_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + clk_disable(scu->clk); return 0; } +static int rsnd_scu_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + return rsnd_scu_transfer_start(priv, mod, rdai, io); +} + static int rsnd_scu_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -298,13 +315,13 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, rsnd_scu_transfer_stop(priv, mod, rdai, io); - clk_disable(scu->clk); - return 0; } static struct rsnd_mod_ops rsnd_scu_ops = { .name = "scu", + .init = rsnd_scu_init, + .quit = rsnd_scu_quit, .start = rsnd_scu_start, .stop = rsnd_scu_stop, }; -- cgit v0.10.2 From 47718dc7d8ca5f5509ac9beb13486642306bb36b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:42 -0800 Subject: ASoC: rsnd: remove meaningless function parameter struct rsnd_priv *priv on rsnd_scu_init/start/stop() are no longer needed Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e1e0873..ece539b 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -50,7 +50,7 @@ struct rsnd_scu { i++) /* Gen1 only */ -static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, +static int rsnd_src_set_route_if_gen1( struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -69,6 +69,7 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 mask; u32 val; @@ -149,11 +150,12 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, return rate; } -static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, +static int rsnd_scu_convert_rate_ctrl( struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 convert_rate = rsnd_scu_convert_rate(scu); @@ -268,17 +270,16 @@ static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int ret; clk_enable(scu->clk); - ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); + ret = rsnd_src_set_route_if_gen1(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io); + ret = rsnd_scu_convert_rate_ctrl(mod, rdai, io); if (ret < 0) return ret; -- cgit v0.10.2 From e7ce74eaa76591e5a4905d0fc07a278533447b80 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:50 -0800 Subject: ASoC: rsnd: merge rsnd_scu_start/stop() and rsnd_scu_transfer_start/stop() rsnd_scu_transfer_start/stop() are no longer needed. merge into rsnd_scu_start/stop() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ece539b..5d2dbbb 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -218,46 +218,6 @@ static int rsnd_scu_convert_rate_ctrl( return 0; } -static int rsnd_scu_transfer_start(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 val; - - if (rsnd_is_gen1(priv)) { - val = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); - - return 0; -} - -static int rsnd_scu_transfer_stop(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 mask; - - if (rsnd_is_gen1(priv)) { - mask = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, mask, 0); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); - - return 0; -} - bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) { struct rsnd_scu *scu = rsnd_mod_to_scu(mod); @@ -303,8 +263,15 @@ static int rsnd_scu_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); - return rsnd_scu_transfer_start(priv, mod, rdai, io); + if (rsnd_is_gen1(priv)) + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; } static int rsnd_scu_stop(struct rsnd_mod *mod, @@ -313,8 +280,13 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); + + if (rsnd_is_gen1(priv)) + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - rsnd_scu_transfer_stop(priv, mod, rdai, io); + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); return 0; } -- cgit v0.10.2 From e779a20da90b12d17af74fe544fafd814b66dc63 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:12 -0800 Subject: ASoC: rsnd: rsnd_dai_is_clk_master() can be shared Current rsnd driver is using ssi local rsnd_rdai_is_clk_master() for checking clock master. But it can be rsnd_dai_is_clk_master(), and share in each file Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index faacdcb..cd396dd 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -215,6 +215,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); +#define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master) /* * R-Car Gen1/Gen2 diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index ef3d450..ddcca06 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -95,7 +95,6 @@ struct rsnd_ssiu { #define rsnd_ssi_dma_available(ssi) \ rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) -#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) #define rsnd_ssi_to_ssiu(ssi)\ @@ -133,7 +132,7 @@ static void rsnd_ssi_mode_set(struct rsnd_priv *priv, #define ssi_parent_set(p, sync, adg, ext) \ do { \ ssi->parent = ssiu->ssi + p; \ - if (rsnd_rdai_is_clk_master(rdai)) \ + if (rsnd_dai_is_clk_master(rdai)) \ val = adg; \ else \ val = ext; \ @@ -252,7 +251,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, if (0 == ssi->usrcnt) { clk_enable(ssi->clk); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, rdai, io); else @@ -302,7 +301,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ rsnd_ssi_status_check(&ssi->mod, IIRQ); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_stop(ssi->parent, rdai); else @@ -522,7 +521,7 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, rsnd_ssi_hw_start(ssi, ssi->rdai, io); /* enable WS continue */ - if (rsnd_rdai_is_clk_master(rdai)) + if (rsnd_dai_is_clk_master(rdai)) rsnd_mod_write(&ssi->mod, SSIWSR, CONT); return 0; -- cgit v0.10.2 From 6f3ab6c1c022e7a4877d38940cd45ae7804a15e2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:23 -0800 Subject: ASoC: rsnd: remove pin sync option Renesas Chip is supporting multi pin sound, but the HW setting is very difficult and confusable. But driver is supporting it halfway. Remove SYNC option at this point. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 6add6cc..1d19bfc 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -35,6 +35,7 @@ */ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) #define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */ +#define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */ #define RSND_SSI_PLAY (1 << 24) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index ddcca06..68393a9 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -136,8 +136,6 @@ static void rsnd_ssi_mode_set(struct rsnd_priv *priv, val = adg; \ else \ val = ext; \ - if (flags & RSND_SSI_SYNC) \ - val |= sync; \ } while (0) flags = rsnd_ssi_mode_flags(ssi); -- cgit v0.10.2 From 7b5ce9759a60ebdffa1e76224ccb3d85bd06e4ac Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:32 -0800 Subject: ASoC: rsnd: SSI_MODE0/1 settings goes to scu.c SRU (Gen1) / SCU (Gen2) / SSIU (Gen2) are controlled under scu.c. (SCU + SSIU (Gen2) was SRU (Gen1)) And register of SSI_MODE0/1 are mapped on these IP. But these have been implemented under ssi.c on this driver. The naming is very confusable, but it should be implemented under scu.c Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index cd396dd..85b9262 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -321,5 +321,6 @@ void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); #endif diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 5d2dbbb..ade1047 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -49,6 +49,46 @@ struct rsnd_scu { ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ i++) +static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + int id = rsnd_mod_id(mod); + + /* + * SSI_MODE0 + */ + rsnd_mod_bset(mod, SSI_MODE0, (1 << id), + rsnd_scu_hpbif_is_enable(mod) ? 0 : (1 << id)); + + /* + * SSI_MODE1 + */ + if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + int shift = -1; + switch (id) { + case 1: + shift = 0; + break; + case 2: + shift = 2; + break; + case 4: + shift = 16; + break; + } + + if (shift >= 0) + rsnd_mod_bset(mod, SSI_MODE1, + 0x3 << shift, + rsnd_dai_is_clk_master(rdai) ? + 0x2 << shift : 0x1 << shift); + } + + return 0; +} + /* Gen1 only */ static int rsnd_src_set_route_if_gen1( struct rsnd_mod *mod, @@ -235,6 +275,10 @@ static int rsnd_scu_init(struct rsnd_mod *mod, clk_enable(scu->clk); + ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + if (ret < 0) + return ret; + ret = rsnd_src_set_route_if_gen1(mod, rdai, io); if (ret < 0) return ret; @@ -301,6 +345,7 @@ static struct rsnd_mod_ops rsnd_scu_ops = { static struct rsnd_mod_ops rsnd_scu_non_ops = { .name = "scu (non)", + .init = rsnd_scu_ssi_mode_init, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 68393a9..0f314db 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -75,9 +75,6 @@ struct rsnd_ssi { }; struct rsnd_ssiu { - u32 ssi_mode0; - u32 ssi_mode1; - int ssi_nr; struct rsnd_ssi *ssi; }; @@ -100,70 +97,6 @@ struct rsnd_ssiu { #define rsnd_ssi_to_ssiu(ssi)\ (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) -static void rsnd_ssi_mode_set(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_ssi *ssi) -{ - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_mod *scu; - struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi); - int id = rsnd_mod_id(&ssi->mod); - u32 flags; - u32 val; - - scu = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod)); - - /* - * SSI_MODE0 - */ - - /* see also BUSIF_MODE */ - if (rsnd_scu_hpbif_is_enable(scu)) { - ssiu->ssi_mode0 &= ~(1 << id); - dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id); - } else { - ssiu->ssi_mode0 |= (1 << id); - dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id); - } - - /* - * SSI_MODE1 - */ -#define ssi_parent_set(p, sync, adg, ext) \ - do { \ - ssi->parent = ssiu->ssi + p; \ - if (rsnd_dai_is_clk_master(rdai)) \ - val = adg; \ - else \ - val = ext; \ - } while (0) - - flags = rsnd_ssi_mode_flags(ssi); - if (flags & RSND_SSI_CLK_PIN_SHARE) { - - val = 0; - switch (id) { - case 1: - ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0)); - break; - case 2: - ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2)); - break; - case 4: - ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16)); - break; - case 8: - ssi_parent_set(7, 0, 0, 0); - break; - } - - ssiu->ssi_mode1 |= val; - } - - rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0); - rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1); -} - static void rsnd_ssi_status_check(struct rsnd_mod *mod, u32 bit) { @@ -320,7 +253,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -365,8 +297,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ - rsnd_ssi_mode_set(priv, rdai, ssi); - return 0; } @@ -588,6 +518,32 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; } +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); +} + +static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) +{ + if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) + return; + + switch (rsnd_mod_id(&ssi->mod)) { + case 1: + case 2: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0)); + break; + case 4: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 3)); + break; + case 8: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 7)); + break; + } +} + int rsnd_ssi_probe(struct platform_device *pdev, struct rcar_snd_info *info, struct rsnd_priv *priv) @@ -668,6 +624,8 @@ int rsnd_ssi_probe(struct platform_device *pdev, } rsnd_mod_init(priv, &ssi->mod, ops, i); + + rsnd_ssi_parent_clk_setup(priv, ssi); } dev_dbg(dev, "ssi probed\n"); -- cgit v0.10.2 From dd27d808f9e084e7e9c4719c17f17d1fa35c45a6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:40 -0800 Subject: ASoC: rsnd: remove ssiu from ssi.c Now, SSI_MODE0/1 are controlled under scu.c ssiu is no longer needed on ssi.c Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 85b9262..e92b1f4 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -280,7 +280,8 @@ struct rsnd_priv { /* * below value will be filled on rsnd_ssi_probe() */ - void *ssiu; + void *ssi; + int ssi_nr; /* * below value will be filled on rsnd_dai_probe() diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0f314db..dc72439 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -74,18 +74,13 @@ struct rsnd_ssi { unsigned int rate; }; -struct rsnd_ssiu { - int ssi_nr; - struct rsnd_ssi *ssi; -}; - #define for_each_rsnd_ssi(pos, priv, i) \ for (i = 0; \ (i < rsnd_ssi_nr(priv)) && \ - ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \ + ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \ i++) -#define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr) +#define rsnd_ssi_nr(priv) ((priv)->ssi_nr) #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) @@ -94,8 +89,6 @@ struct rsnd_ssiu { #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) -#define rsnd_ssi_to_ssiu(ssi)\ - (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) static void rsnd_ssi_status_check(struct rsnd_mod *mod, u32 bit) @@ -515,7 +508,7 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) id = 0; - return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; + return &((struct rsnd_ssi *)(priv->ssi) + id)->mod; } int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) @@ -552,7 +545,6 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; struct clk *clk; - struct rsnd_ssiu *ssiu; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; int i, nr, ret; @@ -561,16 +553,14 @@ int rsnd_ssi_probe(struct platform_device *pdev, * init SSI */ nr = info->ssi_info_nr; - ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr), - GFP_KERNEL); - if (!ssiu) { + ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); + if (!ssi) { dev_err(dev, "SSI allocate failed\n"); return -ENOMEM; } - priv->ssiu = ssiu; - ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1); - ssiu->ssi_nr = nr; + priv->ssi = ssi; + priv->ssi_nr = nr; for_each_rsnd_ssi(ssi, priv, i) { pinfo = &info->ssi_info[i]; -- cgit v0.10.2 From f80e1c96339a45992b5dded0474288e52bd3b18d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:48 -0800 Subject: ASoC: rsnd: rename rsnd_scu_convert_rate_ctrl() rsnd_scu_convert_rate_ctrl() is unclear naming, and there is "rsnd_scu_convert_rate" variable. These are confusable. it renamed to rsnd_scu_set_convert_rate() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ade1047..872a115 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -190,10 +190,9 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, return rate; } -static int rsnd_scu_convert_rate_ctrl( - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); @@ -283,7 +282,7 @@ static int rsnd_scu_init(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_convert_rate_ctrl(mod, rdai, io); + ret = rsnd_scu_set_convert_rate(mod, rdai, io); if (ret < 0) return ret; -- cgit v0.10.2 From 41c6221c39accdc4fe2b0c0fa196b6302b704e57 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:56 -0800 Subject: ASoC: rsnd: explain SRC bypass mode settings in comment SRC bypass mode is useful for debugging. This patch explains SRC bypass mode settings in comment Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 872a115..076aa71 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -40,6 +40,51 @@ struct rsnd_scu { * */ +/* + * How to use SRC bypass mode for debugging + * + * SRC has bypass mode, and it is useful for debugging. + * In Gen2 case, + * SRCm_MODE controls whether SRC is used or not + * SSI_MODE0 controls whether SSIU which receives SRC data + * is used or not. + * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, + * but SRC bypass mode needs SSI_MODE0 only. + * + * This driver request + * struct rsnd_scu_platform_info { + * u32 flags; + * u32 convert_rate; + * } + * + * rsnd_scu_hpbif_is_enable() will be true + * if flags had RSND_SCU_USE_HPBIF, + * and it controls whether SSIU is used or not. + * + * rsnd_scu_convert_rate() indicates + * above convert_rate, and it controls + * whether SRC is used or not. + * + * ex) doesn't use SRC + * struct rsnd_scu_platform_info info = { + * .flags = 0, + * .convert_rate = 0, + * }; + * + * ex) uses SRC + * struct rsnd_scu_platform_info info = { + * .flags = RSND_SCU_USE_HPBIF, + * .convert_rate = 48000, + * }; + * + * ex) uses SRC bypass mode + * struct rsnd_scu_platform_info info = { + * .flags = RSND_SCU_USE_HPBIF, + * .convert_rate = 0, + * }; + * + */ + #define rsnd_mod_to_scu(_mod) \ container_of((_mod), struct rsnd_scu, mod) -- cgit v0.10.2 From 9b5ab573a81b9ac0df90b74d732651fdf8b24525 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:03 -0800 Subject: ASoC: rsnd: remove duplicate *priv from rsnd_dma *priv pointer exists under rsnd_mod, and, it can get rsnd_mod pointer from rsnd_dma. remove duplicate rsnd_dma :: priv Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 743de5e..ed8611f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -156,7 +156,7 @@ void rsnd_dma_stop(struct rsnd_dma *dma) static void rsnd_dma_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; - struct rsnd_priv *priv = dma->priv; + struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); unsigned long flags; rsnd_lock(priv, flags); @@ -172,7 +172,7 @@ static void rsnd_dma_complete(void *data) static void rsnd_dma_do_work(struct work_struct *work) { struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); - struct rsnd_priv *priv = dma->priv; + struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; dma_addr_t buf; @@ -246,7 +246,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma->priv = priv; dma->inquiry = inquiry; dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e92b1f4..33c01fb 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -96,7 +96,6 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, * R-Car DMA */ struct rsnd_dma { - struct rsnd_priv *priv; struct sh_dmae_slave slave; struct work_struct work; struct dma_chan *chan; -- cgit v0.10.2 From 106d2eff563b2abdb34872cb8ec7b19766edaffc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:13 -0800 Subject: ASoC: rsnd: non 0 is error on probe Some xxx_probe() returns not only -Exx, but also PTR_ERR(). Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed8611f..4fd5735 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -737,23 +737,23 @@ static int rsnd_probe(struct platform_device *pdev) * init each module */ ret = rsnd_gen_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_scu_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_adg_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_ssi_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_dai_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; /* -- cgit v0.10.2 From 64de62b38641dec05905930024133726c540040e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:20 -0800 Subject: ASoC: rsnd: fixup Gen2 module naming Gen2 has SCU, not SRU Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index cbdbbfa..76828c2 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -283,7 +283,7 @@ static int rsnd_gen2_probe(struct platform_device *pdev, return ret; dev_dbg(dev, "Gen2 device probed\n"); - dev_dbg(dev, "SRU : %08x => %p\n", scu_res->start, + dev_dbg(dev, "SCU : %08x => %p\n", scu_res->start, gen->base[RSND_GEN2_SCU]); dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, gen->base[RSND_GEN2_ADG]); -- cgit v0.10.2 From f5cab3b8976d59c6166228874a5af3d87c94c723 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:27 -0800 Subject: ASoC: rsnd: don't use schedule_work() when rsnd_dma_start() rsnd_dma_start() is the function to start DMAEngine. Current code is using schedule_work() for it, but it breaks DMAC/SSI register setting timing. Don't use schedule_work() on it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4fd5735..11eb0e3 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -132,6 +132,7 @@ void rsnd_mod_init(struct rsnd_priv *priv, /* * rsnd_dma functions */ +static void __rsnd_dma_start(struct rsnd_dma *dma); static void rsnd_dma_continue(struct rsnd_dma *dma) { /* push next A or B plane */ @@ -143,7 +144,7 @@ void rsnd_dma_start(struct rsnd_dma *dma) { /* push both A and B plane*/ dma->submit_loop = 2; - schedule_work(&dma->work); + __rsnd_dma_start(dma); } void rsnd_dma_stop(struct rsnd_dma *dma) @@ -169,9 +170,8 @@ static void rsnd_dma_complete(void *data) rsnd_unlock(priv, flags); } -static void rsnd_dma_do_work(struct work_struct *work) +static void __rsnd_dma_start(struct rsnd_dma *dma) { - struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; @@ -204,6 +204,13 @@ static void rsnd_dma_do_work(struct work_struct *work) } } +static void rsnd_dma_do_work(struct work_struct *work) +{ + struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); + + __rsnd_dma_start(dma); +} + int rsnd_dma_available(struct rsnd_dma *dma) { return !!dma->chan; -- cgit v0.10.2 From be213ac1af893410eb8256010edf136b4099e827 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:34 -0800 Subject: ASoC: rsnd: SCU should be called before SSI Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 76828c2..db486aa 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -182,14 +182,14 @@ int rsnd_gen_path_init(struct rsnd_priv *priv, rsnd_dai_is_play(rdai, io)); id = rsnd_mod_id(mod); - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); + /* SCU */ + mod = rsnd_scu_mod_get(priv, id); ret = rsnd_dai_connect(rdai, mod, io); if (ret < 0) return ret; - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); + /* SSI */ + mod = rsnd_ssi_mod_get(priv, id); ret = rsnd_dai_connect(rdai, mod, io); return ret; -- cgit v0.10.2 From c926b746055adfd915936c67244e635e9c7a3d84 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:41 -0800 Subject: ASoC: rsnd: clarify scu.c area scu.c cares SRU(Gen1) / SCU(Gen2) / SSIU(Gen2) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 076aa71..1adc858 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -41,6 +41,20 @@ struct rsnd_scu { */ /* + * scu.c is caring... + * + * Gen1 + * + * [mem] -> [SRU] -> [SSI] + * |--------| + * + * Gen2 + * + * [mem] -> [SCU] -> [SSIU] -> [SSI] + * |-----------------| + */ + +/* * How to use SRC bypass mode for debugging * * SRC has bypass mode, and it is useful for debugging. -- cgit v0.10.2 From 39cf3c4064b8db25efe501fec8e3c48a578b4b58 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:47 -0800 Subject: ASoC: rsnd: Merge macros in scu.c Merge #define lines, since these are defined in the scattering place Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 1adc858..8181ec55 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -16,9 +16,6 @@ struct rsnd_scu { struct clk *clk; }; -#define rsnd_scu_mode_flags(p) ((p)->info->flags) -#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) - #define RSND_SCU_NAME_SIZE 16 /* @@ -30,6 +27,18 @@ struct rsnd_scu { #define OTBL_18 (6 << 16) #define OTBL_16 (8 << 16) +#define rsnd_scu_mode_flags(p) ((p)->info->flags) +#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_mod_to_scu(_mod) \ + container_of((_mod), struct rsnd_scu, mod) + +#define for_each_rsnd_scu(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_scu_nr(priv)) && \ + ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ + i++) + + /* * image of SRC (Sampling Rate Converter) * @@ -99,15 +108,6 @@ struct rsnd_scu { * */ -#define rsnd_mod_to_scu(_mod) \ - container_of((_mod), struct rsnd_scu, mod) - -#define for_each_rsnd_scu(pos, priv, i) \ - for ((i) = 0; \ - ((i) < rsnd_scu_nr(priv)) && \ - ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ - i++) - static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) -- cgit v0.10.2 From 96c7c0d6f8c6e09e9123f0518130c047c5de40f6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:54 -0800 Subject: ASoC: rsnd: rsnd_scu_hpbif_is_enable() become macro rsnd_scu_hpbif_is_enable() is used only scu.c now. It can be local macro Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 33c01fb..a9c5830 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -303,7 +303,6 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_mod *ssi_mod, struct snd_pcm_runtime *runtime); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 8181ec55..2f839f7 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -31,6 +31,8 @@ struct rsnd_scu { #define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) #define rsnd_mod_to_scu(_mod) \ container_of((_mod), struct rsnd_scu, mod) +#define rsnd_scu_hpbif_is_enable(scu) \ + (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) #define for_each_rsnd_scu(pos, priv, i) \ for ((i) = 0; \ @@ -113,13 +115,14 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); /* * SSI_MODE0 */ rsnd_mod_bset(mod, SSI_MODE0, (1 << id), - rsnd_scu_hpbif_is_enable(mod) ? 0 : (1 << id)); + rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << id)); /* * SSI_MODE1 @@ -316,14 +319,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, return 0; } -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 flags = rsnd_scu_mode_flags(scu); - - return !!(flags & RSND_SCU_USE_HPBIF); -} - static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -449,7 +444,7 @@ int rsnd_scu_probe(struct platform_device *pdev, scu->clk = clk; ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(&scu->mod)) + if (rsnd_scu_hpbif_is_enable(scu)) ops = &rsnd_scu_ops; rsnd_mod_init(priv, &scu->mod, ops, i); -- cgit v0.10.2 From 28dc4b63cdb96f2448a677320fcc0eb112e13e3f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:10 -0800 Subject: ASoC: rsnd: merge SRC clock timing/setting SRC clock and timing setting register exist in SRU and ADG on Gen1. But, these are merged into ADG on Gen2. Current driver is supporting Gen1 SRC only at this point, but, above settings are set as different function. This patch merges these as preparation of Gen2 support. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a53235c..5bdffa4 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,10 +30,10 @@ struct rsnd_adg { i++, (pos) = adg->clk[i]) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); @@ -91,18 +91,6 @@ find_rate: return 0; } -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) -{ - if (rsnd_is_gen1(priv)) - return rsnd_adg_set_convert_clk_gen1(priv, mod, - src_rate, dst_rate); - - return -EINVAL; -} - static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) { int id = rsnd_mod_id(mod); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a9c5830..3991455 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -246,10 +246,10 @@ int rsnd_adg_probe(struct platform_device *pdev, struct rsnd_priv *priv); void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv); -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate); /* * R-Car sound priv diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 2f839f7..e2ffcc4 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -172,10 +172,8 @@ static int rsnd_src_set_route_if_gen1( { 0x3, 30, }, /* 8 */ }; struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 mask; u32 val; - int shift; int id; /* @@ -197,6 +195,23 @@ static int rsnd_src_set_route_if_gen1( rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); + return 0; +} + +static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate = rsnd_scu_convert_rate(scu); + u32 mask; + u32 val; + int shift; + int id = rsnd_mod_id(mod); + int ret; + /* * SRC_TIMING_SELECT */ @@ -209,12 +224,23 @@ static int rsnd_src_set_route_if_gen1( * SSI WS is used as source clock if SRC is not used * (when playback, source/destination become reverse when capture) */ - if (rsnd_scu_convert_rate(scu)) /* use ADG */ + ret = 0; + if (convert_rate) { + /* use ADG */ val = 0; - else if (8 == id) /* use SSI WS, but SRU8 is special */ + ret = rsnd_adg_set_convert_clk_gen1(priv, mod, + runtime->rate, + convert_rate); + } else if (8 == id) { + /* use SSI WS, but SRU8 is special */ val = id << shift; - else /* use SSI WS */ + } else { + /* use SSI WS */ val = (id + 1) << shift; + } + + if (ret < 0) + return ret; switch (id / 4) { case 0: @@ -284,7 +310,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, if (convert_rate) { u32 fsrate = 0x0400000 / convert_rate * runtime->rate; - int ret; /* Enable the initial value of IFS */ rsnd_mod_write(mod, SRC_IFSCR, 1); @@ -301,13 +326,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, if (rsnd_is_gen1(priv)) { /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ } - - /* set convert clock */ - ret = rsnd_adg_set_convert_clk(priv, mod, - runtime->rate, - convert_rate); - if (ret < 0) - return ret; } /* Cancel the initialization and operate the SRC function */ @@ -340,6 +358,10 @@ static int rsnd_scu_init(struct rsnd_mod *mod, if (ret < 0) return ret; + ret = rsnd_scu_set_convert_timing_gen1(mod, rdai, io); + if (ret < 0) + return ret; + return 0; } -- cgit v0.10.2 From 32f27ebf9b625df610c12408ea15bae37be75eaf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:17 -0800 Subject: ASoC: rsnd: add rsnd_ssi_is_play() SCU needs SSI direction if Gen2. Add rsnd_ssi_is_play() function for it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3991455..b1874eb 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -321,5 +321,6 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); +int rsnd_ssi_is_play(struct rsnd_mod *mod); #endif diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index dc72439..bae309c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -494,7 +494,7 @@ struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, if (rsnd_ssi_dai_id(ssi) != dai_id) continue; - has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); + has_play = rsnd_ssi_is_play(&ssi->mod); if (is_play == has_play) return &ssi->mod; @@ -518,6 +518,13 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); } +int rsnd_ssi_is_play(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); +} + static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) { if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) @@ -582,7 +589,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, if (pinfo->dma_id > 0) { ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), - (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY), + rsnd_ssi_is_play(&ssi->mod), pinfo->dma_id, rsnd_ssi_dma_inquiry, rsnd_ssi_dma_complete); -- cgit v0.10.2 From 1b7b08efbe7419cc3e082f2b5ec8ae89f7af43d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:36 -0800 Subject: ASoC: rsnd: extracts Gen1/Gen2 common parts Renesas sound IP Gen1/Gen2 are similar, but different. This patch extracts Gen1/Gen2 common and dependency parts, and create Gen1/Gen2 ops to control it. According to this structure, SSIU setup which has been implemented on ssi.c can be moved to scu.c (SRU/SSIU/SCU should be implemented on scu.c) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b1874eb..c397dc8 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -48,7 +48,7 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, - RSND_REG_SRC_MNFSR, + RSND_REG_SRC_MNFSR, /* for Gen1 */ /* ADG */ RSND_REG_BRRA, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e2ffcc4..29d8990 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -110,6 +110,9 @@ struct rsnd_scu { * */ +/* + * Gen1/Gen2 common functions + */ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -151,11 +154,145 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, return 0; } -/* Gen1 only */ -static int rsnd_src_set_route_if_gen1( - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_mod *ssi_mod, + struct snd_pcm_runtime *runtime) +{ + struct rsnd_scu *scu; + unsigned int rate; + + /* this function is assuming SSI id = SCU id here */ + scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_scu_convert_rate(scu); + if (!rate) + rate = runtime->rate; + + return rate; +} + +static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + u32 adinr = runtime->channels; + u32 fsrate = 0; + + if (convert_rate) + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* set/clear soft reset */ + rsnd_mod_write(mod, SRC_SWRSR, 0); + rsnd_mod_write(mod, SRC_SWRSR, 1); + + /* + * Initialize the operation of the SRC internal circuits + * see rsnd_scu_start() + */ + rsnd_mod_write(mod, SRC_SRCIR, 1); + + /* Set channel number and output bit length */ + switch (runtime->sample_bits) { + case 16: + adinr |= OTBL_16; + break; + case 32: + adinr |= OTBL_24; + break; + default: + return -EIO; + } + rsnd_mod_write(mod, SRC_ADINR, adinr); + + /* Enable the initial value of IFS */ + if (fsrate) { + rsnd_mod_write(mod, SRC_IFSCR, 1); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + } + + /* use DMA transfer */ + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + + return 0; +} + +static int rsnd_scu_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int ret; + + clk_enable(scu->clk); + + ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_scu_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + clk_disable(scu->clk); + + return 0; +} + +static int rsnd_scu_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + /* + * Cancel the initialization and operate the SRC function + * see rsnd_scu_set_convert_rate() + */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; +} + + +static int rsnd_scu_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); + + return 0; +} + +static struct rsnd_mod_ops rsnd_scu_non_ops = { + .name = "scu (non)", +}; + +/* + * Gen1 functions + */ +static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { struct scu_route_config { u32 mask; @@ -171,17 +308,10 @@ static int rsnd_src_set_route_if_gen1( { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); u32 mask; u32 val; int id; - /* - * Gen1 only - */ - if (!rsnd_is_gen1(priv)) - return 0; - id = rsnd_mod_id(mod); if (id < 0 || id >= ARRAY_SIZE(routes)) return -EIO; @@ -257,104 +387,43 @@ static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, return 0; } -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, - struct snd_pcm_runtime *runtime) -{ - struct rsnd_scu *scu; - unsigned int rate; - - /* this function is assuming SSI id = SCU id here */ - scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); - - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_scu_convert_rate(scu); - if (!rate) - rate = runtime->rate; - - return rate; -} - -static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 adinr = runtime->channels; - - /* set/clear soft reset */ - rsnd_mod_write(mod, SRC_SWRSR, 0); - rsnd_mod_write(mod, SRC_SWRSR, 1); - - /* Initialize the operation of the SRC internal circuits */ - rsnd_mod_write(mod, SRC_SRCIR, 1); - - /* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); - - if (convert_rate) { - u32 fsrate = 0x0400000 / convert_rate * runtime->rate; - - /* Enable the initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSCR, 1); - - /* Set initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSVR, fsrate); - - /* Select SRC mode (fixed value) */ - rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); + int ret; - /* Set the restriction value of the FS ratio (98%) */ - rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98); + ret = rsnd_scu_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; - if (rsnd_is_gen1(priv)) { - /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ - } - } + /* Select SRC mode (fixed value) */ + rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); - /* Cancel the initialization and operate the SRC function */ - rsnd_mod_write(mod, SRC_SRCIR, 0); + /* Set the restriction value of the FS ratio (98%) */ + rsnd_mod_write(mod, SRC_MNFSR, + rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); - /* use DMA transfer */ - rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ return 0; } -static int rsnd_scu_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int ret; - clk_enable(scu->clk); - - ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + ret = rsnd_scu_init(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_src_set_route_if_gen1(mod, rdai, io); + ret = rsnd_src_set_route_gen1(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_scu_set_convert_rate(mod, rdai, io); + ret = rsnd_scu_set_convert_rate_gen1(mod, rdai, io); if (ret < 0) return ret; @@ -365,62 +434,58 @@ static int rsnd_scu_init(struct rsnd_mod *mod, return 0; } -static int rsnd_scu_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); - clk_disable(scu->clk); + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - return 0; + return rsnd_scu_start(mod, rdai, io); } -static int rsnd_scu_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); - if (rsnd_is_gen1(priv)) - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - return 0; + return rsnd_scu_stop(mod, rdai, io); } -static int rsnd_scu_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); +static struct rsnd_mod_ops rsnd_scu_gen1_ops = { + .name = "sru (gen1)", + .init = rsnd_scu_init_gen1, + .quit = rsnd_scu_quit, + .start = rsnd_scu_start_gen1, + .stop = rsnd_scu_stop_gen1, +}; - if (rsnd_is_gen1(priv)) - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); +static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { + .name = "non-sru (gen1)", + .init = rsnd_scu_ssi_mode_init, +}; - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); +/* + * Gen2 functions + */ +static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + /* enable PIO interrupt */ + rsnd_mod_write(mod, INT_ENABLE, 0x0f000000); return 0; } -static struct rsnd_mod_ops rsnd_scu_ops = { - .name = "scu", - .init = rsnd_scu_init, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start, - .stop = rsnd_scu_stop, -}; - -static struct rsnd_mod_ops rsnd_scu_non_ops = { - .name = "scu (non)", +static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { + .name = "non-scu (gen2)", .init = rsnd_scu_ssi_mode_init, + .start = rsnd_scu_start_non_gen2, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) @@ -466,8 +531,15 @@ int rsnd_scu_probe(struct platform_device *pdev, scu->clk = clk; ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(scu)) - ops = &rsnd_scu_ops; + if (rsnd_scu_hpbif_is_enable(scu)) { + if (rsnd_is_gen1(priv)) + ops = &rsnd_scu_gen1_ops; + } else { + if (rsnd_is_gen1(priv)) + ops = &rsnd_scu_non_gen1_ops; + if (rsnd_is_gen2(priv)) + ops = &rsnd_scu_non_gen2_ops; + } rsnd_mod_init(priv, &scu->mod, ops, i); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index bae309c..b7f464e 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -363,16 +363,11 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - /* enable PIO interrupt if gen2 */ - if (rsnd_is_gen2(priv)) - rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); - rsnd_ssi_hw_start(ssi, rdai, io); return 0; -- cgit v0.10.2 From 4686a0ad9aaee89495f181e5755d153e7fe7ffe6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:44 -0800 Subject: ASoC: rsnd: remove SSI dependent DMAEngine callback Renesas Gen2 sound will use 2 DMAC which are Audio-DMAC, and Audio-DMAC-peri-peri. Current driver has callback function for each DMAC, because it assumed each DMAC needs special settings. But it became clear that these can share settings. This patch removes unnecessary callback Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 11eb0e3..b5af6f5 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -143,6 +143,7 @@ static void rsnd_dma_continue(struct rsnd_dma *dma) void rsnd_dma_start(struct rsnd_dma *dma) { /* push both A and B plane*/ + dma->offset = 0; dma->submit_loop = 2; __rsnd_dma_start(dma); } @@ -157,12 +158,26 @@ void rsnd_dma_stop(struct rsnd_dma *dma) static void rsnd_dma_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); unsigned long flags; rsnd_lock(priv, flags); - dma->complete(dma); + /* + * Renesas sound Gen1 needs 1 DMAC, + * Gen2 needs 2 DMAC. + * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri. + * But, Audio-DMAC-peri-peri doesn't have interrupt, + * and this driver is assuming that here. + * + * If Audio-DMAC-peri-peri has interrpt, + * rsnd_dai_pointer_update() will be called twice, + * ant it will breaks io->byte_pos + */ + + rsnd_dai_pointer_update(io, io->byte_per_period); if (dma->submit_loop) rsnd_dma_continue(dma); @@ -172,17 +187,21 @@ static void rsnd_dma_complete(void *data) static void __rsnd_dma_start(struct rsnd_dma *dma) { - struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; dma_addr_t buf; - size_t len; + size_t len = io->byte_per_period; int i; for (i = 0; i < dma->submit_loop; i++) { - if (dma->inquiry(dma, &buf, &len) < 0) - return; + buf = runtime->dma_addr + + rsnd_dai_pointer_offset(io, dma->offset + len); + dma->offset = len; desc = dmaengine_prep_slave_single( dma->chan, buf, len, dma->dir, @@ -217,10 +236,7 @@ int rsnd_dma_available(struct rsnd_dma *dma) } int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, - dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)) + int is_play, int id) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; @@ -253,8 +269,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma->inquiry = inquiry; - dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); return 0; @@ -307,6 +321,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, } list_add_tail(&mod->list, &io->head); + mod->io = io; return 0; } @@ -314,6 +329,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, int rsnd_dai_disconnect(struct rsnd_mod *mod) { list_del_init(&mod->list); + mod->io = NULL; return 0; } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c397dc8..b2c717d 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -100,19 +100,16 @@ struct rsnd_dma { struct work_struct work; struct dma_chan *chan; enum dma_data_direction dir; - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len); - int (*complete)(struct rsnd_dma *dma); int submit_loop; + int offset; /* it cares A/B plane */ }; void rsnd_dma_start(struct rsnd_dma *dma); void rsnd_dma_stop(struct rsnd_dma *dma); int rsnd_dma_available(struct rsnd_dma *dma); int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)); + int is_play, int id); void rsnd_dma_quit(struct rsnd_priv *priv, struct rsnd_dma *dma); @@ -137,17 +134,20 @@ struct rsnd_mod_ops { struct rsnd_dai_stream *io); }; +struct rsnd_dai_stream; struct rsnd_mod { int id; struct rsnd_priv *priv; struct rsnd_mod_ops *ops; struct list_head list; /* connect to rsnd_dai playback/capture */ struct rsnd_dma dma; + struct rsnd_dai_stream *io; }; #define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_dma(mod) (&(mod)->dma) #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) +#define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index b7f464e..d3371d7 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -64,12 +64,10 @@ struct rsnd_ssi { struct rsnd_mod mod; struct rsnd_dai *rdai; - struct rsnd_dai_stream *io; u32 cr_own; u32 cr_clk; u32 cr_etc; int err; - int dma_offset; unsigned int usrcnt; unsigned int rate; }; @@ -286,7 +284,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, * set ssi parameter */ ssi->rdai = rdai; - ssi->io = io; ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ @@ -305,7 +302,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); ssi->rdai = NULL; - ssi->io = NULL; ssi->cr_own = 0; ssi->err = 0; @@ -329,8 +325,9 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) { struct rsnd_ssi *ssi = data; - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); + struct rsnd_mod *mod = &ssi->mod; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + u32 status = rsnd_mod_read(mod, SSISR); irqreturn_t ret = IRQ_NONE; if (io && (status & DIRQ)) { @@ -347,9 +344,9 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) * see rsnd_ssi_init() */ if (rsnd_dai_is_play(rdai, io)) - rsnd_mod_write(&ssi->mod, SSITDR, *buf); + rsnd_mod_write(mod, SSITDR, *buf); else - *buf = rsnd_mod_read(&ssi->mod, SSIRDR); + *buf = rsnd_mod_read(mod, SSIRDR); rsnd_dai_pointer_update(io, sizeof(*buf)); @@ -394,33 +391,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .stop = rsnd_ssi_pio_stop, }; -static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len) -{ - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - - *len = io->byte_per_period; - *buf = runtime->dma_addr + - rsnd_dai_pointer_offset(io, ssi->dma_offset + *len); - ssi->dma_offset = *len; /* it cares A/B plane */ - - return 0; -} - -static int rsnd_ssi_dma_complete(struct rsnd_dma *dma) -{ - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); - - rsnd_ssi_record_error(ssi, status); - - rsnd_dai_pointer_update(ssi->io, io->byte_per_period); - - return 0; -} - static int rsnd_ssi_dma_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -430,7 +400,6 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, /* enable DMA transfer */ ssi->cr_etc = DMEN; - ssi->dma_offset = 0; rsnd_dma_start(dma); @@ -452,6 +421,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, ssi->cr_etc = 0; + rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); + rsnd_ssi_hw_stop(ssi, rdai); rsnd_dma_stop(dma); @@ -585,9 +556,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), rsnd_ssi_is_play(&ssi->mod), - pinfo->dma_id, - rsnd_ssi_dma_inquiry, - rsnd_ssi_dma_complete); + pinfo->dma_id); if (ret < 0) dev_info(dev, "SSI DMA failed. try PIO transter\n"); else -- cgit v0.10.2 From eb854f6dff24a59378acc8d8eda57a3543a25acc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:51 -0800 Subject: ASoC: rsnd: rsnd_ssi_probe() goes forwarder than rsnd_scu_probe() rsnd_ssi_probe() goes forwarder than rsnd_scu_probe(), since scu will need ssi information on Gen2 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index b5af6f5..f316a66 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -763,15 +763,15 @@ static int rsnd_probe(struct platform_device *pdev) if (ret) return ret; - ret = rsnd_scu_probe(pdev, info, priv); + ret = rsnd_ssi_probe(pdev, info, priv); if (ret) return ret; - ret = rsnd_adg_probe(pdev, info, priv); + ret = rsnd_scu_probe(pdev, info, priv); if (ret) return ret; - ret = rsnd_ssi_probe(pdev, info, priv); + ret = rsnd_adg_probe(pdev, info, priv); if (ret) return ret; -- cgit v0.10.2 From 629509c5bc478c0343d94c8c70812396f44447fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:42:00 -0800 Subject: ASoC: rsnd: add Gen2 SRC and DMAEngine support Renesas sound Gen2 has SRC (= Sampling Rate Converter) which needs 2 DMAC. The data path image when you use SRC on Gen2 is [mem] -> Audio-DMAC -> SRC -> Audio-DMAC-peri-peri -> SSIU -> SSI This patch support SRC and DMAEnine. It is tested on R-Car H2 Lager board Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 1d19bfc..2be05ae 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -56,9 +56,15 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ +#define RSND_SCU_SET(rate, _dma_id) \ + { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } +#define RSND_SCU_UNUSED \ + { .flags = 0, .convert_rate = 0, .dma_id = 0, } + struct rsnd_scu_platform_info { u32 flags; u32 convert_rate; /* sampling rate convert */ + int dma_id; /* for Gen2 SCU */ }; /* diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 5bdffa4..821791e 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,6 +30,144 @@ struct rsnd_adg { i++, (pos) = adg->clk[i]) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) + +static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + int id = rsnd_mod_id(mod); + int ws = id; + + if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + switch (id) { + case 1: + case 2: + ws = 0; + break; + case 4: + ws = 3; + break; + case 8: + ws = 7; + break; + } + } + + return (0x6 + ws) << 8; +} + +static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + u32 timsel) +{ + int is_play = rsnd_dai_is_play(rdai, io); + int id = rsnd_mod_id(mod); + int shift = (id % 2) ? 16 : 0; + u32 mask, ws; + u32 in, out; + + ws = rsnd_adg_ssi_ws_timing_gen2(mod); + + in = (is_play) ? timsel : ws; + out = (is_play) ? ws : timsel; + + in = in << shift; + out = out << shift; + mask = 0xffff << shift; + + switch (id / 2) { + case 0: + rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out); + break; + case 1: + rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out); + break; + case 2: + rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out); + break; + case 3: + rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out); + break; + case 4: + rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out); + break; + } + + return 0; +} + +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int idx, sel, div, step; + u32 val; + unsigned int min, diff; + unsigned int sel_rate [] = { + clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ + clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ + clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ + adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ + adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ + }; + + min = ~0; + val = 0; + for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { + idx = 0; + step = 2; + + if (!sel_rate[sel]) + continue; + + for (div = 2; div <= 98304; div += step) { + diff = abs(src_rate - sel_rate[sel] / div); + if (min > diff) { + val = (sel << 8) | idx; + min = diff; + } + + /* + * step of 0_0000 / 0_0001 / 0_1101 + * are out of order + */ + if ((idx > 2) && (idx % 2)) + step *= 2; + if (idx == 0x1c) { + div += step; + step *= 2; + } + idx++; + } + } + + if (min == ~0) { + dev_err(dev, "no Input clock\n"); + return -EIO; + } + + return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); +} + +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + u32 val = rsnd_adg_ssi_ws_timing_gen2(mod); + + return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); +} + int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index db486aa..3e03a8b 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -229,14 +229,40 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), /* FIXME: it needs SSI_MODE2/3 in the future */ + RSND_GEN2_S_REG(gen, SSIU, SSI_CONTROL, 0x810), + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), + RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), + RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b2c717d..8b66dc1 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -37,6 +37,11 @@ enum rsnd_reg { RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ + RSND_REG_SRC_CTRL, /* for Gen2 */ + RSND_REG_SSI_CTRL, /* for Gen2 */ + RSND_REG_SSI_CONTROL, + RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ + RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, RSND_REG_INT_ENABLE, /* for Gen2 */ @@ -49,6 +54,8 @@ enum rsnd_reg { RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, RSND_REG_SRC_MNFSR, /* for Gen1 */ + RSND_REG_SRC_BSDSR, /* for Gen2 */ + RSND_REG_SRC_BSISR, /* for Gen2 */ /* ADG */ RSND_REG_BRRA, @@ -60,6 +67,16 @@ enum rsnd_reg { RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ + RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ /* SSI */ RSND_REG_SSICR, @@ -250,6 +267,14 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate); +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); /* * R-Car sound priv diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 29d8990..6e5c763 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -33,6 +33,8 @@ struct rsnd_scu { container_of((_mod), struct rsnd_scu, mod) #define rsnd_scu_hpbif_is_enable(scu) \ (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) +#define rsnd_scu_dma_available(scu) \ + rsnd_dma_available(rsnd_mod_to_dma(&(scu)->mod)) #define for_each_rsnd_scu(pos, priv, i) \ for ((i) = 0; \ @@ -472,6 +474,103 @@ static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { /* * Gen2 functions */ +static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_scu_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + + rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); + + rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); + rsnd_mod_write(mod, SRC_BSISR, 0x00100060); + + return 0; +} + +static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + int ret; + + if (convert_rate) + ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, + runtime->rate, + convert_rate); + else + ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); + + return ret; +} + +static int rsnd_scu_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_scu_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_scu_set_convert_rate_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_scu_set_convert_timing_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_scu_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + rsnd_dma_start(rsnd_mod_to_dma(&scu->mod)); + + rsnd_mod_write(mod, SSI_CTRL, 0x1); + rsnd_mod_write(mod, SRC_CTRL, 0x11); + + return rsnd_scu_start(mod, rdai, io); +} + +static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + rsnd_mod_write(mod, SSI_CTRL, 0); + rsnd_mod_write(mod, SRC_CTRL, 0); + + rsnd_dma_stop(rsnd_mod_to_dma(&scu->mod)); + + return rsnd_scu_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_scu_gen2_ops = { + .name = "scu (gen2)", + .init = rsnd_scu_init_gen2, + .quit = rsnd_scu_quit, + .start = rsnd_scu_start_gen2, + .stop = rsnd_scu_stop_gen2, +}; + static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -534,6 +633,17 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_scu_hpbif_is_enable(scu)) { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; + if (rsnd_is_gen2(priv)) { + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); + int ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(&scu->mod), + rsnd_ssi_is_play(ssi), + scu->info->dma_id); + if (ret < 0) + return ret; + + ops = &rsnd_scu_gen2_ops; + } } else { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_non_gen1_ops; @@ -553,4 +663,11 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv) { + struct rsnd_scu *scu; + int i; + + for_each_rsnd_scu(scu, priv, i) { + if (rsnd_scu_dma_available(scu)) + rsnd_dma_quit(priv, rsnd_mod_to_dma(&scu->mod)); + } } -- cgit v0.10.2 From 3bba4a7889a1d23f34372aecd6de89134fe9ffd8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Jan 2014 17:30:40 +0530 Subject: ASoC: samsung: h1940_uda1380: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warning: sound/soc/samsung/h1940_uda1380.c:183:6: warning: unused variable ‘err’ [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index fbced58..3b27cd9 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -181,7 +181,6 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(dapm, "Speaker"); -- cgit v0.10.2 From 2046d453712faa9cfcc153e28c9f4b25a90ce6ed Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Jan 2014 17:30:41 +0530 Subject: ASoC: samsung: h1940_uda1380: Fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warning: sound/soc/samsung/h1940_uda1380.c:98:4: warning: passing argument 1 of ‘dev_err’ from incompatible pointer type [enabled by default] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 3b27cd9..0003b66 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -94,7 +94,7 @@ static int h1940_hw_params(struct snd_pcm_substream *substream, div++; break; default: - dev_err(&rtd->dev, "%s: rate %d is not supported\n", + dev_err(rtd->dev, "%s: rate %d is not supported\n", __func__, rate); return -EINVAL; } -- cgit v0.10.2 From d92bba83c790945ee0954f7a408b6b14418bd976 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Jan 2014 17:30:42 +0530 Subject: ASoC: samsung: rx1950_uda1380: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warning: sound/soc/samsung/rx1950_uda1380.c:228:6: warning: unused variable ‘err’ [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 06ebdc0..afbfe4a 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -226,7 +226,6 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(dapm, "Speaker"); -- cgit v0.10.2 From f227b88f0fce5f9b82aa934f8829a741c2e06d82 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:02:10 +0100 Subject: ASoC: core: Add signed register volume control logic Some codecs use signed volume control representation with non standard register sizes, e.g. 6 or 7 bit signed integers. This patch adds generic signed register volume control logic to soc-core. Instead of a fixed width signed register control, this implementation uses a 'min' value and the signed bit location to translate it to an absolute volume. Using the 'sign_bit' we can calculate a correct mask for the register values and translate it back into signed integers of standard size. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a00147..a25f3cc 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1067,6 +1067,7 @@ struct soc_mixer_control { int min, max, platform_max; int reg, rreg; unsigned int shift, rshift; + unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50..c1d9d85 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2716,6 +2716,48 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); /** + * snd_soc_read_signed - Read a codec register and interprete as signed value + * @codec: codec + * @reg: Register to read + * @mask: Mask to use after shifting the register value + * @shift: Right shift of register value + * @sign_bit: Bit that describes if a number is negative or not. + * + * This functions reads a codec register. The register value is shifted right + * by 'shift' bits and masked with the given 'mask'. Afterwards it translates + * the given registervalue into a signed integer if sign_bit is non-zero. + * + * Returns the register value as signed int. + */ +static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg, + unsigned int mask, unsigned int shift, unsigned int sign_bit) +{ + int ret; + unsigned int val; + + val = (snd_soc_read(codec, reg) >> shift) & mask; + + if (!sign_bit) + return val; + + /* non-negative number */ + if (!(val & BIT(sign_bit))) + return val; + + ret = val; + + /* + * The register most probably does not contain a full-sized int. + * Instead we have an arbitrary number of bits in a signed + * representation which has to be translated into a full-sized int. + * This is done by filling up all bits above the sign-bit. + */ + ret |= ~((int)(BIT(sign_bit) - 1)); + + return ret; +} + +/** * snd_soc_info_volsw - single mixer info callback * @kcontrol: mixer control * @uinfo: control element information @@ -2743,7 +2785,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = platform_max; + uinfo->value.integer.max = platform_max - mc->min; return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_volsw); @@ -2769,11 +2811,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - ucontrol->value.integer.value[0] = - (snd_soc_read(codec, reg) >> shift) & mask; + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask, + shift, sign_bit) - min; if (invert) ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0]; @@ -2781,10 +2828,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) { if (reg == reg2) ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg) >> rshift) & mask; + snd_soc_read_signed(codec, reg, mask, rshift, + sign_bit) - min; else ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg2) >> shift) & mask; + snd_soc_read_signed(codec, reg2, mask, shift, + sign_bit) - min; if (invert) ucontrol->value.integer.value[1] = max - ucontrol->value.integer.value[1]; @@ -2815,6 +2864,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + unsigned int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; @@ -2822,13 +2873,16 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int val2 = 0; unsigned int val, val_mask; - val = (ucontrol->value.integer.value[0] & mask); + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + val = ((ucontrol->value.integer.value[0] + min) & mask); if (invert) val = max - val; val_mask = mask << shift; val = val << shift; if (snd_soc_volsw_is_stereo(mc)) { - val2 = (ucontrol->value.integer.value[1] & mask); + val2 = ((ucontrol->value.integer.value[1] + min) & mask); if (invert) val2 = max - val2; if (reg == reg2) { -- cgit v0.10.2 From cd21b123346c6a2f033d8c3bd2bf240198b5712a Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:02:11 +0100 Subject: ASoC: core: Add SOC_DOUBLE_R_S_TLV Add a macro for signed mixer with two registers and tlv array. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index a25f3cc..c4be7ab 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -45,6 +45,11 @@ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ + ((unsigned long)&(struct soc_mixer_control) \ + {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ + .max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \ + .invert = xinvert}) #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ @@ -152,6 +157,15 @@ {.reg = xreg, .rreg = xrreg, \ .shift = xshift, .rshift = xshift, \ .max = xmax, .min = xmin} } +#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ + xmin, xmax, xsign_bit, xinvert) } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ -- cgit v0.10.2 From 7722f830a45f7fbb8f2f7b23265793980bdf3397 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:33 +0100 Subject: ASoC: simple-card: simplify code The check of the mandatory fields is done for DT in its specific sequence. Move the global check to the non-DT sequence. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2a1b1b5..f0784ca 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -225,16 +225,16 @@ static int asoc_simple_card_probe(struct platform_device *pdev) memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); cinfo->snd_card.dev = dev; - } - if (!cinfo->name || - !cinfo->card || - !cinfo->codec_dai.name || - !(cinfo->codec || of_codec) || - !(cinfo->platform || of_platform) || - !(cinfo->cpu_dai.name || of_cpu)) { - dev_err(dev, "insufficient asoc_simple_card_info settings\n"); - return -EINVAL; + if (!cinfo->name || + !cinfo->card || + !cinfo->codec_dai.name || + !cinfo->codec || + !cinfo->platform || + !cinfo->cpu_dai.name) { + dev_err(dev, "insufficient asoc_simple_card_info settings\n"); + return -EINVAL; + } } /* -- cgit v0.10.2 From 2bee991460a838ee3c8064a6d880c4e7bc41717a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:37 +0100 Subject: ASoC: simple-card: simplify code The DT values are copied to the non-DT structure before being moved to the card structure. Set directly the DT values in the card and move the non-DT copy to the non-DT sequence. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index f0784ca..7c5dc73 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -169,12 +169,13 @@ static int asoc_simple_card_parse_of(struct device_node *node, strlen(info->codec_dai.name) + 2, GFP_KERNEL); sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); - info->name = info->card = name; + info->snd_card.name = name; + info->snd_link.name = info->snd_link.stream_name = name; /* simple-card assumes platform == cpu */ *of_platform = *of_cpu; - dev_dbg(dev, "card-name : %s\n", info->card); + dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", info->cpu_dai.name, @@ -217,6 +218,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) dev_err(dev, "parse error %d\n", ret); return ret; } + cinfo->snd_link.cpu_of_node = of_cpu; + cinfo->snd_link.codec_of_node = of_codec; + cinfo->snd_link.platform_of_node = of_platform; } else { if (!dev->platform_data) { dev_err(dev, "no info for asoc-simple-card\n"); @@ -235,26 +239,24 @@ static int asoc_simple_card_probe(struct platform_device *pdev) dev_err(dev, "insufficient asoc_simple_card_info settings\n"); return -EINVAL; } + + cinfo->snd_card.name = cinfo->card; + cinfo->snd_link.name = cinfo->name; + cinfo->snd_link.stream_name = cinfo->name; + cinfo->snd_link.platform_name = cinfo->platform; + cinfo->snd_link.codec_name = cinfo->codec; } /* * init snd_soc_dai_link */ - cinfo->snd_link.name = cinfo->name; - cinfo->snd_link.stream_name = cinfo->name; cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai.name; - cinfo->snd_link.platform_name = cinfo->platform; - cinfo->snd_link.codec_name = cinfo->codec; cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; - cinfo->snd_link.cpu_of_node = of_cpu; - cinfo->snd_link.codec_of_node = of_codec; - cinfo->snd_link.platform_of_node = of_platform; cinfo->snd_link.init = asoc_simple_card_dai_init; /* * init snd_soc_card */ - cinfo->snd_card.name = cinfo->card; cinfo->snd_card.owner = THIS_MODULE; cinfo->snd_card.dai_link = &cinfo->snd_link; cinfo->snd_card.num_links = 1; -- cgit v0.10.2 From 201a0eac7fe5e7a8fa33f0742304f885bc344d0d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:41 +0100 Subject: ASoC: simple-card: simplify code The OF pointers are put in the stack and then copied to the card descriptor. Put them directly at their right place. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7c5dc73..89f83b3 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -60,8 +60,9 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, struct asoc_simple_dai *dai, - struct device_node **node) + const struct device_node **p_node) { + struct device_node *node; struct clk *clk; int ret; @@ -69,9 +70,10 @@ asoc_simple_card_sub_parse_of(struct device_node *np, * get node via "sound-dai = <&phandle port>" * it will be used as xxx_of_node on soc_bind_dai_link() */ - *node = of_parse_phandle(np, "sound-dai", 0); - if (!*node) + node = of_parse_phandle(np, "sound-dai", 0); + if (!node) return -ENODEV; + *p_node = node; /* get dai->name */ ret = snd_soc_of_get_dai_name(np, &dai->name); @@ -104,7 +106,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, "system-clock-frequency", &dai->sysclk); } else { - clk = of_clk_get(*node, 0); + clk = of_clk_get(node, 0); if (!IS_ERR(clk)) dai->sysclk = clk_get_rate(clk); } @@ -112,17 +114,14 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ret = 0; parse_error: - of_node_put(*node); + of_node_put(node); return ret; } static int asoc_simple_card_parse_of(struct device_node *node, struct asoc_simple_card_info *info, - struct device *dev, - struct device_node **of_cpu, - struct device_node **of_codec, - struct device_node **of_platform) + struct device *dev) { struct device_node *np; char *name; @@ -146,7 +145,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->cpu_dai, - of_cpu); + &info->snd_link.cpu_of_node); if (ret < 0) return ret; @@ -156,7 +155,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->codec_dai, - of_codec); + &info->snd_link.codec_of_node); if (ret < 0) return ret; @@ -173,7 +172,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, info->snd_link.name = info->snd_link.stream_name = name; /* simple-card assumes platform == cpu */ - *of_platform = *of_cpu; + info->snd_link.platform_of_node = info->snd_link.cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); @@ -193,34 +192,29 @@ static int asoc_simple_card_probe(struct platform_device *pdev) { struct asoc_simple_card_info *cinfo; struct device_node *np = pdev->dev.of_node; - struct device_node *of_cpu, *of_codec, *of_platform; struct device *dev = &pdev->dev; int ret; - cinfo = NULL; - of_cpu = NULL; - of_codec = NULL; - of_platform = NULL; - cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); if (!cinfo) return -ENOMEM; + /* + * init snd_soc_card + */ + cinfo->snd_card.owner = THIS_MODULE; + cinfo->snd_card.dev = dev; + cinfo->snd_card.dai_link = &cinfo->snd_link; + cinfo->snd_card.num_links = 1; + if (np && of_device_is_available(np)) { - cinfo->snd_card.dev = dev; - ret = asoc_simple_card_parse_of(np, cinfo, dev, - &of_cpu, - &of_codec, - &of_platform); + ret = asoc_simple_card_parse_of(np, cinfo, dev); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); return ret; } - cinfo->snd_link.cpu_of_node = of_cpu; - cinfo->snd_link.codec_of_node = of_codec; - cinfo->snd_link.platform_of_node = of_platform; } else { if (!dev->platform_data) { dev_err(dev, "no info for asoc-simple-card\n"); @@ -228,8 +222,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) } memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); - cinfo->snd_card.dev = dev; - if (!cinfo->name || !cinfo->card || !cinfo->codec_dai.name || @@ -254,13 +246,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; cinfo->snd_link.init = asoc_simple_card_dai_init; - /* - * init snd_soc_card - */ - cinfo->snd_card.owner = THIS_MODULE; - cinfo->snd_card.dai_link = &cinfo->snd_link; - cinfo->snd_card.num_links = 1; - snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); -- cgit v0.10.2 From 5ca8ba4180a6f629d51dba699b4a6428cc5eeba7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:45 +0100 Subject: ASoC: simple-card: simplify code Have a cleaner code using a DAI link pointer. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 89f83b3..797696f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -123,6 +123,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct asoc_simple_card_info *info, struct device *dev) { + struct snd_soc_dai_link *dai_link = info->snd_card.dai_link; struct device_node *np; char *name; int ret; @@ -145,7 +146,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->cpu_dai, - &info->snd_link.cpu_of_node); + &dai_link->cpu_of_node); if (ret < 0) return ret; @@ -155,7 +156,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->codec_dai, - &info->snd_link.codec_of_node); + &dai_link->codec_of_node); if (ret < 0) return ret; @@ -169,10 +170,10 @@ static int asoc_simple_card_parse_of(struct device_node *node, GFP_KERNEL); sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); info->snd_card.name = name; - info->snd_link.name = info->snd_link.stream_name = name; + dai_link->name = dai_link->stream_name = name; /* simple-card assumes platform == cpu */ - info->snd_link.platform_of_node = info->snd_link.cpu_of_node; + dai_link->platform_of_node = dai_link->cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); @@ -191,6 +192,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { struct asoc_simple_card_info *cinfo; + struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int ret; @@ -204,8 +206,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) */ cinfo->snd_card.owner = THIS_MODULE; cinfo->snd_card.dev = dev; - cinfo->snd_card.dai_link = &cinfo->snd_link; - cinfo->snd_card.num_links = 1; + dai_link = &cinfo->snd_link; + cinfo->snd_card.dai_link = dai_link; + cinfo->snd_card.num_links = 1; if (np && of_device_is_available(np)) { @@ -233,18 +236,18 @@ static int asoc_simple_card_probe(struct platform_device *pdev) } cinfo->snd_card.name = cinfo->card; - cinfo->snd_link.name = cinfo->name; - cinfo->snd_link.stream_name = cinfo->name; - cinfo->snd_link.platform_name = cinfo->platform; - cinfo->snd_link.codec_name = cinfo->codec; + dai_link->name = cinfo->name; + dai_link->stream_name = cinfo->name; + dai_link->platform_name = cinfo->platform; + dai_link->codec_name = cinfo->codec; } /* * init snd_soc_dai_link */ - cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai.name; - cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; - cinfo->snd_link.init = asoc_simple_card_dai_init; + dai_link->cpu_dai_name = cinfo->cpu_dai.name; + dai_link->codec_dai_name = cinfo->codec_dai.name; + dai_link->init = asoc_simple_card_dai_init; snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); -- cgit v0.10.2 From 520084729267ac8df1651ad2f118a1d4a631a10a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:48 +0100 Subject: ASoC: simple-card: simplify code The CPU and CODEC DAI names are still copied to the user info structure. Put them directly in the DAI links. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 797696f..9068ab4 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -60,7 +60,8 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, struct asoc_simple_dai *dai, - const struct device_node **p_node) + const struct device_node **p_node, + const char **name) { struct device_node *node; struct clk *clk; @@ -76,7 +77,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, *p_node = node; /* get dai->name */ - ret = snd_soc_of_get_dai_name(np, &dai->name); + ret = snd_soc_of_get_dai_name(np, name); if (ret < 0) goto parse_error; @@ -146,7 +147,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->cpu_dai, - &dai_link->cpu_of_node); + &dai_link->cpu_of_node, + &dai_link->cpu_dai_name); if (ret < 0) return ret; @@ -156,19 +158,21 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->codec_dai, - &dai_link->codec_of_node); + &dai_link->codec_of_node, + &dai_link->codec_dai_name); if (ret < 0) return ret; - if (!info->cpu_dai.name || !info->codec_dai.name) + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) return -EINVAL; /* card name is created from CPU/CODEC dai name */ name = devm_kzalloc(dev, - strlen(info->cpu_dai.name) + - strlen(info->codec_dai.name) + 2, + strlen(dai_link->cpu_dai_name) + + strlen(dai_link->codec_dai_name) + 2, GFP_KERNEL); - sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); + sprintf(name, "%s-%s", dai_link->cpu_dai_name, + dai_link->codec_dai_name); info->snd_card.name = name; dai_link->name = dai_link->stream_name = name; @@ -178,11 +182,11 @@ static int asoc_simple_card_parse_of(struct device_node *node, dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", - info->cpu_dai.name, + dai_link->cpu_dai_name, info->cpu_dai.fmt, info->cpu_dai.sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", - info->codec_dai.name, + dai_link->codec_dai_name, info->codec_dai.fmt, info->codec_dai.sysclk); @@ -240,13 +244,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) dai_link->stream_name = cinfo->name; dai_link->platform_name = cinfo->platform; dai_link->codec_name = cinfo->codec; + dai_link->cpu_dai_name = cinfo->cpu_dai.name; + dai_link->codec_dai_name = cinfo->codec_dai.name; } /* * init snd_soc_dai_link */ - dai_link->cpu_dai_name = cinfo->cpu_dai.name; - dai_link->codec_dai_name = cinfo->codec_dai.name; dai_link->init = asoc_simple_card_dai_init; snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); -- cgit v0.10.2 From ca65b492c7a265b220f763fd68bf87391213248f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:52 +0100 Subject: ASoC: simple-card: simplify code In the non-DT sequence, the platform data is copied as a whole to the dynamic card info and the same pointer 'cinfo' is used to copy the platform information to the card. Use 'priv' as the pointer to the dynamic card info and copy only the useful information from the platform data. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9068ab4..90c6fd5 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -195,40 +195,42 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { - struct asoc_simple_card_info *cinfo; + struct asoc_simple_card_info *priv; struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int ret; - cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); - if (!cinfo) + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; /* * init snd_soc_card */ - cinfo->snd_card.owner = THIS_MODULE; - cinfo->snd_card.dev = dev; - dai_link = &cinfo->snd_link; - cinfo->snd_card.dai_link = dai_link; - cinfo->snd_card.num_links = 1; + priv->snd_card.owner = THIS_MODULE; + priv->snd_card.dev = dev; + dai_link = &priv->snd_link; + priv->snd_card.dai_link = dai_link; + priv->snd_card.num_links = 1; if (np && of_device_is_available(np)) { - ret = asoc_simple_card_parse_of(np, cinfo, dev); + ret = asoc_simple_card_parse_of(np, priv, dev); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); return ret; } } else { - if (!dev->platform_data) { + struct asoc_simple_card_info *cinfo; + + cinfo = dev->platform_data; + if (!cinfo) { dev_err(dev, "no info for asoc-simple-card\n"); return -EINVAL; } - memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); if (!cinfo->name || !cinfo->card || !cinfo->codec_dai.name || @@ -239,13 +241,17 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return -EINVAL; } - cinfo->snd_card.name = cinfo->card; + priv->snd_card.name = cinfo->card; dai_link->name = cinfo->name; dai_link->stream_name = cinfo->name; dai_link->platform_name = cinfo->platform; dai_link->codec_name = cinfo->codec; dai_link->cpu_dai_name = cinfo->cpu_dai.name; dai_link->codec_dai_name = cinfo->codec_dai.name; + memcpy(&priv->cpu_dai, &cinfo->cpu_dai, + sizeof(priv->cpu_dai)); + memcpy(&priv->codec_dai, &cinfo->codec_dai, + sizeof(priv->codec_dai)); } /* @@ -253,9 +259,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) */ dai_link->init = asoc_simple_card_dai_init; - snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); + snd_soc_card_set_drvdata(&priv->snd_card, priv); - return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); + return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); } static const struct of_device_id asoc_simple_of_match[] = { -- cgit v0.10.2 From 45fce59496cbabd46761e6980c05c82d94d08eaa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:56 +0100 Subject: ASoC: simple-card: simplify code The platform data structure contains information which is used only by the driver, and the driver allocates platform information fields which are of no use. Move the driver specific data to a new private structure and cleanup the platform data structure. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index 6c74527..e1ac996 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -29,10 +29,6 @@ struct asoc_simple_card_info { unsigned int daifmt; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai codec_dai; - - /* used in simple-card.c */ - struct snd_soc_dai_link snd_link; - struct snd_soc_card snd_card; }; #endif /* __SIMPLE_CARD_H */ diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 90c6fd5..0f11c28 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -15,6 +15,14 @@ #include #include +struct simple_card_data { + struct snd_soc_card snd_card; + unsigned int daifmt; + struct asoc_simple_dai cpu_dai; + struct asoc_simple_dai codec_dai; + struct snd_soc_dai_link snd_link; +}; + static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, struct asoc_simple_dai *set, unsigned int daifmt) @@ -39,7 +47,7 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct asoc_simple_card_info *info = + struct simple_card_data *info = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; @@ -121,7 +129,7 @@ parse_error: } static int asoc_simple_card_parse_of(struct device_node *node, - struct asoc_simple_card_info *info, + struct simple_card_data *info, struct device *dev) { struct snd_soc_dai_link *dai_link = info->snd_card.dai_link; @@ -195,7 +203,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { - struct asoc_simple_card_info *priv; + struct simple_card_data *priv; struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; -- cgit v0.10.2 From b367a3252b365fd545fc589a40cad3976e73d7d7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:52:00 +0100 Subject: ASoC: simple-card: simplify code Rename the pointer to the private data structure to 'priv' to avoid confusion with the platform data pointer. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 0f11c28..6443c87 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -47,18 +47,18 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct simple_card_data *info = + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - unsigned int daifmt = info->daifmt; + unsigned int daifmt = priv->daifmt; int ret; - ret = __asoc_simple_card_dai_init(codec, &info->codec_dai, daifmt); + ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai, daifmt); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &info->cpu_dai, daifmt); + ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai, daifmt); if (ret < 0) return ret; @@ -129,21 +129,21 @@ parse_error: } static int asoc_simple_card_parse_of(struct device_node *node, - struct simple_card_data *info, + struct simple_card_data *priv, struct device *dev) { - struct snd_soc_dai_link *dai_link = info->snd_card.dai_link; + struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct device_node *np; char *name; int ret; /* get CPU/CODEC common format via simple-audio-card,format */ - info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & + priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); /* DAPM routes */ if (of_property_read_bool(node, "simple-audio-card,routing")) { - ret = snd_soc_of_parse_audio_routing(&info->snd_card, + ret = snd_soc_of_parse_audio_routing(&priv->snd_card, "simple-audio-card,routing"); if (ret) return ret; @@ -154,7 +154,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) ret = asoc_simple_card_sub_parse_of(np, - &info->cpu_dai, + &priv->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); if (ret < 0) @@ -165,7 +165,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) ret = asoc_simple_card_sub_parse_of(np, - &info->codec_dai, + &priv->codec_dai, &dai_link->codec_of_node, &dai_link->codec_dai_name); if (ret < 0) @@ -181,22 +181,22 @@ static int asoc_simple_card_parse_of(struct device_node *node, GFP_KERNEL); sprintf(name, "%s-%s", dai_link->cpu_dai_name, dai_link->codec_dai_name); - info->snd_card.name = name; + priv->snd_card.name = name; dai_link->name = dai_link->stream_name = name; /* simple-card assumes platform == cpu */ dai_link->platform_of_node = dai_link->cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); - dev_dbg(dev, "platform : %04x\n", info->daifmt); + dev_dbg(dev, "platform : %04x\n", priv->daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", dai_link->cpu_dai_name, - info->cpu_dai.fmt, - info->cpu_dai.sysclk); + priv->cpu_dai.fmt, + priv->cpu_dai.sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", dai_link->codec_dai_name, - info->codec_dai.fmt, - info->codec_dai.sysclk); + priv->codec_dai.fmt, + priv->codec_dai.sysclk); return 0; } -- cgit v0.10.2 From 4763ebe226156db985fe75bfe930c4069d1f4207 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 24 Jan 2014 15:43:00 +0800 Subject: ASoC: simple-card: fix __asoc_simple_card_dai_init If the CPU/CODEC DAI set_sysclk() is not support, the -ENOTSUPP will returnd. Here do the check like set_fmt(). Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 6443c87..6366f3f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -27,21 +27,29 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, struct asoc_simple_dai *set, unsigned int daifmt) { - int ret = 0; + int ret; daifmt |= set->fmt; - if (daifmt) + if (daifmt) { ret = snd_soc_dai_set_fmt(dai, daifmt); - - if (ret == -ENOTSUPP) { - dev_dbg(dai->dev, "ASoC: set_fmt is not supported\n"); - ret = 0; + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_fmt error\n"); + goto err; + } } - if (!ret && set->sysclk) + if (set->sysclk) { ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_sysclk error\n"); + goto err; + } + } + + ret = 0; +err: return ret; } -- cgit v0.10.2 From 30d0341e7da0c012f64fb290dd1153360fb49a8d Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 24 Jan 2014 15:43:01 +0800 Subject: ASoC: simple-card: simplify the daifmt code In the asoc_simple_card_parse_of() will parse the device node's CPU/CODEC DAI commone fmts, and then in asoc_simple_card_sub_parse_of() will parse the CPU/CODEC DAI's sub-node fmts, so we can combine the info->daifmt and info->set.fmt in asoc_simple_card_sub_parse_of() not while just before _set_fmt(). And this will be more easy to add new functions, such as supporting _set_tdm_slot(), etc. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 6366f3f..65833fe 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -24,15 +24,12 @@ struct simple_card_data { }; static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, - struct asoc_simple_dai *set, - unsigned int daifmt) + struct asoc_simple_dai *set) { int ret; - daifmt |= set->fmt; - - if (daifmt) { - ret = snd_soc_dai_set_fmt(dai, daifmt); + if (set->fmt) { + ret = snd_soc_dai_set_fmt(dai, set->fmt); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_fmt error\n"); goto err; @@ -59,14 +56,13 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - unsigned int daifmt = priv->daifmt; int ret; - ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai, daifmt); + ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai, daifmt); + ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai); if (ret < 0) return ret; @@ -75,6 +71,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, + unsigned int daifmt, struct asoc_simple_dai *dai, const struct device_node **p_node, const char **name) @@ -103,6 +100,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, * and specific "format" if it has */ dai->fmt = snd_soc_of_parse_daifmt(np, NULL); + dai->fmt |= daifmt; /* * dai->sysclk come from @@ -161,7 +159,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) - ret = asoc_simple_card_sub_parse_of(np, + ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, &priv->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); @@ -172,7 +170,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) - ret = asoc_simple_card_sub_parse_of(np, + ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, &priv->codec_dai, &dai_link->codec_of_node, &dai_link->codec_dai_name); -- cgit v0.10.2 From 2772555b6c5ba79783c04ea6c60549530d737e2e Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 24 Jan 2014 15:43:02 +0800 Subject: ASoC: simple-card: Add snd_card's name parsing from DT node support If the DT is used and the CPU DAI device has only one DAI, the card name will be like : ALSA device list: 0: 40031000.sai-sgtl5000 And this name maybe a little ugly to some customers, so here the card name parsing from DT node is supported. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 65833fe..0890fcd 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -143,6 +143,9 @@ static int asoc_simple_card_parse_of(struct device_node *node, char *name; int ret; + /* parsing the card name from DT */ + snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); + /* get CPU/CODEC common format via simple-audio-card,format */ priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); @@ -187,7 +190,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, GFP_KERNEL); sprintf(name, "%s-%s", dai_link->cpu_dai_name, dai_link->codec_dai_name); - priv->snd_card.name = name; + if (!priv->snd_card.name) + priv->snd_card.name = name; dai_link->name = dai_link->stream_name = name; /* simple-card assumes platform == cpu */ -- cgit v0.10.2 From a74ab5121f8d91fb7f13ac1c86e72e9d35e0bc29 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:30:25 +0100 Subject: ASoC: tlv320aic32x4: Use gpio_is_valid Use function gpio_is_valid to check for gpio ports. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 688151b..36a9cb9 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -588,7 +588,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec) snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (aic32x4->rstn_gpio >= 0) { + if (gpio_is_valid(aic32x4->rstn_gpio)) { ndelay(10); gpio_set_value(aic32x4->rstn_gpio, 1); } @@ -693,7 +693,7 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } - if (aic32x4->rstn_gpio >= 0) { + if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); if (ret != 0) -- cgit v0.10.2 From c671e79d6c2d5a525496fbf18103841c68fe3305 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 27 Jan 2014 13:03:07 +0100 Subject: ASoC: tlv320aic32x4: Use signed int mixer controls There are a number of mixer controls that support negative values. They use signed values for this with different number of bits for the values. Currently they only support the positive range. This patch replaces the unsigned mixers with signed mixers to support the full range. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 36a9cb9..c541213 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -68,18 +68,24 @@ struct aic32x4_priv { int rstn_gpio; }; -/* 0dB min, 1dB steps */ -static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); /* 0dB min, 0.5dB steps */ static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); +/* -63.5dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0); +/* -6dB min, 1dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0); +/* -12dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); static const struct snd_kcontrol_new aic32x4_snd_controls[] = { - SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, - AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), - SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, - AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), - SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, - AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), + SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, + AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), + SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, + AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), + SOC_DOUBLE_R_S_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, + AIC32X4_LORGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, AIC32X4_HPRGAIN, 6, 0x01, 1), SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, @@ -90,8 +96,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = { SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), - SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, - AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), + SOC_DOUBLE_R_S_TLV("ADC Level Volume", AIC32X4_LADCVOL, + AIC32X4_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol), SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), -- cgit v0.10.2 From 4d16700dd926d4c4a66a91a138c34eef4fd342b4 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 27 Jan 2014 13:03:08 +0100 Subject: ASoC: tlv320aic32x4: DT support Add DT support for this codec. The bindings differ a bit from the aic3x codec bindings, so I created a new binding documentation. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt new file mode 100644 index 0000000..db05510 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -0,0 +1,18 @@ +Texas Instruments - tlv320aic32x4 Codec module + +The tlv320aic32x4 serial control bus communicates through I2C protocols + +Required properties: + - compatible: Should be "ti,tlv320aic32x4" + - reg: I2C slave address + +Optional properties: + - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt + + +Example: + +codec: tlv320aic32x4@18 { + compatible = "ti,tlv320aic32x4"; + reg = <0x18>; +}; diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index c541213..1dd50e4 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -669,11 +670,22 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), }; +static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, + struct device_node *np) +{ + aic32x4->swapdacs = false; + aic32x4->micpga_routing = 0; + aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0); + + return 0; +} + static int aic32x4_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct aic32x4_pdata *pdata = i2c->dev.platform_data; struct aic32x4_priv *aic32x4; + struct device_node *np = i2c->dev.of_node; int ret; aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), @@ -692,6 +704,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->swapdacs = pdata->swapdacs; aic32x4->micpga_routing = pdata->micpga_routing; aic32x4->rstn_gpio = pdata->rstn_gpio; + } else if (np) { + ret = aic32x4_parse_dt(aic32x4, np); + if (ret) { + dev_err(&i2c->dev, "Failed to parse DT node\n"); + return ret; + } } else { aic32x4->power_cfg = 0; aic32x4->swapdacs = false; @@ -723,10 +741,17 @@ static const struct i2c_device_id aic32x4_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); +static const struct of_device_id aic32x4_of_id[] = { + { .compatible = "ti,tlv320aic32x4", }, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, aic32x4_of_id); + static struct i2c_driver aic32x4_i2c_driver = { .driver = { .name = "tlv320aic32x4", .owner = THIS_MODULE, + .of_match_table = aic32x4_of_id, }, .probe = aic32x4_i2c_probe, .remove = aic32x4_i2c_remove, -- cgit v0.10.2 From 7e9614ebcf4d74edba864cc91e1e8a3ec6b32fc2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 19:55:45 +0000 Subject: ASoC: wm8962: Hold a runtime PM reference while handling interrupts If the device is runtime suspended then we can't interact with it as it may have been powered off and the register map will be in cache only mode. Signed-off-by: Mark Brown Acked-by: Charles Keepax diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b4..1996567 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3003,9 +3003,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) unsigned int active; int reg, ret; + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "Failed to resume: %d\n", ret); + return IRQ_NONE; + } + ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, &mask); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt mask: %d\n", ret); return IRQ_NONE; @@ -3013,14 +3020,17 @@ static irqreturn_t wm8962_irq(int irq, void *data) ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt: %d\n", ret); return IRQ_NONE; } active &= ~mask; - if (!active) + if (!active) { + pm_runtime_put(dev); return IRQ_NONE; + } /* Acknowledge the interrupts */ ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); @@ -3070,6 +3080,8 @@ static irqreturn_t wm8962_irq(int irq, void *data) msecs_to_jiffies(250)); } + pm_runtime_put(dev); + return IRQ_HANDLED; } -- cgit v0.10.2 From df6ab65f2fef3d7b769f3ba87c7bb265ace80b4e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 19:59:31 +0000 Subject: ASoC: wm8962: Check if we runtime resume the device when starting FLL Signed-off-by: Mark Brown Acked-by: Charles Keepax diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1996567..d7d43c9 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2886,7 +2886,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, try_wait_for_completion(&wm8962->fll_lock); - pm_runtime_get_sync(codec->dev); + ret = pm_runtime_get_sync(codec->dev); + if (ret < 0) { + dev_err(codec->dev, "Failed to resume device: %d\n", ret); + return ret; + } snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | -- cgit v0.10.2 From d6f95e5407674d2f7d61feef81fef96b364d9188 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 20:04:34 +0000 Subject: ASoC: wm8962: Clean up error handling for failed FLL start Don't record the FLL as having started and leave the hardware disabled ensuring we are in a better state if this does happen to be a transient error and making debugging easier. Signed-off-by: Mark Brown Acked-by: Charles Keepax diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d7d43c9..cd96d46 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2898,8 +2898,6 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); - ret = 0; - /* This should be a massive overestimate but go even * higher if we'll error out */ @@ -2913,14 +2911,17 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, if (timeout == 0 && wm8962->irq) { dev_err(codec->dev, "FLL lock timed out"); - ret = -ETIMEDOUT; + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_ENA, 0); + pm_runtime_put(codec->dev); + return -ETIMEDOUT; } wm8962->fll_fref = Fref; wm8962->fll_fout = Fout; wm8962->fll_src = source; - return ret; + return 0; } static int wm8962_mute(struct snd_soc_dai *dai, int mute) -- cgit v0.10.2 From 9d7433b064a6349aae8a266e8243ef75637bec45 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 20:32:06 +0000 Subject: ASoC: wm8962: Reinitialise the IRQ completion rather than just trying it This is better practice. Signed-off-by: Mark Brown Acked-by: Charles Keepax diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index cd96d46..c06bb50 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2884,7 +2884,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); - try_wait_for_completion(&wm8962->fll_lock); + reinit_completion(&wm8962->fll_lock); ret = pm_runtime_get_sync(codec->dev); if (ret < 0) { -- cgit v0.10.2 From 0d724f8a3bbc9b0ffd658732714d23694ff4abca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Jan 2014 12:50:51 +0000 Subject: ASoC: ak4554: Add to SND_SOC_ALL_CODECS For build coverage. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087a..034130b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -25,6 +25,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER select SND_SOC_AK4535 if I2C + select SND_SOC_AK4554 select SND_SOC_AK4641 if I2C select SND_SOC_AK4642 if I2C select SND_SOC_AK4671 if I2C -- cgit v0.10.2 From 50a68fb4bc2516f593ceffa6617c93090d335f31 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Jan 2014 16:07:05 +0000 Subject: ASoC: pcm1681: Convert to params_width() This will help support future enhancements in the way we negotiate parameters in the core. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 73f9c36..e427544 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -172,16 +172,21 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); int val = 0, ret; - int pcm_format = params_format(params); priv->rate = params_rate(params); switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_RIGHT_J: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE) - val = 0x00; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x03; + switch (params_width(params)) { + case 24: + val = 0; + break; + case 16: + val = 3; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_I2S: val = 0x04; -- cgit v0.10.2 From e48c6d7f01032c42907dc2cd81b73f95490c81a1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Jan 2014 16:07:16 +0000 Subject: ASoC: pcm1792a: Convert to params_width() This will help support future enhancements in the way we negotiate parameters in the core. Signed-off-by: Mark Brown Acked-by: Michael Trimarchi diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c index 7146653a..3a80ba4 100644 --- a/sound/soc/codecs/pcm1792a.c +++ b/sound/soc/codecs/pcm1792a.c @@ -107,24 +107,35 @@ static int pcm1792a_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); int val = 0, ret; - int pcm_format = params_format(params); priv->rate = params_rate(params); switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_RIGHT_J: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || - pcm_format == SNDRV_PCM_FORMAT_S32_LE) - val = 0x02; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x00; + switch (params_width(params)) { + case 24: + case 32: + val = 2; + break; + case 16: + val = 0; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_I2S: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || - pcm_format == SNDRV_PCM_FORMAT_S32_LE) - val = 0x05; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x04; + switch (params_width(params)) { + case 24: + case 32: + val = 5; + break; + case 16: + val = 4; + break; + default: + return -EINVAL; + } break; default: dev_err(codec->dev, "Invalid DAI format\n"); -- cgit v0.10.2 From 9f9c47f00ce99329b1a82e2ac4f70f0fe3db549c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Feb 2014 10:42:07 -0500 Subject: sata_sil: apply MOD15WRITE quirk to TOSHIBA MK2561GSYN It's a bit odd to see a newer device showing mod15write; however, the reported behavior is highly consistent and other factors which could contribute seem to have been verified well enough. Also, both sata_sil itself and the drive are fairly outdated at this point making the risk of this change fairly low. It is possible, probably likely, that other drive models in the same family have the same problem; however, for now, let's just add the specific model which was tested. Signed-off-by: Tejun Heo Reported-by: matson References: http://lkml.kernel.org/g/201401211912.s0LJCk7F015058@rs103.luxsci.com Cc: stable@vger.kernel.org diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index d67fc35..b7695e8 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -157,6 +157,7 @@ static const struct sil_drivelist { { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, + { "TOSHIBA MK2561GSYN", SIL_QUIRK_MOD15WRITE }, { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, { } }; -- cgit v0.10.2 From 1ff6bbfd13ca2c114a5cb58e1a92d1e5d68ce0b7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 28 Jan 2014 18:10:37 -0500 Subject: arm, pm, vmpressure: add missing slab.h includes arch/arm/mach-tegra/pm.c, kernel/power/console.c and mm/vmpressure.c were somehow getting slab.h indirectly through cgroup.h which in turn was getting it indirectly through xattr.h. A scheduled cgroup change drops xattr.h inclusion from cgroup.h and breaks compilation of these three files. Add explicit slab.h includes to the three files. A pending cgroup patch depends on this change and it'd be great if this can be routed through cgroup/for-3.14-fixes branch. Signed-off-by: Tejun Heo Acked-by: Stephen Warren Cc: Thierry Reding Cc: linux-tegra@vger.kernel.org Cc: "Rafael J. Wysocki" Cc: linux-pm@vger.kernel.org Cc: Johannes Weiner Cc: Michal Hocko Cc: Balbir Singh Cc: KAMEZAWA Hiroyuki Cc: cgroups@vger.kernel.org diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 4ae0286..f55b05a 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/kernel/power/console.c b/kernel/power/console.c index eacb8bd..aba9c54 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "power.h" #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) diff --git a/mm/vmpressure.c b/mm/vmpressure.c index 196970a..d4042e7 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From 230579d7e0c46fa078ba11899d9b091df689362f Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 28 Jan 2014 11:29:09 +0800 Subject: cpuset: update MAINTAINERS entry Add mailing list and tree tag to the entry. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo diff --git a/MAINTAINERS b/MAINTAINERS index b2cf5cf..41e52c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2408,8 +2408,10 @@ F: tools/power/cpupower/ CPUSETS M: Li Zefan +L: cgroups@vger.kernel.org W: http://www.bullopensource.org/cpuset/ W: http://oss.sgi.com/projects/cpusets/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git S: Maintained F: Documentation/cgroups/cpusets.txt F: include/linux/cpuset.h -- cgit v0.10.2 From a7e46bd9a19c1e0058c7c8c0b4cc3e6cf101e12a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 3 Feb 2014 14:51:50 +0200 Subject: ASoC: davinci-mcasp: Code cleanup in davinci_mcasp_hw_params() Rearrange the code in the function for readability. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 0518ff2..63b1ecc 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -611,10 +611,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, u8 fifo_level; u8 slots = mcasp->tdm_slots; u8 active_serializers; - int channels; + int channels = params_channels(params); int ret; - struct snd_interval *pcm_channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); /* If mcasp is BCLK master we need to set BCLK divider */ if (mcasp->bclk_master) { @@ -627,19 +625,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); } - channels = pcm_channels->min; - - active_serializers = (channels + slots - 1) / slots; - ret = mcasp_common_hw_param(mcasp, substream->stream, channels); if (ret) return ret; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_level = mcasp->txnumevt * active_serializers; - else - fifo_level = mcasp->rxnumevt * active_serializers; - if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) ret = mcasp_dit_hw_param(mcasp); else @@ -680,6 +669,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + /* Calculate FIFO level */ + active_serializers = (channels + slots - 1) / slots; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + fifo_level = mcasp->txnumevt * active_serializers; + else + fifo_level = mcasp->rxnumevt * active_serializers; + if (mcasp->version == MCASP_VERSION_2 && !fifo_level) dma_params->acnt = 4; else -- cgit v0.10.2 From d1debafc381cb1fa340b5d0dc79637ad1d523770 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 3 Feb 2014 14:51:51 +0200 Subject: ASoC: davinci-mcasp: Rename platform data struct Rename the struct for the platform data: snd_platform_data -> davinci_mcasp_pdata Since we have users under arch/arm/mach-davinci/ for this struct add temporary define to avoid breakage. The arch code can be updated later to use the new struct name. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 5245992..85ad68f 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -18,7 +18,7 @@ #include -struct snd_platform_data { +struct davinci_mcasp_pdata { u32 tx_dma_offset; u32 rx_dma_offset; int asp_chan_q; /* event queue number for ASP channel */ @@ -87,6 +87,8 @@ struct snd_platform_data { int tx_dma_channel; int rx_dma_channel; }; +/* TODO: Fix arch/arm/mach-davinci/ users and remove this define */ +#define snd_platform_data davinci_mcasp_pdata enum { MCASP_VERSION_1 = 0, /* DM646x */ diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 63b1ecc..e5fce2e 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -823,28 +823,28 @@ static const struct snd_soc_component_driver davinci_mcasp_component = { }; /* Some HW specific values and defaults. The rest is filled in from DT. */ -static struct snd_platform_data dm646x_mcasp_pdata = { +static struct davinci_mcasp_pdata dm646x_mcasp_pdata = { .tx_dma_offset = 0x400, .rx_dma_offset = 0x400, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_1, }; -static struct snd_platform_data da830_mcasp_pdata = { +static struct davinci_mcasp_pdata da830_mcasp_pdata = { .tx_dma_offset = 0x2000, .rx_dma_offset = 0x2000, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_2, }; -static struct snd_platform_data am33xx_mcasp_pdata = { +static struct davinci_mcasp_pdata am33xx_mcasp_pdata = { .tx_dma_offset = 0, .rx_dma_offset = 0, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_3, }; -static struct snd_platform_data dra7_mcasp_pdata = { +static struct davinci_mcasp_pdata dra7_mcasp_pdata = { .tx_dma_offset = 0x200, .rx_dma_offset = 0x284, .asp_chan_q = EVENTQ_0, @@ -912,11 +912,11 @@ err1: return ret; } -static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( +static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct snd_platform_data *pdata = NULL; + struct davinci_mcasp_pdata *pdata = NULL; const struct of_device_id *match = of_match_device(mcasp_dt_ids, &pdev->dev); struct of_phandle_args dma_spec; @@ -929,7 +929,7 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( pdata = pdev->dev.platform_data; return pdata; } else if (match) { - pdata = (struct snd_platform_data *) match->data; + pdata = (struct davinci_mcasp_pdata*) match->data; } else { /* control shouldn't reach here. something is wrong */ ret = -EINVAL; @@ -1023,7 +1023,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) { struct davinci_pcm_dma_params *dma_data; struct resource *mem, *ioarea, *res, *dat; - struct snd_platform_data *pdata; + struct davinci_mcasp_pdata *pdata; struct davinci_mcasp *mcasp; int ret; -- cgit v0.10.2 From 790bb94b56249b2f40907a0cbf959ca50b4430d2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 3 Feb 2014 14:51:52 +0200 Subject: ASoC: davinci-mcasp: Remove long lines from suspend/resume callbacks Move the context register storage behind of a struct and use a pointer to it in the suspend/resume callbacks to remove the long lines. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index e5fce2e..35b9b55 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -37,6 +37,16 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" +struct davinci_mcasp_context { + u32 txfmtctl; + u32 rxfmtctl; + u32 txfmt; + u32 rxfmt; + u32 aclkxctl; + u32 aclkrctl; + u32 pdir; +}; + struct davinci_mcasp { struct davinci_pcm_dma_params dma_params[2]; struct snd_dmaengine_dai_dma_data dma_data[2]; @@ -63,15 +73,7 @@ struct davinci_mcasp { bool dat_port; #ifdef CONFIG_PM_SLEEP - struct { - u32 txfmtctl; - u32 rxfmtctl; - u32 txfmt; - u32 rxfmt; - u32 aclkxctl; - u32 aclkrctl; - u32 pdir; - } context; + struct davinci_mcasp_context context; #endif }; @@ -741,14 +743,15 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { static int davinci_mcasp_suspend(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + struct davinci_mcasp_context *context = &mcasp->context; - mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); - mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); - mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); - mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); - mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); - mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); - mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); + context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); + context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); + context->rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); + context->aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); + context->aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); + context->pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); return 0; } @@ -756,14 +759,15 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai) static int davinci_mcasp_resume(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); + struct davinci_mcasp_context *context = &mcasp->context; + + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, context->rxfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, context->aclkxctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, context->aclkrctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, context->pdir); return 0; } -- cgit v0.10.2 From 1659b84312617fe846def362f6ccdc73ec452d44 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Feb 2014 17:24:21 +0100 Subject: ASoC: h1940_uda1380: Don't modify runtime->hw Individual components are not supposed to modify the runtime->hw struct itself as it is manged by the ASoC core. If a component wants to limit the list of supported rates it should set a rate constraint. The h1940_uda1380 already does this, so it is safe to just remove the code that modifies runtime->hw. Signed-off-by: Lars-Peter Clausen Acked-by: Vasily Khoruzhick Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 0003b66..88b09e0 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -66,10 +66,6 @@ static int h1940_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.rate_min = hw_rates.list[0]; - runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); -- cgit v0.10.2 From 4f6136fa0d6200f1c6eebfb1f12572ca6b770927 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Feb 2014 17:24:22 +0100 Subject: ASoC: rx1950_uda1380: Don't modify runtime->hw Individual components are not supposed to modify the runtime->hw struct itself as it is manged by the ASoC core. If a component wants to limit the list of supported rates it should set a rate constraint. The rx1950_uda1380 already does this, so it is safe to just remove the code that modifies runtime->hw. Signed-off-by: Lars-Peter Clausen Acked-by: Vasily Khoruzhick Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index afbfe4a..2982d9e 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -131,10 +131,6 @@ static int rx1950_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.rate_min = hw_rates.list[0]; - runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); -- cgit v0.10.2 From 0a6be6555302eebb14510fd6b35bb17e8dfa1386 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Feb 2014 14:31:07 -0500 Subject: nfs: include xattr.h from fs/nfs/nfs3proc.c fs/nfs/nfs3proc.c is making use of xattr but was getting linux/xattr.h indirectly through linux/cgroup.h, which will soon drop the inclusion of xattr.h. Explicitly include linux/xattr.h from nfs3proc.c so that compilation doesn't fail when linux/cgroup.h drops linux/xattr.h. As the following cgroup changes will depend on these changes, it probably would be easier to route this through cgroup branch. Would that be okay? Signed-off-by: Tejun Heo Acked-by: Trond Myklebust Cc: linux-nfs@vger.kernel.org diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index aa9bc97..a462ef0 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "iostat.h" #include "internal.h" -- cgit v0.10.2 From 5547fec74a566e1f5e00a937b9a367f7c6a94a8b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 29 Jan 2014 16:17:57 +0300 Subject: UBI: fix some use after free bugs Move the kmem_cache_free() calls down a couple lines. Signed-off-by: Dan Carpenter Signed-off-by: Artem Bityutskiy diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index ead8613..c5dad65 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -463,8 +463,8 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, } } if (found_orphan) { - kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); list_del(&tmp_aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); } new_aeb = kmem_cache_alloc(ai->aeb_slab_cache, @@ -846,16 +846,16 @@ fail_bad: ret = UBI_BAD_FASTMAP; fail: list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) { - kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); list_del(&tmp_aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); } list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) { - kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); list_del(&tmp_aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); } list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) { - kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); list_del(&tmp_aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); } return ret; -- cgit v0.10.2 From 1291e14175e6b83efe1464f32189acb21bc4be09 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Jan 2014 12:58:16 +0000 Subject: ASoC: codecs: Make OF supported CODECs visible in Kconfig Now that we have a generic card driver we can't rely on the card driver selecting the CODECs for us so make the CODECs that can be enabled with OF directly selectable in Kconfig. For the platforms not using OF it's not clear that we don't still want to have some board specific selection since the kernel needs to contain code to register the devices; ACPI could provide this from firmware does not yet support any kind of generic card. It may also be desirable to hide these if OF is not enabled to reduce noise. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 034130b..f0bdcc5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -190,8 +190,9 @@ config SND_SOC_AD73311 tristate config SND_SOC_ADAU1701 + tristate "Analog Devices ADAU1701 CODEC" + depends on I2C select SND_SOC_SIGMADSP - tristate config SND_SOC_ADAU1373 tristate @@ -203,28 +204,31 @@ config SND_SOC_ADS117X tristate config SND_SOC_AK4104 - tristate + tristate "AKM AK4104 CODEC" + depends on SPI_MASTER config SND_SOC_AK4535 tristate config SND_SOC_AK4554 - tristate + tristate "AKM AK4554 CODEC" config SND_SOC_AK4641 tristate config SND_SOC_AK4642 - tristate + tristate "AKM AK4642 CODEC" + depends on I2C config SND_SOC_AK4671 tristate config SND_SOC_AK5386 - tristate + tristate "AKM AK5638 CODEC" config SND_SOC_ALC5623 tristate + config SND_SOC_ALC5632 tristate @@ -235,14 +239,17 @@ config SND_SOC_CS42L51 tristate config SND_SOC_CS42L52 - tristate + tristate "Cirrus Logic CS42L52 CODEC" + depends on I2C config SND_SOC_CS42L73 - tristate + tristate "Cirrus Logic CS42L73 CODEC" + depends on I2C # Cirrus Logic CS4270 Codec config SND_SOC_CS4270 - tristate + tristate "Cirrus Logic CS4270 CODEC" + depends on I2C # Cirrus Logic CS4270 Codec VD = 3.3V Errata # Select if you are affected by the errata where the part will not function @@ -253,7 +260,8 @@ config SND_SOC_CS4270_VD33_ERRATA depends on SND_SOC_CS4270 config SND_SOC_CS4271 - tristate + tristate "Cirrus Logic CS4271 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_CX20442 tristate @@ -284,6 +292,9 @@ config SND_SOC_BT_SCO config SND_SOC_DMIC tristate +config SND_SOC_HDMI_CODEC + tristate "HDMI stub CODEC" + config SND_SOC_ISABELLE tristate @@ -302,14 +313,13 @@ config SND_SOC_MAX98095 config SND_SOC_MAX9850 tristate -config SND_SOC_HDMI_CODEC - tristate - config SND_SOC_PCM1681 - tristate + tristate "Texas Instruments PCM1681 CODEC" + depends on I2C config SND_SOC_PCM1792A - tristate + tristate "Texas Instruments PCM1792A CODEC" + depends on SPI_MASTER config SND_SOC_PCM3008 tristate @@ -322,7 +332,8 @@ config SND_SOC_RT5640 #Freescale sgtl5000 codec config SND_SOC_SGTL5000 - tristate + tristate "Freescale SGTL5000 CODEC" + depends on I2C config SND_SOC_SI476X tristate @@ -335,7 +346,7 @@ config SND_SOC_SN95031 tristate config SND_SOC_SPDIF - tristate + tristate "S/PDIF CODEC" config SND_SOC_SSM2518 tristate @@ -353,7 +364,8 @@ config SND_SOC_STAC9766 tristate config SND_SOC_TAS5086 - tristate + tristate "Texas Instruments TAS5086 speaker amplifier" + depends on I2C config SND_SOC_TLV320AIC23 tristate @@ -366,7 +378,8 @@ config SND_SOC_TLV320AIC32X4 tristate config SND_SOC_TLV320AIC3X - tristate + tristate "Texas Instruments TLV320AIC3x CODECs" + depends on I2C config SND_SOC_TLV320DAC33 tristate @@ -415,55 +428,69 @@ config SND_SOC_WM8400 tristate config SND_SOC_WM8510 - tristate + tristate "Wolfson Microelectronics WM8510 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8523 - tristate + tristate "Wolfson Microelectronics WM8523 DAC" + depends on I2C config SND_SOC_WM8580 - tristate + tristate "Wolfson Microelectronics WM8523 CODEC" + depends on I2C config SND_SOC_WM8711 - tristate + tristate "Wolfson Microelectronics WM8711 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8727 tristate config SND_SOC_WM8728 - tristate + tristate "Wolfson Microelectronics WM8728 DAC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8731 - tristate + tristate "Wolfson Microelectronics WM8731 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8737 - tristate + tristate "Wolfson Microelectronics WM8737 ADC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8741 - tristate + tristate "Wolfson Microelectronics WM8737 DAC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8750 - tristate + tristate "Wolfson Microelectronics WM8750 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8753 - tristate + tristate "Wolfson Microelectronics WM8753 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8770 - tristate + tristate "Wolfson Microelectronics WM8770 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8776 - tristate + tristate "Wolfson Microelectronics WM8776 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8782 tristate config SND_SOC_WM8804 - tristate + tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8900 tristate config SND_SOC_WM8903 - tristate + tristate "Wolfson Microelectronics WM8903 CODEC" + depends on I2C config SND_SOC_WM8904 tristate @@ -481,7 +508,8 @@ config SND_SOC_WM8961 tristate config SND_SOC_WM8962 - tristate + tristate "Wolfson Microelectronics WM8962 CODEC" + depends on I2C config SND_SOC_WM8971 tristate @@ -554,4 +582,5 @@ config SND_SOC_ML26124 tristate config SND_SOC_TPA6130A2 - tristate + tristate "Texas Instruments TPA6130A2 headphone amplifier" + depends on I2C -- cgit v0.10.2 From 14cfa4bd74be31e5502dcb5c98de86db63fddb65 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 12 Jan 2014 13:09:24 +0100 Subject: ARM: mvebu: dt: add missing alias 'eth3' on Armada XP mv78260 It was correctly set on mv78460 but not on mv78260, resulting in my OpenBlocks AX3-4 retrieving only 3 of its 4 MAC addresses from the boot loader. Cc: Thomas Petazzoni Cc: Gregory CLEMENT Signed-off-by: Willy Tarreau Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index 6660968..9480cf8 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi @@ -23,6 +23,7 @@ gpio0 = &gpio0; gpio1 = &gpio1; gpio2 = &gpio2; + eth3 = ð3; }; cpus { @@ -291,7 +292,7 @@ interrupts = <91>; }; - ethernet@34000 { + eth3: ethernet@34000 { compatible = "marvell,armada-370-neta"; reg = <0x34000 0x4000>; interrupts = <14>; -- cgit v0.10.2 From b224e9b857438afbd802f47008ab36863f71d8d1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Feb 2014 14:48:22 +0100 Subject: ASoC: cs4271: Remove outdated comment Commit 1b1861ead ("ASoC: cs4271: convert to direct regmap API usage") removed the bus_type field from the cs4271_private struct, but left the comment that described the field in there. This patch removes the comment. Signed-off-by: Lars-Peter Clausen Acked-by: Daniel Mack Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index ce05fd9..f7bbe6f 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -159,7 +159,6 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg) } struct cs4271_private { - /* SND_SOC_I2C or SND_SOC_SPI */ unsigned int mclk; bool master; bool deemph; -- cgit v0.10.2 From 6e84b9768dfb299a9881895b331e3e532041fae4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Feb 2014 20:55:31 +0100 Subject: ASoC: cs42l73: Don't mix SNDRV_PCM_RATE_KNOT with specific rates SNDRV_PCM_RATE_KNOT means that the device can support rates that can not be expressed using the rate bits. The driver will provide a list of those rates specified through constraints. Any rate bits that are set in the rates mask will be ignored. So setting other rate bits besides SNDRV_PCM_RATE_KNOT wont have any effect, but might be confusing to the casual reader, so remove them. Signed-off-by: Lars-Peter Clausen Acked-by: Brian Austin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 549d5d6..7cae046 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1255,9 +1255,6 @@ static int cs42l73_pcm_startup(struct snd_pcm_substream *substream, return 0; } -/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ -#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) - #define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) @@ -1278,14 +1275,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "XSP Playback", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "XSP Capture", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, @@ -1298,14 +1295,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "ASP Playback", .channels_min = 2, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "ASP Capture", .channels_min = 2, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, @@ -1318,14 +1315,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "VSP Playback", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "VSP Capture", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, -- cgit v0.10.2 From 5a3af1293194d07610fd7fdf680b3e7f916dca84 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Feb 2014 12:03:27 +0000 Subject: ASoC: pcm512x: Add PCM512x driver The PCM512x devices are a family of monolithic CMOS integrated circuits that include a stereo digital-to-analog converter and additional support circuitry. This is an initial driver which supports some core functionality for the device which covers common use cases but does not cover all features. Currently only slave clocking modes with automatic clock configuration are supported and most of the DSP configuration for the device is not enabled. Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt new file mode 100644 index 0000000..faff75e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/pcm512x.txt @@ -0,0 +1,30 @@ +PCM512x audio CODECs + +These devices support both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : One of "ti,pcm5121" or "ti,pcm5122" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + + - AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the + device, as covered in bindings/regulator/regulator.txt + +Optional properties: + + - clocks : A clock specifier for the clock connected as SCLK. If this + is absent the device will be configured to clock from BCLK. + +Example: + + pcm5122: pcm5122@4c { + compatible = "ti,pcm5122"; + reg = <0x4c>; + + AVDD-supply = <®_3v3_analog>; + DVDD-supply = <®_1v8>; + CPVDD-supply = <®_3v3>; + }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087a..56d0c28 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -59,6 +59,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM1792A if SPI_MASTER select SND_SOC_PCM3008 + select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C @@ -313,6 +314,9 @@ config SND_SOC_PCM1792A config SND_SOC_PCM3008 tristate +config SND_SOC_PCM512x + tristate "Texas Instruments PCM512x CODECs" + config SND_SOC_RT5631 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc12676..d3b536f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -46,6 +46,7 @@ snd-soc-hdmi-codec-objs := hdmi.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm1792a-codec-objs := pcm1792a.o snd-soc-pcm3008-objs := pcm3008.o +snd-soc-pcm512x-objs := pcm512x.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o snd-soc-sgtl5000-objs := sgtl5000.o @@ -179,6 +180,7 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o +obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c new file mode 100644 index 0000000..5ad3e9a --- /dev/null +++ b/sound/soc/codecs/pcm512x.c @@ -0,0 +1,672 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcm512x.h" + +#define PCM512x_NUM_SUPPLIES 3 +static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { + "AVDD", + "DVDD", + "CPVDD", +}; + +struct pcm512x_priv { + struct regmap *regmap; + struct clk *sclk; + struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; + struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; +}; + +/* + * We can't use the same notifier block for more than one supply and + * there's no way I can see to get from a callback to the caller + * except container_of(). + */ +#define PCM512x_REGULATOR_EVENT(n) \ +static int pcm512x_regulator_event_##n(struct notifier_block *nb, \ + unsigned long event, void *data) \ +{ \ + struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \ + supply_nb[n]); \ + if (event & REGULATOR_EVENT_DISABLE) { \ + regcache_mark_dirty(pcm512x->regmap); \ + regcache_cache_only(pcm512x->regmap, true); \ + } \ + return 0; \ +} + +PCM512x_REGULATOR_EVENT(0) +PCM512x_REGULATOR_EVENT(1) +PCM512x_REGULATOR_EVENT(2) + +static const struct reg_default pcm512x_reg_defaults[] = { + { PCM512x_RESET, 0x00 }, + { PCM512x_POWER, 0x00 }, + { PCM512x_MUTE, 0x00 }, + { PCM512x_DSP, 0x00 }, + { PCM512x_PLL_REF, 0x00 }, + { PCM512x_DAC_ROUTING, 0x11 }, + { PCM512x_DSP_PROGRAM, 0x01 }, + { PCM512x_CLKDET, 0x00 }, + { PCM512x_AUTO_MUTE, 0x00 }, + { PCM512x_ERROR_DETECT, 0x00 }, + { PCM512x_DIGITAL_VOLUME_1, 0x00 }, + { PCM512x_DIGITAL_VOLUME_2, 0x30 }, + { PCM512x_DIGITAL_VOLUME_3, 0x30 }, + { PCM512x_DIGITAL_MUTE_1, 0x22 }, + { PCM512x_DIGITAL_MUTE_2, 0x00 }, + { PCM512x_DIGITAL_MUTE_3, 0x07 }, +}; + +static bool pcm512x_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PCM512x_RESET: + case PCM512x_POWER: + case PCM512x_MUTE: + case PCM512x_PLL_EN: + case PCM512x_SPI_MISO_FUNCTION: + case PCM512x_DSP: + case PCM512x_GPIO_EN: + case PCM512x_BCLK_LRCLK_CFG: + case PCM512x_DSP_GPIO_INPUT: + case PCM512x_MASTER_MODE: + case PCM512x_PLL_REF: + case PCM512x_PLL_COEFF_0: + case PCM512x_PLL_COEFF_1: + case PCM512x_PLL_COEFF_2: + case PCM512x_PLL_COEFF_3: + case PCM512x_PLL_COEFF_4: + case PCM512x_DSP_CLKDIV: + case PCM512x_DAC_CLKDIV: + case PCM512x_NCP_CLKDIV: + case PCM512x_OSR_CLKDIV: + case PCM512x_MASTER_CLKDIV_1: + case PCM512x_MASTER_CLKDIV_2: + case PCM512x_FS_SPEED_MODE: + case PCM512x_IDAC_1: + case PCM512x_IDAC_2: + case PCM512x_ERROR_DETECT: + case PCM512x_I2S_1: + case PCM512x_I2S_2: + case PCM512x_DAC_ROUTING: + case PCM512x_DSP_PROGRAM: + case PCM512x_CLKDET: + case PCM512x_AUTO_MUTE: + case PCM512x_DIGITAL_VOLUME_1: + case PCM512x_DIGITAL_VOLUME_2: + case PCM512x_DIGITAL_VOLUME_3: + case PCM512x_DIGITAL_MUTE_1: + case PCM512x_DIGITAL_MUTE_2: + case PCM512x_DIGITAL_MUTE_3: + case PCM512x_GPIO_OUTPUT_1: + case PCM512x_GPIO_OUTPUT_2: + case PCM512x_GPIO_OUTPUT_3: + case PCM512x_GPIO_OUTPUT_4: + case PCM512x_GPIO_OUTPUT_5: + case PCM512x_GPIO_OUTPUT_6: + case PCM512x_GPIO_CONTROL_1: + case PCM512x_GPIO_CONTROL_2: + case PCM512x_OVERFLOW: + case PCM512x_RATE_DET_1: + case PCM512x_RATE_DET_2: + case PCM512x_RATE_DET_3: + case PCM512x_RATE_DET_4: + case PCM512x_ANALOG_MUTE_DET: + case PCM512x_GPIN: + case PCM512x_DIGITAL_MUTE_DET: + return true; + default: + return false; + } +} + +static bool pcm512x_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PCM512x_PLL_EN: + case PCM512x_OVERFLOW: + case PCM512x_RATE_DET_1: + case PCM512x_RATE_DET_2: + case PCM512x_RATE_DET_3: + case PCM512x_RATE_DET_4: + case PCM512x_ANALOG_MUTE_DET: + case PCM512x_GPIN: + case PCM512x_DIGITAL_MUTE_DET: + return true; + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); + +static const char *pcm512x_dsp_program_texts[] = { + "FIR interpolation with de-emphasis", + "Low latency IIR with de-emphasis", + "Fixed process flow", + "High attenuation with de-emphasis", + "Ringing-less low latency FIR", +}; + +static const unsigned int pcm512x_dsp_program_values[] = { + 1, + 2, + 3, + 5, + 7, +}; + +static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, + PCM512x_DSP_PROGRAM, 0, 0x1f, + pcm512x_dsp_program_texts, + pcm512x_dsp_program_values); + +static const char *pcm512x_clk_missing_text[] = { + "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" +}; + +static const struct soc_enum pcm512x_clk_missing = + SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text); + +static const char *pcm512x_autom_text[] = { + "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" +}; + +static const struct soc_enum pcm512x_autom_l = + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8, + pcm512x_autom_text); + +static const struct soc_enum pcm512x_autom_r = + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8, + pcm512x_autom_text); + +static const char *pcm512x_ramp_rate_text[] = { + "1 sample/update", "2 samples/update", "4 samples/update", + "Immediate" +}; + +static const struct soc_enum pcm512x_vndf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const struct soc_enum pcm512x_vnuf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const struct soc_enum pcm512x_vedf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const char *pcm512x_ramp_step_text[] = { + "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" +}; + +static const struct soc_enum pcm512x_vnds = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct soc_enum pcm512x_vnus = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct soc_enum pcm512x_veds = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct snd_kcontrol_new pcm512x_controls[] = { +SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), +SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, + PCM512x_RQMR_SHIFT, 1, 1), + +SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), +SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program), + +SOC_ENUM("Clock Missing Period", pcm512x_clk_missing), +SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l), +SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r), +SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, + PCM512x_ACTL_SHIFT, 1, 0), +SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, + PCM512x_AMLR_SHIFT, 1, 0), + +SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), +SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), +SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf), +SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus), +SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf), +SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds), +}; + +static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = { +SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), + +SND_SOC_DAPM_OUTPUT("OUTL"), +SND_SOC_DAPM_OUTPUT("OUTR"), +}; + +static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { + { "DACL", NULL, "Playback" }, + { "DACR", NULL, "Playback" }, + + { "OUTL", NULL, "DACL" }, + { "OUTR", NULL, "DACR" }, +}; + +static int pcm512x_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev); + int ret; + + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, 0); + if (ret != 0) { + dev_err(codec->dev, "Failed to remove standby: %d\n", + ret); + return ret; + } + break; + + case SND_SOC_BIAS_OFF: + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, PCM512x_RQST); + if (ret != 0) { + dev_err(codec->dev, "Failed to request standby: %d\n", + ret); + return ret; + } + break; + } + + codec->dapm.bias_level = level; + + return 0; +} + +static struct snd_soc_dai_driver pcm512x_dai = { + .name = "pcm512x-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE + }, +}; + +static struct snd_soc_codec_driver pcm512x_codec_driver = { + .set_bias_level = pcm512x_set_bias_level, + .idle_bias_off = true, + + .controls = pcm512x_controls, + .num_controls = ARRAY_SIZE(pcm512x_controls), + .dapm_widgets = pcm512x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), + .dapm_routes = pcm512x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), +}; + +static const struct regmap_config pcm512x_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .readable_reg = pcm512x_readable, + .volatile_reg = pcm512x_volatile, + + .max_register = PCM512x_MAX_REGISTER, + .reg_defaults = pcm512x_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static int pcm512x_probe(struct device *dev, struct regmap *regmap) +{ + struct pcm512x_priv *pcm512x; + int i, ret; + + pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL); + if (!pcm512x) + return -ENOMEM; + + dev_set_drvdata(dev, pcm512x); + pcm512x->regmap = regmap; + + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) + pcm512x->supplies[i].supply = pcm512x_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to get supplies: %d\n", ret); + return ret; + } + + pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0; + pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1; + pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2; + + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) { + ret = regulator_register_notifier(pcm512x->supplies[i].consumer, + &pcm512x->supply_nb[i]); + if (ret != 0) { + dev_err(dev, + "Failed to register regulator notifier: %d\n", + ret); + } + } + + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + /* Reset the device, verifying I/O in the process for I2C */ + ret = regmap_write(regmap, PCM512x_RESET, + PCM512x_RSTM | PCM512x_RSTR); + if (ret != 0) { + dev_err(dev, "Failed to reset device: %d\n", ret); + goto err; + } + + ret = regmap_write(regmap, PCM512x_RESET, 0); + if (ret != 0) { + dev_err(dev, "Failed to reset device: %d\n", ret); + goto err; + } + + pcm512x->sclk = devm_clk_get(dev, NULL); + if (IS_ERR(pcm512x->sclk)) { + if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_info(dev, "No SCLK, using BCLK: %ld\n", + PTR_ERR(pcm512x->sclk)); + + /* Disable reporting of missing SCLK as an error */ + regmap_update_bits(regmap, PCM512x_ERROR_DETECT, + PCM512x_IDCH, PCM512x_IDCH); + + /* Switch PLL input to BCLK */ + regmap_update_bits(regmap, PCM512x_PLL_REF, + PCM512x_SREF, PCM512x_SREF); + } else { + ret = clk_prepare_enable(pcm512x->sclk); + if (ret != 0) { + dev_err(dev, "Failed to enable SCLK: %d\n", ret); + return ret; + } + } + + /* Default to standby mode */ + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, PCM512x_RQST); + if (ret != 0) { + dev_err(dev, "Failed to request standby: %d\n", + ret); + goto err_clk; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, + &pcm512x_dai, 1); + if (ret != 0) { + dev_err(dev, "Failed to register CODEC: %d\n", ret); + goto err_pm; + } + + return 0; + +err_pm: + pm_runtime_disable(dev); +err_clk: + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); +err: + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + return ret; +} + +static void pcm512x_remove(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + + snd_soc_unregister_codec(dev); + pm_runtime_disable(dev); + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); +} + +static int pcm512x_suspend(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + int ret; + + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQPD, PCM512x_RQPD); + if (ret != 0) { + dev_err(dev, "Failed to request power down: %d\n", ret); + return ret; + } + + ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to disable supplies: %d\n", ret); + return ret; + } + + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); + + return 0; +} + +static int pcm512x_resume(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + int ret; + + if (!IS_ERR(pcm512x->sclk)) { + ret = clk_prepare_enable(pcm512x->sclk); + if (ret != 0) { + dev_err(dev, "Failed to enable SCLK: %d\n", ret); + return ret; + } + } + + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + regcache_cache_only(pcm512x->regmap, false); + ret = regcache_sync(pcm512x->regmap); + if (ret != 0) { + dev_err(dev, "Failed to sync cache: %d\n", ret); + return ret; + } + + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQPD, 0); + if (ret != 0) { + dev_err(dev, "Failed to remove power down: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct dev_pm_ops pcm512x_pm_ops = { + SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) +}; + +#if IS_ENABLED(CONFIG_I2C) +static int pcm512x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return pcm512x_probe(&i2c->dev, regmap); +} + +static int pcm512x_i2c_remove(struct i2c_client *i2c) +{ + pcm512x_remove(&i2c->dev); + return 0; +} + +static const struct i2c_device_id pcm512x_i2c_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); + +static struct i2c_driver pcm512x_i2c_driver = { + .probe = pcm512x_i2c_probe, + .remove = pcm512x_i2c_remove, + .id_table = pcm512x_i2c_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; +#endif + +#if defined(CONFIG_SPI_MASTER) +static int pcm512x_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + return ret; + } + + return pcm512x_probe(&spi->dev, regmap); +} + +static int pcm512x_spi_remove(struct spi_device *spi) +{ + pcm512x_remove(&spi->dev); + return 0; +} + +static const struct spi_device_id pcm512x_spi_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { }, +}; +MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); + +static struct spi_driver pcm512x_spi_driver = { + .probe = pcm512x_spi_probe, + .remove = pcm512x_spi_remove, + .id_table = pcm512x_spi_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; +#endif + +static int __init pcm512x_modinit(void) +{ + int ret = 0; + +#if IS_ENABLED(CONFIG_I2C) + ret = i2c_add_driver(&pcm512x_i2c_driver); + if (ret) { + printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n", + ret); + } +#endif +#if defined(CONFIG_SPI_MASTER) + ret = spi_register_driver(&pcm512x_spi_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n", + ret); + } +#endif + return ret; +} +module_init(pcm512x_modinit); + +static void __exit pcm512x_exit(void) +{ +#if IS_ENABLED(CONFIG_I2C) + i2c_del_driver(&pcm512x_i2c_driver); +#endif +#if defined(CONFIG_SPI_MASTER) + spi_unregister_driver(&pcm512x_spi_driver); +#endif +} +module_exit(pcm512x_exit); + +MODULE_DESCRIPTION("ASoC PCM512x codec driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h new file mode 100644 index 0000000..b2f518e --- /dev/null +++ b/sound/soc/codecs/pcm512x.h @@ -0,0 +1,142 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef _SND_SOC_PCM512X +#define _SND_SOC_PCM512X + +#define PCM512x_PAGE_0_BASE 0 + +#define PCM512x_PAGE 0 + +#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1) +#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2) +#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3) +#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4) +#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6) +#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7) +#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8) +#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9) +#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10) +#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12) +#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13) +#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20) +#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21) +#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22) +#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23) +#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24) +#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27) +#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28) +#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29) +#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30) +#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32) +#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33) +#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34) +#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35) +#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36) +#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37) +#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40) +#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41) +#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42) +#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43) +#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44) +#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59) +#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60) +#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61) +#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62) +#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63) +#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64) +#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65) +#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80) +#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81) +#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82) +#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83) +#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84) +#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85) +#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86) +#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87) +#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90) +#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91) +#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92) +#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93) +#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94) +#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108) +#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119) +#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120) + +#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120) + +/* Page 0, Register 1 - reset */ +#define PCM512x_RSTR (1 << 0) +#define PCM512x_RSTM (1 << 4) + +/* Page 0, Register 2 - power */ +#define PCM512x_RQPD (1 << 0) +#define PCM512x_RQPD_SHIFT 0 +#define PCM512x_RQST (1 << 4) +#define PCM512x_RQST_SHIFT 4 + +/* Page 0, Register 3 - mute */ +#define PCM512x_RQMR_SHIFT 0 +#define PCM512x_RQML_SHIFT 4 + +/* Page 0, Register 4 - PLL */ +#define PCM512x_PLCE (1 << 0) +#define PCM512x_RLCE_SHIFT 0 +#define PCM512x_PLCK (1 << 4) +#define PCM512x_PLCK_SHIFT 4 + +/* Page 0, Register 7 - DSP */ +#define PCM512x_SDSL (1 << 0) +#define PCM512x_SDSL_SHIFT 0 +#define PCM512x_DEMP (1 << 4) +#define PCM512x_DEMP_SHIFT 4 + +/* Page 0, Register 13 - PLL reference */ +#define PCM512x_SREF (1 << 4) + +/* Page 0, Register 37 - Error detection */ +#define PCM512x_IPLK (1 << 0) +#define PCM512x_DCAS (1 << 1) +#define PCM512x_IDCM (1 << 2) +#define PCM512x_IDCH (1 << 3) +#define PCM512x_IDSK (1 << 4) +#define PCM512x_IDBK (1 << 5) +#define PCM512x_IDFS (1 << 6) + +/* Page 0, Register 42 - DAC routing */ +#define PCM512x_AUPR_SHIFT 0 +#define PCM512x_AUPL_SHIFT 4 + +/* Page 0, Register 59 - auto mute */ +#define PCM512x_ATMR_SHIFT 0 +#define PCM512x_ATML_SHIFT 4 + +/* Page 0, Register 63 - ramp rates */ +#define PCM512x_VNDF_SHIFT 6 +#define PCM512x_VNDS_SHIFT 4 +#define PCM512x_VNUF_SHIFT 2 +#define PCM512x_VNUS_SHIFT 0 + +/* Page 0, Register 64 - emergency ramp rates */ +#define PCM512x_VEDF_SHIFT 6 +#define PCM512x_VEDS_SHIFT 4 + +/* Page 0, Register 65 - Digital mute enables */ +#define PCM512x_ACTL_SHIFT 2 +#define PCM512x_AMLE_SHIFT 1 +#define PCM512x_AMLR_SHIFT 0 + +#endif -- cgit v0.10.2 From bd4a7ce1da061d97c45673e1ca1a6a474bfb4cff Mon Sep 17 00:00:00 2001 From: Huei-Horng Yo Date: Thu, 6 Feb 2014 17:40:34 +0800 Subject: HID: apple: add Apple wireless keyboard 2011 JIS model support Add Apple wireless keyboard 2011 JIS model (05ac:0257). Signed-off-by: Huei-Horng Yo Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 4975581..f822fd2 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -469,6 +469,9 @@ static const struct hid_device_id apple_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 6ed8f5f..f36b352 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1679,6 +1679,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2f10e6e..3628168 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -135,6 +135,7 @@ #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS 0x0257 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 -- cgit v0.10.2 From 06d0ffcc5c12ad49786141fa9768da38485a8a61 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Feb 2014 14:33:52 +0000 Subject: ASoC: pcm512x: More constification Since the core now takes const strings for enums we should be constifying them (and the regulator supplies while we're at it). Reported-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 5ad3e9a..1150381 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -30,7 +30,7 @@ #include "pcm512x.h" #define PCM512x_NUM_SUPPLIES 3 -static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { +static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { "AVDD", "DVDD", "CPVDD", @@ -167,7 +167,7 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); -static const char *pcm512x_dsp_program_texts[] = { +static const char * const pcm512x_dsp_program_texts[] = { "FIR interpolation with de-emphasis", "Low latency IIR with de-emphasis", "Fixed process flow", @@ -188,14 +188,14 @@ static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, pcm512x_dsp_program_texts, pcm512x_dsp_program_values); -static const char *pcm512x_clk_missing_text[] = { +static const char * const pcm512x_clk_missing_text[] = { "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" }; static const struct soc_enum pcm512x_clk_missing = SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text); -static const char *pcm512x_autom_text[] = { +static const char * const pcm512x_autom_text[] = { "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" }; @@ -207,7 +207,7 @@ static const struct soc_enum pcm512x_autom_r = SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8, pcm512x_autom_text); -static const char *pcm512x_ramp_rate_text[] = { +static const char * const pcm512x_ramp_rate_text[] = { "1 sample/update", "2 samples/update", "4 samples/update", "Immediate" }; @@ -224,7 +224,7 @@ static const struct soc_enum pcm512x_vedf = SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, pcm512x_ramp_rate_text); -static const char *pcm512x_ramp_step_text[] = { +static const char * const pcm512x_ramp_step_text[] = { "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" }; -- cgit v0.10.2 From 7b119fd1bdc59a8060df5b659b9f7a70e0169fd6 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 23 Jan 2014 23:38:04 +0100 Subject: irqchip: orion: clear bridge cause register on init It is good practice to mask and clear pending irqs on init. We already mask all irqs, so also clear the bridge irq cause register. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: # v3.10+ Signed-off-by: Jason Cooper diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index e51d400..4137c3d 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -180,8 +180,9 @@ static int __init orion_bridge_irq_init(struct device_node *np, gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; - /* mask all interrupts */ + /* mask and clear all interrupts */ writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK); + writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE); irq_set_handler_data(irq, domain); irq_set_chained_handler(irq, orion_bridge_irq_handler); -- cgit v0.10.2 From 5f40067fc86f0e49329ad4a852c278998ff4394e Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 23 Jan 2014 23:38:05 +0100 Subject: irqchip: orion: use handle_edge_irq on bridge irqs Bridge irqs are edge-triggered, i.e. they get asserted on low-to-high transitions and not on the level of the downstream interrupt line. This replaces handle_level_irq by the more appropriate handle_edge_irq. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: : f56c0738b5c2: "irqchip: orion: clear bridge cause register on init" Cc: # v3.10+ Signed-off-by: Jason Cooper diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 4137c3d..1f636f7 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -143,7 +143,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, } ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name, - handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); + handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); if (ret) { pr_err("%s: unable to alloc irq domain gc\n", np->name); return ret; -- cgit v0.10.2 From e0318ec3bf3f1502cd11b21b1eb00aa355b40b67 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Fri, 24 Jan 2014 00:10:32 +0100 Subject: irqchip: orion: clear stale interrupts in irq_startup Bridge IRQ_CAUSE bits are asserted regardless of the corresponding bit in IRQ_MASK register. To avoid interrupt events on stale irqs, we have to clear them before unmask. This installs an .irq_startup callback to ensure stale irqs are cleared before initial unmask. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: : f56c0738b5c2: "irqchip: orion: clear bridge cause register on init" Cc: : 38bd80b84fca: "irqchip: orion: use handle_edge_irq on bridge irqs" Cc: # v3.10+ Signed-off-by: Jason Cooper diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 1f636f7..0dfdc5c 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -123,6 +123,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) } } +/* + * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register. + * To avoid interrupt events on stale irqs, we clear them before unmask. + */ +static unsigned int orion_bridge_irq_startup(struct irq_data *d) +{ + struct irq_chip_type *ct = irq_data_get_chip_type(d); + + ct->chip.irq_ack(d); + ct->chip.irq_unmask(d); + return 0; +} + static int __init orion_bridge_irq_init(struct device_node *np, struct device_node *parent) { @@ -176,6 +189,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE; gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK; + gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup; gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit; gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; -- cgit v0.10.2 From 07ad6836fa21b8ae1715d5f82a0d28c4140e1e73 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Sat, 25 Jan 2014 19:19:07 +0100 Subject: clk: mvebu: armada-370: maintain clock init order Init order of CLK_OF_DECLARE'd drivers depends on compile order. Unfortunately, clk_of_init does not allow drivers to return errors, e.g. -EPROBE_DEFER if parent clocks have not been registered, yet. To avoid init order woes for MVEBU clock drivers, we take care of proper init order ourselves. This patch joins core-clk and gating-clk init to maintain proper init order. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Signed-off-by: Jason Cooper diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c index 81a202d..bef198a 100644 --- a/drivers/clk/mvebu/armada-370.c +++ b/drivers/clk/mvebu/armada-370.c @@ -141,13 +141,6 @@ static const struct coreclk_soc_desc a370_coreclks = { .num_ratios = ARRAY_SIZE(a370_coreclk_ratios), }; -static void __init a370_coreclk_init(struct device_node *np) -{ - mvebu_coreclk_setup(np, &a370_coreclks); -} -CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock", - a370_coreclk_init); - /* * Clock Gating Control */ @@ -168,9 +161,15 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = { { } }; -static void __init a370_clk_gating_init(struct device_node *np) +static void __init a370_clk_init(struct device_node *np) { - mvebu_clk_gating_setup(np, a370_gating_desc); + struct device_node *cgnp = + of_find_compatible_node(NULL, NULL, "marvell,armada-370-gating-clock"); + + mvebu_coreclk_setup(np, &a370_coreclks); + + if (cgnp) + mvebu_clk_gating_setup(cgnp, a370_gating_desc); } -CLK_OF_DECLARE(a370_clk_gating, "marvell,armada-370-gating-clock", - a370_clk_gating_init); +CLK_OF_DECLARE(a370_clk, "marvell,armada-370-core-clock", a370_clk_init); + -- cgit v0.10.2 From 0a11a6ae94373f37e738f7dc8f51d60a78d78a58 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Sat, 25 Jan 2014 19:19:08 +0100 Subject: clk: mvebu: armada-xp: maintain clock init order Init order of CLK_OF_DECLARE'd drivers depends on compile order. Unfortunately, clk_of_init does not allow drivers to return errors, e.g. -EPROBE_DEFER if parent clocks have not been registered, yet. To avoid init order woes for MVEBU clock drivers, we take care of proper init order ourselves. This patch joins core-clk and gating-clk init to maintain proper init order. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Jason Cooper diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c index 9922c44..b309431 100644 --- a/drivers/clk/mvebu/armada-xp.c +++ b/drivers/clk/mvebu/armada-xp.c @@ -158,13 +158,6 @@ static const struct coreclk_soc_desc axp_coreclks = { .num_ratios = ARRAY_SIZE(axp_coreclk_ratios), }; -static void __init axp_coreclk_init(struct device_node *np) -{ - mvebu_coreclk_setup(np, &axp_coreclks); -} -CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock", - axp_coreclk_init); - /* * Clock Gating Control */ @@ -202,9 +195,14 @@ static const struct clk_gating_soc_desc axp_gating_desc[] __initconst = { { } }; -static void __init axp_clk_gating_init(struct device_node *np) +static void __init axp_clk_init(struct device_node *np) { - mvebu_clk_gating_setup(np, axp_gating_desc); + struct device_node *cgnp = + of_find_compatible_node(NULL, NULL, "marvell,armada-xp-gating-clock"); + + mvebu_coreclk_setup(np, &axp_coreclks); + + if (cgnp) + mvebu_clk_gating_setup(cgnp, axp_gating_desc); } -CLK_OF_DECLARE(axp_clk_gating, "marvell,armada-xp-gating-clock", - axp_clk_gating_init); +CLK_OF_DECLARE(axp_clk, "marvell,armada-xp-core-clock", axp_clk_init); -- cgit v0.10.2 From 8f7fc5450b64210b08cb3daabb3473dbad197e54 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Sat, 25 Jan 2014 19:19:09 +0100 Subject: clk: mvebu: dove: maintain clock init order Init order of CLK_OF_DECLARE'd drivers depends on compile order. Unfortunately, clk_of_init does not allow drivers to return errors, e.g. -EPROBE_DEFER if parent clocks have not been registered, yet. To avoid init order woes for MVEBU clock drivers, we take care of proper init order ourselves. This patch joins core-clk and gating-clk init to maintain proper init order. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Signed-off-by: Jason Cooper diff --git a/drivers/clk/mvebu/dove.c b/drivers/clk/mvebu/dove.c index 38aee1e..b8c2424 100644 --- a/drivers/clk/mvebu/dove.c +++ b/drivers/clk/mvebu/dove.c @@ -154,12 +154,6 @@ static const struct coreclk_soc_desc dove_coreclks = { .num_ratios = ARRAY_SIZE(dove_coreclk_ratios), }; -static void __init dove_coreclk_init(struct device_node *np) -{ - mvebu_coreclk_setup(np, &dove_coreclks); -} -CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init); - /* * Clock Gating Control */ @@ -186,9 +180,14 @@ static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = { { } }; -static void __init dove_clk_gating_init(struct device_node *np) +static void __init dove_clk_init(struct device_node *np) { - mvebu_clk_gating_setup(np, dove_gating_desc); + struct device_node *cgnp = + of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock"); + + mvebu_coreclk_setup(np, &dove_coreclks); + + if (cgnp) + mvebu_clk_gating_setup(cgnp, dove_gating_desc); } -CLK_OF_DECLARE(dove_clk_gating, "marvell,dove-gating-clock", - dove_clk_gating_init); +CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init); -- cgit v0.10.2 From 58d516ae95cbf7eed44f85a01cdfad41f17b4197 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Sat, 25 Jan 2014 19:19:10 +0100 Subject: clk: mvebu: kirkwood: maintain clock init order Init order of CLK_OF_DECLARE'd drivers depends on compile order. Unfortunately, clk_of_init does not allow drivers to return errors, e.g. -EPROBE_DEFER if parent clocks have not been registered, yet. To avoid init order woes for MVEBU clock drivers, we take care of proper init order ourselves. This patch joins core-clk and gating-clk init to maintain proper init order. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Signed-off-by: Jason Cooper diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c index 2636a55..ddb666a 100644 --- a/drivers/clk/mvebu/kirkwood.c +++ b/drivers/clk/mvebu/kirkwood.c @@ -193,13 +193,6 @@ static const struct coreclk_soc_desc kirkwood_coreclks = { .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios), }; -static void __init kirkwood_coreclk_init(struct device_node *np) -{ - mvebu_coreclk_setup(np, &kirkwood_coreclks); -} -CLK_OF_DECLARE(kirkwood_core_clk, "marvell,kirkwood-core-clock", - kirkwood_coreclk_init); - static const struct coreclk_soc_desc mv88f6180_coreclks = { .get_tclk_freq = kirkwood_get_tclk_freq, .get_cpu_freq = mv88f6180_get_cpu_freq, @@ -208,13 +201,6 @@ static const struct coreclk_soc_desc mv88f6180_coreclks = { .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios), }; -static void __init mv88f6180_coreclk_init(struct device_node *np) -{ - mvebu_coreclk_setup(np, &mv88f6180_coreclks); -} -CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock", - mv88f6180_coreclk_init); - /* * Clock Gating Control */ @@ -239,9 +225,21 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = { { } }; -static void __init kirkwood_clk_gating_init(struct device_node *np) +static void __init kirkwood_clk_init(struct device_node *np) { - mvebu_clk_gating_setup(np, kirkwood_gating_desc); + struct device_node *cgnp = + of_find_compatible_node(NULL, NULL, "marvell,kirkwood-gating-clock"); + + + if (of_device_is_compatible(np, "marvell,mv88f6180-core-clock")) + mvebu_coreclk_setup(np, &mv88f6180_coreclks); + else + mvebu_coreclk_setup(np, &kirkwood_coreclks); + + if (cgnp) + mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc); } -CLK_OF_DECLARE(kirkwood_clk_gating, "marvell,kirkwood-gating-clock", - kirkwood_clk_gating_init); +CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock", + kirkwood_clk_init); +CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock", + kirkwood_clk_init); -- cgit v0.10.2 From 096ae5444b8600bbee0501b01987094657a1458e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:32 +0100 Subject: ASoC: cs42l73: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. While we are at it also change the type for the rates array from u32 to unsigned int. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 7cae046..69c8e2d 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1108,7 +1108,7 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static u32 cs42l73_asrc_rates[] = { +static const unsigned int cs42l73_asrc_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }; @@ -1241,7 +1241,7 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate) 0x7F, tristate << 7); } -static struct snd_pcm_hw_constraint_list constraints_12_24 = { +static const struct snd_pcm_hw_constraint_list constraints_12_24 = { .count = ARRAY_SIZE(cs42l73_asrc_rates), .list = cs42l73_asrc_rates, }; -- cgit v0.10.2 From f75ac2d9bd8211c1890ad591046aef0783ad6416 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:33 +0100 Subject: ASoC: ssm2602: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index af76bbd..f444d58 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -52,7 +52,7 @@ enum ssm2602_type { /* codec private data */ struct ssm2602_priv { unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; struct regmap *regmap; @@ -197,7 +197,7 @@ static const unsigned int ssm2602_rates_12288000[] = { 8000, 16000, 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { +static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { .list = ssm2602_rates_12288000, .count = ARRAY_SIZE(ssm2602_rates_12288000), }; @@ -206,7 +206,7 @@ static const unsigned int ssm2602_rates_11289600[] = { 8000, 44100, 88200, }; -static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { +static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { .list = ssm2602_rates_11289600, .count = ARRAY_SIZE(ssm2602_rates_11289600), }; -- cgit v0.10.2 From 0d76fc6a47b183d519c47e40971e74cfd96cca85 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:34 +0100 Subject: ASoC: twl6040: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 0afe8be..cb642c9 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -81,7 +81,7 @@ struct twl6040_data { }; /* set of rates for each pll: low-power and high-performance */ -static unsigned int lp_rates[] = { +static const unsigned int lp_rates[] = { 8000, 11250, 16000, @@ -93,7 +93,7 @@ static unsigned int lp_rates[] = { 96000, }; -static unsigned int hp_rates[] = { +static const unsigned int hp_rates[] = { 8000, 16000, 32000, @@ -101,7 +101,7 @@ static unsigned int hp_rates[] = { 96000, }; -static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { +static const struct snd_pcm_hw_constraint_list sysclk_constraints[] = { { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, }; -- cgit v0.10.2 From 70bad2c780abc6744ab2ab5832b0c9f3de608dad Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:35 +0100 Subject: ASoC: wm8741: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 2895c8d..dd02ebf 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -44,7 +44,7 @@ struct wm8741_priv { struct regmap *regmap; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; }; static const struct reg_default wm8741_reg_defaults[] = { @@ -122,74 +122,74 @@ static struct { { 6, 768 }, }; -static unsigned int rates_11289[] = { +static const unsigned int rates_11289[] = { 44100, 88235, }; -static struct snd_pcm_hw_constraint_list constraints_11289 = { +static const struct snd_pcm_hw_constraint_list constraints_11289 = { .count = ARRAY_SIZE(rates_11289), .list = rates_11289, }; -static unsigned int rates_12288[] = { +static const unsigned int rates_12288[] = { 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12288 = { +static const struct snd_pcm_hw_constraint_list constraints_12288 = { .count = ARRAY_SIZE(rates_12288), .list = rates_12288, }; -static unsigned int rates_16384[] = { +static const unsigned int rates_16384[] = { 32000, }; -static struct snd_pcm_hw_constraint_list constraints_16384 = { +static const struct snd_pcm_hw_constraint_list constraints_16384 = { .count = ARRAY_SIZE(rates_16384), .list = rates_16384, }; -static unsigned int rates_16934[] = { +static const unsigned int rates_16934[] = { 44100, 88235, }; -static struct snd_pcm_hw_constraint_list constraints_16934 = { +static const struct snd_pcm_hw_constraint_list constraints_16934 = { .count = ARRAY_SIZE(rates_16934), .list = rates_16934, }; -static unsigned int rates_18432[] = { +static const unsigned int rates_18432[] = { 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_18432 = { +static const struct snd_pcm_hw_constraint_list constraints_18432 = { .count = ARRAY_SIZE(rates_18432), .list = rates_18432, }; -static unsigned int rates_22579[] = { +static const unsigned int rates_22579[] = { 44100, 88235, 1764000 }; -static struct snd_pcm_hw_constraint_list constraints_22579 = { +static const struct snd_pcm_hw_constraint_list constraints_22579 = { .count = ARRAY_SIZE(rates_22579), .list = rates_22579, }; -static unsigned int rates_24576[] = { +static const unsigned int rates_24576[] = { 32000, 48000, 96000, 192000 }; -static struct snd_pcm_hw_constraint_list constraints_24576 = { +static const struct snd_pcm_hw_constraint_list constraints_24576 = { .count = ARRAY_SIZE(rates_24576), .list = rates_24576, }; -static unsigned int rates_36864[] = { +static const unsigned int rates_36864[] = { 48000, 96000, 19200 }; -static struct snd_pcm_hw_constraint_list constraints_36864 = { +static const struct snd_pcm_hw_constraint_list constraints_36864 = { .count = ARRAY_SIZE(rates_36864), .list = rates_36864, }; -- cgit v0.10.2 From b57efda1f0372d6107ced5a255384be9fd449260 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:36 +0100 Subject: ASoC: wm8988: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index a55e1c2..c6e4aba 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -116,7 +116,7 @@ static bool wm8988_writeable(struct device *dev, unsigned int reg) struct wm8988_priv { struct regmap *regmap; unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; }; #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) @@ -521,30 +521,30 @@ static inline int get_coeff(int mclk, int rate) /* The set of rates we can generate from the above for each SYSCLK */ -static unsigned int rates_12288[] = { +static const unsigned int rates_12288[] = { 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12288 = { +static const struct snd_pcm_hw_constraint_list constraints_12288 = { .count = ARRAY_SIZE(rates_12288), .list = rates_12288, }; -static unsigned int rates_112896[] = { +static const unsigned int rates_112896[] = { 8000, 11025, 22050, 44100, }; -static struct snd_pcm_hw_constraint_list constraints_112896 = { +static const struct snd_pcm_hw_constraint_list constraints_112896 = { .count = ARRAY_SIZE(rates_112896), .list = rates_112896, }; -static unsigned int rates_12[] = { +static const unsigned int rates_12[] = { 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, 48000, 88235, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12 = { +static const struct snd_pcm_hw_constraint_list constraints_12 = { .count = ARRAY_SIZE(rates_12), .list = rates_12, }; -- cgit v0.10.2 From ab3f5faa6255a0eb4f832675507d9e295ca7e9ba Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 6 Feb 2014 15:56:01 -0800 Subject: cgroup: use an ordered workqueue for cgroup destruction Sometimes the cleanup after memcg hierarchy testing gets stuck in mem_cgroup_reparent_charges(), unable to bring non-kmem usage down to 0. There may turn out to be several causes, but a major cause is this: the workitem to offline parent can get run before workitem to offline child; parent's mem_cgroup_reparent_charges() circles around waiting for the child's pages to be reparented to its lrus, but it's holding cgroup_mutex which prevents the child from reaching its mem_cgroup_reparent_charges(). Just use an ordered workqueue for cgroup_destroy_wq. tj: Committing as the temporary fix until the reverse dependency can be removed from memcg. Comment updated accordingly. Fixes: e5fca243abae ("cgroup: use a dedicated workqueue for cgroup destruction") Suggested-by: Filipe Brandenburger Signed-off-by: Hugh Dickins Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Tejun Heo diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e2f46ba..aa95591 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4845,12 +4845,16 @@ static int __init cgroup_wq_init(void) /* * There isn't much point in executing destruction path in * parallel. Good chunk is serialized with cgroup_mutex anyway. - * Use 1 for @max_active. + * + * XXX: Must be ordered to make sure parent is offlined after + * children. The ordering requirement is for memcg where a + * parent's offline may wait for a child's leading to deadlock. In + * the long term, this should be fixed from memcg side. * * We would prefer to do this in cgroup_init() above, but that * is called before init_workqueues(): so leave this until after. */ - cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1); + cgroup_destroy_wq = alloc_ordered_workqueue("cgroup_destroy", 0); BUG_ON(!cgroup_destroy_wq); /* -- cgit v0.10.2 From 4d1a77224bac47c994ecdc776f0c09c9a0ed9d49 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 15:40:35 +0000 Subject: ASoC: codecs: Put the CODEC drivers in a menu Now they're visible they get a bit noisy. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f0bdcc5..7da528a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -8,6 +8,8 @@ config SND_SOC_I2C_AND_SPI default y if I2C=y default y if SPI_MASTER=y +menu "CODEC drivers" + config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" depends on COMPILE_TEST @@ -584,3 +586,5 @@ config SND_SOC_ML26124 config SND_SOC_TPA6130A2 tristate "Texas Instruments TPA6130A2 headphone amplifier" depends on I2C + +endmenu -- cgit v0.10.2 From e479d85ced01ea7f85c7dd21dc858af25f1493b4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 15:57:50 +0000 Subject: ASoC: wm8770: Depend on SPI only The device has no I2C support so it shouldn't be buildable if only I2C is enabled. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 7da528a..a6afdf5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -474,7 +474,7 @@ config SND_SOC_WM8753 config SND_SOC_WM8770 tristate "Wolfson Microelectronics WM8770 CODEC" - depends on SND_SOC_I2C_AND_SPI + depends on SPI_MASTER config SND_SOC_WM8776 tristate "Wolfson Microelectronics WM8776 CODEC" -- cgit v0.10.2 From 8691d0748e566f8708f7a9139e760134f5dc3130 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 7 Feb 2014 00:53:06 -0800 Subject: ASoC: rsnd: use device dependency clock Current R-Car sound driver is using device independent audio clock, but it is not good design for DT support. This patch adds device dependent clock support. But, there are some platform which is using independent audio clock. It is still supported at this point, but it will be removed soon. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 821791e..8d3a82e 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -385,8 +385,9 @@ int rsnd_adg_probe(struct platform_device *pdev, { struct rsnd_adg *adg; struct device *dev = rsnd_priv_to_dev(priv); - struct clk *clk; + struct clk *clk, *clk_orig; int i; + bool use_old_style = false; adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); if (!adg) { @@ -394,10 +395,39 @@ int rsnd_adg_probe(struct platform_device *pdev, return -ENOMEM; } - adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); - adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); - adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); - adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + clk_orig = clk_get(dev, NULL); + adg->clk[CLKA] = clk_get(dev, "clk_a"); + adg->clk[CLKB] = clk_get(dev, "clk_b"); + adg->clk[CLKC] = clk_get(dev, "clk_c"); + adg->clk[CLKI] = clk_get(dev, "clk_i"); + + /* + * It request device dependent audio clock. + * But above all clks will indicate rsnd module clock + * if platform doesn't it + */ + for_each_rsnd_clk(clk, adg, i) { + if (clk_orig == clk) { + dev_warn(dev, + "doesn't have device dependent clock, use independent clock\n"); + use_old_style = true; + break; + } + } + + /* + * note: + * these exist in order to keep compatible with + * platform which has device independent audio clock, + * but will be removed soon + */ + if (use_old_style) { + adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); + adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); + adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); + adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + } + for_each_rsnd_clk(clk, adg, i) { if (IS_ERR(clk)) { dev_err(dev, "Audio clock failed\n"); -- cgit v0.10.2 From 806d6466076a0aebbe0a9c17294d1a13e93fabcf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 19:08:11 +0000 Subject: ASoC: pcm512x: Implement paging support The PCM512x devices use a paged register map covering the entire register range. Implement support for this, mapping pages in at addresses starting at 0x100 for ease of use (though since the pages are numbered from 0 there is going to be an off by one when looking at the first byte as a page number). Also mark the new registers as accessible with the exception of the coefficient RAM which is a bit fiddly and may benefit from some extra handling to linearise the blocks. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 1150381..cdcb51e 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -66,22 +66,29 @@ PCM512x_REGULATOR_EVENT(1) PCM512x_REGULATOR_EVENT(2) static const struct reg_default pcm512x_reg_defaults[] = { - { PCM512x_RESET, 0x00 }, - { PCM512x_POWER, 0x00 }, - { PCM512x_MUTE, 0x00 }, - { PCM512x_DSP, 0x00 }, - { PCM512x_PLL_REF, 0x00 }, - { PCM512x_DAC_ROUTING, 0x11 }, - { PCM512x_DSP_PROGRAM, 0x01 }, - { PCM512x_CLKDET, 0x00 }, - { PCM512x_AUTO_MUTE, 0x00 }, - { PCM512x_ERROR_DETECT, 0x00 }, - { PCM512x_DIGITAL_VOLUME_1, 0x00 }, - { PCM512x_DIGITAL_VOLUME_2, 0x30 }, - { PCM512x_DIGITAL_VOLUME_3, 0x30 }, - { PCM512x_DIGITAL_MUTE_1, 0x22 }, - { PCM512x_DIGITAL_MUTE_2, 0x00 }, - { PCM512x_DIGITAL_MUTE_3, 0x07 }, + { PCM512x_RESET, 0x00 }, + { PCM512x_POWER, 0x00 }, + { PCM512x_MUTE, 0x00 }, + { PCM512x_DSP, 0x00 }, + { PCM512x_PLL_REF, 0x00 }, + { PCM512x_DAC_ROUTING, 0x11 }, + { PCM512x_DSP_PROGRAM, 0x01 }, + { PCM512x_CLKDET, 0x00 }, + { PCM512x_AUTO_MUTE, 0x00 }, + { PCM512x_ERROR_DETECT, 0x00 }, + { PCM512x_DIGITAL_VOLUME_1, 0x00 }, + { PCM512x_DIGITAL_VOLUME_2, 0x30 }, + { PCM512x_DIGITAL_VOLUME_3, 0x30 }, + { PCM512x_DIGITAL_MUTE_1, 0x22 }, + { PCM512x_DIGITAL_MUTE_2, 0x00 }, + { PCM512x_DIGITAL_MUTE_3, 0x07 }, + { PCM512x_OUTPUT_AMPLITUDE, 0x00 }, + { PCM512x_ANALOG_GAIN_CTRL, 0x00 }, + { PCM512x_UNDERVOLTAGE_PROT, 0x00 }, + { PCM512x_ANALOG_MUTE_CTRL, 0x00 }, + { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, + { PCM512x_VCOM_CTRL_1, 0x00 }, + { PCM512x_VCOM_CTRL_2, 0x01 }, }; static bool pcm512x_readable(struct device *dev, unsigned int reg) @@ -141,9 +148,18 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg) case PCM512x_ANALOG_MUTE_DET: case PCM512x_GPIN: case PCM512x_DIGITAL_MUTE_DET: + case PCM512x_OUTPUT_AMPLITUDE: + case PCM512x_ANALOG_GAIN_CTRL: + case PCM512x_UNDERVOLTAGE_PROT: + case PCM512x_ANALOG_MUTE_CTRL: + case PCM512x_ANALOG_GAIN_BOOST: + case PCM512x_VCOM_CTRL_1: + case PCM512x_VCOM_CTRL_2: + case PCM512x_CRAM_CTRL: return true; default: - return false; + /* There are 256 raw register addresses */ + return reg < 0xff; } } @@ -159,9 +175,11 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) case PCM512x_ANALOG_MUTE_DET: case PCM512x_GPIN: case PCM512x_DIGITAL_MUTE_DET: + case PCM512x_CRAM_CTRL: return true; default: - return false; + /* There are 256 raw register addresses */ + return reg < 0xff; } } @@ -343,6 +361,14 @@ static struct snd_soc_codec_driver pcm512x_codec_driver = { .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), }; +static const struct regmap_range_cfg pcm512x_range = { + .name = "Pages", .range_min = PCM512x_VIRT_BASE, + .range_max = PCM512x_MAX_REGISTER, + .selector_reg = PCM512x_PAGE, + .selector_mask = 0xff, + .window_start = 0, .window_len = 0x100, +}; + static const struct regmap_config pcm512x_regmap = { .reg_bits = 8, .val_bits = 8, @@ -350,6 +376,9 @@ static const struct regmap_config pcm512x_regmap = { .readable_reg = pcm512x_readable, .volatile_reg = pcm512x_volatile, + .ranges = &pcm512x_range, + .num_ranges = 1, + .max_register = PCM512x_MAX_REGISTER, .reg_defaults = pcm512x_reg_defaults, .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index b2f518e..e58743c 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h @@ -17,66 +17,78 @@ #ifndef _SND_SOC_PCM512X #define _SND_SOC_PCM512X -#define PCM512x_PAGE_0_BASE 0 +#define PCM512x_VIRT_BASE 0x100 +#define PCM512x_PAGE_LEN 0x100 +#define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n)) #define PCM512x_PAGE 0 -#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1) -#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2) -#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3) -#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4) -#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6) -#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7) -#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8) -#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9) -#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10) -#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12) -#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13) -#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20) -#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21) -#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22) -#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23) -#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24) -#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27) -#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28) -#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29) -#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30) -#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32) -#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33) -#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34) -#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35) -#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36) -#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37) -#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40) -#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41) -#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42) -#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43) -#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44) -#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59) -#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60) -#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61) -#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62) -#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63) -#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64) -#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65) -#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80) -#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81) -#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82) -#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83) -#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84) -#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85) -#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86) -#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87) -#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90) -#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91) -#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92) -#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93) -#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94) -#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108) -#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119) -#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120) - -#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120) +#define PCM512x_RESET (PCM512x_PAGE_BASE(0) + 1) +#define PCM512x_POWER (PCM512x_PAGE_BASE(0) + 2) +#define PCM512x_MUTE (PCM512x_PAGE_BASE(0) + 3) +#define PCM512x_PLL_EN (PCM512x_PAGE_BASE(0) + 4) +#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_BASE(0) + 6) +#define PCM512x_DSP (PCM512x_PAGE_BASE(0) + 7) +#define PCM512x_GPIO_EN (PCM512x_PAGE_BASE(0) + 8) +#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_BASE(0) + 9) +#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) +#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) +#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) +#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) +#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) +#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) +#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_BASE(0) + 23) +#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_BASE(0) + 24) +#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_BASE(0) + 27) +#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_BASE(0) + 28) +#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_BASE(0) + 29) +#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_BASE(0) + 30) +#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_BASE(0) + 32) +#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_BASE(0) + 33) +#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_BASE(0) + 34) +#define PCM512x_IDAC_1 (PCM512x_PAGE_BASE(0) + 35) +#define PCM512x_IDAC_2 (PCM512x_PAGE_BASE(0) + 36) +#define PCM512x_ERROR_DETECT (PCM512x_PAGE_BASE(0) + 37) +#define PCM512x_I2S_1 (PCM512x_PAGE_BASE(0) + 40) +#define PCM512x_I2S_2 (PCM512x_PAGE_BASE(0) + 41) +#define PCM512x_DAC_ROUTING (PCM512x_PAGE_BASE(0) + 42) +#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_BASE(0) + 43) +#define PCM512x_CLKDET (PCM512x_PAGE_BASE(0) + 44) +#define PCM512x_AUTO_MUTE (PCM512x_PAGE_BASE(0) + 59) +#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_BASE(0) + 60) +#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_BASE(0) + 61) +#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_BASE(0) + 62) +#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_BASE(0) + 63) +#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_BASE(0) + 64) +#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_BASE(0) + 65) +#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_BASE(0) + 80) +#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_BASE(0) + 81) +#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_BASE(0) + 82) +#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_BASE(0) + 83) +#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_BASE(0) + 84) +#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_BASE(0) + 85) +#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_BASE(0) + 86) +#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_BASE(0) + 87) +#define PCM512x_OVERFLOW (PCM512x_PAGE_BASE(0) + 90) +#define PCM512x_RATE_DET_1 (PCM512x_PAGE_BASE(0) + 91) +#define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92) +#define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93) +#define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94) +#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108) +#define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119) +#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120) + +#define PCM512x_OUTPUT_AMPLITUDE (PCM512x_PAGE_BASE(1) + 1) +#define PCM512x_ANALOG_GAIN_CTRL (PCM512x_PAGE_BASE(1) + 2) +#define PCM512x_UNDERVOLTAGE_PROT (PCM512x_PAGE_BASE(1) + 5) +#define PCM512x_ANALOG_MUTE_CTRL (PCM512x_PAGE_BASE(1) + 6) +#define PCM512x_ANALOG_GAIN_BOOST (PCM512x_PAGE_BASE(1) + 7) +#define PCM512x_VCOM_CTRL_1 (PCM512x_PAGE_BASE(1) + 8) +#define PCM512x_VCOM_CTRL_2 (PCM512x_PAGE_BASE(1) + 9) + +#define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1) + +#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1) /* Page 0, Register 1 - reset */ #define PCM512x_RSTR (1 << 0) -- cgit v0.10.2 From 5be2fc20b101b5138c4f54a584dc11790ef16598 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 19:16:56 +0000 Subject: ASoC: pcm512x: Implement analogue volume control There are some analogue volume controls in page 1 of the register map so implement support for them now that we can access the registers. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index cdcb51e..3a0bbb6 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -184,6 +184,8 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); +static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0); +static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0); static const char * const pcm512x_dsp_program_texts[] = { "FIR interpolation with de-emphasis", @@ -261,6 +263,10 @@ static const struct soc_enum pcm512x_veds = static const struct snd_kcontrol_new pcm512x_controls[] = { SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), +SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL, + PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv), +SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST, + PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv), SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, PCM512x_RQMR_SHIFT, 1, 1), diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index e58743c..ac4a52c 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h @@ -151,4 +151,12 @@ #define PCM512x_AMLE_SHIFT 1 #define PCM512x_AMLR_SHIFT 0 +/* Page 1, Register 2 - analog volume control */ +#define PCM512x_RAGN_SHIFT 0 +#define PCM512x_LAGN_SHIFT 4 + +/* Page 1, Register 7 - analog boost control */ +#define PCM512x_AGBR_SHIFT 0 +#define PCM512x_AGBL_SHIFT 4 + #endif -- cgit v0.10.2 From e156291c7bab1771df34acd583c3c1b1ad71231c Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Fri, 7 Feb 2014 19:43:19 +0100 Subject: ASoC: wm8991: Remove unused pointer in wm8991_probe() Remove unused pointer 'wm8991' in function wm8991_probe(). The last user vanished with a86652e5 (ASoC: wm8991: Convert to direct regmap API usage) Detected by Coverity: CID 1162831 Signed-off-by: Christian Engelmayer Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index dba0306..244eb09 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1251,11 +1251,8 @@ static int wm8991_remove(struct snd_soc_codec *codec) static int wm8991_probe(struct snd_soc_codec *codec) { - struct wm8991_priv *wm8991; int ret; - wm8991 = snd_soc_codec_get_drvdata(codec); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); -- cgit v0.10.2 From 2f41898704d3cff796ea0adaea272808707d758e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 1 Feb 2014 16:46:16 +0100 Subject: ARM: sun7i: dt: Fix interrupt trigger types The Allwinner A20 uses the ARM GIC as its internal interrupts controller. The GIC can work on several interrupt triggers, and the A20 was actually setting it up to use a rising edge as a trigger, while it was actually a level high trigger, leading to some interrupts that would be completely ignored if the edge was missed. Fix this for the remaining DT nodes that slipped through. Signed-off-by: Maxime Ripard Cc: stable@vger.kernel.org diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 119f066..2374f5a 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -454,7 +454,7 @@ rtc: rtc@01c20d00 { compatible = "allwinner,sun7i-a20-rtc"; reg = <0x01c20d00 0x20>; - interrupts = <0 24 1>; + interrupts = <0 24 4>; }; sid: eeprom@01c23800 { @@ -596,10 +596,10 @@ hstimer@01c60000 { compatible = "allwinner,sun7i-a20-hstimer"; reg = <0x01c60000 0x1000>; - interrupts = <0 81 1>, - <0 82 1>, - <0 83 1>, - <0 84 1>; + interrupts = <0 81 4>, + <0 82 4>, + <0 83 4>, + <0 84 4>; clocks = <&ahb_gates 28>; }; -- cgit v0.10.2 From 40dd8f3b900cac1d925605a9d3199368c4af0a40 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 2 Feb 2014 14:52:40 +0100 Subject: ARM: sunxi: dt: Change the touchscreen compatibles Switch the device tree touchscreen compatibles to have a common pattern accross all Allwinner SoCs. Since the touchscreen driver has not been merged yet, it has no side effect. Signed-off-by: Maxime Ripard diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 040bb0e..e3ff64c 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -426,7 +426,7 @@ }; rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-ts"; + compatible = "allwinner,sun4i-a10-ts"; reg = <0x01c25000 0x100>; interrupts = <29>; }; diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index ea16054..8e57a28 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -383,7 +383,7 @@ }; rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-ts"; + compatible = "allwinner,sun4i-a10-ts"; reg = <0x01c25000 0x100>; interrupts = <29>; }; diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index 320335a..c463fd7 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -346,7 +346,7 @@ }; rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-ts"; + compatible = "allwinner,sun4i-a10-ts"; reg = <0x01c25000 0x100>; interrupts = <29>; }; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 2374f5a..b79a626 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -463,7 +463,7 @@ }; rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-ts"; + compatible = "allwinner,sun4i-a10-ts"; reg = <0x01c25000 0x100>; interrupts = <0 29 4>; }; -- cgit v0.10.2 From eb46bf89696972b856a9adb6aebd5c7b65c266e4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 8 Feb 2014 10:26:33 -0500 Subject: cgroup: fix error return value in cgroup_mount() When cgroup_mount() fails to allocate an id for the root, it didn't set ret before jumping to unlock_drop ending up returning 0 after a failure. Fix it. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org diff --git a/kernel/cgroup.c b/kernel/cgroup.c index aa95591..793f371 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1566,10 +1566,10 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_root_mutex); - root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp, - 0, 1, GFP_KERNEL); - if (root_cgrp->id < 0) + ret = idr_alloc(&root->cgroup_idr, root_cgrp, 0, 1, GFP_KERNEL); + if (ret < 0) goto unlock_drop; + root_cgrp->id = ret; /* Check for name clashes with existing mounts */ ret = -EBUSY; -- cgit v0.10.2 From b58c89986a77a23658682a100eb15d8edb571ebb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 8 Feb 2014 10:26:33 -0500 Subject: cgroup: fix error return from cgroup_create() cgroup_create() was returning 0 after allocation failures. Fix it. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 793f371..0eb7b86 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4158,7 +4158,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, struct cgroup *cgrp; struct cgroup_name *name; struct cgroupfs_root *root = parent->root; - int ssid, err = 0; + int ssid, err; struct cgroup_subsys *ss; struct super_block *sb = root->sb; @@ -4168,8 +4168,10 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, return -ENOMEM; name = cgroup_alloc_name(dentry); - if (!name) + if (!name) { + err = -ENOMEM; goto err_free_cgrp; + } rcu_assign_pointer(cgrp->name, name); /* @@ -4177,8 +4179,10 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, * a half-baked cgroup. */ cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); - if (cgrp->id < 0) + if (cgrp->id < 0) { + err = -ENOMEM; goto err_free_name; + } /* * Only live parents can have children. Note that the liveliness -- cgit v0.10.2 From 48573a893303986e3b0b2974d6fb11f3d1bb7064 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 8 Feb 2014 10:26:34 -0500 Subject: cgroup: fix locking in cgroup_cfts_commit() cgroup_cfts_commit() walks the cgroup hierarchy that the target subsystem is attached to and tries to apply the file changes. Due to the convolution with inode locking, it can't keep cgroup_mutex locked while iterating. It currently holds only RCU read lock around the actual iteration and then pins the found cgroup using dget(). Unfortunately, this is incorrect. Although the iteration does check cgroup_is_dead() before invoking dget(), there's nothing which prevents the dentry from going away inbetween. Note that this is different from the usual css iterations where css_tryget() is used to pin the css - css_tryget() tests whether the css can be pinned and fails if not. The problem can be solved by simply holding cgroup_mutex instead of RCU read lock around the iteration, which actually reduces LOC. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 0eb7b86..3edf716 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2763,10 +2763,7 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add) */ update_before = cgroup_serial_nr_next; - mutex_unlock(&cgroup_mutex); - /* add/rm files for all cgroups created before */ - rcu_read_lock(); css_for_each_descendant_pre(css, cgroup_css(root, ss)) { struct cgroup *cgrp = css->cgroup; @@ -2775,23 +2772,19 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add) inode = cgrp->dentry->d_inode; dget(cgrp->dentry); - rcu_read_unlock(); - dput(prev); prev = cgrp->dentry; + mutex_unlock(&cgroup_mutex); mutex_lock(&inode->i_mutex); mutex_lock(&cgroup_mutex); if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp)) ret = cgroup_addrm_files(cgrp, cfts, is_add); - mutex_unlock(&cgroup_mutex); mutex_unlock(&inode->i_mutex); - - rcu_read_lock(); if (ret) break; } - rcu_read_unlock(); + mutex_unlock(&cgroup_mutex); dput(prev); deactivate_super(sb); return ret; -- cgit v0.10.2 From 87f9260bf1fb7ec4c3f88c6bb353df17ca1e1c19 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 8 Feb 2014 21:18:24 +0000 Subject: ARM: dts: fix spdif pinmux configuration The spdif pinmux configuration must be connected to the spdif device to take effect, not the spdif-transmitter. Signed-off-by: Russell King diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/imx6dl-hummingboard.dts index fd8fc7c..5bfae54 100644 --- a/arch/arm/boot/dts/imx6dl-hummingboard.dts +++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts @@ -52,12 +52,6 @@ }; }; - codec: spdif-transmitter { - compatible = "linux,spdif-dit"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hummingboard_spdif>; - }; - sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; @@ -111,7 +105,7 @@ }; pinctrl_hummingboard_spdif: hummingboard-spdif { - fsl,pins = ; + fsl,pins = ; }; pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus { @@ -142,6 +136,8 @@ }; &spdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hummingboard_spdif>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi index 64daa3b..c2a2488 100644 --- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi @@ -46,12 +46,6 @@ }; }; - codec: spdif-transmitter { - compatible = "linux,spdif-dit"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_cubox_i_spdif>; - }; - sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; @@ -89,7 +83,7 @@ }; pinctrl_cubox_i_spdif: cubox-i-spdif { - fsl,pins = ; + fsl,pins = ; }; pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus { @@ -121,6 +115,8 @@ }; &spdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cubox_i_spdif>; status = "okay"; }; -- cgit v0.10.2 From e97df76377b8b3b1f7dfd5d6f8a1d5a31438b140 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 5 Feb 2014 20:48:51 +0100 Subject: perf/x86/intel/p6: Add userspace RDPMC quirk for PPro PPro machines can die hard when PCE gets enabled due to a CPU erratum. The safe way it so disable it by default and keep it disabled. See erratum 26 in: http://download.intel.com/design/archives/processors/pro/docs/24268935.pdf Reported-and-Tested-by: Mark Davies Cc: Alan Cox Cc: Stephane Eranian Cc: Vince Weaver Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140206170815.GW2936@laptop.programming.kicks-ass.net Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index b886451..1246b85 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1521,6 +1521,8 @@ static int __init init_hw_perf_events(void) pr_cont("%s PMU driver.\n", x86_pmu.name); + x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ + for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next) quirk->func(); @@ -1534,7 +1536,6 @@ static int __init init_hw_perf_events(void) __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, 0, x86_pmu.num_counters, 0, 0); - x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ x86_pmu_format_group.attrs = x86_pmu.format_attrs; if (x86_pmu.event_attrs) @@ -1820,6 +1821,9 @@ static ssize_t set_attr_rdpmc(struct device *cdev, if (ret) return ret; + if (x86_pmu.attr_rdpmc_broken) + return -ENOTSUPP; + if (!!val != !!x86_pmu.attr_rdpmc) { x86_pmu.attr_rdpmc = !!val; smp_call_function(change_rdpmc, (void *)val, 1); diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index c1a8618..4972c24 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -409,6 +409,7 @@ struct x86_pmu { /* * sysfs attrs */ + int attr_rdpmc_broken; int attr_rdpmc; struct attribute **format_attrs; struct attribute **event_attrs; diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index b1e2fe1..7c1a0c0 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -231,31 +231,49 @@ static __initconst const struct x86_pmu p6_pmu = { }; +static __init void p6_pmu_rdpmc_quirk(void) +{ + if (boot_cpu_data.x86_mask < 9) { + /* + * PPro erratum 26; fixed in stepping 9 and above. + */ + pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n"); + x86_pmu.attr_rdpmc_broken = 1; + x86_pmu.attr_rdpmc = 0; + } +} + __init int p6_pmu_init(void) { + x86_pmu = p6_pmu; + switch (boot_cpu_data.x86_model) { - case 1: - case 3: /* Pentium Pro */ - case 5: - case 6: /* Pentium II */ - case 7: - case 8: - case 11: /* Pentium III */ - case 9: - case 13: - /* Pentium M */ + case 1: /* Pentium Pro */ + x86_add_quirk(p6_pmu_rdpmc_quirk); + break; + + case 3: /* Pentium II - Klamath */ + case 5: /* Pentium II - Deschutes */ + case 6: /* Pentium II - Mendocino */ break; + + case 7: /* Pentium III - Katmai */ + case 8: /* Pentium III - Coppermine */ + case 10: /* Pentium III Xeon */ + case 11: /* Pentium III - Tualatin */ + break; + + case 9: /* Pentium M - Banias */ + case 13: /* Pentium M - Dothan */ + break; + default: - pr_cont("unsupported p6 CPU model %d ", - boot_cpu_data.x86_model); + pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model); return -ENODEV; } - x86_pmu = p6_pmu; - memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, sizeof(hw_cache_event_ids)); - return 0; } -- cgit v0.10.2 From 0e9f2204cfa6d79abe3e525ddf7c4ab5792cc751 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 5 Feb 2014 11:19:56 +0100 Subject: perf/x86: Fix Userspace RDPMC switch The current code forgets to change the CR4 state on the current CPU. Use on_each_cpu() instead of smp_call_function(). Reported-by: Mark Davies Suggested-by: Mark Davies Signed-off-by: Peter Zijlstra Cc: fweisbec@gmail.com Link: http://lkml.kernel.org/n/tip-69efsat90ibhnd577zy3z9gh@git.kernel.org Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 1246b85..895604f 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1826,7 +1826,7 @@ static ssize_t set_attr_rdpmc(struct device *cdev, if (!!val != !!x86_pmu.attr_rdpmc) { x86_pmu.attr_rdpmc = !!val; - smp_call_function(change_rdpmc, (void *)val, 1); + on_each_cpu(change_rdpmc, (void *)val, 1); } return count; -- cgit v0.10.2 From fe60a8a0919eeee862054137fed49f00b710d9cd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Feb 2014 10:35:22 +1100 Subject: xfs: ensure correct timestamp updates from truncate The VFS doesn't set the proper ATTR_CTIME and ATTR_MTIME values for truncate, so filesystems have to manually add them. The introduction of xfs_setattr_time accidentally broke this special case an caused a regression in generic/313. Fix this by removing the local mask variable in xfs_setattr_size so that we only have a single place to keep the attribute information. cc: Signed-off-by: Christoph Hellwig Reported-by: Fengguang Wu Reviewed-by: Brian Foster Reviewed-by: Jie Liu Signed-off-by: Dave Chinner diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f35d5c9..9ddfb81 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -705,7 +705,6 @@ xfs_setattr_size( { struct xfs_mount *mp = ip->i_mount; struct inode *inode = VFS_I(ip); - int mask = iattr->ia_valid; xfs_off_t oldsize, newsize; struct xfs_trans *tp; int error; @@ -726,8 +725,8 @@ xfs_setattr_size( ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(S_ISREG(ip->i_d.di_mode)); - ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| - ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); + ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| + ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); oldsize = inode->i_size; newsize = iattr->ia_size; @@ -736,7 +735,7 @@ xfs_setattr_size( * Short circuit the truncate case for zero length files. */ if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) { - if (!(mask & (ATTR_CTIME|ATTR_MTIME))) + if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME))) return 0; /* @@ -824,10 +823,11 @@ xfs_setattr_size( * these flags set. For all other operations the VFS set these flags * explicitly if it wants a timestamp update. */ - if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) { + if (newsize != oldsize && + !(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) { iattr->ia_ctime = iattr->ia_mtime = current_fs_time(inode->i_sb); - mask |= ATTR_CTIME | ATTR_MTIME; + iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME; } /* @@ -863,9 +863,9 @@ xfs_setattr_size( xfs_inode_clear_eofblocks_tag(ip); } - if (mask & ATTR_MODE) + if (iattr->ia_valid & ATTR_MODE) xfs_setattr_mode(ip, iattr); - if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME)) + if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME)) xfs_setattr_time(ip, iattr); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); -- cgit v0.10.2 From 3895e51f6dbf6610519be070a3bede811f6ac4fb Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 10 Feb 2014 10:37:18 +1100 Subject: xfs: ensure correct log item buffer alignment On 32 bit platforms, the log item vector headers are not 64 bit aligned or sized. hence if we don't take care to align them correctly or pad the buffer appropriately for 8 byte alignment, we can end up with alignment issues when accessing the user buffer directly as a structure. To solve this, simply pad the buffer headers to 64 bit offset so that the data section is always 8 byte aligned. Signed-off-by: Dave Chinner Reported-by: Michael L. Semon Tested-by: Michael L. Semon Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index cdebd83..4ef6fdb 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -205,16 +205,25 @@ xlog_cil_insert_format_items( /* * We 64-bit align the length of each iovec so that the start * of the next one is naturally aligned. We'll need to - * account for that slack space here. + * account for that slack space here. Then round nbytes up + * to 64-bit alignment so that the initial buffer alignment is + * easy to calculate and verify. */ nbytes += niovecs * sizeof(uint64_t); + nbytes = round_up(nbytes, sizeof(uint64_t)); /* grab the old item if it exists for reservation accounting */ old_lv = lip->li_lv; - /* calc buffer size */ - buf_size = sizeof(struct xfs_log_vec) + nbytes + - niovecs * sizeof(struct xfs_log_iovec); + /* + * The data buffer needs to start 64-bit aligned, so round up + * that space to ensure we can align it appropriately and not + * overrun the buffer. + */ + buf_size = nbytes + + round_up((sizeof(struct xfs_log_vec) + + niovecs * sizeof(struct xfs_log_iovec)), + sizeof(uint64_t)); /* compare to existing item size */ if (lip->li_lv && buf_size <= lip->li_lv->lv_size) { @@ -251,6 +260,8 @@ xlog_cil_insert_format_items( /* The allocated data region lies beyond the iovec region */ lv->lv_buf_len = 0; lv->lv_buf = (char *)lv + buf_size - nbytes; + ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t))); + lip->li_ops->iop_format(lip, lv); insert: ASSERT(lv->lv_buf_len <= nbytes); -- cgit v0.10.2 From 4d9c5b89cf3605bbc39c6e274351ff25f0d83e6a Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Sun, 2 Feb 2014 22:21:31 +0100 Subject: ARM: 7950/1: mm: Fix stage-2 device memory attributes The stage-2 memory attributes are distinct from the Hyp memory attributes and the Stage-1 memory attributes. We were using the stage-1 memory attributes for stage-2 mappings causing device mappings to be mapped as normal memory. Add the S2 equivalent defines for memory attributes and fix the comments explaining the defines while at it. Add a prot_pte_s2 field to the mem_type struct and fill out the field for device mappings accordingly. Cc: [3.9+] Acked-by: Marc Zyngier Acked-by: Catalin Marinas Signed-off-by: Christoffer Dall Signed-off-by: Russell King diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index 03243f7..85c60ad 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h @@ -120,13 +120,16 @@ /* * 2nd stage PTE definitions for LPAE. */ -#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ -#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ +#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x0) << 2) /* strongly ordered */ +#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */ +#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */ +#define L_PTE_S2_MT_DEV_SHARED (_AT(pteval_t, 0x1) << 2) /* device */ +#define L_PTE_S2_MT_MASK (_AT(pteval_t, 0xf) << 2) -#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ +#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ +#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ + +#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ /* * Hyp-mode PL2 PTE definitions for LPAE. diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index d5a982d..7ea641b 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -38,6 +38,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt) struct mem_type { pteval_t prot_pte; + pteval_t prot_pte_s2; pmdval_t prot_l1; pmdval_t prot_sect; unsigned int domain; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4f08c13..a623cb3 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -232,12 +232,16 @@ __setup("noalign", noalign_setup); #endif /* ifdef CONFIG_CPU_CP15 / else */ #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN +#define PROT_PTE_S2_DEVICE PROT_PTE_DEVICE #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE static struct mem_type mem_types[] = { [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | L_PTE_SHARED, + .prot_pte_s2 = s2_policy(PROT_PTE_S2_DEVICE) | + s2_policy(L_PTE_S2_MT_DEV_SHARED) | + L_PTE_SHARED, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, .domain = DOMAIN_IO, @@ -508,7 +512,8 @@ static void __init build_mem_type_table(void) cp = &cache_policies[cachepolicy]; vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; s2_pgprot = cp->pte_s2; - hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; + hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; + s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; /* * ARMv6 and above have extended page tables. -- cgit v0.10.2 From ca4744084772e1fee999391bee0fcdca5d91a757 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 6 Feb 2014 19:50:35 +0100 Subject: ARM: 7952/1: mm: Fix the memblock allocation for LPAE machines Commit ad6492b8 added much needed memblock_virt_alloc_low() and further commit 07bacb3 {memblock, bootmem: restore goal for alloc_low} fixed the issue with low memory limit thanks to Yinghai. But even after all these fixes, there is still one case where the limit check done with ARCH_LOW_ADDRESS_LIMIT for low memory fails. Russell pointed out the issue with 32 bit LPAE machines in below thread. https://lkml.org/lkml/2014/1/28/364 Since on some LPAE machines where memory start address is beyond 4GB, the low memory marker in memblock will be set to default ARCH_LOW_ADDRESS_LIMIT which is wrong. We can fix this by letting architectures set the ARCH_LOW_ADDRESS_LIMIT using another export similar to memblock_set_current_limit() but am not sure whether its worth the trouble. Tell me if you think otherwise. Rather am just trying to fix that one broken case using memblock_virt_alloc() in setup code since the memblock.current_limit is updated appropriately makes it work on all ARM 32 bit machines. Cc: Yinghai Lu Cc: Strashko, Grygorii Cc: Andrew Morton Signed-off-by: Santosh Shilimkar Signed-off-by: Russell King diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b0df976..1e8b030 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -731,7 +731,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) kernel_data.end = virt_to_phys(_end - 1); for_each_memblock(memory, region) { - res = memblock_virt_alloc_low(sizeof(*res), 0); + res = memblock_virt_alloc(sizeof(*res), 0); res->name = "System RAM"; res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; -- cgit v0.10.2 From bae0ca2bc550d1ec6a118fb8f2696f18c4da3d8e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Feb 2014 19:12:20 +0100 Subject: ARM: 7953/1: mm: ensure TLB invalidation is complete before enabling MMU During __v{6,7}_setup, we invalidate the TLBs since we are about to enable the MMU on return to head.S. Unfortunately, without a subsequent dsb instruction, the invalidation is not guaranteed to have completed by the time we write to the sctlr, potentially exposing us to junk/stale translations cached in the TLB. This patch reworks the init functions so that the dsb used to ensure completion of cache/predictor maintenance is also used to ensure completion of the TLB invalidation. Cc: Reported-by: Albin Tonnerre Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 45dc29f..32b3558 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -208,7 +208,6 @@ __v6_setup: mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r0, c2, c0, 2 @ TTB control register @@ -218,6 +217,8 @@ __v6_setup: ALT_UP(orr r8, r8, #TTB_FLAGS_UP) mcr p15, 0, r8, c2, c0, 1 @ load TTB1 #endif /* CONFIG_MMU */ + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer and + @ complete invalidations adr r5, v6_crval ldmia r5, {r5, r6} ARM_BE8(orr r6, r6, #1 << 25) @ big-endian page tables diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index bd17819..74f6033 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -351,7 +351,6 @@ __v7_setup: 4: mov r10, #0 mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate - dsb #ifdef CONFIG_MMU mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup @@ -360,6 +359,7 @@ __v7_setup: mcr p15, 0, r5, c10, c2, 0 @ write PRRR mcr p15, 0, r6, c10, c2, 1 @ write NMRR #endif + dsb @ Complete invalidations #ifndef CONFIG_ARM_THUMBEE mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE and r0, r0, #(0xf << 12) @ ThumbEE enabled field -- cgit v0.10.2 From 7c8746a9eb287642deaad0e7c2cdf482dce5e4be Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Feb 2014 19:12:32 +0100 Subject: ARM: 7955/1: spinlock: ensure we have a compiler barrier before sev When unlocking a spinlock, we require the following, strictly ordered sequence of events: /* dmb */ /* dsb */ Whilst the code does indeed reflect this in terms of the architecture, the final + have been contracted into a single inline asm without a "memory" clobber, therefore the compiler is at liberty to reorder the unlock to the end of the above sequence. In such a case, a waiting CPU may be woken up before the lock has been unlocked, leading to extremely poor performance. This patch reworks the dsb_sev() function to make use of the dsb() macro and ensure ordering against the unlock. Cc: Reported-by: Mark Rutland Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index ef3c607..ac4bfae 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -37,18 +37,9 @@ static inline void dsb_sev(void) { -#if __LINUX_ARM_ARCH__ >= 7 - __asm__ __volatile__ ( - "dsb ishst\n" - SEV - ); -#else - __asm__ __volatile__ ( - "mcr p15, 0, %0, c7, c10, 4\n" - SEV - : : "r" (0) - ); -#endif + + dsb(ishst); + __asm__(SEV); } /* -- cgit v0.10.2 From 78957fc349bcf29d415a649601581a993ff25e4d Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 14:38:28 +0800 Subject: ASoC: fsl-sai: convert to use regmap API for Freeacale SAI Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index cdd3fa8..faa65af 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,34 +23,6 @@ #include "fsl_sai.h" -static inline u32 sai_readl(struct fsl_sai *sai, - const void __iomem *addr) -{ - u32 val; - - val = __raw_readl(addr); - - if (likely(sai->big_endian_regs)) - val = be32_to_cpu(val); - else - val = le32_to_cpu(val); - rmb(); - - return val; -} - -static inline void sai_writel(struct fsl_sai *sai, - u32 val, void __iomem *addr) -{ - wmb(); - if (likely(sai->big_endian_regs)) - val = cpu_to_be32(val); - else - val = cpu_to_le32(val); - - __raw_writel(val, addr); -} - static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int fsl_dir) { @@ -61,7 +34,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, else reg_cr2 = FSL_SAI_RCR2; - val_cr2 = sai_readl(sai, sai->base + reg_cr2); + regmap_read(sai->regmap, reg_cr2, &val_cr2); + val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; switch (clk_id) { @@ -81,7 +55,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, return -EINVAL; } - sai_writel(sai, val_cr2, sai->base + reg_cr2); + regmap_write(sai->regmap, reg_cr2, val_cr2); return 0; } @@ -89,32 +63,22 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); int ret; if (dir == SND_SOC_CLOCK_IN) return 0; - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, FSL_FMT_TRANSMITTER); if (ret) { dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); - goto err_clk; + return ret; } ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, FSL_FMT_RECEIVER); - if (ret) { + if (ret) dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); - goto err_clk; - } - -err_clk: - clk_disable_unprepare(sai->clk); return ret; } @@ -133,8 +97,8 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, reg_cr4 = FSL_SAI_RCR4; } - val_cr2 = sai_readl(sai, sai->base + reg_cr2); - val_cr4 = sai_readl(sai, sai->base + reg_cr4); + regmap_read(sai->regmap, reg_cr2, &val_cr2); + regmap_read(sai->regmap, reg_cr4, &val_cr4); if (sai->big_endian_data) val_cr4 &= ~FSL_SAI_CR4_MF; @@ -183,35 +147,25 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, return -EINVAL; } - sai_writel(sai, val_cr2, sai->base + reg_cr2); - sai_writel(sai, val_cr4, sai->base + reg_cr4); + regmap_write(sai->regmap, reg_cr2, val_cr2); + regmap_write(sai->regmap, reg_cr4, val_cr4); return 0; } static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); int ret; - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER); if (ret) { dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); - goto err_clk; + return ret; } ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER); - if (ret) { + if (ret) dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); - goto err_clk; - } - -err_clk: - clk_disable_unprepare(sai->clk); return ret; } @@ -235,11 +189,12 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, reg_mr = FSL_SAI_RMR; } - val_cr4 = sai_readl(sai, sai->base + reg_cr4); + regmap_read(sai->regmap, reg_cr4, &val_cr4); + regmap_read(sai->regmap, reg_cr4, &val_cr5); + val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK; val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK; - val_cr5 = sai_readl(sai, sai->base + reg_cr5); val_cr5 &= ~FSL_SAI_CR5_WNW_MASK; val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; @@ -257,9 +212,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, val_cr4 |= FSL_SAI_CR4_FRSZ(channels); val_mr = ~0UL - ((1 << channels) - 1); - sai_writel(sai, val_cr4, sai->base + reg_cr4); - sai_writel(sai, val_cr5, sai->base + reg_cr5); - sai_writel(sai, val_mr, sai->base + reg_mr); + regmap_write(sai->regmap, reg_cr4, val_cr4); + regmap_write(sai->regmap, reg_cr5, val_cr5); + regmap_write(sai->regmap, reg_mr, val_mr); return 0; } @@ -268,44 +223,34 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); - u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3; - - val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2); - val_cr2 &= ~FSL_SAI_CR2_SYNC; - sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2); + u32 tcsr, rcsr; - val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2); - val_cr2 |= FSL_SAI_CR2_SYNC; - sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2); + regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, + ~FSL_SAI_CR2_SYNC); + regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, + FSL_SAI_CR2_SYNC); - tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR); - rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR); + regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr); + regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { tcsr |= FSL_SAI_CSR_FRDE; rcsr &= ~FSL_SAI_CSR_FRDE; - reg_cr3 = FSL_SAI_TCR3; } else { rcsr |= FSL_SAI_CSR_FRDE; tcsr &= ~FSL_SAI_CSR_FRDE; - reg_cr3 = FSL_SAI_RCR3; } - val_cr3 = sai_readl(sai, sai->base + reg_cr3); - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: tcsr |= FSL_SAI_CSR_TERE; rcsr |= FSL_SAI_CSR_TERE; - val_cr3 |= FSL_SAI_CR3_TRCE; - sai_writel(sai, val_cr3, sai->base + reg_cr3); - sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); - sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); + regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); + regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); break; - case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -314,11 +259,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, rcsr &= ~FSL_SAI_CSR_TERE; } - val_cr3 &= ~FSL_SAI_CR3_TRCE; - - sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); - sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); - sai_writel(sai, val_cr3, sai->base + reg_cr3); + regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); + regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); break; default: return -EINVAL; @@ -331,16 +273,32 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + u32 reg; - return clk_prepare_enable(sai->clk); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = FSL_SAI_TCR3; + else + reg = FSL_SAI_RCR3; + + regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, + FSL_SAI_CR3_TRCE); + + return 0; } static void fsl_sai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + u32 reg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = FSL_SAI_TCR3; + else + reg = FSL_SAI_RCR3; - clk_disable_unprepare(sai->clk); + regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, + ~FSL_SAI_CR3_TRCE); } static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { @@ -355,18 +313,13 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); - int ret; - - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR); - sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR); - sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1); - sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1); - - clk_disable_unprepare(sai->clk); + regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0); + regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0); + regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, + FSL_SAI_MAXBURST_TX * 2); + regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, + FSL_SAI_MAXBURST_RX - 1); snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx); @@ -397,26 +350,109 @@ static const struct snd_soc_component_driver fsl_component = { .name = "fsl-sai", }; +static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TCSR: + case FSL_SAI_TCR1: + case FSL_SAI_TCR2: + case FSL_SAI_TCR3: + case FSL_SAI_TCR4: + case FSL_SAI_TCR5: + case FSL_SAI_TFR: + case FSL_SAI_TMR: + case FSL_SAI_RCSR: + case FSL_SAI_RCR1: + case FSL_SAI_RCR2: + case FSL_SAI_RCR3: + case FSL_SAI_RCR4: + case FSL_SAI_RCR5: + case FSL_SAI_RDR: + case FSL_SAI_RFR: + case FSL_SAI_RMR: + return true; + default: + return false; + } +} + +static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TFR: + case FSL_SAI_RFR: + case FSL_SAI_TDR: + case FSL_SAI_RDR: + return true; + default: + return false; + } + +} + +static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TCSR: + case FSL_SAI_TCR1: + case FSL_SAI_TCR2: + case FSL_SAI_TCR3: + case FSL_SAI_TCR4: + case FSL_SAI_TCR5: + case FSL_SAI_TDR: + case FSL_SAI_TMR: + case FSL_SAI_RCSR: + case FSL_SAI_RCR1: + case FSL_SAI_RCR2: + case FSL_SAI_RCR3: + case FSL_SAI_RCR4: + case FSL_SAI_RCR5: + case FSL_SAI_RMR: + return true; + default: + return false; + } +} + +static struct regmap_config fsl_sai_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + + .max_register = FSL_SAI_RMR, + .readable_reg = fsl_sai_readable_reg, + .volatile_reg = fsl_sai_volatile_reg, + .writeable_reg = fsl_sai_writeable_reg, +}; + static int fsl_sai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct fsl_sai *sai; struct resource *res; + void __iomem *base; int ret; sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); if (!sai) return -ENOMEM; + sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); + if (sai->big_endian_regs) + fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + + sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sai->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(sai->base)) - return PTR_ERR(sai->base); - - sai->clk = devm_clk_get(&pdev->dev, "sai"); - if (IS_ERR(sai->clk)) { - dev_err(&pdev->dev, "Cannot get SAI's clock\n"); - return PTR_ERR(sai->clk); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, + "sai", base, &fsl_sai_regmap_config); + if (IS_ERR(sai->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + return PTR_ERR(sai->regmap); } sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; @@ -424,9 +460,6 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; - sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); - sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); - platform_set_drvdata(pdev, sai); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 41bb62e6..1571459 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -15,31 +15,36 @@ SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +/* SAI Register Map Register */ +#define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ +#define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */ +#define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */ +#define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */ +#define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */ +#define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */ +#define FSL_SAI_TDR 0x20 /* SAI Transmit Data */ +#define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */ +#define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ +#define FSL_SAI_RCSR 0x80 /* SAI Receive Control */ +#define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */ +#define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */ +#define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */ +#define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */ +#define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */ +#define FSL_SAI_RDR 0xa0 /* SAI Receive Data */ +#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */ +#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ + /* SAI Transmit/Recieve Control Register */ -#define FSL_SAI_TCSR 0x00 -#define FSL_SAI_RCSR 0x80 #define FSL_SAI_CSR_TERE BIT(31) #define FSL_SAI_CSR_FWF BIT(17) #define FSL_SAI_CSR_FRIE BIT(8) #define FSL_SAI_CSR_FRDE BIT(0) -/* SAI Transmit Data/FIFO/MASK Register */ -#define FSL_SAI_TDR 0x20 -#define FSL_SAI_TFR 0x40 -#define FSL_SAI_TMR 0x60 - -/* SAI Recieve Data/FIFO/MASK Register */ -#define FSL_SAI_RDR 0xa0 -#define FSL_SAI_RFR 0xc0 -#define FSL_SAI_RMR 0xe0 - /* SAI Transmit and Recieve Configuration 1 Register */ -#define FSL_SAI_TCR1 0x04 -#define FSL_SAI_RCR1 0x84 +#define FSL_SAI_CR1_RFW_MASK 0x1f /* SAI Transmit and Recieve Configuration 2 Register */ -#define FSL_SAI_TCR2 0x08 -#define FSL_SAI_RCR2 0x88 #define FSL_SAI_CR2_SYNC BIT(30) #define FSL_SAI_CR2_MSEL_MASK (0xff << 26) #define FSL_SAI_CR2_MSEL_BUS 0 @@ -50,15 +55,11 @@ #define FSL_SAI_CR2_BCD_MSTR BIT(24) /* SAI Transmit and Recieve Configuration 3 Register */ -#define FSL_SAI_TCR3 0x0c -#define FSL_SAI_RCR3 0x8c #define FSL_SAI_CR3_TRCE BIT(16) #define FSL_SAI_CR3_WDFL(x) (x) #define FSL_SAI_CR3_WDFL_MASK 0x1f /* SAI Transmit and Recieve Configuration 4 Register */ -#define FSL_SAI_TCR4 0x10 -#define FSL_SAI_RCR4 0x90 #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) @@ -69,8 +70,6 @@ #define FSL_SAI_CR4_FSD_MSTR BIT(0) /* SAI Transmit and Recieve Configuration 5 Register */ -#define FSL_SAI_TCR5 0x14 -#define FSL_SAI_RCR5 0x94 #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) @@ -100,9 +99,7 @@ #define FSL_SAI_MAXBURST_RX 6 struct fsl_sai { - struct clk *clk; - - void __iomem *base; + struct regmap *regmap; bool big_endian_regs; bool big_endian_data; -- cgit v0.10.2 From 9a6d48605e632e84db2895cf752c65b3c908cd09 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 15:59:52 +0800 Subject: ASoC: add snd_soc_of_parse_audio_simple_widgets for DT This patch adds snd_soc_of_parse_audio_simple_widgets() and supports below style of widgets name on DT: "template-wname", "user supplied wname" For instance: simple-audio-widgets = "Microphone", "Microphone Jack", "Line", "Line In Jack", "Line", "Line Out Jack", "Headphone", "Headphone Jack", "Speaker", "Speaker External"; The "template-wname" currently includes: "Microphone", "Line", "Headphone" and "Speaker". Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a00147..465dc6e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1173,6 +1173,8 @@ void snd_soc_util_exit(void); int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50..0540cb0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4417,6 +4417,93 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); +static const struct snd_soc_dapm_widget simple_widgets[] = { + SND_SOC_DAPM_MIC("Microphone", NULL), + SND_SOC_DAPM_LINE("Line", NULL), + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname) +{ + struct device_node *np = card->dev->of_node; + struct snd_soc_dapm_widget *widgets; + const char *template, *wname; + int i, j, num_widgets, ret; + + num_widgets = of_property_count_strings(np, propname); + if (num_widgets < 0) { + dev_err(card->dev, + "ASoC: Property '%s' does not exist\n", propname); + return -EINVAL; + } + if (num_widgets & 1) { + dev_err(card->dev, + "ASoC: Property '%s' length is not even\n", propname); + return -EINVAL; + } + + num_widgets /= 2; + if (!num_widgets) { + dev_err(card->dev, "ASoC: Property '%s's length is zero\n", + propname); + return -EINVAL; + } + + widgets = devm_kcalloc(card->dev, num_widgets, sizeof(*widgets), + GFP_KERNEL); + if (!widgets) { + dev_err(card->dev, + "ASoC: Could not allocate memory for widgets\n"); + return -ENOMEM; + } + + for (i = 0; i < num_widgets; i++) { + ret = of_property_read_string_index(np, propname, + 2 * i, &template); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, 2 * i, ret); + return -EINVAL; + } + + for (j = 0; j < ARRAY_SIZE(simple_widgets); j++) { + if (!strncmp(template, simple_widgets[j].name, + strlen(simple_widgets[j].name))) { + widgets[i] = simple_widgets[j]; + break; + } + } + + if (j >= ARRAY_SIZE(simple_widgets)) { + dev_err(card->dev, + "ASoC: DAPM widget '%s' is not supported\n", + template); + return -EINVAL; + } + + ret = of_property_read_string_index(np, propname, + (2 * i) + 1, + &wname); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, (2 * i) + 1, ret); + return -EINVAL; + } + + widgets[i].name = wname; + } + + card->dapm_widgets = widgets; + card->num_dapm_widgets = num_widgets; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) { -- cgit v0.10.2 From ac7f4820301b6b6029f01e4c276c2cd42272d9cb Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 15:59:54 +0800 Subject: ASoC: binding: add widgets.txt Suggested-by: Mark Brown Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/widgets.txt b/Documentation/devicetree/bindings/sound/widgets.txt new file mode 100644 index 0000000..b6de5ba --- /dev/null +++ b/Documentation/devicetree/bindings/sound/widgets.txt @@ -0,0 +1,20 @@ +Widgets: + +This mainly specifies audio off-codec DAPM widgets. + +Each entry is a pair of strings in DT: + + "template-wname", "user-supplied-wname" + +The "template-wname" being the template widget name and currently includes: +"Microphone", "Line", "Headphone" and "Speaker". + +The "user-supplied-wname" being the user specified widget name. + +For instance: + simple-audio-widgets = + "Microphone", "Microphone Jack", + "Line", "Line In Jack", + "Line", "Line Out Jack", + "Headphone", "Headphone Jack", + "Speaker", "Speaker External"; -- cgit v0.10.2 From 9d681f5bfc85515a7b4a4af09337ed5e74f39ad9 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 15:59:53 +0800 Subject: ASoC: simple-card: add off-codec widgets supports. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 0890fcd..4fe8abc 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -150,6 +150,14 @@ static int asoc_simple_card_parse_of(struct device_node *node, priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); + /* off-codec widgets */ + if (of_property_read_bool(node, "simple-audio-card,widgets")) { + ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, + "simple-audio-card,widgets"); + if (ret) + return ret; + } + /* DAPM routes */ if (of_property_read_bool(node, "simple-audio-card,routing")) { ret = snd_soc_of_parse_audio_routing(&priv->snd_card, -- cgit v0.10.2 From 66841345073b049c0c194486bac4d7f07266a57e Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 15:59:55 +0800 Subject: ASoC: simple-card: for new properties documenting and usage This add the following three new properties documenting and usage for simple card: "simple-audio-card,name", "simple-audio-card,widgets", Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index 19c84df..0527358 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -8,9 +8,12 @@ Required properties: Optional properties: +- simple-audio-card,name : User specified audio sound card name, one string + property. - simple-audio-card,format : CPU/CODEC common audio format. "i2s", "right_j", "left_j" , "dsp_a" "dsp_b", "ac97", "pdm", "msb", "lsb" +- simple-audio-card,widgets : Please refer to widgets.txt. - simple-audio-card,routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's @@ -42,11 +45,16 @@ Example: sound { compatible = "simple-audio-card"; + simple-audio-card,name = "VF610-Tower-Sound-Card"; simple-audio-card,format = "left_j"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Speaker", "External Speaker"; simple-audio-card,routing = - "MIC_IN", "Mic Jack", + "MIC_IN", "Microphone Jack", "Headphone Jack", "HP_OUT", - "Ext Spk", "LINE_OUT"; + "External Speaker", "LINE_OUT"; simple-audio-card,cpu { sound-dai = <&sh_fsi2 0>; -- cgit v0.10.2 From 9f10b36ffde2b732def037c1e764a0c71745a372 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 6 Feb 2014 18:03:09 +0000 Subject: ASoC: da9055: Add DT support for CODEC Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/da9055.txt b/Documentation/devicetree/bindings/sound/da9055.txt new file mode 100644 index 0000000..ed1b7cc --- /dev/null +++ b/Documentation/devicetree/bindings/sound/da9055.txt @@ -0,0 +1,22 @@ +* Dialog DA9055 Audio CODEC + +DA9055 provides Audio CODEC support (I2C only). + +The Audio CODEC device in DA9055 has it's own I2C address which is configurable, +so the device is instantiated separately from the PMIC (MFD) device. + +For details on accompanying PMIC I2C device, see the following: +Documentation/devicetree/bindings/mfd/da9055.txt + +Required properties: + + - compatible: "dlg,da9055-codec" + - reg: Specifies the I2C slave address + + +Example: + + codec: da9055-codec@1a { + compatible = "dlg,da9055-codec"; + reg = <0x1a>; + }; diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 4228126..be31f3c 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -1536,11 +1538,17 @@ static const struct i2c_device_id da9055_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); +static const struct of_device_id da9055_of_match[] = { + { .compatible = "dlg,da9055-codec", }, + { } +}; + /* I2C codec control layer */ static struct i2c_driver da9055_i2c_driver = { .driver = { .name = "da9055-codec", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(da9055_of_match), }, .probe = da9055_i2c_probe, .remove = da9055_remove, -- cgit v0.10.2 From fd1defc257e2b12ab69bc0b379105c00eca4e112 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 6 Feb 2014 14:38:53 -0500 Subject: NFS: Do not set NFS_INO_INVALID_LABEL unless server supports labeled NFS Commit aa9c2669626c (NFS: Client implementation of Labeled-NFS) introduces a performance regression. When nfs_zap_caches_locked is called, it sets the NFS_INO_INVALID_LABEL flag irrespectively of whether or not the NFS server supports security labels. Since that flag is never cleared, it means that all calls to nfs_revalidate_inode() will now trigger an on-the-wire GETATTR call. This patch ensures that we never set the NFS_INO_INVALID_LABEL unless the server advertises support for labeled NFS. It also causes nfs_setsecurity() to clear NFS_INO_INVALID_LABEL when it has successfully set the security label for the inode. Finally it gets rid of the NFS_INO_INVALID_LABEL cruft from nfs_update_inode, which has nothing to do with labeled NFS. Reported-by: Neil Brown Cc: stable@vger.kernel.org # 3.11+ Tested-by: Neil Brown Signed-off-by: Trond Myklebust diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 28a0a3c..360114a 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -164,17 +164,16 @@ static void nfs_zap_caches_locked(struct inode *inode) if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { nfs_fscache_invalidate(inode); nfsi->cache_validity |= NFS_INO_INVALID_ATTR - | NFS_INO_INVALID_LABEL | NFS_INO_INVALID_DATA | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL | NFS_INO_REVAL_PAGECACHE; } else nfsi->cache_validity |= NFS_INO_INVALID_ATTR - | NFS_INO_INVALID_LABEL | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL | NFS_INO_REVAL_PAGECACHE; + nfs_zap_label_cache_locked(nfsi); } void nfs_zap_caches(struct inode *inode) @@ -266,6 +265,13 @@ nfs_init_locked(struct inode *inode, void *opaque) } #ifdef CONFIG_NFS_V4_SECURITY_LABEL +static void nfs_clear_label_invalid(struct inode *inode) +{ + spin_lock(&inode->i_lock); + NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_LABEL; + spin_unlock(&inode->i_lock); +} + void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label) { @@ -283,6 +289,7 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, __func__, (char *)label->label, label->len, error); + nfs_clear_label_invalid(inode); } } @@ -1648,7 +1655,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) inode->i_blocks = fattr->du.nfs2.blocks; /* Update attrtimeo value if we're out of the unstable period */ - if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { + if (invalid & NFS_INO_INVALID_ATTR) { nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo_timestamp = now; @@ -1661,7 +1668,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) } } invalid &= ~NFS_INO_INVALID_ATTR; - invalid &= ~NFS_INO_INVALID_LABEL; /* Don't invalidate the data if we were to blame */ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8b5cc04..fafddda 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -279,9 +279,18 @@ static inline void nfs4_label_free(struct nfs4_label *label) } return; } + +static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) +{ + if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL)) + nfsi->cache_validity |= NFS_INO_INVALID_LABEL; +} #else static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } static inline void nfs4_label_free(void *label) {} +static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) +{ +} #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ /* proc.c */ -- cgit v0.10.2 From 981a23792cd02631f8cd5dd65753208a44de5ae1 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 5 Feb 2014 05:18:58 +0000 Subject: perf probe: Do not add offset twice to uprobe address Fix perf-probe not to add offset value twice to uprobe probe address when post processing. The tevs[i].point.address struct member is the address of symbol+offset, but current perf-probe adjusts the point.address by adding the offset. As a result, the probe address becomes symbol+offset+offset. This may cause unexpected code corruption. Urgent fix is needed. Without this fix: --- # ./perf probe -x ./perf dso__load_vmlinux+4 # ./perf probe -l probe_perf:dso__load_vmlinux (on 0x000000000006d2b8) # nm ./perf.orig | grep dso__load_vmlinux\$ 000000000046d0a0 T dso__load_vmlinux --- You can see the given offset is 3 but the actual probed address is dso__load_vmlinux+8. With this fix: --- # ./perf probe -x ./perf dso__load_vmlinux+4 # ./perf probe -l probe_perf:dso__load_vmlinux (on 0x000000000006d2b4) --- Now the problem is fixed. Note: This bug is introduced by commit fb7345bbf7fad9bf72ef63a19c707970b9685812 Signed-off-by: Masami Hiramatsu Cc: "David A. Long" Cc: David Ahern Cc: Ingo Molnar Cc: Namhyung Kim Cc: Oleg Nesterov Cc: Srikar Dronamraju Cc: Steven Rostedt Cc: yrl.pp-manager.tt@hitachi.com Link: http://lkml.kernel.org/r/20140205051858.6519.27314.stgit@kbuild-fedora.yrl.intra.hitachi.co.jp Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index a8a9b6c..d8b048c 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -336,8 +336,8 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, return ret; for (i = 0; i < ntevs && ret >= 0; i++) { + /* point.address is the addres of point.symbol + point.offset */ offset = tevs[i].point.address - stext; - offset += tevs[i].point.offset; tevs[i].point.offset = 0; zfree(&tevs[i].point.symbol); ret = e_snprintf(buf, 32, "0x%lx", offset); -- cgit v0.10.2 From f67697bd079f4bbcbe7d6d26765a06b18afe0630 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 4 Feb 2014 15:37:48 +0100 Subject: perf tools: Handle PERF_RECORD_HEADER_EVENT_TYPE properly We removed event types from data file in following commits: 6065210 perf tools: Remove event types framework completely 44b3c57 perf tools: Remove event types from perf data file We no longer need this information, because we can get it directly from tracepoints. But we still need to handle PERF_RECORD_HEADER_EVENT_TYPE event for the sake of old perf data files created in pipe mode like: $ perf.3.4 record -o - foo >perf.data $ perf.312 report -i - < perf.data Reported-by: Stephane Eranian Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1391524668-12546-1-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0b39a48..5da6ce7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1008,6 +1008,12 @@ static int perf_session__process_user_event(struct perf_session *session, union if (err == 0) perf_session__set_id_hdr_size(session); return err; + case PERF_RECORD_HEADER_EVENT_TYPE: + /* + * Depreceated, but we need to handle it for sake + * of old data files create in pipe mode. + */ + return 0; case PERF_RECORD_HEADER_TRACING_DATA: /* setup for reading amidst mmap */ lseek(fd, file_offset, SEEK_SET); -- cgit v0.10.2 From 88fee52e58ca14d8465b614774ed0bf08e1a7790 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Mon, 30 Dec 2013 15:39:45 -0500 Subject: perf list: Fix checking for supported events on older kernels "perf list" listing of hardware events doesn't work on older ARM devices. The change enabling event detection: commit b41f1cec91c37eeea6fdb15effbfa24ea0a5536b Author: Namhyung Kim Date: Tue Aug 27 11:41:53 2013 +0900 perf list: Skip unsupported events uses the following code in tools/perf/util/parse-events.c: struct perf_event_attr attr = { .type = type, .config = config, .disabled = 1, .exclude_kernel = 1, }; On ARM machines pre-dating the Cortex-A15 this doesn't work, as these machines don't support .exclude_kernel. So starting with 3.12 "perf list" does not report any hardware events at all on older machines (seen on Rasp-Pi, Pandaboard, Beagleboard, etc). This version of the patch makes changes suggested by Namhyung Kim to check for EACCESS and retry (instead of just dropping the exclude_kernel) so we can properly handle machines where /proc/sys/kernel/perf_event_paranoid is set to 2. Reported-by: Chad Paradis Signed-off-by: Vince Weaver Acked-by: Namhyung Kim Cc: Chad Paradis Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1312301536150.28814@vincent-weaver-1.um.maine.edu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index d248fca..1e15df1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1091,12 +1091,12 @@ int is_valid_tracepoint(const char *event_string) static bool is_event_supported(u8 type, unsigned config) { bool ret = true; + int open_return; struct perf_evsel *evsel; struct perf_event_attr attr = { .type = type, .config = config, .disabled = 1, - .exclude_kernel = 1, }; struct { struct thread_map map; @@ -1108,7 +1108,20 @@ static bool is_event_supported(u8 type, unsigned config) evsel = perf_evsel__new(&attr); if (evsel) { - ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; + open_return = perf_evsel__open(evsel, NULL, &tmap.map); + ret = open_return >= 0; + + if (open_return == -EACCES) { + /* + * This happens if the paranoid value + * /proc/sys/kernel/perf_event_paranoid is set to 2 + * Re-run with exclude_kernel set; we don't do that + * by default as some ARM machines do not support it. + * + */ + evsel->attr.exclude_kernel = 1; + ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; + } perf_evsel__delete(evsel); } -- cgit v0.10.2 From 79d26a6a19ace19faabf8d8d27d3430be2e26d34 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 6 Feb 2014 01:00:35 +0000 Subject: perf trace: Add fallback definition of EFD_SEMAPHORE glibc 2.17 is missing this on sparc, despite the fact that it's not architecture-specific. Signed-off-by: Ben Hutchings Fixes: 49af9e93adfa ('perf trace: Beautify eventfd2 'flags' arg') Cc: Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1391648435.3003.100.camel@deadeye.wl.decadent.org.uk Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 896f270..619d11c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -37,6 +37,10 @@ # define MADV_UNMERGEABLE 13 #endif +#ifndef EFD_SEMAPHORE +# define EFD_SEMAPHORE 1 +#endif + struct tp_field { int offset; union { -- cgit v0.10.2 From 97a644208d1a08b7104d1fe2ace8cef011222711 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Fri, 3 Jan 2014 12:01:26 +0000 Subject: iommu/arm-smmu: fix pud/pmd entry fill sequence The ARM SMMU driver's population of puds and pmds is broken, since we iterate over the next level of table repeatedly setting the current level descriptor to point at the pmd being initialised. This is clearly wrong when dealing with multiple pmds/puds. This patch fixes the problem by moving the pud/pmd population out of the loop and instead performing it when we allocate the next level (like we correctly do for ptes already). The starting address for the next level is then calculated prior to entering the loop. Cc: Signed-off-by: Yifan Zhang Signed-off-by: Will Deacon diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 8911850..9f210de 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1320,6 +1320,11 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, pmd = pmd_alloc_one(NULL, addr); if (!pmd) return -ENOMEM; + + pud_populate(NULL, pud, pmd); + arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); + + pmd += pmd_index(addr); } else #endif pmd = pmd_offset(pud, addr); @@ -1328,8 +1333,6 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, next = pmd_addr_end(addr, end); ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn, flags, stage); - pud_populate(NULL, pud, pmd); - arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); phys += next - addr; } while (pmd++, addr = next, addr < end); @@ -1349,6 +1352,11 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, pud = pud_alloc_one(NULL, addr); if (!pud) return -ENOMEM; + + pgd_populate(NULL, pgd, pud); + arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); + + pud += pud_index(addr); } else #endif pud = pud_offset(pgd, addr); @@ -1357,8 +1365,6 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, next = pud_addr_end(addr, end); ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys, flags, stage); - pgd_populate(NULL, pud, pgd); - arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); phys += next - addr; } while (pud++, addr = next, addr < end); -- cgit v0.10.2 From c9d09e2748eaa55cac2af274574baa6368189bc1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 4 Feb 2014 22:12:42 +0000 Subject: iommu/arm-smmu: really fix page table locking Commit a44a9791e778 ("iommu/arm-smmu: use mutex instead of spinlock for locking page tables") replaced the page table spinlock with a mutex, to allow blocking allocations to satisfy lazy mapping requests. Unfortunately, it turns out that IOMMU mappings are created from atomic context (e.g. spinlock held during a dma_map), so this change doesn't really help us in practice. This patch is a partial revert of the offending commit, bringing back the original spinlock but replacing our page table allocations for any levels below the pgd (which is allocated during domain init) with GFP_ATOMIC instead of GFP_KERNEL. Cc: Reported-by: Andreas Herrmann Signed-off-by: Will Deacon diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 9f210de..6eb54ae 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -393,7 +393,7 @@ struct arm_smmu_domain { struct arm_smmu_cfg root_cfg; phys_addr_t output_mask; - struct mutex lock; + spinlock_t lock; }; static DEFINE_SPINLOCK(arm_smmu_devices_lock); @@ -901,7 +901,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain) goto out_free_domain; smmu_domain->root_cfg.pgd = pgd; - mutex_init(&smmu_domain->lock); + spin_lock_init(&smmu_domain->lock); domain->priv = smmu_domain; return 0; @@ -1138,7 +1138,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) * Sanity check the domain. We don't currently support domains * that cross between different SMMU chains. */ - mutex_lock(&smmu_domain->lock); + spin_lock(&smmu_domain->lock); if (!smmu_domain->leaf_smmu) { /* Now that we have a master, we can finalise the domain */ ret = arm_smmu_init_domain_context(domain, dev); @@ -1153,7 +1153,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_name(device_smmu->dev)); goto err_unlock; } - mutex_unlock(&smmu_domain->lock); + spin_unlock(&smmu_domain->lock); /* Looks ok, so add the device to the domain */ master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); @@ -1163,7 +1163,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return arm_smmu_domain_add_master(smmu_domain, master); err_unlock: - mutex_unlock(&smmu_domain->lock); + spin_unlock(&smmu_domain->lock); return ret; } @@ -1210,7 +1210,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, if (pmd_none(*pmd)) { /* Allocate a new set of tables */ - pgtable_t table = alloc_page(PGALLOC_GFP); + pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO); if (!table) return -ENOMEM; @@ -1317,7 +1317,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, #ifndef __PAGETABLE_PMD_FOLDED if (pud_none(*pud)) { - pmd = pmd_alloc_one(NULL, addr); + pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); if (!pmd) return -ENOMEM; @@ -1349,7 +1349,7 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, #ifndef __PAGETABLE_PUD_FOLDED if (pgd_none(*pgd)) { - pud = pud_alloc_one(NULL, addr); + pud = (pud_t *)get_zeroed_page(GFP_ATOMIC); if (!pud) return -ENOMEM; @@ -1403,7 +1403,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, if (paddr & ~output_mask) return -ERANGE; - mutex_lock(&smmu_domain->lock); + spin_lock(&smmu_domain->lock); pgd += pgd_index(iova); end = iova + size; do { @@ -1419,7 +1419,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, } while (pgd++, iova != end); out_unlock: - mutex_unlock(&smmu_domain->lock); + spin_unlock(&smmu_domain->lock); /* Ensure new page tables are visible to the hardware walker */ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) -- cgit v0.10.2 From 6dd35f45b8dac827b6f9dd86f5aca6436cdd2410 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 5 Feb 2014 17:49:34 +0000 Subject: iommu/arm-smmu: fix table flushing during initial allocations Now that we populate page tables as we traverse them ("iommu/arm-smmu: fix pud/pmd entry fill sequence"), we need to ensure that we flush out our zeroed tables after initial allocation, to prevent speculative TLB fills using bogus data. This patch adds additional calls to arm_smmu_flush_pgtable during initial table allocation, and moves the dsb required by coherent table walkers into the helper. Cc: Signed-off-by: Will Deacon diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 6eb54ae..509f01f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -79,7 +79,6 @@ #define ARM_SMMU_PTE_CONT_SIZE (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES) #define ARM_SMMU_PTE_CONT_MASK (~(ARM_SMMU_PTE_CONT_SIZE - 1)) -#define ARM_SMMU_PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t)) /* Stage-1 PTE */ #define ARM_SMMU_PTE_AP_UNPRIV (((pteval_t)1) << 6) @@ -632,6 +631,28 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev) return IRQ_HANDLED; } +static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr, + size_t size) +{ + unsigned long offset = (unsigned long)addr & ~PAGE_MASK; + + + /* Ensure new page tables are visible to the hardware walker */ + if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) { + dsb(); + } else { + /* + * If the SMMU can't walk tables in the CPU caches, treat them + * like non-coherent DMA since we need to flush the new entries + * all the way out to memory. There's no possibility of + * recursion here as the SMMU table walker will not be wired + * through another SMMU. + */ + dma_map_page(smmu->dev, virt_to_page(addr), offset, size, + DMA_TO_DEVICE); + } +} + static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) { u32 reg; @@ -715,6 +736,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) } /* TTBR0 */ + arm_smmu_flush_pgtable(smmu, root_cfg->pgd, + PTRS_PER_PGD * sizeof(pgd_t)); reg = __pa(root_cfg->pgd); writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO); reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32; @@ -1177,23 +1200,6 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) arm_smmu_domain_remove_master(smmu_domain, master); } -static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr, - size_t size) -{ - unsigned long offset = (unsigned long)addr & ~PAGE_MASK; - - /* - * If the SMMU can't walk tables in the CPU caches, treat them - * like non-coherent DMA since we need to flush the new entries - * all the way out to memory. There's no possibility of recursion - * here as the SMMU table walker will not be wired through another - * SMMU. - */ - if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)) - dma_map_page(smmu->dev, virt_to_page(addr), offset, size, - DMA_TO_DEVICE); -} - static bool arm_smmu_pte_is_contiguous_range(unsigned long addr, unsigned long end) { @@ -1214,8 +1220,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, if (!table) return -ENOMEM; - arm_smmu_flush_pgtable(smmu, page_address(table), - ARM_SMMU_PTE_HWTABLE_SIZE); + arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE); if (!pgtable_page_ctor(table)) { __free_page(table); return -ENOMEM; @@ -1321,6 +1326,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, if (!pmd) return -ENOMEM; + arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE); pud_populate(NULL, pud, pmd); arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); @@ -1353,6 +1359,7 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, if (!pud) return -ENOMEM; + arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE); pgd_populate(NULL, pgd, pud); arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); @@ -1421,10 +1428,6 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, out_unlock: spin_unlock(&smmu_domain->lock); - /* Ensure new page tables are visible to the hardware walker */ - if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) - dsb(); - return ret; } -- cgit v0.10.2 From 57ca90f6800987ac274d7ba065ae6692cdf9bcd7 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 6 Feb 2014 14:59:05 +0000 Subject: iommu/arm-smmu: set CBARn.BPSHCFG to NSH for s1-s2-bypass contexts Whilst trying to bring-up an SMMUv2 implementation with the table walker plumbed into a coherent interconnect, I noticed that the memory transactions targetting the CPU caches from the SMMU were marked as outer-shareable instead of inner-shareable. After a bunch of digging, it seems that we actually need to program CBARn.BPSHCFG for s1-s2-bypass contexts to act as non-shareable in order for the shareability configured in the corresponding TTBCR not to be overridden with an outer-shareable attribute. Cc: Signed-off-by: Will Deacon diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 509f01f..0ae4dd3 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -190,6 +190,9 @@ #define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) #define CBAR_VMID_SHIFT 0 #define CBAR_VMID_MASK 0xff +#define CBAR_S1_BPSHCFG_SHIFT 8 +#define CBAR_S1_BPSHCFG_MASK 3 +#define CBAR_S1_BPSHCFG_NSH 3 #define CBAR_S1_MEMATTR_SHIFT 12 #define CBAR_S1_MEMATTR_MASK 0xf #define CBAR_S1_MEMATTR_WB 0xf @@ -671,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) if (smmu->version == 1) reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; - /* Use the weakest memory type, so it is overridden by the pte */ - if (stage1) - reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); - else + /* + * Use the weakest shareability/memory types, so they are + * overridden by the ttbcr/pte. + */ + if (stage1) { + reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) | + (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); + } else { reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT; + } writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); if (smmu->version > 1) { -- cgit v0.10.2 From d123cf82d339c5cc4ffe2a481e0caa23a501d4ac Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 4 Feb 2014 22:17:53 +0000 Subject: iommu/arm-smmu: fix compilation issue when !CONFIG_ARM_AMBA If !CONFIG_ARM_AMBA, we shouldn't try to register ourselves with the amba_bustype. Signed-off-by: Will Deacon diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0ae4dd3..6fe7922 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2004,8 +2004,10 @@ static int __init arm_smmu_init(void) if (!iommu_present(&platform_bus_type)) bus_set_iommu(&platform_bus_type, &arm_smmu_ops); +#ifdef CONFIG_ARM_AMBA if (!iommu_present(&amba_bustype)) bus_set_iommu(&amba_bustype, &arm_smmu_ops); +#endif return 0; } -- cgit v0.10.2 From a18b31dd537f51331b9cd357987a5e807bf3e8d1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 3 Feb 2014 10:35:35 +0100 Subject: m68k: Sort arch/m68k/include/asm/Kbuild Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index 7cc8c36..df4d46f 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -1,4 +1,3 @@ - generic-y += bitsperlong.h generic-y += clkdev.h generic-y += cputime.h @@ -6,6 +5,7 @@ generic-y += device.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += hash.h generic-y += hw_irq.h generic-y += ioctl.h generic-y += ipcbuf.h @@ -18,6 +18,7 @@ generic-y += local.h generic-y += mman.h generic-y += mutex.h generic-y += percpu.h +generic-y += preempt.h generic-y += resource.h generic-y += scatterlist.h generic-y += sections.h @@ -31,5 +32,3 @@ generic-y += trace_clock.h generic-y += types.h generic-y += word-at-a-time.h generic-y += xor.h -generic-y += preempt.h -generic-y += hash.h -- cgit v0.10.2 From 3067bab1cb6e45063c602a731b9341651c4f2ddb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 3 Feb 2014 10:38:39 +0100 Subject: m68k: Switch to asm-generic/barrier.h The generic nop() implementation is fine for m68k. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index df4d46f..6fb9e81 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -1,3 +1,4 @@ +generic-y += barrier.h generic-y += bitsperlong.h generic-y += clkdev.h generic-y += cputime.h diff --git a/arch/m68k/include/asm/barrier.h b/arch/m68k/include/asm/barrier.h deleted file mode 100644 index 15c5f77..0000000 --- a/arch/m68k/include/asm/barrier.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _M68K_BARRIER_H -#define _M68K_BARRIER_H - -#define nop() do { asm volatile ("nop"); barrier(); } while (0) - -#include - -#endif /* _M68K_BARRIER_H */ -- cgit v0.10.2 From 7247f55381d54645a1eb47588de51bb26fa7cb7a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 3 Feb 2014 15:07:13 +0100 Subject: m68k: Wire up sched_setattr and sched_getattr Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 014f288..9d38b73 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -4,7 +4,7 @@ #include -#define NR_syscalls 349 +#define NR_syscalls 351 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h index 625f321..b932dd4 100644 --- a/arch/m68k/include/uapi/asm/unistd.h +++ b/arch/m68k/include/uapi/asm/unistd.h @@ -354,5 +354,7 @@ #define __NR_process_vm_writev 346 #define __NR_kcmp 347 #define __NR_finit_module 348 +#define __NR_sched_setattr 349 +#define __NR_sched_getattr 350 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index 3f04ea0..b6223dc4 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -369,4 +369,6 @@ ENTRY(sys_call_table) .long sys_process_vm_writev .long sys_kcmp .long sys_finit_module + .long sys_sched_setattr + .long sys_sched_getattr /* 350 */ -- cgit v0.10.2 From 42eacf9e57b65ffa768af72cb7fc86cc6f6af042 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 10 Feb 2014 14:08:16 -0600 Subject: [CIFS] Fix cifsacl mounts over smb2 to not call cifs When mounting with smb2/smb3 (e.g. vers=2.1) and cifsacl mount option, it was trying to get the mode by querying the acl over the cifs rather than smb2 protocol. This patch makes that protocol independent and makes cifsacl smb2 mounts return a more intuitive operation not supported error (until we add a worker function for smb2_get_acl). Note that a previous patch fixed getxattr/setxattr for the CIFSACL xattr which would unconditionally call cifs_get_acl and cifs_set_acl (even when mounted smb2). I made those protocol independent last week (new protocol version operations "get_acl" and "set_acl" but did not add an smb2_get_acl and smb2_set_acl yet so those now simply return EOPNOTSUPP which at least is better than sending cifs requests on smb2 mount) The previous patches did not fix the one remaining case though ie mounting with "cifsacl" when getting mode from acl would unconditionally end up calling "cifs_get_acl_from_fid" even for smb2 - so made that protocol independent but to make that protocol independent had to make sure that the callers were passing the protocol independent handle structure (cifs_fid) instead of cifs specific _u16 network file handle (ie cifs_fid instead of cifs_fid->fid) Now mount with smb2 and cifsacl mount options will return EOPNOTSUP (instead of timing out) and a future patch will add smb2 operations (e.g. get_smb2_acl) to enable this. Signed-off-by: Steve French diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c819b0b..7ff866d 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, return rc; } -static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, - __u16 fid, u32 *pacllen) +struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, + const struct cifs_fid *cifsfid, u32 *pacllen) { struct cifs_ntsd *pntsd = NULL; unsigned int xid; @@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, return ERR_CAST(tlink); xid = get_xid(); - rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); + rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd, + pacllen); free_xid(xid); cifs_put_tlink(tlink); @@ -946,7 +947,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, if (!open_file) return get_cifs_acl_by_path(cifs_sb, path, pacllen); - pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen); + pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen); cifsFileInfo_put(open_file); return pntsd; } @@ -1006,19 +1007,31 @@ out: /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, - struct inode *inode, const char *path, const __u16 *pfid) + struct inode *inode, const char *path, + const struct cifs_fid *pfid) { struct cifs_ntsd *pntsd = NULL; u32 acllen = 0; int rc = 0; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct cifs_tcon *tcon; cifs_dbg(NOISY, "converting ACL to mode for %s\n", path); - if (pfid) - pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen); - else - pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + if (pfid && (tcon->ses->server->ops->get_acl_by_fid)) + pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid, + &acllen); + else if (tcon->ses->server->ops->get_acl) + pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path, + &acllen); + else { + cifs_put_tlink(tlink); + return -EOPNOTSUPP; + } /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ if (IS_ERR(pntsd)) { rc = PTR_ERR(pntsd); @@ -1030,6 +1043,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); } + cifs_put_tlink(tlink); + return rc; } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 86dc28c..cf32f03 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -398,6 +398,8 @@ struct smb_version_operations { const struct nls_table *, int); struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, const char *, u32 *); + struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *, + const struct cifs_fid *, u32 *); int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, int); }; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d00e09d..acc4ee8 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -151,7 +151,7 @@ extern struct inode *cifs_iget(struct super_block *sb, extern int cifs_get_inode_info(struct inode **inode, const char *full_path, FILE_ALL_INFO *data, struct super_block *sb, - int xid, const __u16 *fid); + int xid, const struct cifs_fid *fid); extern int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, unsigned int xid); @@ -162,11 +162,13 @@ extern int cifs_rename_pending_delete(const char *full_path, const unsigned int xid); extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, - const char *path, const __u16 *pfid); + const char *path, const struct cifs_fid *pfid); extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, kuid_t, kgid_t); extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, const char *, u32 *); +extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *, + const struct cifs_fid *, u32 *); extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, const char *, int); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index d3a6796..3db0c5f 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -378,7 +378,7 @@ cifs_create_get_file_info: xid); else { rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, - xid, &fid->netfid); + xid, fid); if (newinode) { if (server->ops->set_lease_key) server->ops->set_lease_key(newinode, fid); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index a301edb..290b496 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -244,7 +244,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, xid); else rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, - xid, &fid->netfid); + xid, fid); out: kfree(buf); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index be58b8f..aadc2b6 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -677,7 +677,7 @@ cgfi_exit: int cifs_get_inode_info(struct inode **inode, const char *full_path, FILE_ALL_INFO *data, struct super_block *sb, int xid, - const __u16 *fid) + const struct cifs_fid *fid) { bool validinum = false; __u16 srchflgs; diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index bfd66d8..526fb89 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -1073,6 +1073,7 @@ struct smb_version_operations smb1_operations = { #endif /* CIFS_XATTR */ #ifdef CONFIG_CIFS_ACL .get_acl = get_cifs_acl, + .get_acl_by_fid = get_cifs_acl_by_fid, .set_acl = set_cifs_acl, #endif /* CIFS_ACL */ }; -- cgit v0.10.2 From a65e0c6a7f14d80e87b82959c7333595cbd3e54e Mon Sep 17 00:00:00 2001 From: Ivan Khoronzhuk Date: Tue, 28 Jan 2014 12:49:15 +0200 Subject: clk: keystone: gate: fix clk_init_data initialization The clk_init_data struct is allocated in the stack. All members of this struct should be initialized before using otherwise it will lead to unpredictable situation as it can contain garbage. Ultimately the clk->flag field contains garbage. In my case it leads that flag CLK_IGNORE_UNUSED is set for most of clocks. As result a bunch of unused clocks cannot be disabled. So initialize flags in this structure too. Cc: Mike Turquette Signed-off-by: Ivan Khoronzhuk Signed-off-by: Santosh Shilimkar diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c index 17a5983..86f1e36 100644 --- a/drivers/clk/keystone/gate.c +++ b/drivers/clk/keystone/gate.c @@ -179,6 +179,7 @@ static struct clk *clk_register_psc(struct device *dev, init.name = name; init.ops = &clk_psc_ops; + init.flags = 0; init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); -- cgit v0.10.2 From 565bbdcd3b91523b4142587c00206302e091a23e Mon Sep 17 00:00:00 2001 From: Ivan Khoronzhuk Date: Mon, 10 Feb 2014 14:07:35 -0500 Subject: ARM: keystone: dts: fix clkvcp3 control register address The address for control regs in clkvcp3 node is not correct and should be 0x023500a8 instead of 0x0235000a8. This lead to few unexpected behaviors while clocks were turned of in absence of clk_ignore_unused Mike Turquette Signed-off-by: Ivan Khoronzhuk Signed-off-by: Santosh Shilimkar diff --git a/arch/arm/boot/dts/keystone-clocks.dtsi b/arch/arm/boot/dts/keystone-clocks.dtsi index 2363593..ef58d1c 100644 --- a/arch/arm/boot/dts/keystone-clocks.dtsi +++ b/arch/arm/boot/dts/keystone-clocks.dtsi @@ -612,7 +612,7 @@ clocks { compatible = "ti,keystone,psc-clock"; clocks = <&chipclk13>; clock-output-names = "vcp-3"; - reg = <0x0235000a8 0xb00>, <0x02350060 0x400>; + reg = <0x023500a8 0xb00>, <0x02350060 0x400>; reg-names = "control", "domain"; domain-id = <24>; }; -- cgit v0.10.2 From a699d65ec4ff82245d2c4fdfb8ed1d64776d756e Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 10 Feb 2014 16:28:52 -0500 Subject: SUNRPC: Don't create a gss auth cache unless rpc.gssd is running An infinite loop is caused when nfs4_establish_lease() fails with -EACCES. This causes nfs4_handle_reclaim_lease_error() to sleep a bit and resets the NFS4CLNT_LEASE_EXPIRED bit. This in turn causes nfs4_state_manager() to try and reestablished the lease, again, again, again... The problem is a valid RPCSEC_GSS client is being created when rpc.gssd is not running. Link: http://lkml.kernel.org/r/1392066375-16502-1-git-send-email-steved@redhat.com Fixes: 0ea9de0ea6a4 (sunrpc: turn warn_gssd() log message into a dprintk()) Reported-by: Steve Dickson Signed-off-by: Trond Myklebust diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 6c0513a..44a61e8 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -991,6 +991,8 @@ gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); if (gss_auth->service == 0) goto err_put_mech; + if (!gssd_running(gss_auth->net)) + goto err_put_mech; auth = &gss_auth->rpc_auth; auth->au_cslack = GSS_CRED_SLACK >> 2; auth->au_rslack = GSS_VERF_SLACK >> 2; -- cgit v0.10.2 From 902e6a0c7eba08ec978cea8304c6cb2ddce7b9dc Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 20 Dec 2013 10:46:52 +0100 Subject: ARM: pxa: Add dummy backlight power supply on Mitac Mio A701 Recent changes to the pwm-backlight driver have made the power supply mandatory. There is code in the regulator core to deal with situations where no regulator is specified and provide a dummy, but that works on DT-based boards only. The situation can be remedied by adding a dummy regulator during board initialization. Tested-by: Robert Jarzmik Signed-off-by: Thierry Reding Signed-off-by: Haojian Zhuang diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index f70583f..29997bd 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -714,6 +715,10 @@ static struct gpio global_gpios[] = { { GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" }, }; +static struct regulator_consumer_supply fixed_5v0_consumers[] = { + REGULATOR_SUPPLY("power", "pwm-backlight"), +}; + static void __init mioa701_machine_init(void) { int rc; @@ -753,6 +758,10 @@ static void __init mioa701_machine_init(void) pxa_set_i2c_info(&i2c_pdata); pxa27x_set_i2c_power_info(NULL); pxa_set_camera_info(&mioa701_pxacamera_platform_data); + + regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers, + ARRAY_SIZE(fixed_5v0_consumers), + 5000000); } static void mioa701_machine_exit(void) -- cgit v0.10.2 From 10c8562f932d89c030083e15f9279971ed637136 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 16 Jan 2014 15:39:17 +0100 Subject: ARM: dma-mapping: fix GFP_ATOMIC macro usage GFP_ATOMIC is not a single gfp flag, but a macro which expands to the other flags and LACK of __GFP_WAIT flag. To check if caller wanted to perform an atomic allocation, the code must test __GFP_WAIT flag presence. This patch fixes the issue introduced in v3.6-rc5 Signed-off-by: Marek Szyprowski CC: stable@vger.kernel.org diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 1a77450..11b3914 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1358,7 +1358,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, *handle = DMA_ERROR_CODE; size = PAGE_ALIGN(size); - if (gfp & GFP_ATOMIC) + if (!(gfp & __GFP_WAIT)) return __iommu_alloc_atomic(dev, size, handle); /* -- cgit v0.10.2 From c091c71ad2218fc50a07b3d1dab85783f3b77efd Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 24 Jan 2014 14:49:58 +0100 Subject: x86: dma-mapping: fix GFP_ATOMIC macro usage GFP_ATOMIC is not a single gfp flag, but a macro which expands to the other flags, where meaningful is the LACK of __GFP_WAIT flag. To check if caller wants to perform an atomic allocation, the code must test for a lack of the __GFP_WAIT flag. This patch fixes the issue introduced in v3.5-rc1. CC: stable@vger.kernel.org Signed-off-by: Marek Szyprowski diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 872079a..f7d0672 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -100,8 +100,10 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, flag |= __GFP_ZERO; again: page = NULL; - if (!(flag & GFP_ATOMIC)) + /* CMA can be used only in the context which permits sleeping */ + if (flag & __GFP_WAIT) page = dma_alloc_from_contiguous(dev, count, get_order(size)); + /* fallback */ if (!page) page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); if (!page) -- cgit v0.10.2 From 7d150c60f1a29c62e115e0ee2a5678400e724873 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Feb 2014 10:47:04 +0800 Subject: ASoC: fsl: make sure the regmap-mmio is actually enabled Since the Freescale SAI, ESAI and SPDIF are using the regmap-mmio, there needs a select of REGMAP_MMIO in the Kconfig to ensure that regmap-mmio is actually enabled. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f14..d0914c0 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,5 +1,6 @@ config SND_SOC_FSL_SAI tristate + select REGMAP_MMIO select SND_SOC_GENERIC_DMAENGINE_PCM config SND_SOC_FSL_SSI @@ -7,9 +8,11 @@ config SND_SOC_FSL_SSI config SND_SOC_FSL_SPDIF tristate + select REGMAP_MMIO config SND_SOC_FSL_ESAI tristate + select REGMAP_MMIO config SND_SOC_FSL_UTILS tristate @@ -204,7 +207,6 @@ config SND_SOC_IMX_SPDIF tristate "SoC Audio support for i.MX boards with S/PDIF" select SND_SOC_IMX_PCM_DMA select SND_SOC_FSL_SPDIF - select REGMAP_MMIO help SoC Audio support for i.MX boards with S/PDIF Say Y if you want to add support for SoC audio on an i.MX board with -- cgit v0.10.2 From 32769814d54a5a360b83811b4039c776ec953c71 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 11 Feb 2014 12:27:19 +0200 Subject: mac80211: fix sched_scan restart on recovery In case we were not suspended, the reconfig function returns without configuring the scheduled scan. Signed-off-by: Arik Nemtsov Signed-off-by: Johannes Berg diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 676dc09..1d1bb70 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1741,6 +1741,26 @@ int ieee80211_reconfig(struct ieee80211_local *local) IEEE80211_QUEUE_STOP_REASON_SUSPEND); /* + * Reconfigure sched scan if it was interrupted by FW restart or + * suspend. + */ + mutex_lock(&local->mtx); + sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, + lockdep_is_held(&local->mtx)); + if (sched_scan_sdata && local->sched_scan_req) + /* + * Sched scan stopped, but we don't want to report it. Instead, + * we're trying to reschedule. + */ + if (__ieee80211_request_sched_scan_start(sched_scan_sdata, + local->sched_scan_req)) + sched_scan_stopped = true; + mutex_unlock(&local->mtx); + + if (sched_scan_stopped) + cfg80211_sched_scan_stopped(local->hw.wiphy); + + /* * If this is for hw restart things are still running. * We may want to change that later, however. */ @@ -1768,26 +1788,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) WARN_ON(1); #endif - /* - * Reconfigure sched scan if it was interrupted by FW restart or - * suspend. - */ - mutex_lock(&local->mtx); - sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, - lockdep_is_held(&local->mtx)); - if (sched_scan_sdata && local->sched_scan_req) - /* - * Sched scan stopped, but we don't want to report it. Instead, - * we're trying to reschedule. - */ - if (__ieee80211_request_sched_scan_start(sched_scan_sdata, - local->sched_scan_req)) - sched_scan_stopped = true; - mutex_unlock(&local->mtx); - - if (sched_scan_stopped) - cfg80211_sched_scan_stopped(local->hw.wiphy); - return 0; } -- cgit v0.10.2 From c368ddaa9ad79fdffde4756804321feba6725c75 Mon Sep 17 00:00:00 2001 From: Eytan Lifshitz Date: Thu, 6 Feb 2014 21:01:32 +0200 Subject: mac80211: fix memory leak In case ieee80211_prep_connection() fails to dereference sdata->vif.chanctx_conf, the function returns and doesn't free new_sta. fixed. Signed-off-by: Eytan Lifshitz Signed-off-by: Johannes Berg diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fc1d824..57d5482 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3753,6 +3753,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (WARN_ON(!chanctx_conf)) { rcu_read_unlock(); + sta_info_free(local, new_sta); return -EINVAL; } rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); -- cgit v0.10.2 From 8955f28dba9edb04305504a06d7f395ca3b32904 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Fri, 7 Feb 2014 23:37:16 +0100 Subject: ASoC: wm8995: Remove unused pointer in hp_supply_event() Remove unused driver data pointer 'wm8995' in function hp_supply_event(). Detected by Coverity: CID 141181. Signed-off-by: Christian Engelmayer Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 4300caf..403e1db 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -561,10 +561,8 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec; - struct wm8995_priv *wm8995; codec = w->codec; - wm8995 = snd_soc_codec_get_drvdata(codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: -- cgit v0.10.2 From dfd72a68aa0f6cf87575f3181319bde8a2d4c01b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 30 Jan 2014 18:14:05 +0100 Subject: ASoC: cs42l51: add Device Tree binding to cs42l51 This commit adds a trivial Device Tree binding to the I2C-based cs42l51 sound codec, so that it can be used from Device Tree based platforms. Signed-off-by: Thomas Petazzoni Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 1a1ac2e..f47e56b 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -18,6 +18,7 @@ atmel,24c02 i2c serial eeprom (24cxx) atmel,at97sc3204t i2c trusted platform module (TPM) capella,cm32181 CM32181: Ambient Light Sensor catalyst,24c32 i2c serial eeprom +cirrus,cs42l51 Cirrus Logic CS42L51 audio codec dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock dallas,ds1338 I2C RTC with 56-Byte NV RAM dallas,ds1339 I2C Serial Real-Time Clock diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea83..824cdf4 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -600,10 +600,17 @@ static const struct i2c_device_id cs42l51_id[] = { }; MODULE_DEVICE_TABLE(i2c, cs42l51_id); +static const struct of_device_id cs42l51_of_match[] = { + { .compatible = "cirrus,cs42l51", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs42l51_of_match); + static struct i2c_driver cs42l51_i2c_driver = { .driver = { .name = "cs42l51-codec", .owner = THIS_MODULE, + .of_match_table = cs42l51_of_match, }, .id_table = cs42l51_id, .probe = cs42l51_i2c_probe, -- cgit v0.10.2 From 33529ec94f7cb25f6c98908eefde42a1e8d4e67a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Feb 2014 16:01:28 -0200 Subject: ASoC: fsl_esai: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index d0c72ed..f55341e 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -431,17 +431,26 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int fsl_esai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + int ret; struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); /* * Some platforms might use the same bit to gate all three or two of * clocks, so keep all clocks open/close at the same time for safety */ - clk_prepare_enable(esai_priv->coreclk); - if (!IS_ERR(esai_priv->extalclk)) - clk_prepare_enable(esai_priv->extalclk); - if (!IS_ERR(esai_priv->fsysclk)) - clk_prepare_enable(esai_priv->fsysclk); + ret = clk_prepare_enable(esai_priv->coreclk); + if (ret) + return ret; + if (!IS_ERR(esai_priv->extalclk)) { + ret = clk_prepare_enable(esai_priv->extalclk); + if (ret) + goto err_extalck; + } + if (!IS_ERR(esai_priv->fsysclk)) { + ret = clk_prepare_enable(esai_priv->fsysclk); + if (ret) + goto err_fsysclk; + } if (!dai->active) { /* Reset Port C */ @@ -463,6 +472,14 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, } return 0; + +err_fsysclk: + if (!IS_ERR(esai_priv->extalclk)) + clk_disable_unprepare(esai_priv->extalclk); +err_extalck: + clk_disable_unprepare(esai_priv->coreclk); + + return ret; } static int fsl_esai_hw_params(struct snd_pcm_substream *substream, -- cgit v0.10.2 From 06ea0bfe6e6043cb56a78935a19f6f8ebc636226 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 11 Feb 2014 09:15:54 -0500 Subject: SUNRPC: Fix races in xs_nospace() When a send failure occurs due to the socket being out of buffer space, we call xs_nospace() in order to have the RPC task wait until the socket has drained enough to make it worth while trying again. The current patch fixes a race in which the socket is drained before we get round to setting up the machinery in xs_nospace(), and which is reported to cause hangs. Link: http://lkml.kernel.org/r/20140210170315.33dfc621@notabene.brown Fixes: a9a6b52ee1ba (SUNRPC: Don't start the retransmission timer...) Reported-by: Neil Brown Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 817a1e5..0addefc 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task) struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); + struct sock *sk = transport->inet; int ret = -EAGAIN; dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", @@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task) * window size */ set_bit(SOCK_NOSPACE, &transport->sock->flags); - transport->inet->sk_write_pending++; + sk->sk_write_pending++; /* ...and wait for more buffer space */ xprt_wait_for_buffer_space(task, xs_nospace_callback); } @@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task) } spin_unlock_bh(&xprt->transport_lock); + + /* Race breaker in case memory is freed before above code is called */ + sk->sk_write_space(sk); return ret; } -- cgit v0.10.2 From 0ab02ca8f887908152d1a96db5130fc661d36a1e Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 11 Feb 2014 16:05:46 +0800 Subject: cgroup: protect modifications to cgroup_idr with cgroup_mutex Setup cgroupfs like this: # mount -t cgroup -o cpuacct xxx /cgroup # mkdir /cgroup/sub1 # mkdir /cgroup/sub2 Then run these two commands: # for ((; ;)) { mkdir /cgroup/sub1/tmp && rmdir /mnt/sub1/tmp; } & # for ((; ;)) { mkdir /cgroup/sub2/tmp && rmdir /mnt/sub2/tmp; } & After seconds you may see this warning: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 25243 at lib/idr.c:527 sub_remove+0x87/0x1b0() idr_remove called for id=6 which is not allocated. ... Call Trace: [] dump_stack+0x7a/0x96 [] warn_slowpath_common+0x8c/0xc0 [] warn_slowpath_fmt+0x46/0x50 [] sub_remove+0x87/0x1b0 [] ? css_killed_work_fn+0x32/0x1b0 [] idr_remove+0x25/0xd0 [] cgroup_destroy_css_killed+0x5b/0xc0 [] css_killed_work_fn+0x130/0x1b0 [] process_one_work+0x26c/0x550 [] worker_thread+0x12e/0x3b0 [] kthread+0xe6/0xf0 [] ret_from_fork+0x7c/0xb0 ---[ end trace 2d1577ec10cf80d0 ]--- It's because allocating/removing cgroup ID is not properly synchronized. The bug was introduced when we converted cgroup_ida to cgroup_idr. While synchronization is already done inside ida_simple_{get,remove}(), users are responsible for concurrent calls to idr_{alloc,remove}(). tj: Refreshed on top of b58c89986a77 ("cgroup: fix error return from cgroup_create()"). Fixes: 4e96ee8e981b ("cgroup: convert cgroup_ida to cgroup_idr") Cc: #3.12+ Reported-by: Michal Hocko Signed-off-by: Li Zefan Signed-off-by: Tejun Heo diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 5c09759..9450f02 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -166,6 +166,8 @@ struct cgroup { * * The ID of the root cgroup is always 0, and a new cgroup * will be assigned with a smallest available ID. + * + * Allocating/Removing ID must be protected by cgroup_mutex. */ int id; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3edf716..52719ce 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -886,7 +886,9 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) * per-subsystem and moved to css->id so that lookups are * successful until the target css is released. */ + mutex_lock(&cgroup_mutex); idr_remove(&cgrp->root->cgroup_idr, cgrp->id); + mutex_unlock(&cgroup_mutex); cgrp->id = -1; call_rcu(&cgrp->rcu_head, cgroup_free_rcu); @@ -4168,16 +4170,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, rcu_assign_pointer(cgrp->name, name); /* - * Temporarily set the pointer to NULL, so idr_find() won't return - * a half-baked cgroup. - */ - cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); - if (cgrp->id < 0) { - err = -ENOMEM; - goto err_free_name; - } - - /* * Only live parents can have children. Note that the liveliness * check isn't strictly necessary because cgroup_mkdir() and * cgroup_rmdir() are fully synchronized by i_mutex; however, do it @@ -4186,7 +4178,17 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, */ if (!cgroup_lock_live_group(parent)) { err = -ENODEV; - goto err_free_id; + goto err_free_name; + } + + /* + * Temporarily set the pointer to NULL, so idr_find() won't return + * a half-baked cgroup. + */ + cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); + if (cgrp->id < 0) { + err = -ENOMEM; + goto err_unlock; } /* Grab a reference on the superblock so the hierarchy doesn't @@ -4218,7 +4220,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, */ err = cgroup_create_file(dentry, S_IFDIR | mode, sb); if (err < 0) - goto err_unlock; + goto err_free_id; lockdep_assert_held(&dentry->d_inode->i_mutex); cgrp->serial_nr = cgroup_serial_nr_next++; @@ -4254,12 +4256,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, return 0; -err_unlock: - mutex_unlock(&cgroup_mutex); - /* Release the reference count that we took on the superblock */ - deactivate_super(sb); err_free_id: idr_remove(&root->cgroup_idr, cgrp->id); + /* Release the reference count that we took on the superblock */ + deactivate_super(sb); +err_unlock: + mutex_unlock(&cgroup_mutex); err_free_name: kfree(rcu_dereference_raw(cgrp->name)); err_free_cgrp: -- cgit v0.10.2 From 631f8e94700ac776432826400403703f0bfe063b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 18:26:07 +0000 Subject: ASoC: tobermory: Stop the FLL if we fail to switch SYSCLK to it Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index f21ff60..1807b75 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -44,6 +44,8 @@ static int tobermory_set_bias_level(struct snd_soc_card *card, SND_SOC_CLOCK_IN); if (ret < 0) { pr_err("Failed to set SYSCLK: %d\n", ret); + snd_soc_dai_set_pll(codec_dai, WM8962_FLL, + 0, 0, 0); return ret; } } -- cgit v0.10.2 From 0b166d8ef686ea990f830e23f7de0590c01ed860 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 10 Feb 2014 22:25:31 +0100 Subject: ASoC: smdk_wm8994: Fix typo "wm8894" Signed-off-by: Paul Bolle Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index d38ae98..682eb4f 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -202,7 +202,7 @@ static int smdk_audio_probe(struct platform_device *pdev) static struct platform_driver smdk_audio_driver = { .driver = { - .name = "smdk-audio-wm8894", + .name = "smdk-audio-wm8994", .owner = THIS_MODULE, .of_match_table = of_match_ptr(samsung_wm8994_of_match), .pm = &snd_soc_pm_ops, -- cgit v0.10.2 From 628356791b04ea988fee070f66a748a823d001bb Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 11 Feb 2014 13:56:54 -0500 Subject: SUNRPC: Fix potential memory scribble in xprt_free_bc_request() The call to xprt_free_allocation() will call list_del() on req->rq_bc_pa_list, which is not attached to a list. This patch moves the list_del() out of xprt_free_allocation() and into those callers that need it. Signed-off-by: Trond Myklebust diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 890a299..e860d4f 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c @@ -64,7 +64,6 @@ static void xprt_free_allocation(struct rpc_rqst *req) free_page((unsigned long)xbufp->head[0].iov_base); xbufp = &req->rq_snd_buf; free_page((unsigned long)xbufp->head[0].iov_base); - list_del(&req->rq_bc_pa_list); kfree(req); } @@ -168,8 +167,10 @@ out_free: /* * Memory allocation failed, free the temporary list */ - list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) + list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) { + list_del(&req->rq_bc_pa_list); xprt_free_allocation(req); + } dprintk("RPC: setup backchannel transport failed\n"); return -ENOMEM; @@ -198,6 +199,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) xprt_dec_alloc_count(xprt, max_reqs); list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { dprintk("RPC: req=%p\n", req); + list_del(&req->rq_bc_pa_list); xprt_free_allocation(req); if (--max_reqs == 0) break; -- cgit v0.10.2 From 5be736442ed94217c6521ae0c948abab995f281f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:21:16 +0000 Subject: ASoC: cs42l51: Don't log if we fail to allocate memory The VM subsystem already logs quite loudly if we run out of memory so don't bother here. Signed-off-by: Mark Brown Acked-by: Brian Austin diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 824cdf4..b11079b 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -574,10 +574,8 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client, cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), GFP_KERNEL); - if (!cs42l51) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); + if (!cs42l51) return -ENOMEM; - } i2c_set_clientdata(i2c_client, cs42l51); cs42l51->control_type = SND_SOC_I2C; -- cgit v0.10.2 From da071489762499a3635cb3563d32792cea20c087 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:24:31 +0000 Subject: ASoC: cs42l51: Convert to direct regmap API usage As part of phasing out the ASoC level register I/O code (which is now just a thin wrapper around regmap anyway) convert the cs42l51 driver to use the regmap API directly. We now no longer initialise the cache from hardware at startup, the regmap caches are smart enough to understand which registers are actually cached and read on demand. This should have no visible effect on the system. Signed-off-by: Mark Brown Acked-by: Brian Austin diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index b11079b..e53c871 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "cs42l51.h" @@ -40,7 +41,6 @@ enum master_slave_mode { }; struct cs42l51_private { - enum snd_soc_control_type control_type; unsigned int mclk; unsigned int audio_mode; /* The mode (I2S or left-justified) */ enum master_slave_mode func; @@ -52,24 +52,6 @@ struct cs42l51_private { SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) -static int cs42l51_fill_cache(struct snd_soc_codec *codec) -{ - u8 *cache = codec->reg_cache + 1; - struct i2c_client *i2c_client = to_i2c_client(codec->dev); - s32 length; - - length = i2c_smbus_read_i2c_block_data(i2c_client, - CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache); - if (length != CS42L51_NUMREGS) { - dev_err(&i2c_client->dev, - "I2C read failure, addr=0x%x (ret=%d vs %d)\n", - i2c_client->addr, length, CS42L51_NUMREGS); - return -EIO; - } - - return 0; -} - static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -508,13 +490,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec) struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); int ret, reg; - ret = cs42l51_fill_cache(codec); - if (ret < 0) { - dev_err(codec->dev, "failed to fill register cache\n"); - return ret; - } - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -538,8 +514,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_probe, - .reg_cache_size = CS42L51_NUMREGS + 1, - .reg_word_size = sizeof(u8), .controls = cs42l51_snd_controls, .num_controls = ARRAY_SIZE(cs42l51_snd_controls), @@ -549,28 +523,46 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), }; +static const struct regmap_config cs42l51_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = CS42L51_CHARGE_FREQ, + .cache_type = REGCACHE_RBTREE, +}; + static int cs42l51_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct cs42l51_private *cs42l51; + struct regmap *regmap; + unsigned int val; int ret; + regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c_client->dev, "Failed to create regmap: %d\n", + ret); + return ret; + } + /* Verify that we have a CS42L51 */ - ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); + ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); if (ret < 0) { dev_err(&i2c_client->dev, "failed to read I2C\n"); goto error; } - if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && - (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { - dev_err(&i2c_client->dev, "Invalid chip id\n"); + if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && + (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { + dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val); ret = -ENODEV; goto error; } dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", - ret & 7); + val & 7); cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), GFP_KERNEL); @@ -578,7 +570,6 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client, return -ENOMEM; i2c_set_clientdata(i2c_client, cs42l51); - cs42l51->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c_client->dev, &soc_codec_device_cs42l51, &cs42l51_dai, 1); -- cgit v0.10.2 From 78c51bc6475982a843947a556853affd2c360b19 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:51:58 +0000 Subject: ASoC: ak4671: Convert to table based control init Saves code and adds error handling. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 25bdf6a..456bd0a 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -628,9 +628,6 @@ static int ak4671_probe(struct snd_soc_codec *codec) return ret; } - snd_soc_add_codec_controls(codec, ak4671_snd_controls, - ARRAY_SIZE(ak4671_snd_controls)); - ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return ret; @@ -646,6 +643,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .probe = ak4671_probe, .remove = ak4671_remove, .set_bias_level = ak4671_set_bias_level, + .controls = ak4671_snd_controls, + .num_controls = ARRAY_SIZE(ak4671_snd_controls), .reg_cache_size = AK4671_CACHEREGNUM, .reg_word_size = sizeof(u8), .reg_cache_default = ak4671_reg, -- cgit v0.10.2 From 7ac5a47886ae4b211f08657d0d06027285eda2d0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:53:25 +0000 Subject: ASoC: ak4671: Convert to direct regmap API usage This helps us remove the ASoC level I/O functionality which is now just a thin wrapper around regmap. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 456bd0a..743bbe3 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,104 +24,99 @@ #include "ak4671.h" -/* codec private data */ -struct ak4671_priv { - enum snd_soc_control_type control_type; -}; - /* ak4671 register cache & default register settings */ -static const u8 ak4671_reg[AK4671_CACHEREGNUM] = { - 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ - 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */ - 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */ - 0x02, /* AK4671_FORMAT_SELECT (0x03) */ - 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ - 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ - 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ - 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ - 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ - 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ - 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ - 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ - 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ - 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ - 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ - 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ - 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ - 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ - 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ - 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */ - 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */ - 0x02, /* AK4671_MODE_CONTROL1 (0x18) */ - 0x01, /* AK4671_MODE_CONTROL2 (0x19) */ - 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ - 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ - 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ - 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ - 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ - 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ - 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ - 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ - 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */ - 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */ - 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */ - 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */ - 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */ - 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */ - 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ - 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ - 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ - 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ - 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ - 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ - 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ - 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ - 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ - 0x00, /* this register not used */ - 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */ - 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */ - 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */ - 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */ - 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */ - 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */ - 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */ - 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */ - 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */ - 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */ - 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */ - 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */ - 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */ - 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */ - 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */ - 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */ - 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */ - 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */ - 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */ - 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */ - 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */ - 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */ - 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */ - 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */ - 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */ - 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */ - 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */ - 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */ - 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */ - 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */ - 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ - 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ - 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ - 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */ - 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */ - 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */ - 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ - 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ - 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ - 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */ +static const struct reg_default ak4671_reg_defaults[] = { + { 0x00, 0x00 }, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ + { 0x01, 0xf6 }, /* AK4671_PLL_MODE_SELECT0 (0x01) */ + { 0x02, 0x00 }, /* AK4671_PLL_MODE_SELECT1 (0x02) */ + { 0x03, 0x02 }, /* AK4671_FORMAT_SELECT (0x03) */ + { 0x04, 0x00 }, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ + { 0x05, 0x55 }, /* AK4671_MIC_AMP_GAIN (0x05) */ + { 0x06, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ + { 0x07, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ + { 0x08, 0xb5 }, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ + { 0x09, 0x00 }, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ + { 0x0a, 0x00 }, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ + { 0x0b, 0x00 }, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ + { 0x0c, 0x00 }, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ + { 0x0d, 0x00 }, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ + { 0x0e, 0x00 }, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ + { 0x0f, 0x00 }, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ + { 0x10, 0x00 }, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ + { 0x11, 0x80 }, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ + { 0x12, 0x91 }, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ + { 0x13, 0x91 }, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ + { 0x14, 0xe1 }, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ + { 0x15, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ + { 0x16, 0x00 }, /* AK4671_ALC_TIMER_SELECT (0x16) */ + { 0x17, 0x00 }, /* AK4671_ALC_MODE_CONTROL (0x17) */ + { 0x18, 0x02 }, /* AK4671_MODE_CONTROL1 (0x18) */ + { 0x19, 0x01 }, /* AK4671_MODE_CONTROL2 (0x19) */ + { 0x1a, 0x18 }, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ + { 0x1b, 0x18 }, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ + { 0x1c, 0x00 }, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ + { 0x1d, 0x02 }, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ + { 0x1e, 0x00 }, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ + { 0x1f, 0x00 }, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ + { 0x20, 0x00 }, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ + { 0x21, 0x00 }, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ + { 0x22, 0x00 }, /* AK4671_EQ_COEFFICIENT0 (0x22) */ + { 0x23, 0x00 }, /* AK4671_EQ_COEFFICIENT1 (0x23) */ + { 0x24, 0x00 }, /* AK4671_EQ_COEFFICIENT2 (0x24) */ + { 0x25, 0x00 }, /* AK4671_EQ_COEFFICIENT3 (0x25) */ + { 0x26, 0x00 }, /* AK4671_EQ_COEFFICIENT4 (0x26) */ + { 0x27, 0x00 }, /* AK4671_EQ_COEFFICIENT5 (0x27) */ + { 0x28, 0xa9 }, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ + { 0x29, 0x1f }, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ + { 0x2a, 0xad }, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ + { 0x2b, 0x20 }, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ + { 0x2c, 0x00 }, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ + { 0x2d, 0x00 }, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ + { 0x2e, 0x00 }, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ + { 0x2f, 0x00 }, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ + { 0x30, 0x00 }, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ + + { 0x32, 0x00 }, /* AK4671_E1_COEFFICIENT0 (0x32) */ + { 0x33, 0x00 }, /* AK4671_E1_COEFFICIENT1 (0x33) */ + { 0x34, 0x00 }, /* AK4671_E1_COEFFICIENT2 (0x34) */ + { 0x35, 0x00 }, /* AK4671_E1_COEFFICIENT3 (0x35) */ + { 0x36, 0x00 }, /* AK4671_E1_COEFFICIENT4 (0x36) */ + { 0x37, 0x00 }, /* AK4671_E1_COEFFICIENT5 (0x37) */ + { 0x38, 0x00 }, /* AK4671_E2_COEFFICIENT0 (0x38) */ + { 0x39, 0x00 }, /* AK4671_E2_COEFFICIENT1 (0x39) */ + { 0x3a, 0x00 }, /* AK4671_E2_COEFFICIENT2 (0x3a) */ + { 0x3b, 0x00 }, /* AK4671_E2_COEFFICIENT3 (0x3b) */ + { 0x3c, 0x00 }, /* AK4671_E2_COEFFICIENT4 (0x3c) */ + { 0x3d, 0x00 }, /* AK4671_E2_COEFFICIENT5 (0x3d) */ + { 0x3e, 0x00 }, /* AK4671_E3_COEFFICIENT0 (0x3e) */ + { 0x3f, 0x00 }, /* AK4671_E3_COEFFICIENT1 (0x3f) */ + { 0x40, 0x00 }, /* AK4671_E3_COEFFICIENT2 (0x40) */ + { 0x41, 0x00 }, /* AK4671_E3_COEFFICIENT3 (0x41) */ + { 0x42, 0x00 }, /* AK4671_E3_COEFFICIENT4 (0x42) */ + { 0x43, 0x00 }, /* AK4671_E3_COEFFICIENT5 (0x43) */ + { 0x44, 0x00 }, /* AK4671_E4_COEFFICIENT0 (0x44) */ + { 0x45, 0x00 }, /* AK4671_E4_COEFFICIENT1 (0x45) */ + { 0x46, 0x00 }, /* AK4671_E4_COEFFICIENT2 (0x46) */ + { 0x47, 0x00 }, /* AK4671_E4_COEFFICIENT3 (0x47) */ + { 0x48, 0x00 }, /* AK4671_E4_COEFFICIENT4 (0x48) */ + { 0x49, 0x00 }, /* AK4671_E4_COEFFICIENT5 (0x49) */ + { 0x4a, 0x00 }, /* AK4671_E5_COEFFICIENT0 (0x4a) */ + { 0x4b, 0x00 }, /* AK4671_E5_COEFFICIENT1 (0x4b) */ + { 0x4c, 0x00 }, /* AK4671_E5_COEFFICIENT2 (0x4c) */ + { 0x4d, 0x00 }, /* AK4671_E5_COEFFICIENT3 (0x4d) */ + { 0x4e, 0x00 }, /* AK4671_E5_COEFFICIENT4 (0x4e) */ + { 0x4f, 0x00 }, /* AK4671_E5_COEFFICIENT5 (0x4f) */ + { 0x50, 0x88 }, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ + { 0x51, 0x88 }, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ + { 0x52, 0x08 }, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ + { 0x53, 0x00 }, /* AK4671_PCM_IF_CONTROL0 (0x53) */ + { 0x54, 0x00 }, /* AK4671_PCM_IF_CONTROL1 (0x54) */ + { 0x55, 0x00 }, /* AK4671_PCM_IF_CONTROL2 (0x55) */ + { 0x56, 0x18 }, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ + { 0x57, 0x18 }, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ + { 0x58, 0x00 }, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ + { 0x59, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ + { 0x5a, 0x00 }, /* AK4671_SAR_ADC_CONTROL (0x5a) */ }; /* @@ -619,10 +615,9 @@ static struct snd_soc_dai_driver ak4671_dai = { static int ak4671_probe(struct snd_soc_codec *codec) { - struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -645,28 +640,34 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .set_bias_level = ak4671_set_bias_level, .controls = ak4671_snd_controls, .num_controls = ARRAY_SIZE(ak4671_snd_controls), - .reg_cache_size = AK4671_CACHEREGNUM, - .reg_word_size = sizeof(u8), - .reg_cache_default = ak4671_reg, .dapm_widgets = ak4671_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), .dapm_routes = ak4671_intercon, .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), }; +static const struct regmap_config ak4671_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = AK4671_SAR_ADC_CONTROL, + .reg_defaults = ak4671_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(ak4671_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int ak4671_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ak4671_priv *ak4671; + struct regmap *regmap; int ret; - ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv), - GFP_KERNEL); - if (ak4671 == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, ak4671); - ak4671->control_type = SND_SOC_I2C; + regmap = devm_regmap_init_i2c(client, &ak4671_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&client->dev, "Failed to create regmap: %d\n", ret); + return ret; + } ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_ak4671, &ak4671_dai, 1); diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index 61cb7ab..394a34d 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h @@ -105,8 +105,6 @@ #define AK4671_DIGITAL_MIXING_CONTROL2 0x59 #define AK4671_SAR_ADC_CONTROL 0x5a -#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1) - /* Bitfield Definitions */ /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ -- cgit v0.10.2 From 753b1ad4a281b0663329409d410243e91825c323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 11 Feb 2014 19:52:05 +0200 Subject: drm/i915: Add intel_ring_cachline_align() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_ring_cachline_align() emits MI_NOOPs until the ring tail is aligned to a cacheline boundary. Cc: Bjoern C Cc: Alexandru DAMIAN Cc: Enrico Tagliavini Suggested-by: Chris Wilson Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Cc: stable@vger.kernel.org (prereq for the next patch) Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b7f1742..31b36c5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1653,6 +1653,27 @@ int intel_ring_begin(struct intel_ring_buffer *ring, return 0; } +/* Align the ring tail to a cacheline boundary */ +int intel_ring_cacheline_align(struct intel_ring_buffer *ring) +{ + int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t); + int ret; + + if (num_dwords == 0) + return 0; + + ret = intel_ring_begin(ring, num_dwords); + if (ret) + return ret; + + while (num_dwords--) + intel_ring_emit(ring, MI_NOOP); + + intel_ring_advance(ring); + + return 0; +} + void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) { struct drm_i915_private *dev_priv = ring->dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 71a73f4..0b243ce 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -233,6 +233,7 @@ intel_write_status_page(struct intel_ring_buffer *ring, void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); +int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring); static inline void intel_ring_emit(struct intel_ring_buffer *ring, u32 data) { -- cgit v0.10.2 From f66fab8e1cd6b3127ba4c5c0d11539fbe1de1e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 11 Feb 2014 19:52:06 +0200 Subject: drm/i915: Prevent MI_DISPLAY_FLIP straddling two cachelines on IVB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to BSpec the entire MI_DISPLAY_FLIP packet must be contained in a single cacheline. Make sure that happens. v2: Use intel_ring_begin_cacheline_safe() v3: Use intel_ring_cacheline_align() (Chris) Cc: Bjoern C Cc: Alexandru DAMIAN Cc: Enrico Tagliavini Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74053 Signed-off-by: Ville Syrjälä Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40a9338..88ad172 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8586,6 +8586,20 @@ static int intel_gen7_queue_flip(struct drm_device *dev, if (ring->id == RCS) len += 6; + /* + * BSpec MI_DISPLAY_FLIP for IVB: + * "The full packet must be contained within the same cache line." + * + * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same + * cacheline, if we ever start emitting more commands before + * the MI_DISPLAY_FLIP we may need to first emit everything else, + * then do the cacheline alignment, and finally emit the + * MI_DISPLAY_FLIP. + */ + ret = intel_ring_cacheline_align(ring); + if (ret) + goto err_unpin; + ret = intel_ring_begin(ring, len); if (ret) goto err_unpin; -- cgit v0.10.2 From 6e60163b9db6d0b203ffc0f0b8ef5a5f1c9d3fb8 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 9 Feb 2014 14:01:33 +0100 Subject: drm/tegra: fix typo 'CONFIG_TEGRA_DRM_FBDEV' Signed-off-by: Paul Bolle Signed-off-by: Thierry Reding diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 88a5290..c715947 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -104,7 +104,7 @@ static void tegra_drm_context_free(struct tegra_drm_context *context) static void tegra_drm_lastclose(struct drm_device *drm) { -#ifdef CONFIG_TEGRA_DRM_FBDEV +#ifdef CONFIG_DRM_TEGRA_FBDEV struct tegra_drm *tegra = drm->dev_private; tegra_fbdev_restore_mode(tegra->fbdev); -- cgit v0.10.2 From 89e6e8c85f21555a763d0e47841b515ede6278d1 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Tue, 7 Jan 2014 21:03:06 +0100 Subject: gpu: host1x: do not check previously handled gathers When patching gathers, we don't need to check against gathers with lower indices than the current one, as they are guaranteed to already have been handled. Signed-off-by: Erik Faye-Lund Acked-By: Terje Bergstrom Signed-off-by: Thierry Reding diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index 1146e3b..112f27e 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -538,7 +538,7 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev) g->base = job->gather_addr_phys[i]; - for (j = 0; j < job->num_gathers; j++) + for (j = i + 1; j < job->num_gathers; j++) if (job->gathers[j].bo == g->bo) job->gathers[j].handled = true; -- cgit v0.10.2 From b18915379071b31ea819a36ca67761620decba06 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 11 Feb 2014 21:12:27 +0400 Subject: drm/tegra: Add guard to avoid double disable/enable of RGB outputs Add guard to check whether RGB output is already enabled in the way it's done for HDMI output. Fixes possible hang on trying to disable output twice (first time during driver probe and second on fb registering). Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 338f7f6..0266fb4 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -15,6 +15,7 @@ struct tegra_rgb { struct tegra_output output; struct tegra_dc *dc; + bool enabled; struct clk *clk_parent; struct clk *clk; @@ -89,6 +90,9 @@ static int tegra_output_rgb_enable(struct tegra_output *output) struct tegra_rgb *rgb = to_rgb(output); unsigned long value; + if (rgb->enabled) + return 0; + tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable)); value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL; @@ -122,6 +126,8 @@ static int tegra_output_rgb_enable(struct tegra_output *output) tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); + rgb->enabled = true; + return 0; } @@ -130,6 +136,9 @@ static int tegra_output_rgb_disable(struct tegra_output *output) struct tegra_rgb *rgb = to_rgb(output); unsigned long value; + if (!rgb->enabled) + return 0; + value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL); value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); @@ -144,6 +153,8 @@ static int tegra_output_rgb_disable(struct tegra_output *output) tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable)); + rgb->enabled = false; + return 0; } -- cgit v0.10.2 From 63ef79c25b5bbd356d04ef93d15693d8664c6141 Mon Sep 17 00:00:00 2001 From: Ingo Tuchscherer Date: Wed, 5 Feb 2014 12:29:57 +0100 Subject: s390/zcrypt: additional check to avoid overflow in msg-type 6 requests Signed-off-by: Ingo Tuchscherer Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index dc542e0..0bc91e4 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -311,7 +311,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, } __packed * msg = ap_msg->message; int rcblen = CEIL4(xcRB->request_control_blk_length); - int replylen; + int replylen, req_sumlen, resp_sumlen; char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen; char *function_code; @@ -321,12 +321,34 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, xcRB->request_data_length; if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE) return -EINVAL; + + /* Overflow check + sum must be greater (or equal) than the largest operand */ + req_sumlen = CEIL4(xcRB->request_control_blk_length) + + xcRB->request_data_length; + if ((CEIL4(xcRB->request_control_blk_length) <= + xcRB->request_data_length) ? + (req_sumlen < xcRB->request_data_length) : + (req_sumlen < CEIL4(xcRB->request_control_blk_length))) { + return -EINVAL; + } + replylen = sizeof(struct type86_fmt2_msg) + CEIL4(xcRB->reply_control_blk_length) + xcRB->reply_data_length; if (replylen > MSGTYPE06_MAX_MSG_SIZE) return -EINVAL; + /* Overflow check + sum must be greater (or equal) than the largest operand */ + resp_sumlen = CEIL4(xcRB->reply_control_blk_length) + + xcRB->reply_data_length; + if ((CEIL4(xcRB->reply_control_blk_length) <= xcRB->reply_data_length) ? + (resp_sumlen < xcRB->reply_data_length) : + (resp_sumlen < CEIL4(xcRB->reply_control_blk_length))) { + return -EINVAL; + } + /* prepare type6 header */ msg->hdr = static_type6_hdrX; memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID)); -- cgit v0.10.2 From 862474f8b46f6c1e600d4934e40ba40646c696ec Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Tue, 11 Feb 2014 11:01:23 +0100 Subject: can: kvaser_usb: check number of channels returned by HW It is needed to check the number of channels returned by the HW because it cannot be greater than MAX_NET_DEVICES otherwise it will crash. Signed-off-by: Olivier Sobrie Cc: linux-stable Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 6c859bb..e77d110 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -473,6 +473,8 @@ static int kvaser_usb_get_card_info(struct kvaser_usb *dev) return err; dev->nchannels = msg.u.cardinfo.nchannels; + if (dev->nchannels > MAX_NET_DEVICES) + return -EINVAL; return 0; } -- cgit v0.10.2 From 1bf4bbb4024dcdab5e57634dd8ae1072d42a53ac Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 11 Feb 2014 16:02:47 +0100 Subject: mac80211: send control port protocol frames to the VO queue Improves reliability of wifi connections with WPA, since authentication frames are prioritized over normal traffic and also typically exempt from aggregation. Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 21211c6..d51422c 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, return IEEE80211_AC_BE; } + if (skb->protocol == sdata->control_port_protocol) { + skb->priority = 7; + return ieee80211_downgrade_queue(sdata, skb); + } + /* use the data classifier to determine what 802.1d tag the * data frame has */ rcu_read_lock(); -- cgit v0.10.2 From 8e67bbbc51dbeaba480e83fe2162eb08083a0459 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 6 Feb 2014 12:35:05 +0100 Subject: drm/vmwgfx: Fix a couple of sparse warnings and errors Introduced with 3.14-rc1 Reported-by: Fengguang Wu Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c index 9426c53..1e80152 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c @@ -551,8 +551,7 @@ static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind) cmd->header.size = sizeof(cmd->body); cmd->body.cid = bi->ctx->id; cmd->body.type = bi->i1.shader_type; - cmd->body.shid = - cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID); + cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); vmw_fifo_commit(dev_priv, sizeof(*cmd)); return 0; @@ -585,8 +584,7 @@ static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi, cmd->header.size = sizeof(cmd->body); cmd->body.cid = bi->ctx->id; cmd->body.type = bi->i1.rt_type; - cmd->body.target.sid = - cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID); + cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); cmd->body.target.face = 0; cmd->body.target.mipmap = 0; vmw_fifo_commit(dev_priv, sizeof(*cmd)); @@ -628,8 +626,7 @@ static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi, cmd->body.c.cid = bi->ctx->id; cmd->body.s1.stage = bi->i1.texture_stage; cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE; - cmd->body.s1.value = - cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID); + cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); vmw_fifo_commit(dev_priv, sizeof(*cmd)); return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 269b85c..88a2d56 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -602,7 +602,7 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv, { struct vmw_cid_cmd { SVGA3dCmdHeader header; - __le32 cid; + uint32_t cid; } *cmd; cmd = container_of(header, struct vmw_cid_cmd, header); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index 217d941..ee38565 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -371,13 +371,13 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, TTM_REF_USAGE); } -int vmw_shader_alloc(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buffer, - size_t shader_size, - size_t offset, - SVGA3dShaderType shader_type, - struct ttm_object_file *tfile, - u32 *handle) +static int vmw_shader_alloc(struct vmw_private *dev_priv, + struct vmw_dma_buffer *buffer, + size_t shader_size, + size_t offset, + SVGA3dShaderType shader_type, + struct ttm_object_file *tfile, + u32 *handle) { struct vmw_user_shader *ushader; struct vmw_resource *res, *tmp; @@ -779,6 +779,8 @@ vmw_compat_shader_man_create(struct vmw_private *dev_priv) int ret; man = kzalloc(sizeof(*man), GFP_KERNEL); + if (man == NULL) + return ERR_PTR(-ENOMEM); man->dev_priv = dev_priv; INIT_LIST_HEAD(&man->list); -- cgit v0.10.2 From 857aea1c5769386b1905bb38fbb4464c800b2df6 Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Wed, 12 Feb 2014 12:07:38 +0100 Subject: drm/vmwgfx: Get maximum mob size from register SVGA_REG_MOB_MAX_SIZE This patch queries the register SVGA_REG_MOB_MAX_SIZE for the maximum size of a single mob. Signed-off-by: Charmaine Lee Reviewed-by: Thomas Hellstrom diff --git a/drivers/gpu/drm/vmwgfx/svga_reg.h b/drivers/gpu/drm/vmwgfx/svga_reg.h index 71defa4..11323dd 100644 --- a/drivers/gpu/drm/vmwgfx/svga_reg.h +++ b/drivers/gpu/drm/vmwgfx/svga_reg.h @@ -169,10 +169,17 @@ enum { SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */ SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */ SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */ + SVGA_REG_COMMAND_LOW = 48, /* Lower 32 bits and submits commands */ + SVGA_REG_COMMAND_HIGH = 49, /* Upper 32 bits of command buffer PA */ SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50, /* Max primary memory */ SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, /* Suggested limit on mob mem */ SVGA_REG_DEV_CAP = 52, /* Write dev cap index, read value */ - SVGA_REG_TOP = 53, /* Must be 1 more than the last register */ + SVGA_REG_CMD_PREPEND_LOW = 53, + SVGA_REG_CMD_PREPEND_HIGH = 54, + SVGA_REG_SCREENTARGET_MAX_WIDTH = 55, + SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56, + SVGA_REG_MOB_MAX_SIZE = 57, + SVGA_REG_TOP = 58, /* Must be 1 more than the last register */ SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ /* Next 768 (== 256*3) registers exist for colormap */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 3bdc0ad..0083cbf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -667,6 +667,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->memory_size = 512*1024*1024; } dev_priv->max_mob_pages = 0; + dev_priv->max_mob_size = 0; if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { uint64_t mem_size = vmw_read(dev_priv, @@ -676,6 +677,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->prim_bb_mem = vmw_read(dev_priv, SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM); + dev_priv->max_mob_size = + vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE); } else dev_priv->prim_bb_mem = dev_priv->vram_size; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index ecaa302..9e4be17 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -386,6 +386,7 @@ struct vmw_private { uint32_t max_gmr_ids; uint32_t max_gmr_pages; uint32_t max_mob_pages; + uint32_t max_mob_size; uint32_t memory_size; bool has_gmr; bool has_mob; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index f9881f9..47b7094 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -102,6 +102,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, vmw_fp->gb_aware = true; param->value = dev_priv->max_mob_pages * PAGE_SIZE; break; + case DRM_VMW_PARAM_MAX_MOB_SIZE: + param->value = dev_priv->max_mob_size; + break; default: DRM_ERROR("Illegal vmwgfx get param request: %d\n", param->param); diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index 9971c56..87792a5 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -87,6 +87,7 @@ #define DRM_VMW_PARAM_MAX_SURF_MEMORY 7 #define DRM_VMW_PARAM_3D_CAPS_SIZE 8 #define DRM_VMW_PARAM_MAX_MOB_MEMORY 9 +#define DRM_VMW_PARAM_MAX_MOB_SIZE 10 /** * struct drm_vmw_getparam_arg -- cgit v0.10.2 From b2ad9881d6aeec4f3ee527c00fce34442d6d02d3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 11 Feb 2014 19:03:47 +0300 Subject: drm/vmwgfx: unlock on error path in vmw_execbuf_process() There is a missing unlock on error here. Fixes: 30f82d816d2d ('drm/vmwgfx: Reemit context bindings when necessary v2') Signed-off-by: Dan Carpenter Reviewed-by: Thomas Hellstrom diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 88a2d56..216ef23 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2469,7 +2469,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, if (dev_priv->has_mob) { ret = vmw_rebind_contexts(sw_context); if (unlikely(ret != 0)) - goto out_err; + goto out_unlock_binding; } cmd = vmw_fifo_reserve(dev_priv, command_size); -- cgit v0.10.2 From 00463c113b6ba6506b4f1ebb9b3c5dd249f8750f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 17:15:51 -0800 Subject: ASoC: rsnd: tidyup original for_each_rsnd_xxx macro Current for_each_rsnd_xxx macro will read out-of-array's memory after last loop operation. It was not good C language operation, and the binary which was compiled by (at least) gcc 4.8.1 is broken This patch tidyup these issues Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 8d3a82e..bc8961c5 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -25,9 +25,10 @@ struct rsnd_adg { }; #define for_each_rsnd_clk(pos, adg, i) \ - for (i = 0, (pos) = adg->clk[i]; \ - i < CLKMAX; \ - i++, (pos) = adg->clk[i]) + for (i = 0; \ + (i < CLKMAX) && \ + ((pos) = adg->clk[i]); \ + i++) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8b66dc1..9e4efb4 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -216,9 +216,10 @@ struct rsnd_dai { #define rsnd_dai_nr(priv) ((priv)->dai_nr) #define for_each_rsnd_dai(rdai, priv, i) \ - for (i = 0, (rdai) = rsnd_dai_get(priv, i); \ - i < rsnd_dai_nr(priv); \ - i++, (rdai) = rsnd_dai_get(priv, i)) + for (i = 0; \ + (i < rsnd_dai_nr(priv)) && \ + ((rdai) = rsnd_dai_get(priv, i)); \ + i++) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); int rsnd_dai_disconnect(struct rsnd_mod *mod); -- cgit v0.10.2 From ee2c828d21b2381c813df257235d3c635269e435 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 21:04:12 -0800 Subject: ASoC: rsnd: set DIV_EN register on rsnd_adg_set_convert_clk_gen2() DIV_EN register enable bit is required when you use Gen2 SRC Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index bc8961c5..af9e440 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -111,8 +111,8 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); - int idx, sel, div, step; - u32 val; + int idx, sel, div, step, ret; + u32 val, en; unsigned int min, diff; unsigned int sel_rate [] = { clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ @@ -124,6 +124,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, min = ~0; val = 0; + en = 0; for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { idx = 0; step = 2; @@ -136,6 +137,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, if (min > diff) { val = (sel << 8) | idx; min = diff; + en = 1 << (sel + 1); /* fixme */ } /* @@ -157,7 +159,15 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, return -EIO; } - return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); + ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); + if (ret < 0) { + dev_err(dev, "timsel error\n"); + return ret; + } + + rsnd_mod_bset(mod, DIV_EN, en, en); + + return 0; } int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 3e03a8b..0a43b90 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -253,6 +253,7 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), + RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9e4efb4..d409390 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -67,6 +67,7 @@ enum rsnd_reg { RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ + RSND_REG_DIV_EN, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ -- cgit v0.10.2 From a2070feede404484296aace813b6c518582a3f8e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 21:05:26 -0800 Subject: ASoC: rsnd: print error if there is SRC settings mismatch rsnd request clock master if SRC is used Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 6e5c763..3984d4b 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -122,6 +122,14 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + + if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { + struct device *dev = rsnd_priv_to_dev(priv); + + dev_err(dev, "rsnd should be clk master when you rate convert\n"); + return -EINVAL; + } /* * SSI_MODE0 -- cgit v0.10.2 From 4fbd9d2ec2f12ffb292c1489d1402e8b956afc01 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 12 Feb 2014 12:37:01 +0100 Subject: drm/vmwgfx: Remove stray const Reported-by: Fengguang Wu Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 216ef23..904fdde 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -1835,7 +1835,7 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, return 0; } -static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = { +static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = { VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid, false, false, false), VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid, -- cgit v0.10.2 From ebf6dad0de89677aa58a4d8b009014ff88a23452 Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Wed, 12 Feb 2014 09:57:52 +0000 Subject: regulator: da9063: Bug fix when setting max voltage on LDOs 5-11 Bug fix to allow the setting of maximum voltage for certain LDOs. What the bug is: There is a problem caused by an invalid calculation of n_voltages in the driver. This n_voltages value has the potential to be different for each regulator. The value for linear_min_sel is set as DA9063_V##regl_name# which can be different depending upon the regulator. This is chosen according to the following definitions in the DA9063 registers.h file: DA9063_VLDO1_BIAS 0 DA9063_VLDO2_BIAS 0 DA9063_VLDO3_BIAS 0 DA9063_VLDO4_BIAS 0 DA9063_VLDO5_BIAS 2 DA9063_VLDO6_BIAS 2 DA9063_VLDO7_BIAS 2 DA9063_VLDO8_BIAS 2 DA9063_VLDO9_BIAS 3 DA9063_VLDO10_BIAS 2 DA9063_VLDO11_BIAS 2 The calculation for n_voltages is valid for LDOs whose BIAS value is zero but this is not correct for those LDOs which have a non-zero value. What the fix is: In order to take into account the non-zero linear_min_sel value which is set for the regulators LDO5, LDO6, LDO7, LDO8, LDO9, LDO10 and LDO11, the calculation for n_voltages should take into account the missing term defined by DA9063_V##regl_name#. This will in turn allow the core constraints calculation to set the maximum voltage limits correctly and therefore allow users to apply the maximum expected voltage to all of the LDOs. Signed-off-by: Steve Twiss Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 56727eb..91e99a2 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -1,3 +1,4 @@ + /* * Regulator driver for DA9063 PMIC series * @@ -60,7 +61,8 @@ struct da9063_regulator_info { .desc.ops = &da9063_ldo_ops, \ .desc.min_uV = (min_mV) * 1000, \ .desc.uV_step = (step_mV) * 1000, \ - .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1), \ + .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1 \ + + (DA9063_V##regl_name##_BIAS)), \ .desc.enable_reg = DA9063_REG_##regl_name##_CONT, \ .desc.enable_mask = DA9063_LDO_EN, \ .desc.vsel_reg = DA9063_REG_V##regl_name##_A, \ -- cgit v0.10.2 From 86f28d76435b619bd0bc5f6fde2803a5bc27ca24 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Feb 2014 15:42:48 +0800 Subject: ASoC: fsl-spdif: big-endian support For most platforms, the CPU and SPDIF device is in the same endianess mode. While for the LS1 platform, the CPU is in LE mode and the SPDIF is in BE mode. Signed-off-by: Xiubo Li Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt index f2ae335..3e9e82c8 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt @@ -29,6 +29,10 @@ Required properties: can also be referred to TxClk_Source bit of register SPDIF_STC. + - big-endian : If this property is absent, the native endian mode will + be in use as default, or the big endian mode will be in use for all the + device registers. + Example: spdif: spdif@02004000 { @@ -50,5 +54,6 @@ spdif: spdif@02004000 { "rxtx5", "rxtx6", "rxtx7"; + big-endian; status = "okay"; }; diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4d075f1..73ceb2f 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -985,7 +985,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config fsl_spdif_regmap_config = { +static struct regmap_config fsl_spdif_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -1105,6 +1105,9 @@ static int fsl_spdif_probe(struct platform_device *pdev) memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); spdif_priv->cpu_dai_drv.name = spdif_priv->name; + if (of_property_read_bool(np, "big-endian")) + fsl_spdif_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); -- cgit v0.10.2 From eaba603fc7c6281908c316d9e58de688943d58be Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Feb 2014 15:42:49 +0800 Subject: ASoC: fsl-esai: big-endian support For most platforms, the CPU and ESAI device is in the same endianess mode. While for the LS1 platform, the CPU is in LE mode and the ESAI is in BE mode. Signed-off-by: Xiubo Li Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index d7b99fa..aeb8c4a 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt @@ -34,6 +34,10 @@ Required properties: that ESAI would work in the synchronous mode, which means all the settings for Receiving would be duplicated from Transmition related registers. + - big-endian : If this property is absent, the native endian mode will + be in use as default, or the big endian mode will be in use for all the + device registers. + Example: esai: esai@02024000 { @@ -46,5 +50,6 @@ esai: esai@02024000 { dma-names = "rx", "tx"; fsl,fifo-depth = <128>; fsl,esai-synchronous; + big-endian; status = "disabled"; }; diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index f55341e..d8e13ab 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -678,7 +678,7 @@ static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config fsl_esai_regmap_config = { +static struct regmap_config fsl_esai_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -704,6 +704,9 @@ static int fsl_esai_probe(struct platform_device *pdev) esai_priv->pdev = pdev; strcpy(esai_priv->name, np->name); + if (of_property_read_bool(np, "big-endian")) + fsl_esai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); -- cgit v0.10.2 From 15cc17678547676c82a5da9ccf357447333fc342 Mon Sep 17 00:00:00 2001 From: Eric Whitney Date: Wed, 12 Feb 2014 10:42:45 -0500 Subject: ext4: fix xfstest generic/299 block validity failures Commit a115f749c1 (ext4: remove wait for unwritten extent conversion from ext4_truncate) exposed a bug in ext4_ext_handle_uninitialized_extents(). It can be triggered by xfstest generic/299 when run on a test file system created without a journal. This test continuously fallocates and truncates files to which random dio/aio writes are simultaneously performed by a separate process. The test completes successfully, but if the test filesystem is mounted with the block_validity option, a warning message stating that a logical block has been mapped to an illegal physical block is posted in the kernel log. The bug occurs when an extent is being converted to the written state by ext4_end_io_dio() and ext4_ext_handle_uninitialized_extents() discovers a mapping for an existing uninitialized extent. Although it sets EXT4_MAP_MAPPED in map->m_flags, it fails to set map->m_pblk to the discovered physical block number. Because map->m_pblk is not otherwise initialized or set by this function or its callers, its uninitialized value is returned to ext4_map_blocks(), where it is stored as a bogus mapping in the extent status tree. Since map->m_pblk can accidentally contain illegal values that are larger than the physical size of the file system, calls to check_block_validity() in ext4_map_blocks() that are enabled if the block_validity mount option is used can fail, resulting in the logged warning message. Signed-off-by: Eric Whitney Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org # 3.11+ diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 10cff47..74bc2d5 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3906,6 +3906,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, } else err = ret; map->m_flags |= EXT4_MAP_MAPPED; + map->m_pblk = newblock; if (allocated > map->m_len) allocated = map->m_len; map->m_len = allocated; -- cgit v0.10.2 From 30d29b119ef01776e0a301444ab24defe8d8bef3 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Wed, 12 Feb 2014 11:48:31 -0500 Subject: ext4: fix error paths in swap_inode_boot_loader() In swap_inode_boot_loader() we forgot to release ->i_mutex and resume unlocked dio for inode and inode_bl if there is an error starting the journal handle. This commit fixes this issue. Reported-by: Ahmed Tamrawi Cc: Andreas Dilger Cc: Dr. Tilmann Bubeck Signed-off-by: Zheng Liu Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org # v3.10+ diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6bea806..a2a837f 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -140,7 +140,7 @@ static long swap_inode_boot_loader(struct super_block *sb, handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); if (IS_ERR(handle)) { err = -EINVAL; - goto swap_boot_out; + goto journal_err_out; } /* Protect extent tree against block allocations via delalloc */ @@ -198,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb, ext4_double_up_write_data_sem(inode, inode_bl); +journal_err_out: ext4_inode_resume_unlocked_dio(inode); ext4_inode_resume_unlocked_dio(inode_bl); -- cgit v0.10.2 From 23301410972330c0ae9a8afc379ba2005e249cc6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 12 Feb 2014 12:16:04 -0500 Subject: ext4: don't try to modify s_flags if the the file system is read-only If an ext4 file system is created by some tool other than mke2fs (perhaps by someone who has a pathalogical fear of the GPL) that doesn't set one or the other of the EXT2_FLAGS_{UN}SIGNED_HASH flags, and that file system is then mounted read-only, don't try to modify the s_flags field. Otherwise, if dm_verity is in use, the superblock will change, causing an dm_verity failure. Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 1f7784d..710fed2 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3695,16 +3695,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) for (i = 0; i < 4; i++) sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); sbi->s_def_hash_version = es->s_def_hash_version; - i = le32_to_cpu(es->s_flags); - if (i & EXT2_FLAGS_UNSIGNED_HASH) - sbi->s_hash_unsigned = 3; - else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { + if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { + i = le32_to_cpu(es->s_flags); + if (i & EXT2_FLAGS_UNSIGNED_HASH) + sbi->s_hash_unsigned = 3; + else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { #ifdef __CHAR_UNSIGNED__ - es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); - sbi->s_hash_unsigned = 3; + if (!(sb->s_flags & MS_RDONLY)) + es->s_flags |= + cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); + sbi->s_hash_unsigned = 3; #else - es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); + if (!(sb->s_flags & MS_RDONLY)) + es->s_flags |= + cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); #endif + } } /* Handle clustersize */ -- cgit v0.10.2 From 048d4ff81f1cf26b3f3627a9a69d35aff7898bb3 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 10 Feb 2014 14:09:45 +0800 Subject: ASoC: atmel_ssc_dai: make option to choose clock When SSC works in slave mode, according to the hardware design, the clock can get from TK pin, also can get from RK pin. So, add one parameter to choose where the clock from. Signed-off-by: Bo Shen Acked-by: Nicolas Ferre Signed-off-by: Mark Brown diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 5be80840..22de137 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -150,6 +150,12 @@ static int ssc_probe(struct platform_device *pdev) return -ENODEV; ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat; + if (pdev->dev.of_node) { + struct device_node *np = pdev->dev.of_node; + ssc->clk_from_rk_pin = + of_property_read_bool(np, "atmel,clk-from-rk-pin"); + } + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ssc->regs = devm_ioremap_resource(&pdev->dev, regs); if (IS_ERR(ssc->regs)) diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h index 66a0e53..571a12e 100644 --- a/include/linux/atmel-ssc.h +++ b/include/linux/atmel-ssc.h @@ -18,6 +18,7 @@ struct ssc_device { struct clk *clk; int user; int irq; + bool clk_from_rk_pin; }; struct ssc_device * __must_check ssc_request(unsigned int ssc_num); diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 1ead3c9..de433cfd 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -341,6 +341,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, { int id = dai->id; struct atmel_ssc_info *ssc_p = &ssc_info[id]; + struct ssc_device *ssc = ssc_p->ssc; struct atmel_pcm_dma_params *dma_params; int dir, channels, bits; u32 tfmr, rfmr, tcmr, rcmr; @@ -466,7 +467,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RCMR_START, start_event) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_PIN : SSC_CKS_CLOCK); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) @@ -481,7 +483,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(TCMR_START, start_event) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) - | SSC_BF(TCMR_CKS, SSC_CKS_PIN); + | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_CLOCK : SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) @@ -550,7 +553,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RCMR_START, SSC_START_RISING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_PIN); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_PIN : SSC_CKS_CLOCK); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) @@ -565,7 +569,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(TCMR_START, SSC_START_RISING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) - | SSC_BF(TCMR_CKS, SSC_CKS_PIN); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_CLOCK : SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) -- cgit v0.10.2 From a69d0009aad51e16bf294d78a3b2e4fe655cf10f Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 10 Feb 2014 14:09:46 +0800 Subject: Binding: atmel-ssc: add option to choose clock Add the option to choose clock on which pin input to SSC (as slave). Default is on TK pin to SSC, add "atmel,clk-from-rk-pin" option to specify the clock is on RK pin to SSC. Signed-off-by: Bo Shen Acked-by: Nicolas Ferre Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt index 60960b2..efc98ea 100644 --- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt +++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt @@ -17,6 +17,14 @@ Required properties for devices compatible with "atmel,at91sam9g45-ssc": See Documentation/devicetree/bindings/dma/atmel-dma.txt for details. - dma-names: Must be "tx", "rx". +Optional properties: + - atmel,clk-from-rk-pin: bool property. + - When SSC works in slave mode, according to the hardware design, the + clock can get from TK pin, and also can get from RK pin. So, add + this parameter to choose where the clock from. + - By default the clock is from TK pin, if the clock from RK pin, this + property is needed. + Examples: - PDC transfer: ssc0: ssc@fffbc000 { -- cgit v0.10.2 From b055211d941eb6cb7b285be580cf6e51a01d2f44 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 12 Feb 2014 12:56:48 +0100 Subject: drm/vmwgfx: Fix possible integer overflow Cc: stable@vger.kernel.org Reported-by: Brian Paul Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz diff --git a/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h index 8369c3b..ef33850 100644 --- a/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h +++ b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h @@ -38,8 +38,11 @@ #define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) #define max_t(type, x, y) ((x) > (y) ? (x) : (y)) +#define min_t(type, x, y) ((x) < (y) ? (x) : (y)) #define surf_size_struct SVGA3dSize #define u32 uint32 +#define u64 uint64_t +#define U32_MAX ((u32)~0U) #endif /* __KERNEL__ */ @@ -704,8 +707,8 @@ static const struct svga3d_surface_desc svga3d_surface_descs[] = { static inline u32 clamped_umul32(u32 a, u32 b) { - uint64_t tmp = (uint64_t) a*b; - return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp; + u64 tmp = (u64) a*b; + return (tmp > (u64) U32_MAX) ? U32_MAX : tmp; } static inline const struct svga3d_surface_desc * @@ -834,7 +837,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format, bool cubemap) { const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format); - u32 total_size = 0; + u64 total_size = 0; u32 mip; for (mip = 0; mip < num_mip_levels; mip++) { @@ -847,7 +850,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format, if (cubemap) total_size *= SVGA3D_MAX_SURFACE_FACES; - return total_size; + return (u32) min_t(u64, total_size, (u64) U32_MAX); } -- cgit v0.10.2 From 36e952c1ed8ca44bca245c465c8293e175dd9222 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 12 Feb 2014 13:19:36 +0100 Subject: drm/vmwgfx: Fix command defines and checks Make sure all guest-backed object commands are properly packed. Have the command verifier treat uninitialized command entries as invalid rather than dereferencing NULL pointers. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz diff --git a/drivers/gpu/drm/vmwgfx/svga3d_reg.h b/drivers/gpu/drm/vmwgfx/svga3d_reg.h index b645647..bb594c1 100644 --- a/drivers/gpu/drm/vmwgfx/svga3d_reg.h +++ b/drivers/gpu/drm/vmwgfx/svga3d_reg.h @@ -1223,9 +1223,19 @@ typedef enum { #define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129 #define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE 1130 - +#define SVGA_3D_CMD_GB_SCREEN_DMA 1131 +#define SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH 1132 +#define SVGA_3D_CMD_GB_MOB_FENCE 1133 +#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 1134 #define SVGA_3D_CMD_DEFINE_GB_MOB64 1135 #define SVGA_3D_CMD_REDEFINE_GB_MOB64 1136 +#define SVGA_3D_CMD_NOP_ERROR 1137 + +#define SVGA_3D_CMD_RESERVED1 1138 +#define SVGA_3D_CMD_RESERVED2 1139 +#define SVGA_3D_CMD_RESERVED3 1140 +#define SVGA_3D_CMD_RESERVED4 1141 +#define SVGA_3D_CMD_RESERVED5 1142 #define SVGA_3D_CMD_MAX 1142 #define SVGA_3D_CMD_FUTURE_MAX 3000 @@ -1973,8 +1983,7 @@ struct { uint32 sizeInBytes; uint32 validSizeInBytes; SVGAMobFormat ptDepth; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdSetOTableBase; /* SVGA_3D_CMD_SET_OTABLE_BASE */ typedef @@ -1984,15 +1993,13 @@ struct { uint32 sizeInBytes; uint32 validSizeInBytes; SVGAMobFormat ptDepth; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdSetOTableBase64; /* SVGA_3D_CMD_SET_OTABLE_BASE64 */ typedef struct { SVGAOTableType type; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdReadbackOTable; /* SVGA_3D_CMD_READBACK_OTABLE */ /* @@ -2005,8 +2012,7 @@ struct SVGA3dCmdDefineGBMob { SVGAMobFormat ptDepth; PPN base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdDefineGBMob; /* SVGA_3D_CMD_DEFINE_GB_MOB */ @@ -2017,8 +2023,7 @@ SVGA3dCmdDefineGBMob; /* SVGA_3D_CMD_DEFINE_GB_MOB */ typedef struct SVGA3dCmdDestroyGBMob { SVGAMobId mobid; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdDestroyGBMob; /* SVGA_3D_CMD_DESTROY_GB_MOB */ /* @@ -2031,8 +2036,7 @@ struct SVGA3dCmdRedefineGBMob { SVGAMobFormat ptDepth; PPN base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdRedefineGBMob; /* SVGA_3D_CMD_REDEFINE_GB_MOB */ /* @@ -2045,8 +2049,7 @@ struct SVGA3dCmdDefineGBMob64 { SVGAMobFormat ptDepth; PPN64 base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdDefineGBMob64; /* SVGA_3D_CMD_DEFINE_GB_MOB64 */ /* @@ -2059,8 +2062,7 @@ struct SVGA3dCmdRedefineGBMob64 { SVGAMobFormat ptDepth; PPN64 base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdRedefineGBMob64; /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */ /* @@ -2070,8 +2072,7 @@ SVGA3dCmdRedefineGBMob64; /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */ typedef struct SVGA3dCmdUpdateGBMobMapping { SVGAMobId mobid; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdUpdateGBMobMapping; /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */ /* @@ -2087,7 +2088,8 @@ struct SVGA3dCmdDefineGBSurface { uint32 multisampleCount; SVGA3dTextureFilter autogenFilter; SVGA3dSize size; -} SVGA3dCmdDefineGBSurface; /* SVGA_3D_CMD_DEFINE_GB_SURFACE */ +} __packed +SVGA3dCmdDefineGBSurface; /* SVGA_3D_CMD_DEFINE_GB_SURFACE */ /* * Destroy a guest-backed surface. @@ -2096,7 +2098,8 @@ struct SVGA3dCmdDefineGBSurface { typedef struct SVGA3dCmdDestroyGBSurface { uint32 sid; -} SVGA3dCmdDestroyGBSurface; /* SVGA_3D_CMD_DESTROY_GB_SURFACE */ +} __packed +SVGA3dCmdDestroyGBSurface; /* SVGA_3D_CMD_DESTROY_GB_SURFACE */ /* * Bind a guest-backed surface to an object. @@ -2106,7 +2109,8 @@ typedef struct SVGA3dCmdBindGBSurface { uint32 sid; SVGAMobId mobid; -} SVGA3dCmdBindGBSurface; /* SVGA_3D_CMD_BIND_GB_SURFACE */ +} __packed +SVGA3dCmdBindGBSurface; /* SVGA_3D_CMD_BIND_GB_SURFACE */ /* * Conditionally bind a mob to a guest backed surface if testMobid @@ -2123,7 +2127,7 @@ struct{ SVGAMobId testMobid; SVGAMobId mobid; uint32 flags; -} +} __packed SVGA3dCmdCondBindGBSurface; /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */ /* @@ -2135,7 +2139,8 @@ typedef struct SVGA3dCmdUpdateGBImage { SVGA3dSurfaceImageId image; SVGA3dBox box; -} SVGA3dCmdUpdateGBImage; /* SVGA_3D_CMD_UPDATE_GB_IMAGE */ +} __packed +SVGA3dCmdUpdateGBImage; /* SVGA_3D_CMD_UPDATE_GB_IMAGE */ /* * Update an entire guest-backed surface. @@ -2145,7 +2150,8 @@ struct SVGA3dCmdUpdateGBImage { typedef struct SVGA3dCmdUpdateGBSurface { uint32 sid; -} SVGA3dCmdUpdateGBSurface; /* SVGA_3D_CMD_UPDATE_GB_SURFACE */ +} __packed +SVGA3dCmdUpdateGBSurface; /* SVGA_3D_CMD_UPDATE_GB_SURFACE */ /* * Readback an image in a guest-backed surface. @@ -2155,7 +2161,8 @@ struct SVGA3dCmdUpdateGBSurface { typedef struct SVGA3dCmdReadbackGBImage { SVGA3dSurfaceImageId image; -} SVGA3dCmdReadbackGBImage; /* SVGA_3D_CMD_READBACK_GB_IMAGE*/ +} __packed +SVGA3dCmdReadbackGBImage; /* SVGA_3D_CMD_READBACK_GB_IMAGE*/ /* * Readback an entire guest-backed surface. @@ -2165,7 +2172,8 @@ struct SVGA3dCmdReadbackGBImage { typedef struct SVGA3dCmdReadbackGBSurface { uint32 sid; -} SVGA3dCmdReadbackGBSurface; /* SVGA_3D_CMD_READBACK_GB_SURFACE */ +} __packed +SVGA3dCmdReadbackGBSurface; /* SVGA_3D_CMD_READBACK_GB_SURFACE */ /* * Readback a sub rect of an image in a guest-backed surface. After @@ -2179,7 +2187,7 @@ struct SVGA3dCmdReadbackGBImagePartial { SVGA3dSurfaceImageId image; SVGA3dBox box; uint32 invertBox; -} +} __packed SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */ /* @@ -2190,7 +2198,8 @@ SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */ typedef struct SVGA3dCmdInvalidateGBImage { SVGA3dSurfaceImageId image; -} SVGA3dCmdInvalidateGBImage; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */ +} __packed +SVGA3dCmdInvalidateGBImage; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */ /* * Invalidate an entire guest-backed surface. @@ -2200,7 +2209,8 @@ struct SVGA3dCmdInvalidateGBImage { typedef struct SVGA3dCmdInvalidateGBSurface { uint32 sid; -} SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */ +} __packed +SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */ /* * Invalidate a sub rect of an image in a guest-backed surface. After @@ -2214,7 +2224,7 @@ struct SVGA3dCmdInvalidateGBImagePartial { SVGA3dSurfaceImageId image; SVGA3dBox box; uint32 invertBox; -} +} __packed SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */ /* @@ -2224,7 +2234,8 @@ SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */ typedef struct SVGA3dCmdDefineGBContext { uint32 cid; -} SVGA3dCmdDefineGBContext; /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */ +} __packed +SVGA3dCmdDefineGBContext; /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */ /* * Destroy a guest-backed context. @@ -2233,7 +2244,8 @@ struct SVGA3dCmdDefineGBContext { typedef struct SVGA3dCmdDestroyGBContext { uint32 cid; -} SVGA3dCmdDestroyGBContext; /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */ +} __packed +SVGA3dCmdDestroyGBContext; /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */ /* * Bind a guest-backed context. @@ -2252,7 +2264,8 @@ struct SVGA3dCmdBindGBContext { uint32 cid; SVGAMobId mobid; uint32 validContents; -} SVGA3dCmdBindGBContext; /* SVGA_3D_CMD_BIND_GB_CONTEXT */ +} __packed +SVGA3dCmdBindGBContext; /* SVGA_3D_CMD_BIND_GB_CONTEXT */ /* * Readback a guest-backed context. @@ -2262,7 +2275,8 @@ struct SVGA3dCmdBindGBContext { typedef struct SVGA3dCmdReadbackGBContext { uint32 cid; -} SVGA3dCmdReadbackGBContext; /* SVGA_3D_CMD_READBACK_GB_CONTEXT */ +} __packed +SVGA3dCmdReadbackGBContext; /* SVGA_3D_CMD_READBACK_GB_CONTEXT */ /* * Invalidate a guest-backed context. @@ -2270,7 +2284,8 @@ struct SVGA3dCmdReadbackGBContext { typedef struct SVGA3dCmdInvalidateGBContext { uint32 cid; -} SVGA3dCmdInvalidateGBContext; /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */ +} __packed +SVGA3dCmdInvalidateGBContext; /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */ /* * Define a guest-backed shader. @@ -2281,7 +2296,8 @@ struct SVGA3dCmdDefineGBShader { uint32 shid; SVGA3dShaderType type; uint32 sizeInBytes; -} SVGA3dCmdDefineGBShader; /* SVGA_3D_CMD_DEFINE_GB_SHADER */ +} __packed +SVGA3dCmdDefineGBShader; /* SVGA_3D_CMD_DEFINE_GB_SHADER */ /* * Bind a guest-backed shader. @@ -2291,7 +2307,8 @@ typedef struct SVGA3dCmdBindGBShader { uint32 shid; SVGAMobId mobid; uint32 offsetInBytes; -} SVGA3dCmdBindGBShader; /* SVGA_3D_CMD_BIND_GB_SHADER */ +} __packed +SVGA3dCmdBindGBShader; /* SVGA_3D_CMD_BIND_GB_SHADER */ /* * Destroy a guest-backed shader. @@ -2299,7 +2316,8 @@ typedef struct SVGA3dCmdBindGBShader { typedef struct SVGA3dCmdDestroyGBShader { uint32 shid; -} SVGA3dCmdDestroyGBShader; /* SVGA_3D_CMD_DESTROY_GB_SHADER */ +} __packed +SVGA3dCmdDestroyGBShader; /* SVGA_3D_CMD_DESTROY_GB_SHADER */ typedef struct { @@ -2314,14 +2332,16 @@ struct { * Note that FLOAT and INT constants are 4-dwords in length, while * BOOL constants are 1-dword in length. */ -} SVGA3dCmdSetGBShaderConstInline; +} __packed +SVGA3dCmdSetGBShaderConstInline; /* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */ typedef struct { uint32 cid; SVGA3dQueryType type; -} SVGA3dCmdBeginGBQuery; /* SVGA_3D_CMD_BEGIN_GB_QUERY */ +} __packed +SVGA3dCmdBeginGBQuery; /* SVGA_3D_CMD_BEGIN_GB_QUERY */ typedef struct { @@ -2329,7 +2349,8 @@ struct { SVGA3dQueryType type; SVGAMobId mobid; uint32 offset; -} SVGA3dCmdEndGBQuery; /* SVGA_3D_CMD_END_GB_QUERY */ +} __packed +SVGA3dCmdEndGBQuery; /* SVGA_3D_CMD_END_GB_QUERY */ /* @@ -2346,21 +2367,22 @@ struct { SVGA3dQueryType type; SVGAMobId mobid; uint32 offset; -} SVGA3dCmdWaitForGBQuery; /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */ +} __packed +SVGA3dCmdWaitForGBQuery; /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */ typedef struct { SVGAMobId mobid; uint32 fbOffset; uint32 initalized; -} +} __packed SVGA3dCmdEnableGart; /* SVGA_3D_CMD_ENABLE_GART */ typedef struct { SVGAMobId mobid; uint32 gartOffset; -} +} __packed SVGA3dCmdMapMobIntoGart; /* SVGA_3D_CMD_MAP_MOB_INTO_GART */ @@ -2368,7 +2390,7 @@ typedef struct { uint32 gartOffset; uint32 numPages; -} +} __packed SVGA3dCmdUnmapGartRange; /* SVGA_3D_CMD_UNMAP_GART_RANGE */ @@ -2385,27 +2407,27 @@ struct { int32 xRoot; int32 yRoot; uint32 flags; -} +} __packed SVGA3dCmdDefineGBScreenTarget; /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */ typedef struct { uint32 stid; -} +} __packed SVGA3dCmdDestroyGBScreenTarget; /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */ typedef struct { uint32 stid; SVGA3dSurfaceImageId image; -} +} __packed SVGA3dCmdBindGBScreenTarget; /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */ typedef struct { uint32 stid; SVGA3dBox box; -} +} __packed SVGA3dCmdUpdateGBScreenTarget; /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */ /* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 904fdde..efb575a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2032,6 +2032,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, goto out_invalid; entry = &vmw_cmd_entries[cmd_id]; + if (unlikely(!entry->func)) + goto out_invalid; + if (unlikely(!entry->user_allow && !sw_context->kernel)) goto out_privileged; -- cgit v0.10.2 From 322a8e91844f4ae2093e0d3d8a318d0ef2596756 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 5 Feb 2014 11:55:49 +0100 Subject: PCI: mvebu: Use Device ID and revision from underlying endpoint Marvell SoCs place the SoC number into the PCIe endpoint device ID. The SoC stepping is placed into the PCIe revision. The old plat-orion PCIe driver allowed this information to be seen in user space with a simple lspci command. The new driver places a virtual PCI-PCI bridge on top of these endpoints. It has its own hard coded PCI device ID. Thus it is no longer possible to see what the SoC is using lspci. When initializing the PCI-PCI bridge, set its device ID and revision from the underlying endpoint, thus restoring this functionality. Debian would like to use this in order to aid installing the correct DTB file. Fixes: 45361a4fe4464 ("pci: PCIe driver for Marvell Armada 370/XP systems") Signed-off-by: Andrew Lunn Signed-off-by: Bjorn Helgaas Acked-by: Thomas Petazzoni Acked-by: Jason Cooper Cc: stable@vger.kernel.org # v3.11+ diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 13478ec..0e79665 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -60,14 +60,6 @@ #define PCIE_DEBUG_CTRL 0x1a60 #define PCIE_DEBUG_SOFT_RESET BIT(20) -/* - * This product ID is registered by Marvell, and used when the Marvell - * SoC is not the root complex, but an endpoint on the PCIe bus. It is - * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI - * bridge. - */ -#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846 - /* PCI configuration space of a PCI-to-PCI bridge */ struct mvebu_sw_pci_bridge { u16 vendor; @@ -388,7 +380,8 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port) bridge->class = PCI_CLASS_BRIDGE_PCI; bridge->vendor = PCI_VENDOR_ID_MARVELL; - bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID; + bridge->device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16; + bridge->revision = mvebu_readl(port, PCIE_DEV_REV_OFF) & 0xff; bridge->header_type = PCI_HEADER_TYPE_BRIDGE; bridge->cache_line_size = 0x10; -- cgit v0.10.2 From 1a11533fbd71792e8c5d36f6763fbce8df0d231d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 12 Feb 2014 19:06:19 -0500 Subject: Revert "cgroup: use an ordered workqueue for cgroup destruction" This reverts commit ab3f5faa6255a0eb4f832675507d9e295ca7e9ba. Explanation from Hugh: It's because more thorough testing, by others here, found that it wasn't always solving the problem: so I asked Tejun privately to hold off from sending it in, until we'd worked out why not. Most of our testing being on a v3,11-based kernel, it was perfectly possible that the problem was merely our own e.g. missing Tejun's 8a2b75384444 ("workqueue: fix ordered workqueues in NUMA setups"). But that turned out not to be enough to fix it either. Then Filipe pointed out how percpu_ref_kill_and_confirm() uses call_rcu_sched() before we ever get to put the offline on to the workqueue: by the time we get to the workqueue, the ordering has already been lost. So, thanks for the Acks, but I'm afraid that this ordered workqueue solution is just not good enough: we should simply forget that patch and provide a different answer." Signed-off-by: Tejun Heo Cc: Hugh Dickins diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 52719ce..68d8710 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4844,16 +4844,12 @@ static int __init cgroup_wq_init(void) /* * There isn't much point in executing destruction path in * parallel. Good chunk is serialized with cgroup_mutex anyway. - * - * XXX: Must be ordered to make sure parent is offlined after - * children. The ordering requirement is for memcg where a - * parent's offline may wait for a child's leading to deadlock. In - * the long term, this should be fixed from memcg side. + * Use 1 for @max_active. * * We would prefer to do this in cgroup_init() above, but that * is called before init_workqueues(): so leave this until after. */ - cgroup_destroy_wq = alloc_ordered_workqueue("cgroup_destroy", 0); + cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1); BUG_ON(!cgroup_destroy_wq); /* -- cgit v0.10.2 From c0b00a525c127d0055c1df6283300e17f601a1a1 Mon Sep 17 00:00:00 2001 From: Sumit Semwal Date: Mon, 3 Feb 2014 15:09:12 +0530 Subject: dma-buf: update debugfs output Russell King observed 'wierd' looking output from debugfs, and also suggested better ways of getting device names (use KBUILD_MODNAME, dev_name()) This patch addresses these issues to make the debugfs output correct and better looking. While at it, replace seq_printf with seq_puts to remove the checkpatch.pl warnings. Reported-by: Russell King - ARM Linux Signed-off-by: Sumit Semwal diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 1e16cbd..61d6d62 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c @@ -616,36 +616,35 @@ static int dma_buf_describe(struct seq_file *s) if (ret) return ret; - seq_printf(s, "\nDma-buf Objects:\n"); - seq_printf(s, "\texp_name\tsize\tflags\tmode\tcount\n"); + seq_puts(s, "\nDma-buf Objects:\n"); + seq_puts(s, "size\tflags\tmode\tcount\texp_name\n"); list_for_each_entry(buf_obj, &db_list.head, list_node) { ret = mutex_lock_interruptible(&buf_obj->lock); if (ret) { - seq_printf(s, - "\tERROR locking buffer object: skipping\n"); + seq_puts(s, + "\tERROR locking buffer object: skipping\n"); continue; } - seq_printf(s, "\t"); - - seq_printf(s, "\t%s\t%08zu\t%08x\t%08x\t%08ld\n", - buf_obj->exp_name, buf_obj->size, + seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n", + buf_obj->size, buf_obj->file->f_flags, buf_obj->file->f_mode, - (long)(buf_obj->file->f_count.counter)); + (long)(buf_obj->file->f_count.counter), + buf_obj->exp_name); - seq_printf(s, "\t\tAttached Devices:\n"); + seq_puts(s, "\tAttached Devices:\n"); attach_count = 0; list_for_each_entry(attach_obj, &buf_obj->attachments, node) { - seq_printf(s, "\t\t"); + seq_puts(s, "\t"); - seq_printf(s, "%s\n", attach_obj->dev->init_name); + seq_printf(s, "%s\n", dev_name(attach_obj->dev)); attach_count++; } - seq_printf(s, "\n\t\tTotal %d devices attached\n", + seq_printf(s, "Total %d devices attached\n\n", attach_count); count++; diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index dfac5ed..f886985 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -171,7 +171,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops, size_t size, int flags, const char *); #define dma_buf_export(priv, ops, size, flags) \ - dma_buf_export_named(priv, ops, size, flags, __FILE__) + dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME) int dma_buf_fd(struct dma_buf *dmabuf, int flags); struct dma_buf *dma_buf_get(int fd); -- cgit v0.10.2 From 205e2210daa975d92ace485a65a31ccc4077fe1a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 12 Feb 2014 15:15:05 +0200 Subject: iwlwifi: disable TX AMPDU by default for iwldvm NICs supported by iwldvm don't handle well TX AMPDU. Disable it by default, still leave the possibility to the user to force enable it with a debug parameter. NICs supported by iwlmvm don't suffer from the same issue, leave TX AMPDU enabled by default for these. Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index c24d1d3..73086c1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -696,6 +696,24 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } +static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + return false; + return true; +} + +static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + return false; + if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) + return true; + + /* disabled by default */ + return false; +} + static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, @@ -717,7 +735,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + if (!iwl_enable_rx_ampdu(priv->cfg)) break; IWL_DEBUG_HT(priv, "start Rx\n"); ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn); @@ -729,7 +747,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_START: if (!priv->trans->ops->txq_enable) break; - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + if (!iwl_enable_tx_ampdu(priv->cfg)) break; IWL_DEBUG_HT(priv, "start Tx\n"); ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index c372816..7510355 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1286,7 +1286,7 @@ module_param_named(swcrypto, iwlwifi_mod_params.sw_crypto, int, S_IRUGO); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO); MODULE_PARM_DESC(11n_disable, - "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); + "disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX"); module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, int, S_IRUGO); MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 0a84ade..b29075c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -79,9 +79,12 @@ enum iwl_power_level { IWL_POWER_NUM }; -#define IWL_DISABLE_HT_ALL BIT(0) -#define IWL_DISABLE_HT_TXAGG BIT(1) -#define IWL_DISABLE_HT_RXAGG BIT(2) +enum iwl_disable_11n { + IWL_DISABLE_HT_ALL = BIT(0), + IWL_DISABLE_HT_TXAGG = BIT(1), + IWL_DISABLE_HT_RXAGG = BIT(2), + IWL_ENABLE_HT_TXAGG = BIT(3), +}; /** * struct iwl_mod_params @@ -90,7 +93,7 @@ enum iwl_power_level { * * @sw_crypto: using hardware encryption, default = 0 * @disable_11n: disable 11n capabilities, default = 0, - * use IWL_DISABLE_HT_* constants + * use IWL_[DIS,EN]ABLE_HT_* constants * @amsdu_size_8K: enable 8K amsdu size, default = 0 * @restart_fw: restart firmware, default = 1 * @wd_disable: enable stuck queue check, default = 0 diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 6bf9766..c35b866 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -328,6 +328,24 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, ieee80211_free_txskb(hw, skb); } +static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + return false; + return true; +} + +static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + return false; + if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) + return true; + + /* enabled by default */ + return true; +} + static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, @@ -347,7 +365,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) { + if (!iwl_enable_rx_ampdu(mvm->cfg)) { ret = -EINVAL; break; } @@ -357,7 +375,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); break; case IEEE80211_AMPDU_TX_START: - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) { + if (!iwl_enable_tx_ampdu(mvm->cfg)) { ret = -EINVAL; break; } -- cgit v0.10.2 From 06521c2e4a049504675f64f0a7e6d882fd364bc1 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:05 -0700 Subject: ACPI / AC: fix AC driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI AC driver defines acpi_ac_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: drivers/acpi/ac.c:248:8: error: ‘acpi_ac_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index e7515aa..6f190bc 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -243,6 +243,8 @@ static int acpi_ac_resume(struct device *dev) kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); return 0; } +#else +#define acpi_ac_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume); -- cgit v0.10.2 From 7f6895c60f40354b5adf0320ea5ef8e47cf475c9 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:06 -0700 Subject: ACPI / battery: fix battery driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI battery driver defines acpi_battery_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: drivers/acpi/battery.c:847:8: error: ‘acpi_battery_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 018a428..797a693 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -841,6 +841,8 @@ static int acpi_battery_resume(struct device *dev) acpi_battery_update(battery); return 0; } +#else +#define acpi_battery_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume); -- cgit v0.10.2 From 2de9fd17c0359fea0c2ab5ae393c40d6d299bcaf Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:07 -0700 Subject: ACPI / button: fix button driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI button driver defines acpi_button_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: drivers/acpi/button.c:85:8: error: ‘acpi_button_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 11c11f6..714e957 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -80,6 +80,8 @@ static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP static int acpi_button_resume(struct device *dev); +#else +#define acpi_button_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); -- cgit v0.10.2 From b108e0ea94a33f85590959a7a7fbcfd6f8ea8ab6 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:08 -0700 Subject: ACPI / fan: fix fan driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI fan driver defines acpi_fan_suspend() and acpi_fan_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile errors when CONFIG_PM_SLEEP is undefined: drivers/acpi/fan.c:60:8: error: ‘acpi_fan_suspend’ undeclared here (not in a function) drivers/acpi/fan.c:60:8: error: ‘acpi_fan_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 1fb6290..09e423f 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -55,6 +55,9 @@ MODULE_DEVICE_TABLE(acpi, fan_device_ids); #ifdef CONFIG_PM_SLEEP static int acpi_fan_suspend(struct device *dev); static int acpi_fan_resume(struct device *dev); +#else +#define acpi_fan_suspend NULL +#define acpi_fan_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume); -- cgit v0.10.2 From 15029dd7948c4a7adc0860e1750a2a0bba87c473 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:09 -0700 Subject: ACPI / SBS: fix SBS driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI SBS driver defines acpi_sbs_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: CC [M] drivers/acpi/sbs.o drivers/acpi/sbs.c:674:8: error: ‘acpi_sbs_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index d465ae6..48c92c6 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -668,6 +668,8 @@ static int acpi_sbs_resume(struct device *dev) acpi_sbs_callback(sbs); return 0; } +#else +#define acpi_sbs_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume); -- cgit v0.10.2 From fae9e2a4b1c59d11edfa7c99c34293bf9fbf2bde Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:10 -0700 Subject: ACPI / thermal: fix thermal driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI thermal driver defines acpi_thermal_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined. CC drivers/acpi/thermal.o drivers/acpi/thermal.c:107:8: error: ‘acpi_thermal_resume’ undeclared here (not in a function) make[2]: *** [drivers/acpi/thermal.o] Error 1 Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 8349a55..08626c8 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -102,6 +102,8 @@ MODULE_DEVICE_TABLE(acpi, thermal_device_ids); #ifdef CONFIG_PM_SLEEP static int acpi_thermal_resume(struct device *dev); +#else +#define acpi_thermal_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume); -- cgit v0.10.2 From 32a90512055b300587cceead9127f41e311e01aa Mon Sep 17 00:00:00 2001 From: "Luis G.F" Date: Mon, 10 Feb 2014 11:36:42 +0100 Subject: ACPI / SBS: Fix incorrect sscanf() string Fix incorrect sscanf() string in function acpi_battery_alarm_store(). Signed-off-by: Luis G.F Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index d465ae6..02d0c21 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -450,7 +450,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, { unsigned long x; struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - if (sscanf(buf, "%ld\n", &x) == 1) + if (sscanf(buf, "%lu\n", &x) == 1) battery->alarm_capacity = x / (1000 * acpi_battery_scale(battery)); if (battery->present) -- cgit v0.10.2 From 04eada25d1f72efdecd32d702706594f81de65d5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 11 Feb 2014 11:52:04 +0200 Subject: drm/i915/dp: increase native aux defer retry timeout Give more slack to sink devices before retrying on native aux defer. AFAICT the 100 us timeout was not based on the DP spec. Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org (on Jani's request) Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2f517b8..c3696048 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -556,7 +556,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) break; else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) - udelay(100); + usleep_range(400, 500); else return -EIO; } @@ -608,7 +608,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, return ret - 1; } else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) - udelay(100); + usleep_range(400, 500); else return -EIO; } -- cgit v0.10.2 From f51a44b9a6c4982cc25bfb3727de9bb893621ebc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 11 Feb 2014 11:52:05 +0200 Subject: drm/i915/dp: add native aux defer retry limit Retrying indefinitely places too much trust on the aux implementation of the sink devices. Reported-by: Daniel Martin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71267 Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org Tested-by: Theodore Ts'o Tested-by: Sree Harsha Totakura Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c3696048..57552eb 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -537,6 +537,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, uint8_t msg[20]; int msg_bytes; uint8_t ack; + int retry; if (WARN_ON(send_bytes > 16)) return -E2BIG; @@ -548,19 +549,21 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, msg[3] = send_bytes - 1; memcpy(&msg[4], send, send_bytes); msg_bytes = send_bytes + 4; - for (;;) { + for (retry = 0; retry < 7; retry++) { ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1); if (ret < 0) return ret; ack >>= 4; if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) - break; + return send_bytes; else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) usleep_range(400, 500); else return -EIO; } - return send_bytes; + + DRM_ERROR("too many retries, giving up\n"); + return -EIO; } /* Write a single byte to the aux channel in native mode */ @@ -582,6 +585,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, int reply_bytes; uint8_t ack; int ret; + int retry; if (WARN_ON(recv_bytes > 19)) return -E2BIG; @@ -595,7 +599,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, msg_bytes = 4; reply_bytes = recv_bytes + 1; - for (;;) { + for (retry = 0; retry < 7; retry++) { ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, reply, reply_bytes); if (ret == 0) @@ -612,6 +616,9 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, else return -EIO; } + + DRM_ERROR("too many retries, giving up\n"); + return -EIO; } static int -- cgit v0.10.2 From 86bb4f697a964ab5e50f1159e04c6a5d5acde2d4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Feb 2014 10:47:20 -0700 Subject: PCI/MSI: Check kmalloc() return value, fix leak of name Coverity reported that I forgot to check the return value of kmalloc() when creating the MSI attribute name, so fix that up and properly free it if there is an error when allocating the msi_dev_attr variable. Found by Coverity (CID 1163315 and 1163316). Fixes: 1c51b50c2995 ("PCI/MSI: Export MSI mode using attributes, not kobjects") Signed-off-by: Greg Kroah-Hartman Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7a0fec6..39dff3f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -545,9 +545,15 @@ static int populate_msi_sysfs(struct pci_dev *pdev) return -ENOMEM; list_for_each_entry(entry, &pdev->msi_list, list) { char *name = kmalloc(20, GFP_KERNEL); + if (!name) + goto error_attrs; + msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); - if (!msi_dev_attr) + if (!msi_dev_attr) { + kfree(name); goto error_attrs; + } + sprintf(name, "%d", entry->irq); sysfs_attr_init(&msi_dev_attr->attr); msi_dev_attr->attr.name = name; -- cgit v0.10.2 From 29237756477d5e777e39257d94af449fc66026c2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Feb 2014 10:47:35 -0700 Subject: PCI/MSI: Fix leak of msi_attrs Coverity reported that I forgot to clean up some allocated memory on the error path in populate_msi_sysfs(), so this patch fixes that. Thanks to Dave Jones for pointing out where the error was, I obviously can't read code this morning... Found by Coverity (CID 1163317). Fixes: 1c51b50c2995 ("PCI/MSI: Export MSI mode using attributes, not kobjects") Signed-off-by: Greg Kroah-Hartman Signed-off-by: Bjorn Helgaas Cc: Dave Jones diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 39dff3f..6f0474e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -595,6 +595,7 @@ error_attrs: ++count; msi_attr = msi_attrs[count]; } + kfree(msi_attrs); return ret; } -- cgit v0.10.2 From 75ce2d53cef8ea964634583ba45d6323ba5be243 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 13 Feb 2014 10:47:44 -0700 Subject: PCI/MSI: Fix pci_msix_vec_count() htmldocs failure An empty line in msi.c caused "make htmldocs" failure: Warning(/home/iida/Repo/linux-next//drivers/pci/msi.c:962): bad line: Fixes: ff1aa430a2fa ("PCI/MSI: Add pci_msix_vec_count()") Signed-off-by: Masanari Iida Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 6f0474e..955ab79 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -966,7 +966,6 @@ EXPORT_SYMBOL(pci_disable_msi); /** * pci_msix_vec_count - return the number of device's MSI-X table entries * @dev: pointer to the pci_dev data structure of MSI-X device function - * This function returns the number of device's MSI-X table entries and * therefore the number of MSI-X vectors device is capable of sending. * It returns a negative errno if the device is not capable of sending MSI-X -- cgit v0.10.2 From 7918b2dc66055772eecac28d7219ea679bdde420 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 13 Feb 2014 10:47:51 -0700 Subject: PCI/MSI: Add pci_enable_msi() documentation back We deprecated pci_enable_msi() in 302a2523c277 ("PCI/MSI: Add pci_enable_msi_range() and pci_enable_msix_range()"). But we changed our minds after noticing that: - pci_enable_msi() doesn't have confusing return values like pci_enable_msi_block() and pci_enable_msix() did, and - pci_enable_msi() has a hundred or so callers that we don't want to change. This adds back the pci_enable_msi() documentation. [bhelgaas: changelog] Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index a8d0100..3c3080e 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -82,7 +82,19 @@ Most of the hard work is done for the driver in the PCI layer. It simply has to request that the PCI layer set up the MSI capability for this device. -4.2.1 pci_enable_msi_range +4.2.1 pci_enable_msi + +int pci_enable_msi(struct pci_dev *dev) + +A successful call allocates ONE interrupt to the device, regardless +of how many MSIs the device supports. The device is switched from +pin-based interrupt mode to MSI mode. The dev->irq number is changed +to a new number which represents the message signaled interrupt; +consequently, this function should be called before the driver calls +request_irq(), because an MSI is delivered via a vector that is +different from the vector of a pin-based interrupt. + +4.2.2 pci_enable_msi_range int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) @@ -158,7 +170,12 @@ static int foo_driver_enable_single_msi(struct pci_dev *pdev) return pci_enable_msi_range(pdev, 1, 1); } -4.2.2 pci_disable_msi +Note, unlike pci_enable_msi() function, which could be also used to +enable the single MSI mode, pci_enable_msi_range() returns either a +negative errno or 1 (not negative errno or 0 - as pci_enable_msi() +does). + +4.2.3 pci_disable_msi void pci_disable_msi(struct pci_dev *dev) @@ -172,7 +189,7 @@ on any interrupt for which it previously called request_irq(). Failure to do so results in a BUG_ON(), leaving the device with MSI enabled and thus leaking its vector. -4.2.3 pci_msi_vec_count +4.2.4 pci_msi_vec_count int pci_msi_vec_count(struct pci_dev *dev) -- cgit v0.10.2 From 13f9653dab9a5d350a560c435a0f3d90ff7905ef Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 13 Feb 2014 10:47:56 -0700 Subject: PCI/MSI: Fix cut-and-paste errors in documentation Function pci_enable_msi_range() is used in examples where pci_enable_msix_range() should have been used instead. Reported-by: Bjorn Helgaas Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index 3c3080e..96ee5eb 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -274,8 +274,8 @@ possible, likely up to the limit returned by pci_msix_vec_count() function: static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) { - return pci_enable_msi_range(adapter->pdev, adapter->msix_entries, - 1, nvec); + return pci_enable_msix_range(adapter->pdev, adapter->msix_entries, + 1, nvec); } Note the value of 'minvec' parameter is 1. As 'minvec' is inclusive, @@ -286,8 +286,8 @@ In this case the function could look like this: static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) { - return pci_enable_msi_range(adapter->pdev, adapter->msix_entries, - FOO_DRIVER_MINIMUM_NVEC, nvec); + return pci_enable_msix_range(adapter->pdev, adapter->msix_entries, + FOO_DRIVER_MINIMUM_NVEC, nvec); } 4.3.1.2 Exact number of MSI-X interrupts @@ -299,8 +299,8 @@ parameters: static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) { - return pci_enable_msi_range(adapter->pdev, adapter->msix_entries, - nvec, nvec); + return pci_enable_msix_range(adapter->pdev, adapter->msix_entries, + nvec, nvec); } 4.3.1.3 Specific requirements to the number of MSI-X interrupts -- cgit v0.10.2 From 3ce4e860e578f843db36a1f7357ba00aeaa7610f Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 13 Feb 2014 10:48:02 -0700 Subject: PCI/MSI: Add pci_enable_msi_exact() and pci_enable_msix_exact() The new functions are special cases for pci_enable_msi_range() and pci_enable_msix_range() when a particular number of MSI or MSI-X is needed. By contrast with pci_enable_msi_range() and pci_enable_msix_range() functions, pci_enable_msi_exact() and pci_enable_msix_exact() return zero in case of success, which indicates MSI or MSI-X interrupts have been successfully allocated. Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index 96ee5eb..10a9369 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -159,6 +159,11 @@ static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec) return pci_enable_msi_range(pdev, nvec, nvec); } +Note, unlike pci_enable_msi_exact() function, which could be also used to +enable a particular number of MSI-X interrupts, pci_enable_msi_range() +returns either a negative errno or 'nvec' (not negative errno or 0 - as +pci_enable_msi_exact() does). + 4.2.1.3 Single MSI mode The most notorious example of the request type described above is @@ -175,7 +180,22 @@ enable the single MSI mode, pci_enable_msi_range() returns either a negative errno or 1 (not negative errno or 0 - as pci_enable_msi() does). -4.2.3 pci_disable_msi +4.2.3 pci_enable_msi_exact + +int pci_enable_msi_exact(struct pci_dev *dev, int nvec) + +This variation on pci_enable_msi_range() call allows a device driver to +request exactly 'nvec' MSIs. + +If this function returns a negative number, it indicates an error and +the driver should not attempt to request any more MSI interrupts for +this device. + +By contrast with pci_enable_msi_range() function, pci_enable_msi_exact() +returns zero in case of success, which indicates MSI interrupts have been +successfully allocated. + +4.2.4 pci_disable_msi void pci_disable_msi(struct pci_dev *dev) @@ -303,6 +323,11 @@ static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) nvec, nvec); } +Note, unlike pci_enable_msix_exact() function, which could be also used to +enable a particular number of MSI-X interrupts, pci_enable_msix_range() +returns either a negative errno or 'nvec' (not negative errno or 0 - as +pci_enable_msix_exact() does). + 4.3.1.3 Specific requirements to the number of MSI-X interrupts As noted above, there could be devices that can not operate with just any @@ -349,7 +374,64 @@ Note how pci_enable_msix_range() return value is analized for a fallback - any error code other than -ENOSPC indicates a fatal error and should not be retried. -4.3.2 pci_disable_msix +4.3.2 pci_enable_msix_exact + +int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) + +This variation on pci_enable_msix_range() call allows a device driver to +request exactly 'nvec' MSI-Xs. + +If this function returns a negative number, it indicates an error and +the driver should not attempt to allocate any more MSI-X interrupts for +this device. + +By contrast with pci_enable_msix_range() function, pci_enable_msix_exact() +returns zero in case of success, which indicates MSI-X interrupts have been +successfully allocated. + +Another version of a routine that enables MSI-X mode for a device with +specific requirements described in chapter 4.3.1.3 might look like this: + +/* + * Assume 'minvec' and 'maxvec' are non-zero + */ +static int foo_driver_enable_msix(struct foo_adapter *adapter, + int minvec, int maxvec) +{ + int rc; + + minvec = roundup_pow_of_two(minvec); + maxvec = rounddown_pow_of_two(maxvec); + + if (minvec > maxvec) + return -ERANGE; + +retry: + rc = pci_enable_msix_exact(adapter->pdev, + adapter->msix_entries, maxvec); + + /* + * -ENOSPC is the only error code allowed to be analyzed + */ + if (rc == -ENOSPC) { + if (maxvec == 1) + return -ENOSPC; + + maxvec /= 2; + + if (minvec > maxvec) + return -ENOSPC; + + goto retry; + } else if (rc < 0) { + return rc; + } + + return maxvec; +} + +4.3.3 pci_disable_msix void pci_disable_msix(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index fb57c89..33aa2ca 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1169,8 +1169,23 @@ void msi_remove_pci_irq_vectors(struct pci_dev *dev); void pci_restore_msi_state(struct pci_dev *dev); int pci_msi_enabled(void); int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec); +static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec) +{ + int rc = pci_enable_msi_range(dev, nvec, nvec); + if (rc < 0) + return rc; + return 0; +} int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec); +static inline int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) +{ + int rc = pci_enable_msix_range(dev, entries, nvec, nvec); + if (rc < 0) + return rc; + return 0; +} #else static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; } static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec) @@ -1189,9 +1204,14 @@ static inline int pci_msi_enabled(void) { return 0; } static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) { return -ENOSYS; } +static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec) +{ return -ENOSYS; } static inline int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec) { return -ENOSYS; } +static inline int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) +{ return -ENOSYS; } #endif #ifdef CONFIG_PCIEPORTBUS -- cgit v0.10.2 From 30ac6b6ebd175eaf5db7e0d7c015cd1460548b98 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 13 Feb 2014 14:14:21 +0100 Subject: ASoC: dapm: Consistently use unsigned int for register values Commit f7d3c1709 ("ASoC: dapm: Change prototype of soc_widget_read") changed the signature of soc_widget_read() so that it, instead of return the register value as a int, takes a pointer to a unsigned int and stores the register value in that pointer. There are still a few places that pass a int type value to that function though. Change these to unsigned int. For more consistency also change the signature of soc_widget_write() to take a unsigned int instead of an int for the register value. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dc8ff13..2c2d751 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -386,7 +386,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, return -1; } -static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val) +static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, + unsigned int val) { if (w->codec) return snd_soc_write(w->codec, reg, val); @@ -506,7 +507,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_switch: case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: { - int val; + unsigned int val; struct soc_mixer_control *mc = (struct soc_mixer_control *) w->kcontrol_news[i].private_value; int reg = mc->reg; @@ -530,7 +531,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_mux: { struct soc_enum *e = (struct soc_enum *) w->kcontrol_news[i].private_value; - int val, item; + unsigned int val, item; soc_widget_read(w, e->reg, &val); item = (val >> e->shift_l) & e->mask; @@ -559,7 +560,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_value_mux: { struct soc_enum *e = (struct soc_enum *) w->kcontrol_news[i].private_value; - int val, item; + unsigned int val, item; soc_widget_read(w, e->reg, &val); val = (val >> e->shift_l) & e->mask; -- cgit v0.10.2 From 4e52c03dfcdef5ad1415e18af0e7230d98ff3a7c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 13 Feb 2014 17:05:06 +0530 Subject: regulator: s5m8767: Use of_get_child_by_name of_find_node_by_name walks the allnodes list, and can thus walk outside of the parent node. Use of_get_child_by_name instead. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index d7164bb..092d44e 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -535,7 +535,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, return -ENODEV; } - regulators_np = of_find_node_by_name(pmic_np, "regulators"); + regulators_np = of_get_child_by_name(pmic_np, "regulators"); if (!regulators_np) { dev_err(iodev->dev, "could not find regulators sub-node\n"); return -EINVAL; -- cgit v0.10.2 From b7db01f3b3b86f6b02a98756a051d176610ca0f1 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 13 Feb 2014 17:05:07 +0530 Subject: regulator: s5m8767: Add missing of_node_put Add of_node_put to decrement the ref count. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 092d44e..d958dfa 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -591,6 +591,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, rmode++; } + of_node_put(regulators_np); + if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) { pdata->buck2_gpiodvs = true; -- cgit v0.10.2 From 71c68c4fc9bdcd6e46107a0f40b50a523f3b4fe0 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 12 Feb 2014 22:47:51 -0500 Subject: drm/i2c: tda998x: Fix memory leak in tda998x_encoder_init error path. Commit 6ae668cc19e8 (drm/i2c: tda998x: check the CEC device creation) introduced a memory leak in the error path of tda998x_encoder_init Picked up by the nightly Coverity scan. CID 1174076 Signed-off-by: Dave Jones Acked-by: Jean-Francois Moine Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index fa18cf3..faa77f5 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1151,8 +1151,10 @@ tda998x_encoder_init(struct i2c_client *client, priv->current_page = 0xff; priv->cec = i2c_new_dummy(client->adapter, 0x34); - if (!priv->cec) + if (!priv->cec) { + kfree(priv); return -ENODEV; + } priv->dpms = DRM_MODE_DPMS_OFF; encoder_slave->slave_priv = priv; -- cgit v0.10.2 From f78bccd79ba3cd9d9664981b501d57bdb81ab8a4 Mon Sep 17 00:00:00 2001 From: Olivier Langlois Date: Sat, 1 Feb 2014 01:11:09 -0500 Subject: rtlwifi: rtl8192ce: Fix too long disable of IRQs rtl8192ce is disabling for too long the local interrupts during hw initiatialisation when performing scans The observable symptoms in dmesg can be: - underruns from ALSA playback - clock freezes (tstamps do not change for several dmesg entries until irqs are finaly reenabled): [ 250.817669] rtlwifi:rtl_op_config():<0-0-0> 0x100 [ 250.817685] rtl8192ce:_rtl92ce_phy_set_rf_power_state():<0-1-0> IPS Set eRf nic enable [ 250.817732] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.817796] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.817910] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818024] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818139] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818253] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818367] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:98053f15:10 [ 250.818472] rtl8192ce:rtl92ce_sw_led_on():<0-1-0> LedAddr:4E ledpin=1 [ 250.818472] rtl8192c_common:rtl92c_download_fw():<0-1-0> Firmware Version(49), Signature(0x88c1),Size(32) [ 250.818472] rtl8192ce:rtl92ce_enable_hw_security_config():<0-1-0> PairwiseEncAlgorithm = 0 GroupEncAlgorithm = 0 [ 250.818472] rtl8192ce:rtl92ce_enable_hw_security_config():<0-1-0> The SECR-value cc [ 250.818472] rtl8192c_common:rtl92c_dm_check_txpower_tracking_thermal_meter():<0-1-0> Schedule TxPowerTracking direct call!! [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> rtl92c_dm_txpower_tracking_callback_thermalmeter [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Readback Thermal Meter = 0xe pre thermal meter 0xf eeprom_thermalmeter 0xf [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Initial pathA ele_d reg0xc80 = 0x40000000, ofdm_index=0xc [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Initial reg0xa24 = 0x90e1317, cck_index=0xc, ch14 0 [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Readback Thermal Meter = 0xe pre thermal meter 0xf eeprom_thermalmeter 0xf delta 0x1 delta_lck 0x0 delta_iqk 0x0 [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> <=== [ 250.818472] rtl8192c_common:rtl92c_dm_initialize_txpower_tracking_thermalmeter():<0-1-0> pMgntInfo->txpower_tracking = 1 [ 250.818472] rtl8192ce:rtl92ce_led_control():<0-1-0> ledaction 3 [ 250.818472] rtl8192ce:rtl92ce_sw_led_on():<0-1-0> LedAddr:4E ledpin=1 [ 250.818472] rtlwifi:rtl_ips_nic_on():<0-1-0> before spin_unlock_irqrestore [ 251.154656] PCM: Lost interrupts? [Q]-0 (stream=0, delta=15903, new_hw_ptr=293408, old_hw_ptr=277505) The exact code flow that causes that is: 1. wpa_supplicant send a start_scan request to the nl80211 driver 2. mac80211 module call rtl_op_config with IEEE80211_CONF_CHANGE_IDLE 3. rtl_ips_nic_on is called which disable local irqs 4. rtl92c_phy_set_rf_power_state() is called 5. rtl_ps_enable_nic() is called and hw_init()is executed and then the interrupts on the device are enabled A good solution could be to refactor the code to avoid calling rtl92ce_hw_init() with the irqs disabled but a quick and dirty solution that has proven to work is to reenable the irqs during the function rtl92ce_hw_init(). I think that it is safe doing so since the device interrupt will only be enabled after the init function succeed. Signed-off-by: Olivier Langlois Cc: Stable Acked-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index a82b30a..2eb0b38 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -937,14 +937,26 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) bool is92c; int err; u8 tmp_u1b; + unsigned long flags; rtlpci->being_init_adapter = true; + + /* Since this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + rtlpriv->intf_ops->disable_aspm(hw); rtstatus = _rtl92ce_init_mac(hw); if (!rtstatus) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); err = 1; - return err; + goto exit; } err = rtl92c_download_fw(hw); @@ -952,7 +964,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Failed to download FW. Init HW without FW now..\n"); err = 1; - return err; + goto exit; } rtlhal->last_hmeboxnum = 0; @@ -1032,6 +1044,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); } rtl92c_dm_init(hw); +exit: + local_irq_restore(flags); rtlpci->being_init_adapter = false; return err; } -- cgit v0.10.2 From 2e8c5e56b307271c2dab6f8bfd1d8a3822ca2390 Mon Sep 17 00:00:00 2001 From: Olivier Langlois Date: Sat, 1 Feb 2014 01:11:10 -0500 Subject: rtlwifi: Fix incorrect return from rtl_ps_enable_nic() rtl_ps_enable_nic() is called from loops that will loop until this function returns true or a maximum number of retries is performed. hw_init() returns non-zero on error. In that situation return false to restore the original design intent to retry hw init when it fails. Signed-off-by: Olivier Langlois Cc: Stable Acked-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index deedae3..d1c0191 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -48,7 +48,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /*<2> Enable Adapter */ if (rtlpriv->cfg->ops->hw_init(hw)) - return 1; + return false; RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /*<3> Enable Interrupt */ -- cgit v0.10.2 From 4a0732d1f93ff52b0e74a61302260b9417f6db61 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 7 Feb 2014 14:50:38 +0300 Subject: ath5k: shifting the wrong variable for AR5K_AR5210 In the original code we shift "AR5K_PHY(256) >> 28" which is zero but the intent was to shift the return value of ath5k_hw_reg_read() like we do a couple lines later. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index d6bc7cb..1a2973b 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -110,7 +110,7 @@ ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); if (ah->ah_version == AR5K_AR5210) { - srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; + srev = (ath5k_hw_reg_read(ah, AR5K_PHY(256)) >> 28) & 0xf; ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; } else { srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; -- cgit v0.10.2 From b6213e413a4e0c66548153516b074df14f9d08e0 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Feb 2014 22:38:28 +0100 Subject: rtl8187: fix regression on MIPS without coherent DMA This patch fixes regression caused by commit a16dad77634 "MIPS: Fix potencial corruption". That commit fixes one corruption scenario in cost of adding another one, which actually start to cause crashes on Yeeloong laptop when rtl8187 driver is used. For correct DMA read operation on machines without DMA coherence, kernel have to invalidate cache, such it will refill later with new data that device wrote to memory, when that data is needed to process. We can only invalidate full cache line. Hence when cache line includes both dma buffer and some other data (written in cache, but not yet in main memory), the other data can not hit memory due to invalidation. That happen on rtl8187 where struct rtl8187_priv fields are located just before and after small buffers that are passed to USB layer and DMA is performed on them. To fix the problem we align buffers and reserve space after them to make them match cache line. This patch does not resolve all possible MIPS problems entirely, for that we have to assure that we always map cache aligned buffers for DMA, what can be complex or even not possible. But patch fixes visible and reproducible regression and seems other possible corruptions do not happen in practice, since Yeeloong laptop works stable without rtl8187 driver. Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=54391 Reported-by: Petr Pisar Bisected-by: Tom Li Reported-and-tested-by: Tom Li Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Larry Finger Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h index 56aee06..a6ad79f 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h @@ -15,6 +15,8 @@ #ifndef RTL8187_H #define RTL8187_H +#include + #include "rtl818x.h" #include "leds.h" @@ -139,7 +141,10 @@ struct rtl8187_priv { u8 aifsn[4]; u8 rfkill_mask; struct { - __le64 buf; + union { + __le64 buf; + u8 dummy1[L1_CACHE_BYTES]; + } ____cacheline_aligned; struct sk_buff_head queue; } b_tx_status; /* This queue is used by both -b and non-b devices */ struct mutex io_mutex; @@ -147,7 +152,8 @@ struct rtl8187_priv { u8 bits8; __le16 bits16; __le32 bits32; - } *io_dmabuf; + u8 dummy2[L1_CACHE_BYTES]; + } *io_dmabuf ____cacheline_aligned; bool rfkill_off; u16 seqno; }; -- cgit v0.10.2 From 4885c8731a34eecf509822e089ce17bcd9bd4650 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Wed, 12 Feb 2014 22:38:17 +0000 Subject: hostap: fix "hostap: proc: Use remove_proc_subtree()" remove_proc_subtree() doesn't work here as local->ddev has already been removed, and NULLed out. Use proc_remove() instead. Signed-off-by: Russell King Tested-by: Russell King Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c index aa7ad3a..4e5c0f8 100644 --- a/drivers/net/wireless/hostap/hostap_proc.c +++ b/drivers/net/wireless/hostap/hostap_proc.c @@ -496,7 +496,7 @@ void hostap_init_proc(local_info_t *local) void hostap_remove_proc(local_info_t *local) { - remove_proc_subtree(local->ddev->name, hostap_proc); + proc_remove(local->proc); } -- cgit v0.10.2 From 844ae5b46c08dbc7ba695b543c023f9cf3bbf9ff Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 Feb 2014 14:09:48 -0300 Subject: perf trace: Fix ioctl 'request' beautifier build problems on !(i386 || x86_64) arches Supporting decoding the ioctl 'request' parameter needs more work to properly support more architectures, the current approach doesn't work on at least powerpc and sparc, as reported by Ben Hutchings in http://lkml.kernel.org/r/1391593985.3003.48.camel@deadeye.wl.decadent.org.uk . Work around that by making it to be ifdefed for the architectures known to work with the current, limited approach, i386 and x86_64 till better code is written. Reported-by: Ben Hutchings Acked-by: Ben Hutchings Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: # 3.13 Fixes: 78645cf3ed32 ("perf trace: Initial beautifier for ioctl's 'cmd' arg") Link: http://lkml.kernel.org/n/tip-ss04k11insqlu329xh5g02q0@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 619d11c..6aa6fb6 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -283,6 +283,11 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size, #define SCA_STRARRAY syscall_arg__scnprintf_strarray +#if defined(__i386__) || defined(__x86_64__) +/* + * FIXME: Make this available to all arches as soon as the ioctl beautifier + * gets rewritten to support all arches. + */ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size, struct syscall_arg *arg) { @@ -290,6 +295,7 @@ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size, } #define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray +#endif /* defined(__i386__) || defined(__x86_64__) */ static size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg); @@ -843,6 +849,10 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal #define SCA_SIGNUM syscall_arg__scnprintf_signum +#if defined(__i386__) || defined(__x86_64__) +/* + * FIXME: Make this available to all arches. + */ #define TCGETS 0x5401 static const char *tioctls[] = { @@ -864,6 +874,7 @@ static const char *tioctls[] = { }; static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401); +#endif /* defined(__i386__) || defined(__x86_64__) */ #define STRARRAY(arg, name, array) \ .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ @@ -945,9 +956,16 @@ static struct syscall_fmt { { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, { .name = "ioctl", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ +#if defined(__i386__) || defined(__x86_64__) +/* + * FIXME: Make this available to all arches. + */ [1] = SCA_STRHEXARRAY, /* cmd */ [2] = SCA_HEX, /* arg */ }, .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, }, +#else + [2] = SCA_HEX, /* arg */ }, }, +#endif { .name = "kill", .errmsg = true, .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, { .name = "linkat", .errmsg = true, -- cgit v0.10.2 From c7966b525fc6af6d18a509b33f938312f59b57f5 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Mon, 10 Feb 2014 21:40:51 +0100 Subject: net: fix macvtap type name in Kconfig The netlink kind (and iproute2 type option) is actually called 'macvtap', not 'macvlan'. Signed-off-by: Jan Luebbe Signed-off-by: David S. Miller diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f342278..494b888 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -139,7 +139,7 @@ config MACVTAP This adds a specialized tap character device driver that is based on the MAC-VLAN network interface, called macvtap. A macvtap device can be added in the same way as a macvlan device, using 'type - macvlan', and then be accessed through the tap user space interface. + macvtap', and then be accessed through the tap user space interface. To compile this driver as a module, choose M here: the module will be called macvtap. -- cgit v0.10.2 From d15891ca1fdd7f1f46cede1dc15bcfbf0445a658 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 11 Feb 2014 09:59:57 +0000 Subject: net: stmmac:sti: Add STi SOC glue driver. STi series SOCs have a glue layer on top of the synopsis gmac IP, this glue layer needs to be configured before the gmac driver starts using the IP. This patch adds a support to this glue layer which is configured via stmmac setup, init, exit callbacks. Signed-off-by: Srinivas Kandagatla Signed-off-by: David S. Miller diff --git a/Documentation/devicetree/bindings/net/sti-dwmac.txt b/Documentation/devicetree/bindings/net/sti-dwmac.txt new file mode 100644 index 0000000..3dd3d0b --- /dev/null +++ b/Documentation/devicetree/bindings/net/sti-dwmac.txt @@ -0,0 +1,58 @@ +STMicroelectronics SoC DWMAC glue layer controller + +The device node has following properties. + +Required properties: + - compatible : Can be "st,stih415-dwmac", "st,stih416-dwmac" or + "st,stid127-dwmac". + - reg : Offset of the glue configuration register map in system + configuration regmap pointed by st,syscon property and size. + + - reg-names : Should be "sti-ethconf". + + - st,syscon : Should be phandle to system configuration node which + encompases this glue registers. + + - st,tx-retime-src: On STi Parts for Giga bit speeds, 125Mhz clocks can be + wired up in from different sources. One via TXCLK pin and other via CLK_125 + pin. This wiring is totally board dependent. However the retiming glue + logic should be configured accordingly. Possible values for this property + + "txclk" - if 125Mhz clock is wired up via txclk line. + "clk_125" - if 125Mhz clock is wired up via clk_125 line. + + This property is only valid for Giga bit setup( GMII, RGMII), and it is + un-used for non-giga bit (MII and RMII) setups. Also note that internal + clockgen can not generate stable 125Mhz clock. + + - st,ext-phyclk: This boolean property indicates who is generating the clock + for tx and rx. This property is only valid for RMII case where the clock can + be generated from the MAC or PHY. + + - clock-names: should be "sti-ethclk". + - clocks: Should point to ethernet clockgen which can generate phyclk. + + +Example: + +ethernet0: dwmac@fe810000 { + device_type = "network"; + compatible = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710"; + reg = <0xfe810000 0x8000>, <0x8bc 0x4>; + reg-names = "stmmaceth", "sti-ethconf"; + interrupts = <0 133 0>, <0 134 0>, <0 135 0>; + interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; + phy-mode = "mii"; + + st,syscon = <&syscfg_rear>; + + snps,pbl = <32>; + snps,mixed-burst; + + resets = <&softreset STIH416_ETH0_SOFTRESET>; + reset-names = "stmmaceth"; + pinctrl-0 = <&pinctrl_mii0>; + pinctrl-names = "default"; + clocks = <&CLK_S_GMAC0_PHY>; + clock-names = "stmmaceth"; +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index e2f202e..f2d7c70 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -37,6 +37,17 @@ config DWMAC_SUNXI stmmac device driver. This driver is used for A20/A31 GMAC ethernet controller. +config DWMAC_STI + bool "STi GMAC support" + depends on STMMAC_PLATFORM && ARCH_STI + default y + ---help--- + Support for ethernet controller on STi SOCs. + + This selects STi SoC glue layer support for the stmmac + device driver. This driver is used on for the STi series + SOCs GMAC ethernet controller. + config STMMAC_PCI bool "STMMAC PCI bus support" depends on STMMAC_ETH && PCI diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index ecadece..dcef287 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o +stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c new file mode 100644 index 0000000..552bbc1 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -0,0 +1,330 @@ +/** + * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer + * + * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited + * Author: Srinivas Kandagatla + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * STi GMAC glue logic. + * -------------------- + * + * _ + * | \ + * --------|0 \ ETH_SEL_INTERNAL_NOTEXT_PHYCLK + * phyclk | |___________________________________________ + * | | | (phyclk-in) + * --------|1 / | + * int-clk |_ / | + * | _ + * | | \ + * |_______|1 \ ETH_SEL_TX_RETIME_CLK + * | |___________________________ + * | | (tx-retime-clk) + * _______|0 / + * | |_ / + * _ | + * | \ | + * --------|0 \ | + * clk_125 | |__| + * | | ETH_SEL_TXCLK_NOT_CLK125 + * --------|1 / + * txclk |_ / + * + * + * ETH_SEL_INTERNAL_NOTEXT_PHYCLK is valid only for RMII where PHY can + * generate 50MHz clock or MAC can generate it. + * This bit is configured by "st,ext-phyclk" property. + * + * ETH_SEL_TXCLK_NOT_CLK125 is only valid for gigabit modes, where the 125Mhz + * clock either comes from clk-125 pin or txclk pin. This configuration is + * totally driven by the board wiring. This bit is configured by + * "st,tx-retime-src" property. + * + * TXCLK configuration is different for different phy interface modes + * and changes according to link speed in modes like RGMII. + * + * Below table summarizes the clock requirement and clock sources for + * supported phy interface modes with link speeds. + * ________________________________________________ + *| PHY_MODE | 1000 Mbit Link | 100 Mbit Link | + * ------------------------------------------------ + *| MII | n/a | 25Mhz | + *| | | txclk | + * ------------------------------------------------ + *| GMII | 125Mhz | 25Mhz | + *| | clk-125/txclk | txclk | + * ------------------------------------------------ + *| RGMII | 125Mhz | 25Mhz | + *| | clk-125/txclk | clkgen | + * ------------------------------------------------ + *| RMII | n/a | 25Mhz | + *| | |clkgen/phyclk-in | + * ------------------------------------------------ + * + * TX lines are always retimed with a clk, which can vary depending + * on the board configuration. Below is the table of these bits + * in eth configuration register depending on source of retime clk. + * + *--------------------------------------------------------------- + * src | tx_rt_clk | int_not_ext_phyclk | txclk_n_clk125| + *--------------------------------------------------------------- + * txclk | 0 | n/a | 1 | + *--------------------------------------------------------------- + * ck_125| 0 | n/a | 0 | + *--------------------------------------------------------------- + * phyclk| 1 | 0 | n/a | + *--------------------------------------------------------------- + * clkgen| 1 | 1 | n/a | + *--------------------------------------------------------------- + */ + + /* Register definition */ + + /* 3 bits [8:6] + * [6:6] ETH_SEL_TXCLK_NOT_CLK125 + * [7:7] ETH_SEL_INTERNAL_NOTEXT_PHYCLK + * [8:8] ETH_SEL_TX_RETIME_CLK + * + */ + +#define TX_RETIME_SRC_MASK GENMASK(8, 6) +#define ETH_SEL_TX_RETIME_CLK BIT(8) +#define ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7) +#define ETH_SEL_TXCLK_NOT_CLK125 BIT(6) + +#define ENMII_MASK GENMASK(5, 5) +#define ENMII BIT(5) + +/** + * 3 bits [4:2] + * 000-GMII/MII + * 001-RGMII + * 010-SGMII + * 100-RMII +*/ +#define MII_PHY_SEL_MASK GENMASK(4, 2) +#define ETH_PHY_SEL_RMII BIT(4) +#define ETH_PHY_SEL_SGMII BIT(3) +#define ETH_PHY_SEL_RGMII BIT(2) +#define ETH_PHY_SEL_GMII 0x0 +#define ETH_PHY_SEL_MII 0x0 + +#define IS_PHY_IF_MODE_RGMII(iface) (iface == PHY_INTERFACE_MODE_RGMII || \ + iface == PHY_INTERFACE_MODE_RGMII_ID || \ + iface == PHY_INTERFACE_MODE_RGMII_RXID || \ + iface == PHY_INTERFACE_MODE_RGMII_TXID) + +#define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \ + iface == PHY_INTERFACE_MODE_GMII) + +struct sti_dwmac { + int interface; + bool ext_phyclk; + bool is_tx_retime_src_clk_125; + struct clk *clk; + int reg; + struct device *dev; + struct regmap *regmap; +}; + +static u32 phy_intf_sels[] = { + [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII, + [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII, + [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII, + [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII, + [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII, + [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII, +}; + +enum { + TX_RETIME_SRC_NA = 0, + TX_RETIME_SRC_TXCLK = 1, + TX_RETIME_SRC_CLK_125, + TX_RETIME_SRC_PHYCLK, + TX_RETIME_SRC_CLKGEN, +}; + +static const char *const tx_retime_srcs[] = { + [TX_RETIME_SRC_NA] = "", + [TX_RETIME_SRC_TXCLK] = "txclk", + [TX_RETIME_SRC_CLK_125] = "clk_125", + [TX_RETIME_SRC_PHYCLK] = "phyclk", + [TX_RETIME_SRC_CLKGEN] = "clkgen", +}; + +static u32 tx_retime_val[] = { + [TX_RETIME_SRC_TXCLK] = ETH_SEL_TXCLK_NOT_CLK125, + [TX_RETIME_SRC_CLK_125] = 0x0, + [TX_RETIME_SRC_PHYCLK] = ETH_SEL_TX_RETIME_CLK, + [TX_RETIME_SRC_CLKGEN] = ETH_SEL_TX_RETIME_CLK | + ETH_SEL_INTERNAL_NOTEXT_PHYCLK, +}; + +static void setup_retime_src(struct sti_dwmac *dwmac, u32 spd) +{ + u32 src = 0, freq = 0; + + if (spd == SPEED_100) { + if (dwmac->interface == PHY_INTERFACE_MODE_MII || + dwmac->interface == PHY_INTERFACE_MODE_GMII) { + src = TX_RETIME_SRC_TXCLK; + } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) { + if (dwmac->ext_phyclk) { + src = TX_RETIME_SRC_PHYCLK; + } else { + src = TX_RETIME_SRC_CLKGEN; + freq = 50000000; + } + + } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) { + src = TX_RETIME_SRC_CLKGEN; + freq = 25000000; + } + + if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk) + clk_set_rate(dwmac->clk, freq); + + } else if (spd == SPEED_1000) { + if (dwmac->is_tx_retime_src_clk_125) + src = TX_RETIME_SRC_CLK_125; + else + src = TX_RETIME_SRC_TXCLK; + } + + regmap_update_bits(dwmac->regmap, dwmac->reg, + TX_RETIME_SRC_MASK, tx_retime_val[src]); +} + +static void sti_dwmac_exit(struct platform_device *pdev, void *priv) +{ + struct sti_dwmac *dwmac = priv; + + if (dwmac->clk) + clk_disable_unprepare(dwmac->clk); +} + +static void sti_fix_mac_speed(void *priv, unsigned int spd) +{ + struct sti_dwmac *dwmac = priv; + + setup_retime_src(dwmac, spd); + + return; +} + +static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, + struct platform_device *pdev) +{ + struct resource *res; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct regmap *regmap; + int err; + + if (!np) + return -EINVAL; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf"); + if (!res) + return -ENODATA; + + regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon"); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + dwmac->dev = dev; + dwmac->interface = of_get_phy_mode(np); + dwmac->regmap = regmap; + dwmac->reg = res->start; + dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); + dwmac->is_tx_retime_src_clk_125 = false; + + if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) { + const char *rs; + + err = of_property_read_string(np, "st,tx-retime-src", &rs); + if (err < 0) { + dev_err(dev, "st,tx-retime-src not specified\n"); + return err; + } + + if (!strcasecmp(rs, "clk_125")) + dwmac->is_tx_retime_src_clk_125 = true; + } + + dwmac->clk = devm_clk_get(dev, "sti-ethclk"); + + if (IS_ERR(dwmac->clk)) + dwmac->clk = NULL; + + return 0; +} + +static int sti_dwmac_init(struct platform_device *pdev, void *priv) +{ + struct sti_dwmac *dwmac = priv; + struct regmap *regmap = dwmac->regmap; + int iface = dwmac->interface; + u32 reg = dwmac->reg; + u32 val, spd; + + if (dwmac->clk) + clk_prepare_enable(dwmac->clk); + + regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]); + + val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; + regmap_update_bits(regmap, reg, ENMII_MASK, val); + + if (IS_PHY_IF_MODE_GBIT(iface)) + spd = SPEED_1000; + else + spd = SPEED_100; + + setup_retime_src(dwmac, spd); + + return 0; +} + +static void *sti_dwmac_setup(struct platform_device *pdev) +{ + struct sti_dwmac *dwmac; + int ret; + + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); + if (!dwmac) + return ERR_PTR(-ENOMEM); + + ret = sti_dwmac_parse_data(dwmac, pdev); + if (ret) { + dev_err(&pdev->dev, "Unable to parse OF data\n"); + return ERR_PTR(ret); + } + + return dwmac; +} + +const struct stmmac_of_data sti_gmac_data = { + .fix_mac_speed = sti_fix_mac_speed, + .setup = sti_dwmac_setup, + .init = sti_dwmac_init, + .exit = sti_dwmac_exit, +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index d9af26e..f9e60d7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -133,6 +133,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv); #ifdef CONFIG_DWMAC_SUNXI extern const struct stmmac_of_data sun7i_gmac_data; #endif +#ifdef CONFIG_DWMAC_STI +extern const struct stmmac_of_data sti_gmac_data; +#endif extern struct platform_driver stmmac_pltfr_driver; static inline int stmmac_register_platform(void) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 5884a7d..c61bc72b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -33,6 +33,11 @@ static const struct of_device_id stmmac_dt_ids[] = { #ifdef CONFIG_DWMAC_SUNXI { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, #endif +#ifdef CONFIG_DWMAC_STI + { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data}, + { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data}, + { .compatible = "st,stih127-dwmac", .data = &sti_gmac_data}, +#endif /* SoC specific glue layers should come before generic bindings */ { .compatible = "st,spear600-gmac"}, { .compatible = "snps,dwmac-3.610"}, -- cgit v0.10.2 From 64380a04deeed4720de76b086a3a4eab8dd41671 Mon Sep 17 00:00:00 2001 From: Erik Hugne Date: Tue, 11 Feb 2014 11:38:26 +0100 Subject: tipc: fix message corruption bug for deferred packets If a packet received on a link is out-of-sequence, it will be placed on a deferred queue and later reinserted in the receive path once the preceding packets have been processed. The problem with this is that it will be subject to the buffer adjustment from link_recv_buf_validate twice. The second adjustment for 20 bytes header space will corrupt the packet. We solve this by tagging the deferred packets and bail out from receive buffer validation for packets that have already been subjected to this. Signed-off-by: Erik Hugne Reviewed-by: Jon Maloy Signed-off-by: David S. Miller diff --git a/net/tipc/core.h b/net/tipc/core.h index 1ff477b..5569d96 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -192,6 +192,7 @@ static inline void k_term_timer(struct timer_list *timer) struct tipc_skb_cb { void *handle; + bool deferred; }; #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) diff --git a/net/tipc/link.c b/net/tipc/link.c index d4b5de4..da6018b 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1391,6 +1391,12 @@ static int link_recv_buf_validate(struct sk_buff *buf) u32 hdr_size; u32 min_hdr_size; + /* If this packet comes from the defer queue, the skb has already + * been validated + */ + if (unlikely(TIPC_SKB_CB(buf)->deferred)) + return 1; + if (unlikely(buf->len < MIN_H_SIZE)) return 0; @@ -1703,6 +1709,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, &l_ptr->newest_deferred_in, buf)) { l_ptr->deferred_inqueue_sz++; l_ptr->stats.deferred_recv++; + TIPC_SKB_CB(buf)->deferred = true; if ((l_ptr->deferred_inqueue_sz % 16) == 1) tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); } else -- cgit v0.10.2 From 844fa1b5f8493cff4b976fa7a5b9ebeeafdd75cc Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 13 Feb 2014 15:40:13 -0600 Subject: jfs: set i_ctime when setting ACL This fixes a regression in 3.14-rc1 where xfstests generic/307 fails. jfs sets the ctime on the inode when writing an xattr. Previously, jfs went ahead and stored an acl that can be completely represented in the traditional permission bits, so the ctime was always set in the xattr code. The new code doesn't bother storing the acl in that case, thus the ctime isn't getting set. Signed-off-by: Dave Kleikamp Reported-by: Michael L. Semon diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index e973b85..5a8ea16 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -86,6 +86,8 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, rc = posix_acl_equiv_mode(acl, &inode->i_mode); if (rc < 0) return rc; + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); if (rc == 0) acl = NULL; break; -- cgit v0.10.2 From da37705cef30841616ed644ff33455bbc7374db0 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Feb 2014 15:51:29 -0800 Subject: macvlan: unregister net device when netdev_upper_dev_link() fails rtnl_newlink() doesn't unregister it for us on failure. Cc: Patrick McHardy Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 8433de4..a5d2189 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -879,14 +879,15 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, dev->priv_flags |= IFF_MACVLAN; err = netdev_upper_dev_link(lowerdev, dev); if (err) - goto destroy_port; - + goto unregister_netdev; list_add_tail_rcu(&vlan->list, &port->vlans); netif_stacked_transfer_operstate(lowerdev, dev); return 0; +unregister_netdev: + unregister_netdevice(dev); destroy_port: port->count -= 1; if (!port->count) -- cgit v0.10.2 From 0e0eee2465df77bcec2e8ff75432b8e57897b143 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Feb 2014 15:51:30 -0800 Subject: net: correct error path in rtnl_newlink() I saw the following BUG when ->newlink() fails in rtnl_newlink(): [ 40.240058] kernel BUG at net/core/dev.c:6438! this is due to free_netdev() is not supposed to be called before netdev is completely unregistered, therefore it is not correct to call free_netdev() here, at least for ops->newlink!=NULL case, many drivers call it in ->destructor so that rtnl_unlock() will take care of it, we probably don't need to do anything here. Cc: David S. Miller Cc: Eric Dumazet Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 048dc8d..1a0dac2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1963,16 +1963,21 @@ replay: dev->ifindex = ifm->ifi_index; - if (ops->newlink) + if (ops->newlink) { err = ops->newlink(net, dev, tb, data); - else + /* Drivers should call free_netdev() in ->destructor + * and unregister it on failure so that device could be + * finally freed in rtnl_unlock. + */ + if (err < 0) + goto out; + } else { err = register_netdevice(dev); - - if (err < 0) { - free_netdev(dev); - goto out; + if (err < 0) { + free_netdev(dev); + goto out; + } } - err = rtnl_configure_link(dev, ifm); if (err < 0) unregister_netdevice(dev); -- cgit v0.10.2 From 22a1f5140ed69baa5906ce9b2b9143478f5a4da0 Mon Sep 17 00:00:00 2001 From: wangweidong Date: Wed, 12 Feb 2014 09:44:43 +0800 Subject: sctp: fix a missed .data initialization As commit 3c68198e75111a90("sctp: Make hmac algorithm selection for cookie generation dynamic"), we miss the .data initialization. If we don't use the net_namespace, the problem that parts of the sysctl configuration won't be isolation and won't occur. In sctp_sysctl_net_register(), we register the sysctl for each net, in the for(), we use the 'table[i].data' as check condition, so when the 'i' is the index of sctp_hmac_alg, the data is NULL, then break. So add the .data initialization. Acked-by: Neil Horman Signed-off-by: Wang Weidong Signed-off-by: David S. Miller diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 7135e61..d354de5 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -151,6 +151,7 @@ static struct ctl_table sctp_net_table[] = { }, { .procname = "cookie_hmac_alg", + .data = &init_net.sctp.sctp_hmac_alg, .maxlen = 8, .mode = 0644, .proc_handler = proc_sctp_do_hmac_alg, -- cgit v0.10.2 From efb842c45e667332774196bd5a1d539d048159cc Mon Sep 17 00:00:00 2001 From: wangweidong Date: Wed, 12 Feb 2014 09:44:44 +0800 Subject: sctp: optimize the sctp_sysctl_net_register Here, when the net is init_net, we needn't to kmemdup the ctl_table again. So add a check for net. Also we can save some memory. Signed-off-by: Wang Weidong Acked-by: Neil Horman Signed-off-by: David S. Miller diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index d354de5..35c8923 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -402,15 +402,18 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, int sctp_sysctl_net_register(struct net *net) { - struct ctl_table *table; - int i; + struct ctl_table *table = sctp_net_table; + + if (!net_eq(net, &init_net)) { + int i; - table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); - if (!table) - return -ENOMEM; + table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); + if (!table) + return -ENOMEM; - for (i = 0; table[i].data; i++) - table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; + for (i = 0; table[i].data; i++) + table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; + } net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); return 0; -- cgit v0.10.2 From 455016e5dc623cb784dbaa4f197054ab87d84c76 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 11 Feb 2014 20:52:00 -0500 Subject: Documentation/networking: delete orphaned 3c505.txt file. In the commit 0e245dbaac9fa1c2fd0f4e2af7b9f6d874083a8b ("drivers/net: delete the 3Com 3c505/3c507 intel i825xx support") we clobbered the 3c505 driver (over a year ago) along with other abandoned ISA drivers. However, this orphaned README file escaped detection at that time, and has lived on until today. Get rid of it now. Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt deleted file mode 100644 index 72f38b1..0000000 --- a/Documentation/networking/3c505.txt +++ /dev/null @@ -1,45 +0,0 @@ -The 3Com Etherlink Plus (3c505) driver. - -This driver now uses DMA. There is currently no support for PIO operation. -The default DMA channel is 6; this is _not_ autoprobed, so you must -make sure you configure it correctly. If loading the driver as a -module, you can do this with "modprobe 3c505 dma=n". If the driver is -linked statically into the kernel, you must either use an "ether=" -statement on the command line, or change the definition of ELP_DMA in 3c505.h. - -The driver will warn you if it has to fall back on the compiled in -default DMA channel. - -If no base address is given at boot time, the driver will autoprobe -ports 0x300, 0x280 and 0x310 (in that order). If no IRQ is given, the driver -will try to probe for it. - -The driver can be used as a loadable module. - -Theoretically, one instance of the driver can now run multiple cards, -in the standard way (when loading a module, say "modprobe 3c505 -io=0x300,0x340 irq=10,11 dma=6,7" or whatever). I have not tested -this, though. - -The driver may now support revision 2 hardware; the dependency on -being able to read the host control register has been removed. This -is also untested, since I don't have a suitable card. - -Known problems: - I still see "DMA upload timed out" messages from time to time. These -seem to be fairly non-fatal though. - The card is old and slow. - -To do: - Improve probe/setup code - Test multicast and promiscuous operation - -Authors: - The driver is mainly written by Craig Southeren, email - . - Parts of the driver (adapting the driver to 1.1.4+ kernels, - IRQ/address detection, some changes) and this README by - Juha Laiho . - DMA mode, more fixes, etc, by Philip Blundell - Multicard support, Software configurable DMA, etc., by - Christopher Collins -- cgit v0.10.2 From f80889a5b79cae0b84465a90c21b1273a03b7973 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Wed, 12 Feb 2014 12:06:40 +0800 Subject: bonding: Fix deadlock in bonding driver when using netpoll The bonding driver take write locks and spin locks that are shared by the tx path in enslave processing and notification processing, If the netconsole is in use, the bonding can call printk which puts us in the netpoll tx path, if the netconsole is attached to the bonding driver, result in deadlock. So add protection for these place, by checking the netpoll_block_tx state, we can defer the sending of the netconsole frames until a later time using the retransmit feature of netpoll_send_skb that is triggered on the return code NETDEV_TX_BUSY. Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 71ba18e..8676649 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1543,9 +1543,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_carrier(bond); if (USES_PRIMARY(bond->params.mode)) { + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); } pr_info("%s: enslaving %s as a%s interface with a%s link.\n", @@ -1571,10 +1573,12 @@ err_detach: if (bond->primary_slave == new_slave) bond->primary_slave = NULL; if (bond->curr_active_slave == new_slave) { + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_change_active_slave(bond, NULL); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); } slave_disable_netpoll(new_slave); @@ -2864,9 +2868,12 @@ static int bond_slave_netdev_event(unsigned long event, pr_info("%s: Primary slave changed to %s, reselecting active slave.\n", bond->dev->name, bond->primary_slave ? slave_dev->name : "none"); + + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); break; case NETDEV_FEAT_CHANGE: bond_compute_features(bond); -- cgit v0.10.2 From d206940319c41df4299db75ed56142177bb2e5f6 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 13 Feb 2014 23:09:11 +0100 Subject: net: core: introduce netif_skb_dev_features Will be used by upcoming ipv4 forward path change that needs to determine feature mask using skb->dst->dev instead of skb->dev. Signed-off-by: Florian Westphal Signed-off-by: David S. Miller diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 440a02e..21d4e6b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3068,7 +3068,12 @@ void netdev_change_features(struct net_device *dev); void netif_stacked_transfer_operstate(const struct net_device *rootdev, struct net_device *dev); -netdev_features_t netif_skb_features(struct sk_buff *skb); +netdev_features_t netif_skb_dev_features(struct sk_buff *skb, + const struct net_device *dev); +static inline netdev_features_t netif_skb_features(struct sk_buff *skb) +{ + return netif_skb_dev_features(skb, skb->dev); +} static inline bool net_gso_ok(netdev_features_t features, int gso_type) { diff --git a/net/core/dev.c b/net/core/dev.c index 4ad1b78..b1b0c8d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2420,7 +2420,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault); * 2. No high memory really exists on this machine. */ -static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) +static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb) { #ifdef CONFIG_HIGHMEM int i; @@ -2495,34 +2495,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) } static netdev_features_t harmonize_features(struct sk_buff *skb, - netdev_features_t features) + const struct net_device *dev, + netdev_features_t features) { if (skb->ip_summed != CHECKSUM_NONE && !can_checksum_protocol(features, skb_network_protocol(skb))) { features &= ~NETIF_F_ALL_CSUM; - } else if (illegal_highdma(skb->dev, skb)) { + } else if (illegal_highdma(dev, skb)) { features &= ~NETIF_F_SG; } return features; } -netdev_features_t netif_skb_features(struct sk_buff *skb) +netdev_features_t netif_skb_dev_features(struct sk_buff *skb, + const struct net_device *dev) { __be16 protocol = skb->protocol; - netdev_features_t features = skb->dev->features; + netdev_features_t features = dev->features; - if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) + if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs) features &= ~NETIF_F_GSO_MASK; if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; } else if (!vlan_tx_tag_present(skb)) { - return harmonize_features(skb, features); + return harmonize_features(skb, dev, features); } - features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | + features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX); if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) @@ -2530,9 +2532,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; - return harmonize_features(skb, features); + return harmonize_features(skb, dev, features); } -EXPORT_SYMBOL(netif_skb_features); +EXPORT_SYMBOL(netif_skb_dev_features); int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq) -- cgit v0.10.2 From fe6cc55f3a9a053482a76f5a6b2257cee51b4663 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 13 Feb 2014 23:09:12 +0100 Subject: net: ip, ipv6: handle gso skbs in forwarding path Marcelo Ricardo Leitner reported problems when the forwarding link path has a lower mtu than the incoming one if the inbound interface supports GRO. Given: Host R1 R2 Host sends tcp stream which is routed via R1 and R2. R1 performs GRO. In this case, the kernel will fail to send ICMP fragmentation needed messages (or pkt too big for ipv6), as GSO packets currently bypass dstmtu checks in forward path. Instead, Linux tries to send out packets exceeding the mtu. When locking route MTU on Host (i.e., no ipv4 DF bit set), R1 does not fragment the packets when forwarding, and again tries to send out packets exceeding R1-R2 link mtu. This alters the forwarding dstmtu checks to take the individual gso segment lengths into account. For ipv6, we send out pkt too big error for gso if the individual segments are too big. For ipv4, we either send icmp fragmentation needed, or, if the DF bit is not set, perform software segmentation and let the output path create fragments when the packet is leaving the machine. It is not 100% correct as the error message will contain the headers of the GRO skb instead of the original/segmented one, but it seems to work fine in my (limited) tests. Eric Dumazet suggested to simply shrink mss via ->gso_size to avoid sofware segmentation. However it turns out that skb_segment() assumes skb nr_frags is related to mss size so we would BUG there. I don't want to mess with it considering Herbert and Eric disagree on what the correct behavior should be. Hannes Frederic Sowa notes that when we would shrink gso_size skb_segment would then also need to deal with the case where SKB_MAX_FRAGS would be exceeded. This uses sofware segmentation in the forward path when we hit ipv4 non-DF packets and the outgoing link mtu is too small. Its not perfect, but given the lack of bug reports wrt. GRO fwd being broken this is a rare case anyway. Also its not like this could not be improved later once the dust settles. Acked-by: Herbert Xu Reported-by: Marcelo Ricardo Leitner Signed-off-by: Florian Westphal Signed-off-by: David S. Miller diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f589c9af..3ebbbe7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2916,5 +2916,22 @@ static inline bool skb_head_is_locked(const struct sk_buff *skb) { return !skb->head_frag || skb_cloned(skb); } + +/** + * skb_gso_network_seglen - Return length of individual segments of a gso packet + * + * @skb: GSO skb + * + * skb_gso_network_seglen is used to determine the real size of the + * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP). + * + * The MAC/L2 header is not accounted for. + */ +static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb) +{ + unsigned int hdr_len = skb_transport_header(skb) - + skb_network_header(skb); + return hdr_len + skb_gso_transport_seglen(skb); +} #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index e9f1217..f3869c1 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -39,6 +39,71 @@ #include #include +static bool ip_may_fragment(const struct sk_buff *skb) +{ + return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) || + !skb->local_df; +} + +static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +{ + if (skb->len <= mtu || skb->local_df) + return false; + + if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) + return false; + + return true; +} + +static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb) +{ + unsigned int mtu; + + if (skb->local_df || !skb_is_gso(skb)) + return false; + + mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true); + + /* if seglen > mtu, do software segmentation for IP fragmentation on + * output. DF bit cannot be set since ip_forward would have sent + * icmp error. + */ + return skb_gso_network_seglen(skb) > mtu; +} + +/* called if GSO skb needs to be fragmented on forward */ +static int ip_forward_finish_gso(struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + netdev_features_t features; + struct sk_buff *segs; + int ret = 0; + + features = netif_skb_dev_features(skb, dst->dev); + segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); + if (IS_ERR(segs)) { + kfree_skb(skb); + return -ENOMEM; + } + + consume_skb(skb); + + do { + struct sk_buff *nskb = segs->next; + int err; + + segs->next = NULL; + err = dst_output(segs); + + if (err && ret == 0) + ret = err; + segs = nskb; + } while (segs); + + return ret; +} + static int ip_forward_finish(struct sk_buff *skb) { struct ip_options *opt = &(IPCB(skb)->opt); @@ -49,6 +114,9 @@ static int ip_forward_finish(struct sk_buff *skb) if (unlikely(opt->optlen)) ip_forward_options(skb); + if (ip_gso_exceeds_dst_mtu(skb)) + return ip_forward_finish_gso(skb); + return dst_output(skb); } @@ -91,8 +159,7 @@ int ip_forward(struct sk_buff *skb) IPCB(skb)->flags |= IPSKB_FORWARDED; mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); - if (unlikely(skb->len > mtu && !skb_is_gso(skb) && - (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { + if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) { IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ef02b26..070a2fa 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -342,6 +342,20 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) return mtu; } +static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) +{ + if (skb->len <= mtu || skb->local_df) + return false; + + if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu) + return true; + + if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) + return false; + + return true; +} + int ip6_forward(struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); @@ -466,8 +480,7 @@ int ip6_forward(struct sk_buff *skb) if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; - if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) || - (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) { + if (ip6_pkt_too_big(skb, mtu)) { /* Again, force OUTPUT device used as source address */ skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); -- cgit v0.10.2 From d26794c04553901d00c4ca1542e1cbf4ec9580fb Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Sat, 21 Dec 2013 16:12:23 +0100 Subject: ARM: dts: omap3-gta04: Add EOC irq gpio line handling. BMP085 EOC (End Of Conversion) irq line is connected to gpio113 on gta04. Set irq properties to have driver using irq instead polling for EOC. Signed-off-by: Marek Belisko Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index b9b55c9..7a8e37d 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts @@ -92,6 +92,8 @@ bmp085@77 { compatible = "bosch,bmp085"; reg = <0x77>; + interrupt-parent = <&gpio4>; + interrupts = <17 IRQ_TYPE_EDGE_RISING>; }; /* leds */ -- cgit v0.10.2 From 967d6a0bbfddcc25a7d1debbe8e2e4e7161d0566 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 23 Dec 2013 11:28:34 +0200 Subject: ARM: DTS: am335x-evmsk: Correct audio clock frequency The clock for audio is sourced from virt_24000000_ck, so the correct frequency is 24000000. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index 4718ec4..50abe53 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -121,7 +121,7 @@ ti,model = "AM335x-EVMSK"; ti,audio-codec = <&tlv320aic3106>; ti,mcasp-controller = <&mcasp1>; - ti,codec-clock-rate = <24576000>; + ti,codec-clock-rate = <24000000>; ti,audio-routing = "Headphone Jack", "HPLOUT", "Headphone Jack", "HPROUT"; -- cgit v0.10.2 From 29ea5efb0bb612d352aa360de26e2095cb230e4a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 23 Dec 2013 11:28:35 +0200 Subject: ARM: dts: am335x-evmsk: Fix mmc1 support Add pinctrl section and cd-gpio to mmc1. Without these the SD card is not working on EVM-SK board. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index 50abe53..486880b 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -256,6 +256,12 @@ >; }; + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + mcasp1_pins: mcasp1_pins { pinctrl-single,pins = < 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ @@ -456,6 +462,9 @@ status = "okay"; vmmc-supply = <&vmmc_reg>; bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; }; &sham { -- cgit v0.10.2 From 22106c11252833419a29c9294411101cb2199a5f Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 15 Jan 2014 14:00:38 -0600 Subject: ARM: OMAP2+: add missing ARCH_HAS_OPP OMAP5, DRA7, AM43xx all have OPPs. So select the same to allow SoC only configuration boot to work with OPP. Reported-by: Nikhil Devshatwar Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 653b489..8165a4a 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -50,6 +50,7 @@ config SOC_OMAP5 bool "TI OMAP5" depends on ARCH_MULTI_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select ARM_GIC select CPU_V7 @@ -63,6 +64,7 @@ config SOC_AM33XX bool "TI AM33XX" depends on ARCH_MULTI_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select CPU_V7 select MULTI_IRQ_HANDLER @@ -72,6 +74,7 @@ config SOC_AM43XX depends on ARCH_MULTI_V7 select CPU_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select MULTI_IRQ_HANDLER select ARM_GIC select MACH_OMAP_GENERIC @@ -80,6 +83,7 @@ config SOC_DRA7XX bool "TI DRA7XX" depends on ARCH_MULTI_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select ARM_GIC select CPU_V7 -- cgit v0.10.2 From d8bd67317455744039e10fe33d6c76b82262c647 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 25 Jan 2014 22:28:55 +0100 Subject: ARM: dts: omap3-gta04: Fix 'aux' gpio key flags. It should be ACTIVE_HIGH. Signed-off-by: NeilBrown Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index 7a8e37d..81e0bb4 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts @@ -32,7 +32,7 @@ aux-button { label = "aux"; linux,code = <169>; - gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; gpio-key,wakeup; }; }; -- cgit v0.10.2 From 2d6ac29e6a043c3adc3e82f5200ae1e07617e3ea Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Sat, 25 Jan 2014 22:28:57 +0100 Subject: ARM: dts: omap3-gta04: Fix mmc1 properties. Does not have an aux supply, and must be non-removable. Otherwise it is removed during suspend and filesystem gets confused. Signed-off-by: NeilBrown Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index 81e0bb4..c551e4a 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts @@ -143,8 +143,8 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc1_pins>; vmmc-supply = <&vmmc1>; - vmmc_aux-supply = <&vsim>; bus-width = <4>; + ti,non-removable; }; &mmc2 { -- cgit v0.10.2 From 9d5e8ec6571293cb8a5321176d74d559d2d38542 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 Feb 2014 08:10:42 +0100 Subject: net: axienet: Fix compilation error Add missing header to fix compilation error. drivers/net/ethernet/xilinx/xilinx_axienet_main.c:1575:22: error: undefined identifier 'irq_of_parse_and_map' drivers/net/ethernet/xilinx/xilinx_axienet_main.c:1576:22: error: undefined identifier 'irq_of_parse_and_map' Signed-off-by: Michal Simek Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 1ec65fe..9fb8ab2 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From 91ff37ff0b898e1ac8a1557b968a4918250f22ae Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 Feb 2014 08:10:43 +0100 Subject: net: axienet: Fix compilation warnings Warning log: xilinx_axienet_main.c: In function 'axienet_start_xmit_done': xilinx_axienet_main.c:617:16: warning: operation on 'lp->tx_bd_ci' may be undefined [-Wsequence-point] xilinx_axienet_main.c: In function 'axienet_start_xmit': xilinx_axienet_main.c:703:18: warning: operation on 'lp->tx_bd_tail' may be undefined [-Wsequence-point] xilinx_axienet_main.c:719:17: warning: operation on 'lp->tx_bd_tail' may be undefined [-Wsequence-point] xilinx_axienet_main.c: In function 'axienet_recv': xilinx_axienet_main.c:792:16: warning: operation on 'lp->rx_bd_ci' may be undefined [-Wsequence-point] xilinx_axienet_main.c: In function 'axienet_of_probe': xilinx_axienet_main.c:1501:21: warning: unused variable 'rc' [-Wunused-variable] Signed-off-by: Michal Simek Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 9fb8ab2..4bfdf8c 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -601,7 +601,8 @@ static void axienet_start_xmit_done(struct net_device *ndev) size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; packets++; - lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM; + ++lp->tx_bd_ci; + lp->tx_bd_ci %= TX_BD_NUM; cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; status = cur_p->status; } @@ -687,7 +688,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev) skb_headlen(skb), DMA_TO_DEVICE); for (ii = 0; ii < num_frag; ii++) { - lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM; + ++lp->tx_bd_tail; + lp->tx_bd_tail %= TX_BD_NUM; cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; frag = &skb_shinfo(skb)->frags[ii]; cur_p->phys = dma_map_single(ndev->dev.parent, @@ -703,7 +705,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev) tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; /* Start the transfer */ axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p); - lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM; + ++lp->tx_bd_tail; + lp->tx_bd_tail %= TX_BD_NUM; return NETDEV_TX_OK; } @@ -775,7 +778,8 @@ static void axienet_recv(struct net_device *ndev) cur_p->status = 0; cur_p->sw_id_offset = (u32) new_skb; - lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM; + ++lp->rx_bd_ci; + lp->rx_bd_ci %= RX_BD_NUM; cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; } -- cgit v0.10.2 From 6b187b21c92b6e2c7e8ef0b450181c37a3f31681 Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Tue, 28 Jan 2014 11:42:40 +0530 Subject: ARM: OMAP2+: gpmc: fix: DT NAND child nodes not probed when MTD_NAND is built as module Fixes: commit bc6b1e7b86f5d8e4a6fc1c0189e64bba4077efe0 ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND OMAP SoC(s) depend on GPMC controller driver to parse GPMC DT child nodes and register them platform_device for NAND driver to probe later. However this does not happen if generic MTD_NAND framework is built as module (CONFIG_MTD_NAND=m). Therefore, when MTD/NAND and MTD/NAND/OMAP2 modules are loaded, they are unable to find any matching platform_device and remain un-binded. This causes on board NAND flash to remain un-detected. This patch causes GPMC controller to parse DT nodes when CONFIG_MTD_NAND=y || CONFIG_MTD_NAND=m CC: # 3.9.x+ Signed-off-by: Pekon Gupta Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index d24926e..c77a84b 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1339,7 +1339,7 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, of_property_read_bool(np, "gpmc,time-para-granularity"); } -#ifdef CONFIG_MTD_NAND +#if IS_ENABLED(CONFIG_MTD_NAND) static const char * const nand_xfer_types[] = { [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", -- cgit v0.10.2 From 980386d2d6d49e0b42f48550853ef1ad6aa5d79a Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Tue, 28 Jan 2014 11:42:41 +0530 Subject: ARM: OMAP2+: gpmc: fix: DT ONENAND child nodes not probed when MTD_ONENAND is built as module Fixes: commit 75d3625e0e86b2d8d77b4e9c6f685fd7ea0d5a96 ARM: OMAP2+: gpmc: add DT bindings for OneNAND OMAP SoC(s) depend on GPMC controller driver to parse GPMC DT child nodes and register them platform_device for ONENAND driver to probe later. However this does not happen if generic MTD_ONENAND framework is built as module (CONFIG_MTD_ONENAND=m). Therefore, when MTD/ONENAND and MTD/ONENAND/OMAP2 modules are loaded, they are unable to find any matching platform_device and remain un-binded. This causes on board ONENAND flash to remain un-detected. This patch causes GPMC controller to parse DT nodes when CONFIG_MTD_ONENAND=y || CONFIG_MTD_ONENAND=m CC: # 3.9.x+ Signed-off-by: Pekon Gupta Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index c77a84b..ab43755 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1429,7 +1429,7 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, } #endif -#ifdef CONFIG_MTD_ONENAND +#if IS_ENABLED(CONFIG_MTD_ONENAND) static int gpmc_probe_onenand_child(struct platform_device *pdev, struct device_node *child) { -- cgit v0.10.2 From 8c5cb1a8f81370f60c62450fa5a5cf20aa081050 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 8 Feb 2014 15:48:55 +0200 Subject: ARM: OMAP1: nokia770: enable tahvo-usb Add platform data for tahvo-usb. This is the last missing piece to get Tahvo USB working with 3.14. Signed-off-by: Aaro Koskinen Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 91449c5..85089d8 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -156,6 +156,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = { .register_dev = 1, .hmc_mode = 16, .pins[0] = 6, + .extcon = "tahvo-usb", }; #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) -- cgit v0.10.2 From 2a074deffd66d5e1893e859dc0737887fea9d46d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 9 Feb 2014 14:12:35 +0200 Subject: ARM: dts: N9/N950: fix boot hang with 3.14-rc1 N9/N950 does not boot anymore with 3.14-rc1, because SoC compatible property is missing. Fix that. Signed-off-by: Aaro Koskinen Reviewed-by: Nishanth Menon Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts index 39828ce..9938b5d 100644 --- a/arch/arm/boot/dts/omap3-n9.dts +++ b/arch/arm/boot/dts/omap3-n9.dts @@ -14,5 +14,5 @@ / { model = "Nokia N9"; - compatible = "nokia,omap3-n9", "ti,omap3"; + compatible = "nokia,omap3-n9", "ti,omap36xx", "ti,omap3"; }; diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts index b076a52..261c558 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/omap3-n950.dts @@ -14,5 +14,5 @@ / { model = "Nokia N950"; - compatible = "nokia,omap3-n950", "ti,omap3"; + compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3"; }; -- cgit v0.10.2 From c3580bc12569b4c02ab5505b853825d863e6f86e Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 9 Feb 2014 14:12:36 +0200 Subject: ARM: dts: N900: add missing compatible property Add missing compatible property to avoid problems in the future. Signed-off-by: Aaro Koskinen Reviewed-by: Nishanth Menon Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index 6fc85f9..0bf40c9 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 Pavel Machek - * Copyright 2013 Aaro Koskinen + * Copyright (C) 2013-2014 Aaro Koskinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 (or later) as @@ -13,7 +13,7 @@ / { model = "Nokia N900"; - compatible = "nokia,omap3-n900", "ti,omap3"; + compatible = "nokia,omap3-n900", "ti,omap3430", "ti,omap3"; cpus { cpu@0 { -- cgit v0.10.2 From 9b2b6a2d669c909dd0b125fc834da94bcfc0aee7 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Wed, 12 Feb 2014 15:55:14 +0100 Subject: net: qmi_wwan: add support for Cinterion PXS8 and PHS8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the PXS8 and PHS8 devices show up with PID 0x0053 they will expose both a QMI port and a WWAN interface. CC: Hans-Christoph Schemmel CC: Christian Schmiedl CC: Nicolaus Colberg CC: David McCullough Signed-off-by: Aleksander Morgado Acked-by: Bjørn Mork Signed-off-by: David S. Miller diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index ff5c871..1eddd43 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -732,6 +732,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)}, /* Olivetti Olicard 200 */ {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ + {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -- cgit v0.10.2 From 89e101729be4cacd5847fef7e7c99680772c6e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 12 Feb 2014 23:33:22 +0100 Subject: net: cpsw: catch of_get_phy_mode failing and propagate error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's wrong if the device tree doesn't provide a phy-mode property for the cpsw slaves as it is documented to be required in Documentation/devicetree/bindings/net/cpsw.txt. Anyhow it's nice to catch that problem, still more as it used to work without this property up to commit 388367a5a9fb (drivers: net: cpsw: use cpsw-phy-sel driver to configure phy mode) which is in v3.13-rc1. Signed-off-by: Uwe Kleine-König Acked-by: Mugunthan V N Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 1d860ce..542c511 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1896,6 +1896,11 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); slave_data->phy_if = of_get_phy_mode(slave_node); + if (slave_data->phy_if < 0) { + pr_err("Missing or malformed slave[%d] phy-mode property\n", + i); + return slave_data->phy_if; + } if (data->dual_emac) { if (of_property_read_u32(slave_node, "dual_emac_res_vlan", -- cgit v0.10.2 From 84b57c84b10de62d832b04da02af9cba60199d0c Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 9 Feb 2014 16:01:28 +0100 Subject: ARM: OMAP2+: Remove MACH_NOKIA_N800 The last caller of machine_is_nokia_n800() was removed in commit 5a87cde490e1 ("ARM: OMAP2+: Remove legacy booting support for n8x0"). That means that the Kconfig symbol MACH_NOKIA_N800 is now unused. It can safely be removed. Signed-off-by: Paul Bolle Acked-by: Aaro Koskinen Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 8165a4a..9320252 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -272,9 +272,6 @@ config MACH_OMAP_3430SDP default y select OMAP_PACKAGE_CBB -config MACH_NOKIA_N800 - bool - config MACH_NOKIA_N810 bool @@ -285,7 +282,6 @@ config MACH_NOKIA_N8X0 bool "Nokia N800/N810" depends on SOC_OMAP2420 default y - select MACH_NOKIA_N800 select MACH_NOKIA_N810 select MACH_NOKIA_N810_WIMAX select OMAP_PACKAGE_ZAC -- cgit v0.10.2 From 43e21ef061598024dcb4821b97b9eaebfed0b50d Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 12 Feb 2014 10:45:52 +0100 Subject: ARM: OMAP2+: Remove legacy macros for zoom platforms Commit 97411608fd5f ("ARM: OMAP2+: Remove legacy support for zoom platforms") removed the Kconfig symbols MACH_OMAP_ZOOM2 and MACH_OMAP_ZOOM3. Remove the last usage of the related macros too. Signed-off-by: Paul Bolle Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index d408b15..af432b1 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -179,15 +179,6 @@ static struct map_desc omap34xx_io_desc[] __initdata = { .length = L4_EMU_34XX_SIZE, .type = MT_DEVICE }, -#if defined(CONFIG_DEBUG_LL) && \ - (defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3)) - { - .virtual = ZOOM_UART_VIRT, - .pfn = __phys_to_pfn(ZOOM_UART_BASE), - .length = SZ_1M, - .type = MT_DEVICE - }, -#endif }; #endif -- cgit v0.10.2 From 219e288e8900fac65211e0a23e2a1037fd521af1 Mon Sep 17 00:00:00 2001 From: Vijay Subramanian Date: Wed, 12 Feb 2014 18:58:21 -0800 Subject: net: sched: Cleanup PIE comments Fix incorrect comment reported by Norbert Kiesel. Edit another comment to add more details. Also add references to algorithm (IETF draft and paper) to top of file. Signed-off-by: Vijay Subramanian CC: Mythili Prabhu CC: Norbert Kiesel Signed-off-by: David S. Miller diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c index a255d02..fefeeb7 100644 --- a/net/sched/sch_pie.c +++ b/net/sched/sch_pie.c @@ -15,6 +15,11 @@ * * ECN support is added by Naeem Khademi * University of Oslo, Norway. + * + * References: + * IETF draft submission: http://tools.ietf.org/html/draft-pan-aqm-pie-00 + * IEEE Conference on High Performance Switching and Routing 2013 : + * "PIE: A * Lightweight Control Scheme to Address the Bufferbloat Problem" */ #include @@ -36,7 +41,7 @@ struct pie_params { psched_time_t target; /* user specified target delay in pschedtime */ u32 tupdate; /* timer frequency (in jiffies) */ u32 limit; /* number of packets that can be enqueued */ - u32 alpha; /* alpha and beta are between -4 and 4 */ + u32 alpha; /* alpha and beta are between 0 and 32 */ u32 beta; /* and are used for shift relative to 1 */ bool ecn; /* true if ecn is enabled */ bool bytemode; /* to scale drop early prob based on pkt size */ @@ -326,10 +331,16 @@ static void calculate_probability(struct Qdisc *sch) if (qdelay == 0 && qlen != 0) update_prob = false; - /* Add ranges for alpha and beta, more aggressive for high dropping - * mode and gentle steps for light dropping mode - * In light dropping mode, take gentle steps; in medium dropping mode, - * take medium steps; in high dropping mode, take big steps. + /* In the algorithm, alpha and beta are between 0 and 2 with typical + * value for alpha as 0.125. In this implementation, we use values 0-32 + * passed from user space to represent this. Also, alpha and beta have + * unit of HZ and need to be scaled before they can used to update + * probability. alpha/beta are updated locally below by 1) scaling them + * appropriately 2) scaling down by 16 to come to 0-2 range. + * Please see paper for details. + * + * We scale alpha and beta differently depending on whether we are in + * light, medium or high dropping mode. */ if (q->vars.prob < MAX_PROB / 100) { alpha = -- cgit v0.10.2 From df1a29f4768a3de4ea793ff0b4c6e79ffa15849d Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:13 +0100 Subject: ARM: dts: omap3-tobi: Fix boot with OMAP36xx-based Overo Tobi expansion board can be used with both OMAP35xx-based Overo, and OMAP36xx-based Overo. Currently the boot is broken with newer OMAP36xx-based Overo (Storm and alike). Fix include file and compatible string to be able to boot newer models. This will break older models. This will be addressed later. Signed-off-by: Florian Vaussard Tested-by: Kevin Hilman Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi index a461d2f..5970999 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/omap3-overo.dtsi @@ -9,9 +9,6 @@ /* * The Gumstix Overo must be combined with an expansion board. */ -/dts-v1/; - -#include "omap34xx.dtsi" / { pwmleds { diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts index 7e4ad2a..0e3b8bf 100644 --- a/arch/arm/boot/dts/omap3-tobi.dts +++ b/arch/arm/boot/dts/omap3-tobi.dts @@ -10,11 +10,14 @@ * Tobi expansion board is manufactured by Gumstix Inc. */ +/dts-v1/; + +#include "omap36xx.dtsi" #include "omap3-overo.dtsi" / { model = "TI OMAP3 Gumstix Overo on Tobi"; - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"; + compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap36xx", "ti,omap3"; leds { compatible = "gpio-leds"; -- cgit v0.10.2 From 1ce64826b02032827abb166fc2d8909171d4b296 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:14 +0100 Subject: ARM: dts: omap3-tobi: Use the correct vendor prefix Gumstix is the correct vendor for all Overo related products. Reported-by: Javier Martinez Canillas Signed-off-by: Florian Vaussard Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts index 0e3b8bf..c742afa 100644 --- a/arch/arm/boot/dts/omap3-tobi.dts +++ b/arch/arm/boot/dts/omap3-tobi.dts @@ -17,7 +17,7 @@ / { model = "TI OMAP3 Gumstix Overo on Tobi"; - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap36xx", "ti,omap3"; + compatible = "gumstix,omap3-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; leds { compatible = "gpio-leds"; -- cgit v0.10.2 From f03ef09b6f59c0807d6aeba10f18238be1ea6390 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:15 +0100 Subject: ARM: dts: Add support for both OMAP35xx and OMAP36xx Overo/Tobi Unfortunatly the device tree for older OMAP35xx Overo cannot be used with newer OMAP36xx and vice-versa. To address this issue, move most of the Tobi DTS to a common include file, and create model-specific Tobi DTS. Signed-off-by: Florian Vaussard Tested-by: Kevin Hilman Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b9d6a8b..e8355f4 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -208,7 +208,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap3-n900.dtb \ omap3-n9.dtb \ omap3-n950.dtb \ - omap3-tobi.dtb \ + omap3-overo-tobi.dtb \ + omap3-overo-storm-tobi.dtb \ omap3-gta04.dtb \ omap3-igep0020.dtb \ omap3-igep0030.dtb \ diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts new file mode 100644 index 0000000..966b5c9 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Tobi expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap36xx.dtsi" +#include "omap3-overo-tobi-common.dtsi" + +/ { + model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Tobi"; + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi new file mode 100644 index 0000000..4edc013 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Tobi expansion board is manufactured by Gumstix Inc. + */ + +#include "omap3-overo.dtsi" + +/ { + leds { + compatible = "gpio-leds"; + heartbeat { + label = "overo:red:gpio21"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + }; + + vddvario: regulator-vddvario { + compatible = "regulator-fixed"; + regulator-name = "vddvario"; + regulator-always-on; + }; + + vdd33a: regulator-vdd33a { + compatible = "regulator-fixed"; + regulator-name = "vdd33a"; + regulator-always-on; + }; +}; + +&gpmc { + ranges = <5 0 0x2c000000 0x1000000>; /* CS5 */ + + ethernet@5,0 { + compatible = "smsc,lan9221", "smsc,lan9115"; + reg = <5 0 0xff>; + bank-width = <2>; + + gpmc,mux-add-data; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <42>; + gpmc,cs-wr-off-ns = <36>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <12>; + gpmc,adv-wr-off-ns = <12>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <42>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <36>; + gpmc,rd-cycle-ns = <60>; + gpmc,wr-cycle-ns = <54>; + gpmc,access-ns = <36>; + gpmc,page-burst-access-ns = <0>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,wr-data-mux-bus-ns = <18>; + gpmc,wr-access-ns = <42>; + gpmc,cycle2cycle-samecsen; + gpmc,cycle2cycle-diffcsen; + + interrupt-parent = <&gpio6>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; /* GPIO 176 */ + reg-io-width = <4>; + }; +}; + +&i2c3 { + clock-frequency = <100000>; +}; + +&mmc3 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts new file mode 100644 index 0000000..de5653e --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-tobi.dts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Tobi expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap34xx.dtsi" +#include "omap3-overo-tobi-common.dtsi" + +/ { + model = "OMAP35xx Gumstix Overo on Tobi"; + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; +}; + diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts deleted file mode 100644 index c742afa..0000000 --- a/arch/arm/boot/dts/omap3-tobi.dts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * Tobi expansion board is manufactured by Gumstix Inc. - */ - -/dts-v1/; - -#include "omap36xx.dtsi" -#include "omap3-overo.dtsi" - -/ { - model = "TI OMAP3 Gumstix Overo on Tobi"; - compatible = "gumstix,omap3-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; - - leds { - compatible = "gpio-leds"; - heartbeat { - label = "overo:red:gpio21"; - gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; - linux,default-trigger = "heartbeat"; - }; - }; - - vddvario: regulator-vddvario { - compatible = "regulator-fixed"; - regulator-name = "vddvario"; - regulator-always-on; - }; - - vdd33a: regulator-vdd33a { - compatible = "regulator-fixed"; - regulator-name = "vdd33a"; - regulator-always-on; - }; -}; - -&gpmc { - ranges = <5 0 0x2c000000 0x1000000>; /* CS5 */ - - ethernet@5,0 { - compatible = "smsc,lan9221", "smsc,lan9115"; - reg = <5 0 0xff>; - bank-width = <2>; - - gpmc,mux-add-data; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <42>; - gpmc,cs-wr-off-ns = <36>; - gpmc,adv-on-ns = <6>; - gpmc,adv-rd-off-ns = <12>; - gpmc,adv-wr-off-ns = <12>; - gpmc,oe-on-ns = <0>; - gpmc,oe-off-ns = <42>; - gpmc,we-on-ns = <0>; - gpmc,we-off-ns = <36>; - gpmc,rd-cycle-ns = <60>; - gpmc,wr-cycle-ns = <54>; - gpmc,access-ns = <36>; - gpmc,page-burst-access-ns = <0>; - gpmc,bus-turnaround-ns = <0>; - gpmc,cycle2cycle-delay-ns = <0>; - gpmc,wr-data-mux-bus-ns = <18>; - gpmc,wr-access-ns = <42>; - gpmc,cycle2cycle-samecsen; - gpmc,cycle2cycle-diffcsen; - - interrupt-parent = <&gpio6>; - interrupts = <16 IRQ_TYPE_LEVEL_LOW>; /* GPIO 176 */ - reg-io-width = <4>; - }; -}; - -&i2c3 { - clock-frequency = <100000>; -}; - -&mmc3 { - status = "disabled"; -}; -- cgit v0.10.2 From 6726d971def461eded39cccce24d28f90a2e6df4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 13 Feb 2014 16:09:58 +0900 Subject: USB2NET: SR9800: use %zu for size_t Use %zu for size_t in order to avoid the following build warning in printks. drivers/net/usb/sr9800.c: In function 'sr9800_bind' drivers/net/usb/sr9800.c:826:2: warning: format '%ld' expects argument of type 'long int' but argument 5 has type 'size_t' [-Wformat] Signed-off-by: Jingoo Han Signed-off-by: David S. Miller diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 4175eb9..8017108 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -823,7 +823,7 @@ static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf) dev->rx_urb_size = SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size; } - netdev_dbg(dev->net, "%s : setting rx_urb_size with : %ld\n", __func__, + netdev_dbg(dev->net, "%s : setting rx_urb_size with : %zu\n", __func__, dev->rx_urb_size); return 0; -- cgit v0.10.2 From 208ece14e23b167b43d906c74e3bdcbee8d6e4aa Mon Sep 17 00:00:00 2001 From: Liu Junliang Date: Thu, 13 Feb 2014 12:22:19 +0800 Subject: USB2NET: Fix Default to 'y' for SR9800 Device Driver, setting to 'n' Signed-off-by: Liu Junliang Signed-off-by: David S. Miller diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 409499f..7e7269f 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -296,7 +296,6 @@ config USB_NET_SR9800 tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices" depends on USB_USBNET select CRC32 - default y ---help--- Say Y if you want to use one of the following 100Mbps USB Ethernet device based on the CoreChip-sz SR9800 chip. -- cgit v0.10.2 From 0ad8b480d6ee916aa84324f69acf690142aecd0e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 13 Feb 2014 11:42:05 +0200 Subject: vhost: fix ref cnt checking deadlock vhost checked the counter within the refcnt before decrementing. It really wanted to know that it is the one that has the last reference, as a way to batch freeing resources a bit more efficiently. Note: we only let refcount go to 0 on device release. This works well but we now access the ref counter twice so there's a race: all users might see a high count and decide to defer freeing resources. In the end no one initiates freeing resources until the last reference is gone (which is on VM shotdown so might happen after a looooong time). Let's do what we probably should have done straight away: switch from kref to plain atomic, documenting the semantics, return the refcount value atomically after decrement, then use that to avoid the deadlock. Reported-by: Qin Chuanyu Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: David S. Miller diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 9a68409..41be4de 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -70,7 +70,12 @@ enum { }; struct vhost_net_ubuf_ref { - struct kref kref; + /* refcount follows semantics similar to kref: + * 0: object is released + * 1: no outstanding ubufs + * >1: outstanding ubufs + */ + atomic_t refcount; wait_queue_head_t wait; struct vhost_virtqueue *vq; }; @@ -116,14 +121,6 @@ static void vhost_net_enable_zcopy(int vq) vhost_net_zcopy_mask |= 0x1 << vq; } -static void vhost_net_zerocopy_done_signal(struct kref *kref) -{ - struct vhost_net_ubuf_ref *ubufs; - - ubufs = container_of(kref, struct vhost_net_ubuf_ref, kref); - wake_up(&ubufs->wait); -} - static struct vhost_net_ubuf_ref * vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy) { @@ -134,21 +131,24 @@ vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy) ubufs = kmalloc(sizeof(*ubufs), GFP_KERNEL); if (!ubufs) return ERR_PTR(-ENOMEM); - kref_init(&ubufs->kref); + atomic_set(&ubufs->refcount, 1); init_waitqueue_head(&ubufs->wait); ubufs->vq = vq; return ubufs; } -static void vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs) +static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs) { - kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal); + int r = atomic_sub_return(1, &ubufs->refcount); + if (unlikely(!r)) + wake_up(&ubufs->wait); + return r; } static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs) { - kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal); - wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); + vhost_net_ubuf_put(ubufs); + wait_event(ubufs->wait, !atomic_read(&ubufs->refcount)); } static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs) @@ -306,22 +306,21 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success) { struct vhost_net_ubuf_ref *ubufs = ubuf->ctx; struct vhost_virtqueue *vq = ubufs->vq; - int cnt = atomic_read(&ubufs->kref.refcount); + int cnt; /* set len to mark this desc buffers done DMA */ vq->heads[ubuf->desc].len = success ? VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN; - vhost_net_ubuf_put(ubufs); + cnt = vhost_net_ubuf_put(ubufs); /* * Trigger polling thread if guest stopped submitting new buffers: - * in this case, the refcount after decrement will eventually reach 1 - * so here it is 2. + * in this case, the refcount after decrement will eventually reach 1. * We also trigger polling periodically after each 16 packets * (the value 16 here is more or less arbitrary, it's tuned to trigger * less than 10% of times). */ - if (cnt <= 2 || !(cnt % 16)) + if (cnt <= 1 || !(cnt % 16)) vhost_poll_queue(&vq->poll); } @@ -420,7 +419,7 @@ static void handle_tx(struct vhost_net *net) msg.msg_control = ubuf; msg.msg_controllen = sizeof(ubuf); ubufs = nvq->ubufs; - kref_get(&ubufs->kref); + atomic_inc(&ubufs->refcount); nvq->upend_idx = (nvq->upend_idx + 1) % UIO_MAXIOV; } else { msg.msg_control = NULL; @@ -780,7 +779,7 @@ static void vhost_net_flush(struct vhost_net *n) vhost_net_ubuf_put_and_wait(n->vqs[VHOST_NET_VQ_TX].ubufs); mutex_lock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex); n->tx_flush = false; - kref_init(&n->vqs[VHOST_NET_VQ_TX].ubufs->kref); + atomic_set(&n->vqs[VHOST_NET_VQ_TX].ubufs->refcount, 1); mutex_unlock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex); } } -- cgit v0.10.2 From b0c057ca7e835b36c6050c7627634b664796c1d6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 13 Feb 2014 11:45:11 +0200 Subject: vhost: fix a theoretical race in device cleanup vhost_zerocopy_callback accesses VQ right after it drops a ubuf reference. In theory, this could race with device removal which waits on the ubuf kref, and crash on use after free. Do all accesses within rcu read side critical section, and synchronize on release. Since callbacks are always invoked from bh, synchronize_rcu_bh seems enough and will help release complete a bit faster. Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: David S. Miller diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 41be4de..a0fa5de 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -308,6 +308,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success) struct vhost_virtqueue *vq = ubufs->vq; int cnt; + rcu_read_lock_bh(); + /* set len to mark this desc buffers done DMA */ vq->heads[ubuf->desc].len = success ? VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN; @@ -322,6 +324,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success) */ if (cnt <= 1 || !(cnt % 16)) vhost_poll_queue(&vq->poll); + + rcu_read_unlock_bh(); } /* Expects to be always run from workqueue - which acts as @@ -799,6 +803,8 @@ static int vhost_net_release(struct inode *inode, struct file *f) fput(tx_sock->file); if (rx_sock) fput(rx_sock->file); + /* Make sure no callbacks are outstanding */ + synchronize_rcu_bh(); /* We do an extra flush before freeing memory, * since jobs can re-queue themselves. */ vhost_net_flush(n); -- cgit v0.10.2 From 0d961b3b52f566f823070ce2366511a7f64b928c Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Thu, 13 Feb 2014 14:47:27 +0100 Subject: drivers: net: cpsw: fix buggy loop condition Commit 0cd8f9cc0654c06adde353c6532114c5f53a18e8 ("drivers: net: cpsw: enable promiscuous mode support") Enable promiscuous mode support for CPSW. Introduced a crash on an am335x based board (similiar to am335x-evm). Reason is buggy end condition in for loop in cpsw_set_promiscious() for (i = 0; i <= priv->data.slaves; i++) should be for (i = 0; i < priv->data.slaves; i++) Fix this ... Signed-off-by: Heiko Schocher Cc: Mugunthan V N Cc: David S. Miller Cc: Sebastian Siewior Cc: Daniel Mack Cc: Felipe Balbi Cc: Markus Pargmann Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Mugunthan V N Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 542c511..651087b 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -554,7 +554,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) * common for both the interface as the interface shares * the same hardware resource. */ - for (i = 0; i <= priv->data.slaves; i++) + for (i = 0; i < priv->data.slaves; i++) if (priv->slaves[i].ndev->flags & IFF_PROMISC) flag = true; @@ -578,7 +578,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) unsigned long timeout = jiffies + HZ; /* Disable Learn for all ports */ - for (i = 0; i <= priv->data.slaves; i++) { + for (i = 0; i < priv->data.slaves; i++) { cpsw_ale_control_set(ale, i, ALE_PORT_NOLEARN, 1); cpsw_ale_control_set(ale, i, @@ -606,7 +606,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0); /* Enable Learn for all ports */ - for (i = 0; i <= priv->data.slaves; i++) { + for (i = 0; i < priv->data.slaves; i++) { cpsw_ale_control_set(ale, i, ALE_PORT_NOLEARN, 0); cpsw_ale_control_set(ale, i, -- cgit v0.10.2 From 602b109942b816e56639a965ae81f3a2437004b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Thu, 13 Feb 2014 15:26:57 +0100 Subject: net:phy:dp83640: Move all HW initialization to dp83640_config_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit phy_init_hw not does a full PHY reset after the driver probe has finished, so any hw initialization done in the probe will be lost. Part of the timestamping functionality of the dp83640 is set up in the probe and with that lost, enabling timestamping will cause a PHY lockup, requiring a hard reset / power cycle to recover. This patch moves all the HW initialization in dp83640_probe to dp83640_config_init. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 9414fa2..98e7cbf 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1006,11 +1006,6 @@ static int dp83640_probe(struct phy_device *phydev) } else list_add_tail(&dp83640->list, &clock->phylist); - if (clock->chosen && !list_empty(&clock->phylist)) - recalibrate(clock); - else - enable_broadcast(dp83640->phydev, clock->page, 1); - dp83640_clock_put(clock); return 0; @@ -1063,6 +1058,14 @@ static void dp83640_remove(struct phy_device *phydev) static int dp83640_config_init(struct phy_device *phydev) { + struct dp83640_private *dp83640 = phydev->priv; + struct dp83640_clock *clock = dp83640->clock; + + if (clock->chosen && !list_empty(&clock->phylist)) + recalibrate(clock); + else + enable_broadcast(phydev, clock->page, 1); + enable_status_frames(phydev, true); ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); return 0; -- cgit v0.10.2 From 357137a4222b1984b3d867923c7e388669744ceb Mon Sep 17 00:00:00 2001 From: FX Le Bail Date: Mon, 10 Feb 2014 16:46:54 +0100 Subject: ipv4: ipconfig.c: add parentheses in an if statement Even if the 'time_before' macro expand with parentheses, the look is bad. Signed-off-by: Francois-Xavier Le Bail Signed-off-by: David S. Miller diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index efa1138..b3e86ea 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -273,7 +273,7 @@ static int __init ic_open_devs(void) msleep(1); - if time_before(jiffies, next_msg) + if (time_before(jiffies, next_msg)) continue; elapsed = jiffies_to_msecs(jiffies - start); -- cgit v0.10.2 From ce898ecb5a3c0027855dcee21ed99690b867d017 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 12 Feb 2014 21:13:16 +0000 Subject: netfilter: nft_reject_inet: fix unintended fall-through in switch-statatement For IPv4 packets, we call both IPv4 and IPv6 reject. Reported-by: Dave Jones Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index 8a310f2..b718a52 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c @@ -21,9 +21,9 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, { switch (pkt->ops->pf) { case NFPROTO_IPV4: - nft_reject_ipv4_eval(expr, data, pkt); + return nft_reject_ipv4_eval(expr, data, pkt); case NFPROTO_IPV6: - nft_reject_ipv6_eval(expr, data, pkt); + return nft_reject_ipv6_eval(expr, data, pkt); } } -- cgit v0.10.2 From 06efbd6d5694b2e3cde176f724ba572d57709616 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 12 Feb 2014 10:53:01 +0100 Subject: netfilter: nft_meta: fix typo "CONFIG_NET_CLS_ROUTE" There are two checks for CONFIG_NET_CLS_ROUTE, but the corresponding Kconfig symbol was dropped in v2.6.39. Since the code guards access to dst_entry.tclassid it seems CONFIG_IP_ROUTE_CLASSID should be used instead. Signed-off-by: Paul Bolle Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index e8254ad..425cf39 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -116,7 +116,7 @@ static void nft_meta_get_eval(const struct nft_expr *expr, skb->sk->sk_socket->file->f_cred->fsgid); read_unlock_bh(&skb->sk->sk_callback_lock); break; -#ifdef CONFIG_NET_CLS_ROUTE +#ifdef CONFIG_IP_ROUTE_CLASSID case NFT_META_RTCLASSID: { const struct dst_entry *dst = skb_dst(skb); @@ -199,7 +199,7 @@ static int nft_meta_init_validate_get(uint32_t key) case NFT_META_OIFTYPE: case NFT_META_SKUID: case NFT_META_SKGID: -#ifdef CONFIG_NET_CLS_ROUTE +#ifdef CONFIG_IP_ROUTE_CLASSID case NFT_META_RTCLASSID: #endif #ifdef CONFIG_NETWORK_SECMARK -- cgit v0.10.2 From 2b7a79bae2dc0327af2352e1d1793b9d752648aa Mon Sep 17 00:00:00 2001 From: FX Le Bail Date: Tue, 11 Feb 2014 15:49:25 +0100 Subject: netfilter: nf_nat_snmp_basic: fix duplicates in if/else branches The solution was found by Patrick in 2.4 kernel sources. Cc: Patrick McHardy Signed-off-by: Francois-Xavier Le Bail Acked-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index d551e31..7c67667 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1198,8 +1198,8 @@ static int snmp_translate(struct nf_conn *ct, map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); } else { /* DNAT replies */ - map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip); - map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); + map.from = NOCT1(&ct->tuplehash[!dir].tuple.src.u3.ip); + map.to = NOCT1(&ct->tuplehash[dir].tuple.dst.u3.ip); } if (map.from == map.to) -- cgit v0.10.2 From fada94ee64e6e18793b1db60fb8278d2eddbf922 Mon Sep 17 00:00:00 2001 From: Li Zhong Date: Fri, 14 Feb 2014 10:52:57 +0800 Subject: workqueue: add args to workqueue lockdep name Tommi noticed a 'funny' lock class name: "%s#5" from a lock acquired in process_one_work(). Maybe #fmt plus #args could be used as the lock_name to give some more information for some fmt string like the above. __builtin_constant_p() check is removed (as there seems no good way to check all the variables in args list). However, by removing the check, it only adds two additional "s for those constants. Some lockdep name examples printed out after the change: lockdep name wq->name "events_long" events_long "%s"("khelper") khelper "xfs-data/%s"mp->m_fsname xfs-data/dm-3 Signed-off-by: Li Zhong Signed-off-by: Tejun Heo diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 594521b..704f4f6 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -419,10 +419,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, static struct lock_class_key __key; \ const char *__lock_name; \ \ - if (__builtin_constant_p(fmt)) \ - __lock_name = (fmt); \ - else \ - __lock_name = #fmt; \ + __lock_name = #fmt#args; \ \ __alloc_workqueue_key((fmt), (flags), (max_active), \ &__key, __lock_name, ##args); \ -- cgit v0.10.2 From 8842446ac74263f1330f46e11ed649e2b0ed6545 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:16 +0100 Subject: Documentation: dt: OMAP: Update Overo/Tobi Update the compatible string for Overo/Tobi to reflect the latest changes. Signed-off-by: Florian Vaussard Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt index 34dc40c..af9b4a0 100644 --- a/Documentation/devicetree/bindings/arm/omap/omap.txt +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -91,7 +91,7 @@ Boards: compatible = "ti,omap3-beagle", "ti,omap3" - OMAP3 Tobi with Overo : Commercial expansion board with daughter board - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3" + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3" - OMAP4 SDP : Software Development Board compatible = "ti,omap4-sdp", "ti,omap4430" -- cgit v0.10.2 From 28fa65e643ed7cf753e89db20745e264c41f3682 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 12 Feb 2014 16:08:28 -0800 Subject: mtd: nand: fix off-by-one read retry mode counting A flash may support N read retry voltage threshold modes, numbered 0 through N-1 (where mode 0 represents the initial state). However, nand_do_read_ops() tries to use mode 0 through N. This off-by-one error shows up, for instance, when using nanddump, and we have cycled through available modes: nand: setting READ RETRY mode 0 nand: setting READ RETRY mode 1 nand: setting READ RETRY mode 2 nand: setting READ RETRY mode 3 nand: setting READ RETRY mode 4 nand: setting READ RETRY mode 5 nand: setting READ RETRY mode 6 nand: setting READ RETRY mode 7 nand: setting READ RETRY mode 8 libmtd: error!: cannot read 8192 bytes from mtd0 (eraseblock 20, offset 0) error 22 (Invalid argument) nanddump: error!: mtd_read Tested on Micron MT29F64G08CBCBBH1, with 8 retry modes. Signed-off-by: Brian Norris Acked-by: Huang Shijie diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 59eba5d..9715a7b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1584,7 +1584,7 @@ read_retry: } if (mtd->ecc_stats.failed - ecc_failures) { - if (retry_mode + 1 <= chip->read_retries) { + if (retry_mode + 1 < chip->read_retries) { retry_mode++; ret = nand_setup_read_retry(mtd, retry_mode); -- cgit v0.10.2 From d43ff4cd798911736fb39025ec8004284b1b0bc2 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Thu, 13 Feb 2014 19:30:39 +0100 Subject: net: asix: add missing flag to struct driver_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct driver_info ax88178_info is assigned the function asix_rx_fixup_common as it's rx_fixup callback. This means that FLAG_MULTI_PACKET must be set as this function is cloning the data and calling usbnet_skb_return. Not setting this flag leads to usbnet_skb_return beeing called a second time from within the rx_process function in the usbnet module. Signed-off-by: Emil Goode Reported-by: Bjørn Mork Signed-off-by: David S. Miller diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 9765a7d..5d19409 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -917,7 +917,8 @@ static const struct driver_info ax88178_info = { .status = asix_status, .link_reset = ax88178_link_reset, .reset = ax88178_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | + FLAG_MULTI_PACKET, .rx_fixup = asix_rx_fixup_common, .tx_fixup = asix_tx_fixup, }; -- cgit v0.10.2 From 1f42db786b14a31bf807fc41ee5583a00c08fcb1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 14 Feb 2014 13:48:16 -0700 Subject: PCI: Enable INTx if BIOS left them disabled Some firmware leaves the Interrupt Disable bit set even if the device uses INTx interrupts. Clear Interrupt Disable so we get those interrupts. Based on the report mentioned below, if the user selects the "EHCI only" option in the Intel Baytrail BIOS, the EHCI device is handed off to the OS with the PCI_COMMAND_INTX_DISABLE bit set. Link: http://lkml.kernel.org/r/20140114181721.GC12126@xanatos Link: https://bugzilla.kernel.org/show_bug.cgi?id=70601 Reported-by: Chris Cheng Reported-and-tested-by: Jamie Chen Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org CC: Sarah Sharp diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1febe90..6b05f61 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1181,6 +1181,8 @@ EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state); static int do_pci_enable_device(struct pci_dev *dev, int bars) { int err; + u16 cmd; + u8 pin; err = pci_set_power_state(dev, PCI_D0); if (err < 0 && err != -EIO) @@ -1190,6 +1192,14 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) return err; pci_fixup_device(pci_fixup_enable, dev); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & PCI_COMMAND_INTX_DISABLE) + pci_write_config_word(dev, PCI_COMMAND, + cmd & ~PCI_COMMAND_INTX_DISABLE); + } + return 0; } -- cgit v0.10.2 From ce11c436720cdb8437340be93b2f5efe23ce3e1c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 13 Feb 2014 13:14:48 -0800 Subject: net: of_mdio: fix of_set_phy_supported after driver probing Commit 8fdade4 ("net: of_mdio: parse "max-speed" property to set PHY supported features") introduced a typo in of_set_phy_supported for the first assignment of phydev->supported which will not effectively limit the PHY device supported features bits if the PHY driver contains "higher" features (e.g: max-speed = <100> and PHY driver has PHY_GBIT_FEATURES set). Fix this by making sure that the very first thing is to reset to sane defaults (PHY_BASIC_FEATURES) and then progressively add speed features as we parse them. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 875b7b6..495facc 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -24,7 +24,11 @@ MODULE_LICENSE("GPL"); static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed) { - phydev->supported |= PHY_DEFAULT_FEATURES; + /* The default values for phydev->supported are provided by the PHY + * driver "features" member, we want to reset to sane defaults fist + * before supporting higher speeds. + */ + phydev->supported &= PHY_DEFAULT_FEATURES; switch (max_speed) { default: -- cgit v0.10.2 From eb2d4c64879c99fc78e739b0147db28731ff474e Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Fri, 14 Feb 2014 08:21:04 +0100 Subject: net,bonding: fix bond_options.c direct rwlock.h include drivers/net/bonding/bond_options.c includes rwlock.h directly, which is a nono, and which also breaks RT kernel build. Signed-off-by: Mike Galbraith Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 11cb943..c378784 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v0.10.2 From fc40363b2140f5777c88e67814fac9327bf1ee68 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Fri, 14 Feb 2014 14:27:19 -0700 Subject: ahci: Fix broken fallback to single MSI mode Commit 7b92b4f61ec4 ("PCI/MSI: Remove pci_enable_msi_block_auto()") introduced a regression: if multiple MSI initialization fails, the code falls back to INTx rather than to single MSI. Fixes: 7b92b4f61ec4 ("PCI/MSI: Remove pci_enable_msi_block_auto()") Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas Acked-by: Tejun Heo diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index dc2756f..3c5f35e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1170,8 +1170,10 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, nvec = rc; rc = pci_enable_msi_block(pdev, nvec); - if (rc) + if (rc < 0) goto intx; + else if (rc > 0) + goto single_msi; return nvec; -- cgit v0.10.2 From 5d81de8e8667da7135d3a32a964087c0faf5483f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 14 Feb 2014 07:20:35 -0500 Subject: cifs: ensure that uncached writes handle unmapped areas correctly It's possible for userland to pass down an iovec via writev() that has a bogus user pointer in it. If that happens and we're doing an uncached write, then we can end up getting less bytes than we expect from the call to iov_iter_copy_from_user. This is CVE-2014-0069 cifs_iovec_write isn't set up to handle that situation however. It'll blindly keep chugging through the page array and not filling those pages with anything useful. Worse yet, we'll later end up with a negative number in wdata->tailsz, which will confuse the sending routines and cause an oops at the very least. Fix this by having the copy phase of cifs_iovec_write stop copying data in this situation and send the last write as a short one. At the same time, we want to avoid sending a zero-length write to the server, so break out of the loop and set rc to -EFAULT if that happens. This also allows us to handle the case where no address in the iovec is valid. [Note: Marking this for stable on v3.4+ kernels, but kernels as old as v2.6.38 may have a similar problem and may need similar fix] Cc: # v3.4+ Reviewed-by: Pavel Shilovsky Reported-by: Al Viro Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 290b496..18758bc 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2389,7 +2389,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *poffset) { unsigned long nr_pages, i; - size_t copied, len, cur_len; + size_t bytes, copied, len, cur_len; ssize_t total_written = 0; loff_t offset; struct iov_iter it; @@ -2444,14 +2444,45 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, save_len = cur_len; for (i = 0; i < nr_pages; i++) { - copied = min_t(const size_t, cur_len, PAGE_SIZE); + bytes = min_t(const size_t, cur_len, PAGE_SIZE); copied = iov_iter_copy_from_user(wdata->pages[i], &it, - 0, copied); + 0, bytes); cur_len -= copied; iov_iter_advance(&it, copied); + /* + * If we didn't copy as much as we expected, then that + * may mean we trod into an unmapped area. Stop copying + * at that point. On the next pass through the big + * loop, we'll likely end up getting a zero-length + * write and bailing out of it. + */ + if (copied < bytes) + break; } cur_len = save_len - cur_len; + /* + * If we have no data to send, then that probably means that + * the copy above failed altogether. That's most likely because + * the address in the iovec was bogus. Set the rc to -EFAULT, + * free anything we allocated and bail out. + */ + if (!cur_len) { + for (i = 0; i < nr_pages; i++) + put_page(wdata->pages[i]); + kfree(wdata); + rc = -EFAULT; + break; + } + + /* + * i + 1 now represents the number of pages we actually used in + * the copy phase above. Bring nr_pages down to that, and free + * any pages that we didn't use. + */ + for ( ; nr_pages > i + 1; nr_pages--) + put_page(wdata->pages[nr_pages - 1]); + wdata->sync_mode = WB_SYNC_ALL; wdata->nr_pages = nr_pages; wdata->offset = (__u64)offset; -- cgit v0.10.2 From 2365c4eaf077c48574ab6f143960048fc0f31518 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Fri, 14 Feb 2014 13:31:02 +0400 Subject: CIFS: Fix too big maxBuf size for SMB3 mounts SMB3 servers can respond with MaxTransactSize of more than 4M that can cause a memory allocation error returned from kmalloc in a lock codepath. Also the client doesn't support multicredit requests now and allows buffer sizes of 65536 bytes only. Set MaxTransactSize to this maximum supported value. Cc: stable@vger.kernel.org # 3.7+ Signed-off-by: Pavel Shilovsky Acked-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index c383508..bc0bb9c 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h @@ -57,4 +57,7 @@ #define SMB2_CMACAES_SIZE (16) #define SMB3_SIGNKEY_SIZE (16) +/* Maximum buffer size value we can send with 1 credit */ +#define SMB2_MAX_BUFFER_SIZE 65536 + #endif /* _SMB2_GLOB_H */ diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 757da3e..192f51a 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -182,11 +182,8 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) /* start with specified wsize, or default */ wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; wsize = min_t(unsigned int, wsize, server->max_write); - /* - * limit write size to 2 ** 16, because we don't support multicredit - * requests now. - */ - wsize = min_t(unsigned int, wsize, 2 << 15); + /* set it to the maximum buffer size value we can send with 1 credit */ + wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); return wsize; } @@ -200,11 +197,8 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) /* start with specified rsize, or default */ rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; rsize = min_t(unsigned int, rsize, server->max_read); - /* - * limit write size to 2 ** 16, because we don't support multicredit - * requests now. - */ - rsize = min_t(unsigned int, rsize, 2 << 15); + /* set it to the maximum buffer size value we can send with 1 credit */ + rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); return rsize; } diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index a3f7a9c..8603447 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -413,7 +413,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) /* SMB2 only has an extended negflavor */ server->negflavor = CIFS_NEGFLAVOR_EXTENDED; - server->maxBuf = le32_to_cpu(rsp->MaxTransactSize); + /* set it to the maximum buffer size value we can send with 1 credit */ + server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize), + SMB2_MAX_BUFFER_SIZE); server->max_read = le32_to_cpu(rsp->MaxReadSize); server->max_write = le32_to_cpu(rsp->MaxWriteSize); /* BB Do we need to validate the SecurityMode? */ -- cgit v0.10.2 From ab62f9cd7b5ecdf853f1612fe1e983cb7cbbac3e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 15 Feb 2014 01:29:06 +0100 Subject: ACPI / dock: Make 'docked' sysfs attribute work as documented After recent ACPI core changes acpi_bus_get_device() will always succeed for dock station ACPI device objects, so show_docked() should not use that function's return value as an indicator of whether or not the dock device is present. Make it use acpi_device_enumerated() for this purpose. Fixes: 202317a573b2 (ACPI / scan: Add acpi_device objects for all device nodes in the namespace) Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index e9b3081..5bfd769 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -713,13 +713,11 @@ static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl, static ssize_t show_docked(struct device *dev, struct device_attribute *attr, char *buf) { - struct acpi_device *tmp; - struct dock_station *dock_station = dev->platform_data; + struct acpi_device *adev = NULL; - if (!acpi_bus_get_device(dock_station->handle, &tmp)) - return snprintf(buf, PAGE_SIZE, "1\n"); - return snprintf(buf, PAGE_SIZE, "0\n"); + acpi_bus_get_device(dock_station->handle, &adev); + return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev)); } static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); -- cgit v0.10.2 From f951f835a9719996e08e5c2932afc65ebfdbf47a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 16 Feb 2014 08:29:21 +0800 Subject: ASoC: pcm512x: Add regmap select We need at least the core regmap code to build. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 56d0c28..fa47a83 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -316,6 +316,7 @@ config SND_SOC_PCM3008 config SND_SOC_PCM512x tristate "Texas Instruments PCM512x CODECs" + select REGMAP config SND_SOC_RT5631 tristate -- cgit v0.10.2 From b93c95353413041a8cebad915a8109619f66bcc6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 15 Feb 2014 21:33:13 -0500 Subject: ext4: fix online resize with very large inode tables If a file system has a large number of inodes per block group, all of the metadata blocks in a flex_bg may be larger than what can fit in a single block group. Unfortunately, ext4_alloc_group_tables() in resize.c was never tested to see if it would handle this case correctly, and there were a large number of bugs which caused the following sequence to result in a BUG_ON: kernel bug at fs/ext4/resize.c:409! ... call trace: [] ext4_flex_group_add+0x1448/0x1830 [] ext4_resize_fs+0x7b2/0xe80 [] ext4_ioctl+0xbf0/0xf00 [] do_vfs_ioctl+0x2dd/0x4b0 [] ? final_putname+0x22/0x50 [] sys_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x1b code: c8 4c 89 df e8 41 96 f8 ff 44 89 e8 49 01 c4 44 29 6d d4 0 rip [] set_flexbg_block_bitmap+0x171/0x180 This can be reproduced with the following command sequence: mke2fs -t ext4 -i 4096 /dev/vdd 1G mount -t ext4 /dev/vdd /vdd resize2fs /dev/vdd 8G To fix this, we need to make sure the right thing happens when a block group's inode table straddles two block groups, which means the following bugs had to be fixed: 1) Not clearing the BLOCK_UNINIT flag in the second block group in ext4_alloc_group_tables --- the was proximate cause of the BUG_ON. 2) Incorrectly determining how many block groups contained contiguous free blocks in ext4_alloc_group_tables(). 3) Incorrectly setting the start of the next block range to be marked in use after a discontinuity in setup_new_flex_group_blocks(). Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index c5adbb3..69a6261 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb, ext4_group_t group; ext4_group_t last_group; unsigned overhead; + __u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0; BUG_ON(flex_gd->count == 0 || group_data == NULL); @@ -266,7 +267,7 @@ next_group: src_group++; for (; src_group <= last_group; src_group++) { overhead = ext4_group_overhead_blocks(sb, src_group); - if (overhead != 0) + if (overhead == 0) last_blk += group_data[src_group - group].blocks_count; else break; @@ -280,8 +281,7 @@ next_group: group = ext4_get_group_number(sb, start_blk - 1); group -= group_data[0].group; group_data[group].free_blocks_count--; - if (flexbg_size > 1) - flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; + flex_gd->bg_flags[group] &= uninit_mask; } /* Allocate inode bitmaps */ @@ -292,22 +292,30 @@ next_group: group = ext4_get_group_number(sb, start_blk - 1); group -= group_data[0].group; group_data[group].free_blocks_count--; - if (flexbg_size > 1) - flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; + flex_gd->bg_flags[group] &= uninit_mask; } /* Allocate inode tables */ for (; it_index < flex_gd->count; it_index++) { - if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk) + unsigned int itb = EXT4_SB(sb)->s_itb_per_group; + ext4_fsblk_t next_group_start; + + if (start_blk + itb > last_blk) goto next_group; group_data[it_index].inode_table = start_blk; - group = ext4_get_group_number(sb, start_blk - 1); + group = ext4_get_group_number(sb, start_blk); + next_group_start = ext4_group_first_block_no(sb, group + 1); group -= group_data[0].group; - group_data[group].free_blocks_count -= - EXT4_SB(sb)->s_itb_per_group; - if (flexbg_size > 1) - flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; + if (start_blk + itb > next_group_start) { + flex_gd->bg_flags[group + 1] &= uninit_mask; + overhead = start_blk + itb - next_group_start; + group_data[group + 1].free_blocks_count -= overhead; + itb -= overhead; + } + + group_data[group].free_blocks_count -= itb; + flex_gd->bg_flags[group] &= uninit_mask; start_blk += EXT4_SB(sb)->s_itb_per_group; } @@ -620,7 +628,7 @@ handle_ib: if (err) goto out; count = group_table_count[j]; - start = group_data[i].block_bitmap; + start = (&group_data[i].block_bitmap)[j]; block = start; } -- cgit v0.10.2 From 3d2660d0c9c2f296837078c189b68a47f6b2e3b5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 15 Feb 2014 22:42:25 -0500 Subject: ext4: fix online resize with a non-standard blocks per group setting The set_flexbg_block_bitmap() function assumed that the number of blocks in a blockgroup was sb->blocksize * 8, which is normally true, but not always! Use EXT4_BLOCKS_PER_GROUP(sb) instead, to fix block bitmap corruption after: mke2fs -t ext4 -g 3072 -i 4096 /dev/vdd 1G mount -t ext4 /dev/vdd /vdd resize2fs /dev/vdd 8G Signed-off-by: "Theodore Ts'o" Reported-by: Jon Bernard Cc: stable@vger.kernel.org diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 69a6261..f3b84cd 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -409,7 +409,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle, start = ext4_group_first_block_no(sb, group); group -= flex_gd->groups[0].group; - count2 = sb->s_blocksize * 8 - (block - start); + count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start); if (count2 > count) count2 = count; -- cgit v0.10.2 From 8ad116e649b21a42e3cccfb3c1b8d5ea52ba19e5 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sun, 16 Feb 2014 12:29:53 -0300 Subject: ata: sata_mv: Cleanup only the initialized ports When an error occurs in the port initialization loop, currently the driver tries to cleanup all the ports. This results in a NULL pointer dereference if the ports were only partially initialized. Fix this by updating only the number of initialized ports (either with failure or successfully), before jumping to the error path and looping over that number in the cleanup loop. Cc: Andrew Lunn Reported-by: Mikael Pettersson Signed-off-by: Ezequiel Garcia Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 20a7517..9c1a11d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4104,7 +4104,6 @@ static int mv_platform_probe(struct platform_device *pdev) if (!hpriv->port_phys) return -ENOMEM; host->private_data = hpriv; - hpriv->n_ports = n_ports; hpriv->board_idx = chip_soc; host->iomap = NULL; @@ -4132,11 +4131,17 @@ static int mv_platform_probe(struct platform_device *pdev) hpriv->port_phys[port] = NULL; if ((rc != -EPROBE_DEFER) && (rc != -ENODEV)) dev_warn(&pdev->dev, "error getting phy"); + + /* Cleanup only the initialized ports */ + hpriv->n_ports = port; goto err; } else phy_power_on(hpriv->port_phys[port]); } + /* All the ports have been initialized */ + hpriv->n_ports = n_ports; + /* * (Re-)program MBUS remapping windows if we are asked to. */ @@ -4174,7 +4179,7 @@ err: clk_disable_unprepare(hpriv->clk); clk_put(hpriv->clk); } - for (port = 0; port < n_ports; port++) { + for (port = 0; port < hpriv->n_ports; port++) { if (!IS_ERR(hpriv->port_clks[port])) { clk_disable_unprepare(hpriv->port_clks[port]); clk_put(hpriv->port_clks[port]); -- cgit v0.10.2 From 9eb2ddb48ce3a7bd745c14a933112994647fa3cd Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 16 Feb 2014 12:14:13 -0500 Subject: SUNRPC: Ensure that gss_auth isn't freed before its upcall messages Fix a race in which the RPC client is shutting down while the gss daemon is processing a downcall. If the RPC client manages to shut down before the gss daemon is done, then the struct gss_auth used in gss_release_msg() may have already been freed. Link: http://lkml.kernel.org/r/1392494917.71728.YahooMailNeo@web140002.mail.bf1.yahoo.com Reported-by: John Reported-by: Borislav Petkov Cc: stable@vger.kernel.org # 3.12+ Signed-off-by: Trond Myklebust diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 44a61e8..1ba1fd1 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -108,6 +108,7 @@ struct gss_auth { static DEFINE_SPINLOCK(pipe_version_lock); static struct rpc_wait_queue pipe_version_rpc_waitqueue; static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); +static void gss_put_auth(struct gss_auth *gss_auth); static void gss_free_ctx(struct gss_cl_ctx *); static const struct rpc_pipe_ops gss_upcall_ops_v0; @@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) if (gss_msg->ctx != NULL) gss_put_ctx(gss_msg->ctx); rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); + gss_put_auth(gss_msg->auth); kfree(gss_msg); } @@ -500,6 +502,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, if (err) goto err_free_msg; }; + kref_get(&gss_auth->kref); return gss_msg; err_free_msg: kfree(gss_msg); @@ -1064,6 +1067,12 @@ gss_free_callback(struct kref *kref) } static void +gss_put_auth(struct gss_auth *gss_auth) +{ + kref_put(&gss_auth->kref, gss_free_callback); +} + +static void gss_destroy(struct rpc_auth *auth) { struct gss_auth *gss_auth = container_of(auth, @@ -1084,7 +1093,7 @@ gss_destroy(struct rpc_auth *auth) gss_auth->gss_pipe[1] = NULL; rpcauth_destroy_credcache(auth); - kref_put(&gss_auth->kref, gss_free_callback); + gss_put_auth(gss_auth); } /* @@ -1255,7 +1264,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) call_rcu(&cred->cr_rcu, gss_free_cred_callback); if (ctx) gss_put_ctx(ctx); - kref_put(&gss_auth->kref, gss_free_callback); + gss_put_auth(gss_auth); } static void -- cgit v0.10.2 From e9776d0f4adee8877145672f6416b06b57f2dc27 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 16 Feb 2014 13:28:01 -0500 Subject: SUNRPC: Fix a pipe_version reference leak In gss_alloc_msg(), if the call to gss_encode_v1_msg() fails, we want to release the reference to the pipe_version that was obtained earlier in the function. Fixes: 9d3a2260f0f4b (SUNRPC: Fix buffer overflow checking in...) Signed-off-by: Trond Myklebust diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1ba1fd1..36e431e 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -500,10 +500,12 @@ gss_alloc_msg(struct gss_auth *gss_auth, default: err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); if (err) - goto err_free_msg; + goto err_put_pipe_version; }; kref_get(&gss_auth->kref); return gss_msg; +err_put_pipe_version: + put_pipe_version(gss_auth->net); err_free_msg: kfree(gss_msg); err: -- cgit v0.10.2 From 1a18a66446f3f289b05b634f18012424d82aa63a Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Fri, 17 Jan 2014 12:25:28 +0800 Subject: powerpc: Set the correct ksp_limit on ppc32 when switching to irq stack Guenter Roeck has got the following call trace on a p2020 board: Kernel stack overflow in process eb3e5a00, r1=eb79df90 CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4 task: eb3e5a00 ti: c0616000 task.ti: ef440000 NIP: c003a420 LR: c003a410 CTR: c0017518 REGS: eb79dee0 TRAP: 0901 Not tainted (3.13.0-rc8-juniper-00146-g19eca00) MSR: 00029000 CR: 24008444 XER: 00000000 GPR00: c003a410 eb79df90 eb3e5a00 00000000 eb05d900 00000001 65d87646 00000000 GPR08: 00000000 020b8000 00000000 00000000 44008442 NIP [c003a420] __do_softirq+0x94/0x1ec LR [c003a410] __do_softirq+0x84/0x1ec Call Trace: [eb79df90] [c003a410] __do_softirq+0x84/0x1ec (unreliable) [eb79dfe0] [c003a970] irq_exit+0xbc/0xc8 [eb79dff0] [c000cc1c] call_do_irq+0x24/0x3c [ef441f20] [c00046a8] do_IRQ+0x8c/0xf8 [ef441f40] [c000e7f4] ret_from_except+0x0/0x18 --- Exception: 501 at 0xfcda524 LR = 0x10024900 Instruction dump: 7c781b78 3b40000a 3a73b040 543c0024 3a800000 3b3913a0 7ef5bb78 48201bf9 5463103a 7d3b182e 7e89b92e 7c008146 <3ba00000> 7e7e9b78 48000014 57fff87f Kernel panic - not syncing: kernel stack overflow CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4 Call Trace: The reason is that we have used the wrong register to calculate the ksp_limit in commit cbc9565ee826 (powerpc: Remove ksp_limit on ppc64). Just fix it. As suggested by Benjamin Herrenschmidt, also add the C prototype of the function in the comment in order to avoid such kind of errors in the future. Cc: stable@vger.kernel.org # 3.12 Reported-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 879f096..7c6bb4b 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -57,11 +57,14 @@ _GLOBAL(call_do_softirq) mtlr r0 blr +/* + * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp); + */ _GLOBAL(call_do_irq) mflr r0 stw r0,4(r1) lwz r10,THREAD+KSP_LIMIT(r2) - addi r11,r3,THREAD_INFO_GAP + addi r11,r4,THREAD_INFO_GAP stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4) mr r1,r4 stw r10,8(r1) -- cgit v0.10.2 From b020cc6c03a37c3526fcb1dff274f649257949e0 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Fri, 17 Jan 2014 11:56:51 -0200 Subject: powerpc/pseries: Fix regression on PCI link speed Commit 5091f0c (powerpc/pseries: Fix PCIE link speed endian issue) introduced a regression on the PCI link speed detection using the device-tree property. The ibm,pcie-link-speed-stats property is composed of two 32-bit integers, the first one being the maxinum link speed and the second the current link speed. The changes introduced by the aforementioned commit are considering just the first integer. Fix this issue by changing how the property is accessed, using the helper functions to properly access the array of values. The explicit byte swapping is not needed anymore here, since it's done by the helper functions. Signed-off-by: Kleber Sacilotto de Souza Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 70670a2..a6f7a14 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -113,7 +113,8 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) { struct device_node *dn, *pdn; struct pci_bus *bus; - const __be32 *pcie_link_speed_stats; + u32 pcie_link_speed_stats[2]; + int rc; bus = bridge->bus; @@ -122,20 +123,21 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) return 0; for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) { - pcie_link_speed_stats = of_get_property(pdn, - "ibm,pcie-link-speed-stats", NULL); - if (pcie_link_speed_stats) + rc = of_property_read_u32_array(pdn, + "ibm,pcie-link-speed-stats", + &pcie_link_speed_stats[0], 2); + if (!rc) break; } of_node_put(pdn); - if (!pcie_link_speed_stats) { + if (rc) { pr_err("no ibm,pcie-link-speed-stats property\n"); return 0; } - switch (be32_to_cpup(pcie_link_speed_stats)) { + switch (pcie_link_speed_stats[0]) { case 0x01: bus->max_bus_speed = PCIE_SPEED_2_5GT; break; @@ -147,7 +149,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) break; } - switch (be32_to_cpup(pcie_link_speed_stats)) { + switch (pcie_link_speed_stats[1]) { case 0x01: bus->cur_bus_speed = PCIE_SPEED_2_5GT; break; -- cgit v0.10.2 From 49d9684a54d21930372b7fb0d3d7b5617f621706 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Fri, 17 Jan 2014 11:56:52 -0200 Subject: powerpc/pseries: Add Gen3 definitions for PCIE link speed Rev3 of the PCI Express Base Specification defines a Supported Link Speeds Vector where the bit definitions within this field are: Bit 0 - 2.5 GT/s Bit 1 - 5.0 GT/s Bit 2 - 8.0 GT/s This vector definition is used by the platform firmware to export the maximum and current link speeds of the PCI bus via the "ibm,pcie-link-speed-stats" device-tree property. This patch updates pseries_root_bridge_prepare() to detect Gen3 speed buses (defined by 0x04). Signed-off-by: Kleber Sacilotto de Souza Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index a6f7a14..c413ec1 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -144,6 +144,9 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) case 0x02: bus->max_bus_speed = PCIE_SPEED_5_0GT; break; + case 0x04: + bus->max_bus_speed = PCIE_SPEED_8_0GT; + break; default: bus->max_bus_speed = PCI_SPEED_UNKNOWN; break; @@ -156,6 +159,9 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) case 0x02: bus->cur_bus_speed = PCIE_SPEED_5_0GT; break; + case 0x04: + bus->cur_bus_speed = PCIE_SPEED_8_0GT; + break; default: bus->cur_bus_speed = PCI_SPEED_UNKNOWN; break; -- cgit v0.10.2 From 88247e8d7ba6639f2c199e147ebbc91f7673150c Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 12 Feb 2014 09:13:36 +0530 Subject: powerpc/mm: Add new "set" flag argument to pte/pmd update function pte_update() is a powerpc-ism used to change the bits of a PTE when the access permission is being restricted (a flush is potentially needed). It uses atomic operations on when needed and handles the hash synchronization on hash based processors. It is currently only used to clear PTE bits and so the current implementation doesn't provide a way to also set PTE bits. The new _PAGE_NUMA bit, when set, is actually restricting access so it must use that function too, so this change adds the ability for pte_update() to also set bits. We will use this later to set the _PAGE_NUMA bit. Acked-by: Mel Gorman Acked-by: Rik van Riel Signed-off-by: Aneesh Kumar K.V Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index d750336..623f297 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h @@ -127,7 +127,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { #ifdef CONFIG_PPC64 - return __pte(pte_update(mm, addr, ptep, ~0UL, 1)); + return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 1)); #else return __pte(pte_update(ptep, ~0UL, 0)); #endif diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index bc141c9..eb92610 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h @@ -195,6 +195,7 @@ extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr, static inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr, pte_t *ptep, unsigned long clr, + unsigned long set, int huge) { #ifdef PTE_ATOMIC_UPDATES @@ -205,14 +206,15 @@ static inline unsigned long pte_update(struct mm_struct *mm, andi. %1,%0,%6\n\ bne- 1b \n\ andc %1,%0,%4 \n\ + or %1,%1,%7\n\ stdcx. %1,0,%3 \n\ bne- 1b" : "=&r" (old), "=&r" (tmp), "=m" (*ptep) - : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY) + : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set) : "cc" ); #else unsigned long old = pte_val(*ptep); - *ptep = __pte(old & ~clr); + *ptep = __pte((old & ~clr) | set); #endif /* huge pages use the old page table lock */ if (!huge) @@ -231,9 +233,9 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, { unsigned long old; - if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) + if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) return 0; - old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0); + old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); return (old & _PAGE_ACCESSED) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG @@ -252,7 +254,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, if ((pte_val(*ptep) & _PAGE_RW) == 0) return; - pte_update(mm, addr, ptep, _PAGE_RW, 0); + pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); } static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, @@ -261,7 +263,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, if ((pte_val(*ptep) & _PAGE_RW) == 0) return; - pte_update(mm, addr, ptep, _PAGE_RW, 1); + pte_update(mm, addr, ptep, _PAGE_RW, 0, 1); } /* @@ -284,14 +286,14 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0); + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0); return __pte(old); } static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep) { - pte_update(mm, addr, ptep, ~0UL, 0); + pte_update(mm, addr, ptep, ~0UL, 0, 0); } @@ -506,7 +508,9 @@ extern int pmdp_set_access_flags(struct vm_area_struct *vma, extern unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, - pmd_t *pmdp, unsigned long clr); + pmd_t *pmdp, + unsigned long clr, + unsigned long set); static inline int __pmdp_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) @@ -515,7 +519,7 @@ static inline int __pmdp_test_and_clear_young(struct mm_struct *mm, if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) return 0; - old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED); + old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0); return ((old & _PAGE_ACCESSED) != 0); } @@ -542,7 +546,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, if ((pmd_val(*pmdp) & _PAGE_RW) == 0) return; - pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW); + pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW, 0); } #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 65b7b65..62bf5e8 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -510,7 +510,8 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address, } unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, - pmd_t *pmdp, unsigned long clr) + pmd_t *pmdp, unsigned long clr, + unsigned long set) { unsigned long old, tmp; @@ -526,14 +527,15 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, andi. %1,%0,%6\n\ bne- 1b \n\ andc %1,%0,%4 \n\ + or %1,%1,%7\n\ stdcx. %1,0,%3 \n\ bne- 1b" : "=&r" (old), "=&r" (tmp), "=m" (*pmdp) - : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY) + : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY), "r" (set) : "cc" ); #else old = pmd_val(*pmdp); - *pmdp = __pmd(old & ~clr); + *pmdp = __pmd((old & ~clr) | set); #endif if (old & _PAGE_HASHPTE) hpte_do_hugepage_flush(mm, addr, pmdp); @@ -708,7 +710,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) { - pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT); + pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0); } /* @@ -835,7 +837,7 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm, unsigned long old; pgtable_t *pgtable_slot; - old = pmd_hugepage_update(mm, addr, pmdp, ~0UL); + old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0); old_pmd = __pmd(old); /* * We have pmd == none and we are holding page_table_lock. diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c index a770df2d..6c0b1f5 100644 --- a/arch/powerpc/mm/subpage-prot.c +++ b/arch/powerpc/mm/subpage-prot.c @@ -78,7 +78,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, pte = pte_offset_map_lock(mm, pmd, addr, &ptl); arch_enter_lazy_mmu_mode(); for (; npages > 0; --npages) { - pte_update(mm, addr, pte, 0, 0); + pte_update(mm, addr, pte, 0, 0, 0); addr += PAGE_SIZE; ++pte; } -- cgit v0.10.2 From 9d85d5863fa4818eb7fa306563bf830c0210c3a6 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 12 Feb 2014 09:13:37 +0530 Subject: mm: Dirty accountable change only apply to non prot numa case So move it within the if loop Acked-by: Mel Gorman Reviewed-by: Rik van Riel Signed-off-by: Aneesh Kumar K.V Signed-off-by: Benjamin Herrenschmidt diff --git a/mm/mprotect.c b/mm/mprotect.c index 7332c17..33eab90 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -58,6 +58,13 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, if (pte_numa(ptent)) ptent = pte_mknonnuma(ptent); ptent = pte_modify(ptent, newprot); + /* + * Avoid taking write faults for pages we + * know to be dirty. + */ + if (dirty_accountable && pte_dirty(ptent)) + ptent = pte_mkwrite(ptent); + ptep_modify_prot_commit(mm, addr, pte, ptent); updated = true; } else { struct page *page; @@ -72,22 +79,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, } } } - - /* - * Avoid taking write faults for pages we know to be - * dirty. - */ - if (dirty_accountable && pte_dirty(ptent)) { - ptent = pte_mkwrite(ptent); - updated = true; - } - if (updated) pages++; - - /* Only !prot_numa always clears the pte */ - if (!prot_numa) - ptep_modify_prot_commit(mm, addr, pte, ptent); } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) { swp_entry_t entry = pte_to_swp_entry(oldpte); -- cgit v0.10.2 From 56eecdb912b536a4fa97fb5bfe5a940a54d79be6 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 12 Feb 2014 09:13:38 +0530 Subject: mm: Use ptep/pmdp_set_numa() for updating _PAGE_NUMA bit Archs like ppc64 doesn't do tlb flush in set_pte/pmd functions when using a hash table MMU for various reasons (the flush is handled as part of the PTE modification when necessary). ppc64 thus doesn't implement flush_tlb_range for hash based MMUs. Additionally ppc64 require the tlb flushing to be batched within ptl locks. The reason to do that is to ensure that the hash page table is in sync with linux page table. We track the hpte index in linux pte and if we clear them without flushing hash and drop the ptl lock, we can have another cpu update the pte and can end up with duplicate entry in the hash table, which is fatal. We also want to keep set_pte_at simpler by not requiring them to do hash flush for performance reason. We do that by assuming that set_pte_at() is never *ever* called on a PTE that is already valid. This was the case until the NUMA code went in which broke that assumption. Fix that by introducing a new pair of helpers to set _PAGE_NUMA in a way similar to ptep/pmdp_set_wrprotect(), with a generic implementation using set_pte_at() and a powerpc specific one using the appropriate mechanism needed to keep the hash table in sync. Acked-by: Mel Gorman Reviewed-by: Rik van Riel Signed-off-by: Aneesh Kumar K.V Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index f83b6f3..3ebb188 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -75,12 +75,34 @@ static inline pte_t pte_mknuma(pte_t pte) return pte; } +#define ptep_set_numa ptep_set_numa +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + if ((pte_val(*ptep) & _PAGE_PRESENT) == 0) + VM_BUG_ON(1); + + pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0); + return; +} + #define pmd_numa pmd_numa static inline int pmd_numa(pmd_t pmd) { return pte_numa(pmd_pte(pmd)); } +#define pmdp_set_numa pmdp_set_numa +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp) +{ + if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0) + VM_BUG_ON(1); + + pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA); + return; +} + #define pmd_mknonnuma pmd_mknonnuma static inline pmd_t pmd_mknonnuma(pmd_t pmd) { diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 8e4f41d..34c7bdc 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -701,6 +701,18 @@ static inline pte_t pte_mknuma(pte_t pte) } #endif +#ifndef ptep_set_numa +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + pte_t ptent = *ptep; + + ptent = pte_mknuma(ptent); + set_pte_at(mm, addr, ptep, ptent); + return; +} +#endif + #ifndef pmd_mknuma static inline pmd_t pmd_mknuma(pmd_t pmd) { @@ -708,6 +720,18 @@ static inline pmd_t pmd_mknuma(pmd_t pmd) return pmd_clear_flags(pmd, _PAGE_PRESENT); } #endif + +#ifndef pmdp_set_numa +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp) +{ + pmd_t pmd = *pmdp; + + pmd = pmd_mknuma(pmd); + set_pmd_at(mm, addr, pmdp, pmd); + return; +} +#endif #else extern int pte_numa(pte_t pte); extern int pmd_numa(pmd_t pmd); @@ -715,6 +739,8 @@ extern pte_t pte_mknonnuma(pte_t pte); extern pmd_t pmd_mknonnuma(pmd_t pmd); extern pte_t pte_mknuma(pte_t pte); extern pmd_t pmd_mknuma(pmd_t pmd); +extern void ptep_set_numa(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +extern void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp); #endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */ #else static inline int pmd_numa(pmd_t pmd) @@ -742,10 +768,23 @@ static inline pte_t pte_mknuma(pte_t pte) return pte; } +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + return; +} + + static inline pmd_t pmd_mknuma(pmd_t pmd) { return pmd; } + +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp) +{ + return ; +} #endif /* CONFIG_NUMA_BALANCING */ #endif /* CONFIG_MMU */ diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 82166bf..da23eb9 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1545,6 +1545,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, entry = pmd_mknonnuma(entry); entry = pmd_modify(entry, newprot); ret = HPAGE_PMD_NR; + set_pmd_at(mm, addr, pmd, entry); BUG_ON(pmd_write(entry)); } else { struct page *page = pmd_page(*pmd); @@ -1557,16 +1558,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, */ if (!is_huge_zero_page(page) && !pmd_numa(*pmd)) { - entry = *pmd; - entry = pmd_mknuma(entry); + pmdp_set_numa(mm, addr, pmd); ret = HPAGE_PMD_NR; } } - - /* Set PMD if cleared earlier */ - if (ret == HPAGE_PMD_NR) - set_pmd_at(mm, addr, pmd, entry); - spin_unlock(ptl); } diff --git a/mm/mprotect.c b/mm/mprotect.c index 33eab90..769a67a 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -69,12 +69,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, } else { struct page *page; - ptent = *pte; page = vm_normal_page(vma, addr, oldpte); if (page && !PageKsm(page)) { if (!pte_numa(oldpte)) { - ptent = pte_mknuma(ptent); - set_pte_at(mm, addr, pte, ptent); + ptep_set_numa(mm, addr, pte); updated = true; } } -- cgit v0.10.2 From a0a4419e302fedb548d56129e02130347810f892 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 12 Feb 2014 17:17:05 +1100 Subject: powerpc: Link VDSOs at 0x0 perf is failing to resolve symbols in the VDSO. A while (1) gettimeofday() loop shows: 93.99% [vdso] [.] 0x00000000000005e0 3.12% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 2.81% test [.] main The reason for this is that we are linking our VDSO shared libraries at 1MB, which is a little weird. Even though this is uncommon, Alan points out that it is valid and we should probably fix perf userspace. Regardless, I can't see a reason why we are doing this. The code is all position independent and we never rely on the VDSO ending up at 1M (and we never place it there on 64bit tasks). Changing our link address to 0x0 fixes perf VDSO symbol resolution: 73.18% [vdso] [.] 0x000000000000060c 12.39% [vdso] [.] __kernel_gettimeofday 3.58% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 2.94% [vdso] [.] __kernel_datapage_offset 2.90% test [.] main We still have some local symbol resolution issues that will be fixed in a subsequent patch. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h index 0d9cecd..c53f5f6 100644 --- a/arch/powerpc/include/asm/vdso.h +++ b/arch/powerpc/include/asm/vdso.h @@ -4,11 +4,11 @@ #ifdef __KERNEL__ /* Default link addresses for the vDSOs */ -#define VDSO32_LBASE 0x100000 -#define VDSO64_LBASE 0x100000 +#define VDSO32_LBASE 0x0 +#define VDSO64_LBASE 0x0 /* Default map addresses for 32bit vDSO */ -#define VDSO32_MBASE VDSO32_LBASE +#define VDSO32_MBASE 0x100000 #define VDSO_VERSION_STRING LINUX_2.6.15 -- cgit v0.10.2 From 24b659a13866b935eca72748ce725279bd3c4466 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 12 Feb 2014 17:18:50 +1100 Subject: powerpc: Use unstripped VDSO image for more accurate profiling data We are seeing a lot of hits in the VDSO that are not resolved by perf. A while(1) gettimeofday() loop shows the issue: 27.64% [vdso] [.] 0x000000000000060c 22.57% [vdso] [.] 0x0000000000000628 16.88% [vdso] [.] 0x0000000000000610 12.39% [vdso] [.] __kernel_gettimeofday 6.09% [vdso] [.] 0x00000000000005f8 3.58% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 2.94% [vdso] [.] __kernel_datapage_offset 2.90% test [.] main We are using a stripped VDSO image which means only symbols with relocation info can be resolved. There isn't a lot of point to stripping the VDSO, the debug info is only about 1kB: 4680 arch/powerpc/kernel/vdso64/vdso64.so 5815 arch/powerpc/kernel/vdso64/vdso64.so.dbg By using the unstripped image, we can resolve all the symbols in the VDSO and the perf profile data looks much better: 76.53% [vdso] [.] __do_get_tspec 12.20% [vdso] [.] __kernel_gettimeofday 5.05% [vdso] [.] __get_datapage 3.20% test [.] main 2.92% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/vdso32/vdso32_wrapper.S b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S index 79683d0..6ac107a 100644 --- a/arch/powerpc/kernel/vdso32/vdso32_wrapper.S +++ b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S @@ -6,7 +6,7 @@ .globl vdso32_start, vdso32_end .balign PAGE_SIZE vdso32_start: - .incbin "arch/powerpc/kernel/vdso32/vdso32.so" + .incbin "arch/powerpc/kernel/vdso32/vdso32.so.dbg" .balign PAGE_SIZE vdso32_end: diff --git a/arch/powerpc/kernel/vdso64/vdso64_wrapper.S b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S index 8df9e24..df60fca 100644 --- a/arch/powerpc/kernel/vdso64/vdso64_wrapper.S +++ b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S @@ -6,7 +6,7 @@ .globl vdso64_start, vdso64_end .balign PAGE_SIZE vdso64_start: - .incbin "arch/powerpc/kernel/vdso64/vdso64.so" + .incbin "arch/powerpc/kernel/vdso64/vdso64.so.dbg" .balign PAGE_SIZE vdso64_end: -- cgit v0.10.2 From 5b2e198e50f6ba57081586b853163ea1bb95f1a8 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 12 Feb 2014 15:24:54 +0800 Subject: powerpc/powernv: Rework EEH reset When doing reset in order to recover the affected PE, we issue hot reset on PE primary bus if it's not root bus. Otherwise, we issue hot or fundamental reset on root port or PHB accordingly. For the later case, we didn't cover the situation where PE only includes root port and it potentially causes kernel crash upon EEH error to the PE. The patch reworks the logic of EEH reset to improve the code readability and also avoid the kernel crash. Cc: stable@vger.kernel.org Reported-by: Thadeu Lima de Souza Cascardo Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index e1e7161..fcb79cf 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -489,8 +489,7 @@ static int ioda_eeh_bridge_reset(struct pci_controller *hose, static int ioda_eeh_reset(struct eeh_pe *pe, int option) { struct pci_controller *hose = pe->phb; - struct eeh_dev *edev; - struct pci_dev *dev; + struct pci_bus *bus; int ret; /* @@ -519,31 +518,11 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) if (pe->type & EEH_PE_PHB) { ret = ioda_eeh_phb_reset(hose, option); } else { - if (pe->type & EEH_PE_DEVICE) { - /* - * If it's device PE, we didn't refer to the parent - * PCI bus yet. So we have to figure it out indirectly. - */ - edev = list_first_entry(&pe->edevs, - struct eeh_dev, list); - dev = eeh_dev_to_pci_dev(edev); - dev = dev->bus->self; - } else { - /* - * If it's bus PE, the parent PCI bus is already there - * and just pick it up. - */ - dev = pe->bus->self; - } - - /* - * Do reset based on the fact that the direct upstream bridge - * is root bridge (port) or not. - */ - if (dev->bus->number == 0) + bus = eeh_pe_bus_get(pe); + if (pci_is_root_bus(bus)) ret = ioda_eeh_root_reset(hose, option); else - ret = ioda_eeh_bridge_reset(hose, dev, option); + ret = ioda_eeh_bridge_reset(hose, bus->self, option); } return ret; -- cgit v0.10.2 From 2ec5a0adf60c23bb6b0a95d3b96a8c1ff1e1aa5a Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 12 Feb 2014 15:24:55 +0800 Subject: powerpc/eeh: Cleanup on eeh_subsystem_enabled The patch cleans up variable eeh_subsystem_enabled so that we needn't refer the variable directly from external. Instead, we will use function eeh_enabled() and eeh_set_enable() to operate the variable. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 9e39ceb..d4dd41f 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -172,10 +172,20 @@ struct eeh_ops { }; extern struct eeh_ops *eeh_ops; -extern int eeh_subsystem_enabled; +extern bool eeh_subsystem_enabled; extern raw_spinlock_t confirm_error_lock; extern int eeh_probe_mode; +static inline bool eeh_enabled(void) +{ + return eeh_subsystem_enabled; +} + +static inline void eeh_set_enable(bool mode) +{ + eeh_subsystem_enabled = mode; +} + #define EEH_PROBE_MODE_DEV (1<<0) /* From PCI device */ #define EEH_PROBE_MODE_DEVTREE (1<<1) /* From device tree */ @@ -246,7 +256,7 @@ void eeh_remove_device(struct pci_dev *); * If this macro yields TRUE, the caller relays to eeh_check_failure() * which does further tests out of line. */ -#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0 && eeh_subsystem_enabled) +#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0 && eeh_enabled()) /* * Reads from a device which has been isolated by EEH will return @@ -257,6 +267,13 @@ void eeh_remove_device(struct pci_dev *); #else /* !CONFIG_EEH */ +static inline bool eeh_enabled(void) +{ + return false; +} + +static inline void eeh_set_enable(bool mode) { } + static inline int eeh_init(void) { return 0; diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 148db72..f22f7b6 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -89,7 +89,7 @@ /* Platform dependent EEH operations */ struct eeh_ops *eeh_ops = NULL; -int eeh_subsystem_enabled; +bool eeh_subsystem_enabled = false; EXPORT_SYMBOL(eeh_subsystem_enabled); /* @@ -364,7 +364,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev) eeh_stats.total_mmio_ffs++; - if (!eeh_subsystem_enabled) + if (!eeh_enabled()) return 0; if (!edev) { @@ -822,7 +822,7 @@ int eeh_init(void) return ret; } - if (eeh_subsystem_enabled) + if (eeh_enabled()) pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); else pr_warning("EEH: No capable adapters found\n"); @@ -897,7 +897,7 @@ void eeh_add_device_late(struct pci_dev *dev) struct device_node *dn; struct eeh_dev *edev; - if (!dev || !eeh_subsystem_enabled) + if (!dev || !eeh_enabled()) return; pr_debug("EEH: Adding device %s\n", pci_name(dev)); @@ -1005,7 +1005,7 @@ void eeh_remove_device(struct pci_dev *dev) { struct eeh_dev *edev; - if (!dev || !eeh_subsystem_enabled) + if (!dev || !eeh_enabled()) return; edev = pci_dev_to_eeh_dev(dev); @@ -1045,7 +1045,7 @@ void eeh_remove_device(struct pci_dev *dev) static int proc_eeh_show(struct seq_file *m, void *v) { - if (0 == eeh_subsystem_enabled) { + if (!eeh_enabled()) { seq_printf(m, "EEH Subsystem is globally disabled\n"); seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs); } else { diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index a79fddc..a59788e 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -145,7 +145,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) * Enable EEH explicitly so that we will do EEH check * while accessing I/O stuff */ - eeh_subsystem_enabled = 1; + eeh_set_enable(true); /* Save memory bars */ eeh_save_bars(edev); diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 9ef3cc8..8a8f047 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -265,7 +265,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) enable = 1; if (enable) { - eeh_subsystem_enabled = 1; + eeh_set_enable(true); eeh_add_to_parent_pe(edev); pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", -- cgit v0.10.2 From 66f9af83e56bfa12964d251df9d60fb571579913 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 12 Feb 2014 15:24:56 +0800 Subject: powerpc/eeh: Disable EEH on reboot We possiblly detect EEH errors during reboot, particularly in kexec path, but it's impossible for device drivers and EEH core to handle or recover them properly. The patch registers one reboot notifier for EEH and disable EEH subsystem during reboot. That means the EEH errors is going to be cleared by hardware reset or second kernel during early stage of PCI probe. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index f22f7b6..e7b76a6 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -747,6 +748,17 @@ int __exit eeh_ops_unregister(const char *name) return -EEXIST; } +static int eeh_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + eeh_set_enable(false); + return NOTIFY_DONE; +} + +static struct notifier_block eeh_reboot_nb = { + .notifier_call = eeh_reboot_notifier, +}; + /** * eeh_init - EEH initialization * @@ -778,6 +790,14 @@ int eeh_init(void) if (machine_is(powernv) && cnt++ <= 0) return ret; + /* Register reboot notifier */ + ret = register_reboot_notifier(&eeh_reboot_nb); + if (ret) { + pr_warn("%s: Failed to register notifier (%d)\n", + __func__, ret); + return ret; + } + /* call platform initialization function */ if (!eeh_ops) { pr_warning("%s: Platform EEH operation not found\n", diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index fcb79cf..f514743 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -44,7 +44,8 @@ static int ioda_eeh_event(struct notifier_block *nb, /* We simply send special EEH event */ if ((changed_evts & OPAL_EVENT_PCI_ERROR) && - (events & OPAL_EVENT_PCI_ERROR)) + (events & OPAL_EVENT_PCI_ERROR) && + eeh_enabled()) eeh_send_failure_event(NULL); return 0; -- cgit v0.10.2 From 19ea80603715d473600cd993b9987bc97d042e02 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 16 Feb 2014 19:29:32 -0500 Subject: ext4: don't leave i_crtime.tv_sec uninitialized If the i_crtime field is not present in the inode, don't leave the field uninitialized. Fixes: ef7f38359 ("ext4: Add nanosecond timestamps") Reported-by: Vegard Nossum Tested-by: Vegard Nossum Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ece5556..d3a534f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -771,6 +771,8 @@ do { \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ (einode)->xtime.tv_sec = \ (signed)le32_to_cpu((raw_inode)->xtime); \ + else \ + (einode)->xtime.tv_sec = 0; \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ ext4_decode_extra_time(&(einode)->xtime, \ raw_inode->xtime ## _extra); \ -- cgit v0.10.2 From 09db30805300e9ed5ad43d4d339115cf1d9c84e1 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Thu, 13 Feb 2014 19:02:33 -0700 Subject: dccp: re-enable debug macro dccp tfrc: revert This reverts 6aee49c558de ("dccp: make local variable static") since the variable tfrc_debug is referenced by the tfrc_pr_debug(fmt, ...) macro when TFRC debugging is enabled. If it is enabled, use of the macro produces a compilation error. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c index c073b81..62b5828 100644 --- a/net/dccp/ccids/lib/tfrc.c +++ b/net/dccp/ccids/lib/tfrc.c @@ -8,7 +8,7 @@ #include "tfrc.h" #ifdef CONFIG_IP_DCCP_TFRC_DEBUG -static bool tfrc_debug; +bool tfrc_debug; module_param(tfrc_debug, bool, 0644); MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages"); #endif diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index a3d8f7c..40ee7d6 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h @@ -21,6 +21,7 @@ #include "packet_history.h" #ifdef CONFIG_IP_DCCP_TFRC_DEBUG +extern bool tfrc_debug; #define tfrc_pr_debug(format, a...) DCCP_PR_DEBUG(tfrc_debug, format, ##a) #else #define tfrc_pr_debug(format, a...) -- cgit v0.10.2 From 891de74d693bb4fefe2efcc6432a4a9a9bee561e Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Wed, 12 Feb 2014 16:54:27 -0800 Subject: hyperv: Fix the carrier status setting Without this patch, the "cat /sys/class/net/ethN/operstate" shows "unknown", and "ethtool ethN" shows "Link detected: yes", when VM boots up with or without vNIC connected. This patch fixed the problem. Signed-off-by: Haiyang Zhang Reviewed-by: K. Y. Srinivasan Acked-by: Jason Wang Signed-off-by: David S. Miller diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 7756118..7141a19 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -88,8 +88,12 @@ static int netvsc_open(struct net_device *net) { struct net_device_context *net_device_ctx = netdev_priv(net); struct hv_device *device_obj = net_device_ctx->device_ctx; + struct netvsc_device *nvdev; + struct rndis_device *rdev; int ret = 0; + netif_carrier_off(net); + /* Open up the device */ ret = rndis_filter_open(device_obj); if (ret != 0) { @@ -99,6 +103,11 @@ static int netvsc_open(struct net_device *net) netif_start_queue(net); + nvdev = hv_get_drvdata(device_obj); + rdev = nvdev->extension; + if (!rdev->link_state) + netif_carrier_on(net); + return ret; } @@ -229,23 +238,24 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, struct net_device *net; struct net_device_context *ndev_ctx; struct netvsc_device *net_device; + struct rndis_device *rdev; net_device = hv_get_drvdata(device_obj); + rdev = net_device->extension; + + rdev->link_state = status != 1; + net = net_device->ndev; - if (!net) { - netdev_err(net, "got link status but net device " - "not initialized yet\n"); + if (!net || net->reg_state != NETREG_REGISTERED) return; - } + ndev_ctx = netdev_priv(net); if (status == 1) { - netif_carrier_on(net); - ndev_ctx = netdev_priv(net); schedule_delayed_work(&ndev_ctx->dwork, 0); schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20)); } else { - netif_carrier_off(net); + schedule_delayed_work(&ndev_ctx->dwork, 0); } } @@ -388,17 +398,35 @@ static const struct net_device_ops device_ops = { * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add * another netif_notify_peers() into a delayed work, otherwise GARP packet * will not be sent after quick migration, and cause network disconnection. + * Also, we update the carrier status here. */ -static void netvsc_send_garp(struct work_struct *w) +static void netvsc_link_change(struct work_struct *w) { struct net_device_context *ndev_ctx; struct net_device *net; struct netvsc_device *net_device; + struct rndis_device *rdev; + bool notify; + + rtnl_lock(); ndev_ctx = container_of(w, struct net_device_context, dwork.work); net_device = hv_get_drvdata(ndev_ctx->device_ctx); + rdev = net_device->extension; net = net_device->ndev; - netdev_notify_peers(net); + + if (rdev->link_state) { + netif_carrier_off(net); + notify = false; + } else { + netif_carrier_on(net); + notify = true; + } + + rtnl_unlock(); + + if (notify) + netdev_notify_peers(net); } @@ -414,13 +442,10 @@ static int netvsc_probe(struct hv_device *dev, if (!net) return -ENOMEM; - /* Set initial state */ - netif_carrier_off(net); - net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = dev; hv_set_drvdata(dev, net); - INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); + INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); INIT_WORK(&net_device_ctx->work, do_set_multicast); net->netdev_ops = &device_ops; @@ -443,8 +468,6 @@ static int netvsc_probe(struct hv_device *dev, } memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); - netif_carrier_on(net); - ret = register_netdev(net); if (ret != 0) { pr_err("Unable to register netdev.\n"); -- cgit v0.10.2 From cd0f0b95fd2cd2b716caf5f15db73ab76992789b Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Fri, 14 Feb 2014 18:26:22 +0800 Subject: ipv4: distinguish EHOSTUNREACH from the ENETUNREACH since commit 251da413("ipv4: Cache ip_error() routes even when not forwarding."), the counter IPSTATS_MIB_INADDRERRORS can't work correctly, because the value of err was always set to ENETUNREACH. Signed-off-by: Duan Jiong Signed-off-by: David S. Miller diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 25071b4..6f6dd85 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1695,8 +1695,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, fl4.daddr = daddr; fl4.saddr = saddr; err = fib_lookup(net, &fl4, &res); - if (err != 0) + if (err != 0) { + if (!IN_DEV_FORWARD(in_dev)) + err = -EHOSTUNREACH; goto no_route; + } RT_CACHE_STAT_INC(in_slow_tot); @@ -1712,8 +1715,10 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto local_input; } - if (!IN_DEV_FORWARD(in_dev)) + if (!IN_DEV_FORWARD(in_dev)) { + err = -EHOSTUNREACH; goto no_route; + } if (res.type != RTN_UNICAST) goto martian_destination; -- cgit v0.10.2 From ef2820a735f74ea60335f8ba3801b844f0cb184d Mon Sep 17 00:00:00 2001 From: Matija Glavinic Pecotic Date: Fri, 14 Feb 2014 14:51:18 +0100 Subject: net: sctp: Fix a_rwnd/rwnd management to reflect real state of the receiver's buffer Implementation of (a)rwnd calculation might lead to severe performance issues and associations completely stalling. These problems are described and solution is proposed which improves lksctp's robustness in congestion state. 1) Sudden drop of a_rwnd and incomplete window recovery afterwards Data accounted in sctp_assoc_rwnd_decrease takes only payload size (sctp data), but size of sk_buff, which is blamed against receiver buffer, is not accounted in rwnd. Theoretically, this should not be the problem as actual size of buffer is double the amount requested on the socket (SO_RECVBUF). Problem here is that this will have bad scaling for data which is less then sizeof sk_buff. E.g. in 4G (LTE) networks, link interfacing radio side will have a large portion of traffic of this size (less then 100B). An example of sudden drop and incomplete window recovery is given below. Node B exhibits problematic behavior. Node A initiates association and B is configured to advertise rwnd of 10000. A sends messages of size 43B (size of typical sctp message in 4G (LTE) network). On B data is left in buffer by not reading socket in userspace. Lets examine when we will hit pressure state and declare rwnd to be 0 for scenario with above stated parameters (rwnd == 10000, chunk size == 43, each chunk is sent in separate sctp packet) Logic is implemented in sctp_assoc_rwnd_decrease: socket_buffer (see below) is maximum size which can be held in socket buffer (sk_rcvbuf). current_alloced is amount of data currently allocated (rx_count) A simple expression is given for which it will be examined after how many packets for above stated parameters we enter pressure state: We start by condition which has to be met in order to enter pressure state: socket_buffer < currently_alloced; currently_alloced is represented as size of sctp packets received so far and not yet delivered to userspace. x is the number of chunks/packets (since there is no bundling, and each chunk is delivered in separate packet, we can observe each chunk also as sctp packet, and what is important here, having its own sk_buff): socket_buffer < x*each_sctp_packet; each_sctp_packet is sctp chunk size + sizeof(struct sk_buff). socket_buffer is twice the amount of initially requested size of socket buffer, which is in case of sctp, twice the a_rwnd requested: 2*rwnd < x*(payload+sizeof(struc sk_buff)); sizeof(struct sk_buff) is 190 (3.13.0-rc4+). Above is stated that rwnd is 10000 and each payload size is 43 20000 < x(43+190); x > 20000/233; x ~> 84; After ~84 messages, pressure state is entered and 0 rwnd is advertised while received 84*43B ~= 3612B sctp data. This is why external observer notices sudden drop from 6474 to 0, as it will be now shown in example: IP A.34340 > B.12345: sctp (1) [INIT] [init tag: 1875509148] [rwnd: 81920] [OS: 10] [MIS: 65535] [init TSN: 1096057017] IP B.12345 > A.34340: sctp (1) [INIT ACK] [init tag: 3198966556] [rwnd: 10000] [OS: 10] [MIS: 10] [init TSN: 902132839] IP A.34340 > B.12345: sctp (1) [COOKIE ECHO] IP B.12345 > A.34340: sctp (1) [COOKIE ACK] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057017] [SID: 0] [SSEQ 0] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057017] [a_rwnd 9957] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057018] [SID: 0] [SSEQ 1] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057018] [a_rwnd 9957] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057019] [SID: 0] [SSEQ 2] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057019] [a_rwnd 9914] [#gap acks 0] [#dup tsns 0] <...> IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057098] [SID: 0] [SSEQ 81] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057098] [a_rwnd 6517] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057099] [SID: 0] [SSEQ 82] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057099] [a_rwnd 6474] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057100] [SID: 0] [SSEQ 83] [PPID 0x18] --> Sudden drop IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057100] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] At this point, rwnd_press stores current rwnd value so it can be later restored in sctp_assoc_rwnd_increase. This however doesn't happen as condition to start slowly increasing rwnd until rwnd_press is returned to rwnd is never met. This condition is not met since rwnd, after it hit 0, must first reach rwnd_press by adding amount which is read from userspace. Let us observe values in above example. Initial a_rwnd is 10000, pressure was hit when rwnd was ~6500 and the amount of actual sctp data currently waiting to be delivered to userspace is ~3500. When userspace starts to read, sctp_assoc_rwnd_increase will be blamed only for sctp data, which is ~3500. Condition is never met, and when userspace reads all data, rwnd stays on 3569. IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057100] [a_rwnd 1505] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057100] [a_rwnd 3010] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057101] [SID: 0] [SSEQ 84] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057101] [a_rwnd 3569] [#gap acks 0] [#dup tsns 0] --> At this point userspace read everything, rwnd recovered only to 3569 IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057102] [SID: 0] [SSEQ 85] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057102] [a_rwnd 3569] [#gap acks 0] [#dup tsns 0] Reproduction is straight forward, it is enough for sender to send packets of size less then sizeof(struct sk_buff) and receiver keeping them in its buffers. 2) Minute size window for associations sharing the same socket buffer In case multiple associations share the same socket, and same socket buffer (sctp.rcvbuf_policy == 0), different scenarios exist in which congestion on one of the associations can permanently drop rwnd of other association(s). Situation will be typically observed as one association suddenly having rwnd dropped to size of last packet received and never recovering beyond that point. Different scenarios will lead to it, but all have in common that one of the associations (let it be association from 1)) nearly depleted socket buffer, and the other association blames socket buffer just for the amount enough to start the pressure. This association will enter pressure state, set rwnd_press and announce 0 rwnd. When data is read by userspace, similar situation as in 1) will occur, rwnd will increase just for the size read by userspace but rwnd_press will be high enough so that association doesn't have enough credit to reach rwnd_press and restore to previous state. This case is special case of 1), being worse as there is, in the worst case, only one packet in buffer for which size rwnd will be increased. Consequence is association which has very low maximum rwnd ('minute size', in our case down to 43B - size of packet which caused pressure) and as such unusable. Scenario happened in the field and labs frequently after congestion state (link breaks, different probabilities of packet drop, packet reordering) and with scenario 1) preceding. Here is given a deterministic scenario for reproduction: >From node A establish two associations on the same socket, with rcvbuf_policy being set to share one common buffer (sctp.rcvbuf_policy == 0). On association 1 repeat scenario from 1), that is, bring it down to 0 and restore up. Observe scenario 1). Use small payload size (here we use 43). Once rwnd is 'recovered', bring it down close to 0, as in just one more packet would close it. This has as a consequence that association number 2 is able to receive (at least) one more packet which will bring it in pressure state. E.g. if association 2 had rwnd of 10000, packet received was 43, and we enter at this point into pressure, rwnd_press will have 9957. Once payload is delivered to userspace, rwnd will increase for 43, but conditions to restore rwnd to original state, just as in 1), will never be satisfied. --> Association 1, between A.y and B.12345 IP A.55915 > B.12345: sctp (1) [INIT] [init tag: 836880897] [rwnd: 10000] [OS: 10] [MIS: 65535] [init TSN: 4032536569] IP B.12345 > A.55915: sctp (1) [INIT ACK] [init tag: 2873310749] [rwnd: 81920] [OS: 10] [MIS: 10] [init TSN: 3799315613] IP A.55915 > B.12345: sctp (1) [COOKIE ECHO] IP B.12345 > A.55915: sctp (1) [COOKIE ACK] --> Association 2, between A.z and B.12346 IP A.55915 > B.12346: sctp (1) [INIT] [init tag: 534798321] [rwnd: 10000] [OS: 10] [MIS: 65535] [init TSN: 2099285173] IP B.12346 > A.55915: sctp (1) [INIT ACK] [init tag: 516668823] [rwnd: 81920] [OS: 10] [MIS: 10] [init TSN: 3676403240] IP A.55915 > B.12346: sctp (1) [COOKIE ECHO] IP B.12346 > A.55915: sctp (1) [COOKIE ACK] --> Deplete socket buffer by sending messages of size 43B over association 1 IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315613] [SID: 0] [SSEQ 0] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315613] [a_rwnd 9957] [#gap acks 0] [#dup tsns 0] <...> IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315696] [a_rwnd 6388] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315697] [SID: 0] [SSEQ 84] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315697] [a_rwnd 6345] [#gap acks 0] [#dup tsns 0] --> Sudden drop on 1 IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315698] [SID: 0] [SSEQ 85] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315698] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] --> Here userspace read, rwnd 'recovered' to 3698, now deplete again using association 1 so there is place in buffer for only one more packet IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315799] [SID: 0] [SSEQ 186] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315799] [a_rwnd 86] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315800] [SID: 0] [SSEQ 187] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315800] [a_rwnd 43] [#gap acks 0] [#dup tsns 0] --> Socket buffer is almost depleted, but there is space for one more packet, send them over association 2, size 43B IP B.12346 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3676403240] [SID: 0] [SSEQ 0] [PPID 0x18] IP A.55915 > B.12346: sctp (1) [SACK] [cum ack 3676403240] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] --> Immediate drop IP A.60995 > B.12346: sctp (1) [SACK] [cum ack 387491510] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] --> Read everything from the socket, both association recover up to maximum rwnd they are capable of reaching, note that association 1 recovered up to 3698, and association 2 recovered only to 43 IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315800] [a_rwnd 1548] [#gap acks 0] [#dup tsns 0] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315800] [a_rwnd 3053] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315801] [SID: 0] [SSEQ 188] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315801] [a_rwnd 3698] [#gap acks 0] [#dup tsns 0] IP B.12346 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3676403241] [SID: 0] [SSEQ 1] [PPID 0x18] IP A.55915 > B.12346: sctp (1) [SACK] [cum ack 3676403241] [a_rwnd 43] [#gap acks 0] [#dup tsns 0] A careful reader might wonder why it is necessary to reproduce 1) prior reproduction of 2). It is simply easier to observe when to send packet over association 2 which will push association into the pressure state. Proposed solution: Both problems share the same root cause, and that is improper scaling of socket buffer with rwnd. Solution in which sizeof(sk_buff) is taken into concern while calculating rwnd is not possible due to fact that there is no linear relationship between amount of data blamed in increase/decrease with IP packet in which payload arrived. Even in case such solution would be followed, complexity of the code would increase. Due to nature of current rwnd handling, slow increase (in sctp_assoc_rwnd_increase) of rwnd after pressure state is entered is rationale, but it gives false representation to the sender of current buffer space. Furthermore, it implements additional congestion control mechanism which is defined on implementation, and not on standard basis. Proposed solution simplifies whole algorithm having on mind definition from rfc: o Receiver Window (rwnd): This gives the sender an indication of the space available in the receiver's inbound buffer. Core of the proposed solution is given with these lines: sctp_assoc_rwnd_update: if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; else asoc->rwnd = 0; We advertise to sender (half of) actual space we have. Half is in the braces depending whether you would like to observe size of socket buffer as SO_RECVBUF or twice the amount, i.e. size is the one visible from userspace, that is, from kernelspace. In this way sender is given with good approximation of our buffer space, regardless of the buffer policy - we always advertise what we have. Proposed solution fixes described problems and removes necessity for rwnd restoration algorithm. Finally, as proposed solution is simplification, some lines of code, along with some bytes in struct sctp_association are saved. Version 2 of the patch addressed comments from Vlad. Name of the function is set to be more descriptive, and two parts of code are changed, in one removing the superfluous call to sctp_assoc_rwnd_update since call would not result in update of rwnd, and the other being reordering of the code in a way that call to sctp_assoc_rwnd_update updates rwnd. Version 3 corrected change introduced in v2 in a way that existing function is not reordered/copied in line, but it is correctly called. Thanks Vlad for suggesting. Signed-off-by: Matija Glavinic Pecotic Reviewed-by: Alexander Sverdlin Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index d992ca3..6ee76c8 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1653,17 +1653,6 @@ struct sctp_association { /* This is the last advertised value of rwnd over a SACK chunk. */ __u32 a_rwnd; - /* Number of bytes by which the rwnd has slopped. The rwnd is allowed - * to slop over a maximum of the association's frag_point. - */ - __u32 rwnd_over; - - /* Keeps treack of rwnd pressure. This happens when we have - * a window, but not recevie buffer (i.e small packets). This one - * is releases slowly (1 PMTU at a time ). - */ - __u32 rwnd_press; - /* This is the sndbuf size in use for the association. * This corresponds to the sndbuf size for the association, * as specified in the sk->sndbuf. @@ -1892,8 +1881,7 @@ void sctp_assoc_update(struct sctp_association *old, __u32 sctp_association_get_next_tsn(struct sctp_association *); void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *); -void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int); -void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int); +void sctp_assoc_rwnd_update(struct sctp_association *, bool); void sctp_assoc_set_primary(struct sctp_association *, struct sctp_transport *); void sctp_assoc_del_nonprimary_peers(struct sctp_association *, diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5ae6092..f558433 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1367,44 +1367,35 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc) return false; } -/* Increase asoc's rwnd by len and send any window update SACK if needed. */ -void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) +/* Update asoc's rwnd for the approximated state in the buffer, + * and check whether SACK needs to be sent. + */ +void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) { + int rx_count; struct sctp_chunk *sack; struct timer_list *timer; - if (asoc->rwnd_over) { - if (asoc->rwnd_over >= len) { - asoc->rwnd_over -= len; - } else { - asoc->rwnd += (len - asoc->rwnd_over); - asoc->rwnd_over = 0; - } - } else { - asoc->rwnd += len; - } + if (asoc->ep->rcvbuf_policy) + rx_count = atomic_read(&asoc->rmem_alloc); + else + rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); - /* If we had window pressure, start recovering it - * once our rwnd had reached the accumulated pressure - * threshold. The idea is to recover slowly, but up - * to the initial advertised window. - */ - if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) { - int change = min(asoc->pathmtu, asoc->rwnd_press); - asoc->rwnd += change; - asoc->rwnd_press -= change; - } + if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) + asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; + else + asoc->rwnd = 0; - pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n", - __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, - asoc->a_rwnd); + pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n", + __func__, asoc, asoc->rwnd, rx_count, + asoc->base.sk->sk_rcvbuf); /* Send a window update SACK if the rwnd has increased by at least the * minimum of the association's PMTU and half of the receive buffer. * The algorithm used is similar to the one described in * Section 4.2.3.3 of RFC 1122. */ - if (sctp_peer_needs_update(asoc)) { + if (update_peer && sctp_peer_needs_update(asoc)) { asoc->a_rwnd = asoc->rwnd; pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " @@ -1426,45 +1417,6 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) } } -/* Decrease asoc's rwnd by len. */ -void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) -{ - int rx_count; - int over = 0; - - if (unlikely(!asoc->rwnd || asoc->rwnd_over)) - pr_debug("%s: association:%p has asoc->rwnd:%u, " - "asoc->rwnd_over:%u!\n", __func__, asoc, - asoc->rwnd, asoc->rwnd_over); - - if (asoc->ep->rcvbuf_policy) - rx_count = atomic_read(&asoc->rmem_alloc); - else - rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); - - /* If we've reached or overflowed our receive buffer, announce - * a 0 rwnd if rwnd would still be positive. Store the - * the potential pressure overflow so that the window can be restored - * back to original value. - */ - if (rx_count >= asoc->base.sk->sk_rcvbuf) - over = 1; - - if (asoc->rwnd >= len) { - asoc->rwnd -= len; - if (over) { - asoc->rwnd_press += asoc->rwnd; - asoc->rwnd = 0; - } - } else { - asoc->rwnd_over = len - asoc->rwnd; - asoc->rwnd = 0; - } - - pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n", - __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, - asoc->rwnd_press); -} /* Build the bind address list for the association based on info from the * local endpoint and the remote peer. diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 483dcd7..591b44d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -6176,7 +6176,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, * PMTU. In cases, such as loopback, this might be a rather * large spill over. */ - if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over || + if ((!chunk->data_accepted) && (!asoc->rwnd || (datalen > asoc->rwnd + asoc->frag_point))) { /* If this is the next TSN, consider reneging to make diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9e91d6e..7075ac8 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2092,12 +2092,6 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, sctp_skb_pull(skb, copied); skb_queue_head(&sk->sk_receive_queue, skb); - /* When only partial message is copied to the user, increase - * rwnd by that amount. If all the data in the skb is read, - * rwnd is updated when the event is freed. - */ - if (!sctp_ulpevent_is_notification(event)) - sctp_assoc_rwnd_increase(event->asoc, copied); goto out; } else if ((event->msg_flags & MSG_NOTIFICATION) || (event->msg_flags & MSG_EOR)) diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 85c6465..8d198ae 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, skb = sctp_event2skb(event); /* Set the owner and charge rwnd for bytes received. */ sctp_ulpevent_set_owner(event, asoc); - sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); + sctp_assoc_rwnd_update(asoc, false); if (!skb->data_len) return; @@ -1011,6 +1011,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) { struct sk_buff *skb, *frag; unsigned int len; + struct sctp_association *asoc; /* Current stack structures assume that the rcv buffer is * per socket. For UDP style sockets this is not true as @@ -1035,8 +1036,11 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) } done: - sctp_assoc_rwnd_increase(event->asoc, len); + asoc = event->asoc; + sctp_association_hold(asoc); sctp_ulpevent_release_owner(event); + sctp_assoc_rwnd_update(asoc, true); + sctp_association_put(asoc); } static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) -- cgit v0.10.2 From c321f7d7c87cdc623c87845f6378620573e57512 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 14 Feb 2014 15:32:20 +0100 Subject: drivers/net: tulip_remove_one needs to call pci_disable_device() Otherwise the device is not completely shut down. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index add05f1..1642de7 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -1939,6 +1939,7 @@ static void tulip_remove_one(struct pci_dev *pdev) pci_iounmap(pdev, tp->base_addr); free_netdev (dev); pci_release_regions (pdev); + pci_disable_device(pdev); /* pci_power_off (pdev, -1); */ } -- cgit v0.10.2 From 99932d4fc03a13bb3e94938fe25458fabc8f2fc3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 16 Feb 2014 15:55:20 +0100 Subject: netdevice: add queue selection fallback handler for ndo_select_queue Add a new argument for ndo_select_queue() callback that passes a fallback handler. This gets invoked through netdev_pick_tx(); fallback handler is currently __netdev_pick_tx() as most drivers invoke this function within their customized implementation in case for skbs that don't need any special handling. This fallback handler can then be replaced on other call-sites with different queue selection methods (e.g. in packet sockets, pktgen etc). This also has the nice side-effect that __netdev_pick_tx() is then only invoked from netdev_pick_tx() and export of that function to modules can be undone. Suggested-by: David S. Miller Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 8676649..1c6104d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3707,7 +3707,7 @@ static inline int bond_slave_override(struct bonding *bond, static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* * This helper function exists to help dev_pick_tx get the correct diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 9d7419e..66c0df7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1873,7 +1873,7 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) } u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct bnx2x *bp = netdev_priv(dev); @@ -1895,7 +1895,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, } /* select a non-FCoE queue */ - return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); + return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); } void bnx2x_set_num_queues(struct bnx2x *bp) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index bfc58d4..a89a40f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -496,7 +496,7 @@ int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos); /* select_queue callback */ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, select_queue_fallback_t fallback); static inline void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 6d4ada7..18076c4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6881,7 +6881,7 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size) } static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct ixgbe_fwd_adapter *fwd_adapter = accel_priv; #ifdef IXGBE_FCOE @@ -6907,7 +6907,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb, if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) break; default: - return __netdev_pick_tx(dev, skb); + return fallback(dev, skb); } f = &adapter->ring_feature[RING_F_FCOE]; @@ -6920,7 +6920,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb, return txq + f->offset; #else - return __netdev_pick_tx(dev, skb); + return fallback(dev, skb); #endif } diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 8f9266c..fd4b6ae 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -619,7 +619,7 @@ ltq_etop_set_multicast_list(struct net_device *dev) static u16 ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* we are currently only using the first queue */ return 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 8e8a7eb..1345703 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -629,7 +629,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk } u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct mlx4_en_priv *priv = netdev_priv(dev); u16 rings_p_up = priv->num_tx_rings_p_up; @@ -641,7 +641,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb, if (vlan_tx_tag_present(skb)) up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT; - return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up; + return fallback(dev, skb) % rings_p_up + up * rings_p_up; } static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt) diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 3af04c3..9ca223b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -723,7 +723,7 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); void mlx4_en_tx_irq(struct mlx4_cq *mcq); u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, select_queue_fallback_t fallback); netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 023237a..17503da 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -2071,7 +2071,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) /* Return subqueue id on this core (one per core). */ static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { return smp_processor_id(); } diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 2840742..c8624a8 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1648,7 +1648,7 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev) } static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* * This helper function exists to help dev_pick_tx get the correct diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 44c4db8..8fe9cb7 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -366,7 +366,7 @@ static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash) * hope the rxq no. may help here. */ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct tun_struct *tun = netdev_priv(dev); struct tun_flow_entry *e; diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 4d79761..9d3d275 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -748,7 +748,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) static u16 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { skb->priority = cfg80211_classify8021d(skb, NULL); return mwifiex_1d_to_wmm_queue[skb->priority]; diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c index 8dfdd27..95a2358 100644 --- a/drivers/staging/bcm/Bcmnet.c +++ b/drivers/staging/bcm/Bcmnet.c @@ -40,7 +40,7 @@ static INT bcm_close(struct net_device *dev) } static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { return ClassifyPacket(netdev_priv(dev), skb); } diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index eedffed..6f9ac27 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -307,7 +307,7 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb, } static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { return (u16)smp_processor_id(); } diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 68f98fa..7c9ee58 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -653,7 +653,7 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb) } static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct adapter *padapter = rtw_netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 21d4e6b..1de9c13 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -752,6 +752,9 @@ struct netdev_phys_port_id { unsigned char id_len; }; +typedef u16 (*select_queue_fallback_t)(struct net_device *dev, + struct sk_buff *skb); + /* * This structure defines the management hooks for network devices. * The following hooks can be defined; unless noted otherwise, they are @@ -783,7 +786,7 @@ struct netdev_phys_port_id { * Required can not be NULL. * * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, - * void *accel_priv); + * void *accel_priv, select_queue_fallback_t fallback); * Called to decide which queue to when device supports multiple * transmit queues. * @@ -1005,7 +1008,8 @@ struct net_device_ops { struct net_device *dev); u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, + select_queue_fallback_t fallback); void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); @@ -1551,7 +1555,6 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev, struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, void *accel_priv); -u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb); /* * Net namespace inlines diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 87577d4..75fe83f 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -372,7 +372,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) #endif } -u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) +static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) { struct sock *sk = skb->sk; int queue_index = sk_tx_queue_get(sk); @@ -392,7 +392,6 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) return queue_index; } -EXPORT_SYMBOL(__netdev_pick_tx); struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, @@ -403,8 +402,8 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, if (dev->real_num_tx_queues != 1) { const struct net_device_ops *ops = dev->netdev_ops; if (ops->ndo_select_queue) - queue_index = ops->ndo_select_queue(dev, skb, - accel_priv); + queue_index = ops->ndo_select_queue(dev, skb, accel_priv, + __netdev_pick_tx); else queue_index = __netdev_pick_tx(dev, skb); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d6d1f1d..ce1c443 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1057,7 +1057,8 @@ static void ieee80211_uninit(struct net_device *dev) static u16 ieee80211_netdev_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, + select_queue_fallback_t fallback) { return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); } @@ -1075,7 +1076,8 @@ static const struct net_device_ops ieee80211_dataif_ops = { static u16 ieee80211_monitor_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, + select_queue_fallback_t fallback) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; -- cgit v0.10.2 From b9507bdaf40e91fea2b1c0c1ee7dc627c8ee6fd6 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 16 Feb 2014 15:55:21 +0100 Subject: netdevice: move netdev_cap_txqueue for shared usage to header In order to allow users to invoke netdev_cap_txqueue, it needs to be moved into netdevice.h header file. While at it, also add kernel doc header to document the API. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1de9c13..e8eeebd 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2279,6 +2279,26 @@ static inline void netdev_reset_queue(struct net_device *dev_queue) } /** + * netdev_cap_txqueue - check if selected tx queue exceeds device queues + * @dev: network device + * @queue_index: given tx queue index + * + * Returns 0 if given tx queue index >= number of device tx queues, + * otherwise returns the originally passed tx queue index. + */ +static inline u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index) +{ + if (unlikely(queue_index >= dev->real_num_tx_queues)) { + net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n", + dev->name, queue_index, + dev->real_num_tx_queues); + return 0; + } + + return queue_index; +} + +/** * netif_running - test if up * @dev: network device * diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 75fe83f..e29e810 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -323,17 +323,6 @@ u32 __skb_get_poff(const struct sk_buff *skb) return poff; } -static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) -{ - if (unlikely(queue_index >= dev->real_num_tx_queues)) { - net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n", - dev->name, queue_index, - dev->real_num_tx_queues); - return 0; - } - return queue_index; -} - static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) { #ifdef CONFIG_XPS @@ -408,7 +397,7 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, queue_index = __netdev_pick_tx(dev, skb); if (!accel_priv) - queue_index = dev_cap_txqueue(dev, queue_index); + queue_index = netdev_cap_txqueue(dev, queue_index); } skb_set_queue_mapping(skb, queue_index); -- cgit v0.10.2 From 0fd5d57ba3456c4d0b77d1ae64be4818b47d7545 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 16 Feb 2014 15:55:22 +0100 Subject: packet: check for ndo_select_queue during queue selection Mathias reported that on an AMD Geode LX embedded board (ALiX) with ath9k driver PACKET_QDISC_BYPASS, introduced in commit d346a3fae3ff ("packet: introduce PACKET_QDISC_BYPASS socket option"), triggers a WARN_ON() coming from the driver itself via 066dae93bdf ("ath9k: rework tx queue selection and fix queue stopping/waking"). The reason why this happened is that ndo_select_queue() call is not invoked from direct xmit path i.e. for ieee80211 subsystem that sets queue and TID (similar to 802.1d tag) which is being put into the frame through 802.11e (WMM, QoS). If that is not set, pending frame counter for e.g. ath9k can get messed up. So the WARN_ON() in ath9k is absolutely legitimate. Generally, the hw queue selection in ieee80211 depends on the type of traffic, and priorities are set according to ieee80211_ac_numbers mapping; working in a similar way as DiffServ only on a lower layer, so that the AP can favour frames that have "real-time" requirements like voice or video data frames. Therefore, check for presence of ndo_select_queue() in netdev ops and, if available, invoke it with a fallback handler to __packet_pick_tx_queue(), so that driver such as bnx2x, ixgbe, or mlx4 can still select a hw queue for transmission in relation to the current CPU while e.g. ieee80211 subsystem can make their own choices. Reported-by: Mathias Kretschmer Signed-off-by: Daniel Borkmann Cc: Jesper Dangaard Brouer Signed-off-by: David S. Miller diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 6a2bb37..b5dc116 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -308,11 +308,27 @@ static bool packet_use_direct_xmit(const struct packet_sock *po) return po->xmit == packet_direct_xmit; } -static u16 packet_pick_tx_queue(struct net_device *dev) +static u16 __packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) { return (u16) raw_smp_processor_id() % dev->real_num_tx_queues; } +static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) +{ + const struct net_device_ops *ops = dev->netdev_ops; + u16 queue_index; + + if (ops->ndo_select_queue) { + queue_index = ops->ndo_select_queue(dev, skb, NULL, + __packet_pick_tx_queue); + queue_index = netdev_cap_txqueue(dev, queue_index); + } else { + queue_index = __packet_pick_tx_queue(dev, skb); + } + + skb_set_queue_mapping(skb, queue_index); +} + /* register_prot_hook must be invoked with the po->bind_lock held, * or from a context in which asynchronous accesses to the packet * socket is not possible (packet_create()). @@ -2285,7 +2301,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) } } - skb_set_queue_mapping(skb, packet_pick_tx_queue(dev)); + packet_pick_tx_queue(dev, skb); + skb->destructor = tpacket_destruct_skb; __packet_set_status(po, ph, TP_STATUS_SENDING); packet_inc_pending(&po->tx_ring); @@ -2499,7 +2516,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) skb->dev = dev; skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - skb_set_queue_mapping(skb, packet_pick_tx_queue(dev)); + + packet_pick_tx_queue(dev, skb); if (po->has_vnet_hdr) { if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { -- cgit v0.10.2 From e9baa9d9d520fb0e24cca671e430689de2d4a4b2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 13 Feb 2014 10:39:01 +0100 Subject: dma: ste_dma40: don't dereference free:d descriptor It appears that in the DMA40 driver the DMA tasklet will very often dereference memory for a descriptor just free:d from the DMA40 slab. Nothing happens because no other part of the driver has yet had a chance to claim this memory, but it's really nasty to dereference free:d memory, so let's check the flag before the descriptor is free and store it in a bool variable. Cc: stable@vger.kernel.org Reported-by: Dan Carpenter Signed-off-by: Linus Walleij Signed-off-by: Vinod Koul diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 00a2de9..bf18c78 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1641,6 +1641,7 @@ static void dma_tasklet(unsigned long data) struct d40_chan *d40c = (struct d40_chan *) data; struct d40_desc *d40d; unsigned long flags; + bool callback_active; dma_async_tx_callback callback; void *callback_param; @@ -1668,6 +1669,7 @@ static void dma_tasklet(unsigned long data) } /* Callback to client */ + callback_active = !!(d40d->txd.flags & DMA_PREP_INTERRUPT); callback = d40d->txd.callback; callback_param = d40d->txd.callback_param; @@ -1690,7 +1692,7 @@ static void dma_tasklet(unsigned long data) spin_unlock_irqrestore(&d40c->lock, flags); - if (callback && (d40d->txd.flags & DMA_PREP_INTERRUPT)) + if (callback_active && callback) callback(callback_param); return; -- cgit v0.10.2 From e306dfd06fcb44d21c80acb8e5a88d55f3d1cf63 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 14 Feb 2014 19:35:15 +0000 Subject: ARM64: unwind: Fix PC calculation The frame PC value in the unwind code used to just take the saved LR value and use that. That's incorrect as a stack trace, since it shows the return path stack, not the call path stack. In particular, it shows faulty information in case the bl is done as the very last instruction of one label, since the return point will be in the next label. That can easily be seen with tail calls to panic(), which is marked __noreturn and thus doesn't have anything useful after it. Easiest here is to just correct the unwind code and do a -4, to get the actual call site for the backtrace instead of the return site. Signed-off-by: Olof Johansson Cc: stable@vger.kernel.org Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index c3b6c63..38f0558 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -48,7 +48,11 @@ int unwind_frame(struct stackframe *frame) frame->sp = fp + 0x10; frame->fp = *(unsigned long *)(fp); - frame->pc = *(unsigned long *)(fp + 8); + /* + * -4 here because we care about the PC at time of bl, + * not where the return will go. + */ + frame->pc = *(unsigned long *)(fp + 8) - 4; return 0; } -- cgit v0.10.2 From 478b360a47b71f3b5030eacd3aae6acb1a32c2b6 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 15 Feb 2014 23:48:45 +0100 Subject: netfilter: nf_tables: fix nf_trace always-on with XT_TRACE=n When using nftables with CONFIG_NETFILTER_XT_TARGET_TRACE=n, we get lots of "TRACE: filter:output:policy:1 IN=..." warnings as several places will leave skb->nf_trace uninitialised. Unlike iptables tracing functionality is not conditional in nftables, so always copy/zero nf_trace setting when nftables is enabled. Move this into __nf_copy() helper. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f589c9af..d40d40b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2725,7 +2725,7 @@ static inline void nf_reset(struct sk_buff *skb) static inline void nf_reset_trace(struct sk_buff *skb) { -#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) +#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES) skb->nf_trace = 0; #endif } @@ -2742,6 +2742,9 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src) dst->nf_bridge = src->nf_bridge; nf_bridge_get(src->nf_bridge); #endif +#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES) + dst->nf_trace = src->nf_trace; +#endif } static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5976ef0..5d6236d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -707,9 +707,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->mark = old->mark; new->skb_iif = old->skb_iif; __nf_copy(new, old); -#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) - new->nf_trace = old->nf_trace; -#endif #ifdef CONFIG_NET_SCHED new->tc_index = old->tc_index; #ifdef CONFIG_NET_CLS_ACT diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8971780..73c6b63 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -422,9 +422,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->tc_index = from->tc_index; #endif nf_copy(to, from); -#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) - to->nf_trace = from->nf_trace; -#endif #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) to->ipvs_property = from->ipvs_property; #endif diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ef02b26..4cfbe0f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -517,9 +517,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->tc_index = from->tc_index; #endif nf_copy(to, from); -#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) - to->nf_trace = from->nf_trace; -#endif skb_copy_secmark(to, from); } -- cgit v0.10.2 From f627ed91d85ed7a189ec8b3b045a0d831e1655e2 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Sun, 16 Feb 2014 14:01:58 +0100 Subject: netfilter: nf_tables: check if payload length is a power of 2 Add a check if payload's length is a power of 2 when selecting ops. The fast ops were meant for well aligned loads, also this fixes a small bug when using a length of 3 with some offsets which causes only 1 byte to be loaded because the fast ops are chosen. Signed-off-by: Nikolay Aleksandrov Acked-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index a2aeb31..85daa84 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -135,7 +135,8 @@ nft_payload_select_ops(const struct nft_ctx *ctx, if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data)) return ERR_PTR(-EINVAL); - if (len <= 4 && IS_ALIGNED(offset, len) && base != NFT_PAYLOAD_LL_HEADER) + if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && + base != NFT_PAYLOAD_LL_HEADER) return &nft_payload_fast_ops; else return &nft_payload_ops; -- cgit v0.10.2 From 5745d6a41a4f4aec29e2ccd591c6fb09ed73a955 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 10 Jan 2014 09:29:39 -0500 Subject: avr32: fix missing module.h causing build failure in mimc200/fram.c Causing this: In file included from arch/avr32/boards/mimc200/fram.c:13: include/linux/miscdevice.h:51: error: field 'list' has incomplete type include/linux/miscdevice.h:55: error: expected specifier-qualifier-list before 'mode_t' arch/avr32/boards/mimc200/fram.c:42: error: 'THIS_MODULE' undeclared here (not in a function) Reported-by: Fengguang Wu Cc: Haavard Skinnemoen Cc: Hans-Christian Egtvedt Signed-off-by: Paul Gortmaker Signed-off-by: Sergei Trofimovich Acked-by: Hans-Christian Egtvedt Cc: stable@vger.kernel.org diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c index 9764a1a..c1466a8 100644 --- a/arch/avr32/boards/mimc200/fram.c +++ b/arch/avr32/boards/mimc200/fram.c @@ -11,6 +11,7 @@ #define FRAM_VERSION "1.0" #include +#include #include #include #include -- cgit v0.10.2 From 8d80390cfc9434d5aa4fb9e5f9768a66b30cb8a6 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sat, 1 Feb 2014 20:35:54 +0800 Subject: avr32: Makefile: add '-D__linux__' flag for gcc-4.4.7 use For avr32 cross compiler, do not define '__linux__' internally, so it will cause issue with allmodconfig. The related error: CC [M] fs/coda/psdev.o In file included from include/linux/coda.h:64, from fs/coda/psdev.c:45: include/uapi/linux/coda.h:221: error: expected specifier-qualifier-list before 'u_quad_t' The related toolchain version (which only download, not re-compile): [root@gchen linux-next]# /upstream/toolchain/download/avr32-gnu-toolchain-linux_x86/bin/avr32-gcc -v Using built-in specs. Target: avr32 Configured with: /data2/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/src/gcc/configure --target=avr32 --host=i686-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86 --enable-languages=c,c++ --disable-nls --disable-libssp --disable-libstdcxx-pch --with-dwarf2 --enable-version-specific-runtime-libs --disable-shared --enable-doc --with-mpfr-lib=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86/lib --with-mpfr-include=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86/include --with-gmp=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86 --with-mpc=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86 --enable-__cxa_atexit --disable-shared --with-newlib --with-pkgversion=AVR_32_bit_GNU_Toolchain_3.4.2_435 --with-bugurl=http://www .atmel.com/avr Thread model: single gcc version 4.4.7 (AVR_32_bit_GNU_Toolchain_3.4.2_435) Signed-off-by: Chen Gang Acked-by: Hans-Christian Egtvedt Cc: stable@vger.kernel.org diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile index 22fb665..dba48a5d 100644 --- a/arch/avr32/Makefile +++ b/arch/avr32/Makefile @@ -11,7 +11,7 @@ all: uImage vmlinux.elf KBUILD_DEFCONFIG := atstk1002_defconfig -KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic +KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic -D__linux__ KBUILD_AFLAGS += -mrelax -mno-pic KBUILD_CFLAGS_MODULE += -mno-relax LDFLAGS_vmlinux += --relax -- cgit v0.10.2 From 1bbce4f3d11a6bfac0c51800f6337766f82b42da Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 16 Feb 2014 19:39:30 +0800 Subject: avr32: add generic ioremap_wc() definition in io.h Need generic ioremap_wc(), or can not pass compiling with allmodconfig, the related error: CC [M] drivers/gpu/drm/drm_bufs.o drivers/gpu/drm/drm_bufs.c: In function 'drm_addmap_core': drivers/gpu/drm/drm_bufs.c:217: error: implicit declaration of function 'ioremap_wc' drivers/gpu/drm/drm_bufs.c:218: warning: assignment makes pointer from integer without a cast Signed-off-by: Chen Gang Acked-by: Hans-Christian Egtvedt diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h index fc6483f..4f5ec2b 100644 --- a/arch/avr32/include/asm/io.h +++ b/arch/avr32/include/asm/io.h @@ -295,6 +295,8 @@ extern void __iounmap(void __iomem *addr); #define iounmap(addr) \ __iounmap(addr) +#define ioremap_wc ioremap_nocache + #define cached(addr) P1SEGADDR(addr) #define uncached(addr) P2SEGADDR(addr) -- cgit v0.10.2 From d7668f9d448aa757971ec3e68ecedb5ebecbddcc Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 16 Feb 2014 19:36:06 +0800 Subject: avr32: add generic vga.h to Kbuild Need add generic "vga.h", or can not pass building for allmodconfig, the related error: CC [M] drivers/gpu/drm/drm_irq.o In file included from include/linux/vgaarb.h:34, from drivers/gpu/drm/drm_irq.c:42: include/video/vga.h:22:21: error: asm/vga.h: No such file or directory Signed-off-by: Chen Gang Acked-by: Hans-Christian Egtvedt diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index cfb9fe1..c7c64a6 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@ -17,5 +17,6 @@ generic-y += scatterlist.h generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h +generic-y += vga.h generic-y += xor.h generic-y += hash.h -- cgit v0.10.2 From 218eb9ed840c6279686ed6b0c3e31a083e241ff9 Mon Sep 17 00:00:00 2001 From: Archana Patni Date: Mon, 3 Feb 2014 12:44:16 +0530 Subject: HID: hid-sensor-hub: quirk for STM Sensor hub Added STM sensor hub vendor id in HID_SENSOR_HUB_ENUM_QUIRK to fix report descriptors. These devices uses old FW which uses logical 0 as minimum. In these, HID reports are not using proper collection classes. So we need to fix report descriptors,for such devices. This will not have any impact, if the FW uses logical 1 as minimum. We look for usage id for "power and report state", and modify logical minimum value to 1. This is a follow-up patch to commit id 875e36f8. Signed-off-by: Archana Patni Reviewed-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 3628168..00fd745 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -451,6 +451,9 @@ #define USB_VENDOR_ID_INTEL_1 0x8087 #define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa +#define USB_VENDOR_ID_STM_0 0x0483 +#define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1 + #define USB_VENDOR_ID_ION 0x15e4 #define USB_DEVICE_ID_ICADE 0x0132 diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 46f4480..9c22e14 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -665,6 +665,9 @@ static const struct hid_device_id sensor_hub_devices[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, USB_DEVICE_ID_INTEL_HID_SENSOR), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, + USB_DEVICE_ID_STM_HID_SENSOR), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) }, { } -- cgit v0.10.2 From cb6448ab0a9ac5f1d1c72a0f573dd9677d8e5418 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 19 Dec 2013 16:18:20 +0200 Subject: clk: tegra: Add missing Tegra20 fuse clks Add clocks required for accessing fuses on Tegra20. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index dbace15..dace2b1 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -574,6 +574,8 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { [tegra_clk_tvdac] = { .dt_id = TEGRA20_CLK_TVDAC, .present = true }, [tegra_clk_vi_sensor] = { .dt_id = TEGRA20_CLK_VI_SENSOR, .present = true }, [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true }, + [tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true }, + [tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true }, }; static unsigned long tegra20_clk_measure_input_freq(void) -- cgit v0.10.2 From 2edf3e035302776e4756e446baf3b6c7b94c3698 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 2 Dec 2013 12:30:25 +0100 Subject: clk: tegra: Correct clock number for UARTE UARTE has clock number 66. Number 65 is the right one for UARTD. Signed-off-by: Thierry Reding diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 5c35885..3744a6f 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -492,7 +492,7 @@ static struct tegra_periph_init_data periph_clks[] = { UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd), - UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte), + UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte), XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src), XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src), XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src), -- cgit v0.10.2 From 2ec35fd503bf6367ba55ed94dcb68edfe0d26e6a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 26 Dec 2013 16:44:21 -0800 Subject: clk: tegra: Fix PLLP rate table This table had settings for 216MHz, but PLLP is (and is supposed to be) configured at 408MHz. If that table is used and PLLP_BASE_OVRRIDE is not set, the kernel will panic in clk_pll_recalc_rate(). Signed-off-by: Gabe Black Signed-off-by: Andrew Bresticker diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index aff86b5..28bb238 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -516,11 +516,11 @@ static struct div_nmp pllp_nmp = { }; static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { - {12000000, 216000000, 432, 12, 1, 8}, - {13000000, 216000000, 432, 13, 1, 8}, - {16800000, 216000000, 360, 14, 1, 8}, - {19200000, 216000000, 360, 16, 1, 8}, - {26000000, 216000000, 432, 26, 1, 8}, + {12000000, 408000000, 408, 12, 0, 8}, + {13000000, 408000000, 408, 13, 0, 8}, + {16800000, 408000000, 340, 14, 0, 8}, + {19200000, 408000000, 340, 16, 0, 8}, + {26000000, 408000000, 408, 26, 0, 8}, {0, 0, 0, 0, 0, 0}, }; -- cgit v0.10.2 From 67fc26bfd7a265883fd0804f24f6287d16769e3d Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 26 Dec 2013 16:44:22 -0800 Subject: clk: tegra: Fix PLLD mnp table PLLD was using the same mnp table as PLLP. Fix it to use its own table which is different from PLLP's. Signed-off-by: Rhyland Klein Signed-off-by: Andrew Bresticker diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 28bb238..14c3f2f 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -570,6 +570,15 @@ static struct tegra_clk_pll_params pll_a_params = { .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, }; +static struct div_nmp plld_nmp = { + .divm_shift = 0, + .divm_width = 5, + .divn_shift = 8, + .divn_width = 11, + .divp_shift = 20, + .divp_width = 3, +}; + static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { {12000000, 216000000, 864, 12, 4, 12}, {13000000, 216000000, 864, 13, 4, 12}, @@ -603,7 +612,7 @@ static struct tegra_clk_pll_params pll_d_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, - .div_nmp = &pllp_nmp, + .div_nmp = &plld_nmp, .freq_table = pll_d_freq_table, .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, -- cgit v0.10.2 From 0e766c2d9fc8cd2ad0e0fe97ff4e264cb686fc32 Mon Sep 17 00:00:00 2001 From: David Ung Date: Thu, 26 Dec 2013 16:44:23 -0800 Subject: clk: tegra: PLLD2 fixes for hdmi Set correct pll_d2_out0 divider and correct the p div values for pll_d2. Signed-off-by: David Ung Signed-off-by: Andrew Bresticker diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 14c3f2f..0fc9126 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -619,12 +619,11 @@ static struct tegra_clk_pll_params pll_d_params = { }; static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = { - { 12000000, 148500000, 99, 1, 8}, - { 12000000, 594000000, 99, 1, 1}, - { 13000000, 594000000, 91, 1, 1}, /* actual: 591.5 MHz */ - { 16800000, 594000000, 71, 1, 1}, /* actual: 596.4 MHz */ - { 19200000, 594000000, 62, 1, 1}, /* actual: 595.2 MHz */ - { 26000000, 594000000, 91, 2, 1}, /* actual: 591.5 MHz */ + { 12000000, 594000000, 99, 1, 2}, + { 13000000, 594000000, 91, 1, 2}, /* actual: 591.5 MHz */ + { 16800000, 594000000, 71, 1, 2}, /* actual: 596.4 MHz */ + { 19200000, 594000000, 62, 1, 2}, /* actual: 595.2 MHz */ + { 26000000, 594000000, 91, 2, 2}, /* actual: 591.5 MHz */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1295,9 +1294,9 @@ static void __init tegra124_pll_init(void __iomem *clk_base, clk_register_clkdev(clk, "pll_d2", NULL); clks[TEGRA124_CLK_PLL_D2] = clk; - /* PLLD2_OUT0 ?? */ + /* PLLD2_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", - CLK_SET_RATE_PARENT, 1, 2); + CLK_SET_RATE_PARENT, 1, 1); clk_register_clkdev(clk, "pll_d2_out0", NULL); clks[TEGRA124_CLK_PLL_D2_OUT0] = clk; -- cgit v0.10.2 From 82ba1c3c9988a8055f4a4d7ca2168e9efe7e7874 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Thu, 26 Dec 2013 16:44:24 -0800 Subject: clk: tegra: fix host1x clock on Tegra124 The host1x clock on Tegra124 is a 3-bit wide mux with 6 parents. Change thte id to tegra_clk_host1x_8 so that the correct clock gets registered. Signed-off-by: Mark Zhang Signed-off-by: Andrew Bresticker diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 0fc9126..743ccb4 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -775,7 +775,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_gr3d] = { .dt_id = TEGRA124_CLK_GR_3D, .present = true }, [tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true }, [tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true }, - [tegra_clk_host1x] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true }, + [tegra_clk_host1x_8] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true }, [tegra_clk_vcp] = { .dt_id = TEGRA124_CLK_VCP, .present = true }, [tegra_clk_i2s0] = { .dt_id = TEGRA124_CLK_I2S0, .present = true }, [tegra_clk_apbdma] = { .dt_id = TEGRA124_CLK_APBDMA, .present = true }, -- cgit v0.10.2 From 20e7c323abac390deb35248705807bd844590048 Mon Sep 17 00:00:00 2001 From: Andrew Bresticker Date: Thu, 26 Dec 2013 16:44:25 -0800 Subject: clk: tegra: fix sdmmc clks on Tegra1x4 The sdmmc clocks on Tegra114 and Tegra124 are 3-bit wide muxes with 6 parents. Add support for tegra_clk_sdmmc*_8 and switch Tegra114 and Tegra124 to use these clocks instead. Signed-off-by: Andrew Bresticker diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index cf0c323..c39613c 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -180,9 +180,13 @@ enum clk_id { tegra_clk_sbc6_8, tegra_clk_sclk, tegra_clk_sdmmc1, + tegra_clk_sdmmc1_8, tegra_clk_sdmmc2, + tegra_clk_sdmmc2_8, tegra_clk_sdmmc3, + tegra_clk_sdmmc3_8, tegra_clk_sdmmc4, + tegra_clk_sdmmc4_8, tegra_clk_se, tegra_clk_soc_therm, tegra_clk_sor0, diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 3744a6f..f5376a3 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -465,6 +465,10 @@ static struct tegra_periph_init_data periph_clks[] = { MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1), MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1), MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2), + MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1_8), + MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2_8), + MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3_8), + MUX8("sdmmc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4_8), MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8), MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8), MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8), diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 90d9d25..80431f0 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -682,12 +682,12 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { [tegra_clk_timer] = { .dt_id = TEGRA114_CLK_TIMER, .present = true }, [tegra_clk_uarta] = { .dt_id = TEGRA114_CLK_UARTA, .present = true }, [tegra_clk_uartd] = { .dt_id = TEGRA114_CLK_UARTD, .present = true }, - [tegra_clk_sdmmc2] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true }, + [tegra_clk_sdmmc2_8] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true }, [tegra_clk_i2s1] = { .dt_id = TEGRA114_CLK_I2S1, .present = true }, [tegra_clk_i2c1] = { .dt_id = TEGRA114_CLK_I2C1, .present = true }, [tegra_clk_ndflash] = { .dt_id = TEGRA114_CLK_NDFLASH, .present = true }, - [tegra_clk_sdmmc1] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true }, - [tegra_clk_sdmmc4] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true }, + [tegra_clk_sdmmc1_8] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true }, + [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true }, [tegra_clk_pwm] = { .dt_id = TEGRA114_CLK_PWM, .present = true }, [tegra_clk_i2s0] = { .dt_id = TEGRA114_CLK_I2S0, .present = true }, [tegra_clk_i2s2] = { .dt_id = TEGRA114_CLK_I2S2, .present = true }, @@ -723,7 +723,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { [tegra_clk_bsev] = { .dt_id = TEGRA114_CLK_BSEV, .present = true }, [tegra_clk_i2c3] = { .dt_id = TEGRA114_CLK_I2C3, .present = true }, [tegra_clk_sbc4_8] = { .dt_id = TEGRA114_CLK_SBC4, .present = true }, - [tegra_clk_sdmmc3] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true }, + [tegra_clk_sdmmc3_8] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true }, [tegra_clk_owr] = { .dt_id = TEGRA114_CLK_OWR, .present = true }, [tegra_clk_csite] = { .dt_id = TEGRA114_CLK_CSITE, .present = true }, [tegra_clk_la] = { .dt_id = TEGRA114_CLK_LA, .present = true }, diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 743ccb4..b4cf650 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -761,12 +761,12 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true }, [tegra_clk_timer] = { .dt_id = TEGRA124_CLK_TIMER, .present = true }, [tegra_clk_uarta] = { .dt_id = TEGRA124_CLK_UARTA, .present = true }, - [tegra_clk_sdmmc2] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true }, + [tegra_clk_sdmmc2_8] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true }, [tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true }, [tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true }, [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true }, - [tegra_clk_sdmmc1] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true }, - [tegra_clk_sdmmc4] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true }, + [tegra_clk_sdmmc1_8] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true }, + [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true }, [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true }, [tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true }, [tegra_clk_gr2d] = { .dt_id = TEGRA124_CLK_GR_2D, .present = true }, @@ -802,7 +802,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_uartd] = { .dt_id = TEGRA124_CLK_UARTD, .present = true }, [tegra_clk_i2c3] = { .dt_id = TEGRA124_CLK_I2C3, .present = true }, [tegra_clk_sbc4] = { .dt_id = TEGRA124_CLK_SBC4, .present = true }, - [tegra_clk_sdmmc3] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true }, + [tegra_clk_sdmmc3_8] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true }, [tegra_clk_pcie] = { .dt_id = TEGRA124_CLK_PCIE, .present = true }, [tegra_clk_owr] = { .dt_id = TEGRA124_CLK_OWR, .present = true }, [tegra_clk_afi] = { .dt_id = TEGRA124_CLK_AFI, .present = true }, -- cgit v0.10.2 From 88b4bd7071ac06e321b4bf4bdb8c69db40182c5a Mon Sep 17 00:00:00 2001 From: Andrew Bresticker Date: Thu, 26 Dec 2013 16:44:26 -0800 Subject: clk: tegra: cclk_lp has a pllx/2 divider When pll_x is the parent of cclk_lp, PLLX_DIV2_BYPASS_LP determines whether cclk_lp output is divided by 2. Set TEGRA_DIVIDER_2 so that the clk_super driver is aware of this. Signed-off-by: Andrew Bresticker diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 05dce4a..feb3201 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -120,7 +120,7 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base, ARRAY_SIZE(cclk_lp_parents), CLK_SET_RATE_PARENT, clk_base + CCLKLP_BURST_POLICY, - 0, 4, 8, 9, NULL); + TEGRA_DIVIDER_2, 4, 8, 9, NULL); *dt_clk = clk; } -- cgit v0.10.2 From 3de5bdfb4cb3bd99052a4ffaee358189779be042 Mon Sep 17 00:00:00 2001 From: Andrew Bresticker Date: Thu, 26 Dec 2013 16:44:27 -0800 Subject: clk: tegra: use max divider if divider overflows When requesting a rate less than the minimum clock rate for a divider, use the maximum divider value instead of bailing out with an error. This matches the behavior of the generic clock divider. Signed-off-by: Andrew Bresticker diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c index 4d75b1f..290f9c1 100644 --- a/drivers/clk/tegra/clk-divider.c +++ b/drivers/clk/tegra/clk-divider.c @@ -59,7 +59,7 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, return 0; if (divider_ux1 > get_max_div(divider)) - return -EINVAL; + return get_max_div(divider); return divider_ux1; } -- cgit v0.10.2 From c6eda5e81c4fcc77185117255c7419eda771f67f Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 31 Jan 2014 14:11:54 -0500 Subject: dm cache: move hook_info into common portion of per_bio_data structure Commit c9d28d5d ("dm cache: promotion optimisation for writes") incorrectly placed the 'hook_info' member in the writethrough-only portion of the per_bio_data structure. Given that the overwrite optimization may be used for writeback the 'hook_info' member must be placed above the 'cache' member of the per_bio_data structure. Any members above 'cache' are available from both writeback and writethrough modes' per_bio_data structure. Signed-off-by: Mike Snitzer Acked-by: Joe Thornber Cc: stable@vger.kernel.org # 3.13+ diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index ffd472e..14256b7 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -289,6 +289,7 @@ struct per_bio_data { bool tick:1; unsigned req_nr:2; struct dm_deferred_entry *all_io_entry; + struct dm_hook_info hook_info; /* * writethrough fields. These MUST remain at the end of this @@ -297,7 +298,6 @@ struct per_bio_data { */ struct cache *cache; dm_cblock_t cblock; - struct dm_hook_info hook_info; struct dm_bio_details bio_details; }; -- cgit v0.10.2 From 80ae49aaed32af72630251eb06161b15cde15ac8 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 31 Jan 2014 14:30:37 -0500 Subject: dm cache: do not add migration to completed list before unhooking bio When completing an overwrite bio, in overwrite_endio(), the associated migration should not be added to the 'completed_migrations' until the bio's fields are restored with dm_unhook_bio(). Otherwise, do_worker() can race to process 'completed_migrations' before dm_unhook_bio() -- so the bio's bi_end_io is incorrect. This is unlikely to cause any problems given the current code but should be fixed on the basis of correctness. Also, the cache's spinlock only needs to be held when manipulating the 'completed_migrations' list -- other changes don't need protection. Signed-off-by: Mike Snitzer Acked-by: Joe Thornber diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 14256b7..db09444 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -1010,13 +1010,15 @@ static void overwrite_endio(struct bio *bio, int err) struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size); unsigned long flags; + dm_unhook_bio(&pb->hook_info, bio); + if (err) mg->err = true; + mg->requeue_holder = false; + spin_lock_irqsave(&cache->lock, flags); list_add_tail(&mg->list, &cache->completed_migrations); - dm_unhook_bio(&pb->hook_info, bio); - mg->requeue_holder = false; spin_unlock_irqrestore(&cache->lock, flags); wake_worker(cache); -- cgit v0.10.2 From 4d1662a30dde6e545086fe0e8fd7e474c4e0b639 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 6 Feb 2014 06:08:56 -0500 Subject: dm thin: avoid metadata commit if a pool's thin devices haven't changed Commit 905e51b ("dm thin: commit outstanding data every second") introduced a periodic commit. This commit occurs regardless of whether any thin devices have made changes. Fix the periodic commit to check if any of a pool's thin devices have changed using dm_pool_changed_this_transaction(). Reported-by: Alexander Larsson Signed-off-by: Mike Snitzer Acked-by: Joe Thornber Cc: stable@vger.kernel.org diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 7da3476..3bb4506 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -1489,6 +1489,23 @@ bool dm_thin_changed_this_transaction(struct dm_thin_device *td) return r; } +bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd) +{ + bool r = false; + struct dm_thin_device *td, *tmp; + + down_read(&pmd->root_lock); + list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) { + if (td->changed) { + r = td->changed; + break; + } + } + up_read(&pmd->root_lock); + + return r; +} + bool dm_thin_aborted_changes(struct dm_thin_device *td) { bool r; diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h index 9a36856..dd6088a 100644 --- a/drivers/md/dm-thin-metadata.h +++ b/drivers/md/dm-thin-metadata.h @@ -161,6 +161,8 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block); */ bool dm_thin_changed_this_transaction(struct dm_thin_device *td); +bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd); + bool dm_thin_aborted_changes(struct dm_thin_device *td); int dm_thin_get_highest_mapped_block(struct dm_thin_device *td, diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index faaf944..d501e43 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1357,7 +1357,8 @@ static void process_deferred_bios(struct pool *pool) bio_list_init(&pool->deferred_flush_bios); spin_unlock_irqrestore(&pool->lock, flags); - if (bio_list_empty(&bios) && !need_commit_due_to_time(pool)) + if (bio_list_empty(&bios) && + !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool))) return; if (commit(pool)) { -- cgit v0.10.2 From d73f9907294c670da14baea3fb31be27879e818e Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 12 Feb 2014 16:37:30 -0500 Subject: dm io: fix I/O to multiple destinations Commit 003b5c5719f159f4f4bf97511c4702a0638313dd ("block: Convert drivers to immutable biovecs") broke dm-mirror due to dm-io breakage. dm-io had three possible iterators (DM_IO_PAGE_LIST, DM_IO_BVEC, DM_IO_VMA) that iterate over pages where the I/O should be performed. The switch to immutable biovecs changed the DM_IO_BVEC iterator to DM_IO_BIO. Before this change the iterator stored the pointer to a bio vector in the dpages structure. The iterator incremented the pointer in the dpages structure as it advanced over the pages. After the immutable biovecs change, the DM_IO_BIO iterator stores a pointer to the bio in the dpages structure and uses bio_advance to change the bio as it advances. The problem is that the function dispatch_io stores the content of the dpages structure into the variable old_pages and restores it before issuing I/O to each of the devices. Before the change, the statement "*dp = old_pages;" restored the iterator to its starting position. After the change, struct dpages holds a pointer to the bio, thus the statement "*dp = old_pages;" doesn't restore the iterator. Consequently, in the context of dm-mirror: only the first mirror leg is written correctly, the kernel locks up when trying to write the other mirror legs because the number of sectors to write in the where->count variable doesn't match the number of sectors returned by the iterator. This patch fixes the bug by partially reverting the original patch - it changes the code so that struct dpages holds a pointer to the bio vector, so that the statement "*dp = old_pages;" restores the iterator correctly. The field "context_u" holds the offset from the beginning of the current bio vector entry, just like the "bio->bi_iter.bi_bvec_done" field. Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index b2b8a10..3842ac7 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -201,29 +201,28 @@ static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offse /* * Functions for getting the pages from a bvec. */ -static void bio_get_page(struct dpages *dp, - struct page **p, unsigned long *len, unsigned *offset) +static void bio_get_page(struct dpages *dp, struct page **p, + unsigned long *len, unsigned *offset) { - struct bio *bio = dp->context_ptr; - struct bio_vec bvec = bio_iovec(bio); - *p = bvec.bv_page; - *len = bvec.bv_len; - *offset = bvec.bv_offset; + struct bio_vec *bvec = dp->context_ptr; + *p = bvec->bv_page; + *len = bvec->bv_len - dp->context_u; + *offset = bvec->bv_offset + dp->context_u; } static void bio_next_page(struct dpages *dp) { - struct bio *bio = dp->context_ptr; - struct bio_vec bvec = bio_iovec(bio); - - bio_advance(bio, bvec.bv_len); + struct bio_vec *bvec = dp->context_ptr; + dp->context_ptr = bvec + 1; + dp->context_u = 0; } static void bio_dp_init(struct dpages *dp, struct bio *bio) { dp->get_page = bio_get_page; dp->next_page = bio_next_page; - dp->context_ptr = bio; + dp->context_ptr = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); + dp->context_u = bio->bi_iter.bi_bvec_done; } /* -- cgit v0.10.2 From 930cd6e46eadce8b8ed2a232ee536e5fd286c152 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 21 Jan 2014 11:22:05 +0100 Subject: batman-adv: fix soft-interface MTU computation The current MTU computation always returns a value smaller than 1500bytes even if the real interfaces have an MTU large enough to compensate the batman-adv overhead. Fix the computation by properly returning the highest admitted value. Introduced by a19d3d85e1b854e4a483a55d740a42458085560d ("batman-adv: limit local translation table max size") Reported-by: Russell Senior Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 3d417d3..b851cc5 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -241,7 +241,7 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) { struct batadv_priv *bat_priv = netdev_priv(soft_iface); const struct batadv_hard_iface *hard_iface; - int min_mtu = ETH_DATA_LEN; + int min_mtu = INT_MAX; rcu_read_lock(); list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { @@ -256,8 +256,6 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) } rcu_read_unlock(); - atomic_set(&bat_priv->packet_size_max, min_mtu); - if (atomic_read(&bat_priv->fragmentation) == 0) goto out; @@ -268,13 +266,21 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE); min_mtu -= sizeof(struct batadv_frag_packet); min_mtu *= BATADV_FRAG_MAX_FRAGMENTS; - atomic_set(&bat_priv->packet_size_max, min_mtu); - - /* with fragmentation enabled we can fragment external packets easily */ - min_mtu = min_t(int, min_mtu, ETH_DATA_LEN); out: - return min_mtu - batadv_max_header_len(); + /* report to the other components the maximum amount of bytes that + * batman-adv can send over the wire (without considering the payload + * overhead). For example, this value is used by TT to compute the + * maximum local table table size + */ + atomic_set(&bat_priv->packet_size_max, min_mtu); + + /* the real soft-interface MTU is computed by removing the payload + * overhead from the maximum amount of bytes that was just computed. + * + * However batman-adv does not support MTUs bigger than ETH_DATA_LEN + */ + return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN); } /* adjusts the MTU if a new interface with a smaller MTU appeared. */ -- cgit v0.10.2 From e889241f45f9cecbc84a6ffed577083ab52e62ee Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 27 Jan 2014 12:23:28 +0100 Subject: batman-adv: fix TT-TVLV parsing on OGM reception When accessing a TT-TVLV container in the OGM RX path the variable pointing to the list of changes to apply is altered by mistake. This makes the TT component read data at the wrong position in the OGM packet buffer. Fix it by removing the bogus pointer alteration. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index b6071f6..beba13f 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -3218,7 +3218,6 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv, spin_lock_bh(&orig_node->tt_lock); - tt_change = (struct batadv_tvlv_tt_change *)tt_buff; batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn, tt_change); -- cgit v0.10.2 From 91c2b1a9f680ff105369d49abc7e19ca7efb33e1 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 28 Jan 2014 02:06:47 +0100 Subject: batman-adv: release vlan object after checking the CRC There is a refcounter unbalance in the CRC checking routine invoked on OGM reception. A vlan object is retrieved (thus its refcounter is increased by one) but it is never properly released. This leads to a memleak because the vlan object will never be free'd. Fix this by releasing the vlan object after having read the CRC. Reported-by: Russell Senior Reported-by: Daniel Reported-by: cmsv Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index beba13f..c21c557 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -2262,6 +2262,7 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, { struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; struct batadv_orig_node_vlan *vlan; + uint32_t crc; int i; /* check if each received CRC matches the locally stored one */ @@ -2281,7 +2282,10 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, if (!vlan) return false; - if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc)) + crc = vlan->tt.crc; + batadv_orig_node_vlan_free_ref(vlan); + + if (crc != ntohl(tt_vlan_tmp->crc)) return false; } -- cgit v0.10.2 From f1791425cf0bcda43ab9a9a37df1ad3ccb1f6654 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 30 Jan 2014 00:12:24 +0100 Subject: batman-adv: properly check pskb_may_pull return value pskb_may_pull() returns 1 on success and 0 in case of failure, therefore checking for the return value being negative does not make sense at all. This way if the function fails we will probably read beyond the current skb data buffer. Fix this by doing the proper check. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 1ed9f7c..c26f073 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -688,7 +688,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, int is_old_ttvn; /* check if there is enough data before accessing it */ - if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0) + if (!pskb_may_pull(skb, hdr_len + ETH_HLEN)) return 0; /* create a copy of the skb (in case of for re-routing) to modify it. */ -- cgit v0.10.2 From 08bf0ed29c7ded45c477d08618220dd200c3524a Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 29 Jan 2014 11:25:12 +0100 Subject: batman-adv: avoid potential race condition when adding a new neighbour When adding a new neighbour it is important to atomically perform the following: - check if the neighbour already exists - append the neighbour to the proper list If the two operations are not performed in an atomic context it is possible that two concurrent insertions add the same neighbour twice. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 512159b..094ae7c 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -266,7 +266,7 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, struct batadv_orig_node *orig_neigh) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); - struct batadv_neigh_node *neigh_node; + struct batadv_neigh_node *neigh_node, *tmp_neigh_node; neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node); if (!neigh_node) @@ -281,14 +281,24 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, neigh_node->orig_node = orig_neigh; neigh_node->if_incoming = hard_iface; - batadv_dbg(BATADV_DBG_BATMAN, bat_priv, - "Creating new neighbor %pM for orig_node %pM on interface %s\n", - neigh_addr, orig_node->orig, hard_iface->net_dev->name); - spin_lock_bh(&orig_node->neigh_list_lock); - hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); + tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface, + neigh_addr); + if (!tmp_neigh_node) { + hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); + } else { + kfree(neigh_node); + batadv_hardif_free_ref(hard_iface); + neigh_node = tmp_neigh_node; + } spin_unlock_bh(&orig_node->neigh_list_lock); + if (!tmp_neigh_node) + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, + "Creating new neighbor %pM for orig_node %pM on interface %s\n", + neigh_addr, orig_node->orig, + hard_iface->net_dev->name); + out: return neigh_node; } diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 6df12a2..8539416 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -458,6 +458,42 @@ out: } /** + * batadv_neigh_node_get - retrieve a neighbour from the list + * @orig_node: originator which the neighbour belongs to + * @hard_iface: the interface where this neighbour is connected to + * @addr: the address of the neighbour + * + * Looks for and possibly returns a neighbour belonging to this originator list + * which is connected through the provided hard interface. + * Returns NULL if the neighbour is not found. + */ +struct batadv_neigh_node * +batadv_neigh_node_get(const struct batadv_orig_node *orig_node, + const struct batadv_hard_iface *hard_iface, + const uint8_t *addr) +{ + struct batadv_neigh_node *tmp_neigh_node, *res = NULL; + + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) { + if (!batadv_compare_eth(tmp_neigh_node->addr, addr)) + continue; + + if (tmp_neigh_node->if_incoming != hard_iface) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + res = tmp_neigh_node; + break; + } + rcu_read_unlock(); + + return res; +} + +/** * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object * @rcu: rcu pointer of the orig_ifinfo object */ diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 37be290..db3a9ed 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -29,6 +29,10 @@ void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, const uint8_t *addr); struct batadv_neigh_node * +batadv_neigh_node_get(const struct batadv_orig_node *orig_node, + const struct batadv_hard_iface *hard_iface, + const uint8_t *addr); +struct batadv_neigh_node * batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, const uint8_t *neigh_addr, struct batadv_orig_node *orig_node); -- cgit v0.10.2 From b2262df7fcf2c395eca564df83238e931d88d7bf Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sat, 8 Feb 2014 16:45:06 +0100 Subject: batman-adv: fix potential orig_node reference leak Since batadv_orig_node_new() sets the refcount to two, assuming that the calling function will use a reference for putting the orig_node into a hash or similar, both references must be freed if initialization of the orig_node fails. Otherwise that object may be leaked in that error case. Reported-by: Antonio Quartulli Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 094ae7c..42cbc0a 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -254,6 +254,8 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr) free_bcast_own: kfree(orig_node->bat_iv.bcast_own); free_orig_node: + /* free twice, as batadv_orig_node_new sets refcount to 2 */ + batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node); return NULL; -- cgit v0.10.2 From a30e22ca8464c2dc573e0144a972221c2f06c2cd Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Feb 2014 17:05:06 +0100 Subject: batman-adv: fix TT CRC computation by ensuring byte order When computing the CRC on a 2byte variable the order of the bytes obviously alters the final result. This means that computing the CRC over the same value on two archs having different endianess leads to different numbers. The global and local translation table CRC computation routine makes this mistake while processing the clients VIDs. The result is a continuous CRC mismatching between nodes having different endianess. Fix this by converting the VID to Network Order before processing it. This guarantees that every node uses the same byte order. Introduced by 7ea7b4a142758deaf46c1af0ca9ceca6dd55138b ("batman-adv: make the TT CRC logic VLAN specific") Reported-by: Russel Senior Signed-off-by: Antonio Quartulli Tested-by: Russell Senior Signed-off-by: Marek Lindner diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index c21c557..959dde7 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1975,6 +1975,7 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, struct hlist_head *head; uint32_t i, crc_tmp, crc = 0; uint8_t flags; + __be16 tmp_vid; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -2011,8 +2012,11 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, orig_node)) continue; - crc_tmp = crc32c(0, &tt_common->vid, - sizeof(tt_common->vid)); + /* use network order to read the VID: this ensures that + * every node reads the bytes in the same order. + */ + tmp_vid = htons(tt_common->vid); + crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); /* compute the CRC on flags that have to be kept in sync * among nodes @@ -2046,6 +2050,7 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv, struct hlist_head *head; uint32_t i, crc_tmp, crc = 0; uint8_t flags; + __be16 tmp_vid; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -2064,8 +2069,11 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv, if (tt_common->flags & BATADV_TT_CLIENT_NEW) continue; - crc_tmp = crc32c(0, &tt_common->vid, - sizeof(tt_common->vid)); + /* use network order to read the VID: this ensures that + * every node reads the bytes in the same order. + */ + tmp_vid = htons(tt_common->vid); + crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); /* compute the CRC on flags that have to be kept in sync * among nodes -- cgit v0.10.2 From 05c3c8a636aa9ee35ce13f65afc5b665615cc786 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Feb 2014 17:05:07 +0100 Subject: batman-adv: free skb on TVLV parsing success When the TVLV parsing routine succeed the skb is left untouched thus leading to a memory leak. Fix this by consuming the skb in case of success. Introduced by ef26157747d42254453f6b3ac2bd8bd3c53339c3 ("batman-adv: tvlv - basic infrastructure") Reported-by: Russel Senior Signed-off-by: Antonio Quartulli Tested-by: Russell Senior Signed-off-by: Marek Lindner diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c26f073..a953d5b 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -918,6 +918,8 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb, if (ret != NET_RX_SUCCESS) ret = batadv_route_unicast_packet(skb, recv_if); + else + consume_skb(skb); return ret; } -- cgit v0.10.2 From a5a5cb8cab526af2f6cbe9715f8ca843192f0d81 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 15 Feb 2014 02:17:20 +0100 Subject: batman-adv: avoid double free when orig_node initialization fails In the failure path of the orig_node initialization routine the orig_node->bat_iv.bcast_own field is free'd twice: first in batadv_iv_ogm_orig_get() and then later in batadv_orig_node_free_rcu(). Fix it by removing the kfree in batadv_iv_ogm_orig_get(). Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 42cbc0a..8323bce 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -241,18 +241,16 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr) size = bat_priv->num_ifaces * sizeof(uint8_t); orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC); if (!orig_node->bat_iv.bcast_own_sum) - goto free_bcast_own; + goto free_orig_node; hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig, batadv_choose_orig, orig_node, &orig_node->hash_entry); if (hash_added != 0) - goto free_bcast_own; + goto free_orig_node; return orig_node; -free_bcast_own: - kfree(orig_node->bat_iv.bcast_own); free_orig_node: /* free twice, as batadv_orig_node_new sets refcount to 2 */ batadv_orig_node_free_ref(orig_node); -- cgit v0.10.2 From 70b271a78beba787155d6696aacd7c4d4a251c50 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 15 Feb 2014 21:50:37 +0100 Subject: batman-adv: fix potential kernel paging error for unicast transmissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit batadv_send_skb_prepare_unicast(_4addr) might reallocate the skb's data. If it does then our ethhdr pointer is not valid anymore in batadv_send_skb_unicast(), resulting in a kernel paging error. Fixing this by refetching the ethhdr pointer after the potential reallocation. Signed-off-by: Linus Lüssing Signed-off-by: Antonio Quartulli diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 579f5f0..843febd 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -254,9 +254,9 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, unsigned short vid) { - struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct ethhdr *ethhdr; struct batadv_unicast_packet *unicast_packet; - int ret = NET_XMIT_DROP; + int ret = NET_XMIT_DROP, hdr_size; if (!orig_node) goto out; @@ -265,12 +265,16 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, case BATADV_UNICAST: if (!batadv_send_skb_prepare_unicast(skb, orig_node)) goto out; + + hdr_size = sizeof(*unicast_packet); break; case BATADV_UNICAST_4ADDR: if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, orig_node, packet_subtype)) goto out; + + hdr_size = sizeof(struct batadv_unicast_4addr_packet); break; default: /* this function supports UNICAST and UNICAST_4ADDR only. It @@ -279,6 +283,7 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, goto out; } + ethhdr = (struct ethhdr *)(skb->data + hdr_size); unicast_packet = (struct batadv_unicast_packet *)skb->data; /* inform the destination node that we are still missing a correct route -- cgit v0.10.2 From 08b44656c08c8c2f73cdac2a058be2880e3361f2 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 17 Feb 2014 14:22:21 +0100 Subject: gre: add link local route when local addr is any This bug was reported by Steinar H. Gunderson and was introduced by commit f7cb8886335d ("sit/gre6: don't try to add the same route two times"). root@morgental:~# ip tunnel add foo mode gre remote 1.2.3.4 ttl 64 root@morgental:~# ip link set foo up mtu 1468 root@morgental:~# ip -6 route show dev foo fe80::/64 proto kernel metric 256 but after the above commit, no such route shows up. There is no link local route because dev->dev_addr is 0 (because local ipv4 address is 0), hence no link local address is configured. In this scenario, the link local address is added manually: 'ip -6 addr add fe80::1 dev foo' and because prefix is /128, no link local route is added by the kernel. Even if the right things to do is to add the link local address with a /64 prefix, we need to restore the previous behavior to avoid breaking userpace. Reported-by: Steinar H. Gunderson Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ad23569..fdbfeca 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2783,6 +2783,8 @@ static void addrconf_gre_config(struct net_device *dev) ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) addrconf_add_linklocal(idev, &addr); + else + addrconf_prefix_route(&addr, 64, dev, 0, 0); } #endif -- cgit v0.10.2 From 292f503cade2b1d966239ef56a851e6897d1ba92 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 16 Feb 2014 21:42:56 -0500 Subject: NFSv4: Use the correct net namespace in nfs4_update_server We need to use the same net namespace that was used to resolve the hostname and sockaddr arguments. Fixes: 32e62b7c3ef09 (NFS: Add nfs4_update_server) Cc: Chuck Lever Signed-off-by: Trond Myklebust diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index fafddda..b46cf5a 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -176,7 +176,8 @@ extern struct nfs_server *nfs4_create_server( extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, struct nfs_fh *); extern int nfs4_update_server(struct nfs_server *server, const char *hostname, - struct sockaddr *sap, size_t salen); + struct sockaddr *sap, size_t salen, + struct net *net); extern void nfs_free_server(struct nfs_server *server); extern struct nfs_server *nfs_clone_server(struct nfs_server *, struct nfs_fh *, diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 860ad26..0e46d3d 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -1135,6 +1135,7 @@ static int nfs_probe_destination(struct nfs_server *server) * @hostname: new end-point's hostname * @sap: new end-point's socket address * @salen: size of "sap" + * @net: net namespace * * The nfs_server must be quiescent before this function is invoked. * Either its session is drained (NFSv4.1+), or its transport is @@ -1143,13 +1144,13 @@ static int nfs_probe_destination(struct nfs_server *server) * Returns zero on success, or a negative errno value. */ int nfs4_update_server(struct nfs_server *server, const char *hostname, - struct sockaddr *sap, size_t salen) + struct sockaddr *sap, size_t salen, struct net *net) { struct nfs_client *clp = server->nfs_client; struct rpc_clnt *clnt = server->client; struct xprt_create xargs = { .ident = clp->cl_proto, - .net = &init_net, + .net = net, .dstaddr = sap, .addrlen = salen, .servername = hostname, @@ -1189,7 +1190,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname, error = nfs4_set_client(server, hostname, sap, salen, buf, clp->cl_rpcclient->cl_auth->au_flavor, clp->cl_proto, clnt->cl_timeout, - clp->cl_minorversion, clp->cl_net); + clp->cl_minorversion, net); nfs_put_client(clp); if (error != 0) { nfs_server_insert_lists(server); diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 4e7f05d..3d5dbf8 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -121,9 +121,8 @@ static int nfs4_validate_fspath(struct dentry *dentry, } static size_t nfs_parse_server_name(char *string, size_t len, - struct sockaddr *sa, size_t salen, struct nfs_server *server) + struct sockaddr *sa, size_t salen, struct net *net) { - struct net *net = rpc_net_ns(server->client); ssize_t ret; ret = rpc_pton(net, string, len, sa, salen); @@ -223,6 +222,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, const struct nfs4_fs_location *location) { const size_t addr_bufsize = sizeof(struct sockaddr_storage); + struct net *net = rpc_net_ns(NFS_SB(mountdata->sb)->client); struct vfsmount *mnt = ERR_PTR(-ENOENT); char *mnt_path; unsigned int maxbuflen; @@ -248,8 +248,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, continue; mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, - mountdata->addr, addr_bufsize, - NFS_SB(mountdata->sb)); + mountdata->addr, addr_bufsize, net); if (mountdata->addrlen == 0) continue; @@ -419,6 +418,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, const struct nfs4_fs_location *location) { const size_t addr_bufsize = sizeof(struct sockaddr_storage); + struct net *net = rpc_net_ns(server->client); struct sockaddr *sap; unsigned int s; size_t salen; @@ -440,7 +440,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, continue; salen = nfs_parse_server_name(buf->data, buf->len, - sap, addr_bufsize, server); + sap, addr_bufsize, net); if (salen == 0) continue; rpc_set_port(sap, NFS_PORT); @@ -450,7 +450,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, if (hostname == NULL) break; - error = nfs4_update_server(server, hostname, sap, salen); + error = nfs4_update_server(server, hostname, sap, salen, net); kfree(hostname); if (error == 0) break; -- cgit v0.10.2 From eb85569fe2d06c2fbf4de7b66c263ca095b397aa Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Thu, 13 Feb 2014 17:50:19 +0100 Subject: usbnet: remove generic hard_header_len check This patch removes a generic hard_header_len check from the usbnet module that is causing dropped packages under certain circumstances for devices that send rx packets that cross urb boundaries. One example is the AX88772B which occasionally send rx packets that cross urb boundaries where the remaining partial packet is sent with no hardware header. When the buffer with a partial packet is of less number of octets than the value of hard_header_len the buffer is discarded by the usbnet module. With AX88772B this can be reproduced by using ping with a packet size between 1965-1976. The bug has been reported here: https://bugzilla.kernel.org/show_bug.cgi?id=29082 This patch introduces the following changes: - Removes the generic hard_header_len check in the rx_complete function in the usbnet module. - Introduces a ETH_HLEN check for skbs that are not cloned from within a rx_fixup callback. - For safety a hard_header_len check is added to each rx_fixup callback function that could be affected by this change. These extra checks could possibly be removed by someone who has the hardware to test. - Removes a call to dev_kfree_skb_any() and instead utilizes the dev->done list to queue skbs for cleanup. The changes place full responsibility on the rx_fixup callback functions that clone skbs to only pass valid skbs to the usbnet_skb_return function. Signed-off-by: Emil Goode Reported-by: Igor Gnatenko Signed-off-by: David S. Miller diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index d6f64da..955df81 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1118,6 +1118,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) u16 hdr_off; u32 *pkt_hdr; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + skb_trim(skb, skb->len - 4); memcpy(&rx_hdr, skb_tail_pointer(skb), 4); le32_to_cpus(&rx_hdr); diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c index e4a8a93..1cc24e6 100644 --- a/drivers/net/usb/gl620a.c +++ b/drivers/net/usb/gl620a.c @@ -84,6 +84,10 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) u32 size; u32 count; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + header = (struct gl_header *) skb->data; // get the packet count of the received skb diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index a305a7b..82d844a 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -526,8 +526,9 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { u8 status; - if (skb->len == 0) { - dev_err(&dev->udev->dev, "unexpected empty rx frame\n"); + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) { + dev_err(&dev->udev->dev, "unexpected tiny rx frame\n"); return 0; } diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 0a85d92..4cbdb13 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -364,6 +364,10 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) struct nc_trailer *trailer; u16 hdr_len, packet_len; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + if (!(skb->len & 0x01)) { netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n", skb->len, dev->net->hard_header_len, dev->hard_mtu, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 1eddd43..313cb6c 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -80,10 +80,10 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { __be16 proto; - /* usbnet rx_complete guarantees that skb->len is at least - * hard_header_len, so we can inspect the dest address without - * checking skb->len - */ + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + switch (skb->data[0] & 0xf0) { case 0x40: proto = htons(ETH_P_IP); diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index a48bc0f..524a47a281 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -492,6 +492,10 @@ EXPORT_SYMBOL_GPL(rndis_unbind); */ int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + /* peripheral may have batched packets to us... */ while (likely(skb->len)) { struct rndis_data_hdr *hdr = (void *)skb->data; diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index f17b9e0..d9e7892 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -2106,6 +2106,10 @@ static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (skb->len > 0) { u32 rx_cmd_a, rx_cmd_b, align_count, size; struct sk_buff *ax_skb; diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 8dd54a0..424db65e 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1723,6 +1723,10 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb) static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (skb->len > 0) { u32 header, align_count; struct sk_buff *ax_skb; diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 8017108..b94a0fb 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -63,6 +63,10 @@ static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { int offset = 0; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (offset + sizeof(u32) < skb->len) { struct sk_buff *sr_skb; u16 size; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 4671da7..dd10d58 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -542,17 +542,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) } // else network stack removes extra byte if we forced a short packet - if (skb->len) { - /* all data was already cloned from skb inside the driver */ - if (dev->driver_info->flags & FLAG_MULTI_PACKET) - dev_kfree_skb_any(skb); - else - usbnet_skb_return(dev, skb); + /* all data was already cloned from skb inside the driver */ + if (dev->driver_info->flags & FLAG_MULTI_PACKET) + goto done; + + if (skb->len < ETH_HLEN) { + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len); + } else { + usbnet_skb_return(dev, skb); return; } - netif_dbg(dev, rx_err, dev->net, "drop\n"); - dev->net->stats.rx_errors++; done: skb_queue_tail(&dev->done, skb); } @@ -574,13 +576,6 @@ static void rx_complete (struct urb *urb) switch (urb_status) { /* success */ case 0: - if (skb->len < dev->net->hard_header_len) { - state = rx_cleanup; - dev->net->stats.rx_errors++; - dev->net->stats.rx_length_errors++; - netif_dbg(dev, rx_err, dev->net, - "rx length %d\n", skb->len); - } break; /* stalls need manual reset. this is rare ... except that -- cgit v0.10.2 From 163c8ff30dbe473abfbb24a7eac5536c87f3baa9 Mon Sep 17 00:00:00 2001 From: Jiri Bohac Date: Fri, 14 Feb 2014 18:13:50 +0100 Subject: bonding: 802.3ad: make aggregator_identifier bond-private aggregator_identifier is used to assign unique aggregator identifiers to aggregators of a bond during device enslaving. aggregator_identifier is currently a global variable that is zeroed in bond_3ad_initialize(). This sequence will lead to duplicate aggregator identifiers for eth1 and eth3: create bond0 change bond0 mode to 802.3ad enslave eth0 to bond0 //eth0 gets agg id 1 enslave eth1 to bond0 //eth1 gets agg id 2 create bond1 change bond1 mode to 802.3ad enslave eth2 to bond1 //aggregator_identifier is reset to 0 //eth2 gets agg id 1 enslave eth3 to bond0 //eth3 gets agg id 2 Fix this by making aggregator_identifier private to the bond. Signed-off-by: Jiri Bohac Acked-by: Veaceslav Falico Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index cce1f1b..6d20fbd 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1796,8 +1796,6 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) BOND_AD_INFO(bond).agg_select_timer = timeout; } -static u16 aggregator_identifier; - /** * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures * @bond: bonding struct to work on @@ -1811,7 +1809,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution) if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr), bond->dev->dev_addr)) { - aggregator_identifier = 0; + BOND_AD_INFO(bond).aggregator_identifier = 0; BOND_AD_INFO(bond).system.sys_priority = 0xFFFF; BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr); @@ -1880,7 +1878,7 @@ void bond_3ad_bind_slave(struct slave *slave) ad_initialize_agg(aggregator); aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr); - aggregator->aggregator_identifier = (++aggregator_identifier); + aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier; aggregator->slave = slave; aggregator->is_active = 0; aggregator->num_of_ports = 0; diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 13dc9d3..f4dd959 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -253,6 +253,7 @@ struct ad_system { struct ad_bond_info { struct ad_system system; /* 802.3ad system structure */ u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes + u16 aggregator_identifier; }; struct ad_slave_info { -- cgit v0.10.2 From a4b1b5877b514b276f0f31efe02388a9c2836728 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 19 Dec 2013 12:09:32 +0100 Subject: HID: Bluetooth: hidp: make sure input buffers are big enough HID core expects the input buffers to be at least of size 4096 (HID_MAX_BUFFER_SIZE). Other sizes will result in buffer-overflows if an input-report is smaller than advertised. We could, like i2c, compute the biggest report-size instead of using HID_MAX_BUFFER_SIZE, but this will blow up if report-descriptors are changed after ->start() has been called. So lets be safe and just use the biggest buffer we have. Note that this adds an additional copy to the HIDP input path. If there is a way to make sure the skb-buf is big enough, we should use that instead. The best way would be to make hid-core honor the @size argument, though, that sounds easier than it is. So lets just fix the buffer-overflows for now and afterwards look for a faster way for all transport drivers. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 292e619..d9fb934 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session) del_timer(&session->timer); } +static void hidp_process_report(struct hidp_session *session, + int type, const u8 *data, int len, int intr) +{ + if (len > HID_MAX_BUFFER_SIZE) + len = HID_MAX_BUFFER_SIZE; + + memcpy(session->input_buf, data, len); + hid_input_report(session->hid, type, session->input_buf, len, intr); +} + static void hidp_process_handshake(struct hidp_session *session, unsigned char param) { @@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, hidp_input_report(session, skb); if (session->hid) - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0); + hidp_process_report(session, HID_INPUT_REPORT, + skb->data, skb->len, 0); break; case HIDP_DATA_RTYPE_OTHER: @@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session, hidp_input_report(session, skb); if (session->hid) { - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1); + hidp_process_report(session, HID_INPUT_REPORT, + skb->data, skb->len, 1); BT_DBG("report len %d", skb->len); } } else { diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index ab52414..8798492 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h @@ -24,6 +24,7 @@ #define __HIDP_H #include +#include #include #include #include @@ -179,6 +180,9 @@ struct hidp_session { /* Used in hidp_output_raw_report() */ int output_report_success; /* boolean */ + + /* temporary input buffer */ + u8 input_buf[HID_MAX_BUFFER_SIZE]; }; /* HIDP init defines */ -- cgit v0.10.2 From 3ccfd0a8d7062a5590923578eea829ee582beba8 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 19 Dec 2013 12:32:24 +0100 Subject: HID: hyperv: make sure input buffer is big enough We need at least HID_MAX_BUFFER_SIZE (4096) bytes as input buffer. HID core depends on this as it requires every input report to be at least as big as advertised. Signed-off-by: David Herrmann Signed-off-by: K. Y. Srinivasan Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 8fae6d1..c24908f 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -157,6 +157,7 @@ struct mousevsc_dev { u32 report_desc_size; struct hv_input_dev_info hid_dev_info; struct hid_device *hid_device; + u8 input_buf[HID_MAX_BUFFER_SIZE]; }; @@ -256,6 +257,7 @@ static void mousevsc_on_receive(struct hv_device *device, struct synthhid_msg *hid_msg; struct mousevsc_dev *input_dev = hv_get_drvdata(device); struct synthhid_input_report *input_report; + size_t len; pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + (packet->offset8 << 3)); @@ -300,9 +302,12 @@ static void mousevsc_on_receive(struct hv_device *device, (struct synthhid_input_report *)pipe_msg->data; if (!input_dev->init_complete) break; - hid_input_report(input_dev->hid_device, - HID_INPUT_REPORT, input_report->buffer, - input_report->header.size, 1); + + len = min(input_report->header.size, + (u32)sizeof(input_dev->input_buf)); + memcpy(input_dev->input_buf, input_report->buffer, len); + hid_input_report(input_dev->hid_device, HID_INPUT_REPORT, + input_dev->input_buf, len, 1); break; default: pr_err("unsupported hid msg type - type %d len %d", -- cgit v0.10.2 From e4178d809fdaee32a56833fff1f5056c99e90a1a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 17 Feb 2014 12:24:45 -0800 Subject: printk: fix syslog() overflowing user buffer This is not a buffer overflow in the traditional sense: we don't overflow any *kernel* buffers, but we do mis-count the amount of data we copy back to user space for the SYSLOG_ACTION_READ_ALL case. In particular, if the user buffer is too small to hold everything, and *if* there is a continuation line at just the right place, we can end up giving the user more data than he asked for. The reason is that we first count up the number of bytes all the log records contains, then we walk the records again until we've skipped the records at the beginning that won't fit, and then we walk the rest of the records and copy them to the user space buffer. And in between that "skip the initial records that won't fit" and the "copy the records that *will* fit to user space", we reset the 'prev' variable that contained the record information for the last record not copied. That meant that when we started copying to user space, we now had a different character count than what we had originally calculated in the first record walk-through. The fix is to simply not clear the 'prev' flags value (in both cases where we had the same logic: syslog_print_all and kmsg_dump_get_buffer: the latter is used for pstore-like dumping) Reported-and-tested-by: Debabrata Banerjee Acked-by: Kay Sievers Cc: Greg Kroah-Hartman Cc: Jeff Mahoney Signed-off-by: Linus Torvalds diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index b1d255f..4dae9cb 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1076,7 +1076,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) next_seq = log_next_seq; len = 0; - prev = 0; while (len >= 0 && seq < next_seq) { struct printk_log *msg = log_from_idx(idx); int textlen; @@ -2788,7 +2787,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, next_idx = idx; l = 0; - prev = 0; while (seq < dumper->next_seq) { struct printk_log *msg = log_from_idx(idx); -- cgit v0.10.2 From fbc0b970ddfab4b35dad27ebaae712af680bdc7e Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:01:19 +0800 Subject: ceph: properly handle XATTR_CREATE and XATTR_REPLACE return -EEXIST if XATTR_CREATE is set and xattr alread exists. return -ENODATA if XATTR_REPLACE is set but xattr does not exist. Signed-off-by: Yan, Zheng diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 898b656..28f9793 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -319,8 +319,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, static int __set_xattr(struct ceph_inode_info *ci, const char *name, int name_len, const char *val, int val_len, - int dirty, - int should_free_name, int should_free_val, + int flags, int update_xattr, struct ceph_inode_xattr **newxattr) { struct rb_node **p; @@ -349,12 +348,25 @@ static int __set_xattr(struct ceph_inode_info *ci, xattr = NULL; } + if (update_xattr) { + int err = 0; + if (xattr && (flags & XATTR_CREATE)) + err = -EEXIST; + else if (!xattr && (flags & XATTR_REPLACE)) + err = -ENODATA; + if (err) { + kfree(name); + kfree(val); + return err; + } + } + if (!xattr) { new = 1; xattr = *newxattr; xattr->name = name; xattr->name_len = name_len; - xattr->should_free_name = should_free_name; + xattr->should_free_name = update_xattr; ci->i_xattrs.count++; dout("__set_xattr count=%d\n", ci->i_xattrs.count); @@ -364,7 +376,7 @@ static int __set_xattr(struct ceph_inode_info *ci, if (xattr->should_free_val) kfree((void *)xattr->val); - if (should_free_name) { + if (update_xattr) { kfree((void *)name); name = xattr->name; } @@ -379,8 +391,8 @@ static int __set_xattr(struct ceph_inode_info *ci, xattr->val = ""; xattr->val_len = val_len; - xattr->dirty = dirty; - xattr->should_free_val = (val && should_free_val); + xattr->dirty = update_xattr; + xattr->should_free_val = (val && update_xattr); if (new) { rb_link_node(&xattr->node, parent, p); @@ -588,7 +600,7 @@ start: p += len; err = __set_xattr(ci, name, namelen, val, len, - 0, 0, 0, &xattrs[numattr]); + 0, 0, &xattrs[numattr]); if (err < 0) goto bad; @@ -892,7 +904,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, struct ceph_inode_info *ci = ceph_inode(inode); int issued; int err; - int dirty; + int dirty = 0; int name_len = strlen(name); int val_len = size; char *newname = NULL; @@ -954,11 +966,13 @@ retry: } err = __set_xattr(ci, newname, name_len, newval, - val_len, 1, 1, 1, &xattr); + val_len, flags, 1, &xattr); - dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); - ci->i_xattrs.dirty = true; - inode->i_ctime = CURRENT_TIME; + if (!err) { + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); + ci->i_xattrs.dirty = true; + inode->i_ctime = CURRENT_TIME; + } spin_unlock(&ci->i_ceph_lock); if (dirty) -- cgit v0.10.2 From bcdfeb2eb4e42b811950b9cd226109291051732a Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:04:19 +0800 Subject: ceph: remove xattr when null value is given to setxattr() For the setxattr request, introduce a new flag CEPH_XATTR_REMOVE to distinguish null value case from the zero-length value case. Signed-off-by: Yan, Zheng diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 28f9793..231c02b 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -12,6 +12,9 @@ #define XATTR_CEPH_PREFIX "ceph." #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) +static int __remove_xattr(struct ceph_inode_info *ci, + struct ceph_inode_xattr *xattr); + /* * List of handlers for synthetic system.* attributes. Other * attributes are handled directly. @@ -359,6 +362,12 @@ static int __set_xattr(struct ceph_inode_info *ci, kfree(val); return err; } + if (update_xattr < 0) { + if (xattr) + __remove_xattr(ci, xattr); + kfree(name); + return 0; + } } if (!xattr) { @@ -862,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name, dout("setxattr value=%.*s\n", (int)size, value); + if (!value) + flags |= CEPH_XATTR_REMOVE; + /* do request */ req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, USE_AUTH_MDS); @@ -965,8 +977,8 @@ retry: goto retry; } - err = __set_xattr(ci, newname, name_len, newval, - val_len, flags, 1, &xattr); + err = __set_xattr(ci, newname, name_len, newval, val_len, + flags, value ? 1 : -1, &xattr); if (!err) { dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h index 2623cff..25bfb0e 100644 --- a/include/linux/ceph/ceph_fs.h +++ b/include/linux/ceph/ceph_fs.h @@ -373,8 +373,9 @@ extern const char *ceph_mds_op_name(int op); /* * Ceph setxattr request flags. */ -#define CEPH_XATTR_CREATE 1 -#define CEPH_XATTR_REPLACE 2 +#define CEPH_XATTR_CREATE (1 << 0) +#define CEPH_XATTR_REPLACE (1 << 1) +#define CEPH_XATTR_REMOVE (1 << 31) union ceph_mds_request_args { struct { -- cgit v0.10.2 From 524186ace6c4dcc83975b858622a66888b018fd0 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:23:09 +0800 Subject: ceph: fix ceph_removexattr() Signed-off-by: Yan, Zheng diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 231c02b..a55ec37 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -463,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci, struct ceph_inode_xattr *xattr) { if (!xattr) - return -EOPNOTSUPP; + return -ENODATA; rb_erase(&xattr->node, &ci->i_xattrs.index); -- cgit v0.10.2 From 7a92d64760541e66bf5d1131f029b82773ce3922 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:08:51 +0800 Subject: ceph: fix ceph_set_acl() If acl is equivalent to file mode permission bits, ceph_set_acl() needs to remove any existing acl xattr. Use __ceph_setxattr() to handle both setting and removing acl xattr cases, it doesn't return -ENODATA when there is no acl xattr. Signed-off-by: Yan, Zheng diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 4c2d452..accc9f2 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -160,11 +160,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) goto out_dput; } - if (value) - ret = __ceph_setxattr(dentry, name, value, size, 0); - else - ret = __ceph_removexattr(dentry, name); - + ret = __ceph_setxattr(dentry, name, value, size, 0); if (ret) { if (new_mode != old_mode) { newattrs.ia_mode = old_mode; -- cgit v0.10.2 From b20a95a0dd47c56c5d20e1c9e260293d0b87abe0 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 12:55:05 +0800 Subject: ceph: add missing init_acl() for mkdir() and atomic_open() Signed-off-by: Yan, Zheng diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 6da4df8..2e3b30d 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -695,9 +695,8 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, ceph_mdsc_put_request(req); if (!err) - err = ceph_init_acl(dentry, dentry->d_inode, dir); - - if (err) + ceph_init_acl(dentry, dentry->d_inode, dir); + else d_drop(dentry); return err; } @@ -735,7 +734,9 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, if (!err && !req->r_reply_info.head->is_dentry) err = ceph_handle_notrace_create(dir, dentry); ceph_mdsc_put_request(req); - if (err) + if (!err) + ceph_init_acl(dentry, dentry->d_inode, dir); + else d_drop(dentry); return err; } @@ -776,7 +777,9 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) err = ceph_handle_notrace_create(dir, dentry); ceph_mdsc_put_request(req); out: - if (err < 0) + if (!err) + ceph_init_acl(dentry, dentry->d_inode, dir); + else d_drop(dentry); return err; } diff --git a/fs/ceph/file.c b/fs/ceph/file.c index dfd2ce3..09c7afe 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -286,6 +286,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, } else { dout("atomic_open finish_open on dn %p\n", dn); if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { + ceph_init_acl(dentry, dentry->d_inode, dir); *opened |= FILE_CREATED; } err = finish_open(file, dentry, ceph_open, opened); -- cgit v0.10.2 From c969d9bf91e1868d823351993216cd64dfab6a4c Mon Sep 17 00:00:00 2001 From: Guangliang Zhao Date: Sun, 16 Feb 2014 08:35:52 -0800 Subject: ceph: make ceph_forget_all_cached_acls() static inline Signed-off-by: Guangliang Zhao Reviewed-by: Alex Elder Signed-off-by: Sage Weil diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index accc9f2..21887d6 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -54,11 +54,6 @@ static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode, return acl; } -void ceph_forget_all_cached_acls(struct inode *inode) -{ - forget_all_cached_acls(inode); -} - struct posix_acl *ceph_get_acl(struct inode *inode, int type) { int size; diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 19793b5..d8801a9 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -743,7 +744,11 @@ extern const struct xattr_handler *ceph_xattr_handlers[]; struct posix_acl *ceph_get_acl(struct inode *, int); int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type); int ceph_init_acl(struct dentry *, struct inode *, struct inode *); -void ceph_forget_all_cached_acls(struct inode *inode); + +static inline void ceph_forget_all_cached_acls(struct inode *inode) +{ + forget_all_cached_acls(inode); +} #else -- cgit v0.10.2 From 45195e42c78ea91135108207dbcaf75e5556a309 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 16 Feb 2014 10:05:29 -0800 Subject: ceph: add acl, noacl options for cephfs mount Make the 'acl' option dependent on having ACL support compiled in. Make the 'noacl' option work even without it so that one can always ask it to be off and not error out on mount when it is not supported. Signed-off-by: Guangliang Zhao Signed-off-by: Sage Weil diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 2df963f..10a4ccb 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -144,7 +144,11 @@ enum { Opt_ino32, Opt_noino32, Opt_fscache, - Opt_nofscache + Opt_nofscache, +#ifdef CONFIG_CEPH_FS_POSIX_ACL + Opt_acl, +#endif + Opt_noacl }; static match_table_t fsopt_tokens = { @@ -172,6 +176,10 @@ static match_table_t fsopt_tokens = { {Opt_noino32, "noino32"}, {Opt_fscache, "fsc"}, {Opt_nofscache, "nofsc"}, +#ifdef CONFIG_CEPH_FS_POSIX_ACL + {Opt_acl, "acl"}, +#endif + {Opt_noacl, "noacl"}, {-1, NULL} }; @@ -271,6 +279,14 @@ static int parse_fsopt_token(char *c, void *private) case Opt_nofscache: fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE; break; +#ifdef CONFIG_CEPH_FS_POSIX_ACL + case Opt_acl: + fsopt->sb_flags |= MS_POSIXACL; + break; +#endif + case Opt_noacl: + fsopt->sb_flags &= ~MS_POSIXACL; + break; default: BUG_ON(token); } @@ -438,6 +454,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) else seq_puts(m, ",nofsc"); +#ifdef CONFIG_CEPH_FS_POSIX_ACL + if (fsopt->sb_flags & MS_POSIXACL) + seq_puts(m, ",acl"); + else + seq_puts(m, ",noacl"); +#endif + if (fsopt->wsize) seq_printf(m, ",wsize=%d", fsopt->wsize); if (fsopt->rsize != CEPH_RSIZE_DEFAULT) @@ -819,9 +842,6 @@ static int ceph_set_super(struct super_block *s, void *data) s->s_flags = fsc->mount_options->sb_flags; s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */ -#ifdef CONFIG_CEPH_FS_POSIX_ACL - s->s_flags |= MS_POSIXACL; -#endif s->s_xattr = ceph_xattr_handlers; s->s_fs_info = fsc; @@ -911,6 +931,10 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type, struct ceph_options *opt = NULL; dout("ceph_mount\n"); + +#ifdef CONFIG_CEPH_FS_POSIX_ACL + flags |= MS_POSIXACL; +#endif err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path); if (err < 0) { res = ERR_PTR(err); -- cgit v0.10.2 From 4d5f5df673ee673851986b5a492a9752fbb39dc5 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 13 Feb 2014 19:40:26 +0800 Subject: ceph: fix __dcache_readdir() If directory is fragmented, readdir() read its dirfrags one by one. After reading all dirfrags, the corresponding dentries are sorted in (frag_t, off) order in the dcache. If dentries of a directory are all cached, __dcache_readdir() can use the cached dentries to satisfy readdir syscall. But when checking if a given dentry is after the position of readdir, __dcache_readdir() compares numerical value of frag_t directly. This is wrong, it should use ceph_frag_compare(). Signed-off-by: Yan, Zheng diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 2e3b30d..45eda6d 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -100,6 +100,14 @@ static unsigned fpos_off(loff_t p) return p & 0xffffffff; } +static int fpos_cmp(loff_t l, loff_t r) +{ + int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r)); + if (v) + return v; + return (int)(fpos_off(l) - fpos_off(r)); +} + /* * When possible, we try to satisfy a readdir by peeking at the * dcache. We make this work by carefully ordering dentries on @@ -156,7 +164,7 @@ more: if (!d_unhashed(dentry) && dentry->d_inode && ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && - ctx->pos <= di->offset) + fpos_cmp(ctx->pos, di->offset) <= 0) break; dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry, dentry->d_name.len, dentry->d_name.name, di->offset, -- cgit v0.10.2 From 3eca5299532ea9d6ab63b03e7aaac9071d5eed29 Mon Sep 17 00:00:00 2001 From: Tommie Gannert Date: Mon, 17 Feb 2014 20:46:04 +0000 Subject: irtty-sir.c: Do not set_termios() on irtty_close() Issuing set_termios() from irtty_close() causes kernel Oops for unplugged usb-serial devices. Since no other tty_ldisc calls set_termios() on close and no tty driver seem to check if tty->device_data is NULL or not on entry to set_termios(), the only solution I can come up with is to remove the irtty_stop_receiver() call, which only updates termios. Signed-off-by: Tommie Gannert Signed-off-by: David S. Miller diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 177441a..24b6ddd 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -522,7 +522,6 @@ static void irtty_close(struct tty_struct *tty) sirdev_put_instance(priv->dev); /* Stop tty */ - irtty_stop_receiver(tty, TRUE); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); if (tty->ops->stop) tty->ops->stop(tty); -- cgit v0.10.2 From 416e2abd925d0f41dc877d1fe01489d79bdecf4c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 17 Feb 2014 16:21:24 -0500 Subject: reiserfs: fix utterly brain-damaged indentation. This has been this way for years, and every time I stumble across it I lose my lunch. After coming across it for the nth time in the Coverity results, I had to overcome the bystander effect and do something about it. This ignores the 79 column limit in favor of making it look like C instead of gibberish. The correct thing to do here would be to lose some of the indentation by breaking this function up into several smaller ones. I might do that at some point if I have the stomach to look at this again. (Also some of those overlong ternary operations would likely be more readable as regular if's) Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index 2b7882b..9a3c68c 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c @@ -324,23 +324,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h switch (flag) { case M_INSERT: /* insert item into L[0] */ - if (item_pos == tb->lnum[0] - 1 - && tb->lbytes != -1) { + if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { /* part of new item falls into L[0] */ int new_item_len; int version; - ret_val = - leaf_shift_left(tb, tb->lnum[0] - 1, - -1); + ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, -1); /* Calculate item length to insert to S[0] */ - new_item_len = - ih_item_len(ih) - tb->lbytes; + new_item_len = ih_item_len(ih) - tb->lbytes; /* Calculate and check item length to insert to L[0] */ - put_ih_item_len(ih, - ih_item_len(ih) - - new_item_len); + put_ih_item_len(ih, ih_item_len(ih) - new_item_len); RFALSE(ih_item_len(ih) <= 0, "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d", @@ -349,30 +343,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* Insert new item into L[0] */ buffer_info_init_left(tb, &bi); leaf_insert_into_buf(&bi, - n + item_pos - - ret_val, ih, body, - zeros_num > - ih_item_len(ih) ? - ih_item_len(ih) : - zeros_num); + n + item_pos - ret_val, ih, body, + zeros_num > ih_item_len(ih) ? ih_item_len(ih) : zeros_num); version = ih_version(ih); /* Calculate key component, item length and body to insert into S[0] */ - set_le_ih_k_offset(ih, - le_ih_k_offset(ih) + - (tb-> - lbytes << - (is_indirect_le_ih - (ih) ? tb->tb_sb-> - s_blocksize_bits - - UNFM_P_SHIFT : - 0))); + set_le_ih_k_offset(ih, le_ih_k_offset(ih) + + (tb-> lbytes << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0))); put_ih_item_len(ih, new_item_len); if (tb->lbytes > zeros_num) { - body += - (tb->lbytes - zeros_num); + body += (tb->lbytes - zeros_num); zeros_num = 0; } else zeros_num -= tb->lbytes; @@ -383,15 +365,10 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h } else { /* new item in whole falls into L[0] */ /* Shift lnum[0]-1 items to L[0] */ - ret_val = - leaf_shift_left(tb, tb->lnum[0] - 1, - tb->lbytes); + ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes); /* Insert new item into L[0] */ buffer_info_init_left(tb, &bi); - leaf_insert_into_buf(&bi, - n + item_pos - - ret_val, ih, body, - zeros_num); + leaf_insert_into_buf(&bi, n + item_pos - ret_val, ih, body, zeros_num); tb->insert_size[0] = 0; zeros_num = 0; } @@ -399,264 +376,117 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h case M_PASTE: /* append item in L[0] */ - if (item_pos == tb->lnum[0] - 1 - && tb->lbytes != -1) { + if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { /* we must shift the part of the appended item */ - if (is_direntry_le_ih - (B_N_PITEM_HEAD(tbS0, item_pos))) { + if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) { RFALSE(zeros_num, "PAP-12090: invalid parameter in case of a directory"); /* directory item */ if (tb->lbytes > pos_in_item) { /* new directory entry falls into L[0] */ - struct item_head - *pasted; - int l_pos_in_item = - pos_in_item; + struct item_head *pasted; + int l_pos_in_item = pos_in_item; /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */ - ret_val = - leaf_shift_left(tb, - tb-> - lnum - [0], - tb-> - lbytes - - - 1); - if (ret_val - && !item_pos) { - pasted = - B_N_PITEM_HEAD - (tb->L[0], - B_NR_ITEMS - (tb-> - L[0]) - - 1); - l_pos_in_item += - I_ENTRY_COUNT - (pasted) - - (tb-> - lbytes - - 1); + ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes-1); + if (ret_val && !item_pos) { + pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1); + l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes -1); } /* Append given directory entry to directory item */ buffer_info_init_left(tb, &bi); - leaf_paste_in_buffer - (&bi, - n + item_pos - - ret_val, - l_pos_in_item, - tb->insert_size[0], - body, zeros_num); + leaf_paste_in_buffer(&bi, n + item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, zeros_num); /* previous string prepared space for pasting new entry, following string pastes this entry */ /* when we have merge directory item, pos_in_item has been changed too */ /* paste new directory entry. 1 is entry number */ - leaf_paste_entries(&bi, - n + - item_pos - - - ret_val, - l_pos_in_item, - 1, - (struct - reiserfs_de_head - *) - body, - body - + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, n + item_pos - ret_val, l_pos_in_item, + 1, (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); tb->insert_size[0] = 0; } else { /* new directory item doesn't fall into L[0] */ /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */ - leaf_shift_left(tb, - tb-> - lnum[0], - tb-> - lbytes); + leaf_shift_left(tb, tb->lnum[0], tb->lbytes); } /* Calculate new position to append in item body */ pos_in_item -= tb->lbytes; } else { /* regular object */ - RFALSE(tb->lbytes <= 0, - "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", - tb->lbytes); - RFALSE(pos_in_item != - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), + RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", tb->lbytes); + RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)), "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d", - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), - pos_in_item); + ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),pos_in_item); if (tb->lbytes >= pos_in_item) { /* appended item will be in L[0] in whole */ int l_n; /* this bytes number must be appended to the last item of L[h] */ - l_n = - tb->lbytes - - pos_in_item; + l_n = tb->lbytes - pos_in_item; /* Calculate new insert_size[0] */ - tb->insert_size[0] -= - l_n; + tb->insert_size[0] -= l_n; - RFALSE(tb-> - insert_size[0] <= - 0, + RFALSE(tb->insert_size[0] <= 0, "PAP-12105: there is nothing to paste into L[0]. insert_size=%d", - tb-> - insert_size[0]); - ret_val = - leaf_shift_left(tb, - tb-> - lnum - [0], - ih_item_len - (B_N_PITEM_HEAD - (tbS0, - item_pos))); + tb->insert_size[0]); + ret_val = leaf_shift_left(tb, tb->lnum[0], ih_item_len + (B_N_PITEM_HEAD(tbS0, item_pos))); /* Append to body of item in L[0] */ buffer_info_init_left(tb, &bi); leaf_paste_in_buffer - (&bi, - n + item_pos - - ret_val, - ih_item_len - (B_N_PITEM_HEAD - (tb->L[0], - n + item_pos - - ret_val)), l_n, - body, - zeros_num > - l_n ? l_n : - zeros_num); + (&bi, n + item_pos - ret_val, ih_item_len + (B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)), + l_n, body, + zeros_num > l_n ? l_n : zeros_num); /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */ { int version; - int temp_l = - l_n; - - RFALSE - (ih_item_len - (B_N_PITEM_HEAD - (tbS0, - 0)), + int temp_l = l_n; + + RFALSE(ih_item_len(B_N_PITEM_HEAD(tbS0, 0)), "PAP-12106: item length must be 0"); - RFALSE - (comp_short_le_keys - (B_N_PKEY - (tbS0, 0), - B_N_PKEY - (tb->L[0], - n + - item_pos - - - ret_val)), + RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY + (tb->L[0], n + item_pos - ret_val)), "PAP-12107: items must be of the same file"); if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) { - temp_l = - l_n - << - (tb-> - tb_sb-> - s_blocksize_bits - - - UNFM_P_SHIFT); + temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT); } /* update key of first item in S0 */ - version = - ih_version - (B_N_PITEM_HEAD - (tbS0, 0)); - set_le_key_k_offset - (version, - B_N_PKEY - (tbS0, 0), - le_key_k_offset - (version, - B_N_PKEY - (tbS0, - 0)) + - temp_l); + version = ih_version(B_N_PITEM_HEAD(tbS0, 0)); + set_le_key_k_offset(version, B_N_PKEY(tbS0, 0), + le_key_k_offset(version,B_N_PKEY(tbS0, 0)) + temp_l); /* update left delimiting key */ - set_le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb-> - CFL[0], - tb-> - lkey[0]), - le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb-> - CFL[0], - tb-> - lkey[0])) - + temp_l); + set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), + le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l); } /* Calculate new body, position in item and insert_size[0] */ if (l_n > zeros_num) { - body += - (l_n - - zeros_num); + body += (l_n - zeros_num); zeros_num = 0; } else - zeros_num -= - l_n; + zeros_num -= l_n; pos_in_item = 0; - RFALSE - (comp_short_le_keys - (B_N_PKEY(tbS0, 0), - B_N_PKEY(tb->L[0], - B_NR_ITEMS - (tb-> - L[0]) - - 1)) - || - !op_is_left_mergeable - (B_N_PKEY(tbS0, 0), - tbS0->b_size) - || - !op_is_left_mergeable - (B_N_PDELIM_KEY - (tb->CFL[0], - tb->lkey[0]), - tbS0->b_size), + RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1)) + || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size) + || !op_is_left_mergeable(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), tbS0->b_size), "PAP-12120: item must be merge-able with left neighboring item"); } else { /* only part of the appended item will be in L[0] */ /* Calculate position in item for append in S[0] */ - pos_in_item -= - tb->lbytes; + pos_in_item -= tb->lbytes; - RFALSE(pos_in_item <= 0, - "PAP-12125: no place for paste. pos_in_item=%d", - pos_in_item); + RFALSE(pos_in_item <= 0, "PAP-12125: no place for paste. pos_in_item=%d", pos_in_item); /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ - leaf_shift_left(tb, - tb-> - lnum[0], - tb-> - lbytes); + leaf_shift_left(tb, tb->lnum[0], tb->lbytes); } } } else { /* appended item will be in L[0] in whole */ @@ -665,52 +495,30 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) { /* if we paste into first item of S[0] and it is left mergable */ /* then increment pos_in_item by the size of the last item in L[0] */ - pasted = - B_N_PITEM_HEAD(tb->L[0], - n - 1); + pasted = B_N_PITEM_HEAD(tb->L[0], n - 1); if (is_direntry_le_ih(pasted)) - pos_in_item += - ih_entry_count - (pasted); + pos_in_item += ih_entry_count(pasted); else - pos_in_item += - ih_item_len(pasted); + pos_in_item += ih_item_len(pasted); } /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ - ret_val = - leaf_shift_left(tb, tb->lnum[0], - tb->lbytes); + ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes); /* Append to body of item in L[0] */ buffer_info_init_left(tb, &bi); - leaf_paste_in_buffer(&bi, - n + item_pos - - ret_val, + leaf_paste_in_buffer(&bi, n + item_pos - ret_val, pos_in_item, tb->insert_size[0], body, zeros_num); /* if appended item is directory, paste entry */ - pasted = - B_N_PITEM_HEAD(tb->L[0], - n + item_pos - - ret_val); + pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val); if (is_direntry_le_ih(pasted)) - leaf_paste_entries(&bi, - n + - item_pos - - ret_val, - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, n + item_pos - ret_val, + pos_in_item, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, + tb->insert_size[0]); /* if appended item is indirect item, put unformatted node into un list */ if (is_indirect_le_ih(pasted)) set_ih_free_space(pasted, 0); @@ -722,13 +530,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h reiserfs_panic(tb->tb_sb, "PAP-12130", "lnum > 0: unexpected mode: " " %s(%d)", - (flag == - M_DELETE) ? "DELETE" : ((flag == - M_CUT) - ? "CUT" - : - "UNKNOWN"), - flag); + (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } } else { /* new item doesn't fall into L[0] */ @@ -748,14 +550,12 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h case M_INSERT: /* insert item */ if (n - tb->rnum[0] < item_pos) { /* new item or its part falls to R[0] */ if (item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) { /* part of new item falls into R[0] */ - loff_t old_key_comp, old_len, - r_zeros_number; + loff_t old_key_comp, old_len, r_zeros_number; const char *r_body; int version; loff_t offset; - leaf_shift_right(tb, tb->rnum[0] - 1, - -1); + leaf_shift_right(tb, tb->rnum[0] - 1, -1); version = ih_version(ih); /* Remember key component and item length */ @@ -763,29 +563,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h old_len = ih_item_len(ih); /* Calculate key component and item length to insert into R[0] */ - offset = - le_ih_k_offset(ih) + - ((old_len - - tb-> - rbytes) << (is_indirect_le_ih(ih) - ? tb->tb_sb-> - s_blocksize_bits - - UNFM_P_SHIFT : 0)); + offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << (is_indirect_le_ih(ih) ? tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0)); set_le_ih_k_offset(ih, offset); put_ih_item_len(ih, tb->rbytes); /* Insert part of the item into R[0] */ buffer_info_init_right(tb, &bi); if ((old_len - tb->rbytes) > zeros_num) { r_zeros_number = 0; - r_body = - body + (old_len - - tb->rbytes) - - zeros_num; + r_body = body + (old_len - tb->rbytes) - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - (old_len - - tb->rbytes); + r_zeros_number = zeros_num - (old_len - tb->rbytes); zeros_num -= r_zeros_number; } @@ -798,25 +586,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* Calculate key component and item length to insert into S[0] */ set_le_ih_k_offset(ih, old_key_comp); - put_ih_item_len(ih, - old_len - tb->rbytes); + put_ih_item_len(ih, old_len - tb->rbytes); tb->insert_size[0] -= tb->rbytes; } else { /* whole new item falls into R[0] */ /* Shift rnum[0]-1 items to R[0] */ - ret_val = - leaf_shift_right(tb, - tb->rnum[0] - 1, - tb->rbytes); + ret_val = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes); /* Insert new item into R[0] */ buffer_info_init_right(tb, &bi); - leaf_insert_into_buf(&bi, - item_pos - n + - tb->rnum[0] - 1, - ih, body, - zeros_num); + leaf_insert_into_buf(&bi, item_pos - n + tb->rnum[0] - 1, + ih, body, zeros_num); if (item_pos - n + tb->rnum[0] - 1 == 0) { replace_key(tb, tb->CFR[0], @@ -841,200 +622,97 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h RFALSE(zeros_num, "PAP-12145: invalid parameter in case of a directory"); - entry_count = - I_ENTRY_COUNT(B_N_PITEM_HEAD - (tbS0, - item_pos)); + entry_count = I_ENTRY_COUNT(B_N_PITEM_HEAD + (tbS0, item_pos)); if (entry_count - tb->rbytes < pos_in_item) /* new directory entry falls into R[0] */ { int paste_entry_position; - RFALSE(tb->rbytes - 1 >= - entry_count - || !tb-> - insert_size[0], + RFALSE(tb->rbytes - 1 >= entry_count || !tb-> insert_size[0], "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d", - tb->rbytes, - entry_count); + tb->rbytes, entry_count); /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */ - leaf_shift_right(tb, - tb-> - rnum - [0], - tb-> - rbytes - - 1); + leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1); /* Paste given directory entry to directory item */ - paste_entry_position = - pos_in_item - - entry_count + - tb->rbytes - 1; + paste_entry_position = pos_in_item - entry_count + tb->rbytes - 1; buffer_info_init_right(tb, &bi); - leaf_paste_in_buffer - (&bi, 0, - paste_entry_position, - tb->insert_size[0], - body, zeros_num); + leaf_paste_in_buffer(&bi, 0, paste_entry_position, tb->insert_size[0], body, zeros_num); /* paste entry */ - leaf_paste_entries(&bi, - 0, - paste_entry_position, - 1, - (struct - reiserfs_de_head - *) - body, - body - + - DEH_SIZE, - tb-> - insert_size - [0] - ); - - if (paste_entry_position - == 0) { + leaf_paste_entries(&bi, 0, paste_entry_position, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); + + if (paste_entry_position == 0) { /* change delimiting keys */ - replace_key(tb, - tb-> - CFR - [0], - tb-> - rkey - [0], - tb-> - R - [0], - 0); + replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0],0); } tb->insert_size[0] = 0; pos_in_item++; } else { /* new directory entry doesn't fall into R[0] */ - leaf_shift_right(tb, - tb-> - rnum - [0], - tb-> - rbytes); + leaf_shift_right(tb, tb->rnum[0], tb->rbytes); } } else { /* regular object */ - int n_shift, n_rem, - r_zeros_number; + int n_shift, n_rem, r_zeros_number; const char *r_body; /* Calculate number of bytes which must be shifted from appended item */ - if ((n_shift = - tb->rbytes - - tb->insert_size[0]) < 0) + if ((n_shift = tb->rbytes - tb->insert_size[0]) < 0) n_shift = 0; - RFALSE(pos_in_item != - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), + RFALSE(pos_in_item != ih_item_len + (B_N_PITEM_HEAD(tbS0, item_pos)), "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d", - pos_in_item, - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos))); - - leaf_shift_right(tb, - tb->rnum[0], - n_shift); + pos_in_item, ih_item_len + (B_N_PITEM_HEAD(tbS0, item_pos))); + + leaf_shift_right(tb, tb->rnum[0], n_shift); /* Calculate number of bytes which must remain in body after appending to R[0] */ - if ((n_rem = - tb->insert_size[0] - - tb->rbytes) < 0) + if ((n_rem = tb->insert_size[0] - tb->rbytes) < 0) n_rem = 0; { int version; - unsigned long temp_rem = - n_rem; - - version = - ih_version - (B_N_PITEM_HEAD - (tb->R[0], 0)); - if (is_indirect_le_key - (version, - B_N_PKEY(tb->R[0], - 0))) { - temp_rem = - n_rem << - (tb->tb_sb-> - s_blocksize_bits - - - UNFM_P_SHIFT); + unsigned long temp_rem = n_rem; + + version = ih_version(B_N_PITEM_HEAD(tb->R[0], 0)); + if (is_indirect_le_key(version, B_N_PKEY(tb->R[0], 0))) { + temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT); } - set_le_key_k_offset - (version, - B_N_PKEY(tb->R[0], - 0), - le_key_k_offset - (version, - B_N_PKEY(tb->R[0], - 0)) + - temp_rem); - set_le_key_k_offset - (version, - B_N_PDELIM_KEY(tb-> - CFR - [0], - tb-> - rkey - [0]), - le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb->CFR[0], - tb->rkey[0])) + - temp_rem); + set_le_key_k_offset(version, B_N_PKEY(tb->R[0], 0), + le_key_k_offset(version, B_N_PKEY(tb->R[0], 0)) + temp_rem); + set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]), + le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0])) + temp_rem); } /* k_offset (B_N_PKEY(tb->R[0],0)) += n_rem; k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/ - do_balance_mark_internal_dirty - (tb, tb->CFR[0], 0); + do_balance_mark_internal_dirty(tb, tb->CFR[0], 0); /* Append part of body into R[0] */ buffer_info_init_right(tb, &bi); if (n_rem > zeros_num) { r_zeros_number = 0; - r_body = - body + n_rem - - zeros_num; + r_body = body + n_rem - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - n_rem; - zeros_num -= - r_zeros_number; + r_zeros_number = zeros_num - n_rem; + zeros_num -= r_zeros_number; } - leaf_paste_in_buffer(&bi, 0, - n_shift, - tb-> - insert_size - [0] - - n_rem, - r_body, - r_zeros_number); - - if (is_indirect_le_ih - (B_N_PITEM_HEAD - (tb->R[0], 0))) { + leaf_paste_in_buffer(&bi, 0, n_shift, + tb->insert_size[0] - n_rem, + r_body, r_zeros_number); + + if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->R[0], 0))) { #if 0 RFALSE(n_rem, "PAP-12160: paste more than one unformatted node pointer"); #endif - set_ih_free_space - (B_N_PITEM_HEAD - (tb->R[0], 0), 0); + set_ih_free_space(B_N_PITEM_HEAD(tb->R[0], 0), 0); } tb->insert_size[0] = n_rem; if (!n_rem) @@ -1044,58 +722,28 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h struct item_head *pasted; - ret_val = - leaf_shift_right(tb, tb->rnum[0], - tb->rbytes); + ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes); /* append item in R[0] */ if (pos_in_item >= 0) { buffer_info_init_right(tb, &bi); - leaf_paste_in_buffer(&bi, - item_pos - - n + - tb-> - rnum[0], - pos_in_item, - tb-> - insert_size - [0], body, - zeros_num); + leaf_paste_in_buffer(&bi, item_pos - n + tb->rnum[0], pos_in_item, + tb->insert_size[0], body, zeros_num); } /* paste new entry, if item is directory item */ - pasted = - B_N_PITEM_HEAD(tb->R[0], - item_pos - n + - tb->rnum[0]); - if (is_direntry_le_ih(pasted) - && pos_in_item >= 0) { - leaf_paste_entries(&bi, - item_pos - - n + - tb->rnum[0], - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] - ); + pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]); + if (is_direntry_le_ih(pasted) && pos_in_item >= 0) { + leaf_paste_entries(&bi, item_pos - n + tb->rnum[0], + pos_in_item, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); if (!pos_in_item) { - RFALSE(item_pos - n + - tb->rnum[0], + RFALSE(item_pos - n + tb->rnum[0], "PAP-12165: directory item must be first item of node when pasting is in 0th position"); /* update delimiting keys */ - replace_key(tb, - tb->CFR[0], - tb->rkey[0], - tb->R[0], - 0); + replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0); } } @@ -1111,22 +759,16 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h default: /* cases d and t */ reiserfs_panic(tb->tb_sb, "PAP-12175", "rnum > 0: unexpected mode: %s(%d)", - (flag == - M_DELETE) ? "DELETE" : ((flag == - M_CUT) ? "CUT" - : "UNKNOWN"), - flag); + (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } } /* tb->rnum[0] > 0 */ RFALSE(tb->blknum[0] > 3, - "PAP-12180: blknum can not be %d. It must be <= 3", - tb->blknum[0]); + "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]); RFALSE(tb->blknum[0] < 0, - "PAP-12185: blknum can not be %d. It must be >= 0", - tb->blknum[0]); + "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]); /* if while adding to a node we discover that it is possible to split it in two, and merge the left part into the left neighbor and the @@ -1177,8 +819,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h if (n - snum[i] < item_pos) { /* new item or it's part falls to first new node S_new[i] */ if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) { /* part of new item falls into S_new[i] */ - int old_key_comp, old_len, - r_zeros_number; + int old_key_comp, old_len, r_zeros_number; const char *r_body; int version; @@ -1192,15 +833,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h old_len = ih_item_len(ih); /* Calculate key component and item length to insert into S_new[i] */ - set_le_ih_k_offset(ih, - le_ih_k_offset(ih) + - ((old_len - - sbytes[i]) << - (is_indirect_le_ih - (ih) ? tb->tb_sb-> - s_blocksize_bits - - UNFM_P_SHIFT : - 0))); + set_le_ih_k_offset(ih, le_ih_k_offset(ih) + + ((old_len - sbytes[i]) << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0))); put_ih_item_len(ih, sbytes[i]); @@ -1209,39 +843,29 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h if ((old_len - sbytes[i]) > zeros_num) { r_zeros_number = 0; - r_body = - body + (old_len - - sbytes[i]) - - zeros_num; + r_body = body + (old_len - sbytes[i]) - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - (old_len - - sbytes[i]); + r_zeros_number = zeros_num - (old_len - sbytes[i]); zeros_num -= r_zeros_number; } - leaf_insert_into_buf(&bi, 0, ih, r_body, - r_zeros_number); + leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number); /* Calculate key component and item length to insert into S[i] */ set_le_ih_k_offset(ih, old_key_comp); - put_ih_item_len(ih, - old_len - sbytes[i]); + put_ih_item_len(ih, old_len - sbytes[i]); tb->insert_size[0] -= sbytes[i]; } else { /* whole new item falls into S_new[i] */ /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */ leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, - snum[i] - 1, sbytes[i], - S_new[i]); + snum[i] - 1, sbytes[i], S_new[i]); /* Insert new item into S_new[i] */ buffer_info_init_bh(tb, &bi, S_new[i]); - leaf_insert_into_buf(&bi, - item_pos - n + - snum[i] - 1, ih, - body, zeros_num); + leaf_insert_into_buf(&bi, item_pos - n + snum[i] - 1, + ih, body, zeros_num); zeros_num = tb->insert_size[0] = 0; } @@ -1268,150 +892,73 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h int entry_count; - entry_count = - ih_entry_count(aux_ih); + entry_count = ih_entry_count(aux_ih); - if (entry_count - sbytes[i] < - pos_in_item - && pos_in_item <= - entry_count) { + if (entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count) { /* new directory entry falls into S_new[i] */ - RFALSE(!tb-> - insert_size[0], - "PAP-12215: insert_size is already 0"); - RFALSE(sbytes[i] - 1 >= - entry_count, + RFALSE(!tb->insert_size[0], "PAP-12215: insert_size is already 0"); + RFALSE(sbytes[i] - 1 >= entry_count, "PAP-12220: there are no so much entries (%d), only %d", - sbytes[i] - 1, - entry_count); + sbytes[i] - 1, entry_count); /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */ - leaf_move_items - (LEAF_FROM_S_TO_SNEW, - tb, snum[i], - sbytes[i] - 1, - S_new[i]); + leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i] - 1, S_new[i]); /* Paste given directory entry to directory item */ buffer_info_init_bh(tb, &bi, S_new[i]); - leaf_paste_in_buffer - (&bi, 0, - pos_in_item - - entry_count + - sbytes[i] - 1, - tb->insert_size[0], - body, zeros_num); + leaf_paste_in_buffer(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, + tb->insert_size[0], body, zeros_num); /* paste new directory entry */ - leaf_paste_entries(&bi, - 0, - pos_in_item - - - entry_count - + - sbytes - [i] - - 1, 1, - (struct - reiserfs_de_head - *) - body, - body - + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); tb->insert_size[0] = 0; pos_in_item++; } else { /* new directory entry doesn't fall into S_new[i] */ - leaf_move_items - (LEAF_FROM_S_TO_SNEW, - tb, snum[i], - sbytes[i], - S_new[i]); + leaf_move_items(LEAF_FROM_S_TO_SNEW,tb, snum[i], sbytes[i], S_new[i]); } } else { /* regular object */ - int n_shift, n_rem, - r_zeros_number; + int n_shift, n_rem, r_zeros_number; const char *r_body; - RFALSE(pos_in_item != - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)) - || tb->insert_size[0] <= - 0, + RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)) || tb->insert_size[0] <= 0, "PAP-12225: item too short or insert_size <= 0"); /* Calculate number of bytes which must be shifted from appended item */ - n_shift = - sbytes[i] - - tb->insert_size[0]; + n_shift = sbytes[i] - tb->insert_size[0]; if (n_shift < 0) n_shift = 0; - leaf_move_items - (LEAF_FROM_S_TO_SNEW, tb, - snum[i], n_shift, - S_new[i]); + leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], n_shift, S_new[i]); /* Calculate number of bytes which must remain in body after append to S_new[i] */ - n_rem = - tb->insert_size[0] - - sbytes[i]; + n_rem = tb->insert_size[0] - sbytes[i]; if (n_rem < 0) n_rem = 0; /* Append part of body into S_new[0] */ buffer_info_init_bh(tb, &bi, S_new[i]); if (n_rem > zeros_num) { r_zeros_number = 0; - r_body = - body + n_rem - - zeros_num; + r_body = body + n_rem - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - n_rem; - zeros_num -= - r_zeros_number; + r_zeros_number = zeros_num - n_rem; + zeros_num -= r_zeros_number; } - leaf_paste_in_buffer(&bi, 0, - n_shift, - tb-> - insert_size - [0] - - n_rem, - r_body, - r_zeros_number); + leaf_paste_in_buffer(&bi, 0, n_shift, + tb->insert_size[0] - n_rem, + r_body, r_zeros_number); { struct item_head *tmp; - tmp = - B_N_PITEM_HEAD(S_new - [i], - 0); + tmp = B_N_PITEM_HEAD(S_new[i], 0); if (is_indirect_le_ih (tmp)) { - set_ih_free_space - (tmp, 0); - set_le_ih_k_offset - (tmp, - le_ih_k_offset - (tmp) + - (n_rem << - (tb-> - tb_sb-> - s_blocksize_bits - - - UNFM_P_SHIFT))); + set_ih_free_space(tmp, 0); + set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT))); } else { - set_le_ih_k_offset - (tmp, - le_ih_k_offset - (tmp) + - n_rem); + set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + n_rem); } } @@ -1426,8 +973,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h struct item_head *pasted; #ifdef CONFIG_REISERFS_CHECK - struct item_head *ih_check = - B_N_PITEM_HEAD(tbS0, item_pos); + struct item_head *ih_check = B_N_PITEM_HEAD(tbS0, item_pos); if (!is_direntry_le_ih(ih_check) && (pos_in_item != ih_item_len(ih_check) @@ -1439,8 +985,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h "to ih_item_len"); #endif /* CONFIG_REISERFS_CHECK */ - leaf_mi = - leaf_move_items(LEAF_FROM_S_TO_SNEW, + leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]); @@ -1452,30 +997,19 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* paste into item */ buffer_info_init_bh(tb, &bi, S_new[i]); leaf_paste_in_buffer(&bi, - item_pos - n + - snum[i], + item_pos - n + snum[i], pos_in_item, tb->insert_size[0], body, zeros_num); - pasted = - B_N_PITEM_HEAD(S_new[i], - item_pos - n + - snum[i]); + pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]); if (is_direntry_le_ih(pasted)) { leaf_paste_entries(&bi, - item_pos - - n + snum[i], - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] + item_pos - n + snum[i], + pos_in_item, 1, + (struct reiserfs_de_head *)body, + body + DEH_SIZE, + tb->insert_size[0] ); } @@ -1495,11 +1029,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h default: /* cases d and t */ reiserfs_panic(tb->tb_sb, "PAP-12245", "blknum > 2: unexpected mode: %s(%d)", - (flag == - M_DELETE) ? "DELETE" : ((flag == - M_CUT) ? "CUT" - : "UNKNOWN"), - flag); + (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE); @@ -1524,9 +1054,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* If we insert the first key change the delimiting key */ if (item_pos == 0) { if (tb->CFL[0]) /* can be 0 in reiserfsck */ - replace_key(tb, tb->CFL[0], tb->lkey[0], - tbS0, 0); - + replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0); } break; @@ -1536,53 +1064,27 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h pasted = B_N_PITEM_HEAD(tbS0, item_pos); /* when directory, may be new entry already pasted */ if (is_direntry_le_ih(pasted)) { - if (pos_in_item >= 0 && - pos_in_item <= - ih_entry_count(pasted)) { + if (pos_in_item >= 0 && pos_in_item <= ih_entry_count(pasted)) { RFALSE(!tb->insert_size[0], "PAP-12260: insert_size is 0 already"); /* prepare space */ buffer_info_init_tbS0(tb, &bi); - leaf_paste_in_buffer(&bi, - item_pos, - pos_in_item, - tb-> - insert_size - [0], body, + leaf_paste_in_buffer(&bi, item_pos, pos_in_item, + tb->insert_size[0], body, zeros_num); /* paste entry */ - leaf_paste_entries(&bi, - item_pos, - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, item_pos, pos_in_item, 1, + (struct reiserfs_de_head *)body, + body + DEH_SIZE, + tb->insert_size[0]); if (!item_pos && !pos_in_item) { - RFALSE(!tb->CFL[0] - || !tb->L[0], + RFALSE(!tb->CFL[0] || !tb->L[0], "PAP-12270: CFL[0]/L[0] must be specified"); - if (tb->CFL[0]) { - replace_key(tb, - tb-> - CFL - [0], - tb-> - lkey - [0], - tbS0, - 0); - - } + if (tb->CFL[0]) + replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0); } tb->insert_size[0] = 0; } @@ -1593,13 +1095,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h "PAP-12275: insert size must not be %d", tb->insert_size[0]); buffer_info_init_tbS0(tb, &bi); - leaf_paste_in_buffer(&bi, - item_pos, - pos_in_item, - tb-> - insert_size - [0], body, - zeros_num); + leaf_paste_in_buffer(&bi, item_pos, pos_in_item, + tb->insert_size[0], body, zeros_num); if (is_indirect_le_ih(pasted)) { #if 0 @@ -1611,8 +1108,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h tb-> insert_size[0]); #endif - set_ih_free_space - (pasted, 0); + set_ih_free_space(pasted, 0); } tb->insert_size[0] = 0; } @@ -1620,8 +1116,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h else { if (tb->insert_size[0]) { print_cur_tb("12285"); - reiserfs_panic(tb-> - tb_sb, + reiserfs_panic(tb->tb_sb, "PAP-12285", "insert_size " "must be 0 " -- cgit v0.10.2 From 7026f1929e18921fd67bf478f475a8fdfdff16ae Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 17 Feb 2014 15:01:47 +0000 Subject: FS-Cache: Handle removal of unadded object to the fscache_object_list rb tree When FS-Cache allocates an object, the following sequence of events can occur: -->fscache_alloc_object() -->cachefiles_alloc_object() [via cache->ops->alloc_object] <--[returns new object] -->fscache_attach_object() <--[failed] -->cachefiles_put_object() [via cache->ops->put_object] -->fscache_object_destroy() -->fscache_objlist_remove() -->rb_erase() to remove the object from fscache_object_list. resulting in a crash in the rbtree code. The problem is that the object is only added to fscache_object_list on the success path of fscache_attach_object() where it calls fscache_objlist_add(). So if fscache_attach_object() fails, the object won't have been added to the objlist rbtree. We do, however, unconditionally try to remove the object from the tree. Thanks to NeilBrown for finding this and suggesting this solution. Reported-by: NeilBrown Signed-off-by: David Howells Tested-by: (a customer of) NeilBrown Signed-off-by: Linus Torvalds diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index e1959ef..b5ebc2d 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c @@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj) struct fscache_object *xobj; struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL; + ASSERT(RB_EMPTY_NODE(&obj->objlist_link)); + write_lock(&fscache_object_list_lock); while (*p) { @@ -75,6 +77,9 @@ void fscache_objlist_add(struct fscache_object *obj) */ void fscache_objlist_remove(struct fscache_object *obj) { + if (RB_EMPTY_NODE(&obj->objlist_link)) + return; + write_lock(&fscache_object_list_lock); BUG_ON(RB_EMPTY_ROOT(&fscache_object_list)); diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 53d35c5..d3b4539 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object, object->cache = cache; object->cookie = cookie; object->parent = NULL; +#ifdef CONFIG_FSCACHE_OBJECT_LIST + RB_CLEAR_NODE(&object->objlist_link); +#endif object->oob_event_mask = 0; for (t = object->oob_table; t->events; t++) -- cgit v0.10.2 From a6254864c08109c66a194612585afc0439005286 Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Mon, 17 Feb 2014 15:23:43 +0800 Subject: ipv4: fix counter in_slow_tot since commit 89aef8921bf("ipv4: Delete routing cache."), the counter in_slow_tot can't work correctly. The counter in_slow_tot increase by one when fib_lookup() return successfully in ip_route_input_slow(), but actually the dst struct maybe not be created and cached, so we can increase in_slow_tot after the dst struct is created. Signed-off-by: Duan Jiong Signed-off-by: David S. Miller diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6f6dd85..4c011ec 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1597,6 +1597,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); + RT_CACHE_STAT_INC(in_slow_tot); rth->dst.input = ip_forward; rth->dst.output = ip_output; @@ -1701,8 +1702,6 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto no_route; } - RT_CACHE_STAT_INC(in_slow_tot); - if (res.type == RTN_BROADCAST) goto brd_input; @@ -1773,6 +1772,7 @@ local_input: rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); + RT_CACHE_STAT_INC(in_slow_tot); if (res.type == RTN_UNREACHABLE) { rth->dst.input= ip_error; rth->dst.error= -err; -- cgit v0.10.2 From e83b366487b5582274374f8226e489cb214ae5a6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Feb 2014 17:11:04 +0000 Subject: Fix uses of dma_max_pfn() when converting to a limiting address We must use a 64-bit for this, otherwise overflowed bits get lost, and that can result in a lower than intended value set. Fixes: 8e0cb8a1f6ac ("ARM: 7797/1: mmc: Use dma_max_pfn(dev) helper for bounce_limit calculations") Fixes: 7d35496dd982 ("ARM: 7796/1: scsi: Use dma_max_pfn(dev) helper for bounce_limit calculations") Tested-Acked-by: Santosh Shilimkar Reviewed-by: Ulf Hansson Signed-off-by: Russell King diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 357bbc5..3e049c1 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -197,7 +197,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, struct mmc_queue_req *mqrq_prev = &mq->mqrq[1]; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) - limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; + limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; mq->card = card; mq->queue = blk_init_queue(mmc_request_fn, lock); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7bd7f0d..62ec84b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1684,7 +1684,7 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) host_dev = scsi_get_device(shost); if (host_dev && host_dev->dma_mask) - bounce_limit = dma_max_pfn(host_dev) << PAGE_SHIFT; + bounce_limit = (u64)dma_max_pfn(host_dev) << PAGE_SHIFT; return bounce_limit; } -- cgit v0.10.2 From 39544ac9df20f73e49fc6b9ac19ff533388c82c0 Mon Sep 17 00:00:00 2001 From: Vinayak Kale Date: Wed, 12 Feb 2014 07:30:01 +0100 Subject: ARM: 7957/1: add DSB after icache flush in __flush_icache_all() Add DSB after icache flush to complete the cache maintenance operation. Signed-off-by: Vinayak Kale Acked-by: Catalin Marinas Cc: Signed-off-by: Russell King diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index e9a49fe..8b8b616 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -212,6 +212,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, static inline void __flush_icache_all(void) { __flush_icache_preferred(); + dsb(); } /* -- cgit v0.10.2 From 0eba801b64cc8284d9024c7ece30415a2b981a72 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 16 Feb 2014 12:15:43 +0100 Subject: netfilter: ctnetlink: force null nat binding on insert Quoting Andrey Vagin: When a conntrack is created by kernel, it is initialized (sets IPS_{DST,SRC}_NAT_DONE_BIT bits in nf_nat_setup_info) and only then it is added in hashes (__nf_conntrack_hash_insert), so one conntract can't be initialized from a few threads concurrently. ctnetlink can add an uninitialized conntrack (w/o IPS_{DST,SRC}_NAT_DONE_BIT) in hashes, then a few threads can look up this conntrack and start initialize it concurrently. It's dangerous, because BUG can be triggered from nf_nat_setup_info. Fix this race by always setting up nat, even if no CTA_NAT_ attribute was requested before inserting the ct into the hash table. In absence of CTA_NAT_ attribute, a null binding is created. This alters current behaviour: Before this patch, the first packet matching the newly injected conntrack would be run through the nat table since nf_nat_initialized() returns false. IOW, this forces ctnetlink users to specify the desired nat transformation on ct creation time. Thanks for Florian Westphal, this patch is based on his original patch to address this problem, including this patch description. Reported-By: Andrey Vagin Signed-off-by: Pablo Neira Ayuso Acked-by: Florian Westphal diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index bb322d0..b9f0e03 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1310,27 +1310,22 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) } static int -ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[]) +ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[]) { #ifdef CONFIG_NF_NAT_NEEDED int ret; - if (cda[CTA_NAT_DST]) { - ret = ctnetlink_parse_nat_setup(ct, - NF_NAT_MANIP_DST, - cda[CTA_NAT_DST]); - if (ret < 0) - return ret; - } - if (cda[CTA_NAT_SRC]) { - ret = ctnetlink_parse_nat_setup(ct, - NF_NAT_MANIP_SRC, - cda[CTA_NAT_SRC]); - if (ret < 0) - return ret; - } - return 0; + ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST, + cda[CTA_NAT_DST]); + if (ret < 0) + return ret; + + ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC, + cda[CTA_NAT_SRC]); + return ret; #else + if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC]) + return 0; return -EOPNOTSUPP; #endif } @@ -1659,11 +1654,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, goto err2; } - if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { - err = ctnetlink_change_nat(ct, cda); - if (err < 0) - goto err2; - } + err = ctnetlink_setup_nat(ct, cda); + if (err < 0) + goto err2; nf_ct_acct_ext_add(ct, GFP_ATOMIC); nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index d3f5cd6..52ca952 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -432,15 +432,15 @@ nf_nat_setup_info(struct nf_conn *ct, } EXPORT_SYMBOL(nf_nat_setup_info); -unsigned int -nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) +static unsigned int +__nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip) { /* Force range to this IP; let proto decide mapping for * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). * Use reply in case it's already been mangled (eg local packet). */ union nf_inet_addr ip = - (HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ? + (manip == NF_NAT_MANIP_SRC ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3); struct nf_nat_range range = { @@ -448,7 +448,13 @@ nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) .min_addr = ip, .max_addr = ip, }; - return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); + return nf_nat_setup_info(ct, &range, manip); +} + +unsigned int +nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) +{ + return __nf_nat_alloc_null_binding(ct, HOOK2MANIP(hooknum)); } EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding); @@ -702,9 +708,9 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { static int nfnetlink_parse_nat(const struct nlattr *nat, - const struct nf_conn *ct, struct nf_nat_range *range) + const struct nf_conn *ct, struct nf_nat_range *range, + const struct nf_nat_l3proto *l3proto) { - const struct nf_nat_l3proto *l3proto; struct nlattr *tb[CTA_NAT_MAX+1]; int err; @@ -714,38 +720,46 @@ nfnetlink_parse_nat(const struct nlattr *nat, if (err < 0) return err; - rcu_read_lock(); - l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); - if (l3proto == NULL) { - err = -EAGAIN; - goto out; - } err = l3proto->nlattr_to_range(tb, range); if (err < 0) - goto out; + return err; if (!tb[CTA_NAT_PROTO]) - goto out; + return 0; - err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); -out: - rcu_read_unlock(); - return err; + return nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); } +/* This function is called under rcu_read_lock() */ static int nfnetlink_parse_nat_setup(struct nf_conn *ct, enum nf_nat_manip_type manip, const struct nlattr *attr) { struct nf_nat_range range; + const struct nf_nat_l3proto *l3proto; int err; - err = nfnetlink_parse_nat(attr, ct, &range); + /* Should not happen, restricted to creating new conntracks + * via ctnetlink. + */ + if (WARN_ON_ONCE(nf_nat_initialized(ct, manip))) + return -EEXIST; + + /* Make sure that L3 NAT is there by when we call nf_nat_setup_info to + * attach the null binding, otherwise this may oops. + */ + l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); + if (l3proto == NULL) + return -EAGAIN; + + /* No NAT information has been passed, allocate the null-binding */ + if (attr == NULL) + return __nf_nat_alloc_null_binding(ct, manip); + + err = nfnetlink_parse_nat(attr, ct, &range, l3proto); if (err < 0) return err; - if (nf_nat_initialized(ct, manip)) - return -EEXIST; return nf_nat_setup_info(ct, &range, manip); } -- cgit v0.10.2 From 7d3428cd4b2ad51af86fdbdf8284ca38fa95e601 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 29 Jan 2014 19:53:00 -0500 Subject: drm/nouveau: set irq_enabled manually Since commit 0fa9061ae8c ("drm/nouveau/mc: handle irq-related setup ourselves"), drm_device->irq_enabled remained unset. This is needed in order to properly wait for a vblank event in the generic drm code. See https://bugs.freedesktop.org/show_bug.cgi?id=74195 Reported-by: Jan Janecek Signed-off-by: Ilia Mirkin Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 78c8e71..89c484d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -376,6 +376,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail_device; + dev->irq_enabled = true; + /* workaround an odd issue on nvc1 by disabling the device's * nosnoop capability. hopefully won't cause issues until a * better fix is found - assuming there is one... @@ -475,6 +477,7 @@ nouveau_drm_remove(struct pci_dev *pdev) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_object *device; + dev->irq_enabled = false; device = drm->client.base.device; drm_put_dev(dev); -- cgit v0.10.2 From fa8c9ac72fe0bcdf5bc7cc84e85cc2a1af53f9fd Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 5 Feb 2014 14:33:02 -0500 Subject: drm/nv4c/mc: nv4x igp's have a different msi rearm register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://bugs.freedesktop.org/show_bug.cgi?id=74492 Reported-by: Ronald Suggested-by: Marcin KoÅ›cielnicki Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index e88145b..d310c19 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -141,6 +141,7 @@ nouveau-y += core/subdev/mc/base.o nouveau-y += core/subdev/mc/nv04.o nouveau-y += core/subdev/mc/nv40.o nouveau-y += core/subdev/mc/nv44.o +nouveau-y += core/subdev/mc/nv4c.o nouveau-y += core/subdev/mc/nv50.o nouveau-y += core/subdev/mc/nv94.o nouveau-y += core/subdev/mc/nv98.o diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c index 1b653dd..08b8859 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c @@ -311,7 +311,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; @@ -334,7 +334,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv4e_fb_oclass; @@ -357,7 +357,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; @@ -380,7 +380,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; @@ -403,7 +403,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index adc88b7..3c6738e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h @@ -47,6 +47,7 @@ struct nouveau_mc_oclass { extern struct nouveau_oclass *nv04_mc_oclass; extern struct nouveau_oclass *nv40_mc_oclass; extern struct nouveau_oclass *nv44_mc_oclass; +extern struct nouveau_oclass *nv4c_mc_oclass; extern struct nouveau_oclass *nv50_mc_oclass; extern struct nouveau_oclass *nv94_mc_oclass; extern struct nouveau_oclass *nv98_mc_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h index b0d5c31..81a408e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h @@ -14,6 +14,7 @@ int nv04_mc_ctor(struct nouveau_object *, struct nouveau_object *, extern const struct nouveau_mc_intr nv04_mc_intr[]; int nv04_mc_init(struct nouveau_object *); void nv40_mc_msi_rearm(struct nouveau_mc *); +int nv44_mc_init(struct nouveau_object *object); int nv50_mc_init(struct nouveau_object *); extern const struct nouveau_mc_intr nv50_mc_intr[]; extern const struct nouveau_mc_intr nvc0_mc_intr[]; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c index 3bfee5c..cc4d0d2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c @@ -24,7 +24,7 @@ #include "nv04.h" -static int +int nv44_mc_init(struct nouveau_object *object) { struct nv04_mc_priv *priv = (void *)object; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c new file mode 100644 index 0000000..a75c35c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c @@ -0,0 +1,45 @@ +/* + * Copyright 2014 Ilia Mirkin + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ilia Mirkin + */ + +#include "nv04.h" + +static void +nv4c_mc_msi_rearm(struct nouveau_mc *pmc) +{ + struct nv04_mc_priv *priv = (void *)pmc; + nv_wr08(priv, 0x088050, 0xff); +} + +struct nouveau_oclass * +nv4c_mc_oclass = &(struct nouveau_mc_oclass) { + .base.handle = NV_SUBDEV(MC, 0x4c), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv44_mc_init, + .fini = _nouveau_mc_fini, + }, + .intr = nv04_mc_intr, + .msi_rearm = nv4c_mc_msi_rearm, +}.base; -- cgit v0.10.2 From b71313e14bbc0b8fc25eeff53828ab8e2aee4f25 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 5 Feb 2014 14:33:03 -0500 Subject: drm/nv4c/vga: decode register is in a different place on nv4x igp's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Marcin KoÅ›cielnicki Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 81638d7..471347e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -14,7 +14,9 @@ nouveau_vga_set_decode(void *priv, bool state) { struct nouveau_device *device = nouveau_dev(priv); - if (device->chipset >= 0x40) + if (device->card_type == NV_40 && device->chipset >= 0x4c) + nv_wr32(device, 0x088060, state); + else if (device->chipset >= 0x40) nv_wr32(device, 0x088054, state); else nv_wr32(device, 0x001854, state); -- cgit v0.10.2 From 5ac607ec4006d61c425c7846f29de8a9d8ce4f9f Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 5 Feb 2014 14:33:04 -0500 Subject: drm/nv4c/bios: disallow retrieving from prom on nv4x igp's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Marcin KoÅ›cielnicki Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index aa0fbbe..ef0c9c4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -130,6 +130,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) u16 pcir; int i; + /* there is no prom on nv4x IGP's */ + if (device->card_type == NV_40 && device->chipset >= 0x4c) + return; + /* enable access to rom */ if (device->card_type >= NV_50) pcireg = 0x088050; -- cgit v0.10.2 From bf787d7cdf459d2e7f673b66b69441c708f4472c Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 7 Feb 2014 22:22:57 +0900 Subject: drm/nouveau: fix ENG_RUNLIST register address Address of the ENG_RUNLIST register should be 0x002284 + (engine * 8), not 0x002284 + (engine * 4). Signed-off-by: Alexandre Courbot Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 9a850fe..54c1b5b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -112,7 +112,7 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine) nv_wr32(priv, 0x002270, cur->addr >> 12); nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); - if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) + if (!nv_wait(priv, 0x002284 + (engine * 8), 0x00100000, 0x00000000)) nv_error(priv, "runlist %d update timeout\n", engine); mutex_unlock(&nv_subdev(priv)->mutex); } -- cgit v0.10.2 From a8c13aacdc20268ced05c9bb065c5d219840205e Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 8 Feb 2014 22:35:13 -0500 Subject: drm/nv50/gr: add missing nv_error parameter priv Commit ea7dce901 ("drm/nv50/gr: print mpc trap name when it's not an mp trap") added an nv_error call that was missing the priv parameter. This causes GPFs if the error is ever hit. Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 30ed19c..7a367c4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -539,7 +539,7 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old, ustatus &= ~0x04030000; } if (ustatus && display) { - nv_error("%s - TP%d:", name, i); + nv_error(priv, "%s - TP%d:", name, i); nouveau_bitfield_print(nv50_mpc_traps, ustatus); pr_cont("\n"); ustatus = 0; -- cgit v0.10.2 From 95ca5b550ac255bf3cee108c123407785c47e3cc Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Wed, 12 Feb 2014 01:41:42 +0000 Subject: drm/nouveau/fb: use correct ram oclass for nv1a hardware commit 8613e7314ac254fdd67ed46192f021d76141e4c9 Author: Ben Skeggs Date: Mon Oct 21 08:50:25 2013 +1000 drm/nouveau/fb: remove ram oclass argument from base fb constructor Introduced a unfortunate regression by using nv10 ram oclass for nv1a hardware, causing corruption and eventually system lockup. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74866 Reported-by: John F. Godfrey Signed-off-by: Emil Velikov Cc: stable@vger.kernel.org # 3.13+ Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c index 9159a5c..265d125 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c @@ -36,7 +36,7 @@ nv1a_fb_oclass = &(struct nv04_fb_impl) { .fini = _nouveau_fb_fini, }, .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv10_ram_oclass, + .base.ram = &nv1a_ram_oclass, .tile.regions = 8, .tile.init = nv10_fb_tile_init, .tile.fini = nv10_fb_tile_fini, -- cgit v0.10.2 From a7f1c1e65b68e1e1ab70898528d5977ed68a0a7d Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Thu, 13 Feb 2014 21:57:15 -0500 Subject: drm/nv50/disp: use correct register to determine DP display bpp Commit 0a0afd282f ("drm/nv50-/disp: move DP link training to core and train from supervisor") added code that uses the wrong register for computing the display bpp, used for bandwidth calculation. Adjust to use the same register as used by exec_clkcmp and nv50_disp_intr_unk20_2_dp. Reported-by: Torsten Wagner Reported-by: Michael Gulick Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67628 Cc: stable@vger.kernel.org # 3.9+ Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 940eaa5..9ad722e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -1142,7 +1142,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) if (conf != ~0) { if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) { u32 soff = (ffs(outp.or) - 1) * 0x08; - u32 ctrl = nv_rd32(priv, 0x610798 + soff); + u32 ctrl = nv_rd32(priv, 0x610794 + soff); u32 datarate; switch ((ctrl & 0x000f0000) >> 16) { -- cgit v0.10.2 From 34d595081812da62b5357579267c4ab5eae64ac1 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 15 Feb 2014 23:27:01 -0500 Subject: drm/nouveau: fix TTM_PL_TT memtype on pre-nv50 Commit a55409066 ("drm/nv50-: map TTM_PL_SYSTEM through a BAR for CPU access") made it possible to work with tiled memory. However mem->mm_node is not a nouveau_mem for AGP-using pre-NV50 cards, but a drm_mm_node, as created by the ttm_bo_manager_func. As such, extend the untiled check to explicitly include all pre-nv50 cards. Reported-by: Ronald Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74613 Signed-off-by: Ilia Mirkin Tested-by: Ronald Uitermark Acked-by: Maarten Lankhorst Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 488686d..4aed171 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1249,7 +1249,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) mem->bus.is_iomem = !dev->agp->cant_use_aperture; } #endif - if (!node->memtype) + if (nv_device(drm->device)->card_type < NV_50 || !node->memtype) /* untiled */ break; /* fallthrough, tiled memory */ -- cgit v0.10.2 From 6c3d713e6d32706999689e379a9098afb4cd8a2c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:54 +0100 Subject: ASoC: ad193x: Split SPI and I2C code into different modules There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register? Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus, allows the registration of the other bus driver to continue without problems if one of them fails. This patch splits the AD193X driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8..3591367 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -68,7 +68,8 @@ config SND_BF5XX_SOC_AD193X tristate "SoC AD193X Audio support for Blackfin" depends on SND_BF5XX_I2S select SND_BF5XX_SOC_I2S - select SND_SOC_AD193X + select SND_SOC_AD193X_I2C if I2C + select SND_SOC_AD193X_SPI if SPI_MASTER help Say Y if you want to add support for AD193X codec on Blackfin. This driver supports AD1936, AD1937, AD1938 and AD1939. diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087a..d7da619 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -16,7 +16,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_AB8500_CODEC if ABX500_CORE select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1836 if SPI_MASTER - select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI + select SND_SOC_AD193X_SPI if SPI_MASTER + select SND_SOC_AD193X_I2C if I2C select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 select SND_SOC_ADAU1373 if I2C @@ -182,6 +183,14 @@ config SND_SOC_AD1836 config SND_SOC_AD193X tristate +config SND_SOC_AD193X_SPI + tristate + select SND_SOC_AD193X + +config SND_SOC_AD193X_I2C + tristate + select SND_SOC_AD193X + config SND_SOC_AD1980 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc12676..7795e37 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -3,6 +3,8 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o snd-soc-ac97-objs := ac97.o snd-soc-ad1836-objs := ad1836.o snd-soc-ad193x-objs := ad193x.o +snd-soc-ad193x-spi-objs := ad193x-spi.o +snd-soc-ad193x-i2c-objs := ad193x-i2c.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o @@ -134,6 +136,8 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o +obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o +obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c new file mode 100644 index 0000000..df3a1a4 --- /dev/null +++ b/sound/soc/codecs/ad193x-i2c.c @@ -0,0 +1,54 @@ +/* + * AD1936/AD1937 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ad193x.h" + +static const struct i2c_device_id ad193x_id[] = { + { "ad1936", 0 }, + { "ad1937", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad193x_id); + +static int ad193x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 8; + + return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); +} + +static int ad193x_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static struct i2c_driver ad193x_i2c_driver = { + .driver = { + .name = "ad193x", + }, + .probe = ad193x_i2c_probe, + .remove = ad193x_i2c_remove, + .id_table = ad193x_id, +}; +module_i2c_driver(ad193x_i2c_driver); + +MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c new file mode 100644 index 0000000..390cef9 --- /dev/null +++ b/sound/soc/codecs/ad193x-spi.c @@ -0,0 +1,48 @@ +/* + * AD1938/AD1939 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ad193x.h" + +static int ad193x_spi_probe(struct spi_device *spi) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 16; + config.read_flag_mask = 0x09; + config.write_flag_mask = 0x08; + + return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); +} + +static int ad193x_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver ad193x_spi_driver = { + .driver = { + .name = "ad193x", + .owner = THIS_MODULE, + }, + .probe = ad193x_spi_probe, + .remove = ad193x_spi_remove, +}; +module_spi_driver(ad193x_spi_driver); + +MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 5a42dca..f644a34 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -6,12 +6,10 @@ * Licensed under the GPL-2 or later. */ -#include #include #include #include -#include -#include +#include #include #include #include @@ -19,6 +17,7 @@ #include #include #include + #include "ad193x.h" /* codec private data */ @@ -320,7 +319,7 @@ static struct snd_soc_dai_driver ad193x_dai = { .ops = &ad193x_dai_ops, }; -static int ad193x_probe(struct snd_soc_codec *codec) +static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); int ret; @@ -352,7 +351,7 @@ static int ad193x_probe(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_ad193x = { - .probe = ad193x_probe, + .probe = ad193x_codec_probe, .controls = ad193x_snd_controls, .num_controls = ARRAY_SIZE(ad193x_snd_controls), .dapm_widgets = ad193x_dapm_widgets, @@ -366,140 +365,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) return false; } -#if defined(CONFIG_SPI_MASTER) - -static const struct regmap_config ad193x_spi_regmap_config = { - .val_bits = 8, - .reg_bits = 16, - .read_flag_mask = 0x09, - .write_flag_mask = 0x08, - +const struct regmap_config ad193x_regmap_config = { .max_register = AD193X_NUM_REGS - 1, .volatile_reg = adau193x_reg_volatile, }; +EXPORT_SYMBOL_GPL(ad193x_regmap_config); -static int ad193x_spi_probe(struct spi_device *spi) +int ad193x_probe(struct device *dev, struct regmap *regmap) { struct ad193x_priv *ad193x; - ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); - if (ad193x == NULL) - return -ENOMEM; - - ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - spi_set_drvdata(spi, ad193x); - - return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ad193x_spi_driver = { - .driver = { - .name = "ad193x", - .owner = THIS_MODULE, - }, - .probe = ad193x_spi_probe, - .remove = ad193x_spi_remove, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) - -static const struct regmap_config ad193x_i2c_regmap_config = { - .val_bits = 8, - .reg_bits = 8, - - .max_register = AD193X_NUM_REGS - 1, - .volatile_reg = adau193x_reg_volatile, -}; - -static const struct i2c_device_id ad193x_id[] = { - { "ad1936", 0 }, - { "ad1937", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad193x_id); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); -static int ad193x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ad193x_priv *ad193x; - - ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); + ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - i2c_set_clientdata(client, ad193x); - - return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} + ad193x->regmap = regmap; -static struct i2c_driver ad193x_i2c_driver = { - .driver = { - .name = "ad193x", - }, - .probe = ad193x_i2c_probe, - .remove = ad193x_i2c_remove, - .id_table = ad193x_id, -}; -#endif - -static int __init ad193x_modinit(void) -{ - int ret; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&ad193x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", - ret); - } -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ad193x_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(ad193x_modinit); - -static void __exit ad193x_modexit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ad193x_spi_driver); -#endif + dev_set_drvdata(dev, ad193x); -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&ad193x_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } -module_exit(ad193x_modexit); +EXPORT_SYMBOL_GPL(ad193x_probe); MODULE_DESCRIPTION("ASoC ad193x driver"); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 4733880..ab9a998 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -9,6 +9,13 @@ #ifndef __AD193X_H__ #define __AD193X_H__ +#include + +struct device; + +extern const struct regmap_config ad193x_regmap_config; +int ad193x_probe(struct device *dev, struct regmap *regmap); + #define AD193X_PLL_CLK_CTRL0 0x00 #define AD193X_PLL_POWERDOWN 0x01 #define AD193X_PLL_INPUT_MASK 0x6 -- cgit v0.10.2 From c924dc68f7371582cb420c003faadb700cd4f76c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:53 +0100 Subject: ASoC: ssm2602: Split SPI and I2C code into different modules There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register? Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus allows the registration of the other bus driver to continue without problems if one of them fails. This patch splits the ssm2602 driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. While we are at it also cleanup the include section of the ssm2602 driver and remove unneeded includes. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8..f9118dc 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -14,7 +14,8 @@ config SND_BF5XX_SOC_SSM2602 depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) select SND_BF5XX_SOC_I2S if !BF60x select SND_BF6XX_SOC_I2S if BF60x - select SND_SOC_SSM2602 + select SND_SOC_SSM2602_SPI if SPI_MASTER + select SND_SOC_SSM2602_I2C if I2C help Say Y if you want to add support for the Analog Devices SSM2602 Audio Codec Add-On Card. diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087a..f17e6da 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -66,7 +66,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF select SND_SOC_SSM2518 if I2C - select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI + select SND_SOC_SSM2602_SPI if SPI_MASTER + select SND_SOC_SSM2602_I2C if I2C select SND_SOC_STA32X if I2C select SND_SOC_STA529 if I2C select SND_SOC_STAC9766 if SND_SOC_AC97_BUS @@ -342,6 +343,14 @@ config SND_SOC_SSM2518 config SND_SOC_SSM2602 tristate +config SND_SOC_SSM2602_SPI + select SND_SOC_SSM2602 + tristate + +config SND_SOC_SSM2602_I2C + select SND_SOC_SSM2602 + tristate + config SND_SOC_STA32X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc12676..e7a2fb9 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -58,6 +58,8 @@ snd-soc-spdif-tx-objs := spdif_transmitter.o snd-soc-spdif-rx-objs := spdif_receiver.o snd-soc-ssm2518-objs := ssm2518.o snd-soc-ssm2602-objs := ssm2602.o +snd-soc-ssm2602-spi-objs := ssm2602-spi.o +snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o snd-soc-sta32x-objs := sta32x.o snd-soc-sta529-objs := sta529.o snd-soc-stac9766-objs := stac9766.o @@ -188,6 +190,8 @@ obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o +obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o +obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c new file mode 100644 index 0000000..abd63d5 --- /dev/null +++ b/sound/soc/codecs/ssm2602-i2c.c @@ -0,0 +1,57 @@ +/* + * SSM2602/SSM2603/SSM2604 I2C audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ssm2602.h" + +/* + * ssm2602 2 wire address is determined by GPIO5 + * state during powerup. + * low = 0x1a + * high = 0x1b + */ +static int ssm2602_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return ssm2602_probe(&client->dev, id->driver_data, + devm_regmap_init_i2c(client, &ssm2602_regmap_config)); +} + +static int ssm2602_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id ssm2602_i2c_id[] = { + { "ssm2602", SSM2602 }, + { "ssm2603", SSM2602 }, + { "ssm2604", SSM2604 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); + +static struct i2c_driver ssm2602_i2c_driver = { + .driver = { + .name = "ssm2602", + .owner = THIS_MODULE, + }, + .probe = ssm2602_i2c_probe, + .remove = ssm2602_i2c_remove, + .id_table = ssm2602_i2c_id, +}; +module_i2c_driver(ssm2602_i2c_driver); + +MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 I2C driver"); +MODULE_AUTHOR("Cliff Cai"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c new file mode 100644 index 0000000..2bf55e2 --- /dev/null +++ b/sound/soc/codecs/ssm2602-spi.c @@ -0,0 +1,41 @@ +/* + * SSM2602 SPI audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ssm2602.h" + +static int ssm2602_spi_probe(struct spi_device *spi) +{ + return ssm2602_probe(&spi->dev, SSM2602, + devm_regmap_init_spi(spi, &ssm2602_regmap_config)); +} + +static int ssm2602_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver ssm2602_spi_driver = { + .driver = { + .name = "ssm2602", + .owner = THIS_MODULE, + }, + .probe = ssm2602_spi_probe, + .remove = ssm2602_spi_remove, +}; +module_spi_driver(ssm2602_spi_driver); + +MODULE_DESCRIPTION("ASoC SSM2602 SPI driver"); +MODULE_AUTHOR("Cliff Cai"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index f444d58..49d28ea 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -27,28 +27,16 @@ */ #include -#include -#include -#include -#include -#include -#include #include #include -#include + #include #include #include -#include #include #include "ssm2602.h" -enum ssm2602_type { - SSM2602, - SSM2604, -}; - /* codec private data */ struct ssm2602_priv { unsigned int sysclk; @@ -529,7 +517,7 @@ static int ssm2602_resume(struct snd_soc_codec *codec) return 0; } -static int ssm2602_probe(struct snd_soc_codec *codec) +static int ssm2602_codec_probe(struct snd_soc_codec *codec) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; @@ -554,7 +542,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec) ARRAY_SIZE(ssm2602_routes)); } -static int ssm2604_probe(struct snd_soc_codec *codec) +static int ssm2604_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; @@ -568,7 +556,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec) ARRAY_SIZE(ssm2604_routes)); } -static int ssm260x_probe(struct snd_soc_codec *codec) +static int ssm260x_codec_probe(struct snd_soc_codec *codec) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret; @@ -597,10 +585,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec) switch (ssm2602->type) { case SSM2602: - ret = ssm2602_probe(codec); + ret = ssm2602_codec_probe(codec); break; case SSM2604: - ret = ssm2604_probe(codec); + ret = ssm2604_codec_probe(codec); break; } @@ -620,7 +608,7 @@ static int ssm2602_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { - .probe = ssm260x_probe, + .probe = ssm260x_codec_probe, .remove = ssm2602_remove, .suspend = ssm2602_suspend, .resume = ssm2602_resume, @@ -639,7 +627,7 @@ static bool ssm2602_register_volatile(struct device *dev, unsigned int reg) return reg == SSM2602_RESET; } -static const struct regmap_config ssm2602_regmap_config = { +const struct regmap_config ssm2602_regmap_config = { .val_bits = 9, .reg_bits = 7, @@ -650,134 +638,28 @@ static const struct regmap_config ssm2602_regmap_config = { .reg_defaults_raw = ssm2602_reg, .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), }; +EXPORT_SYMBOL_GPL(ssm2602_regmap_config); -#if defined(CONFIG_SPI_MASTER) -static int ssm2602_spi_probe(struct spi_device *spi) +int ssm2602_probe(struct device *dev, enum ssm2602_type type, + struct regmap *regmap) { struct ssm2602_priv *ssm2602; - int ret; - - ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); - if (ssm2602 == NULL) - return -ENOMEM; - - spi_set_drvdata(spi, ssm2602); - ssm2602->type = SSM2602; - - ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config); - if (IS_ERR(ssm2602->regmap)) - return PTR_ERR(ssm2602->regmap); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} -static int ssm2602_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ssm2602_spi_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_spi_probe, - .remove = ssm2602_spi_remove, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) -/* - * ssm2602 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ -static int ssm2602_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ssm2602_priv *ssm2602; - int ret; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); + ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL); if (ssm2602 == NULL) return -ENOMEM; - i2c_set_clientdata(i2c, ssm2602); - ssm2602->type = id->driver_data; - - ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config); - if (IS_ERR(ssm2602->regmap)) - return PTR_ERR(ssm2602->regmap); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} - -static int ssm2602_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id ssm2602_i2c_id[] = { - { "ssm2602", SSM2602 }, - { "ssm2603", SSM2602 }, - { "ssm2604", SSM2604 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); - -/* corgi i2c codec control layer */ -static struct i2c_driver ssm2602_i2c_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_i2c_probe, - .remove = ssm2602_i2c_remove, - .id_table = ssm2602_i2c_id, -}; -#endif - - -static int __init ssm2602_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ssm2602_spi_driver); - if (ret) - return ret; -#endif - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&ssm2602_i2c_driver); - if (ret) - return ret; -#endif - - return ret; -} -module_init(ssm2602_modinit); - -static void __exit ssm2602_exit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ssm2602_spi_driver); -#endif + dev_set_drvdata(dev, ssm2602); + ssm2602->type = SSM2602; + ssm2602->regmap = regmap; -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&ssm2602_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_ssm2602, + &ssm2602_dai, 1); } -module_exit(ssm2602_exit); +EXPORT_SYMBOL_GPL(ssm2602_probe); MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); MODULE_AUTHOR("Cliff Cai"); diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index fbd07d7..7475388 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h @@ -28,6 +28,20 @@ #ifndef _SSM2602_H #define _SSM2602_H +#include + +struct device; + +enum ssm2602_type { + SSM2602, + SSM2604, +}; + +extern const struct regmap_config ssm2602_regmap_config; + +int ssm2602_probe(struct device *dev, enum ssm2602_type type, + struct regmap *regmap); + /* SSM2602 Codec Register definitions */ #define SSM2602_LINVOL 0x00 -- cgit v0.10.2 From f96a5d3f1c09ce85ac1a90d733ca3585b9f2f70a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:55 +0100 Subject: ASoC: adav80x: Use devm_kzalloc() Use devm_kzalloc() to allocate the device state struct. Saves use from having to free it manually on the error path and in the remove callback. Now that the adav80x_bus_probe() function is only a call to snd_soc_unregister_codec() also inline that. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a..a4bd051 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -872,27 +872,15 @@ static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) if (IS_ERR(regmap)) return PTR_ERR(regmap); - adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); + adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL); if (!adav80x) return -ENOMEM; - dev_set_drvdata(dev, adav80x); adav80x->regmap = regmap; - ret = snd_soc_register_codec(dev, &adav80x_codec_driver, + return snd_soc_register_codec(dev, &adav80x_codec_driver, adav80x_dais, ARRAY_SIZE(adav80x_dais)); - if (ret) - kfree(adav80x); - - return ret; -} - -static int adav80x_bus_remove(struct device *dev) -{ - snd_soc_unregister_codec(dev); - kfree(dev_get_drvdata(dev)); - return 0; } #if defined(CONFIG_SPI_MASTER) @@ -923,7 +911,8 @@ static int adav80x_spi_probe(struct spi_device *spi) static int adav80x_spi_remove(struct spi_device *spi) { - return adav80x_bus_remove(&spi->dev); + snd_soc_unregister_codec(dev); + return 0; } static struct spi_driver adav80x_spi_driver = { @@ -965,7 +954,8 @@ static int adav80x_i2c_probe(struct i2c_client *client, static int adav80x_i2c_remove(struct i2c_client *client) { - return adav80x_bus_remove(&client->dev); + snd_soc_unregister_codec(dev); + return 0; } static struct i2c_driver adav80x_i2c_driver = { -- cgit v0.10.2 From 0c2d6964562835501280409cac5d4ee28e07e8c2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:56 +0100 Subject: ASoC: adav80x: Split SPI and I2C code into different modules There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register. Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus, allows the registration of the other bus drive to continue without problems if one of them fails. This patch splits the ADAV80X driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8..18abd88 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -47,7 +47,8 @@ config SND_SOC_BFIN_EVAL_ADAV80X tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) select SND_BF5XX_SOC_I2S - select SND_SOC_ADAV80X + select SND_SOC_ADAV801 if SPI_MASTER + select SND_SOC_ADAV803 if I2C help Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or EVAL-ADAV803 board connected to one of the Blackfin evaluation boards diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087a..9556321 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -20,7 +20,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 select SND_SOC_ADAU1373 if I2C - select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI + select SND_SOC_ADAV801 if SPI_MASTER + select SND_SOC_ADAV803 if I2C select SND_SOC_ADAU1701 if I2C select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER @@ -198,6 +199,14 @@ config SND_SOC_ADAU1373 config SND_SOC_ADAV80X tristate +config SND_SOC_ADAV801 + tristate + select SND_SOC_ADAV80X + +config SND_SOC_ADAV803 + tristate + select SND_SOC_ADAV80X + config SND_SOC_ADS117X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc12676..1b2c6ec 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -8,6 +8,8 @@ snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau1373-objs := adau1373.o snd-soc-adav80x-objs := adav80x.o +snd-soc-adav801-objs := adav801.o +snd-soc-adav803-objs := adav803.o snd-soc-ads117x-objs := ads117x.o snd-soc-ak4104-objs := ak4104.o snd-soc-ak4535-objs := ak4535.o @@ -139,6 +141,8 @@ obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o +obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o +obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o diff --git a/sound/soc/codecs/adav801.c b/sound/soc/codecs/adav801.c new file mode 100644 index 0000000..790fce3 --- /dev/null +++ b/sound/soc/codecs/adav801.c @@ -0,0 +1,53 @@ +/* + * ADAV801 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "adav80x.h" + +static const struct spi_device_id adav80x_spi_id[] = { + { "adav801", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adav80x_spi_id); + +static int adav80x_spi_probe(struct spi_device *spi) +{ + struct regmap_config config; + + config = adav80x_regmap_config; + config.read_flag_mask = 0x01; + + return adav80x_bus_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); +} + +static int adav80x_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver adav80x_spi_driver = { + .driver = { + .name = "adav801", + .owner = THIS_MODULE, + }, + .probe = adav80x_spi_probe, + .remove = adav80x_spi_remove, + .id_table = adav80x_spi_id, +}; +module_spi_driver(adav80x_spi_driver); + +MODULE_DESCRIPTION("ASoC ADAV801 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_AUTHOR("Yi Li >"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c new file mode 100644 index 0000000..66d9fce --- /dev/null +++ b/sound/soc/codecs/adav803.c @@ -0,0 +1,50 @@ +/* + * ADAV803 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "adav80x.h" + +static const struct i2c_device_id adav803_id[] = { + { "adav803", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adav803_id); + +static int adav803_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return adav80x_bus_probe(&client->dev, + devm_regmap_init_i2c(client, &adav80x_regmap_config)); +} + +static int adav803_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static struct i2c_driver adav803_driver = { + .driver = { + .name = "adav803", + .owner = THIS_MODULE, + }, + .probe = adav803_probe, + .remove = adav803_remove, + .id_table = adav803_id, +}; +module_i2c_driver(adav803_driver); + +MODULE_DESCRIPTION("ASoC ADAV803 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_AUTHOR("Yi Li >"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index a4bd051..09d5609 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -8,17 +8,15 @@ * Licensed under the GPL-2 or later. */ -#include #include #include -#include -#include +#include #include -#include + #include #include -#include #include +#include #include "adav80x.h" @@ -864,10 +862,9 @@ static struct snd_soc_codec_driver adav80x_codec_driver = { .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), }; -static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) +int adav80x_bus_probe(struct device *dev, struct regmap *regmap) { struct adav80x *adav80x; - int ret; if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -882,9 +879,9 @@ static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) return snd_soc_register_codec(dev, &adav80x_codec_driver, adav80x_dais, ARRAY_SIZE(adav80x_dais)); } +EXPORT_SYMBOL_GPL(adav80x_bus_probe); -#if defined(CONFIG_SPI_MASTER) -static const struct regmap_config adav80x_spi_regmap_config = { +const struct regmap_config adav80x_regmap_config = { .val_bits = 8, .pad_bits = 1, .reg_bits = 7, @@ -896,107 +893,7 @@ static const struct regmap_config adav80x_spi_regmap_config = { .reg_defaults = adav80x_reg_defaults, .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), }; - -static const struct spi_device_id adav80x_spi_id[] = { - { "adav801", 0 }, - { } -}; -MODULE_DEVICE_TABLE(spi, adav80x_spi_id); - -static int adav80x_spi_probe(struct spi_device *spi) -{ - return adav80x_bus_probe(&spi->dev, - devm_regmap_init_spi(spi, &adav80x_spi_regmap_config)); -} - -static int adav80x_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(dev); - return 0; -} - -static struct spi_driver adav80x_spi_driver = { - .driver = { - .name = "adav801", - .owner = THIS_MODULE, - }, - .probe = adav80x_spi_probe, - .remove = adav80x_spi_remove, - .id_table = adav80x_spi_id, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) -static const struct regmap_config adav80x_i2c_regmap_config = { - .val_bits = 8, - .pad_bits = 1, - .reg_bits = 7, - - .max_register = ADAV80X_PLL_OUTE, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = adav80x_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), -}; - -static const struct i2c_device_id adav80x_i2c_id[] = { - { "adav803", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id); - -static int adav80x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return adav80x_bus_probe(&client->dev, - devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config)); -} - -static int adav80x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(dev); - return 0; -} - -static struct i2c_driver adav80x_i2c_driver = { - .driver = { - .name = "adav803", - .owner = THIS_MODULE, - }, - .probe = adav80x_i2c_probe, - .remove = adav80x_i2c_remove, - .id_table = adav80x_i2c_id, -}; -#endif - -static int __init adav80x_init(void) -{ - int ret = 0; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&adav80x_i2c_driver); - if (ret) - return ret; -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&adav80x_spi_driver); -#endif - - return ret; -} -module_init(adav80x_init); - -static void __exit adav80x_exit(void) -{ -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&adav80x_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&adav80x_spi_driver); -#endif -} -module_exit(adav80x_exit); +EXPORT_SYMBOL_GPL(adav80x_regmap_config); MODULE_DESCRIPTION("ASoC ADAV80x driver"); MODULE_AUTHOR("Lars-Peter Clausen "); diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h index adb0fc7..8a1d7c0 100644 --- a/sound/soc/codecs/adav80x.h +++ b/sound/soc/codecs/adav80x.h @@ -9,6 +9,13 @@ #ifndef _ADAV80X_H #define _ADAV80X_H +#include + +struct device; + +extern const struct regmap_config adav80x_regmap_config; +int adav80x_bus_probe(struct device *dev, struct regmap *regmap); + enum adav80x_pll_src { ADAV80X_PLL_SRC_XIN, ADAV80X_PLL_SRC_XTAL, -- cgit v0.10.2 From 92e3b40537707001d17bbad800d150ab04e53bf4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Feb 2014 20:33:01 -0500 Subject: jbd2: fix use after free in jbd2_journal_start_reserved() If start_this_handle() fails then it leads to a use after free of "handle". Signed-off-by: Dan Carpenter Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 8360674..60bb365 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -514,11 +514,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type, * similarly constrained call sites */ ret = start_this_handle(journal, handle, GFP_NOFS); - if (ret < 0) + if (ret < 0) { jbd2_journal_free_reserved(handle); + return ret; + } handle->h_type = type; handle->h_line_no = line_no; - return ret; + return 0; } EXPORT_SYMBOL(jbd2_journal_start_reserved); -- cgit v0.10.2 From 45a22f4c11fef4ecd5c61c0a299cd3f23d77be8e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 17 Feb 2014 13:09:50 +0100 Subject: inotify: Fix reporting of cookies for inotify events My rework of handling of notification events (namely commit 7053aee26a35 "fsnotify: do not share events between notification groups") broke sending of cookies with inotify events. We didn't propagate the value passed to fsnotify() properly and passed 4 uninitialized bytes to userspace instead (so it is also an information leak). Sadly I didn't notice this during my testing because inotify cookies aren't used very much and LTP inotify tests ignore them. Fix the problem by passing the cookie value properly. Fixes: 7053aee26a3548ebaba046ae2e52396ccf56ac6c Reported-by: Vegard Nossum Signed-off-by: Jan Kara diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 0b9ff43..abc8cbc 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -86,7 +86,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, u32 mask, void *data, int data_type, - const unsigned char *file_name) + const unsigned char *file_name, u32 cookie) { struct dnotify_mark *dn_mark; struct dnotify_struct *dn; diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 0e792f5..205dc21 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -147,7 +147,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_mark *inode_mark, struct fsnotify_mark *fanotify_mark, u32 mask, void *data, int data_type, - const unsigned char *file_name) + const unsigned char *file_name, u32 cookie) { int ret = 0; struct fanotify_event_info *event; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 1d4e1ea..9d3e9c5 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -179,7 +179,7 @@ static int send_to_group(struct inode *to_tell, return group->ops->handle_event(group, to_tell, inode_mark, vfsmount_mark, mask, data, data_is, - file_name); + file_name, cookie); } /* diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index 485eef3..ed855ef 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h @@ -27,6 +27,6 @@ extern int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, u32 mask, void *data, int data_type, - const unsigned char *file_name); + const unsigned char *file_name, u32 cookie); extern const struct fsnotify_ops inotify_fsnotify_ops; diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index d5ee563..43ab1e1 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -67,7 +67,7 @@ int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, u32 mask, void *data, int data_type, - const unsigned char *file_name) + const unsigned char *file_name, u32 cookie) { struct inotify_inode_mark *i_mark; struct inotify_event_info *event; @@ -103,6 +103,7 @@ int inotify_handle_event(struct fsnotify_group *group, fsn_event = &event->fse; fsnotify_init_event(fsn_event, inode, mask); event->wd = i_mark->wd; + event->sync_cookie = cookie; event->name_len = len; if (len) strcpy(event->name, file_name); diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 497395c..6528b5a 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -495,7 +495,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, /* Queue ignore event for the watch */ inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED, - NULL, FSNOTIFY_EVENT_NONE, NULL); + NULL, FSNOTIFY_EVENT_NONE, NULL, 0); i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); /* remove this mark from the idr */ diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 3d286ff..c84bc7c 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -99,7 +99,7 @@ struct fsnotify_ops { struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, u32 mask, void *data, int data_type, - const unsigned char *file_name); + const unsigned char *file_name, u32 cookie); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); void (*free_event)(struct fsnotify_event *event); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 67ccf0e..135944a 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -916,7 +916,7 @@ static int audit_tree_handle_event(struct fsnotify_group *group, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, u32 mask, void *data, int data_type, - const unsigned char *file_name) + const unsigned char *file_name, u32 cookie) { return 0; } diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 2596fac..70b4554 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -471,7 +471,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, u32 mask, void *data, int data_type, - const unsigned char *dname) + const unsigned char *dname, u32 cookie) { struct inode *inode; struct audit_parent *parent; -- cgit v0.10.2 From 26c17a1c56f957560cb96d219c13d21dfb605819 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Fri, 14 Feb 2014 10:04:00 +0000 Subject: iio: cm36651: Fix read/write integration time function. This patch is fixed [read/write] integration time function. cm36651 have integration time from 1 to 640 milliseconds. But, print more then the thousand second. when call *_integration_time attribute. Because read_integration_time function return IIO_VAL_INT. read integration time function is changed return IIO_VAL_INT_PLUS_MICRO; And then .write_raw_get_fmt callback function for parse a fixed-point number from a string. Some description is revised milliseconds unit. v2: cm36651_write_int_time function fixed as it was. Signed-off-by: Beomho Seo Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 0a142af..a45e074 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -50,10 +50,10 @@ #define CM36651_CS_CONF2_DEFAULT_BIT 0x08 /* CS_CONF3 channel integration time */ -#define CM36651_CS_IT1 0x00 /* Integration time 80000 usec */ -#define CM36651_CS_IT2 0x40 /* Integration time 160000 usec */ -#define CM36651_CS_IT3 0x80 /* Integration time 320000 usec */ -#define CM36651_CS_IT4 0xC0 /* Integration time 640000 usec */ +#define CM36651_CS_IT1 0x00 /* Integration time 80 msec */ +#define CM36651_CS_IT2 0x40 /* Integration time 160 msec */ +#define CM36651_CS_IT3 0x80 /* Integration time 320 msec */ +#define CM36651_CS_IT4 0xC0 /* Integration time 640 msec */ /* PS_CONF1 command code */ #define CM36651_PS_ENABLE 0x00 @@ -64,10 +64,10 @@ #define CM36651_PS_PERS4 0x0C /* PS_CONF1 command code: integration time */ -#define CM36651_PS_IT1 0x00 /* Integration time 320 usec */ -#define CM36651_PS_IT2 0x10 /* Integration time 420 usec */ -#define CM36651_PS_IT3 0x20 /* Integration time 520 usec */ -#define CM36651_PS_IT4 0x30 /* Integration time 640 usec */ +#define CM36651_PS_IT1 0x00 /* Integration time 0.32 msec */ +#define CM36651_PS_IT2 0x10 /* Integration time 0.42 msec */ +#define CM36651_PS_IT3 0x20 /* Integration time 0.52 msec */ +#define CM36651_PS_IT4 0x30 /* Integration time 0.64 msec */ /* PS_CONF1 command code: duty ratio */ #define CM36651_PS_DR1 0x00 /* Duty ratio 1/80 */ @@ -93,8 +93,8 @@ #define CM36651_CLOSE_PROXIMITY 0x32 #define CM36651_FAR_PROXIMITY 0x33 -#define CM36651_CS_INT_TIME_AVAIL "80000 160000 320000 640000" -#define CM36651_PS_INT_TIME_AVAIL "320 420 520 640" +#define CM36651_CS_INT_TIME_AVAIL "0.08 0.16 0.32 0.64" +#define CM36651_PS_INT_TIME_AVAIL "0.000320 0.000420 0.000520 0.000640" enum cm36651_operation_mode { CM36651_LIGHT_EN, @@ -356,30 +356,30 @@ static int cm36651_read_channel(struct cm36651_data *cm36651, } static int cm36651_read_int_time(struct cm36651_data *cm36651, - struct iio_chan_spec const *chan, int *val) + struct iio_chan_spec const *chan, int *val2) { switch (chan->type) { case IIO_LIGHT: if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT1) - *val = 80000; + *val2 = 80000; else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT2) - *val = 160000; + *val2 = 160000; else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT3) - *val = 320000; + *val2 = 320000; else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT4) - *val = 640000; + *val2 = 640000; else return -EINVAL; break; case IIO_PROXIMITY: if (cm36651->ps_int_time == CM36651_PS_IT1) - *val = 320; + *val2 = 320; else if (cm36651->ps_int_time == CM36651_PS_IT2) - *val = 420; + *val2 = 420; else if (cm36651->ps_int_time == CM36651_PS_IT3) - *val = 520; + *val2 = 520; else if (cm36651->ps_int_time == CM36651_PS_IT4) - *val = 640; + *val2 = 640; else return -EINVAL; break; @@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651, return -EINVAL; } - return IIO_VAL_INT; + return IIO_VAL_INT_PLUS_MICRO; } static int cm36651_write_int_time(struct cm36651_data *cm36651, @@ -459,7 +459,8 @@ static int cm36651_read_raw(struct iio_dev *indio_dev, ret = cm36651_read_channel(cm36651, chan, val); break; case IIO_CHAN_INFO_INT_TIME: - ret = cm36651_read_int_time(cm36651, chan, val); + *val = 0; + ret = cm36651_read_int_time(cm36651, chan, val2); break; default: ret = -EINVAL; @@ -479,7 +480,7 @@ static int cm36651_write_raw(struct iio_dev *indio_dev, int ret = -EINVAL; if (mask == IIO_CHAN_INFO_INT_TIME) { - ret = cm36651_write_int_time(cm36651, chan, val); + ret = cm36651_write_int_time(cm36651, chan, val2); if (ret < 0) dev_err(&client->dev, "Integration time write failed\n"); } -- cgit v0.10.2 From 1463a166b4eafc654874528ba5e2f66dbdfb8048 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Fri, 14 Feb 2014 10:04:00 +0000 Subject: iio: cm32181: Change cm32181 ambient light sensor driver Integration time of cm32181 is guessed about milliseconds. But cm32181_read_als_it function return IIO_VAL_INT. So fixed to return IIO_VAL_INT_PLUS_MICRO. Next, add .write_raw_get_fmt callback function for call iio_str_to_fixpoint. v2: cm32181_write_als_id function fixed as it was. Cc: Kevin Tsai Signed-off-by: Beomho Seo Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index f17b4e6..47a6dba 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -103,13 +103,13 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181) /** * cm32181_read_als_it() - Get sensor integration time (ms) * @cm32181: pointer of struct cm32181 - * @val: pointer of int to load the als_it value. + * @val2: pointer of int to load the als_it value. * * Report the current integartion time by millisecond. * - * Return: IIO_VAL_INT for success, otherwise -EINVAL. + * Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL. */ -static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val) +static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2) { u16 als_it; int i; @@ -119,8 +119,8 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val) als_it >>= CM32181_CMD_ALS_IT_SHIFT; for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) { if (als_it == als_it_bits[i]) { - *val = als_it_value[i]; - return IIO_VAL_INT; + *val2 = als_it_value[i]; + return IIO_VAL_INT_PLUS_MICRO; } } @@ -221,7 +221,7 @@ static int cm32181_read_raw(struct iio_dev *indio_dev, *val = cm32181->calibscale; return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME: - ret = cm32181_read_als_it(cm32181, val); + ret = cm32181_read_als_it(cm32181, val2); return ret; } @@ -240,7 +240,7 @@ static int cm32181_write_raw(struct iio_dev *indio_dev, cm32181->calibscale = val; return val; case IIO_CHAN_INFO_INT_TIME: - ret = cm32181_write_als_it(cm32181, val); + ret = cm32181_write_als_it(cm32181, val2); return ret; } @@ -264,7 +264,7 @@ static ssize_t cm32181_get_it_available(struct device *dev, n = ARRAY_SIZE(als_it_value); for (i = 0, len = 0; i < n; i++) - len += sprintf(buf + len, "%d ", als_it_value[i]); + len += sprintf(buf + len, "0.%06u ", als_it_value[i]); return len + sprintf(buf + len, "\n"); } -- cgit v0.10.2 From a0657716416f834ef7710a9044614d50a36c3bdc Mon Sep 17 00:00:00 2001 From: Denis CIOCCA Date: Fri, 14 Feb 2014 14:15:00 +0000 Subject: iio:gyro: bug on L3GD20H gyroscope support The driver was not able to manage the sensor: during probe function and wai check, the driver stops and writes: "device name and WhoAmI mismatch." The correct value of L3GD20H wai is 0xd7 instead of 0xd4. Dropped support for the sensor. Signed-off-by: Denis Ciocca Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 41c64a4..ac2d69e 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -70,7 +70,7 @@ config IIO_ST_GYRO_3AXIS select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) help Say yes here to build support for STMicroelectronics gyroscopes: - L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330. + L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330. This driver can also be built as a module. If so, these modules will be created: diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index f8f2bf8..c197360 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -19,7 +19,6 @@ #define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro" #define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro" #define L3GD20_GYRO_DEV_NAME "l3gd20" -#define L3GD20H_GYRO_DEV_NAME "l3gd20h" #define L3G4IS_GYRO_DEV_NAME "l3g4is_ui" #define LSM330_GYRO_DEV_NAME "lsm330_gyro" diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index d53d91a..a8e174a 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -167,11 +167,10 @@ static const struct st_sensors st_gyro_sensors[] = { .wai = ST_GYRO_2_WAI_EXP, .sensors_supported = { [0] = L3GD20_GYRO_DEV_NAME, - [1] = L3GD20H_GYRO_DEV_NAME, - [2] = LSM330D_GYRO_DEV_NAME, - [3] = LSM330DLC_GYRO_DEV_NAME, - [4] = L3G4IS_GYRO_DEV_NAME, - [5] = LSM330_GYRO_DEV_NAME, + [1] = LSM330D_GYRO_DEV_NAME, + [2] = LSM330DLC_GYRO_DEV_NAME, + [3] = L3G4IS_GYRO_DEV_NAME, + [4] = LSM330_GYRO_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 16b8b8d..23c12f3 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -55,7 +55,6 @@ static const struct i2c_device_id st_gyro_id_table[] = { { LSM330DL_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME }, - { L3GD20H_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, {}, diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index 94763e2..b4ad3be 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -54,7 +54,6 @@ static const struct spi_device_id st_gyro_id_table[] = { { LSM330DL_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME }, - { L3GD20H_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, {}, -- cgit v0.10.2 From 63edea16b7fea3e422e63e218c9e7349b2d0a63b Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Sun, 16 Feb 2014 20:10:55 +0100 Subject: dma: sdma: Add imx25 compatible imx25 did not work without a firmware previously. This patch adds a DT compatible to pass the correct data with the default script addresses for imx25. Add imx25 compatible to the list of compatibles in the binding documentation. Signed-off-by: Markus Pargmann Acked-by: Shawn Guo Signed-off-by: Vinod Koul diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt index 68b83ec..ee9be99 100644 --- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt @@ -1,12 +1,16 @@ * Freescale Smart Direct Memory Access (SDMA) Controller for i.MX Required properties: -- compatible : Should be "fsl,imx31-sdma", "fsl,imx31-to1-sdma", - "fsl,imx31-to2-sdma", "fsl,imx35-sdma", "fsl,imx35-to1-sdma", - "fsl,imx35-to2-sdma", "fsl,imx51-sdma", "fsl,imx53-sdma" or - "fsl,imx6q-sdma". The -to variants should be preferred since they - allow to determnine the correct ROM script addresses needed for - the driver to work without additional firmware. +- compatible : Should be one of + "fsl,imx25-sdma" + "fsl,imx31-sdma", "fsl,imx31-to1-sdma", "fsl,imx31-to2-sdma" + "fsl,imx35-sdma", "fsl,imx35-to1-sdma", "fsl,imx35-to2-sdma" + "fsl,imx51-sdma" + "fsl,imx53-sdma" + "fsl,imx6q-sdma" + The -to variants should be preferred since they allow to determnine the + correct ROM script addresses needed for the driver to work without additional + firmware. - reg : Should contain SDMA registers location and length - interrupts : Should contain SDMA interrupt - #dma-cells : Must be <3>. diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 4e79183..19041ce 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -449,6 +449,7 @@ static const struct of_device_id sdma_dt_ids[] = { { .compatible = "fsl,imx51-sdma", .data = &sdma_imx51, }, { .compatible = "fsl,imx35-sdma", .data = &sdma_imx35, }, { .compatible = "fsl,imx31-sdma", .data = &sdma_imx31, }, + { .compatible = "fsl,imx25-sdma", .data = &sdma_imx25, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sdma_dt_ids); -- cgit v0.10.2 From 728a0cdf065b9f42d1ff25d94858f824bb0989ba Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Sun, 9 Feb 2014 18:43:18 +0900 Subject: drm/ttm: declare 'struct device' in ttm_page_alloc.h Declare 'struct device' explicitly in ttm_page_alloc.h as this file does not include any file declaring it. This removes the following warning: warning: 'struct device' declared inside parameter list Signed-off-by: Alexandre Courbot Reviewed-by: Thierry Reding diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h index d1f61bf..49a8284 100644 --- a/include/drm/ttm/ttm_page_alloc.h +++ b/include/drm/ttm/ttm_page_alloc.h @@ -29,6 +29,8 @@ #include #include +struct device; + /** * Initialize pool allocator. */ -- cgit v0.10.2 From 7a444d1f0b557c68f847050b33713ae7b56f25e7 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 12 Feb 2014 22:46:25 +0900 Subject: drm/ttm: Fix memory leak in ttm_agp_backend.c This patch fix a memory leak found by cppcheck. [drivers/gpu/drm/ttm/ttm_agp_backend.c:129]: (error) Memory leak: agp_be Signed-off-by: Masanari Iida Reviewed-by: Thomas Hellstrom diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 3302f99e..764be36 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -126,6 +126,7 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev, agp_be->ttm.func = &ttm_agp_func; if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) { + kfree(agp_be); return NULL; } -- cgit v0.10.2 From b685f3b1744061aa9ad822548ba9c674de5be7c6 Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Mon, 10 Feb 2014 14:00:11 +0100 Subject: ACPI / PCI: Fix memory leak in acpi_pci_irq_enable() acpi_pci_link_allocate_irq() can return negative gsi even if entry != NULL. For that case we have a memory leak, so free entry before returning from acpi_pci_irq_enable() for gsi < 0. Signed-off-by: Tomasz Nowicki Cc: All applicable [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 52d45ea..361b40c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -430,6 +430,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) pin_name(pin)); } + kfree(entry); return 0; } -- cgit v0.10.2 From 67809f85d31eac600f6b28defa5386c9d2a13b1d Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 18 Feb 2014 10:22:17 -0500 Subject: ahci: disable NCQ on Samsung pci-e SSDs on macbooks Samsung's pci-e SSDs with device ID 0x1600 which are found on some macbooks time out on NCQ commands. Blacklist NCQ on the device so that the affected machines can at least boot. Original-patch-by: Levente Kurusa Signed-off-by: Tejun Heo Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=60731 Cc: stable@vger.kernel.org diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index dc2756f..7df81576 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -61,6 +61,7 @@ enum board_ids { /* board IDs by feature in alphabetical order */ board_ahci, board_ahci_ign_iferr, + board_ahci_noncq, board_ahci_nosntf, board_ahci_yes_fbs, @@ -121,6 +122,13 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, + [board_ahci_noncq] = { + AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, [board_ahci_nosntf] = { AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), .flags = AHCI_FLAG_COMMON, @@ -452,6 +460,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + /* + * Samsung SSDs found on some macbooks. NCQ times out. + * https://bugzilla.kernel.org/show_bug.cgi?id=60731 + */ + { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, + /* Enmotus */ { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, -- cgit v0.10.2 From 30a70b026b4cde4e51989661ff3bd0ede08d9646 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Feb 2014 21:25:37 +0200 Subject: usb: musb: fix obex in g_nokia.ko causing kernel panic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit phy_power_off() can, depending on the PHY being used, start I2C transactions which shouldn't happen in atomic context. Current call to phy_power_off() inside omap2430_runtime callbacks causes the following dump, as a fix, just don't power off the PHY in runtime. [ 18.606414] [] (__schedule+0x5c/0x50c) from [] (schedule_timeout+0x1f4/0x25c) [ 18.623809] [] (schedule_timeout+0x1f4/0x25c) from [] (wait_for_common+0xc8/0x1ac) [ 18.649291] [] (wait_for_common+0xc8/0x1ac) from [] (omap_i2c_xfer+0x338/0x488) [ 18.674499] [] (omap_i2c_xfer+0x338/0x488) from [] (__i2c_transfer+0x40/0x74) [ 18.692047] [] (__i2c_transfer+0x40/0x74) from [] (i2c_transfer+0x6c/0x90) [ 18.709320] [] (i2c_transfer+0x6c/0x90) from [] (regmap_i2c_read+0x48/0x68) [ 18.726715] [] (regmap_i2c_read+0x48/0x68) from [] (_regmap_raw_read+0x128/0x220) [ 18.752685] [] (_regmap_raw_read+0x128/0x220) from [] (regmap_raw_read+0xa0/0x130) [ 18.779052] [] (regmap_raw_read+0xa0/0x130) from [] (regmap_bulk_read+0xf8/0x16c) [ 18.805694] [] (regmap_bulk_read+0xf8/0x16c) from [] (twl_i2c_read+0xa4/0xe0) [ 18.823730] [] (twl_i2c_read+0xa4/0xe0) from [] (__twl4030_phy_power.isra.12+0x1c/0x58) [ 18.850921] [] (__twl4030_phy_power.isra.12+0x1c/0x58) from [] (twl4030_phy_power.part.14+0x80/0xc8) [ 18.879699] [] (twl4030_phy_power.part.14+0x80/0xc8) from [] (twl4030_set_suspend+0x54/0x1e8) [ 18.908325] [] (twl4030_set_suspend+0x54/0x1e8) from [] (omap2430_runtime_resume+0x5c/0x64) [ 18.937042] [] (omap2430_runtime_resume+0x5c/0x64) from [] (pm_generic_runtime_resume+0x2c/0x38) [ 18.966461] [] (pm_generic_runtime_resume+0x2c/0x38) from [] (__rpm_callback+0x54/0x80) [ 18.995117] [] (__rpm_callback+0x54/0x80) from [] (rpm_callback+0x40/0x74) [ 19.013610] [] (rpm_callback+0x40/0x74) from [] (rpm_resume+0x448/0x63c) [ 19.031921] [] (rpm_resume+0x448/0x63c) from [] (rpm_resume+0x364/0x63c) [ 19.050140] [] (rpm_resume+0x364/0x63c) from [] (__pm_runtime_resume+0x48/0x74) [ 19.077728] [] (__pm_runtime_resume+0x48/0x74) from [] (musb_gadget_pullup+0x1c/0xb4) [ 19.105895] [] (musb_gadget_pullup+0x1c/0xb4) from [] (usb_function_deactivate+0x54/0xa4 [libcomposite]) [ 19.135955] [] (usb_function_deactivate+0x54/0xa4 [libcomposite]) from [] (obex_bind+0x124/0x1d8 [usb_f_obex]) [ 19.166870] [] (obex_bind+0x124/0x1d8 [usb_f_obex]) from [] (usb_add_function+0x58/0xf4 [libcomposite]) [ 19.197143] [] (usb_add_function+0x58/0xf4 [libcomposite]) from [] (nokia_bind_config+0x204/0x250 [g_nokia]) [ 19.227905] [] (nokia_bind_config+0x204/0x250 [g_nokia]) from [] (usb_add_config+0x28/0xc0 [libcomposite]) [ 19.258483] [] (usb_add_config+0x28/0xc0 [libcomposite]) from [] (nokia_bind+0x9c/0x21c [g_nokia]) [ 19.288421] [] (nokia_bind+0x9c/0x21c [g_nokia]) from [] (composite_bind+0x74/0x180 [libcomposite]) [ 19.318420] [] (composite_bind+0x74/0x180 [libcomposite]) from [] (udc_bind_to_driver+0x2c/0xc4) [ 19.348114] [] (udc_bind_to_driver+0x2c/0xc4) from [] (usb_gadget_probe_driver+0x74/0x94) [ 19.377166] [] (usb_gadget_probe_driver+0x74/0x94) from [] (do_one_initcall+0x94/0x138) [ 19.406005] [] (do_one_initcall+0x94/0x138) from [] (load_module+0x113c/0x13c4) [ 19.434051] [] (load_module+0x113c/0x13c4) from [] (SyS_init_module+0xcc/0xec) [ 19.462127] [] (SyS_init_module+0xcc/0xec) from [] (ret_fast_syscall+0x0/0x30) [ 19.490753] Code: 0a00002e e1a00004 eb001438 e598300c (e5d3202c) [ 19.506805] ---[ end trace 060b62ec0d68a78b ]--- [ 19.523132] Kernel panic - not syncing: Fatal exception in interrupt dump is from 3.12-rc5 kernel Reported-by: Pali Rohár Signed-off-by: Ivaylo Dimitrov Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 2a408cd..8aa59a2 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -659,7 +659,6 @@ static int omap2430_runtime_suspend(struct device *dev) OTG_INTERFSEL); omap2430_low_level_exit(musb); - phy_power_off(musb->phy); } return 0; @@ -674,7 +673,6 @@ static int omap2430_runtime_resume(struct device *dev) omap2430_low_level_init(musb); musb_writel(musb->mregs, OTG_INTERFSEL, musb->context.otg_interfsel); - phy_power_on(musb->phy); } return 0; -- cgit v0.10.2 From f3a44fe0608eb628e1f8f6e3540462e6d171a745 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Tue, 18 Feb 2014 09:57:22 -0500 Subject: dm raid1: fix immutable biovec related BUG when retrying read bio When restoring bi_end_io, increase bi_remaining before retrying the bio to avoid BUG_ON(atomic_read(&bio->bi_remaining) <= 0) in bio_endio(). Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index f284e0b..7dfdb5c 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1244,6 +1244,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) dm_bio_restore(bd, bio); bio_record->details.bi_bdev = NULL; + + atomic_inc(&bio->bi_remaining); + queue_bio(ms, bio, rw); return DM_ENDIO_INCOMPLETE; } -- cgit v0.10.2 From ae10f8329f9b22d650aa12307b260eba2bc0c571 Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Mon, 17 Feb 2014 19:09:58 +0000 Subject: ARM: dove: dt: revert PMU interrupt controller node The corresponding driver didn't make it into v3.14, so we need to remove the node. Dove systems fail to boot with the node present and no driver. This node will be re-added when the driver makes it to mainline. Reported-by: Jean-Francois Moine Tested-by: Jean-Francois Moine Signed-off-by: Jason Cooper diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi index 2b76524..187fd46 100644 --- a/arch/arm/boot/dts/dove.dtsi +++ b/arch/arm/boot/dts/dove.dtsi @@ -379,15 +379,6 @@ #clock-cells = <1>; }; - pmu_intc: pmu-interrupt-ctrl@d0050 { - compatible = "marvell,dove-pmu-intc"; - interrupt-controller; - #interrupt-cells = <1>; - reg = <0xd0050 0x8>; - interrupts = <33>; - marvell,#interrupts = <7>; - }; - pinctrl: pin-ctrl@d0200 { compatible = "marvell,dove-pinctrl"; reg = <0xd0200 0x10>; @@ -610,8 +601,6 @@ rtc: real-time-clock@d8500 { compatible = "marvell,orion-rtc"; reg = <0xd8500 0x20>; - interrupt-parent = <&pmu_intc>; - interrupts = <5>; }; gpio2: gpio-ctrl@e8400 { -- cgit v0.10.2 From 3c4653c1f62ea5f1706084090a5a3bcf3402dc8f Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 4 Feb 2014 15:28:06 +0200 Subject: usb: musb: host: Fix SuperSpeed hub enumeration Disables PING on status phase of control transfer. PING token is not mandatory in status phase of control transfer and so some high speed USB devices don't support it. If such devices are connected to MUSB then they would not respond to PING token causing delayed or failed enumeration. [Roger Q] Fixes enumeration issues with some Super-Speed USB hubs e.g. Dlink DUB-1340 Signed-off-by: Ajay Kumar Gupta Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index ed45572..abb38c3 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1183,6 +1183,9 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) csr = MUSB_CSR0_H_STATUSPKT | MUSB_CSR0_TXPKTRDY; + /* disable ping token in status phase */ + csr |= MUSB_CSR0_H_DIS_PING; + /* flag status stage */ musb->ep0_stage = MUSB_EP0_STATUS; -- cgit v0.10.2 From 33f8d75f5771993ef16ed6bd56d7210f54226203 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 4 Feb 2014 15:29:33 +0200 Subject: usb: musb: core: Fix remote-wakeup resume During resume don't touch SUSPENDM/RESUME bits of POWER register while restoring controller context. These bits might be changed by the controller during resume operation and so will be different than what they were during suspend. e.g. SUSPENDM bit is set by software during USB global suspend but automatically cleared by the controller during remote wakeup or during resume. Setting this bit back while restoring context causes undesired behaviour. i.e. Babble interrupt is generated and USB is broken. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fc192ad..a501542 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2157,11 +2157,19 @@ static void musb_restore_context(struct musb *musb) void __iomem *musb_base = musb->mregs; void __iomem *ep_target_regs; void __iomem *epio; + u8 power; musb_writew(musb_base, MUSB_FRAME, musb->context.frame); musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); - musb_writeb(musb_base, MUSB_POWER, musb->context.power); + + /* Don't affect SUSPENDM/RESUME bits in POWER reg */ + power = musb_readb(musb_base, MUSB_POWER); + power &= MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME; + musb->context.power &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME); + power |= musb->context.power; + musb_writeb(musb_base, MUSB_POWER, power); + musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe); musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe); musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); -- cgit v0.10.2 From d246c9d55a90722fac9e7284201088eb62adcfc3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 3 Feb 2014 13:59:38 +0530 Subject: usb: gadget: s3c2410_udc: Fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass value instead of address as expected by 'usb_ep_set_maxpacket_limit'. Fixes the following compilation error introduced by commit e117e742d310 ("usb: gadget: add "maxpacket_limit" field to struct usb_ep"): drivers/usb/gadget/s3c2410_udc.c: In function ‘s3c2410_udc_reinit’: drivers/usb/gadget/s3c2410_udc.c:1632:3: error: cannot take address of bit-field ‘maxpacket’ usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket); Signed-off-by: Sachin Kamat Reviewed-by: Robert Baldyga Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index f04b2c3..dd9678f 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1629,7 +1629,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev) ep->ep.desc = NULL; ep->halted = 0; INIT_LIST_HEAD(&ep->queue); - usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket); + usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket); } } -- cgit v0.10.2 From 30d361bf0f81ece8de42c5e0a4e560270ad72b65 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 15 Jan 2014 14:09:49 +0100 Subject: usb: musb: do not sleep in atomic context musb_port_reset() is called from musb_hub_control() which in turn holds a spinlock, so musb_port_reset() is not allowed to call msleep(). With the asynchronous work helpers in place, this is fortunately easy to fix by rescheduling the reset deassertion function to after the time when the wait period is finished. Note, however, that the MUSB_POWER_RESUME bit is only set on AM33xx processors under rare conditions such as when to another driver reporting an error during suspend. Hence, this didn't hit me yet in normal operation. Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index a501542..b49a594 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -477,6 +477,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->port1_status |= (USB_PORT_STAT_C_SUSPEND << 16) | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies + + msecs_to_jiffies(20); schedule_delayed_work( &musb->finish_resume_work, 20); diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index eb63443..32f49e1 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -158,7 +158,6 @@ void musb_port_reset(struct musb *musb, bool do_reset) */ power = musb_readb(mbase, MUSB_POWER); if (do_reset) { - /* * If RESUME is set, we must make sure it stays minimum 20 ms. * Then we must clear RESUME and wait a bit to let musb start @@ -167,11 +166,22 @@ void musb_port_reset(struct musb *musb, bool do_reset) * detected". */ if (power & MUSB_POWER_RESUME) { - while (time_before(jiffies, musb->rh_timer)) - msleep(1); + long remain = (unsigned long) musb->rh_timer - jiffies; + + if (musb->rh_timer > 0 && remain > 0) { + /* take into account the minimum delay after resume */ + schedule_delayed_work( + &musb->deassert_reset_work, + jiffies_to_msecs(remain)); + return; + } + musb_writeb(mbase, MUSB_POWER, - power & ~MUSB_POWER_RESUME); - msleep(1); + power & ~MUSB_POWER_RESUME); + + /* Give the core 1 ms to clear MUSB_POWER_RESUME */ + schedule_delayed_work(&musb->deassert_reset_work, 1); + return; } power &= 0xf0; -- cgit v0.10.2 From 2d1f7af3d60dd09794e0738a915d272c6c27abc5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 14 Jan 2014 15:36:29 -0800 Subject: usb: gadget: bcm63xx_udc: fix build failure on DMA channel code Commit 3dc6475 ("bcm63xx_enet: add support Broadcom BCM6345 Ethernet") changed the ENETDMA[CS] macros such that they are no longer macros, but actual register offset definitions. The bcm63xx_udc driver was not updated, and as a result, causes the following build error to pop up: CC drivers/usb/gadget/u_ether.o drivers/usb/gadget/bcm63xx_udc.c: In function 'iudma_write': drivers/usb/gadget/bcm63xx_udc.c:642:24: error: called object '0' is not a function drivers/usb/gadget/bcm63xx_udc.c: In function 'iudma_reset_channel': drivers/usb/gadget/bcm63xx_udc.c:698:46: error: called object '0' is not a function drivers/usb/gadget/bcm63xx_udc.c:700:49: error: called object '0' is not a function Fix this by updating usb_dmac_{read,write}l and usb_dmas_{read,write}l to take an extra channel argument, and use the channel width (ENETDMA_CHAN_WIDTH) to offset the register we want to access, hence doing again what the macro implicitely did for us. Cc: Kevin Cernekee Cc: Jonas Gorski Cc: Signed-off-by: Florian Fainelli Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index 888fbb4..e969eb8 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -360,24 +360,30 @@ static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off) bcm_writel(val, udc->iudma_regs + off); } -static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off) +static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan) { - return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off); + return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } -static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off, + int chan) { - bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off); + bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } -static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off) +static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan) { - return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off); + return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } -static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off, + int chan) { - bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off); + bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled) @@ -638,7 +644,7 @@ static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma, } while (!last_bd); usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK, - ENETDMAC_CHANCFG_REG(iudma->ch_idx)); + ENETDMAC_CHANCFG_REG, iudma->ch_idx); } /** @@ -694,9 +700,9 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num)); /* stop DMA, then wait for the hardware to wrap up */ - usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG(ch_idx)); + usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx); - while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)) & + while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) & ENETDMAC_CHANCFG_EN_MASK) { udelay(1); @@ -713,10 +719,10 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n", ch_idx); usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK, - ENETDMAC_CHANCFG_REG(ch_idx)); + ENETDMAC_CHANCFG_REG, ch_idx); } } - usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG(ch_idx)); + usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx); /* don't leave "live" HW-owned entries for the next guy to step on */ for (d = iudma->bd_ring; d <= iudma->end_bd; d++) @@ -728,11 +734,11 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) /* set up IRQs, UBUS burst size, and BD base for this channel */ usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, - ENETDMAC_IRMASK_REG(ch_idx)); - usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG(ch_idx)); + ENETDMAC_IRMASK_REG, ch_idx); + usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx); - usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG(ch_idx)); - usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG(ch_idx)); + usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx); + usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx); } /** @@ -2035,7 +2041,7 @@ static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id) spin_lock(&udc->lock); usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, - ENETDMAC_IR_REG(iudma->ch_idx)); + ENETDMAC_IR_REG, iudma->ch_idx); bep = iudma->bep; rc = iudma_read(udc, iudma); @@ -2175,18 +2181,18 @@ static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p) seq_printf(s, " [ep%d]:\n", max_t(int, iudma_defaults[ch_idx].ep_num, 0)); seq_printf(s, " cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n", - usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)), - usb_dmac_readl(udc, ENETDMAC_IR_REG(ch_idx)), - usb_dmac_readl(udc, ENETDMAC_IRMASK_REG(ch_idx)), - usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG(ch_idx))); + usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx), + usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx), + usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx), + usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx)); - sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG(ch_idx)); - sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG(ch_idx)); + sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx); + sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx); seq_printf(s, " base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n", - usb_dmas_readl(udc, ENETDMAS_RSTART_REG(ch_idx)), + usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx), sram2 >> 16, sram2 & 0xffff, sram3 >> 16, sram3 & 0xffff, - usb_dmas_readl(udc, ENETDMAS_SRAM4_REG(ch_idx))); + usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx)); seq_printf(s, " desc: %d/%d used", iudma->n_bds_used, iudma->n_bds); -- cgit v0.10.2 From accb884b32e82f943340688c9cd30290531e73e0 Mon Sep 17 00:00:00 2001 From: Chao Bi Date: Wed, 12 Feb 2014 21:27:25 +0200 Subject: mei: set client's read_cb to NULL when flow control fails In mei_cl_read_start(), if it fails to send flow control request, it will release "cl->read_cb" but forget to set pointer to NULL, leaving "cl->read_cb" still pointing to random memory, next time this client is operated like mei_release(), it has chance to refer to this wrong pointer. Fixes: PANIC at kfree in mei_release() [228781.826904] Call Trace: [228781.829737] [] ? mei_cl_unlink+0x48/0xa0 [228781.835283] [] mei_io_cb_free+0x17/0x30 [228781.840733] [] mei_release+0xa8/0x180 [228781.845989] [] ? __fsnotify_parent+0xa0/0xf0 [228781.851925] [] __fput+0xd9/0x200 [228781.856696] [] ____fput+0xd/0x10 [228781.861467] [] task_work_run+0x81/0xb0 [228781.866821] [] do_exit+0x283/0xa00 [228781.871786] [] ? kprobe_flush_task+0x66/0xc0 [228781.877722] [] ? __dequeue_signal+0x18/0x1a0 [228781.883657] [] ? dequeue_signal+0x32/0x190 [228781.889397] [] do_group_exit+0x34/0xa0 [228781.894750] [] get_signal_to_deliver+0x206/0x610 [228781.901075] [] do_signal+0x38/0x100 [228781.906136] [] ? mei_read+0x42c/0x4e0 [228781.911393] [] ? wake_up_bit+0x30/0x30 [228781.916745] [] ? mei_poll+0x120/0x120 [228781.922001] [] ? vfs_read+0x89/0x160 [228781.927158] [] ? mei_poll+0x120/0x120 [228781.932414] [] ? fget_light+0x44/0xe0 [228781.937670] [] ? SyS_read+0x68/0x80 [228781.942730] [] do_notify_resume+0x55/0x70 [228781.948376] [] work_notifysig+0x29/0x30 [228781.953827] [] ? bad_area+0x5/0x3e Cc: stable # 3.9+ Signed-off-by: Chao Bi Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 9b809cf..89a5579 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -666,7 +666,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) goto err; cb->fop_type = MEI_FOP_READ; - cl->read_cb = cb; if (dev->hbuf_is_ready) { dev->hbuf_is_ready = false; if (mei_hbm_cl_flow_control_req(dev, cl)) { @@ -678,6 +677,9 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) } else { list_add_tail(&cb->list, &dev->ctrl_wr_list.list); } + + cl->read_cb = cb; + return rets; err: mei_io_cb_free(cb); -- cgit v0.10.2 From 7d5a33b071d19314c452ca5252ecd990eb0dd696 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 3 Feb 2014 15:53:25 -0500 Subject: drm/radeon: unify bpc handling We were already storing the bpc (bits per color) information in radeon_crtc, so just use that everywhere rather than calculating it everywhere we use it. This also allows us to change it in one place if we ever want to override it. Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a9338c8..f0d409d 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -559,7 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, u32 adjusted_clock = mode->clock; int encoder_mode = atombios_get_encoder_mode(encoder); u32 dp_clock = mode->clock; - int bpc = radeon_get_monitor_bpc(connector); + int bpc = radeon_crtc->bpc; bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); /* reset the pll flags */ diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index a42d615..2cec2ab 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -464,11 +464,12 @@ atombios_tv_setup(struct drm_encoder *encoder, int action) static u8 radeon_atom_get_bpc(struct drm_encoder *encoder) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); int bpc = 8; - if (connector) - bpc = radeon_get_monitor_bpc(connector); + if (encoder->crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + bpc = radeon_crtc->bpc; + } switch (bpc) { case 0: -- cgit v0.10.2 From 8716ed4e7bed4e4c7e3f37940e950ddc0362f450 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 12 Feb 2014 12:48:23 -0500 Subject: drm: add DRM_CAPs for cursor size Some hardware may not support standard 64x64 cursors. Add a drm cap to query the cursor size from the kernel. Some examples include radeon CIK parts (128x128 cursors) and armada (32x64 or 64x32). This allows things like device specific ddxes to remove asics specific logic and also allows xf86-video-modesetting to work properly with hw cursors on this hardware. Default to 64 if the driver doesn't specify a size. Signed-off-by: Alex Deucher Reviewed-by: Rob Clark diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index dffc836..f4dc9b7 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -296,6 +296,18 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) case DRM_CAP_ASYNC_PAGE_FLIP: req->value = dev->mode_config.async_page_flip; break; + case DRM_CAP_CURSOR_WIDTH: + if (dev->mode_config.cursor_width) + req->value = dev->mode_config.cursor_width; + else + req->value = 64; + break; + case DRM_CAP_CURSOR_HEIGHT: + if (dev->mode_config.cursor_height) + req->value = dev->mode_config.cursor_height; + else + req->value = 64; + break; default: return -EINVAL; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 71727b6..8f3dee0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -907,6 +907,9 @@ struct drm_mode_config { /* whether async page flip is supported or not */ bool async_page_flip; + + /* cursor size */ + uint32_t cursor_width, cursor_height; }; #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 3c9a833..b06c8ed 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -619,6 +619,8 @@ struct drm_gem_open { #define DRM_PRIME_CAP_EXPORT 0x2 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9 /** DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- cgit v0.10.2 From bea61c59d799c23591da2b29444ecc649a8682cf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 12 Feb 2014 12:56:53 -0500 Subject: drm/radeon: fill in DRM_CAPs for cursor size CIK parts are 128x128, older parts are 64x64. Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d680608..fbd8b93 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -571,6 +571,8 @@ static void radeon_crtc_init(struct drm_device *dev, int index) radeon_crtc->max_cursor_width = CURSOR_WIDTH; radeon_crtc->max_cursor_height = CURSOR_HEIGHT; } + dev->mode_config.cursor_width = radeon_crtc->max_cursor_width; + dev->mode_config.cursor_height = radeon_crtc->max_cursor_height; #if 0 radeon_crtc->mode_set.crtc = &radeon_crtc->base; -- cgit v0.10.2 From 78b035101999d8d071781778c019c387dc8bebb2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Feb 2014 12:50:13 -0500 Subject: drm/radeon/dpm: reduce r7xx vblank mclk threshold to 200 Most laptops seems to have a vblank period of less than 300 and mclk switching works fine. Drop the quirk and set the default threshold to 200. bug: https://bugzilla.kernel.org/show_bug.cgi?id=70701 Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 5b2ea8a..b5f63f5 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2526,14 +2526,7 @@ u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low) bool rv770_dpm_vblank_too_short(struct radeon_device *rdev) { u32 vblank_time = r600_dpm_get_vblank_time(rdev); - u32 switch_limit = 300; - - /* quirks */ - /* ASUS K70AF */ - if ((rdev->pdev->device == 0x9553) && - (rdev->pdev->subsystem_vendor == 0x1043) && - (rdev->pdev->subsystem_device == 0x1c42)) - switch_limit = 200; + u32 switch_limit = 200; /* 300 */ /* RV770 */ /* mclk switching doesn't seem to work reliably on desktop RV770s */ -- cgit v0.10.2 From 6d8ea7de3f5035610f3bfacbe35e7b71ad1e4663 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Feb 2014 14:16:31 -0500 Subject: drm/radeon: fix display tiling setup on SI Apply the same logic as CI to SI for setting up the display tiling parameters. The num banks may vary per tiling index just like CI. Bugs: https://bugs.freedesktop.org/show_bug.cgi?id=71488 https://bugs.freedesktop.org/show_bug.cgi?id=73946 https://bugs.freedesktop.org/show_bug.cgi?id=74927 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index f0d409d..0d19f4f 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1176,7 +1176,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split); /* Set NUM_BANKS. */ - if (rdev->family >= CHIP_BONAIRE) { + if (rdev->family >= CHIP_TAHITI) { unsigned tileb, index, num_banks, tile_split_bytes; /* Calculate the macrotile mode index. */ @@ -1194,13 +1194,14 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, return -EINVAL; } - num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; + if (rdev->family >= CHIP_BONAIRE) + num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; + else + num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3; fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks); } else { - /* SI and older. */ - if (rdev->family >= CHIP_TAHITI) - tmp = rdev->config.si.tile_config; - else if (rdev->family >= CHIP_CAYMAN) + /* NI and older. */ + if (rdev->family >= CHIP_CAYMAN) tmp = rdev->config.cayman.tile_config; else tmp = rdev->config.evergreen.tile_config; -- cgit v0.10.2 From ebc54ffe1c57067d4700f970ef88f26e18b48690 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Feb 2014 23:01:30 +0300 Subject: drm/radeon: delete a stray tab Static checkers complain that probably curly braces were intended here, but actually it makes more sense to remove the extra tab. Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index f2b9e21..5623e75 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1680,7 +1680,7 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) case RADEON_HPD_6: if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) connected = true; - break; + break; default: break; } -- cgit v0.10.2 From 8f53492f86f9ca66bc762be98f0a9fce9bcb319a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 18 Feb 2014 11:37:20 +0100 Subject: drm/radeon: fix CP semaphores on CIK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CP semaphore queue on CIK has a bug that triggers if uncompleted waits use the same address while a signal is still pending. Work around this by using different addresses for each sync. Signed-off-by: Christian König Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4a8ac1c..024db37 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -135,6 +135,9 @@ extern int radeon_hard_reset; /* R600+ */ #define R600_RING_TYPE_UVD_INDEX 5 +/* number of hw syncs before falling back on blocking */ +#define RADEON_NUM_SYNCS 4 + /* hardcode those limit for now */ #define RADEON_VA_IB_OFFSET (1 << 20) #define RADEON_VA_RESERVED_SIZE (8 << 20) @@ -554,7 +557,6 @@ int radeon_mode_dumb_mmap(struct drm_file *filp, /* * Semaphores. */ -/* everything here is constant */ struct radeon_semaphore { struct radeon_sa_bo *sa_bo; signed waiters; diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 1b783f0..15e44a7 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -139,7 +139,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, } /* 64 dwords should be enough for fence too */ - r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); + r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8); if (r) { dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); return r; diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 2b42aa1..9006b32 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -34,14 +34,15 @@ int radeon_semaphore_create(struct radeon_device *rdev, struct radeon_semaphore **semaphore) { + uint32_t *cpu_addr; int i, r; *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); if (*semaphore == NULL) { return -ENOMEM; } - r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, - &(*semaphore)->sa_bo, 8, 8, true); + r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo, + 8 * RADEON_NUM_SYNCS, 8, true); if (r) { kfree(*semaphore); *semaphore = NULL; @@ -49,7 +50,10 @@ int radeon_semaphore_create(struct radeon_device *rdev, } (*semaphore)->waiters = 0; (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); - *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; + + cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo); + for (i = 0; i < RADEON_NUM_SYNCS; ++i) + cpu_addr[i] = 0; for (i = 0; i < RADEON_NUM_RINGS; ++i) (*semaphore)->sync_to[i] = NULL; @@ -125,6 +129,7 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, struct radeon_semaphore *semaphore, int ring) { + unsigned count = 0; int i, r; for (i = 0; i < RADEON_NUM_RINGS; ++i) { @@ -140,6 +145,12 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, return -EINVAL; } + if (++count > RADEON_NUM_SYNCS) { + /* not enough room, wait manually */ + radeon_fence_wait_locked(fence); + continue; + } + /* allocate enough space for sync command */ r = radeon_ring_alloc(rdev, &rdev->ring[i], 16); if (r) { @@ -164,6 +175,8 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, radeon_ring_commit(rdev, &rdev->ring[i]); radeon_fence_note_sync(fence, ring); + + semaphore->gpu_addr += 8; } return 0; -- cgit v0.10.2 From 5b43c3cd07981619dbdb1fb935ef705a3e80955f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 10:14:46 -0500 Subject: drm/radeon/si: fix typo in dpm sq ramping setup inverted logic. Noticed-by: Sylvain BERTRAND Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index eafb0e6..0a2f5b4 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2395,7 +2395,7 @@ static int si_populate_sq_ramping_values(struct radeon_device *rdev, if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) enable_sq_ramping = false; - if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) + if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) enable_sq_ramping = false; for (i = 0; i < state->performance_level_count; i++) { -- cgit v0.10.2 From 21ed4947fdfe19b60a27b84162622e56439c7937 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 10:16:28 -0500 Subject: drm/radeon/ni: fix typo in dpm sq ramping setup inverted logic. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 1217fbc..ca81427 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -2588,7 +2588,7 @@ static int ni_populate_sq_ramping_values(struct radeon_device *rdev, if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) enable_sq_ramping = false; - if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) + if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) enable_sq_ramping = false; for (i = 0; i < state->performance_level_count; i++) { -- cgit v0.10.2 From cd91b2fecfa66967e6ad732a9af860eb96c31ba4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 14 Feb 2014 20:19:03 +0100 Subject: ARM: 7963/1: mm: report both sections from PMD On 2-level page table systems, the PMD has 2 section entries. Report these, otherwise ARM_PTDUMP will miss reporting permission changes on odd section boundaries. Signed-off-by: Kees Cook Acked-by: Catalin Marinas Tested-by: Steve Capper Signed-off-by: Russell King diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c index 2b3a564..ef69152 100644 --- a/arch/arm/mm/dump.c +++ b/arch/arm/mm/dump.c @@ -264,6 +264,9 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start) note_page(st, addr, 3, pmd_val(*pmd)); else walk_pte(st, pmd, addr); + + if (SECTION_SIZE < PMD_SIZE && pmd_large(pmd[1])) + note_page(st, addr + SECTION_SIZE, 3, pmd_val(pmd[1])); } } -- cgit v0.10.2 From c9698e5cd6ad1ff2844bc44fabddc0f2e0562047 Mon Sep 17 00:00:00 2001 From: "David A. Long" Date: Fri, 14 Feb 2014 22:41:18 +0100 Subject: ARM: 7964/1: Detect section mismatches in thumb relocations Add processing for normally encountered thumb relocation types so that section mismatches will be detected. Comment from Rusty Russell follows: Happiest for this to go through an ARM tree, so: Signed-off-by: David A. Long Acked-by: Rusty Russell Signed-off-by: Russell King diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 4061098..99a45fd 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1502,6 +1502,16 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) #define R_ARM_JUMP24 29 #endif +#ifndef R_ARM_THM_CALL +#define R_ARM_THM_CALL 10 +#endif +#ifndef R_ARM_THM_JUMP24 +#define R_ARM_THM_JUMP24 30 +#endif +#ifndef R_ARM_THM_JUMP19 +#define R_ARM_THM_JUMP19 51 +#endif + static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) { unsigned int r_typ = ELF_R_TYPE(r->r_info); @@ -1515,6 +1525,9 @@ static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) case R_ARM_PC24: case R_ARM_CALL: case R_ARM_JUMP24: + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + case R_ARM_THM_JUMP19: /* From ARM ABI: ((S + A) | T) - P */ r->r_addend = (int)(long)(elf->hdr + sechdr->sh_offset + -- cgit v0.10.2 From 3e8d6d85adedc59115a564c0a54b36e42087c4d9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 13 Feb 2014 15:49:17 -0500 Subject: USB: EHCI: add delay during suspend to prevent erroneous wakeups High-speed USB connections revert back to full-speed signalling when the device goes into suspend. This takes several milliseconds, and during that time it's not possible to tell reliably whether the device has been disconnected. On some platforms, the Wake-On-Disconnect circuitry gets confused during this intermediate state. It generates a false wakeup signal, which can prevent the controller from going to sleep. To avoid this problem, this patch adds a 5-ms delay to the ehci_bus_suspend() routine if any ports have to switch over to full-speed signalling. (Actually, the delay was already present for devices using a particular kind of PHY power management; the patch merely causes the delay to be used more widely.) Signed-off-by: Alan Stern Reviewed-by: Peter Chen CC: Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 47b858f..7ae0c4d 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -238,6 +238,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) int port; int mask; int changed; + bool fs_idle_delay; ehci_dbg(ehci, "suspend root hub\n"); @@ -272,6 +273,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci->bus_suspended = 0; ehci->owned_ports = 0; changed = 0; + fs_idle_delay = false; port = HCS_N_PORTS(ehci->hcs_params); while (port--) { u32 __iomem *reg = &ehci->regs->port_status [port]; @@ -300,16 +302,32 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } if (t1 != t2) { + /* + * On some controllers, Wake-On-Disconnect will + * generate false wakeup signals until the bus + * switches over to full-speed idle. For their + * sake, add a delay if we need one. + */ + if ((t2 & PORT_WKDISC_E) && + ehci_port_speed(ehci, t2) == + USB_PORT_STAT_HIGH_SPEED) + fs_idle_delay = true; ehci_writel(ehci, t2, reg); changed = 1; } } + spin_unlock_irq(&ehci->lock); + + if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) { + /* + * Wait for HCD to enter low-power mode or for the bus + * to switch to full-speed idle. + */ + usleep_range(5000, 5500); + } if (changed && ehci->has_tdi_phy_lpm) { - spin_unlock_irq(&ehci->lock); - msleep(5); /* 5 ms for HCD to enter low-power mode */ spin_lock_irq(&ehci->lock); - port = HCS_N_PORTS(ehci->hcs_params); while (port--) { u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; @@ -322,8 +340,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) port, (t3 & HOSTPC_PHCD) ? "succeeded" : "failed"); } + spin_unlock_irq(&ehci->lock); } - spin_unlock_irq(&ehci->lock); /* Apparently some devices need a >= 1-uframe delay here */ if (ehci->bus_suspended) -- cgit v0.10.2 From 12df84d4a80278a5b1abfec3206795291da52fc9 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Wed, 12 Feb 2014 16:04:45 +0100 Subject: USB: serial: option: blacklist interface 4 for Cinterion PHS8 and PXS8 This interface is to be handled by the qmi_wwan driver. CC: Hans-Christoph Schemmel CC: Christian Schmiedl CC: Nicolaus Colberg CC: David McCullough Signed-off-by: Aleksander Morgado Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 216d20a..68fc9fe 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1526,7 +1526,8 @@ static const struct usb_device_id option_ids[] = { /* Cinterion */ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, - { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, -- cgit v0.10.2 From 73926db33b277c4c371edbc9fe9093adc9b2803b Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 14 Feb 2014 20:49:46 +0100 Subject: usb: musb: do not sleep in atomic context musb_port_reset() is called from musb_hub_control() which in turn holds a spinlock, so musb_port_reset() is not allowed to call msleep(). With the asynchronous work helpers in place, this is fortunately easy to fix by rescheduling the reset deassertion function to after the time when the wait period is finished. Note, however, that the MUSB_POWER_RESUME bit is only set on AM33xx processors under rare conditions such as when to another driver reporting an error during suspend. Hence, this didn't hit me yet in normal operation. Signed-off-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fc192ad..1a377ca 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -477,6 +477,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->port1_status |= (USB_PORT_STAT_C_SUSPEND << 16) | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies + + msecs_to_jiffies(20); schedule_delayed_work( &musb->finish_resume_work, 20); diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index eb63443..32f49e1 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -158,7 +158,6 @@ void musb_port_reset(struct musb *musb, bool do_reset) */ power = musb_readb(mbase, MUSB_POWER); if (do_reset) { - /* * If RESUME is set, we must make sure it stays minimum 20 ms. * Then we must clear RESUME and wait a bit to let musb start @@ -167,11 +166,22 @@ void musb_port_reset(struct musb *musb, bool do_reset) * detected". */ if (power & MUSB_POWER_RESUME) { - while (time_before(jiffies, musb->rh_timer)) - msleep(1); + long remain = (unsigned long) musb->rh_timer - jiffies; + + if (musb->rh_timer > 0 && remain > 0) { + /* take into account the minimum delay after resume */ + schedule_delayed_work( + &musb->deassert_reset_work, + jiffies_to_msecs(remain)); + return; + } + musb_writeb(mbase, MUSB_POWER, - power & ~MUSB_POWER_RESUME); - msleep(1); + power & ~MUSB_POWER_RESUME); + + /* Give the core 1 ms to clear MUSB_POWER_RESUME */ + schedule_delayed_work(&musb->deassert_reset_work, 1); + return; } power &= 0xf0; -- cgit v0.10.2 From f2dece4499eea534c7c92e49fbf6a9bb0510cbcf Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 14 Feb 2014 20:49:47 +0100 Subject: usb: musb: correct use of schedule_delayed_work() schedule_delayed_work() takes the delay in jiffies, not msecs. Fix the caller sites in musb. This bug caused regressions with the cleanups that went in for 3.14 (8ed1fb790ea: "usb: musb: finish suspend/reset work independently from musb_hub_control()"). Signed-off-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 1a377ca..93eba53 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -480,7 +480,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->rh_timer = jiffies + msecs_to_jiffies(20); schedule_delayed_work( - &musb->finish_resume_work, 20); + &musb->finish_resume_work, + msecs_to_jiffies(20)); musb->xceiv->state = OTG_STATE_A_HOST; musb->is_active = 1; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 32f49e1..e2d2d8c 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) /* later, GetPortStatus will stop RESUME signaling */ musb->port1_status |= MUSB_PORT_STAT_RESUME; - schedule_delayed_work(&musb->finish_resume_work, 20); + schedule_delayed_work(&musb->finish_resume_work, + msecs_to_jiffies(20)); } } @@ -171,8 +172,7 @@ void musb_port_reset(struct musb *musb, bool do_reset) if (musb->rh_timer > 0 && remain > 0) { /* take into account the minimum delay after resume */ schedule_delayed_work( - &musb->deassert_reset_work, - jiffies_to_msecs(remain)); + &musb->deassert_reset_work, remain); return; } @@ -180,7 +180,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) power & ~MUSB_POWER_RESUME); /* Give the core 1 ms to clear MUSB_POWER_RESUME */ - schedule_delayed_work(&musb->deassert_reset_work, 1); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(1)); return; } @@ -190,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) musb->port1_status |= USB_PORT_STAT_RESET; musb->port1_status &= ~USB_PORT_STAT_ENABLE; - schedule_delayed_work(&musb->deassert_reset_work, 50); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(50)); } else { dev_dbg(musb->controller, "root port reset stopped\n"); musb_writeb(mbase, MUSB_POWER, -- cgit v0.10.2 From 06c304e88907cac9b1f5b21727ff268bf1705bb5 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 17 Feb 2014 14:29:21 +0530 Subject: phy,phy-bcm-kona-usb2.c: Add dependency on HAS_IOMEM On archs like S390 or um this driver cannot build nor work. Make it depend on HAS_IOMEM to bypass build failures. drivers/phy/phy-bcm-kona-usb2.c:114: undefined reference to `devm_ioremap_resource' Signed-off-by: Richard Weinberger Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index afa2354..79e3c70 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -61,6 +61,7 @@ config PHY_EXYNOS_DP_VIDEO config BCM_KONA_USB2_PHY tristate "Broadcom Kona USB2 PHY Driver" depends on GENERIC_PHY + depends on HAS_IOMEM help Enable this to support the Broadcom Kona USB 2.0 PHY. -- cgit v0.10.2 From f40037fd3677ae240978f469cc4155bf3ca7c076 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 14:29:22 +0530 Subject: phy-core: phy_get: Leave error logging to the caller In various cases errors may be expected, ie probe-deferral or a call to phy_get from a driver where the use of a phy is optional. Rather then adding all sort of complicated checks for this, and/or adding special functions like devm_phy_get_optional, simply don't log an error, and let deciding if get_phy returning an error really should result in a dev_err up to the caller. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 5f5b0f4..b355553 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -404,17 +404,11 @@ struct phy *phy_get(struct device *dev, const char *string) index = of_property_match_string(dev->of_node, "phy-names", string); phy = of_phy_get(dev, index); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } } else { phy = phy_lookup(dev, string); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } } + if (IS_ERR(phy)) + return phy; if (!try_module_get(phy->ops->owner)) return ERR_PTR(-EPROBE_DEFER); -- cgit v0.10.2 From 767a1b5d6ec4ac5335dde17100880347ed154ce2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 14:29:23 +0530 Subject: phy-core: Don't propagate -ENOSUPP from phy_pm_runtime_get_sync to caller The phy-core allows phy_init and phy_power_on to be called multiple times, but before this patch -ENOSUPP from phy_pm_runtime_get_sync would be propagated to the caller for the 2nd and later calls. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index b355553..6c73837 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -176,6 +176,8 @@ int phy_init(struct phy *phy) dev_err(&phy->dev, "phy init failed --> %d\n", ret); goto out; } + } else { + ret = 0; /* Override possible ret == -ENOTSUPP */ } ++phy->init_count; @@ -232,6 +234,8 @@ int phy_power_on(struct phy *phy) dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); goto out; } + } else { + ret = 0; /* Override possible ret == -ENOTSUPP */ } ++phy->power_count; mutex_unlock(&phy->mutex); -- cgit v0.10.2 From b51fbf9fb0c32c1a98f824ab5d6f59b17b39ef9e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 14:29:24 +0530 Subject: phy-core: Don't allow building phy-core as a module include/phy/phy.h has stub code in there for when building without the phy-core enabled. This is useful for generic drivers such as ahci-platform, ehci-platoform and ohci-platform which have support for driving an optional phy passed to them through the devicetree. Since on some boards this phy functionality is not needed, being able to disable the phy subsystem without needing a lot of #ifdef magic in the driver using it is quite useful. However this breaks when the module using the phy subsystem is build-in and the phy-core is not, which leads to the build failing with missing symbol errors in the linking stage of the zImage. Which leads to gems such as this being added to the Kconfig for achi_platform: depends on GENERIC_PHY || !GENERIC_PHY Rather then duplicating this code in a lot of places using the phy-core, I believe it is better to simply not allow the phy-core to be built as a module. The phy core is quite small and has no external dependencies, so always building it in when enabling it should not be an issue. Signed-off-by: Hans de Goede Acked-by: Roger Quadros Acked-by: Andrew Lunn Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 79e3c70..c7a551c 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -5,7 +5,7 @@ menu "PHY Subsystem" config GENERIC_PHY - tristate "PHY Core" + bool "PHY Core" help Generic PHY support. -- cgit v0.10.2 From 64fe1891696cdef4603b5f2d7c3a846bce8cf42b Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 17 Feb 2014 14:29:25 +0530 Subject: phy: let phy_provider_register be the last step in registering PHY Registering phy_provider before creating the PHY can result in PHY callbacks being invoked which will lead to aborts. In order to avoid this invoke phy_provider_register after phy_create and phy_set_drvdata. Reported-by: Felipe Balbi Signed-off-by: Kishon Vijay Abraham I Acked-by: Sylwester Nawrocki Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index 1dbe6ce..0786fef 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c @@ -76,10 +76,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) if (IS_ERR(state->regs)) return PTR_ERR(state->regs); - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create Display Port PHY\n"); @@ -87,6 +83,10 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) } phy_set_drvdata(phy, state); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + return 0; } diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index 0c5efab..7f13932 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c @@ -134,11 +134,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) dev_set_drvdata(dev, state); spin_lock_init(&state->slock); - phy_provider = devm_of_phy_provider_register(dev, - exynos_mipi_video_phy_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { struct phy *phy = devm_phy_create(dev, &exynos_mipi_video_phy_ops, NULL); @@ -152,6 +147,11 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy, &state->phys[i]); } + phy_provider = devm_of_phy_provider_register(dev, + exynos_mipi_video_phy_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + return 0; } diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c index d43786f..d70ecd6 100644 --- a/drivers/phy/phy-mvebu-sata.c +++ b/drivers/phy/phy-mvebu-sata.c @@ -99,17 +99,17 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev) if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); - phy_provider = devm_of_phy_provider_register(&pdev->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL); if (IS_ERR(phy)) return PTR_ERR(phy); phy_set_drvdata(phy, priv); + phy_provider = devm_of_phy_provider_register(&pdev->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + /* The boot loader may of left it on. Turn it off. */ phy_mvebu_sata_power_off(phy); diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index bfc5c33..7699752 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -177,11 +177,6 @@ static int omap_usb2_probe(struct platform_device *pdev) phy->phy.otg = otg; phy->phy.type = USB_PHY_TYPE_USB2; - phy_provider = devm_of_phy_provider_register(phy->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - control_node = of_parse_phandle(node, "ctrl-module", 0); if (!control_node) { dev_err(&pdev->dev, "Failed to get control device phandle\n"); @@ -214,6 +209,11 @@ static int omap_usb2_probe(struct platform_device *pdev) phy_set_drvdata(generic_phy, phy); + phy_provider = devm_of_phy_provider_register(phy->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); if (IS_ERR(phy->wkupclk)) { dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index daf65e6..c3ace1d 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -695,11 +695,6 @@ static int twl4030_usb_probe(struct platform_device *pdev) otg->set_host = twl4030_set_host; otg->set_peripheral = twl4030_set_peripheral; - phy_provider = devm_of_phy_provider_register(twl->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - phy = devm_phy_create(twl->dev, &ops, init_data); if (IS_ERR(phy)) { dev_dbg(&pdev->dev, "Failed to create PHY\n"); @@ -708,6 +703,11 @@ static int twl4030_usb_probe(struct platform_device *pdev) phy_set_drvdata(phy, twl); + phy_provider = devm_of_phy_provider_register(twl->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + /* init spinlock for workqueue */ spin_lock_init(&twl->lock); -- cgit v0.10.2 From ffd5939381c609056b33b7585fb05a77b4c695f3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 17 Feb 2014 12:11:11 +0100 Subject: net: sctp: fix sctp_connectx abi for ia32 emulation/compat mode SCTP's sctp_connectx() abi breaks for 64bit kernels compiled with 32bit emulation (e.g. ia32 emulation or x86_x32). Due to internal usage of 'struct sctp_getaddrs_old' which includes a struct sockaddr pointer, sizeof(param) check will always fail in kernel as the structure in 64bit kernel space is 4bytes larger than for user binaries compiled in 32bit mode. Thus, applications making use of sctp_connectx() won't be able to run under such circumstances. Introduce a compat interface in the kernel to deal with such situations by using a 'struct compat_sctp_getaddrs_old' structure where user data is copied into it, and then sucessively transformed into a 'struct sctp_getaddrs_old' structure with the help of compat_ptr(). That fixes sctp_connectx() abi without any changes needed in user space, and lets the SCTP test suite pass when compiled in 32bit and run on 64bit kernels. Fixes: f9c67811ebc0 ("sctp: Fix regression introduced by new sctp_connectx api") Signed-off-by: Daniel Borkmann Acked-by: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 7075ac8..981aaf8 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -1368,11 +1369,19 @@ static int sctp_setsockopt_connectx(struct sock *sk, /* * New (hopefully final) interface for the API. * We use the sctp_getaddrs_old structure so that use-space library - * can avoid any unnecessary allocations. The only defferent part + * can avoid any unnecessary allocations. The only different part * is that we store the actual length of the address buffer into the - * addrs_num structure member. That way we can re-use the existing + * addrs_num structure member. That way we can re-use the existing * code. */ +#ifdef CONFIG_COMPAT +struct compat_sctp_getaddrs_old { + sctp_assoc_t assoc_id; + s32 addr_num; + compat_uptr_t addrs; /* struct sockaddr * */ +}; +#endif + static int sctp_getsockopt_connectx3(struct sock *sk, int len, char __user *optval, int __user *optlen) @@ -1381,16 +1390,30 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len, sctp_assoc_t assoc_id = 0; int err = 0; - if (len < sizeof(param)) - return -EINVAL; +#ifdef CONFIG_COMPAT + if (is_compat_task()) { + struct compat_sctp_getaddrs_old param32; - if (copy_from_user(¶m, optval, sizeof(param))) - return -EFAULT; + if (len < sizeof(param32)) + return -EINVAL; + if (copy_from_user(¶m32, optval, sizeof(param32))) + return -EFAULT; - err = __sctp_setsockopt_connectx(sk, - (struct sockaddr __user *)param.addrs, - param.addr_num, &assoc_id); + param.assoc_id = param32.assoc_id; + param.addr_num = param32.addr_num; + param.addrs = compat_ptr(param32.addrs); + } else +#endif + { + if (len < sizeof(param)) + return -EINVAL; + if (copy_from_user(¶m, optval, sizeof(param))) + return -EFAULT; + } + err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *) + param.addrs, param.addr_num, + &assoc_id); if (err == 0 || err == -EINPROGRESS) { if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) return -EFAULT; -- cgit v0.10.2 From 5bdfff96c69a4d5ab9c49e60abf9e070ecd2acbb Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sat, 15 Feb 2014 22:02:28 +0800 Subject: workqueue: ensure @task is valid across kthread_stop() When a kworker should die, the kworkre is notified through WORKER_DIE flag instead of kthread_should_stop(). This, IIRC, is primarily to keep the test synchronized inside worker_pool lock. WORKER_DIE is first set while holding pool->lock, the lock is dropped and kthread_stop() is called. Unfortunately, this means that there's a slight chance that the target kworker may see WORKER_DIE before kthread_stop() finishes and exits and frees the target task before or during kthread_stop(). Fix it by pinning the target task before setting WORKER_DIE and putting it after kthread_stop() is done. tj: Improved patch description and comment. Moved pinning above WORKER_DIE for better signify what it's protecting. CC: stable@vger.kernel.org Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 82ef9f3..193e977 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1851,6 +1851,12 @@ static void destroy_worker(struct worker *worker) if (worker->flags & WORKER_IDLE) pool->nr_idle--; + /* + * Once WORKER_DIE is set, the kworker may destroy itself at any + * point. Pin to ensure the task stays until we're done with it. + */ + get_task_struct(worker->task); + list_del_init(&worker->entry); worker->flags |= WORKER_DIE; @@ -1859,6 +1865,7 @@ static void destroy_worker(struct worker *worker) spin_unlock_irq(&pool->lock); kthread_stop(worker->task); + put_task_struct(worker->task); kfree(worker); spin_lock_irq(&pool->lock); -- cgit v0.10.2 From 71c5498eed06b5ac4325a525ed83aeed3e9a250a Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Tue, 18 Feb 2014 15:57:29 +0800 Subject: Revert "of: search the best compatible match first in __of_match_node()" This reverts commit 06b29e76a74b2373e6f8b5a7938b3630b9ae98b2. As pointed out by Grant Likely, we should also take the type and name into account when searching the best compatible match. That means the match with compatible, type and name should be better than the match just with the same compatible string. So revert this and we will implement another method to find the best match entry. Signed-off-by: Kevin Hao Signed-off-by: Grant Likely diff --git a/drivers/of/base.c b/drivers/of/base.c index 10b5110..ba195fb 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -730,49 +730,13 @@ out: } EXPORT_SYMBOL(of_find_node_with_property); -static const struct of_device_id * -of_match_compatible(const struct of_device_id *matches, - const struct device_node *node) -{ - const char *cp; - int cplen, l; - const struct of_device_id *m; - - cp = __of_get_property(node, "compatible", &cplen); - while (cp && (cplen > 0)) { - m = matches; - while (m->name[0] || m->type[0] || m->compatible[0]) { - /* Only match for the entries without type and name */ - if (m->name[0] || m->type[0] || - of_compat_cmp(m->compatible, cp, - strlen(m->compatible))) - m++; - else - return m; - } - - /* Get node's next compatible string */ - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return NULL; -} - static const struct of_device_id *__of_match_node(const struct of_device_id *matches, const struct device_node *node) { - const struct of_device_id *m; - if (!matches) return NULL; - m = of_match_compatible(matches, node); - if (m) - return m; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { int match = 1; if (matches->name[0]) @@ -796,12 +760,7 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, * @matches: array of of device match structures to search in * @node: the of device structure to match against * - * Low level utility function used by device matching. We have two ways - * of matching: - * - Try to find the best compatible match by comparing each compatible - * string of device node with all the given matches respectively. - * - If the above method failed, then try to match the compatible by using - * __of_device_is_compatible() besides the match in type and name. + * Low level utility function used by device matching. */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) -- cgit v0.10.2 From 5a98268e0f657e8f1289ad9b83fe010f0208565d Mon Sep 17 00:00:00 2001 From: Asai Thambi S P Date: Tue, 18 Feb 2014 14:49:17 -0800 Subject: mtip32xx: Reduce the number of unaligned writes to 2 After several experiments, deduced the the optimal number of unaligned writes to be 2. Changing the value accordingly. Signed-off-by: Asai Thambi S P Signed-off-by: Sam Bradshaw Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index b52e9a6..54174cb 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -53,7 +53,7 @@ #define MTIP_FTL_REBUILD_TIMEOUT_MS 2400000 /* unaligned IO handling */ -#define MTIP_MAX_UNALIGNED_SLOTS 8 +#define MTIP_MAX_UNALIGNED_SLOTS 2 /* Macro to extract the tag bit number from a tag value. */ #define MTIP_TAG_BIT(tag) (tag & 0x1F) -- cgit v0.10.2 From d7cf0c34af067555737193b6c1aa7abaa677f29c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Feb 2014 15:20:51 +0300 Subject: af_packet: remove a stray tab in packet_set_ring() At first glance it looks like there is a missing curly brace but actually the code works the same either way. I have adjusted the indenting but left the code the same. Signed-off-by: Dan Carpenter Acked-by: Daniel Borkmann Signed-off-by: David S. Miller diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b5dc116..48a6a93 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3804,7 +3804,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, */ if (!tx_ring) init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring); - break; + break; default: break; } -- cgit v0.10.2 From ce5eaf023a231ebd313ecc7e0b33278513d8ad80 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Feb 2014 12:55:42 +0000 Subject: NET: fec: only enable napi if we are successful If napi is left enabled after a failed attempt to bring the interface up, we BUG: fec 2188000.ethernet eth0: no PHY, assuming direct connection to switch libphy: PHY fixed-0:00 not found fec 2188000.ethernet eth0: could not attach to PHY ------------[ cut here ]------------ kernel BUG at include/linux/netdevice.h:502! Internal error: Oops - BUG: 0 [#1] SMP ARM ... PC is at fec_enet_open+0x4d0/0x500 LR is at __dev_open+0xa4/0xfc Only enable napi after we are past all the failure paths. Signed-off-by: Russell King Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index d4782b4..903362a 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1778,8 +1778,6 @@ fec_enet_open(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); int ret; - napi_enable(&fep->napi); - /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. */ @@ -1794,6 +1792,8 @@ fec_enet_open(struct net_device *ndev) fec_enet_free_buffers(ndev); return ret; } + + napi_enable(&fep->napi); phy_start(fep->phy_dev); netif_start_queue(ndev); fep->opened = 1; -- cgit v0.10.2 From 4b636b535d55f89077691e737930a615422113d6 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 18 Feb 2014 14:18:11 +0100 Subject: net: ethernet: update dependency and help text of mvneta With the introduction of the support for Armada 375 and Armada 38x, the hidden Kconfig option MACH_ARMADA_370_XP is being renamed to MACH_MVEBU_V7. Therefore, the dependency that was used for the mvneta driver can no longer work. This commit replaces this dependency by a dependency on PLAT_ORION, which is used similarly for the mv643xx_eth driver. In addition to this, it takes this opportunity to adjust the description and help text to indicate that the driver can is also used for Armada 38x. Note that Armada 375 cannot use this driver as it has a completely different networking unit, which will require a separate driver. Signed-off-by: Thomas Petazzoni Acked-by: Jason Cooper Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig index 6300fd2..68e6a66 100644 --- a/drivers/net/ethernet/marvell/Kconfig +++ b/drivers/net/ethernet/marvell/Kconfig @@ -43,12 +43,12 @@ config MVMDIO This driver is used by the MV643XX_ETH and MVNETA drivers. config MVNETA - tristate "Marvell Armada 370/XP network interface support" - depends on MACH_ARMADA_370_XP + tristate "Marvell Armada 370/38x/XP network interface support" + depends on PLAT_ORION select MVMDIO ---help--- This driver supports the network interface units in the - Marvell ARMADA XP and ARMADA 370 SoC family. + Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family. Note that this driver is distinct from the mv643xx_eth driver, which should be used for the older Marvell SoCs -- cgit v0.10.2 From f15c586d1d9d99b04712d2b2eeee31ab29db77ff Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 18 Feb 2014 12:16:58 +0000 Subject: of_mdio: fix phy interrupt passing The of_mdiobus_register_phy() is not setting phy->irq thus causing some drivers to incorrectly assume that the PHY does not have an IRQ associated with it. Not only do some drivers report no IRQ they do not install an interrupt handler for the PHY. Simplify the code setting irq and set the phy->irq at the same time so that we cover the following issues, which should cover all the cases the code will find: - Set phy->irq if node has irq property and mdio->irq is NULL - Set phy->irq if node has no irq and mdio->irq is not NULL - Leave phy->irq as PHY_POLL default if none of the above This fixes the issue: net eth0: attached PHY 1 (IRQ -1) to driver Micrel KSZ8041RNLI to the correct: net eth0: attached PHY 1 (IRQ 416) to driver Micrel KSZ8041RNLI Signed-off-by: Ben Dooks Signed-off-by: David S. Miller diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 495facc..5b3c24f 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -48,7 +48,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi { struct phy_device *phy; bool is_c45; - int rc, prev_irq; + int rc; u32 max_speed = 0; is_c45 = of_device_is_compatible(child, @@ -58,12 +58,14 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi if (!phy || IS_ERR(phy)) return 1; - if (mdio->irq) { - prev_irq = mdio->irq[addr]; - mdio->irq[addr] = - irq_of_parse_and_map(child, 0); - if (!mdio->irq[addr]) - mdio->irq[addr] = prev_irq; + rc = irq_of_parse_and_map(child, 0); + if (rc > 0) { + phy->irq = rc; + if (mdio->irq) + mdio->irq[addr] = rc; + } else { + if (mdio->irq) + phy->irq = mdio->irq[addr]; } /* Associate the OF node with the device structure so it -- cgit v0.10.2 From 22f08ad9721d4d1a92061b60026144627a60d644 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Feb 2014 09:47:49 -0800 Subject: MAINTAINERS: add entry for the PHY library The PHY library has been subject to some changes, new drivers and DT interactions over the past few months. Add myself as a maintainer for the core PHY library parts and drivers. Make sure the PHY library entry also covers the Device Tree files which have a close interaction with the MDIO bus, PHY connection and Ethernet PHY mode parsing. CC: Grant Likely CC: Shaohui Xie CC: Andy Fleming Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index 091b50e..c8b3975 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3324,6 +3324,17 @@ S: Maintained F: include/linux/netfilter_bridge/ F: net/bridge/ +ETHERNET PHY LIBRARY +M: Florian Fainelli +L: netdev@vger.kernel.org +S: Maintained +F: include/linux/phy.h +F: include/linux/phy_fixed.h +F: drivers/net/phy/ +F: Documentation/networking/phy.txt +F: drivers/of/of_mdio.c +F: drivers/of/of_net.c + EXT2 FILE SYSTEM M: Jan Kara L: linux-ext4@vger.kernel.org -- cgit v0.10.2 From 532de3fc72adc2a6525c4d53c07bf81e1732083d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 13 Feb 2014 13:29:31 -0500 Subject: cgroup: update cgroup_enable_task_cg_lists() to grab siglock Currently, there's nothing preventing cgroup_enable_task_cg_lists() from missing set PF_EXITING and race against cgroup_exit(). Depending on the timing, cgroup_exit() may finish with the task still linked on css_set leading to list corruption. Fix it by grabbing siglock in cgroup_enable_task_cg_lists() so that PF_EXITING is guaranteed to be visible. This whole on-demand cg_list optimization is extremely fragile and has ample possibility to lead to bugs which can cause things like once-a-year oops during boot. I'm wondering whether the better approach would be just adding "cgroup_disable=all" handling which disables the whole cgroup rather than tempting fate with this on-demand craziness. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 68d8710..105f273 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2905,9 +2905,14 @@ static void cgroup_enable_task_cg_lists(void) * We should check if the process is exiting, otherwise * it will race with cgroup_exit() in that the list * entry won't be deleted though the process has exited. + * Do it while holding siglock so that we don't end up + * racing against cgroup_exit(). */ + spin_lock_irq(&p->sighand->siglock); if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list)) list_add(&p->cg_list, &task_css_set(p)->tasks); + spin_unlock_irq(&p->sighand->siglock); + task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); -- cgit v0.10.2 From 500a91571f0a5d0d3242d83802ea2fd1faccc66e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 15 Feb 2014 17:54:06 -0800 Subject: hwmon: (max1668) Fix writing the minimum temperature When trying to set the minimum temperature, the driver was erroneously writing the maximum temperature into the chip. Signed-off-by: Guenter Roeck Cc: stable@vger.kernel.org # v3.2+ Reviewed-by: Jean Delvare diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c index a762635..029b65e 100644 --- a/drivers/hwmon/max1668.c +++ b/drivers/hwmon/max1668.c @@ -243,7 +243,7 @@ static ssize_t set_temp_min(struct device *dev, data->temp_min[index] = clamp_val(temp/1000, -128, 127); if (i2c_smbus_write_byte_data(client, MAX1668_REG_LIML_WR(index), - data->temp_max[index])) + data->temp_min[index])) count = -EIO; mutex_unlock(&data->update_lock); -- cgit v0.10.2 From 763fbff2bef5d5db5a993b54c29c841432e056ec Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 13 Feb 2014 17:18:26 -0700 Subject: ARM: tegra: fix RTC0 alias for Cardhu This alias entry was evidently cut/paste from a different board, and not correctly updated to match Cardhu. Fix this. Fixes: 553c0a200e20 ("ARM: tegra: set up /aliases entries for RTCs") Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index 9104224..1e156d9 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -28,7 +28,7 @@ compatible = "nvidia,cardhu", "nvidia,tegra30"; aliases { - rtc0 = "/i2c@7000d000/tps6586x@34"; + rtc0 = "/i2c@7000d000/tps65911@2d"; rtc1 = "/rtc@7000e000"; }; -- cgit v0.10.2 From 28a9f3b078c545064dcf4b46d2c6917554d1642e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 18 Feb 2014 10:35:05 +0800 Subject: ARM: imx6: build pm-imx6q.c independently of CONFIG_PM When building a kernel image with only CONFIG_CPU_IDLE but no CONFIG_PM, we will get the following link error. LD init/built-in.o arch/arm/mach-imx/built-in.o: In function `imx6q_enter_wait': platform-spi_imx.c:(.text+0x25c0): undefined reference to `imx6q_set_lpm' platform-spi_imx.c:(.text+0x25d4): undefined reference to `imx6q_set_lpm' arch/arm/mach-imx/built-in.o: In function `imx6q_cpuidle_init': platform-spi_imx.c:(.init.text+0x75d4): undefined reference to `imx6q_set_chicken_bit' make[1]: *** [vmlinux] Error 1 Since pm-imx6q.c has been a collection of library functions that access CCM low-power registers used by not only suspend but also cpuidle and other drivers, let's build pm-imx6q.c independently of CONFIG_PM to fix above error. Reported-by: Lucas Stach Signed-off-by: Shawn Guo Cc: stable@vger.kernel.org Acked-by: Christian Gmeiner Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index befcaf5..ec41964 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -101,11 +101,9 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o -ifeq ($(CONFIG_PM),y) obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o # i.MX6SL reuses i.MX6Q code obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o -endif # i.MX5 based machines obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 59c3b9b..baf439d 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -144,13 +144,11 @@ void imx6q_set_chicken_bit(void); void imx_cpu_die(unsigned int cpu); int imx_cpu_kill(unsigned int cpu); -#ifdef CONFIG_PM void imx6q_pm_init(void); void imx6q_pm_set_ccm_base(void __iomem *base); +#ifdef CONFIG_PM void imx5_pm_init(void); #else -static inline void imx6q_pm_init(void) {} -static inline void imx6q_pm_set_ccm_base(void __iomem *base) {} static inline void imx5_pm_init(void) {} #endif -- cgit v0.10.2 From 6964d91db2becfe80658f50584d264708ca7f49e Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Mon, 17 Feb 2014 14:52:11 +0530 Subject: cpufreq: remove sysfs link when a cpu != policy->cpu, is removed Commit 42f921a (cpufreq: remove sysfs files for CPUs which failed to come back after resume) tried to do this but missed this piece of code to fix. Currently we are getting this on suspend/resume: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 877 at fs/sysfs/dir.c:52 sysfs_warn_dup+0x68/0x84() sysfs: cannot create duplicate filename '/devices/system/cpu/cpu1/cpufreq' Modules linked in: brcmfmac brcmutil CPU: 0 PID: 877 Comm: test-rtc-resume Not tainted 3.14.0-rc2-00259-g9398a10cd964 #12 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x80/0xcc) [] (dump_stack) from [] (warn_slowpath_common+0x64/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) [] (warn_slowpath_fmt) from [] (sysfs_warn_dup+0x68/0x84) [] (sysfs_warn_dup) from [] (sysfs_do_create_link_sd+0xb0/0xb8) [] (sysfs_do_create_link_sd) from [] (__cpufreq_add_dev.isra.27+0x2a8/0x814) [] (__cpufreq_add_dev.isra.27) from [] (cpufreq_cpu_callback+0x70/0x8c) [] (cpufreq_cpu_callback) from [] (notifier_call_chain+0x44/0x84) [] (notifier_call_chain) from [] (__cpu_notify+0x28/0x44) [] (__cpu_notify) from [] (_cpu_up+0xf0/0x140) [] (_cpu_up) from [] (enable_nonboot_cpus+0x68/0xb0) [] (enable_nonboot_cpus) from [] (suspend_devices_and_enter+0x198/0x2dc) [] (suspend_devices_and_enter) from [] (pm_suspend+0x174/0x1e8) [] (pm_suspend) from [] (state_store+0x6c/0xbc) [] (state_store) from [] (kobj_attr_store+0x14/0x20) [] (kobj_attr_store) from [] (sysfs_kf_write+0x44/0x48) [] (sysfs_kf_write) from [] (kernfs_fop_write+0xb4/0x14c) [] (kernfs_fop_write) from [] (vfs_write+0xa8/0x180) [] (vfs_write) from [] (SyS_write+0x3c/0x70) [] (SyS_write) from [] (ret_fast_syscall+0x0/0x30) ---[ end trace 76969904b614c18f ]--- Fix this by removing sysfs link for cpufreq directory when cpu removed isn't policy->cpu. Revamps: 42f921a (cpufreq: remove sysfs files for CPUs which failed to come back after resume) Reported-and-tested-by: Stephen Warren Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 08ca8c9..cb003a6 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1323,8 +1323,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, up_read(&policy->rwsem); if (cpu != policy->cpu) { - if (!frozen) - sysfs_remove_link(&dev->kobj, "cpufreq"); + sysfs_remove_link(&dev->kobj, "cpufreq"); } else if (cpus > 1) { new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu); if (new_cpu >= 0) { -- cgit v0.10.2 From c3274763bfc3bf1ececa269ed6e6c4d7ec1c3e5e Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Mon, 17 Feb 2014 16:18:21 +0530 Subject: cpufreq: powernow-k8: Initialize per-cpu data-structures properly The powernow-k8 driver maintains a per-cpu data-structure called powernow_data that is used to perform the frequency transitions. It initializes this data structure only for the policy->cpu. So, accesses to this data structure by other CPUs results in various problems because they would have been uninitialized. Specifically, if a cpu (!= policy->cpu) invokes the drivers' ->get() function, it returns 0 as the KHz value, since its per-cpu memory doesn't point to anything valid. This causes problems during suspend/resume since cpufreq_update_policy() tries to enforce this (0 KHz) as the current frequency of the CPU, and this madness gets propagated to adjust_jiffies() as well. Eventually, lots of things start breaking down, including the r8169 ethernet card, in one particularly interesting case reported by Pierre Ossman. Fix this by initializing the per-cpu data-structures of all the CPUs in the policy appropriately. References: https://bugzilla.kernel.org/show_bug.cgi?id=70311 Reported-by: Pierre Ossman Signed-off-by: Srivatsa S. Bhat Cc: All applicable Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index e10b646..6684e03 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1076,7 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) { struct powernow_k8_data *data; struct init_on_cpu init_on_cpu; - int rc; + int rc, cpu; smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1); if (rc) @@ -1140,7 +1140,9 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); - per_cpu(powernow_data, pol->cpu) = data; + /* Point all the CPUs in this policy to the same data */ + for_each_cpu(cpu, pol->cpus) + per_cpu(powernow_data, cpu) = data; return 0; @@ -1155,6 +1157,7 @@ err_out: static int powernowk8_cpu_exit(struct cpufreq_policy *pol) { struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); + int cpu; if (!data) return -EINVAL; @@ -1165,7 +1168,8 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol) kfree(data->powernow_table); kfree(data); - per_cpu(powernow_data, pol->cpu) = NULL; + for_each_cpu(cpu, pol->cpus) + per_cpu(powernow_data, cpu) = NULL; return 0; } -- cgit v0.10.2 From 688b56b485578465f6619b9529d08c2b95641915 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 18 Feb 2014 23:03:31 +0100 Subject: ARM: tegra: Add head numbers to display controllers The number of the head specifies the index of the display controller unit and is required to properly configure outputs so that they receive video data from the correct source. Signed-off-by: Thierry Reding Acked-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index 389e987..44ec401 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi @@ -57,6 +57,8 @@ resets = <&tegra_car 27>; reset-names = "dc"; + nvidia,head = <0>; + rgb { status = "disabled"; }; @@ -72,6 +74,8 @@ resets = <&tegra_car 26>; reset-names = "dc"; + nvidia,head = <1>; + rgb { status = "disabled"; }; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 480ecda..48d2a7f 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -94,6 +94,8 @@ resets = <&tegra_car 27>; reset-names = "dc"; + nvidia,head = <0>; + rgb { status = "disabled"; }; @@ -109,6 +111,8 @@ resets = <&tegra_car 26>; reset-names = "dc"; + nvidia,head = <1>; + rgb { status = "disabled"; }; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index ed8e770..19a84e9 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -170,6 +170,8 @@ resets = <&tegra_car 27>; reset-names = "dc"; + nvidia,head = <0>; + rgb { status = "disabled"; }; @@ -185,6 +187,8 @@ resets = <&tegra_car 26>; reset-names = "dc"; + nvidia,head = <1>; + rgb { status = "disabled"; }; -- cgit v0.10.2 From 423f0c4a3d32cc83dff204324f59aecb4516f3cf Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Feb 2014 14:32:48 +0530 Subject: ASoC: cs42l51: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘cs42l51’ is not used. Remove it. Signed-off-by: Sachin Kamat Acked-by: Brian Austin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index e53c871..3eab460 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -487,7 +487,6 @@ static struct snd_soc_dai_driver cs42l51_dai = { static int cs42l51_probe(struct snd_soc_codec *codec) { - struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); int ret, reg; ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); -- cgit v0.10.2 From 30686c350628a68852f8abd67557aecb137789d5 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 16:05:27 +0000 Subject: ASoC: dapm: Correct regulator bypass error messages The error messages for bypassing/unbypassing a regulator appear to be swapped round, this patch corrects these. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dc8ff13..fd39cd2 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1218,7 +1218,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, ret = regulator_allow_bypass(w->regulator, false); if (ret != 0) dev_warn(w->dapm->dev, - "ASoC: Failed to bypass %s: %d\n", + "ASoC: Failed to unbypass %s: %d\n", w->name, ret); } @@ -1228,7 +1228,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, ret = regulator_allow_bypass(w->regulator, true); if (ret != 0) dev_warn(w->dapm->dev, - "ASoC: Failed to unbypass %s: %d\n", + "ASoC: Failed to bypass %s: %d\n", w->name, ret); } @@ -3248,7 +3248,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, ret = regulator_allow_bypass(w->regulator, true); if (ret != 0) dev_warn(w->dapm->dev, - "ASoC: Failed to unbypass %s: %d\n", + "ASoC: Failed to bypass %s: %d\n", w->name, ret); } break; -- cgit v0.10.2 From 8859685785bfafadf9bc922dd3a2278e59886947 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 18 Feb 2014 16:51:58 -0700 Subject: ARM: tegra: only run PL310 init on systems with one Fix tegra_init_cache() to check whether the system has a PL310 cache before touching the PL310 registers. This prevents access to non-existent registers on Tegra114 and later. Note for stable kernels: In <= v3.12, the file to patch is arch/arm/mach-tegra/common.c. Cc: # v3.9+ Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 303a285..6191603 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -73,10 +73,20 @@ u32 tegra_uart_config[3] = { static void __init tegra_init_cache(void) { #ifdef CONFIG_CACHE_L2X0 + static const struct of_device_id pl310_ids[] __initconst = { + { .compatible = "arm,pl310-cache", }, + {} + }; + + struct device_node *np; int ret; void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; u32 aux_ctrl, cache_type; + np = of_find_matching_node(NULL, pl310_ids); + if (!np) + return; + cache_type = readl(p + L2X0_CACHE_TYPE); aux_ctrl = (cache_type & 0x700) << (17-8); aux_ctrl |= 0x7C400001; -- cgit v0.10.2 From 7a01e707a324a4585949ca3df6c7f7485d8783f2 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 19 Feb 2014 15:33:05 +1100 Subject: xfs: xfs_sb_read_verify() doesn't flag bad crcs on primary sb My earlier commit 10e6e65 deserves a layer or two of brown paper bags. The logic in that commit means that a CRC failure on the primary superblock will *never* result in an error return. Hopefully this fixes it, so that we always return the error if it's a primary superblock, otherwise only if the filesystem has CRCs enabled. Signed-off-by: Eric Sandeen Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index b7c9aea..5071ccb 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -614,7 +614,7 @@ xfs_sb_read_verify( if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), offsetof(struct xfs_sb, sb_crc))) { /* Only fail bad secondaries on a known V5 filesystem */ - if (bp->b_bn != XFS_SB_DADDR && + if (bp->b_bn == XFS_SB_DADDR || xfs_sb_version_hascrc(&mp->m_sb)) { error = EFSCORRUPTED; goto out_error; -- cgit v0.10.2 From 603597c9375b8162edae3231dd4cc7f1f500de79 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 18 Feb 2014 15:57:35 +0100 Subject: ASoC: Add ADAU1977 CODEC driver This patch adds support for the ADAU1977, ADAU1978 and ADAU1979 audio CODEC devices. They are a family of 4-channel differential input audio ADC devices. They can be connected to either a SPI or I2C bus. The driver is implemented in three modules, one main module (adau1977.ko) which implements the device logic and one module each for SPI (adau1977-spi.ko) and I2C (adau1977-i2c.ko) bus access. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/linux/platform_data/adau1977.h b/include/linux/platform_data/adau1977.h new file mode 100644 index 0000000..bed11d9 --- /dev/null +++ b/include/linux/platform_data/adau1977.h @@ -0,0 +1,45 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#ifndef __LINUX_PLATFORM_DATA_ADAU1977_H__ +#define __LINUX_PLATFORM_DATA_ADAU1977_H__ + +/** + * enum adau1977_micbias - ADAU1977 MICBIAS pin voltage setting + * @ADAU1977_MICBIAS_5V0: MICBIAS is set to 5.0 V + * @ADAU1977_MICBIAS_5V5: MICBIAS is set to 5.5 V + * @ADAU1977_MICBIAS_6V0: MICBIAS is set to 6.0 V + * @ADAU1977_MICBIAS_6V5: MICBIAS is set to 6.5 V + * @ADAU1977_MICBIAS_7V0: MICBIAS is set to 7.0 V + * @ADAU1977_MICBIAS_7V5: MICBIAS is set to 7.5 V + * @ADAU1977_MICBIAS_8V0: MICBIAS is set to 8.0 V + * @ADAU1977_MICBIAS_8V5: MICBIAS is set to 8.5 V + * @ADAU1977_MICBIAS_9V0: MICBIAS is set to 9.0 V + */ +enum adau1977_micbias { + ADAU1977_MICBIAS_5V0 = 0x0, + ADAU1977_MICBIAS_5V5 = 0x1, + ADAU1977_MICBIAS_6V0 = 0x2, + ADAU1977_MICBIAS_6V5 = 0x3, + ADAU1977_MICBIAS_7V0 = 0x4, + ADAU1977_MICBIAS_7V5 = 0x5, + ADAU1977_MICBIAS_8V0 = 0x6, + ADAU1977_MICBIAS_8V5 = 0x7, + ADAU1977_MICBIAS_9V0 = 0x8, +}; + +/** + * struct adau1977_platform_data - Platform configuration data for the ADAU1977 + * @micbias: Specifies the voltage for the MICBIAS pin + */ +struct adau1977_platform_data { + enum adau1977_micbias micbias; +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9ea428b..4535674 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -24,6 +24,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_ADAU1373 if I2C select SND_SOC_ADAV801 if SPI_MASTER select SND_SOC_ADAV803 if I2C + select SND_SOC_ADAU1977_SPI if SPI_MASTER + select SND_SOC_ADAU1977_I2C if I2C select SND_SOC_ADAU1701 if I2C select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER @@ -200,6 +202,19 @@ config SND_SOC_ADAU1701 config SND_SOC_ADAU1373 tristate +config SND_SOC_ADAU1977 + tristate + +config SND_SOC_ADAU1977_SPI + tristate + select SND_SOC_ADAU1977 + select REGMAP_SPI + +config SND_SOC_ADAU1977_I2C + tristate + select SND_SOC_ADAU1977 + select REGMAP_I2C + config SND_SOC_ADAV80X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1b2c6ec..bfd85ec 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -7,6 +7,9 @@ snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau1373-objs := adau1373.o +snd-soc-adau1977-objs := adau1977.o +snd-soc-adau1977-spi-objs := adau1977-spi.o +snd-soc-adau1977-i2c-objs := adau1977-i2c.o snd-soc-adav80x-objs := adav80x.o snd-soc-adav801-objs := adav801.o snd-soc-adav803-objs := adav803.o @@ -139,6 +142,9 @@ obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o +obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o +obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o +obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c new file mode 100644 index 0000000..9700e8c --- /dev/null +++ b/sound/soc/codecs/adau1977-i2c.c @@ -0,0 +1,59 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include + +#include "adau1977.h" + +static int adau1977_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = adau1977_regmap_config; + config.val_bits = 8; + config.reg_bits = 8; + + return adau1977_probe(&client->dev, + devm_regmap_init_i2c(client, &config), + id->driver_data, NULL); +} + +static int adau1977_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id adau1977_i2c_ids[] = { + { "adau1977", ADAU1977 }, + { "adau1978", ADAU1978 }, + { "adau1979", ADAU1978 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids); + +static struct i2c_driver adau1977_i2c_driver = { + .driver = { + .name = "adau1977", + .owner = THIS_MODULE, + }, + .probe = adau1977_i2c_probe, + .remove = adau1977_i2c_remove, + .id_table = adau1977_i2c_ids, +}; +module_i2c_driver(adau1977_i2c_driver); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c new file mode 100644 index 0000000..b05cf5d --- /dev/null +++ b/sound/soc/codecs/adau1977-spi.c @@ -0,0 +1,76 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include + +#include "adau1977.h" + +static void adau1977_spi_switch_mode(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + + /* + * To get the device into SPI mode CLATCH has to be pulled low three + * times. Do this by issuing three dummy reads. + */ + spi_w8r8(spi, 0x00); + spi_w8r8(spi, 0x00); + spi_w8r8(spi, 0x00); +} + +static int adau1977_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap_config config; + + if (!id) + return -EINVAL; + + config = adau1977_regmap_config; + config.val_bits = 8; + config.reg_bits = 16; + config.read_flag_mask = 0x1; + + return adau1977_probe(&spi->dev, + devm_regmap_init_spi(spi, &config), + id->driver_data, adau1977_spi_switch_mode); +} + +static int adau1977_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static const struct spi_device_id adau1977_spi_ids[] = { + { "adau1977", ADAU1977 }, + { "adau1978", ADAU1978 }, + { "adau1979", ADAU1978 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); + +static struct spi_driver adau1977_spi_driver = { + .driver = { + .name = "adau1977", + .owner = THIS_MODULE, + }, + .probe = adau1977_spi_probe, + .remove = adau1977_spi_remove, + .id_table = adau1977_spi_ids, +}; +module_spi_driver(adau1977_spi_driver); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c new file mode 100644 index 0000000..fd55da7 --- /dev/null +++ b/sound/soc/codecs/adau1977.c @@ -0,0 +1,1018 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "adau1977.h" + +#define ADAU1977_REG_POWER 0x00 +#define ADAU1977_REG_PLL 0x01 +#define ADAU1977_REG_BOOST 0x02 +#define ADAU1977_REG_MICBIAS 0x03 +#define ADAU1977_REG_BLOCK_POWER_SAI 0x04 +#define ADAU1977_REG_SAI_CTRL0 0x05 +#define ADAU1977_REG_SAI_CTRL1 0x06 +#define ADAU1977_REG_CMAP12 0x07 +#define ADAU1977_REG_CMAP34 0x08 +#define ADAU1977_REG_SAI_OVERTEMP 0x09 +#define ADAU1977_REG_POST_ADC_GAIN(x) (0x0a + (x)) +#define ADAU1977_REG_MISC_CONTROL 0x0e +#define ADAU1977_REG_DIAG_CONTROL 0x10 +#define ADAU1977_REG_STATUS(x) (0x11 + (x)) +#define ADAU1977_REG_DIAG_IRQ1 0x15 +#define ADAU1977_REG_DIAG_IRQ2 0x16 +#define ADAU1977_REG_ADJUST1 0x17 +#define ADAU1977_REG_ADJUST2 0x18 +#define ADAU1977_REG_ADC_CLIP 0x19 +#define ADAU1977_REG_DC_HPF_CAL 0x1a + +#define ADAU1977_POWER_RESET BIT(7) +#define ADAU1977_POWER_PWUP BIT(0) + +#define ADAU1977_PLL_CLK_S BIT(4) +#define ADAU1977_PLL_MCS_MASK 0x7 + +#define ADAU1977_MICBIAS_MB_VOLTS_MASK 0xf0 +#define ADAU1977_MICBIAS_MB_VOLTS_OFFSET 4 + +#define ADAU1977_BLOCK_POWER_SAI_LR_POL BIT(7) +#define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6) +#define ADAU1977_BLOCK_POWER_SAI_LDO_EN BIT(5) + +#define ADAU1977_SAI_CTRL0_FMT_MASK (0x3 << 6) +#define ADAU1977_SAI_CTRL0_FMT_I2S (0x0 << 6) +#define ADAU1977_SAI_CTRL0_FMT_LJ (0x1 << 6) +#define ADAU1977_SAI_CTRL0_FMT_RJ_24BIT (0x2 << 6) +#define ADAU1977_SAI_CTRL0_FMT_RJ_16BIT (0x3 << 6) + +#define ADAU1977_SAI_CTRL0_SAI_MASK (0x7 << 3) +#define ADAU1977_SAI_CTRL0_SAI_I2S (0x0 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_2 (0x1 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_4 (0x2 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_8 (0x3 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_16 (0x4 << 3) + +#define ADAU1977_SAI_CTRL0_FS_MASK (0x7) +#define ADAU1977_SAI_CTRL0_FS_8000_12000 (0x0) +#define ADAU1977_SAI_CTRL0_FS_16000_24000 (0x1) +#define ADAU1977_SAI_CTRL0_FS_32000_48000 (0x2) +#define ADAU1977_SAI_CTRL0_FS_64000_96000 (0x3) +#define ADAU1977_SAI_CTRL0_FS_128000_192000 (0x4) + +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK (0x3 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_32 (0x0 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_24 (0x1 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_16 (0x2 << 5) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK (0x1 << 4) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT (0x1 << 4) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT (0x0 << 4) +#define ADAU1977_SAI_CTRL1_LRCLK_PULSE BIT(3) +#define ADAU1977_SAI_CTRL1_MSB BIT(2) +#define ADAU1977_SAI_CTRL1_BCLKRATE_16 (0x1 << 1) +#define ADAU1977_SAI_CTRL1_BCLKRATE_32 (0x0 << 1) +#define ADAU1977_SAI_CTRL1_BCLKRATE_MASK (0x1 << 1) +#define ADAU1977_SAI_CTRL1_MASTER BIT(0) + +#define ADAU1977_SAI_OVERTEMP_DRV_C(x) BIT(4 + (x)) +#define ADAU1977_SAI_OVERTEMP_DRV_HIZ BIT(3) + +#define ADAU1977_MISC_CONTROL_SUM_MODE_MASK (0x3 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_1CH (0x2 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_2CH (0x1 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_4CH (0x0 << 6) +#define ADAU1977_MISC_CONTROL_MMUTE BIT(4) +#define ADAU1977_MISC_CONTROL_DC_CAL BIT(0) + +#define ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET 4 +#define ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET 0 + +struct adau1977 { + struct regmap *regmap; + bool right_j; + unsigned int sysclk; + enum adau1977_sysclk_src sysclk_src; + struct gpio_desc *reset_gpio; + enum adau1977_type type; + + struct regulator *avdd_reg; + struct regulator *dvdd_reg; + + struct snd_pcm_hw_constraint_list constraints; + + struct device *dev; + void (*switch_mode)(struct device *dev); + + unsigned int max_master_fs; + unsigned int slot_width; + bool enabled; + bool master; +}; + +static const struct reg_default adau1977_reg_defaults[] = { + { 0x00, 0x00 }, + { 0x01, 0x41 }, + { 0x02, 0x4a }, + { 0x03, 0x7d }, + { 0x04, 0x3d }, + { 0x05, 0x02 }, + { 0x06, 0x00 }, + { 0x07, 0x10 }, + { 0x08, 0x32 }, + { 0x09, 0xf0 }, + { 0x0a, 0xa0 }, + { 0x0b, 0xa0 }, + { 0x0c, 0xa0 }, + { 0x0d, 0xa0 }, + { 0x0e, 0x02 }, + { 0x10, 0x0f }, + { 0x15, 0x20 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x00 }, + { 0x1a, 0x00 }, +}; + +static const DECLARE_TLV_DB_MINMAX_MUTE(adau1977_adc_gain, -3562, 6000); + +static const struct snd_soc_dapm_widget adau1977_micbias_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU1977_REG_MICBIAS, + 3, 0, NULL, 0) +}; + +static const struct snd_soc_dapm_widget adau1977_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Vref", ADAU1977_REG_BLOCK_POWER_SAI, + 4, 0, NULL, 0), + + SND_SOC_DAPM_ADC("ADC1", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 0, 0), + SND_SOC_DAPM_ADC("ADC2", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 1, 0), + SND_SOC_DAPM_ADC("ADC3", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 2, 0), + SND_SOC_DAPM_ADC("ADC4", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 3, 0), + + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + SND_SOC_DAPM_INPUT("AIN3"), + SND_SOC_DAPM_INPUT("AIN4"), + + SND_SOC_DAPM_OUTPUT("VREF"), +}; + +static const struct snd_soc_dapm_route adau1977_dapm_routes[] = { + { "ADC1", NULL, "AIN1" }, + { "ADC2", NULL, "AIN2" }, + { "ADC3", NULL, "AIN3" }, + { "ADC4", NULL, "AIN4" }, + + { "ADC1", NULL, "Vref" }, + { "ADC2", NULL, "Vref" }, + { "ADC3", NULL, "Vref" }, + { "ADC4", NULL, "Vref" }, + + { "VREF", NULL, "Vref" }, +}; + +#define ADAU1977_VOLUME(x) \ + SOC_SINGLE_TLV("ADC" #x " Capture Volume", \ + ADAU1977_REG_POST_ADC_GAIN((x) - 1), \ + 0, 255, 1, adau1977_adc_gain) + +#define ADAU1977_HPF_SWITCH(x) \ + SOC_SINGLE("ADC" #x " Highpass-Filter Capture Switch", \ + ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0) + +#define ADAU1977_DC_SUB_SWITCH(x) \ + SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \ + ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0) + +static const struct snd_kcontrol_new adau1977_snd_controls[] = { + ADAU1977_VOLUME(1), + ADAU1977_VOLUME(2), + ADAU1977_VOLUME(3), + ADAU1977_VOLUME(4), + + ADAU1977_HPF_SWITCH(1), + ADAU1977_HPF_SWITCH(2), + ADAU1977_HPF_SWITCH(3), + ADAU1977_HPF_SWITCH(4), + + ADAU1977_DC_SUB_SWITCH(1), + ADAU1977_DC_SUB_SWITCH(2), + ADAU1977_DC_SUB_SWITCH(3), + ADAU1977_DC_SUB_SWITCH(4), +}; + +static int adau1977_reset(struct adau1977 *adau1977) +{ + int ret; + + /* + * The reset bit is obviously volatile, but we need to be able to cache + * the other bits in the register, so we can't just mark the whole + * register as volatile. Since this is the only place where we'll ever + * touch the reset bit just bypass the cache for this operation. + */ + regcache_cache_bypass(adau1977->regmap, true); + ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_RESET); + regcache_cache_bypass(adau1977->regmap, false); + if (ret) + return ret; + + return ret; +} + +/* + * Returns the appropriate setting for ths FS field in the CTRL0 register + * depending on the rate. + */ +static int adau1977_lookup_fs(unsigned int rate) +{ + if (rate >= 8000 && rate <= 12000) + return ADAU1977_SAI_CTRL0_FS_8000_12000; + else if (rate >= 16000 && rate <= 24000) + return ADAU1977_SAI_CTRL0_FS_16000_24000; + else if (rate >= 32000 && rate <= 48000) + return ADAU1977_SAI_CTRL0_FS_32000_48000; + else if (rate >= 64000 && rate <= 96000) + return ADAU1977_SAI_CTRL0_FS_64000_96000; + else if (rate >= 128000 && rate <= 192000) + return ADAU1977_SAI_CTRL0_FS_128000_192000; + else + return -EINVAL; +} + +static int adau1977_lookup_mcs(struct adau1977 *adau1977, unsigned int rate, + unsigned int fs) +{ + unsigned int mcs; + + /* + * rate = sysclk / (512 * mcs_lut[mcs]) * 2**fs + * => mcs_lut[mcs] = sysclk / (512 * rate) * 2**fs + * => mcs_lut[mcs] = sysclk / ((512 / 2**fs) * rate) + */ + + rate *= 512 >> fs; + + if (adau1977->sysclk % rate != 0) + return -EINVAL; + + mcs = adau1977->sysclk / rate; + + /* The factors configured by MCS are 1, 2, 3, 4, 6 */ + if (mcs < 1 || mcs > 6 || mcs == 5) + return -EINVAL; + + mcs = mcs - 1; + if (mcs == 5) + mcs = 4; + + return mcs; +} + +static int adau1977_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + unsigned int rate = params_rate(params); + unsigned int slot_width; + unsigned int ctrl0, ctrl0_mask; + unsigned int ctrl1; + int mcs, fs; + int ret; + + fs = adau1977_lookup_fs(rate); + if (fs < 0) + return fs; + + if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) { + mcs = adau1977_lookup_mcs(adau1977, rate, fs); + if (mcs < 0) + return mcs; + } else { + mcs = 0; + } + + ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK; + ctrl0 = fs; + + if (adau1977->right_j) { + switch (params_width(params)) { + case 16: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT; + break; + case 24: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; + break; + default: + return -EINVAL; + } + ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK; + } + + if (adau1977->master) { + switch (params_width(params)) { + case 16: + ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT; + slot_width = 16; + break; + case 24: + case 32: + ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT; + slot_width = 32; + break; + default: + return -EINVAL; + } + + /* In TDM mode there is a fixed slot width */ + if (adau1977->slot_width) + slot_width = adau1977->slot_width; + + if (slot_width == 16) + ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16; + else + ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32; + + ret = regmap_update_bits(adau1977->regmap, + ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK | + ADAU1977_SAI_CTRL1_BCLKRATE_MASK, + ctrl1); + if (ret < 0) + return ret; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ctrl0_mask, ctrl0); + if (ret < 0) + return ret; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, + ADAU1977_PLL_MCS_MASK, mcs); +} + +static int adau1977_power_disable(struct adau1977 *adau1977) +{ + int ret = 0; + + if (!adau1977->enabled) + return 0; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_PWUP, 0); + if (ret) + return ret; + + regcache_mark_dirty(adau1977->regmap); + + if (adau1977->reset_gpio) + gpiod_set_value_cansleep(adau1977->reset_gpio, 0); + + regcache_cache_only(adau1977->regmap, true); + + regulator_disable(adau1977->avdd_reg); + if (adau1977->dvdd_reg) + regulator_disable(adau1977->dvdd_reg); + + adau1977->enabled = false; + + return 0; +} + +static int adau1977_power_enable(struct adau1977 *adau1977) +{ + unsigned int val; + int ret = 0; + + if (adau1977->enabled) + return 0; + + ret = regulator_enable(adau1977->avdd_reg); + if (ret) + return ret; + + if (adau1977->dvdd_reg) { + ret = regulator_enable(adau1977->dvdd_reg); + if (ret) + goto err_disable_avdd; + } + + if (adau1977->reset_gpio) + gpiod_set_value_cansleep(adau1977->reset_gpio, 1); + + regcache_cache_only(adau1977->regmap, false); + + if (adau1977->switch_mode) + adau1977->switch_mode(adau1977->dev); + + ret = adau1977_reset(adau1977); + if (ret) + goto err_disable_dvdd; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP); + if (ret) + goto err_disable_dvdd; + + ret = regcache_sync(adau1977->regmap); + if (ret) + goto err_disable_dvdd; + + /* + * The PLL register is not affected by the software reset. It is + * possible that the value of the register was changed to the + * default value while we were in cache only mode. In this case + * regcache_sync will skip over it and we have to manually sync + * it. + */ + ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val); + if (ret) + goto err_disable_dvdd; + + if (val == 0x41) { + regcache_cache_bypass(adau1977->regmap, true); + ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL, + 0x41); + if (ret) + goto err_disable_dvdd; + regcache_cache_bypass(adau1977->regmap, false); + } + + adau1977->enabled = true; + + return ret; + +err_disable_dvdd: + if (adau1977->dvdd_reg) + regulator_disable(adau1977->dvdd_reg); +err_disable_avdd: + regulator_disable(adau1977->avdd_reg); + return ret; +} + +static int adau1977_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + ret = adau1977_power_enable(adau1977); + break; + case SND_SOC_BIAS_OFF: + ret = adau1977_power_disable(adau1977); + break; + } + + if (ret) + return ret; + + codec->dapm.bias_level = level; + + return 0; +} + +static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int width) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ctrl0, ctrl1, drv; + unsigned int slot[4]; + unsigned int i; + int ret; + + if (slots == 0) { + /* 0 = No fixed slot width */ + adau1977->slot_width = 0; + adau1977->max_master_fs = 192000; + return regmap_update_bits(adau1977->regmap, + ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK, + ADAU1977_SAI_CTRL0_SAI_I2S); + } + + if (rx_mask == 0 || tx_mask != 0) + return -EINVAL; + + drv = 0; + for (i = 0; i < 4; i++) { + slot[i] = __ffs(rx_mask); + drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i); + rx_mask &= ~(1 << slot[i]); + if (slot[i] >= slots) + return -EINVAL; + if (rx_mask == 0) + break; + } + + if (rx_mask != 0) + return -EINVAL; + + switch (width) { + case 16: + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16; + break; + case 24: + /* We can only generate 16 bit or 32 bit wide slots */ + if (adau1977->master) + return -EINVAL; + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24; + break; + case 32: + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32; + break; + default: + return -EINVAL; + } + + switch (slots) { + case 2: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2; + break; + case 4: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4; + break; + case 8: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8; + break; + case 16: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, + ADAU1977_SAI_OVERTEMP_DRV_C(0) | + ADAU1977_SAI_OVERTEMP_DRV_C(1) | + ADAU1977_SAI_OVERTEMP_DRV_C(2) | + ADAU1977_SAI_OVERTEMP_DRV_C(3), drv); + if (ret) + return ret; + + ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12, + (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | + (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); + if (ret) + return ret; + + ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34, + (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | + (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1); + if (ret) + return ret; + + adau1977->slot_width = width; + + /* In master mode the maximum bitclock is 24.576 MHz */ + adau1977->max_master_fs = min(192000, 24576000 / width / slots); + + return 0; +} + +static int adau1977_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int val; + + if (mute) + val = ADAU1977_MISC_CONTROL_MMUTE; + else + val = 0; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MISC_CONTROL, + ADAU1977_MISC_CONTROL_MMUTE, val); +} + +static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0; + bool invert_lrclk; + int ret; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + adau1977->master = false; + break; + case SND_SOC_DAIFMT_CBM_CFM: + ctrl1 |= ADAU1977_SAI_CTRL1_MASTER; + adau1977->master = true; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_IB_NF: + block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_NB_IF: + invert_lrclk = true; + break; + case SND_SOC_DAIFMT_IB_IF: + block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; + invert_lrclk = true; + break; + default: + return -EINVAL; + } + + adau1977->right_j = false; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; + invert_lrclk = !invert_lrclk; + break; + case SND_SOC_DAIFMT_RIGHT_J: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; + adau1977->right_j = true; + invert_lrclk = !invert_lrclk; + break; + case SND_SOC_DAIFMT_DSP_A: + ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_DSP_B: + ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; + invert_lrclk = false; + break; + default: + return -EINVAL; + } + + if (invert_lrclk) + block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, + ADAU1977_BLOCK_POWER_SAI_LR_POL | + ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ADAU1977_SAI_CTRL0_FMT_MASK, + ctrl0); + if (ret) + return ret; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE, + ctrl1); +} + +static int adau1977_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + u64 formats = 0; + + if (adau1977->slot_width == 16) + formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE; + else if (adau1977->right_j || adau1977->slot_width == 24) + formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE; + + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &adau1977->constraints); + + if (adau1977->master) + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, 8000, adau1977->max_master_fs); + + if (formats != 0) + snd_pcm_hw_constraint_mask64(substream->runtime, + SNDRV_PCM_HW_PARAM_FORMAT, formats); + + return 0; +} + +static int adau1977_set_tristate(struct snd_soc_dai *dai, int tristate) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int val; + + if (tristate) + val = ADAU1977_SAI_OVERTEMP_DRV_HIZ; + else + val = 0; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, + ADAU1977_SAI_OVERTEMP_DRV_HIZ, val); +} + +static const struct snd_soc_dai_ops adau1977_dai_ops = { + .startup = adau1977_startup, + .hw_params = adau1977_hw_params, + .mute_stream = adau1977_mute, + .set_fmt = adau1977_set_dai_fmt, + .set_tdm_slot = adau1977_set_tdm_slot, + .set_tristate = adau1977_set_tristate, +}; + +static struct snd_soc_dai_driver adau1977_dai = { + .name = "adau1977-hifi", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 4, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .sig_bits = 24, + }, + .ops = &adau1977_dai_ops, +}; + +static const unsigned int adau1977_rates[] = { + 8000, 16000, 32000, 64000, 128000, + 11025, 22050, 44100, 88200, 172400, + 12000, 24000, 48000, 96000, 192000, +}; + +#define ADAU1977_RATE_CONSTRAINT_MASK_32000 0x001f +#define ADAU1977_RATE_CONSTRAINT_MASK_44100 0x03e0 +#define ADAU1977_RATE_CONSTRAINT_MASK_48000 0x7c00 +/* All rates >= 32000 */ +#define ADAU1977_RATE_CONSTRAINT_MASK_LRCLK 0x739c + +static bool adau1977_check_sysclk(unsigned int mclk, unsigned int base_freq) +{ + unsigned int mcs; + + if (mclk % (base_freq * 128) != 0) + return false; + + mcs = mclk / (128 * base_freq); + if (mcs < 1 || mcs > 6 || mcs == 5) + return false; + + return true; +} + +static int adau1977_set_sysclk(struct snd_soc_codec *codec, + int clk_id, int source, unsigned int freq, int dir) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + unsigned int mask = 0; + unsigned int clk_src; + unsigned int ret; + + if (dir != SND_SOC_CLOCK_IN) + return -EINVAL; + + if (clk_id != ADAU1977_SYSCLK) + return -EINVAL; + + switch (source) { + case ADAU1977_SYSCLK_SRC_MCLK: + clk_src = 0; + break; + case ADAU1977_SYSCLK_SRC_LRCLK: + clk_src = ADAU1977_PLL_CLK_S; + break; + default: + return -EINVAL; + } + + if (freq != 0 && source == ADAU1977_SYSCLK_SRC_MCLK) { + if (freq < 4000000 || freq > 36864000) + return -EINVAL; + + if (adau1977_check_sysclk(freq, 32000)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_32000; + if (adau1977_check_sysclk(freq, 44100)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_44100; + if (adau1977_check_sysclk(freq, 48000)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_48000; + + if (mask == 0) + return -EINVAL; + } else if (source == ADAU1977_SYSCLK_SRC_LRCLK) { + mask = ADAU1977_RATE_CONSTRAINT_MASK_LRCLK; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, + ADAU1977_PLL_CLK_S, clk_src); + if (ret) + return ret; + + adau1977->constraints.mask = mask; + adau1977->sysclk_src = source; + adau1977->sysclk = freq; + + return 0; +} + +static int adau1977_codec_probe(struct snd_soc_codec *codec) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + int ret; + + switch (adau1977->type) { + case ADAU1977: + ret = snd_soc_dapm_new_controls(&codec->dapm, + adau1977_micbias_dapm_widgets, + ARRAY_SIZE(adau1977_micbias_dapm_widgets)); + if (ret < 0) + return ret; + break; + default: + break; + } + + return 0; +} + +static struct snd_soc_codec_driver adau1977_codec_driver = { + .probe = adau1977_codec_probe, + .set_bias_level = adau1977_set_bias_level, + .set_sysclk = adau1977_set_sysclk, + .idle_bias_off = true, + + .controls = adau1977_snd_controls, + .num_controls = ARRAY_SIZE(adau1977_snd_controls), + .dapm_widgets = adau1977_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), + .dapm_routes = adau1977_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), +}; + +static int adau1977_setup_micbias(struct adau1977 *adau1977) +{ + struct adau1977_platform_data *pdata = adau1977->dev->platform_data; + unsigned int micbias; + + if (pdata) { + micbias = pdata->micbias; + if (micbias > ADAU1977_MICBIAS_9V0) + return -EINVAL; + + } else { + micbias = ADAU1977_MICBIAS_8V5; + } + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS, + ADAU1977_MICBIAS_MB_VOLTS_MASK, + micbias << ADAU1977_MICBIAS_MB_VOLTS_OFFSET); +} + +int adau1977_probe(struct device *dev, struct regmap *regmap, + enum adau1977_type type, void (*switch_mode)(struct device *dev)) +{ + unsigned int power_off_mask; + struct adau1977 *adau1977; + int ret; + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL); + if (adau1977 == NULL) + return -ENOMEM; + + adau1977->dev = dev; + adau1977->type = type; + adau1977->regmap = regmap; + adau1977->switch_mode = switch_mode; + adau1977->max_master_fs = 192000; + + adau1977->constraints.list = adau1977_rates; + adau1977->constraints.count = ARRAY_SIZE(adau1977_rates); + + adau1977->avdd_reg = devm_regulator_get(dev, "AVDD"); + if (IS_ERR(adau1977->avdd_reg)) + return PTR_ERR(adau1977->avdd_reg); + + adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD"); + if (IS_ERR(adau1977->dvdd_reg)) { + if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV) + return PTR_ERR(adau1977->dvdd_reg); + adau1977->dvdd_reg = NULL; + } + + adau1977->reset_gpio = devm_gpiod_get(dev, "reset"); + if (IS_ERR(adau1977->reset_gpio)) { + ret = PTR_ERR(adau1977->reset_gpio); + if (ret != -ENOENT && ret != -ENOSYS) + return PTR_ERR(adau1977->reset_gpio); + adau1977->reset_gpio = NULL; + } + + dev_set_drvdata(dev, adau1977); + + if (adau1977->reset_gpio) { + ret = gpiod_direction_output(adau1977->reset_gpio, 0); + if (ret) + return ret; + ndelay(100); + } + + ret = adau1977_power_enable(adau1977); + if (ret) + return ret; + + if (type == ADAU1977) { + ret = adau1977_setup_micbias(adau1977); + if (ret) + goto err_poweroff; + } + + if (adau1977->dvdd_reg) + power_off_mask = ~0; + else + power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, + power_off_mask, 0x00); + if (ret) + goto err_poweroff; + + ret = adau1977_power_disable(adau1977); + if (ret) + return ret; + + return snd_soc_register_codec(dev, &adau1977_codec_driver, + &adau1977_dai, 1); + +err_poweroff: + adau1977_power_disable(adau1977); + return ret; + +} +EXPORT_SYMBOL_GPL(adau1977_probe); + +static bool adau1977_register_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADAU1977_REG_STATUS(0): + case ADAU1977_REG_STATUS(1): + case ADAU1977_REG_STATUS(2): + case ADAU1977_REG_STATUS(3): + case ADAU1977_REG_ADC_CLIP: + return true; + } + + return false; +} + +const struct regmap_config adau1977_regmap_config = { + .max_register = ADAU1977_REG_DC_HPF_CAL, + .volatile_reg = adau1977_register_volatile, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = adau1977_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults), +}; +EXPORT_SYMBOL_GPL(adau1977_regmap_config); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977.h b/sound/soc/codecs/adau1977.h new file mode 100644 index 0000000..95e7143 --- /dev/null +++ b/sound/soc/codecs/adau1977.h @@ -0,0 +1,37 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#ifndef __SOUND_SOC_CODECS_ADAU1977_H__ +#define __SOUND_SOC_CODECS_ADAU1977_H__ + +#include + +struct device; + +enum adau1977_type { + ADAU1977, + ADAU1978, + ADAU1979, +}; + +int adau1977_probe(struct device *dev, struct regmap *regmap, + enum adau1977_type type, void (*switch_mode)(struct device *dev)); + +extern const struct regmap_config adau1977_regmap_config; + +enum adau1977_clk_id { + ADAU1977_SYSCLK, +}; + +enum adau1977_sysclk_src { + ADAU1977_SYSCLK_SRC_MCLK, + ADAU1977_SYSCLK_SRC_LRCLK, +}; + +#endif -- cgit v0.10.2 From 82daa86a77e592b38b7fa3f533173d1a3c1299a1 Mon Sep 17 00:00:00 2001 From: Ben Myers Date: Wed, 19 Feb 2014 15:38:22 +1100 Subject: MAINTAINERS: SGI no longer maintaining XFS SGI is stepping out of maintainer roles for xfs, xfsprogs, xfsdump, and xfstests. This removes me from the MAINTAINERS entry. Signed-off-by: Ben Myers Signed-off-by: Dave Chinner diff --git a/MAINTAINERS b/MAINTAINERS index b2cf5cf..e75188f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9715,7 +9715,6 @@ F: drivers/xen/*swiotlb* XFS FILESYSTEM P: Silicon Graphics Inc M: Dave Chinner -M: Ben Myers M: xfs@oss.sgi.com L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs -- cgit v0.10.2 From daba5427dad6b260256053f914de2c0b79f7a79f Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 19 Feb 2014 15:39:16 +1100 Subject: xfs: skip verification on initial "guess" superblock read When xfs_readsb() does the very first read of the superblock, it makes a guess at the length of the buffer, based on the sector size of the underlying storage. This may or may not match the filesystem sector size in sb_sectsize, so we can't i.e. do a CRC check on it; it might be too short. In fact, mounting a filesystem with sb_sectsize larger than the device sector size will cause a mount failure if CRCs are enabled, because we are checksumming a length which exceeds the buffer passed to it. So always read twice; the first time we read with NULL buffer ops to skip verification; then set the proper read length, hook up the proper verifier, and give it another go. Once we are sure that we've got the right buffer length, we can also use bp->b_length in the xfs_sb_read_verify, rather than the less-trusted on-disk sectorsize for secondary superblocks. Before this we ran the risk of passing junk to the crc32c routines, which didn't always handle extreme values. Signed-off-by: Eric Sandeen Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 02df7b4..f96c056 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -282,22 +282,29 @@ xfs_readsb( struct xfs_sb *sbp = &mp->m_sb; int error; int loud = !(flags & XFS_MFSI_QUIET); + const struct xfs_buf_ops *buf_ops; ASSERT(mp->m_sb_bp == NULL); ASSERT(mp->m_ddev_targp != NULL); /* + * For the initial read, we must guess at the sector + * size based on the block device. It's enough to + * get the sb_sectsize out of the superblock and + * then reread with the proper length. + * We don't verify it yet, because it may not be complete. + */ + sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); + buf_ops = NULL; + + /* * Allocate a (locked) buffer to hold the superblock. * This will be kept around at all times to optimize * access to the superblock. */ - sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); - reread: bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR, - BTOBB(sector_size), 0, - loud ? &xfs_sb_buf_ops - : &xfs_sb_quiet_buf_ops); + BTOBB(sector_size), 0, buf_ops); if (!bp) { if (loud) xfs_warn(mp, "SB buffer read failed"); @@ -328,12 +335,13 @@ reread: } /* - * If device sector size is smaller than the superblock size, - * re-read the superblock so the buffer is correctly sized. + * Re-read the superblock so the buffer is correctly sized, + * and properly verified. */ - if (sector_size < sbp->sb_sectsize) { + if (buf_ops == NULL) { xfs_buf_relse(bp); sector_size = sbp->sb_sectsize; + buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops; goto reread; } diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 5071ccb..359b19a 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -611,7 +611,7 @@ xfs_sb_read_verify( XFS_SB_VERSION_5) || dsb->sb_crc != 0)) { - if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), + if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), offsetof(struct xfs_sb, sb_crc))) { /* Only fail bad secondaries on a known V5 filesystem */ if (bp->b_bn == XFS_SB_DADDR || @@ -644,7 +644,6 @@ xfs_sb_quiet_read_verify( { struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp); - if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) { /* XFS filesystem, verify noisily! */ xfs_sb_read_verify(bp); -- cgit v0.10.2 From 5ef11eb0700f806c4671ba33e5befa784a2f70ef Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 19 Feb 2014 15:39:35 +1100 Subject: xfs: limit superblock corruption errors to actual corruption Today, if xfs_sb_read_verify xfs_sb_verify xfs_mount_validate_sb detects superblock corruption, it'll be extremely noisy, dumping 2 stacks, 2 hexdumps, etc. This is because we call XFS_CORRUPTION_ERROR in xfs_mount_validate_sb as well as in xfs_sb_read_verify. Also, *any* errors in xfs_mount_validate_sb which are not corruption per se; things like too-big-blocksize, bad version, bad magic, v1 dirs, rw-incompat etc - things which do not return EFSCORRUPTED - will still do the whole XFS_CORRUPTION_ERROR spew when xfs_sb_read_verify sees any error at all. And it suggests to the user that they should run xfs_repair, even if the root cause of the mount failure is a simple incompatibility. I'll submit that the probably-not-corrupted errors don't warrant this much noise, so this patch removes the warning for anything other than EFSCORRUPTED returns, and replaces the lower-level XFS_CORRUPTION_ERROR with an xfs_notice(). Signed-off-by: Eric Sandeen Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 359b19a..1e11679 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -295,8 +295,7 @@ xfs_mount_validate_sb( sbp->sb_dblocks == 0 || sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) { - XFS_CORRUPTION_ERROR("SB sanity check failed", - XFS_ERRLEVEL_LOW, mp, sbp); + xfs_notice(mp, "SB sanity check failed"); return XFS_ERROR(EFSCORRUPTED); } @@ -625,7 +624,7 @@ xfs_sb_read_verify( out_error: if (error) { - if (error != EWRONGFS) + if (error == EFSCORRUPTED) XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); xfs_buf_ioerror(bp, error); -- cgit v0.10.2 From 995a9190ac9ca85cc15d11d9566017e91c58a118 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 7 Jan 2014 17:47:52 +0100 Subject: clk: shmobile: rcar-gen2: Fix clock parent all non-PLL clocks The lb, qspi, sdh, sd0 and sd1 clocks have the PLL1 (divided by 2) as their parent, not the main clock. Fix it. Reported-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Simon Horman Signed-off-by: Mike Turquette diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index a59ec21..8c7bcbd 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -186,7 +186,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, const char *name) { const struct clk_div_table *table = NULL; - const char *parent_name = "main"; + const char *parent_name; unsigned int shift; unsigned int mult = 1; unsigned int div = 1; @@ -201,23 +201,31 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, * the multiplier value. */ u32 value = clk_readl(cpg->reg + CPG_PLL0CR); + parent_name = "main"; mult = ((value >> 24) & ((1 << 7) - 1)) + 1; } else if (!strcmp(name, "pll1")) { + parent_name = "main"; mult = config->pll1_mult / 2; } else if (!strcmp(name, "pll3")) { + parent_name = "main"; mult = config->pll3_mult; } else if (!strcmp(name, "lb")) { + parent_name = "pll1_div2"; div = cpg_mode & BIT(18) ? 36 : 24; } else if (!strcmp(name, "qspi")) { + parent_name = "pll1_div2"; div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ? 16 : 20; } else if (!strcmp(name, "sdh")) { + parent_name = "pll1_div2"; table = cpg_sdh_div_table; shift = 8; } else if (!strcmp(name, "sd0")) { + parent_name = "pll1_div2"; table = cpg_sd01_div_table; shift = 4; } else if (!strcmp(name, "sd1")) { + parent_name = "pll1_div2"; table = cpg_sd01_div_table; shift = 0; } else if (!strcmp(name, "z")) { -- cgit v0.10.2 From 8510e7263ad9399e771e0f67517a0d5409390445 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 7 Jan 2014 17:47:53 +0100 Subject: clk: shmobile: rcar-gen2: Fix qspi divisor The qspi clock divisor is incorrectly set to twice the value it should have, possibly because it has been computed based on PLL1 as the clock parent instead of PLL1 / 2 (the datasheets specifies the qspi nominal frequencies, not the divisor values). Fix it. Reported-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Simon Horman Signed-off-by: Mike Turquette diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index 8c7bcbd..dd272a0 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -215,7 +215,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, } else if (!strcmp(name, "qspi")) { parent_name = "pll1_div2"; div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) - ? 16 : 20; + ? 8 : 10; } else if (!strcmp(name, "sdh")) { parent_name = "pll1_div2"; table = cpg_sdh_div_table; -- cgit v0.10.2 From 50c11eb9982554e9f99b7bab322c517cbe5ce1a1 Mon Sep 17 00:00:00 2001 From: Inbal Hacohen Date: Wed, 12 Feb 2014 09:32:27 +0200 Subject: cfg80211: bugfix in regulatory user hint process After processing hint_user, we would want to schedule the timeout work only if we are actually waiting to CRDA. This happens when the status is not "IGNORE" nor "ALREADY_SET". Signed-off-by: Inbal Hacohen Signed-off-by: Johannes Berg diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9b897fc..4c50c21 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) return; case NL80211_REGDOM_SET_BY_USER: treatment = reg_process_hint_user(reg_request); - if (treatment == REG_REQ_OK || + if (treatment == REG_REQ_IGNORE || treatment == REG_REQ_ALREADY_SET) return; schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); -- cgit v0.10.2 From 7611c7a5613f20ec2fb536c1d868d15045730bc0 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 19 Feb 2014 10:36:08 +0100 Subject: spi/topcliff-pch: Fix DMA channel bus_num might be asigned dynamically to e.g. 32766. In this case the calculated DMA channel based on SPI bus number is bogus. Use SPI channel number instead for calculation. Signed-off-by: Alexander Stein Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 2e7f38c..3383008c 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -915,7 +915,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) /* Set Tx DMA */ param = &dma->param_tx; param->dma_dev = &dma_dev->dev; - param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */ + param->chan_id = data->ch * 2; /* Tx = 0, 2 */; param->tx_reg = data->io_base_addr + PCH_SPDWR; param->width = width; chan = dma_request_channel(mask, pch_spi_filter, param); @@ -930,7 +930,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) /* Set Rx DMA */ param = &dma->param_rx; param->dma_dev = &dma_dev->dev; - param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */ + param->chan_id = data->ch * 2 + 1; /* Rx = Tx + 1 */; param->rx_reg = data->io_base_addr + PCH_SPDRR; param->width = width; chan = dma_request_channel(mask, pch_spi_filter, param); -- cgit v0.10.2 From 05fb7a56ad65ceaa1907bb9c66bfa1108847667f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 Jan 2014 14:35:28 +0000 Subject: mfd: max8997: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the MAX8997 for a 64bit architecture we receive the following warnings: drivers/mfd/max8997.c: In function ‘max8997_i2c_get_driver_data’: drivers/mfd/max8997.c:173:10: warning: cast from pointer to integer of different size return (int)match->data; ^ Signed-off-by: Lee Jones diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index be88a3b..5adede0 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -164,15 +164,15 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( return pd; } -static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c, +static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { const struct of_device_id *match; match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node); - return (int)match->data; + return (unsigned long)match->data; } - return (int)id->driver_data; + return id->driver_data; } static int max8997_i2c_probe(struct i2c_client *i2c, diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h index ad1ae7f..78c76cd 100644 --- a/include/linux/mfd/max8997-private.h +++ b/include/linux/mfd/max8997-private.h @@ -387,7 +387,7 @@ struct max8997_dev { struct i2c_client *muic; /* slave addr 0x4a */ struct mutex iolock; - int type; + unsigned long type; struct platform_device *battery; /* battery control (not fuel gauge) */ int irq; -- cgit v0.10.2 From 8bace2d5b4baa0f60b6094b53aeb79515ec94e4a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 3 Feb 2014 08:22:30 +0000 Subject: mfd: max8998: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the MAX8998 for a 64bit architecture we receive the following warnings: drivers/mfd/max8998.c: In function ‘max8998_i2c_get_driver_data’: drivers/mfd/max8998.c:178:10: warning: cast from pointer to integer of different size return (int)match->data; ^ Signed-off-by: Lee Jones diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 612ca40..5d5e186 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -169,16 +169,16 @@ static struct max8998_platform_data *max8998_i2c_parse_dt_pdata( return pd; } -static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c, +static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { const struct of_device_id *match; match = of_match_node(max8998_dt_match, i2c->dev.of_node); - return (int)(long)match->data; + return (unsigned long)match->data; } - return (int)id->driver_data; + return id->driver_data; } static int max8998_i2c_probe(struct i2c_client *i2c, diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h index 4ecb24b..d68ada5 100644 --- a/include/linux/mfd/max8998-private.h +++ b/include/linux/mfd/max8998-private.h @@ -163,7 +163,7 @@ struct max8998_dev { int ono; u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS]; u8 irq_masks_cache[MAX8998_NUM_IRQ_REGS]; - int type; + unsigned long type; bool wakeup; }; -- cgit v0.10.2 From 7f8279ce04589a2e0f29b865c3af40609b0ea08d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 Jan 2014 14:47:13 +0000 Subject: mfd: wm8994-core: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the WM8994 for a 64bit architecture we receive the following warnings: drivers/mfd/wm8994-core.c: In function ‘wm8994_i2c_probe’: drivers/mfd/wm8994-core.c:639:19: warning: cast from pointer to integer of different size wm8994->type = (int)of_id->data; ^ Signed-off-by: Lee Jones diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index ba04f1b..e6fab94 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -636,7 +636,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, if (i2c->dev.of_node) { of_id = of_match_device(wm8994_of_match, &i2c->dev); if (of_id) - wm8994->type = (int)of_id->data; + wm8994->type = (enum wm8994_type)of_id->data; } else { wm8994->type = id->driver_data; } -- cgit v0.10.2 From 5c6fbd56d16f38fddec629e1dccdeee5ad7f5a42 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 3 Feb 2014 08:24:20 +0000 Subject: mfd: tps65217: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the TPS65217 for a 64bit architecture we receive the following warnings: drivers/mfd/tps65217.c: In function ‘tps65217_probe’: drivers/mfd/tps65217.c:173:13: warning: cast from pointer to integer of different size chip_id = (unsigned int)match->data; ^ Signed-off-by: Lee Jones diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 966cf65..3cc4c70 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -158,7 +158,7 @@ static int tps65217_probe(struct i2c_client *client, { struct tps65217 *tps; unsigned int version; - unsigned int chip_id = ids->driver_data; + unsigned long chip_id = ids->driver_data; const struct of_device_id *match; bool status_off = false; int ret; @@ -170,7 +170,7 @@ static int tps65217_probe(struct i2c_client *client, "Failed to find matching dt id\n"); return -EINVAL; } - chip_id = (unsigned int)(unsigned long)match->data; + chip_id = (unsigned long)match->data; status_off = of_property_read_bool(client->dev.of_node, "ti,pmic-shutdown-controller"); } diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index a5a7f01..54b5458 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -252,7 +252,7 @@ struct tps65217_board { struct tps65217 { struct device *dev; struct tps65217_board *pdata; - unsigned int id; + unsigned long id; struct regulator_desc desc[TPS65217_NUM_REGULATOR]; struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; struct regmap *regmap; @@ -263,7 +263,7 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev) return dev_get_drvdata(dev); } -static inline int tps65217_chip_id(struct tps65217 *tps65217) +static inline unsigned long tps65217_chip_id(struct tps65217 *tps65217) { return tps65217->id; } -- cgit v0.10.2 From 3edeb1e4b27e1553f4879e0e462724ac7cd75c62 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 26 Jan 2014 11:38:42 +0100 Subject: mfd: max14577: max14577_{suspend,resume}() should depend on CONFIG_PM_SLEEP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_PM_SLEEP=n: drivers/mfd/max14577.c:177: warning: ‘max14577_suspend’ defined but not used drivers/mfd/max14577.c:200: warning: ‘max14577_resume’ defined but not used Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index ac514fb..71aa14a 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -173,6 +173,7 @@ static const struct i2c_device_id max14577_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, max14577_i2c_id); +#ifdef CONFIG_PM_SLEEP static int max14577_suspend(struct device *dev) { struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); @@ -208,6 +209,7 @@ static int max14577_resume(struct device *dev) return 0; } +#endif /* CONFIG_PM_SLEEP */ static struct of_device_id max14577_dt_match[] = { { .compatible = "maxim,max14577", }, -- cgit v0.10.2 From 8321bbf8906990e60cdb46be4c909a7780275942 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 26 Jan 2014 11:38:43 +0100 Subject: mfd: sec-core: sec_pmic_{suspend,resume}() should depend on CONFIG_PM_SLEEP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_PM_SLEEP=n: drivers/mfd/sec-core.c:349: warning: ‘sec_pmic_suspend’ defined but not used drivers/mfd/sec-core.c:371: warning: ‘sec_pmic_resume’ defined but not used Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index a139798..714e213 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -315,6 +315,7 @@ static int sec_pmic_remove(struct i2c_client *i2c) return 0; } +#ifdef CONFIG_PM_SLEEP static int sec_pmic_suspend(struct device *dev) { struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); @@ -349,6 +350,7 @@ static int sec_pmic_resume(struct device *dev) return 0; } +#endif /* CONFIG_PM_SLEEP */ static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); -- cgit v0.10.2 From 146d70caaa1b87f64597743429d7da4b8073d0c9 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Tue, 18 Feb 2014 10:36:05 -0500 Subject: NFS fix error return in nfs4_select_rw_stateid Do not return an error when nfs4_copy_delegation_stateid succeeds. Signed-off-by: Andy Adamson Link: http://lkml.kernel.org/r/1392737765-41942-1-git-send-email-andros@netapp.com Fixes: ef1820f9be27b (NFSv4: Don't try to recover NFSv4 locks when...) Cc: NeilBrown Cc: stable@vger.kernel.org # 3.12+ Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e5be725..e1a4721 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1015,8 +1015,11 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, if (ret == -EIO) /* A lost lock - don't even consider delegations */ goto out; - if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) + /* returns true if delegation stateid found and copied */ + if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) { + ret = 0; goto out; + } if (ret != -ENOENT) /* nfs4_copy_delegation_stateid() didn't over-write * dst, so it still has the lock stateid which we now -- cgit v0.10.2 From 5ae8aabeaec3fe69c4fb21cbe5b17b72b35b5892 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 17 Feb 2014 10:45:36 -0800 Subject: sched_clock: Prevent callers from seeing half-updated data The generic sched_clock registration function was previously done lockless, due to the fact that it was expected to be called only once. However, now there are systems that may register multiple sched_clock sources, for which the lack of locking has casued problems: If two sched_clock sources are registered we may end up in a situation where a call to sched_clock() may be accessing the epoch cycle count for the old counter and the cycle count for the new counter. This can lead to confusing results where sched_clock() values jump and then are reset to 0 (due to the way the registration function forces the epoch_ns to be 0). Fix this by reorganizing the registration function to hold the seqlock for as short a time as possible while we update the clock_data structure for a new counter. We also put any accumulated time into epoch_ns instead of resetting the time to 0 so that the clock doesn't reset after each successful registration. [jstultz: Added extra context to the commit message] Reported-by: Will Deacon Signed-off-by: Stephen Boyd Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Peter Zijlstra Cc: Josh Cartwright Link: http://lkml.kernel.org/r/1392662736-7803-2-git-send-email-john.stultz@linaro.org Signed-off-by: John Stultz Signed-off-by: Thomas Gleixner diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index 0abb364..4d23dc4 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c @@ -116,20 +116,42 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt) void __init sched_clock_register(u64 (*read)(void), int bits, unsigned long rate) { + u64 res, wrap, new_mask, new_epoch, cyc, ns; + u32 new_mult, new_shift; + ktime_t new_wrap_kt; unsigned long r; - u64 res, wrap; char r_unit; if (cd.rate > rate) return; WARN_ON(!irqs_disabled()); - read_sched_clock = read; - sched_clock_mask = CLOCKSOURCE_MASK(bits); - cd.rate = rate; /* calculate the mult/shift to convert counter ticks to ns. */ - clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600); + clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600); + + new_mask = CLOCKSOURCE_MASK(bits); + + /* calculate how many ns until we wrap */ + wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask); + new_wrap_kt = ns_to_ktime(wrap - (wrap >> 3)); + + /* update epoch for new counter and update epoch_ns from old counter*/ + new_epoch = read(); + cyc = read_sched_clock(); + ns = cd.epoch_ns + cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask, + cd.mult, cd.shift); + + raw_write_seqcount_begin(&cd.seq); + read_sched_clock = read; + sched_clock_mask = new_mask; + cd.rate = rate; + cd.wrap_kt = new_wrap_kt; + cd.mult = new_mult; + cd.shift = new_shift; + cd.epoch_cyc = new_epoch; + cd.epoch_ns = ns; + raw_write_seqcount_end(&cd.seq); r = rate; if (r >= 4000000) { @@ -141,22 +163,12 @@ void __init sched_clock_register(u64 (*read)(void), int bits, } else r_unit = ' '; - /* calculate how many ns until we wrap */ - wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask); - cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3)); - /* calculate the ns resolution of this counter */ - res = cyc_to_ns(1ULL, cd.mult, cd.shift); + res = cyc_to_ns(1ULL, new_mult, new_shift); + pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n", bits, r, r_unit, res, wrap); - update_sched_clock(); - - /* - * Ensure that sched_clock() starts off at 0ns - */ - cd.epoch_ns = 0; - /* Enable IRQ time accounting if we have a fast enough sched_clock */ if (irqtime > 0 || (irqtime == -1 && rate >= 1000000)) enable_sched_clock_irqtime(); -- cgit v0.10.2 From 5f0e030930d715920be4de638084aaf8653867e8 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 19 Feb 2014 13:52:29 +0200 Subject: x86, tsc: Fallback to normal calibration if fast MSR calibration fails If we cannot calibrate TSC via MSR based calibration try_msr_calibrate_tsc() stores zero to fast_calibrate and returns that to the caller. This value gets then propagated further to clockevents code resulting division by zero oops like the one below: divide error: 0000 [#1] PREEMPT SMP Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Tainted: G W 3.13.0+ #47 task: ffff880075508000 ti: ffff880075506000 task.ti: ffff880075506000 RIP: 0010:[] [] clockevents_config.part.3+0x24/0xa0 RSP: 0000:ffff880075507e58 EFLAGS: 00010246 RAX: ffffffffffffffff RBX: ffff880079c0cd80 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffffffffffff RBP: ffff880075507e70 R08: 0000000000000001 R09: 00000000000000be R10: 00000000000000bd R11: 0000000000000003 R12: 000000000000b008 R13: 0000000000000008 R14: 000000000000b010 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff880079c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: ffff880079fff000 CR3: 0000000001c0b000 CR4: 00000000001006f0 Stack: ffff880079c0cd80 000000000000b008 0000000000000008 ffff880075507e88 ffffffff810aecb0 ffff880079c0cd80 ffff880075507e98 ffffffff81030168 ffff880075507ed8 ffffffff81d1104f 00000000000000c3 0000000000000000 Call Trace: [] clockevents_config_and_register+0x20/0x30 [] setup_APIC_timer+0xc8/0xd0 [] setup_boot_APIC_clock+0x4cc/0x4d8 [] native_smp_prepare_cpus+0x3dd/0x3f0 [] kernel_init_freeable+0xc3/0x205 [] ? rest_init+0x90/0x90 [] kernel_init+0xe/0x120 [] ret_from_fork+0x7c/0xb0 [] ? rest_init+0x90/0x90 Prevent this from happening by: 1) Modifying try_msr_calibrate_tsc() to return calibration value or zero if it fails. 2) Check this return value in native_calibrate_tsc() and in case of zero fallback to use normal non-MSR based calibration. [mw: Added subject and changelog] Reported-and-tested-by: Mika Westerberg Signed-off-by: Thomas Gleixner Cc: Bin Gao Cc: One Thousand Gnomes Cc: Ingo Molnar Cc: H. Peter Anvin Link: http://lkml.kernel.org/r/1392810750-18660-1-git-send-email-mika.westerberg@linux.intel.com Signed-off-by: Mika Westerberg Signed-off-by: Thomas Gleixner diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index 57ae63c..94605c0 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -66,6 +66,6 @@ extern void tsc_save_sched_clock_state(void); extern void tsc_restore_sched_clock_state(void); /* MSR based TSC calibration for Intel Atom SoC platforms */ -int try_msr_calibrate_tsc(unsigned long *fast_calibrate); +unsigned long try_msr_calibrate_tsc(void); #endif /* _ASM_X86_TSC_H */ diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index acb3b60..cfbe99f 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -653,13 +653,10 @@ unsigned long native_calibrate_tsc(void) /* Calibrate TSC using MSR for Intel Atom SoCs */ local_irq_save(flags); - i = try_msr_calibrate_tsc(&fast_calibrate); + fast_calibrate = try_msr_calibrate_tsc(); local_irq_restore(flags); - if (i >= 0) { - if (i == 0) - pr_warn("Fast TSC calibration using MSR failed\n"); + if (fast_calibrate) return fast_calibrate; - } local_irq_save(flags); fast_calibrate = quick_pit_calibrate(); diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c index 8b5434f..5dfff58 100644 --- a/arch/x86/kernel/tsc_msr.c +++ b/arch/x86/kernel/tsc_msr.c @@ -77,21 +77,18 @@ static int match_cpu(u8 family, u8 model) /* * Do MSR calibration only for known/supported CPUs. - * Return values: - * -1: CPU is unknown/unsupported for MSR based calibration - * 0: CPU is known/supported, but calibration failed - * 1: CPU is known/supported, and calibration succeeded + * + * Returns the calibration value or 0 if MSR calibration failed. */ -int try_msr_calibrate_tsc(unsigned long *fast_calibrate) +unsigned long try_msr_calibrate_tsc(void) { - int cpu_index; u32 lo, hi, ratio, freq_id, freq; + unsigned long res; + int cpu_index; cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model); if (cpu_index < 0) - return -1; - - *fast_calibrate = 0; + return 0; if (freq_desc_tables[cpu_index].msr_plat) { rdmsr(MSR_PLATFORM_INFO, lo, hi); @@ -103,7 +100,7 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate) pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio); if (!ratio) - return 0; + goto fail; /* Get FSB FREQ ID */ rdmsr(MSR_FSB_FREQ, lo, hi); @@ -112,16 +109,19 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate) pr_info("Resolved frequency ID: %u, frequency: %u KHz\n", freq_id, freq); if (!freq) - return 0; + goto fail; /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */ - *fast_calibrate = freq * ratio; - pr_info("TSC runs at %lu KHz\n", *fast_calibrate); + res = freq * ratio; + pr_info("TSC runs at %lu KHz\n", res); #ifdef CONFIG_X86_LOCAL_APIC lapic_timer_frequency = (freq * 1000) / HZ; pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency); #endif + return res; - return 1; +fail: + pr_warn("Fast TSC calibration using MSR failed\n"); + return 0; } -- cgit v0.10.2 From 3e11e818bfd7bd4a8e1214970337bab73ffed32d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 19 Feb 2014 13:52:30 +0200 Subject: x86: tsc: Add missing Baytrail frequency to the table Intel Baytrail is based on Silvermont core so MSR_FSB_FREQ[2:0] == 0 means that the CPU reference clock runs at 83.3MHz. Add this missing frequency to the table. Signed-off-by: Mika Westerberg Cc: Bin Gao Cc: One Thousand Gnomes Cc: Ingo Molnar Cc: H. Peter Anvin Link: http://lkml.kernel.org/r/1392810750-18660-2-git-send-email-mika.westerberg@linux.intel.com Signed-off-by: Thomas Gleixner diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c index 5dfff58..92ae6ac 100644 --- a/arch/x86/kernel/tsc_msr.c +++ b/arch/x86/kernel/tsc_msr.c @@ -53,7 +53,7 @@ static struct freq_desc freq_desc_tables[] = { /* TNG */ { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } }, /* VLV2 */ - { 6, 0x37, 1, { 0, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, + { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, /* ANN */ { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } }, }; -- cgit v0.10.2 From d6cf89ee07cbfd980f189cc12ae924c811b00ee4 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 19 Feb 2014 14:05:54 +0100 Subject: ASoC: cs4271: claim reset GPIO in bus probe function Move the GPIO acquisition from the codec to the bus probe functions. Signed-off-by: Daniel Mack Acked-by: Brian Austin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index f7bbe6f..96c3097 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -539,14 +539,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; int ret; - int gpio_nreset = -EINVAL; bool amutec_eq_bmutec = false; #ifdef CONFIG_OF if (of_match_device(cs4271_dt_ids, codec->dev)) { - gpio_nreset = of_get_named_gpio(codec->dev->of_node, - "reset-gpio", 0); - if (of_get_property(codec->dev->of_node, "cirrus,amutec-eq-bmutec", NULL)) amutec_eq_bmutec = true; @@ -558,27 +554,19 @@ static int cs4271_probe(struct snd_soc_codec *codec) #endif if (cs4271plat) { - if (gpio_is_valid(cs4271plat->gpio_nreset)) - gpio_nreset = cs4271plat->gpio_nreset; - amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; } - if (gpio_nreset >= 0) - if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset")) - gpio_nreset = -EINVAL; - if (gpio_nreset >= 0) { + if (gpio_is_valid(cs4271->gpio_nreset)) { /* Reset codec */ - gpio_direction_output(gpio_nreset, 0); + gpio_direction_output(cs4271->gpio_nreset, 0); udelay(1); - gpio_set_value(gpio_nreset, 1); + gpio_set_value(cs4271->gpio_nreset, 1); /* Give the codec time to wake up */ udelay(1); } - cs4271->gpio_nreset = gpio_nreset; - ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN | CS4271_MODE2_CPEN, CS4271_MODE2_PDN | CS4271_MODE2_CPEN); @@ -640,14 +628,45 @@ static const struct regmap_config cs4271_spi_regmap = { .volatile_reg = cs4271_volatile_reg, }; -static int cs4271_spi_probe(struct spi_device *spi) +static int cs4271_common_probe(struct device *dev, + struct cs4271_private **c) { + struct cs4271_platform_data *cs4271plat = dev->platform_data; struct cs4271_private *cs4271; - cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL); + cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL); if (!cs4271) return -ENOMEM; + if (of_match_device(cs4271_dt_ids, dev)) + cs4271->gpio_nreset = + of_get_named_gpio(dev->of_node, "reset-gpio", 0); + + if (cs4271plat) + cs4271->gpio_nreset = cs4271plat->gpio_nreset; + + if (gpio_is_valid(cs4271->gpio_nreset)) { + int ret; + + ret = devm_gpio_request(dev, cs4271->gpio_nreset, + "CS4271 Reset"); + if (ret < 0) + return ret; + } + + *c = cs4271; + return 0; +} + +static int cs4271_spi_probe(struct spi_device *spi) +{ + struct cs4271_private *cs4271; + int ret; + + ret = cs4271_common_probe(&spi->dev, &cs4271); + if (ret < 0) + return ret; + spi_set_drvdata(spi, cs4271); cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); if (IS_ERR(cs4271->regmap)) @@ -697,10 +716,11 @@ static int cs4271_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cs4271_private *cs4271; + int ret; - cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL); - if (!cs4271) - return -ENOMEM; + ret = cs4271_common_probe(&client->dev, &cs4271); + if (ret < 0) + return ret; i2c_set_clientdata(client, cs4271); cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); -- cgit v0.10.2 From 7ec02609739d82f7786e5a169e5a900dbaf0d1a1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:59:39 +0100 Subject: ASoC: da732x: Remove superfluous DA732X_SOC_ENUM_DOUBLE_R() It's nowhere used. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h index c8ce547..1dceafe 100644 --- a/sound/soc/codecs/da732x.h +++ b/sound/soc/codecs/da732x.h @@ -113,9 +113,6 @@ #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 #define DA732X_EQ_OVERALL_VOL_DB_INC 600 -#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ - {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} - enum da732x_sysctl { DA732X_SR_8KHZ = 0x1, DA732X_SR_11_025KHZ = 0x2, -- cgit v0.10.2 From 025c3fa9256d4c54506b7a29dc3befac54f5c68d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:24:12 +0100 Subject: ASoC: sta32x: Fix array access overflow Preset EQ enum of sta32x codec driver declares too many number of items and it may lead to the access over the actual array size. Use SOC_ENUM_SINGLE_DECL() helper and it's automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 06edb39..42c5b45 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -187,42 +187,42 @@ static const unsigned int sta32x_limiter_drc_release_tlv[] = { 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), }; -static const struct soc_enum sta32x_drc_ac_enum = - SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, - 2, sta32x_drc_ac); -static const struct soc_enum sta32x_auto_eq_enum = - SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT, - 3, sta32x_auto_eq_mode); -static const struct soc_enum sta32x_auto_gc_enum = - SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT, - 4, sta32x_auto_gc_mode); -static const struct soc_enum sta32x_auto_xo_enum = - SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT, - 16, sta32x_auto_xo_mode); -static const struct soc_enum sta32x_preset_eq_enum = - SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT, - 32, sta32x_preset_eq_mode); -static const struct soc_enum sta32x_limiter_ch1_enum = - SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT, - 3, sta32x_limiter_select); -static const struct soc_enum sta32x_limiter_ch2_enum = - SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT, - 3, sta32x_limiter_select); -static const struct soc_enum sta32x_limiter_ch3_enum = - SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT, - 3, sta32x_limiter_select); -static const struct soc_enum sta32x_limiter1_attack_rate_enum = - SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT, - 16, sta32x_limiter_attack_rate); -static const struct soc_enum sta32x_limiter2_attack_rate_enum = - SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT, - 16, sta32x_limiter_attack_rate); -static const struct soc_enum sta32x_limiter1_release_rate_enum = - SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT, - 16, sta32x_limiter_release_rate); -static const struct soc_enum sta32x_limiter2_release_rate_enum = - SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT, - 16, sta32x_limiter_release_rate); +static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum, + STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, + sta32x_drc_ac); +static SOC_ENUM_SINGLE_DECL(sta32x_auto_eq_enum, + STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT, + sta32x_auto_eq_mode); +static SOC_ENUM_SINGLE_DECL(sta32x_auto_gc_enum, + STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT, + sta32x_auto_gc_mode); +static SOC_ENUM_SINGLE_DECL(sta32x_auto_xo_enum, + STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT, + sta32x_auto_xo_mode); +static SOC_ENUM_SINGLE_DECL(sta32x_preset_eq_enum, + STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT, + sta32x_preset_eq_mode); +static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch1_enum, + STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT, + sta32x_limiter_select); +static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch2_enum, + STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT, + sta32x_limiter_select); +static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch3_enum, + STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT, + sta32x_limiter_select); +static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_attack_rate_enum, + STA32X_L1AR, STA32X_LxA_SHIFT, + sta32x_limiter_attack_rate); +static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_attack_rate_enum, + STA32X_L2AR, STA32X_LxA_SHIFT, + sta32x_limiter_attack_rate); +static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_release_rate_enum, + STA32X_L1AR, STA32X_LxR_SHIFT, + sta32x_limiter_release_rate); +static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum, + STA32X_L2AR, STA32X_LxR_SHIFT, + sta32x_limiter_release_rate); /* byte array controls for setting biquad, mixer, scaling coefficients; * for biquads all five coefficients need to be set in one go, -- cgit v0.10.2 From 18ba7b9d5fd6eb2c2c510dfcfc6e8fee56c42571 Mon Sep 17 00:00:00 2001 From: Vaibhav Bedia Date: Sun, 16 Feb 2014 18:15:44 -0500 Subject: ARM: OMAP5: PRM: Fix reboot handling Use the correct register offset for issuing the reset command in OMAP5. Since dev_inst is set dynamically OMAP4 should not be affected by this change. Signed-off-by: Vaibhav Bedia Tested-by: Lokesh Vutla Acked-by: Rajendra Nayak Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c index 6334b96..280f3c5 100644 --- a/arch/arm/mach-omap2/prminst44xx.c +++ b/arch/arm/mach-omap2/prminst44xx.c @@ -183,11 +183,11 @@ void omap4_prminst_global_warm_sw_reset(void) OMAP4_PRM_RSTCTRL_OFFSET); v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK; omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION, - OMAP4430_PRM_DEVICE_INST, + dev_inst, OMAP4_PRM_RSTCTRL_OFFSET); /* OCP barrier */ v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, - OMAP4430_PRM_DEVICE_INST, + dev_inst, OMAP4_PRM_RSTCTRL_OFFSET); } -- cgit v0.10.2 From c317d0f241fa0bbb098aa35f3d4b3067be2b5f3d Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 10 Jan 2014 17:43:08 -0600 Subject: ARM: DRA7: hwmod data: correct the sysc data for spinlock The spinlock module's SYSCONFIG register on DRA7xx does not support smart wakeup, and also does not have the CLKACTIVITY field. The sysc data for spinlock module has been appropriately fixed up to reflect the same. Cc: Ambresh K Signed-off-by: Suman Anna Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 18f333c..810c205 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -1365,11 +1365,10 @@ static struct omap_hwmod_class_sysconfig dra7xx_spinlock_sysc = { .rev_offs = 0x0000, .sysc_offs = 0x0010, .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | - SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - SIDLE_SMART_WKUP), + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP | + SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; -- cgit v0.10.2 From 01142519ffc0734436f26b01aeed37a915dece05 Mon Sep 17 00:00:00 2001 From: Illia Smyrnov Date: Wed, 5 Feb 2014 17:06:09 +0200 Subject: ARM: OMAP4: hwmod: Fix SOFTRESET logic for OMAP4 Commit 313a76e (ARM: OMAP2+: hwmod: Fix SOFTRESET logic) introduced softreset bit cleaning right after set one. It is caused L3 error for OMAP4 ISS because ISS register write occurs when ISS reset process is in progress. Avoid this situation by cleaning softreset bit later, when reset process is successfully finished. Signed-off-by: Illia Smyrnov Reviewed-by: Grygorii Strashko Acked-by: Roger Quadros Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 42d8188..1f33f5d 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1947,29 +1947,31 @@ static int _ocp_softreset(struct omap_hwmod *oh) goto dis_opt_clks; _write_sysconfig(v, oh); - ret = _clear_softreset(oh, &v); - if (ret) - goto dis_opt_clks; - - _write_sysconfig(v, oh); if (oh->class->sysc->srst_udelay) udelay(oh->class->sysc->srst_udelay); c = _wait_softreset_complete(oh); - if (c == MAX_MODULE_SOFTRESET_WAIT) + if (c == MAX_MODULE_SOFTRESET_WAIT) { pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", oh->name, MAX_MODULE_SOFTRESET_WAIT); - else + ret = -ETIMEDOUT; + goto dis_opt_clks; + } else { pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c); + } + + ret = _clear_softreset(oh, &v); + if (ret) + goto dis_opt_clks; + + _write_sysconfig(v, oh); /* * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from * _wait_target_ready() or _reset() */ - ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0; - dis_opt_clks: if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) _disable_optional_clocks(oh); -- cgit v0.10.2 From 994c41ee0ac875797b4dfef509ac7753e2649b4d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 30 Jan 2014 13:17:20 +0200 Subject: ARM: OMAP2+: clock: fix clkoutx2 with CLK_SET_RATE_PARENT If CLK_SET_RATE_PARENT is set for a clkoutx2 clock, calling clk_set_rate() on the clock "skips" the x2 multiplier as there are no set_rate and round_rate functions defined for the clkoutx2. This results in getting double the requested clock rates, breaking the display on omap3430 based devices. This got broken when d0f58bd3bba3877fb1af4664c4e33273d36f00e4 and related patches were merged for v3.14, as omapdss driver now relies more on the clk-framework and CLK_SET_RATE_PARENT. This patch implements set_rate and round_rate for clkoutx2. Tested on OMAP3430, OMAP3630, OMAP4460. Signed-off-by: Tomi Valkeinen Acked-by: Tero Kristo Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 3b05aea..11ed915 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -433,7 +433,9 @@ static const struct clk_ops dpll4_m5x2_ck_ops = { .enable = &omap2_dflt_clk_enable, .disable = &omap2_dflt_clk_disable, .is_enabled = &omap2_dflt_clk_is_enabled, + .set_rate = &omap3_clkoutx2_set_rate, .recalc_rate = &omap3_clkoutx2_recalc, + .round_rate = &omap3_clkoutx2_round_rate, }; static const struct clk_ops dpll4_m5x2_ck_3630_ops = { diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 3185ced..3c418ea 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -623,6 +623,32 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk) /* Clock control for DPLL outputs */ +/* Find the parent DPLL for the given clkoutx2 clock */ +static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw) +{ + struct clk_hw_omap *pclk = NULL; + struct clk *parent; + + /* Walk up the parents of clk, looking for a DPLL */ + do { + do { + parent = __clk_get_parent(hw->clk); + hw = __clk_get_hw(parent); + } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC)); + if (!hw) + break; + pclk = to_clk_hw_omap(hw); + } while (pclk && !pclk->dpll_data); + + /* clk does not have a DPLL as a parent? error in the clock data */ + if (!pclk) { + WARN_ON(1); + return NULL; + } + + return pclk; +} + /** * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate * @clk: DPLL output struct clk @@ -637,27 +663,14 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, unsigned long rate; u32 v; struct clk_hw_omap *pclk = NULL; - struct clk *parent; if (!parent_rate) return 0; - /* Walk up the parents of clk, looking for a DPLL */ - do { - do { - parent = __clk_get_parent(hw->clk); - hw = __clk_get_hw(parent); - } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC)); - if (!hw) - break; - pclk = to_clk_hw_omap(hw); - } while (pclk && !pclk->dpll_data); + pclk = omap3_find_clkoutx2_dpll(hw); - /* clk does not have a DPLL as a parent? error in the clock data */ - if (!pclk) { - WARN_ON(1); + if (!pclk) return 0; - } dd = pclk->dpll_data; @@ -672,6 +685,55 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, return rate; } +int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return 0; +} + +long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + const struct dpll_data *dd; + u32 v; + struct clk_hw_omap *pclk = NULL; + + if (!*prate) + return 0; + + pclk = omap3_find_clkoutx2_dpll(hw); + + if (!pclk) + return 0; + + dd = pclk->dpll_data; + + /* TYPE J does not have a clkoutx2 */ + if (dd->flags & DPLL_J_TYPE) { + *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate); + return *prate; + } + + WARN_ON(!dd->enable_mask); + + v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask; + v >>= __ffs(dd->enable_mask); + + /* If in bypass, the rate is fixed to the bypass rate*/ + if (v != OMAP3XXX_EN_DPLL_LOCKED) + return *prate; + + if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) { + unsigned long best_parent; + + best_parent = (rate / 2); + *prate = __clk_round_rate(__clk_get_parent(hw->clk), + best_parent); + } + + return *prate * 2; +} + /* OMAP3/4 non-CORE DPLL clkops */ const struct clk_hw_omap_ops clkhwops_omap3_dpll = { .allow_idle = omap3_dpll_allow_idle, diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index 092b641..4a21a87 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -245,6 +245,10 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, void omap2_init_clk_clkdm(struct clk_hw *clk); unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, unsigned long parent_rate); +int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate); +long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate); int omap2_clkops_enable_clkdm(struct clk_hw *hw); void omap2_clkops_disable_clkdm(struct clk_hw *hw); int omap2_clk_disable_autoidle_all(void); -- cgit v0.10.2 From c89b5c65c08116cef4b80f2903cb452ca0e20cee Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Feb 2014 02:46:50 +0400 Subject: net: ethoc: document OF bindings Signed-off-by: Max Filippov Signed-off-by: David S. Miller diff --git a/Documentation/devicetree/bindings/net/opencores-ethoc.txt b/Documentation/devicetree/bindings/net/opencores-ethoc.txt new file mode 100644 index 0000000..2dc127c --- /dev/null +++ b/Documentation/devicetree/bindings/net/opencores-ethoc.txt @@ -0,0 +1,22 @@ +* OpenCores MAC 10/100 Mbps + +Required properties: +- compatible: Should be "opencores,ethoc". +- reg: two memory regions (address and length), + first region is for the device registers and descriptor rings, + second is for the device packet memory. +- interrupts: interrupt for the device. + +Optional properties: +- clocks: phandle to refer to the clk used as per + Documentation/devicetree/bindings/clock/clock-bindings.txt + +Examples: + + enet0: ethoc@fd030000 { + compatible = "opencores,ethoc"; + reg = <0xfd030000 0x4000 0xfd800000 0x4000>; + interrupts = <1>; + local-mac-address = [00 50 c2 13 6f 00]; + clocks = <&osc>; + }; -- cgit v0.10.2 From d554f73df6bc35ac8f6a65e5560bf1d31dfebed9 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Wed, 19 Feb 2014 18:48:34 +0000 Subject: xen-netfront: reset skb network header before checksum In ed1f50c3a ("net: add skb_checksum_setup") we introduced some checksum functions in core driver. Subsequent change b5cf66cd1 ("xen-netfront: use new skb_checksum_setup function") made use of those functions to replace its own implementation. However with that change netfront is broken. It sees a lot of checksum error. That's because its own implementation of checksum function was a bit hacky (dereferencing skb->data directly) while the new function was implemented using ip_hdr(). The network header is not reset before skb is passed to the new function. When the new function tries to do its job, it's confused and reports error. The fix is simple, we need to reset network header before passing skb to checksum function. Netback is not affected as it already does the right thing. Reported-by: Sander Eikelenboom Signed-off-by: Wei Liu Cc: Konrad Rzeszutek Wilk Cc: Paul Durrant Tested-By: Sander Eikelenboom Signed-off-by: David S. Miller diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index f9daa9e..e30d800 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -907,6 +907,7 @@ static int handle_incoming_queue(struct net_device *dev, /* Ethernet work: Delayed to here as it peeks the header. */ skb->protocol = eth_type_trans(skb, dev); + skb_reset_network_header(skb); if (checksum_setup(dev, skb)) { kfree_skb(skb); -- cgit v0.10.2 From bd8ba20597f0cfef3ef65c3fd2aa92ab23d4c8e1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 13 Feb 2014 16:32:51 +0100 Subject: ACPI / video: Filter the _BCL table for duplicate brightness values Some devices have duplicate entries in there brightness levels table, ie on my Dell Latitude E6430 the table looks like this: [ 3.686060] acpi backlight index 0, val 80 [ 3.686095] acpi backlight index 1, val 50 [ 3.686122] acpi backlight index 2, val 5 [ 3.686147] acpi backlight index 3, val 5 [ 3.686172] acpi backlight index 4, val 5 [ 3.686197] acpi backlight index 5, val 5 [ 3.686223] acpi backlight index 6, val 5 [ 3.686248] acpi backlight index 7, val 5 [ 3.686273] acpi backlight index 8, val 6 [ 3.686332] acpi backlight index 9, val 7 [ 3.686356] acpi backlight index 10, val 8 [ 3.686380] acpi backlight index 11, val 9 etc. Notice that brightness values 0-5 are all mapped to 5. This means that if userspace writes any value between 0 and 5 to the brightness sysfs attribute and then reads it, it will always return 0, which is somewhat unexpected. This is a problem for ie gnome-settings-daemon, which uses read-modify-write logic when the users presses the brightness up or down keys. This is done this way to take brightness changes from other sources into account. On this specific laptop what happens once the brightness has been set to 0, is that gsd reads 0, adds 5, writes 5, and on the next brightness up key press again reads 0, so things get stuck at the lowest brightness setting. Filtering out the duplicate table entries, makes any write to brightness read back as the written value as one would expect, fixing this. Signed-off-by: Hans de Goede Reviewed-by: Aaron Lu Cc: All applicable Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index b727d10..ea9d914 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -685,6 +685,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) union acpi_object *o; struct acpi_video_device_brightness *br = NULL; int result = -EINVAL; + u32 value; if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " @@ -715,7 +716,12 @@ acpi_video_init_brightness(struct acpi_video_device *device) printk(KERN_ERR PREFIX "Invalid data\n"); continue; } - br->levels[count] = (u32) o->integer.value; + value = (u32) o->integer.value; + /* Skip duplicate entries */ + if (count > 2 && br->levels[count - 1] == value) + continue; + + br->levels[count] = value; if (br->levels[count] > max_level) max_level = br->levels[count]; -- cgit v0.10.2 From 0e9f81d3b7cd0649a3bc437391b6a0650f98f844 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Tue, 18 Feb 2014 13:54:20 +0800 Subject: ACPI / video: Add systems that should favour native backlight interface Some system's ACPI video backlight control interface is broken and the native backlight control interface should be used by default. This patch sets the use_native_backlight parameter to true for those systems so that video backlight control interface will not be created. For detailed models that are added here, reference the following list. Note that the user specified kernel cmdline option will always have the highest priority, i.e. if use_native_backlight=0 is specified and the system is in the DMI table, the video module will not skip registering backlight interface for it. Thinkpad T430s: Reported-by: Theodore Tso Reported-and-tested-by: Peter Weber References: https://bugzilla.kernel.org/show_bug.cgi?id=51231 Thinkpad X230: Reported-and-tested-by: Igor Gnatenko References: https://bugzilla.kernel.org/show_bug.cgi?id=51231 ThinkPad X1 Carbon: Reported-and-tested-by: Igor Gnatenko Lenovo Yoga 13: Reported-by: Lennart Poettering Reported-and-tested-by: Kevin Smith References: https://bugzilla.kernel.org/show_bug.cgi?id=63811 Dell Inspiron 7520: Reported-by: Rinat Ibragimov Acer Aspire 5733Z: Reported-by: References: https://bugzilla.kernel.org/show_bug.cgi?id=62941 Acer Aspire V5-431: Reported-by: Thomas Christensen References: https://bugzilla.kernel.org/show_bug.cgi?id=68751 HP ProBook 4340s: Reported-and-tested-by: Vladimir Sherenkov References: http://redmine.russianfedora.pro/issues/1258 HP EliteBook/ProBook 2013 models, ZBook and some others: Provided-by: Takashi Iwai Signed-off-by: Aaron Lu Tested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 10e4964..e8e4c3d 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -260,14 +260,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { .callback = dmi_disable_osi_win8, - .ident = "Dell Inspiron 15R SE", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"), - }, - }, - { - .callback = dmi_disable_osi_win8, .ident = "ThinkPad Edge E530", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index ea9d914..b6ba88e 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -81,11 +81,12 @@ static bool allow_duplicates; module_param(allow_duplicates, bool, 0644); /* - * For Windows 8 systems: if set ture and the GPU driver has - * registered a backlight interface, skip registering ACPI video's. + * For Windows 8 systems: used to decide if video module + * should skip registering backlight interface of its own. */ -static bool use_native_backlight = false; -module_param(use_native_backlight, bool, 0644); +static int use_native_backlight_param = -1; +module_param_named(use_native_backlight, use_native_backlight_param, int, 0444); +static bool use_native_backlight_dmi = false; static int register_count; static struct mutex video_list_lock; @@ -231,9 +232,17 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, static int acpi_video_switch_brightness(struct acpi_video_device *device, int event); +static bool acpi_video_use_native_backlight(void) +{ + if (use_native_backlight_param != -1) + return use_native_backlight_param; + else + return use_native_backlight_dmi; +} + static bool acpi_video_verify_backlight_support(void) { - if (acpi_osi_is_win8() && use_native_backlight && + if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && backlight_device_registered(BACKLIGHT_RAW)) return false; return acpi_video_backlight_support(); @@ -398,6 +407,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) return 0; } +static int __init video_set_use_native_backlight(const struct dmi_system_id *d) +{ + use_native_backlight_dmi = true; + return 0; +} + static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -442,6 +457,120 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad T430s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad X230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad X1 Carbon", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Lenovo Yoga 13", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Dell Inspiron 7520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire 5733Z", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-431", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ProBook 4340s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4340s"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ProBook 2013 models", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "), + DMI_MATCH(DMI_PRODUCT_NAME, " G1"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP EliteBook 2013 models", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), + DMI_MATCH(DMI_PRODUCT_NAME, " G1"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ZBook 14", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ZBook 15", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ZBook 17", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP EliteBook 8780w", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"), + }, + }, {} }; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index a697b77..19080c8 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -168,22 +168,6 @@ static struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), }, }, - { - .callback = video_detect_force_vendor, - .ident = "HP EliteBook Revolve 810", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Revolve 810 G1"), - }, - }, - { - .callback = video_detect_force_vendor, - .ident = "Lenovo Yoga 13", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), - }, - }, { }, }; -- cgit v0.10.2 From a6940190ac15c361862a1a8f50a2072db7184749 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 18 Feb 2014 14:55:15 +0100 Subject: Revert "ACPI: Blacklist Win8 OSI for some HP laptop 2013 models" This reverts commit 2d4054d84224 (ACPI: Blacklist Win8 OSI for some HP laptop 2013 models) that is not necessary any more after previous commit 1811fcb029fa (ACPI / video: Add systems that should favour native backlight interface). Requested-by: Takashi Iwai Tested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index e8e4c3d..afec452 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -314,56 +314,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), }, }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ProBook 2013 models", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "), - DMI_MATCH(DMI_PRODUCT_NAME, " G1"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP EliteBook 2013 models", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), - DMI_MATCH(DMI_PRODUCT_NAME, " G1"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ZBook 14", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ZBook 15", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ZBook 17", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP EliteBook 8780w", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"), - }, - }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v0.10.2 From 4f6500fff5f7644a03c46728fd7ef0f62fa6940b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 13 Feb 2014 13:57:44 -0500 Subject: sparc32: fix build failure for arch_jump_label_transform In arch/sparc/Kernel/Makefile, we see: obj-$(CONFIG_SPARC64) += jump_label.o However, the Kconfig selects HAVE_ARCH_JUMP_LABEL unconditionally for all SPARC. This in turn leads to the following failure when doing allmodconfig coverage builds: kernel/built-in.o: In function `__jump_label_update': jump_label.c:(.text+0x8560c): undefined reference to `arch_jump_label_transform' kernel/built-in.o: In function `arch_jump_label_transform_static': (.text+0x85cf4): undefined reference to `arch_jump_label_transform' make: *** [vmlinux] Error 1 Change HAVE_ARCH_JUMP_LABEL to be conditional on SPARC64 so that it matches the Makefile. Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index c51efdc..7d8b7e9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -27,7 +27,7 @@ config SPARC select RTC_DRV_M48T59 select HAVE_DMA_ATTRS select HAVE_DMA_API_DEBUG - select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL if SPARC64 select GENERIC_IRQ_SHOW select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_PCI_IOMAP -- cgit v0.10.2 From a56b072fa357ab076cb6c9b52e58fbe3c709da10 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 13 Feb 2014 16:15:01 -0500 Subject: sparc32: make copy_to/from_user_page() usable from modular code While copy_to/from_user_page() users are uncommon, there is one in drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c which leads to the following: ERROR: "sparc32_cachetlb_ops" [drivers/staging/lustre/lustre/libcfs/libcfs.ko] undefined! during routine allmodconfig build coverage. The reason this happens is as follows: In arch/sparc/include/asm/cacheflush_32.h we have: #define flush_cache_page(vma,addr,pfn) \ sparc32_cachetlb_ops->cache_page(vma, addr) #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { \ flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ } while (0) #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ do { \ flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ } while (0) However, sparc32_cachetlb_ops isn't exported and hence the error. Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 869023a..cfbe53c 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ extern unsigned long last_valid_pfn; static pgd_t *srmmu_swapper_pg_dir; const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops; +EXPORT_SYMBOL(sparc32_cachetlb_ops); #ifdef CONFIG_SMP const struct sparc32_cachetlb_ops *local_ops; -- cgit v0.10.2 From b38fbe30739afa83695c4969c8e966d919d828b0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:17:44 +0100 Subject: ASoC: ssm2602: Omit superfluous elements in input select array The array contains too many elements although it should have only two. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 49d28ea..1294709 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -63,15 +63,16 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { /*Appending several "None"s just for OSS mixer use*/ static const char *ssm2602_input_select[] = { - "Line", "Mic", "None", "None", "None", - "None", "None", "None", + "Line", "Mic", }; static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; static const struct soc_enum ssm2602_enum[] = { - SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select), - SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), + SOC_ENUM_SINGLE(SSM2602_APANA, 2, ARRAY_SIZE(ssm2602_input_select), + ssm2602_input_select), + SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, ARRAY_SIZE(ssm2602_deemph), + ssm2602_deemph), }; static const unsigned int ssm260x_outmix_tlv[] = { -- cgit v0.10.2 From 7a6c0a58dc824523966f212c76322d47c5b0e6fe Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:37:30 +0100 Subject: ASoC: wm8770: Fix wrong number of enum items wm8770 codec driver defines ain_enum with a wrong number of items. Use SOC_ENUM_DOUBLE_DECL() macro and it's automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 89a18d8..5bce210 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -196,8 +196,8 @@ static const char *ain_text[] = { "AIN5", "AIN6", "AIN7", "AIN8" }; -static const struct soc_enum ain_enum = - SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text); +static SOC_ENUM_DOUBLE_DECL(ain_enum, + WM8770_ADCMUX, 0, 4, ain_text); static const struct snd_kcontrol_new ain_mux = SOC_DAPM_ENUM("Capture Mux", ain_enum); -- cgit v0.10.2 From 9d1663143652d579dd5555e60fd8c78362ffb8c6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:39:46 +0100 Subject: ASoC: wm8900: Fix the wrong number of enum items wm8900 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index e98bc70..43c2201 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -304,53 +304,53 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" }; -static const struct soc_enum mic_bias_level = -SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt); +static SOC_ENUM_SINGLE_DECL(mic_bias_level, + WM8900_REG_INCTL, 8, mic_bias_level_txt); static const char *dac_mute_rate_txt[] = { "Fast", "Slow" }; -static const struct soc_enum dac_mute_rate = -SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt); +static SOC_ENUM_SINGLE_DECL(dac_mute_rate, + WM8900_REG_DACCTRL, 7, dac_mute_rate_txt); static const char *dac_deemphasis_txt[] = { "Disabled", "32kHz", "44.1kHz", "48kHz" }; -static const struct soc_enum dac_deemphasis = -SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt); +static SOC_ENUM_SINGLE_DECL(dac_deemphasis, + WM8900_REG_DACCTRL, 4, dac_deemphasis_txt); static const char *adc_hpf_cut_txt[] = { "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3" }; -static const struct soc_enum adc_hpf_cut = -SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt); +static SOC_ENUM_SINGLE_DECL(adc_hpf_cut, + WM8900_REG_ADCCTRL, 5, adc_hpf_cut_txt); static const char *lr_txt[] = { "Left", "Right" }; -static const struct soc_enum aifl_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt); +static SOC_ENUM_SINGLE_DECL(aifl_src, + WM8900_REG_AUDIO1, 15, lr_txt); -static const struct soc_enum aifr_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt); +static SOC_ENUM_SINGLE_DECL(aifr_src, + WM8900_REG_AUDIO1, 14, lr_txt); -static const struct soc_enum dacl_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt); +static SOC_ENUM_SINGLE_DECL(dacl_src, + WM8900_REG_AUDIO2, 15, lr_txt); -static const struct soc_enum dacr_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt); +static SOC_ENUM_SINGLE_DECL(dacr_src, + WM8900_REG_AUDIO2, 14, lr_txt); static const char *sidetone_txt[] = { "Disabled", "Left ADC", "Right ADC" }; -static const struct soc_enum dacl_sidetone = -SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt); +static SOC_ENUM_SINGLE_DECL(dacl_sidetone, + WM8900_REG_SIDETONE, 2, sidetone_txt); -static const struct soc_enum dacr_sidetone = -SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt); +static SOC_ENUM_SINGLE_DECL(dacr_sidetone, + WM8900_REG_SIDETONE, 0, sidetone_txt); static const struct snd_kcontrol_new wm8900_snd_controls[] = { SOC_ENUM("Mic Bias Level", mic_bias_level), @@ -496,8 +496,8 @@ SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" }; -static const struct soc_enum wm8900_lineout2_lp_mux = -SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux); +static SOC_ENUM_SINGLE_DECL(wm8900_lineout2_lp_mux, + WM8900_REG_LOUTMIXCTL1, 1, wm8900_lp_mux); static const struct snd_kcontrol_new wm8900_lineout2_lp = SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); -- cgit v0.10.2 From 830b501138ab50dd413143dce47d1ae6dd1e39a5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:49 +0100 Subject: ASoC: wm8990: Fix the wrong number of enum items wm8990 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 0ccd4d8..33f53ab 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -157,26 +157,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8990_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8990_left_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACL_SHIFT, - WM8990_ADC_TO_DACL_MASK, - wm8990_digital_sidetone); - -static const struct soc_enum wm8990_right_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACR_SHIFT, - WM8990_ADC_TO_DACR_MASK, - wm8990_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8990_left_digital_sidetone_enum, + WM8990_DIGITAL_SIDE_TONE, + WM8990_ADC_TO_DACL_SHIFT, + wm8990_digital_sidetone); + +static SOC_ENUM_SINGLE_DECL(wm8990_right_digital_sidetone_enum, + WM8990_DIGITAL_SIDE_TONE, + WM8990_ADC_TO_DACR_SHIFT, + wm8990_digital_sidetone); static const char *wm8990_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8990_right_adcmode_enum = -SOC_ENUM_SINGLE(WM8990_ADC_CTRL, - WM8990_ADC_HPF_CUT_SHIFT, - WM8990_ADC_HPF_CUT_MASK, - wm8990_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8990_right_adcmode_enum, + WM8990_ADC_CTRL, + WM8990_ADC_HPF_CUT_SHIFT, + wm8990_adcmode); static const struct snd_kcontrol_new wm8990_snd_controls[] = { /* INMIXL */ @@ -475,9 +472,9 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, static const char *wm8990_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8990_ainlmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, - ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8990_ainlmux_enum, + WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, + wm8990_ainlmux); static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); @@ -488,9 +485,9 @@ SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); static const char *wm8990_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8990_ainrmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, - ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8990_ainrmux_enum, + WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, + wm8990_ainrmux); static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); -- cgit v0.10.2 From d07338b0f2e1697c99fcd52bf1895227ce5e1a14 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:23 +0100 Subject: ASoC: wm8991: Fix the wrong number of enum items wm8991 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 244eb09..32d2195 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -171,26 +171,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8991_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8991_left_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACL_SHIFT, - WM8991_ADC_TO_DACL_MASK, - wm8991_digital_sidetone); - -static const struct soc_enum wm8991_right_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACR_SHIFT, - WM8991_ADC_TO_DACR_MASK, - wm8991_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACL_SHIFT, + wm8991_digital_sidetone); + +static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACR_SHIFT, + wm8991_digital_sidetone); static const char *wm8991_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8991_right_adcmode_enum = - SOC_ENUM_SINGLE(WM8991_ADC_CTRL, - WM8991_ADC_HPF_CUT_SHIFT, - WM8991_ADC_HPF_CUT_MASK, - wm8991_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum, + WM8991_ADC_CTRL, + WM8991_ADC_HPF_CUT_SHIFT, + wm8991_adcmode); static const struct snd_kcontrol_new wm8991_snd_controls[] = { /* INMIXL */ @@ -486,9 +483,9 @@ static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { static const char *wm8991_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8991_ainlmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, - ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, + wm8991_ainlmux); static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); @@ -499,9 +496,9 @@ static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = static const char *wm8991_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8991_ainrmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, - ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, + wm8991_ainrmux); static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); -- cgit v0.10.2 From e61a35b798497a85725ce10c07049fa1b9ca014c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:45:30 +0100 Subject: ASoC: wm8994: Fix the wrong number of enum items wm8994 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b9be9cb..adb7206 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -265,21 +265,21 @@ static const char *sidetone_hpf_text[] = { "2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz" }; -static const struct soc_enum sidetone_hpf = - SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text); +static SOC_ENUM_SINGLE_DECL(sidetone_hpf, + WM8994_SIDETONE, 7, sidetone_hpf_text); static const char *adc_hpf_text[] = { "HiFi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum aif1adc1_hpf = - SOC_ENUM_SINGLE(WM8994_AIF1_ADC1_FILTERS, 13, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(aif1adc1_hpf, + WM8994_AIF1_ADC1_FILTERS, 13, adc_hpf_text); -static const struct soc_enum aif1adc2_hpf = - SOC_ENUM_SINGLE(WM8994_AIF1_ADC2_FILTERS, 13, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(aif1adc2_hpf, + WM8994_AIF1_ADC2_FILTERS, 13, adc_hpf_text); -static const struct soc_enum aif2adc_hpf = - SOC_ENUM_SINGLE(WM8994_AIF2_ADC_FILTERS, 13, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(aif2adc_hpf, + WM8994_AIF2_ADC_FILTERS, 13, adc_hpf_text); static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0); static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); @@ -501,39 +501,39 @@ static const char *aif_chan_src_text[] = { "Left", "Right" }; -static const struct soc_enum aif1adcl_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 15, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif1adcl_src, + WM8994_AIF1_CONTROL_1, 15, aif_chan_src_text); -static const struct soc_enum aif1adcr_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 14, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif1adcr_src, + WM8994_AIF1_CONTROL_1, 14, aif_chan_src_text); -static const struct soc_enum aif2adcl_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 15, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif2adcl_src, + WM8994_AIF2_CONTROL_1, 15, aif_chan_src_text); -static const struct soc_enum aif2adcr_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 14, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif2adcr_src, + WM8994_AIF2_CONTROL_1, 14, aif_chan_src_text); -static const struct soc_enum aif1dacl_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif1dacl_src, + WM8994_AIF1_CONTROL_2, 15, aif_chan_src_text); -static const struct soc_enum aif1dacr_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif1dacr_src, + WM8994_AIF1_CONTROL_2, 14, aif_chan_src_text); -static const struct soc_enum aif2dacl_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif2dacl_src, + WM8994_AIF2_CONTROL_2, 15, aif_chan_src_text); -static const struct soc_enum aif2dacr_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aif_chan_src_text); +static SOC_ENUM_SINGLE_DECL(aif2dacr_src, + WM8994_AIF2_CONTROL_2, 14, aif_chan_src_text); static const char *osr_text[] = { "Low Power", "High Performance", }; -static const struct soc_enum dac_osr = - SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(dac_osr, + WM8994_OVERSAMPLING, 0, osr_text); -static const struct soc_enum adc_osr = - SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(adc_osr, + WM8994_OVERSAMPLING, 1, osr_text); static const struct snd_kcontrol_new wm8994_snd_controls[] = { SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, @@ -690,17 +690,20 @@ static const char *wm8958_ng_text[] = { "30ms", "125ms", "250ms", "500ms", }; -static const struct soc_enum wm8958_aif1dac1_ng_hold = - SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE, - WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text); +static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac1_ng_hold, + WM8958_AIF1_DAC1_NOISE_GATE, + WM8958_AIF1DAC1_NG_THR_SHIFT, + wm8958_ng_text); -static const struct soc_enum wm8958_aif1dac2_ng_hold = - SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE, - WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text); +static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac2_ng_hold, + WM8958_AIF1_DAC2_NOISE_GATE, + WM8958_AIF1DAC2_NG_THR_SHIFT, + wm8958_ng_text); -static const struct soc_enum wm8958_aif2dac_ng_hold = - SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE, - WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text); +static SOC_ENUM_SINGLE_DECL(wm8958_aif2dac_ng_hold, + WM8958_AIF2_DAC_NOISE_GATE, + WM8958_AIF2DAC_NG_THR_SHIFT, + wm8958_ng_text); static const struct snd_kcontrol_new wm8958_snd_controls[] = { SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), @@ -1341,8 +1344,8 @@ static const char *adc_mux_text[] = { "DMIC", }; -static const struct soc_enum adc_enum = - SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(adc_enum, + 0, 0, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); @@ -1478,14 +1481,14 @@ static const char *sidetone_text[] = { "ADC/DMIC1", "DMIC2", }; -static const struct soc_enum sidetone1_enum = - SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone1_enum, + WM8994_SIDETONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetone1_mux = SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); -static const struct soc_enum sidetone2_enum = - SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone2_enum, + WM8994_SIDETONE, 1, sidetone_text); static const struct snd_kcontrol_new sidetone2_mux = SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); @@ -1498,22 +1501,24 @@ static const char *loopback_text[] = { "None", "ADCDAT", }; -static const struct soc_enum aif1_loopback_enum = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2, - loopback_text); +static SOC_ENUM_SINGLE_DECL(aif1_loopback_enum, + WM8994_AIF1_CONTROL_2, + WM8994_AIF1_LOOPBACK_SHIFT, + loopback_text); static const struct snd_kcontrol_new aif1_loopback = SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum); -static const struct soc_enum aif2_loopback_enum = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2, - loopback_text); +static SOC_ENUM_SINGLE_DECL(aif2_loopback_enum, + WM8994_AIF2_CONTROL_2, + WM8994_AIF2_LOOPBACK_SHIFT, + loopback_text); static const struct snd_kcontrol_new aif2_loopback = SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum); -static const struct soc_enum aif1dac_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); +static SOC_ENUM_SINGLE_DECL(aif1dac_enum, + WM8994_POWER_MANAGEMENT_6, 0, aif1dac_text); static const struct snd_kcontrol_new aif1dac_mux = SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum); @@ -1522,8 +1527,8 @@ static const char *aif2dac_text[] = { "AIF2DACDAT", "AIF3DACDAT", }; -static const struct soc_enum aif2dac_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text); +static SOC_ENUM_SINGLE_DECL(aif2dac_enum, + WM8994_POWER_MANAGEMENT_6, 1, aif2dac_text); static const struct snd_kcontrol_new aif2dac_mux = SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum); @@ -1532,8 +1537,8 @@ static const char *aif2adc_text[] = { "AIF2ADCDAT", "AIF3DACDAT", }; -static const struct soc_enum aif2adc_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text); +static SOC_ENUM_SINGLE_DECL(aif2adc_enum, + WM8994_POWER_MANAGEMENT_6, 2, aif2adc_text); static const struct snd_kcontrol_new aif2adc_mux = SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum); @@ -1542,14 +1547,14 @@ static const char *aif3adc_text[] = { "AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM", }; -static const struct soc_enum wm8994_aif3adc_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text); +static SOC_ENUM_SINGLE_DECL(wm8994_aif3adc_enum, + WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text); static const struct snd_kcontrol_new wm8994_aif3adc_mux = SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum); -static const struct soc_enum wm8958_aif3adc_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 4, aif3adc_text); +static SOC_ENUM_SINGLE_DECL(wm8958_aif3adc_enum, + WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text); static const struct snd_kcontrol_new wm8958_aif3adc_mux = SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum); @@ -1558,8 +1563,8 @@ static const char *mono_pcm_out_text[] = { "None", "AIF2ADCL", "AIF2ADCR", }; -static const struct soc_enum mono_pcm_out_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 9, 3, mono_pcm_out_text); +static SOC_ENUM_SINGLE_DECL(mono_pcm_out_enum, + WM8994_POWER_MANAGEMENT_6, 9, mono_pcm_out_text); static const struct snd_kcontrol_new mono_pcm_out_mux = SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum); @@ -1569,14 +1574,14 @@ static const char *aif2dac_src_text[] = { }; /* Note that these two control shouldn't be simultaneously switched to AIF3 */ -static const struct soc_enum aif2dacl_src_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 7, 2, aif2dac_src_text); +static SOC_ENUM_SINGLE_DECL(aif2dacl_src_enum, + WM8994_POWER_MANAGEMENT_6, 7, aif2dac_src_text); static const struct snd_kcontrol_new aif2dacl_src_mux = SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum); -static const struct soc_enum aif2dacr_src_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 8, 2, aif2dac_src_text); +static SOC_ENUM_SINGLE_DECL(aif2dacr_src_enum, + WM8994_POWER_MANAGEMENT_6, 8, aif2dac_src_text); static const struct snd_kcontrol_new aif2dacr_src_mux = SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum); -- cgit v0.10.2 From b6592d88ec37440c88cc3bc2c9c08a61d0de3eec Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:55:27 +0100 Subject: ASoC: ad193x: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index f644a34..9381a76 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -31,8 +31,8 @@ struct ad193x_priv { */ static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; -static const struct soc_enum ad193x_deemp_enum = - SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); +static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, + ad193x_deemp); static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); -- cgit v0.10.2 From 9a8d38db030f016bee45b927af02d9b46398ed46 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:11:42 +0100 Subject: ASoC: Rename soc_enum.max field with items The name "max" in struct soc_enum is rather confusing since it actually takes the number of items. With "max", one might try to assign (nitems - 1) value. Rename the field to a more appropriate one, "items", which is also used in struct snd_ctl_elem_info, too. This patch also rewrites some code like "if (x > e->nitems - 1)" with "if (x >= e->nitems)". Not only the latter improves the readability, it also fixes a potential bug when e->items is zero. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a00147..66de6a7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -162,19 +162,19 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .min = xmin, .max = xmax, \ .platform_max = xmax} } -#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ +#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .max = xmax, .texts = xtexts, \ - .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0} -#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ - SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) -#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ -{ .max = xmax, .texts = xtexts } -#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \ + .items = xitems, .texts = xtexts, \ + .mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0} +#define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \ + SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts) +#define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \ +{ .items = xitems, .texts = xtexts } +#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .mask = xmask, .max = xmax, .texts = xtexts, .values = xvalues} -#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \ - SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues) + .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} +#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \ + SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues) #define SOC_ENUM(xname, xenum) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ .info = snd_soc_info_enum_double, \ @@ -1089,7 +1089,7 @@ struct soc_enum { unsigned short reg2; unsigned char shift_l; unsigned char shift_r; - unsigned int max; + unsigned int items; unsigned int mask; const char * const *texts; const unsigned int *values; diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ee660e2..bb1ecfc 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1849,7 +1849,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98088->eq_enum.texts = max98088->eq_texts; - max98088->eq_enum.max = max98088->eq_textcnt; + max98088->eq_enum.items = max98088->eq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3ba1170..5bce9cd 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -1861,7 +1861,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98095->eq_enum.texts = max98095->eq_texts; - max98095->eq_enum.max = max98095->eq_textcnt; + max98095->eq_enum.items = max98095->eq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) @@ -2016,7 +2016,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98095->bq_enum.texts = max98095->bq_texts; - max98095->bq_enum.max = max98095->bq_textcnt; + max98095->bq_enum.items = max98095->bq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 00665ad..1eb13d5 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -975,13 +975,13 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, return -EBUSY; } - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= e->mask << e->shift_r; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 53bbfac..b2664ec 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1981,7 +1981,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8904->num_retune_mobile_texts); - wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; + wm8904->retune_mobile_enum.items = wm8904->num_retune_mobile_texts; wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; ret = snd_soc_add_codec_controls(codec, &control, 1); @@ -2022,7 +2022,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_drc_cfgs; i++) wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; - wm8904->drc_enum.max = pdata->num_drc_cfgs; + wm8904->drc_enum.items = pdata->num_drc_cfgs; wm8904->drc_enum.texts = wm8904->drc_texts; ret = snd_soc_add_codec_controls(codec, &control, 1); diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index b7488f1..1974377 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -944,7 +944,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_mbc_cfgs; i++) wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; - wm8994->mbc_enum.max = pdata->num_mbc_cfgs; + wm8994->mbc_enum.items = pdata->num_mbc_cfgs; wm8994->mbc_enum.texts = wm8994->mbc_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -973,7 +973,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_vss_cfgs; i++) wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; - wm8994->vss_enum.max = pdata->num_vss_cfgs; + wm8994->vss_enum.items = pdata->num_vss_cfgs; wm8994->vss_enum.texts = wm8994->vss_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -1003,7 +1003,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; - wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; + wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs; wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -1034,7 +1034,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_enh_eq_cfgs; i++) wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; - wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; + wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs; wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b9be9cb..8253c3c 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3237,7 +3237,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8994->num_retune_mobile_texts); - wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; + wm8994->retune_mobile_enum.items = wm8994->num_retune_mobile_texts; wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, @@ -3293,7 +3293,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) for (i = 0; i < pdata->num_drc_cfgs; i++) wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; - wm8994->drc_enum.max = pdata->num_drc_cfgs; + wm8994->drc_enum.items = pdata->num_drc_cfgs; wm8994->drc_enum.texts = wm8994->drc_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b..ea6b587 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2595,7 +2595,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8996->num_retune_mobile_texts); - wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts; + wm8996->retune_mobile_enum.items = wm8996->num_retune_mobile_texts; wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 6294464..2eca91a 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -103,7 +103,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, if (!codec->hw_write) return -EUNATCH; - if (ucontrol->value.enumerated.item[0] >= control->max) + if (ucontrol->value.enumerated.item[0] >= control->items) return -EINVAL; mutex_lock(&codec->mutex); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50..4372efb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2571,10 +2571,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = e->shift_l == e->shift_r ? 1 : 2; - uinfo->value.enumerated.items = e->max; + uinfo->value.enumerated.items = e->items; - if (uinfo->value.enumerated.item > e->max - 1) - uinfo->value.enumerated.item = e->max - 1; + if (uinfo->value.enumerated.item >= e->items) + uinfo->value.enumerated.item = e->items - 1; strlcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item], sizeof(uinfo->value.enumerated.name)); @@ -2626,12 +2626,12 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, unsigned int val; unsigned int mask; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= e->mask << e->shift_r; @@ -2662,14 +2662,14 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } ucontrol->value.enumerated.item[0] = mux; if (e->shift_l != e->shift_r) { val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } @@ -2700,12 +2700,12 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, unsigned int val; unsigned int mask; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; mask |= e->mask << e->shift_r; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dc8ff13..2026a64 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -535,7 +535,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, soc_widget_read(w, e->reg, &val); item = (val >> e->shift_l) & e->mask; - if (item < e->max && !strcmp(p->name, e->texts[item])) + if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; else p->connect = 0; @@ -563,12 +563,12 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, soc_widget_read(w, e->reg, &val); val = (val >> e->shift_l) & e->mask; - for (item = 0; item < e->max; item++) { + for (item = 0; item < e->items; item++) { if (val == e->values[item]) break; } - if (item < e->max && !strcmp(p->name, e->texts[item])) + if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; else p->connect = 0; @@ -616,7 +616,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int i; - for (i = 0; i < e->max; i++) { + for (i = 0; i < e->items; i++) { if (!(strcmp(control_name, e->texts[i]))) { list_add(&path->list, &dapm->card->paths); list_add(&path->list_sink, &dest->sources); @@ -2967,13 +2967,13 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_update update; int ret = 0; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = mux << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= e->mask << e->shift_r; @@ -3036,7 +3036,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, int change; int ret = 0; - if (ucontrol->value.enumerated.item[0] >= e->max) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); @@ -3077,14 +3077,14 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } ucontrol->value.enumerated.item[0] = mux; if (e->shift_l != e->shift_r) { val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } @@ -3119,13 +3119,13 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_update update; int ret = 0; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; mask |= e->mask << e->shift_r; -- cgit v0.10.2 From 6b207c0f166e7f19c9d9dc48feb25e276e36c43f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:56:39 +0100 Subject: ASoC: twl4030: Clean up duplicated code Remove the open code in snd_soc_put_twl4030_opmode_enum_double() but just call snd_soc_put_enum_double() instead, which does the very same thing (even correctly with a lock). Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 1eb13d5..682e4ac 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -965,9 +965,6 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned short val; - unsigned short mask; if (twl4030->configured) { dev_err(codec->dev, @@ -975,19 +972,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, return -EBUSY; } - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - - val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) - return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - return snd_soc_update_bits(codec, e->reg, mask, val); + return snd_soc_put_enum_double(kcontrol, ucontrol); } /* -- cgit v0.10.2 From c28b14f49978af2fc864dd2faeb89f517746f9f9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:59:39 +0100 Subject: ALSA: da732x: Remove superfluous DA732X_SOC_ENUM_DOUBLE_R() It's nowhere used. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h index c8ce547..1dceafe 100644 --- a/sound/soc/codecs/da732x.h +++ b/sound/soc/codecs/da732x.h @@ -113,9 +113,6 @@ #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 #define DA732X_EQ_OVERALL_VOL_DB_INC 600 -#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ - {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} - enum da732x_sysctl { DA732X_SR_8KHZ = 0x1, DA732X_SR_11_025KHZ = 0x2, -- cgit v0.10.2 From 2e7e1993f992b16342b3799de2f9572b2e53d53b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:08:51 +0100 Subject: ASoC: Add const to SOC_ENUM_*_DECL() macros Since these macros are supposed to be used for decalring const objects, let's add the const modifier there. The doubled const appearing in usages will be cleaned by later patches. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 66de6a7..ab5f1fe 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -272,14 +272,14 @@ * ARRAY_SIZE internally */ #define SOC_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xtexts) \ - struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \ + const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \ ARRAY_SIZE(xtexts), xtexts) #define SOC_ENUM_SINGLE_DECL(name, xreg, xshift, xtexts) \ SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts) #define SOC_ENUM_SINGLE_EXT_DECL(name, xtexts) \ - struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts) + const struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts) #define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, xtexts, xvalues) \ - struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \ + const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \ ARRAY_SIZE(xtexts), xtexts, xvalues) #define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) -- cgit v0.10.2 From 4988aff78bfd7c97cc67f0390555a9c2b6825f40 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:40:51 +0100 Subject: ASoC: adau1373: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index eb836ed..46b1595 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -345,15 +345,15 @@ static const char *adau1373_fdsp_sel_text[] = { "Channel 5", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); static const char *adau1373_hpf_cutoff_text[] = { @@ -362,7 +362,7 @@ static const char *adau1373_hpf_cutoff_text[] = { "800Hz", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); static const char *adau1373_bass_lpf_cutoff_text[] = { @@ -388,14 +388,14 @@ static const unsigned int adau1373_bass_tlv[] = { 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), }; -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); -static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, +static SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, adau1373_bass_clip_level_values); -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); static const char *adau1373_3d_level_text[] = { @@ -409,9 +409,9 @@ static const char *adau1373_3d_cutoff_text[] = { "0.16875 fs", "0.27083 fs" }; -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); static const unsigned int adau1373_3d_tlv[] = { @@ -427,11 +427,11 @@ static const char *adau1373_lr_mux_text[] = { "Stereo", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); static const struct snd_kcontrol_new adau1373_controls[] = { -- cgit v0.10.2 From 51e5b59c3559e63e8a943350714a8c070fba8cbf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:42:16 +0100 Subject: ASoC: lm49453: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index e19490c..6b7fe5e 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -195,18 +195,18 @@ struct lm49453_priv { static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"}; -static const SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, - lm49453_mic2mode_text); +static SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, + lm49453_mic2mode_text); static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"}; -static const SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, - LM49453_P0_DIGITAL_MIC1_CONFIG_REG, - 7, lm49453_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, + LM49453_P0_DIGITAL_MIC1_CONFIG_REG, 7, + lm49453_dmic_cfg_text); -static const SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, - LM49453_P0_DIGITAL_MIC2_CONFIG_REG, - 7, lm49453_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, + LM49453_P0_DIGITAL_MIC2_CONFIG_REG, 7, + lm49453_dmic_cfg_text); /* MUX Controls */ static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" }; -- cgit v0.10.2 From a750987443cd4239c2b4dd742a59474aea10b179 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:42:50 +0100 Subject: ASoC: mc13783: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bb..147c2e5 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -430,8 +430,8 @@ static const struct snd_kcontrol_new samp_ctl = static const char * const speaker_amp_source_text[] = { "CODEC", "Right" }; -static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, - speaker_amp_source_text); +static SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, + speaker_amp_source_text); static const struct snd_kcontrol_new speaker_amp_source_mux = SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source); @@ -439,8 +439,8 @@ static const char * const headset_amp_source_text[] = { "CODEC", "Mixer" }; -static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, - headset_amp_source_text); +static SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, + headset_amp_source_text); static const struct snd_kcontrol_new headset_amp_source_mux = SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source); -- cgit v0.10.2 From f843cdf2f767a88e7cfe9300f37e1c02b97cc389 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:08 +0100 Subject: ASoC: rt5631: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 912c9cb..ce199d3 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -210,26 +210,22 @@ static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, static const char *rt5631_input_mode[] = { "Single ended", "Differential"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); /* MONO Input Type */ -static const SOC_ENUM_SINGLE_DECL( - rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, - RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, + RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); /* SPK Ratio Gain Control */ static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x", "1.56x", "1.68x", "1.99x", "2.34x"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, - RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); +static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, + RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); static const struct snd_kcontrol_new rt5631_snd_controls[] = { /* MIC */ @@ -759,9 +755,8 @@ static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = { /* Left SPK Volume Input */ static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum); @@ -769,9 +764,8 @@ static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = /* Left HP Volume Input */ static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum); @@ -779,9 +773,8 @@ static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = /* Left Out Volume Input */ static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_L_EN_SHIFT, rt5631_outvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_L_EN_SHIFT, rt5631_outvoll_sel); static const struct snd_kcontrol_new rt5631_outvoll_mux_control = SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum); @@ -789,9 +782,8 @@ static const struct snd_kcontrol_new rt5631_outvoll_mux_control = /* Right Out Volume Input */ static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_R_EN_SHIFT, rt5631_outvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_R_EN_SHIFT, rt5631_outvolr_sel); static const struct snd_kcontrol_new rt5631_outvolr_mux_control = SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum); @@ -799,9 +791,8 @@ static const struct snd_kcontrol_new rt5631_outvolr_mux_control = /* Right HP Volume Input */ static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum); @@ -809,9 +800,8 @@ static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = /* Right SPK Volume Input */ static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum); @@ -820,9 +810,8 @@ static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = static const char *rt5631_spol_src_sel[] = { "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); static const struct snd_kcontrol_new rt5631_spol_mux_control = SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum); @@ -831,9 +820,8 @@ static const struct snd_kcontrol_new rt5631_spol_mux_control = static const char *rt5631_spor_src_sel[] = { "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); static const struct snd_kcontrol_new rt5631_spor_mux_control = SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum); @@ -841,9 +829,8 @@ static const struct snd_kcontrol_new rt5631_spor_mux_control = /* MONO Input */ static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); static const struct snd_kcontrol_new rt5631_mono_mux_control = SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum); @@ -851,9 +838,8 @@ static const struct snd_kcontrol_new rt5631_mono_mux_control = /* Left HPO Input */ static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); static const struct snd_kcontrol_new rt5631_hpl_mux_control = SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum); @@ -861,9 +847,8 @@ static const struct snd_kcontrol_new rt5631_hpl_mux_control = /* Right HPO Input */ static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); static const struct snd_kcontrol_new rt5631_hpr_mux_control = SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum); -- cgit v0.10.2 From 4c03cb6f86c1e171c3b277c207a6b9003402fbb6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:21 +0100 Subject: ASoC: rt5640: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index a3fb411..fe4a5c2 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -361,25 +361,24 @@ static unsigned int bst_tlv[] = { static const char * const rt5640_data_select[] = { "Normal", "left copy to right", "right copy to left", "Swap"}; -static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, - RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, + RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, - RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, + RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, - RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, + RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, - RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, + RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); /* Class D speaker gain ratio */ static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x", "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"}; -static const SOC_ENUM_SINGLE_DECL( - rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, - RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); +static SOC_ENUM_SINGLE_DECL(rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, + RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); static const struct snd_kcontrol_new rt5640_snd_controls[] = { /* Speaker Output Volume */ @@ -753,9 +752,8 @@ static const char * const rt5640_stereo_adc1_src[] = { "DIG MIX", "ADC" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, - RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, + RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); static const struct snd_kcontrol_new rt5640_sto_adc_1_mux = SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum); @@ -764,9 +762,8 @@ static const char * const rt5640_stereo_adc2_src[] = { "DMIC1", "DMIC2", "DIG MIX" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, - RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, + RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); static const struct snd_kcontrol_new rt5640_sto_adc_2_mux = SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum); @@ -776,9 +773,8 @@ static const char * const rt5640_mono_adc_l1_src[] = { "Mono DAC MIXL", "ADCL" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux = SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum); @@ -787,9 +783,8 @@ static const char * const rt5640_mono_adc_l2_src[] = { "DMIC L1", "DMIC L2", "Mono DAC MIXL" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux = SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum); @@ -798,9 +793,8 @@ static const char * const rt5640_mono_adc_r1_src[] = { "Mono DAC MIXR", "ADCR" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux = SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum); @@ -809,9 +803,8 @@ static const char * const rt5640_mono_adc_r2_src[] = { "DMIC R1", "DMIC R2", "Mono DAC MIXR" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux = SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum); @@ -826,9 +819,9 @@ static int rt5640_dac_l2_values[] = { 3, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, - 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_l2_enum, + RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, + 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); static const struct snd_kcontrol_new rt5640_dac_l2_mux = SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum); @@ -841,9 +834,9 @@ static int rt5640_dac_r2_values[] = { 0, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, - 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_r2_enum, + RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, + 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); static const struct snd_kcontrol_new rt5640_dac_r2_mux = SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum); @@ -860,9 +853,10 @@ static int rt5640_dai_iis_map_values[] = { 7, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, - 0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dai_iis_map_enum, + RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, + 0x7, rt5640_dai_iis_map, + rt5640_dai_iis_map_values); static const struct snd_kcontrol_new rt5640_dai_mux = SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum); @@ -872,9 +866,8 @@ static const char * const rt5640_sdi_sel[] = { "IF1", "IF2" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_sdi_sel_enum, RT5640_I2S2_SDP, - RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); +static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP, + RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); static const struct snd_kcontrol_new rt5640_sdi_mux = SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); -- cgit v0.10.2 From 655e3652db7c5fd73d8b7949f24e9d7432cdb806 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:35 +0100 Subject: ASoC: ssm2518: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index cc8debc..806f3d8 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -169,19 +169,19 @@ static const char * const ssm2518_drc_hold_time_text[] = { "682.24 ms", "1364 ms", }; -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text); static const struct snd_kcontrol_new ssm2518_snd_controls[] = { -- cgit v0.10.2 From f281205422d8924bee025af79f222d0c79646ae7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:49 +0100 Subject: ASoC: sta529: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 40c07be..f15b0e3 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -141,7 +141,7 @@ static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary", static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); -static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); +static SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); static const struct snd_kcontrol_new sta529_snd_controls[] = { SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, -- cgit v0.10.2 From da9f39f512eb2ac322d0ee340479d2739759919e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:00 +0100 Subject: ASoC: wm8804: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9bc8206..72d12bb 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -92,7 +92,7 @@ WM8804_REGULATOR_EVENT(0) WM8804_REGULATOR_EVENT(1) static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; -static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); +static SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); static const struct snd_kcontrol_new wm8804_snd_controls[] = { SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put), -- cgit v0.10.2 From 11a544bb2fe5bcacd20d2cdb9b792e035bd82eb2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:10 +0100 Subject: ASoC: wm8978: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index d8fc531..a9e2f46 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -117,21 +117,21 @@ static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"}; static const char *wm8978_alc3[] = {"ALC", "Limiter"}; static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"}; -static const SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); -static const SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); -static const SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); -static const SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); -static const SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); -static const SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); -static const SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); -static const SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); +static SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, + wm8978_companding); +static SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, + wm8978_companding); +static SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); +static SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); +static SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); +static SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); +static SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); +static SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); +static SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); +static SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -- cgit v0.10.2 From ae170688da955e9fb0536a117be63ee031cd1f6d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:56 +0100 Subject: ASoC: wm8983: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index aa41ba0..770e5a7 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -205,49 +205,44 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, - alc_sel_text); +static SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, alc_sel_text); static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, - alc_mode_text); +static SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, alc_mode_text); static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, - filter_mode_text); +static SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, + filter_mode_text); static const char *eq_bw_text[] = { "Narrow", "Wide" }; static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); +static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); static const char *eq1_cutoff_text[] = { "80Hz", "105Hz", "135Hz", "175Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, + eq1_cutoff_text); static const char *eq2_cutoff_text[] = { "230Hz", "300Hz", "385Hz", "500Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, - eq2_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, eq2_cutoff_text); static const char *eq3_cutoff_text[] = { "650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, - eq3_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, eq3_cutoff_text); static const char *eq4_cutoff_text[] = { "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, - eq4_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, eq4_cutoff_text); static const char *eq5_cutoff_text[] = { "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, - eq5_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, + eq5_cutoff_text); static const char *depth_3d_text[] = { "Off", @@ -267,8 +262,8 @@ static const char *depth_3d_text[] = { "93.3%", "100%" }; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, - depth_3d_text); +static SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, + depth_3d_text); static const struct snd_kcontrol_new wm8983_snd_controls[] = { SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, -- cgit v0.10.2 From d0a4eec16adf3a528dbd1b52c3fc653a2bfee8c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:45:08 +0100 Subject: ASoC: wm8985: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 271b517..d786f2b 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -226,52 +226,48 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, - alc_sel_text); +static SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, alc_sel_text); static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, - alc_mode_text); +static SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, alc_mode_text); static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, - filter_mode_text); +static SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, + filter_mode_text); static const char *eq_bw_text[] = { "Narrow", "Wide" }; static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); +static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); static const char *eq1_cutoff_text[] = { "80Hz", "105Hz", "135Hz", "175Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, + eq1_cutoff_text); static const char *eq2_cutoff_text[] = { "230Hz", "300Hz", "385Hz", "500Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, - eq2_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, eq2_cutoff_text); static const char *eq3_cutoff_text[] = { "650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, - eq3_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, + eq3_cutoff_text); static const char *eq4_cutoff_text[] = { "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, - eq4_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, eq4_cutoff_text); static const char *eq5_cutoff_text[] = { "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, +static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, eq5_cutoff_text); static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; -static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); static const char *depth_3d_text[] = { "Off", @@ -291,8 +287,7 @@ static const char *depth_3d_text[] = { "93.3%", "100%" }; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, - depth_3d_text); +static SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, depth_3d_text); static const struct snd_kcontrol_new wm8985_snd_controls[] = { SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL, -- cgit v0.10.2 From 48e50ce37fcf4c376845d1c42177eeb1601f99ad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:45:18 +0100 Subject: ASoC: wm8995: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 4300caf..dcd1e72 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -423,24 +423,24 @@ static const char *in1l_text[] = { "Differential", "Single-ended IN1LN", "Single-ended IN1LP" }; -static const SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 2, in1l_text); +static SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, + 2, in1l_text); static const char *in1r_text[] = { "Differential", "Single-ended IN1RN", "Single-ended IN1RP" }; -static const SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 0, in1r_text); +static SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, + 0, in1r_text); static const char *dmic_src_text[] = { "DMICDAT1", "DMICDAT2", "DMICDAT3" }; -static const SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, - 8, dmic_src_text); -static const SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, - 6, dmic_src_text); +static SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, + 8, dmic_src_text); +static SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, + 6, dmic_src_text); static const struct snd_kcontrol_new wm8995_snd_controls[] = { SOC_DOUBLE_R_TLV("DAC1 Volume", WM8995_DAC1_LEFT_VOLUME, @@ -899,14 +899,14 @@ static const char *spk_src_text[] = { "DAC1L", "DAC1R", "DAC2L", "DAC2R" }; -static const SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, - 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, + 0, spk_src_text); static const struct snd_kcontrol_new spk1l_mux = SOC_DAPM_ENUM("SPK1L SRC", spk1l_src_enum); -- cgit v0.10.2 From 27ca2c30f4fec73d53f727fe2fe729e16d9a43b2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:01:43 +0100 Subject: ASoC: arizona: Fix wrong number of items in enum ctls arizona codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e4295fe..a32b84a 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -542,67 +542,76 @@ static const char *arizona_vol_ramp_text[] = { "15ms/6dB", "30ms/6dB", }; -const struct soc_enum arizona_in_vd_ramp = - SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, - ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp, + ARIZONA_INPUT_VOLUME_RAMP, + ARIZONA_IN_VD_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); -const struct soc_enum arizona_in_vi_ramp = - SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, - ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp, + ARIZONA_INPUT_VOLUME_RAMP, + ARIZONA_IN_VI_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); -const struct soc_enum arizona_out_vd_ramp = - SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, - ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp, + ARIZONA_OUTPUT_VOLUME_RAMP, + ARIZONA_OUT_VD_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); -const struct soc_enum arizona_out_vi_ramp = - SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, - ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp, + ARIZONA_OUTPUT_VOLUME_RAMP, + ARIZONA_OUT_VI_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); static const char *arizona_lhpf_mode_text[] = { "Low-pass", "High-pass" }; -const struct soc_enum arizona_lhpf1_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode, + ARIZONA_HPLPF1_1, + ARIZONA_LHPF1_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); -const struct soc_enum arizona_lhpf2_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode, + ARIZONA_HPLPF2_1, + ARIZONA_LHPF2_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); -const struct soc_enum arizona_lhpf3_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode, + ARIZONA_HPLPF3_1, + ARIZONA_LHPF3_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); -const struct soc_enum arizona_lhpf4_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode, + ARIZONA_HPLPF4_1, + ARIZONA_LHPF4_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); static const char *arizona_ng_hold_text[] = { "30ms", "120ms", "250ms", "500ms", }; -const struct soc_enum arizona_ng_hold = - SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT, - 4, arizona_ng_hold_text); +SOC_ENUM_SINGLE_DECL(arizona_ng_hold, + ARIZONA_NOISE_GATE_CONTROL, + ARIZONA_NGATE_HOLD_SHIFT, + arizona_ng_hold_text); EXPORT_SYMBOL_GPL(arizona_ng_hold); static const char * const arizona_in_hpf_cut_text[] = { "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" }; -const struct soc_enum arizona_in_hpf_cut_enum = - SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT, - ARRAY_SIZE(arizona_in_hpf_cut_text), - arizona_in_hpf_cut_text); +SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum, + ARIZONA_HPF_CONTROL, + ARIZONA_IN_HPF_CUT_SHIFT, + arizona_in_hpf_cut_text); EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); static const char * const arizona_in_dmic_osr_text[] = { -- cgit v0.10.2 From 901bb6c55d2a7ef66bc0bdf0ba410c417f16b7cf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:56:40 +0100 Subject: ASoC: ad1980: Fix wrong number of items for capture source The number of capture sources is 8, not 7. Use SOC_ENUM_DOUBLE_DECL() macro and it's automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 7257a88..34d965a 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -57,8 +57,8 @@ static const u16 ad1980_reg[] = { static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", "Stereo Mix", "Mono Mix", "Phone"}; -static const struct soc_enum ad1980_cap_src = - SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel); +static SOC_ENUM_DOUBLE_DECL(ad1980_cap_src, + AC97_REC_SEL, 8, 0, ad1980_rec_sel); static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = { SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), -- cgit v0.10.2 From cdbb492557112bddad26f0ba4ba9ba87d919ebfc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:07:56 +0100 Subject: ASoC: isabelle: Fix the wrong number of items in enum ctls isabelle codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5839048..cb736dd 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -140,13 +140,17 @@ static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"}; static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"}; static const struct soc_enum isabelle_rx1_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts), - SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts), + SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, + ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts), + SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, + ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts), }; static const struct soc_enum isabelle_rx2_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts), - SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts), + SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, + ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts), + SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, + ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts), }; /* Headset DAC playback switches */ @@ -161,13 +165,17 @@ static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"}; static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"}; static const struct soc_enum isabelle_atx_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts), - SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts), + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, + ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts), + SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, + ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts), }; static const struct soc_enum isabelle_vtx_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts), - SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts), + SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, + ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts), + SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, + ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts), }; static const struct snd_kcontrol_new atx_mux_controls = @@ -183,17 +191,13 @@ static const char *isabelle_amic1_texts[] = { /* Left analog microphone selection */ static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"}; -static const struct soc_enum isabelle_amic1_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5, - ARRAY_SIZE(isabelle_amic1_texts), - isabelle_amic1_texts), -}; +static SOC_ENUM_SINGLE_DECL(isabelle_amic1_enum, + ISABELLE_AMIC_CFG_REG, 5, + isabelle_amic1_texts); -static const struct soc_enum isabelle_amic2_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4, - ARRAY_SIZE(isabelle_amic2_texts), - isabelle_amic2_texts), -}; +static SOC_ENUM_SINGLE_DECL(isabelle_amic2_enum, + ISABELLE_AMIC_CFG_REG, 4, + isabelle_amic2_texts); static const struct snd_kcontrol_new amic1_control = SOC_DAPM_ENUM("Route", isabelle_amic1_enum); @@ -206,16 +210,20 @@ static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"}; static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"}; static const struct soc_enum isabelle_st_audio_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1, + SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, + ARRAY_SIZE(isabelle_st_audio_texts), isabelle_st_audio_texts), - SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1, + SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, + ARRAY_SIZE(isabelle_st_audio_texts), isabelle_st_audio_texts), }; static const struct soc_enum isabelle_st_voice_enum[] = { - SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1, + SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, + ARRAY_SIZE(isabelle_st_voice_texts), isabelle_st_voice_texts), - SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1, + SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, + ARRAY_SIZE(isabelle_st_voice_texts), isabelle_st_voice_texts), }; -- cgit v0.10.2 From 898b48eb88bff3a7a49590a08bee546c2d26bd91 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:34:44 +0100 Subject: ASoC: wm8400: Fix the wrong number of enum items wm8400 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 48dc7d2..6d684d9 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -117,19 +117,23 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8400_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8400_left_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, - WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8400_left_digital_sidetone_enum, + WM8400_DIGITAL_SIDE_TONE, + WM8400_ADC_TO_DACL_SHIFT, + wm8400_digital_sidetone); -static const struct soc_enum wm8400_right_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, - WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8400_right_digital_sidetone_enum, + WM8400_DIGITAL_SIDE_TONE, + WM8400_ADC_TO_DACR_SHIFT, + wm8400_digital_sidetone); static const char *wm8400_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8400_right_adcmode_enum = -SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8400_right_adcmode_enum, + WM8400_ADC_CTRL, + WM8400_ADC_HPF_CUT_SHIFT, + wm8400_adcmode); static const struct snd_kcontrol_new wm8400_snd_controls[] = { /* INMIXL */ @@ -422,9 +426,10 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, static const char *wm8400_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8400_ainlmux_enum = -SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT, - ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8400_ainlmux_enum, + WM8400_INPUT_MIXER1, + WM8400_AINLMODE_SHIFT, + wm8400_ainlmux); static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); @@ -435,9 +440,10 @@ SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); static const char *wm8400_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8400_ainrmux_enum = -SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT, - ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum, + WM8400_INPUT_MIXER1, + WM8400_AINRMODE_SHIFT, + wm8400_ainrmux); static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); -- cgit v0.10.2 From 1c38450b9fe52a86da7f4fd2a2c97935b71f2b62 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:58:45 +0100 Subject: ASoC: adau1373: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index eb836ed..83c0acd 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = { "DMIC1", }; -static const struct soc_enum adau1373_decimator_enum = - SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); +static SOC_ENUM_SINGLE_DECL(adau1373_decimator_enum, + 0, 0, adau1373_decimator_text); static const struct snd_kcontrol_new adau1373_decimator_mux = SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); -- cgit v0.10.2 From 98bf1b5e788e63536705dcc418cc97b36481067e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:00:29 +0100 Subject: ASoC: alc5623: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index d303628..ba61c07 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -228,32 +228,37 @@ static const char *alc5623_aux_out_input_sel[] = { "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; /* auxout output mux */ -static const struct soc_enum alc5623_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 6, + alc5623_aux_out_input_sel); static const struct snd_kcontrol_new alc5623_auxout_mux_controls = SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum); /* speaker output mux */ -static const struct soc_enum alc5623_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 10, + alc5623_spkout_input_sel); static const struct snd_kcontrol_new alc5623_spkout_mux_controls = SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum); /* headphone left output mux */ -static const struct soc_enum alc5623_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 9, + alc5623_hpl_out_input_sel); static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls = SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum); /* headphone right output mux */ -static const struct soc_enum alc5623_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 8, + alc5623_hpr_out_input_sel); static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls = SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum); /* speaker output N select */ -static const struct soc_enum alc5623_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum, + ALC5623_OUTPUT_MIXER_CTRL, 14, + alc5623_spk_n_sour_sel); static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls = SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum); @@ -338,8 +343,9 @@ SND_SOC_DAPM_VMID("Vmid"), }; static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5623_amp_enum = - SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names); +static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum, + ALC5623_OUTPUT_MIXER_CTRL, 13, + alc5623_amp_names); static const struct snd_kcontrol_new alc5623_amp_mux_controls = SOC_DAPM_ENUM("Route", alc5623_amp_enum); -- cgit v0.10.2 From 4682a0a2b8e5d9633727276455f445e0b402767c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:05:01 +0100 Subject: ASoC: cs42l52: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Acked-by: Brian Austin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 0bac6d5..be455ea 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -210,13 +210,11 @@ static const char * const cs42l52_adca_text[] = { static const char * const cs42l52_adcb_text[] = { "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"}; -static const struct soc_enum adca_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_PGA_A, 5, - ARRAY_SIZE(cs42l52_adca_text), cs42l52_adca_text); +static SOC_ENUM_SINGLE_DECL(adca_enum, + CS42L52_ADC_PGA_A, 5, cs42l52_adca_text); -static const struct soc_enum adcb_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_PGA_B, 5, - ARRAY_SIZE(cs42l52_adcb_text), cs42l52_adcb_text); +static SOC_ENUM_SINGLE_DECL(adcb_enum, + CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text); static const struct snd_kcontrol_new adca_mux = SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum); @@ -229,26 +227,22 @@ static const char * const mic_bias_level_text[] = { "0.8 +VA", "0.83 +VA", "0.91 +VA" }; -static const struct soc_enum mic_bias_level_enum = - SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, - ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); +static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum, + CS42L52_IFACE_CTL2, 0, mic_bias_level_text); static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; -static const struct soc_enum mica_enum = - SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, - ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); +static SOC_ENUM_SINGLE_DECL(mica_enum, + CS42L52_MICA_CTL, 5, cs42l52_mic_text); -static const struct soc_enum micb_enum = - SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, - ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); +static SOC_ENUM_SINGLE_DECL(micb_enum, + CS42L52_MICB_CTL, 5, cs42l52_mic_text); static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; -static const struct soc_enum digital_output_mux_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_MISC_CTL, 6, - ARRAY_SIZE(digital_output_mux_text), - digital_output_mux_text); +static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum, + CS42L52_ADC_MISC_CTL, 6, + digital_output_mux_text); static const struct snd_kcontrol_new digital_output_mux = SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum); @@ -258,18 +252,18 @@ static const char * const hp_gain_num_text[] = { "0.7099", "0.8399", "1.000", "1.1430" }; -static const struct soc_enum hp_gain_enum = - SOC_ENUM_SINGLE(CS42L52_PB_CTL1, 5, - ARRAY_SIZE(hp_gain_num_text), hp_gain_num_text); +static SOC_ENUM_SINGLE_DECL(hp_gain_enum, + CS42L52_PB_CTL1, 5, + hp_gain_num_text); static const char * const beep_pitch_text[] = { "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7" }; -static const struct soc_enum beep_pitch_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 4, - ARRAY_SIZE(beep_pitch_text), beep_pitch_text); +static SOC_ENUM_SINGLE_DECL(beep_pitch_enum, + CS42L52_BEEP_FREQ, 4, + beep_pitch_text); static const char * const beep_ontime_text[] = { "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s", @@ -277,66 +271,66 @@ static const char * const beep_ontime_text[] = { "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s" }; -static const struct soc_enum beep_ontime_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 0, - ARRAY_SIZE(beep_ontime_text), beep_ontime_text); +static SOC_ENUM_SINGLE_DECL(beep_ontime_enum, + CS42L52_BEEP_FREQ, 0, + beep_ontime_text); static const char * const beep_offtime_text[] = { "1.23 s", "2.58 s", "3.90 s", "5.20 s", "6.60 s", "8.05 s", "9.35 s", "10.80 s" }; -static const struct soc_enum beep_offtime_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_VOL, 5, - ARRAY_SIZE(beep_offtime_text), beep_offtime_text); +static SOC_ENUM_SINGLE_DECL(beep_offtime_enum, + CS42L52_BEEP_VOL, 5, + beep_offtime_text); static const char * const beep_config_text[] = { "Off", "Single", "Multiple", "Continuous" }; -static const struct soc_enum beep_config_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 6, - ARRAY_SIZE(beep_config_text), beep_config_text); +static SOC_ENUM_SINGLE_DECL(beep_config_enum, + CS42L52_BEEP_TONE_CTL, 6, + beep_config_text); static const char * const beep_bass_text[] = { "50 Hz", "100 Hz", "200 Hz", "250 Hz" }; -static const struct soc_enum beep_bass_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 1, - ARRAY_SIZE(beep_bass_text), beep_bass_text); +static SOC_ENUM_SINGLE_DECL(beep_bass_enum, + CS42L52_BEEP_TONE_CTL, 1, + beep_bass_text); static const char * const beep_treble_text[] = { "5 kHz", "7 kHz", "10 kHz", " 15 kHz" }; -static const struct soc_enum beep_treble_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 3, - ARRAY_SIZE(beep_treble_text), beep_treble_text); +static SOC_ENUM_SINGLE_DECL(beep_treble_enum, + CS42L52_BEEP_TONE_CTL, 3, + beep_treble_text); static const char * const ng_threshold_text[] = { "-34dB", "-37dB", "-40dB", "-43dB", "-46dB", "-52dB", "-58dB", "-64dB" }; -static const struct soc_enum ng_threshold_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 2, - ARRAY_SIZE(ng_threshold_text), ng_threshold_text); +static SOC_ENUM_SINGLE_DECL(ng_threshold_enum, + CS42L52_NOISE_GATE_CTL, 2, + ng_threshold_text); static const char * const cs42l52_ng_delay_text[] = { "50ms", "100ms", "150ms", "200ms"}; -static const struct soc_enum ng_delay_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 0, - ARRAY_SIZE(cs42l52_ng_delay_text), cs42l52_ng_delay_text); +static SOC_ENUM_SINGLE_DECL(ng_delay_enum, + CS42L52_NOISE_GATE_CTL, 0, + cs42l52_ng_delay_text); static const char * const cs42l52_ng_type_text[] = { "Apply Specific", "Apply All" }; -static const struct soc_enum ng_type_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 6, - ARRAY_SIZE(cs42l52_ng_type_text), cs42l52_ng_type_text); +static SOC_ENUM_SINGLE_DECL(ng_type_enum, + CS42L52_NOISE_GATE_CTL, 6, + cs42l52_ng_type_text); static const char * const left_swap_text[] = { "Left", "LR 2", "Right"}; -- cgit v0.10.2 From e34042d850a7117b9acafeabd50287d5d8e61849 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:06:00 +0100 Subject: ASoC: da7210: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index e62e294..01e55fc 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -307,29 +307,29 @@ static const char * const da7210_hpf_cutoff_txt[] = { "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi" }; -static const struct soc_enum da7210_dac_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_dac_hpf_cutoff, + DA7210_DAC_HPF, 0, da7210_hpf_cutoff_txt); -static const struct soc_enum da7210_adc_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_adc_hpf_cutoff, + DA7210_ADC_HPF, 0, da7210_hpf_cutoff_txt); /* ADC and DAC voice (8kHz) high pass cutoff value */ static const char * const da7210_vf_cutoff_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da7210_dac_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_dac_vf_cutoff, + DA7210_DAC_HPF, 4, da7210_vf_cutoff_txt); -static const struct soc_enum da7210_adc_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_adc_vf_cutoff, + DA7210_ADC_HPF, 4, da7210_vf_cutoff_txt); static const char *da7210_hp_mode_txt[] = { "Class H", "Class G" }; -static const struct soc_enum da7210_hp_mode_sel = - SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); +static SOC_ENUM_SINGLE_DECL(da7210_hp_mode_sel, + DA7210_HP_CFG, 0, da7210_hp_mode_txt); /* ALC can be enabled only if noise suppression is disabled */ static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, -- cgit v0.10.2 From c99f8b216c39b1fbeb8b6830b95e461db551afa9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:06:47 +0100 Subject: ASoC: da7213: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0c77e7a..439d103 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -63,30 +63,30 @@ static const char * const da7213_voice_hpf_corner_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da7213_dac_voice_hpf_corner = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, - DA7213_VOICE_HPF_CORNER_MAX, - da7213_voice_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_voice_hpf_corner, + DA7213_DAC_FILTERS1, + DA7213_VOICE_HPF_CORNER_SHIFT, + da7213_voice_hpf_corner_txt); -static const struct soc_enum da7213_adc_voice_hpf_corner = - SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, - DA7213_VOICE_HPF_CORNER_MAX, - da7213_voice_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_adc_voice_hpf_corner, + DA7213_ADC_FILTERS1, + DA7213_VOICE_HPF_CORNER_SHIFT, + da7213_voice_hpf_corner_txt); /* ADC and DAC high pass filter cutoff value */ static const char * const da7213_audio_hpf_corner_txt[] = { "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" }; -static const struct soc_enum da7213_dac_audio_hpf_corner = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, - DA7213_AUDIO_HPF_CORNER_MAX, - da7213_audio_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_audio_hpf_corner, + DA7213_DAC_FILTERS1 + , DA7213_AUDIO_HPF_CORNER_SHIFT, + da7213_audio_hpf_corner_txt); -static const struct soc_enum da7213_adc_audio_hpf_corner = - SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, - DA7213_AUDIO_HPF_CORNER_MAX, - da7213_audio_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner, + DA7213_ADC_FILTERS1, + DA7213_AUDIO_HPF_CORNER_SHIFT, + da7213_audio_hpf_corner_txt); /* Gain ramping rate value */ static const char * const da7213_gain_ramp_rate_txt[] = { @@ -94,52 +94,50 @@ static const char * const da7213_gain_ramp_rate_txt[] = { "nominal rate / 32" }; -static const struct soc_enum da7213_gain_ramp_rate = - SOC_ENUM_SINGLE(DA7213_GAIN_RAMP_CTRL, DA7213_GAIN_RAMP_RATE_SHIFT, - DA7213_GAIN_RAMP_RATE_MAX, da7213_gain_ramp_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_gain_ramp_rate, + DA7213_GAIN_RAMP_CTRL, + DA7213_GAIN_RAMP_RATE_SHIFT, + da7213_gain_ramp_rate_txt); /* DAC noise gate setup time value */ static const char * const da7213_dac_ng_setup_time_txt[] = { "256 samples", "512 samples", "1024 samples", "2048 samples" }; -static const struct soc_enum da7213_dac_ng_setup_time = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_SETUP_TIME_SHIFT, - DA7213_DAC_NG_SETUP_TIME_MAX, - da7213_dac_ng_setup_time_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_setup_time, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_SETUP_TIME_SHIFT, + da7213_dac_ng_setup_time_txt); /* DAC noise gate rampup rate value */ static const char * const da7213_dac_ng_rampup_txt[] = { "0.02 ms/dB", "0.16 ms/dB" }; -static const struct soc_enum da7213_dac_ng_rampup_rate = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_RAMPUP_RATE_SHIFT, - DA7213_DAC_NG_RAMP_RATE_MAX, - da7213_dac_ng_rampup_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampup_rate, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_RAMPUP_RATE_SHIFT, + da7213_dac_ng_rampup_txt); /* DAC noise gate rampdown rate value */ static const char * const da7213_dac_ng_rampdown_txt[] = { "0.64 ms/dB", "20.48 ms/dB" }; -static const struct soc_enum da7213_dac_ng_rampdown_rate = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_RAMPDN_RATE_SHIFT, - DA7213_DAC_NG_RAMP_RATE_MAX, - da7213_dac_ng_rampdown_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampdown_rate, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_RAMPDN_RATE_SHIFT, + da7213_dac_ng_rampdown_txt); /* DAC soft mute rate value */ static const char * const da7213_dac_soft_mute_rate_txt[] = { "1", "2", "4", "8", "16", "32", "64" }; -static const struct soc_enum da7213_dac_soft_mute_rate = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS5, DA7213_DAC_SOFTMUTE_RATE_SHIFT, - DA7213_DAC_SOFTMUTE_RATE_MAX, - da7213_dac_soft_mute_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_soft_mute_rate, + DA7213_DAC_FILTERS5, + DA7213_DAC_SOFTMUTE_RATE_SHIFT, + da7213_dac_soft_mute_rate_txt); /* ALC Attack Rate select */ static const char * const da7213_alc_attack_rate_txt[] = { @@ -147,9 +145,10 @@ static const char * const da7213_alc_attack_rate_txt[] = { "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da7213_alc_attack_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_ATTACK_SHIFT, - DA7213_ALC_ATTACK_MAX, da7213_alc_attack_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_attack_rate, + DA7213_ALC_CTRL2, + DA7213_ALC_ATTACK_SHIFT, + da7213_alc_attack_rate_txt); /* ALC Release Rate select */ static const char * const da7213_alc_release_rate_txt[] = { @@ -157,9 +156,10 @@ static const char * const da7213_alc_release_rate_txt[] = { "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da7213_alc_release_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_RELEASE_SHIFT, - DA7213_ALC_RELEASE_MAX, da7213_alc_release_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_release_rate, + DA7213_ALC_CTRL2, + DA7213_ALC_RELEASE_SHIFT, + da7213_alc_release_rate_txt); /* ALC Hold Time select */ static const char * const da7213_alc_hold_time_txt[] = { @@ -168,22 +168,25 @@ static const char * const da7213_alc_hold_time_txt[] = { "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" }; -static const struct soc_enum da7213_alc_hold_time = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_HOLD_SHIFT, - DA7213_ALC_HOLD_MAX, da7213_alc_hold_time_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_hold_time, + DA7213_ALC_CTRL3, + DA7213_ALC_HOLD_SHIFT, + da7213_alc_hold_time_txt); /* ALC Input Signal Tracking rate select */ static const char * const da7213_alc_integ_rate_txt[] = { "1/4", "1/16", "1/256", "1/65536" }; -static const struct soc_enum da7213_alc_integ_attack_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_ATTACK_SHIFT, - DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_attack_rate, + DA7213_ALC_CTRL3, + DA7213_ALC_INTEG_ATTACK_SHIFT, + da7213_alc_integ_rate_txt); -static const struct soc_enum da7213_alc_integ_release_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_RELEASE_SHIFT, - DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate, + DA7213_ALC_CTRL3, + DA7213_ALC_INTEG_RELEASE_SHIFT, + da7213_alc_integ_rate_txt); /* @@ -584,15 +587,17 @@ static const char * const da7213_mic_amp_in_sel_txt[] = { "Differential", "MIC_P", "MIC_N" }; -static const struct soc_enum da7213_mic_1_amp_in_sel = - SOC_ENUM_SINGLE(DA7213_MIC_1_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, - DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); +static SOC_ENUM_SINGLE_DECL(da7213_mic_1_amp_in_sel, + DA7213_MIC_1_CTRL, + DA7213_MIC_AMP_IN_SEL_SHIFT, + da7213_mic_amp_in_sel_txt); static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux = SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel); -static const struct soc_enum da7213_mic_2_amp_in_sel = - SOC_ENUM_SINGLE(DA7213_MIC_2_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, - DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); +static SOC_ENUM_SINGLE_DECL(da7213_mic_2_amp_in_sel, + DA7213_MIC_2_CTRL, + DA7213_MIC_AMP_IN_SEL_SHIFT, + da7213_mic_amp_in_sel_txt); static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux = SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel); @@ -601,15 +606,17 @@ static const char * const da7213_dai_src_txt[] = { "ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right" }; -static const struct soc_enum da7213_dai_l_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_L_SRC_SHIFT, - DA7213_DAI_SRC_MAX, da7213_dai_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dai_l_src, + DA7213_DIG_ROUTING_DAI, + DA7213_DAI_L_SRC_SHIFT, + da7213_dai_src_txt); static const struct snd_kcontrol_new da7213_dai_l_src_mux = SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src); -static const struct soc_enum da7213_dai_r_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_R_SRC_SHIFT, - DA7213_DAI_SRC_MAX, da7213_dai_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dai_r_src, + DA7213_DIG_ROUTING_DAI, + DA7213_DAI_R_SRC_SHIFT, + da7213_dai_src_txt); static const struct snd_kcontrol_new da7213_dai_r_src_mux = SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src); @@ -619,15 +626,17 @@ static const char * const da7213_dac_src_txt[] = { "DAI Input Right" }; -static const struct soc_enum da7213_dac_l_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_L_SRC_SHIFT, - DA7213_DAC_SRC_MAX, da7213_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_l_src, + DA7213_DIG_ROUTING_DAC, + DA7213_DAC_L_SRC_SHIFT, + da7213_dac_src_txt); static const struct snd_kcontrol_new da7213_dac_l_src_mux = SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src); -static const struct soc_enum da7213_dac_r_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_R_SRC_SHIFT, - DA7213_DAC_SRC_MAX, da7213_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_r_src, + DA7213_DIG_ROUTING_DAC, + DA7213_DAC_R_SRC_SHIFT, + da7213_dac_src_txt); static const struct snd_kcontrol_new da7213_dac_r_src_mux = SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src); -- cgit v0.10.2 From 9839ce9360c4410bdf30d2670a2329c444160f02 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:07:25 +0100 Subject: ASoC: da9055: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index be31f3c..f118daa 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -323,22 +323,22 @@ static const char * const da9055_hpf_cutoff_txt[] = { "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" }; -static const struct soc_enum da9055_dac_hpf_cutoff = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_hpf_cutoff, + DA9055_DAC_FILTERS1, 4, da9055_hpf_cutoff_txt); -static const struct soc_enum da9055_adc_hpf_cutoff = - SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_adc_hpf_cutoff, + DA9055_ADC_FILTERS1, 4, da9055_hpf_cutoff_txt); /* ADC and DAC voice mode (8kHz) high pass cutoff value */ static const char * const da9055_vf_cutoff_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da9055_dac_vf_cutoff = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_vf_cutoff, + DA9055_DAC_FILTERS1, 0, da9055_vf_cutoff_txt); -static const struct soc_enum da9055_adc_vf_cutoff = - SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_adc_vf_cutoff, + DA9055_ADC_FILTERS1, 0, da9055_vf_cutoff_txt); /* Gain ramping rate value */ static const char * const da9055_gain_ramping_txt[] = { @@ -346,44 +346,44 @@ static const char * const da9055_gain_ramping_txt[] = { "nominal rate / 8" }; -static const struct soc_enum da9055_gain_ramping_rate = - SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt); +static SOC_ENUM_SINGLE_DECL(da9055_gain_ramping_rate, + DA9055_GAIN_RAMP_CTRL, 0, da9055_gain_ramping_txt); /* DAC noise gate setup time value */ static const char * const da9055_dac_ng_setup_time_txt[] = { "256 samples", "512 samples", "1024 samples", "2048 samples" }; -static const struct soc_enum da9055_dac_ng_setup_time = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4, - da9055_dac_ng_setup_time_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_setup_time, + DA9055_DAC_NG_SETUP_TIME, 0, + da9055_dac_ng_setup_time_txt); /* DAC noise gate rampup rate value */ static const char * const da9055_dac_ng_rampup_txt[] = { "0.02 ms/dB", "0.16 ms/dB" }; -static const struct soc_enum da9055_dac_ng_rampup_rate = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2, - da9055_dac_ng_rampup_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampup_rate, + DA9055_DAC_NG_SETUP_TIME, 2, + da9055_dac_ng_rampup_txt); /* DAC noise gate rampdown rate value */ static const char * const da9055_dac_ng_rampdown_txt[] = { "0.64 ms/dB", "20.48 ms/dB" }; -static const struct soc_enum da9055_dac_ng_rampdown_rate = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2, - da9055_dac_ng_rampdown_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampdown_rate, + DA9055_DAC_NG_SETUP_TIME, 3, + da9055_dac_ng_rampdown_txt); /* DAC soft mute rate value */ static const char * const da9055_dac_soft_mute_rate_txt[] = { "1", "2", "4", "8", "16", "32", "64" }; -static const struct soc_enum da9055_dac_soft_mute_rate = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7, - da9055_dac_soft_mute_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_soft_mute_rate, + DA9055_DAC_FILTERS5, 4, + da9055_dac_soft_mute_rate_txt); /* DAC routing select */ static const char * const da9055_dac_src_txt[] = { @@ -391,40 +391,40 @@ static const char * const da9055_dac_src_txt[] = { "AIF input right" }; -static const struct soc_enum da9055_dac_l_src = - SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_l_src, + DA9055_DIG_ROUTING_DAC, 0, da9055_dac_src_txt); -static const struct soc_enum da9055_dac_r_src = - SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_r_src, + DA9055_DIG_ROUTING_DAC, 4, da9055_dac_src_txt); /* MIC PGA Left source select */ static const char * const da9055_mic_l_src_txt[] = { "MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L" }; -static const struct soc_enum da9055_mic_l_src = - SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_mic_l_src, + DA9055_MIXIN_L_SELECT, 4, da9055_mic_l_src_txt); /* MIC PGA Right source select */ static const char * const da9055_mic_r_src_txt[] = { "MIC2_R_L", "MIC2_R", "MIC2_L" }; -static const struct soc_enum da9055_mic_r_src = - SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_mic_r_src, + DA9055_MIXIN_R_SELECT, 4, da9055_mic_r_src_txt); /* ALC Input Signal Tracking rate select */ static const char * const da9055_signal_tracking_rate_txt[] = { "1/4", "1/16", "1/256", "1/65536" }; -static const struct soc_enum da9055_integ_attack_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4, - da9055_signal_tracking_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_integ_attack_rate, + DA9055_ALC_CTRL3, 4, + da9055_signal_tracking_rate_txt); -static const struct soc_enum da9055_integ_release_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4, - da9055_signal_tracking_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_integ_release_rate, + DA9055_ALC_CTRL3, 6, + da9055_signal_tracking_rate_txt); /* ALC Attack Rate select */ static const char * const da9055_attack_rate_txt[] = { @@ -432,8 +432,8 @@ static const char * const da9055_attack_rate_txt[] = { "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da9055_attack_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_attack_rate, + DA9055_ALC_CTRL2, 0, da9055_attack_rate_txt); /* ALC Release Rate select */ static const char * const da9055_release_rate_txt[] = { @@ -441,8 +441,8 @@ static const char * const da9055_release_rate_txt[] = { "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da9055_release_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_release_rate, + DA9055_ALC_CTRL2, 4, da9055_release_rate_txt); /* ALC Hold Time select */ static const char * const da9055_hold_time_txt[] = { @@ -451,8 +451,8 @@ static const char * const da9055_hold_time_txt[] = { "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" }; -static const struct soc_enum da9055_hold_time = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt); +static SOC_ENUM_SINGLE_DECL(da9055_hold_time, + DA9055_ALC_CTRL3, 0, da9055_hold_time_txt); static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val) { -- cgit v0.10.2 From 2907cbcc120e0c388df499fcb1be7d093ade3993 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:14:13 +0100 Subject: ASoC: max98090: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 51f9b3d..c7b9e90 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -512,65 +512,75 @@ static const char *max98090_perf_pwr_text[] = static const char *max98090_pwr_perf_text[] = { "Low Power", "High Performance" }; -static const struct soc_enum max98090_vcmbandgap_enum = - SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_vcmbandgap_enum, + M98090_REG_BIAS_CONTROL, + M98090_VCM_MODE_SHIFT, + max98090_pwr_perf_text); static const char *max98090_osr128_text[] = { "64*fs", "128*fs" }; -static const struct soc_enum max98090_osr128_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT, - ARRAY_SIZE(max98090_osr128_text), max98090_osr128_text); +static SOC_ENUM_SINGLE_DECL(max98090_osr128_enum, + M98090_REG_ADC_CONTROL, + M98090_OSR128_SHIFT, + max98090_osr128_text); static const char *max98090_mode_text[] = { "Voice", "Music" }; -static const struct soc_enum max98090_mode_enum = - SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, M98090_MODE_SHIFT, - ARRAY_SIZE(max98090_mode_text), max98090_mode_text); +static SOC_ENUM_SINGLE_DECL(max98090_mode_enum, + M98090_REG_FILTER_CONFIG, + M98090_MODE_SHIFT, + max98090_mode_text); -static const struct soc_enum max98090_filter_dmic34mode_enum = - SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, - M98090_FLT_DMIC34MODE_SHIFT, - ARRAY_SIZE(max98090_mode_text), max98090_mode_text); +static SOC_ENUM_SINGLE_DECL(max98090_filter_dmic34mode_enum, + M98090_REG_FILTER_CONFIG, + M98090_FLT_DMIC34MODE_SHIFT, + max98090_mode_text); static const char *max98090_drcatk_text[] = { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; -static const struct soc_enum max98090_drcatk_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT, - ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcatk_enum, + M98090_REG_DRC_TIMING, + M98090_DRCATK_SHIFT, + max98090_drcatk_text); static const char *max98090_drcrls_text[] = { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; -static const struct soc_enum max98090_drcrls_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT, - ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcrls_enum, + M98090_REG_DRC_TIMING, + M98090_DRCRLS_SHIFT, + max98090_drcrls_text); static const char *max98090_alccmp_text[] = { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; -static const struct soc_enum max98090_alccmp_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT, - ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text); +static SOC_ENUM_SINGLE_DECL(max98090_alccmp_enum, + M98090_REG_DRC_COMPRESSOR, + M98090_DRCCMP_SHIFT, + max98090_alccmp_text); static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; -static const struct soc_enum max98090_drcexp_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT, - ARRAY_SIZE(max98090_drcexp_text), max98090_drcexp_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcexp_enum, + M98090_REG_DRC_EXPANDER, + M98090_DRCEXP_SHIFT, + max98090_drcexp_text); -static const struct soc_enum max98090_dac_perfmode_enum = - SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_PERFMODE_SHIFT, - ARRAY_SIZE(max98090_perf_pwr_text), max98090_perf_pwr_text); +static SOC_ENUM_SINGLE_DECL(max98090_dac_perfmode_enum, + M98090_REG_DAC_CONTROL, + M98090_PERFMODE_SHIFT, + max98090_perf_pwr_text); -static const struct soc_enum max98090_dachp_enum = - SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_DACHP_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_dachp_enum, + M98090_REG_DAC_CONTROL, + M98090_DACHP_SHIFT, + max98090_pwr_perf_text); -static const struct soc_enum max98090_adchp_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_ADCHP_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum, + M98090_REG_ADC_CONTROL, + M98090_ADCHP_SHIFT, + max98090_pwr_perf_text); static const struct snd_kcontrol_new max98090_snd_controls[] = { SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum), @@ -841,39 +851,42 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, static const char *mic1_mux_text[] = { "IN12", "IN56" }; -static const struct soc_enum mic1_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC1_SHIFT, - ARRAY_SIZE(mic1_mux_text), mic1_mux_text); +static SOC_ENUM_SINGLE_DECL(mic1_mux_enum, + M98090_REG_INPUT_MODE, + M98090_EXTMIC1_SHIFT, + mic1_mux_text); static const struct snd_kcontrol_new max98090_mic1_mux = SOC_DAPM_ENUM("MIC1 Mux", mic1_mux_enum); static const char *mic2_mux_text[] = { "IN34", "IN56" }; -static const struct soc_enum mic2_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC2_SHIFT, - ARRAY_SIZE(mic2_mux_text), mic2_mux_text); +static SOC_ENUM_SINGLE_DECL(mic2_mux_enum, + M98090_REG_INPUT_MODE, + M98090_EXTMIC2_SHIFT, + mic2_mux_text); static const struct snd_kcontrol_new max98090_mic2_mux = SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); static const char *dmic_mux_text[] = { "ADC", "DMIC" }; -static const struct soc_enum dmic_mux_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text); +static SOC_ENUM_SINGLE_EXT_DECL(dmic_mux_enum, dmic_mux_text); static const struct snd_kcontrol_new max98090_dmic_mux = SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); static const char *max98090_micpre_text[] = { "Off", "On" }; -static const struct soc_enum max98090_pa1en_enum = - SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, - ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); +static SOC_ENUM_SINGLE_DECL(max98090_pa1en_enum, + M98090_REG_MIC1_INPUT_LEVEL, + M98090_MIC_PA1EN_SHIFT, + max98090_micpre_text); -static const struct soc_enum max98090_pa2en_enum = - SOC_ENUM_SINGLE(M98090_REG_MIC2_INPUT_LEVEL, M98090_MIC_PA2EN_SHIFT, - ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); +static SOC_ENUM_SINGLE_DECL(max98090_pa2en_enum, + M98090_REG_MIC2_INPUT_LEVEL, + M98090_MIC_PA2EN_SHIFT, + max98090_micpre_text); /* LINEA mixer switch */ static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = { @@ -937,13 +950,15 @@ static const struct snd_kcontrol_new max98090_right_adc_mixer_controls[] = { static const char *lten_mux_text[] = { "Normal", "Loopthrough" }; -static const struct soc_enum ltenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, - ARRAY_SIZE(lten_mux_text), lten_mux_text); +static SOC_ENUM_SINGLE_DECL(ltenl_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LTEN_SHIFT, + lten_mux_text); -static const struct soc_enum ltenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, - ARRAY_SIZE(lten_mux_text), lten_mux_text); +static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LTEN_SHIFT, + lten_mux_text); static const struct snd_kcontrol_new max98090_ltenl_mux = SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum); @@ -953,13 +968,15 @@ static const struct snd_kcontrol_new max98090_ltenr_mux = static const char *lben_mux_text[] = { "Normal", "Loopback" }; -static const struct soc_enum lbenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, - ARRAY_SIZE(lben_mux_text), lben_mux_text); +static SOC_ENUM_SINGLE_DECL(lbenl_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LBEN_SHIFT, + lben_mux_text); -static const struct soc_enum lbenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, - ARRAY_SIZE(lben_mux_text), lben_mux_text); +static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LBEN_SHIFT, + lben_mux_text); static const struct snd_kcontrol_new max98090_lbenl_mux = SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum); @@ -971,13 +988,15 @@ static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" }; static const char *stenr_mux_text[] = { "Normal", "Sidetone Right" }; -static const struct soc_enum stenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSL_SHIFT, - ARRAY_SIZE(stenl_mux_text), stenl_mux_text); +static SOC_ENUM_SINGLE_DECL(stenl_mux_enum, + M98090_REG_ADC_SIDETONE, + M98090_DSTSL_SHIFT, + stenl_mux_text); -static const struct soc_enum stenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSR_SHIFT, - ARRAY_SIZE(stenr_mux_text), stenr_mux_text); +static SOC_ENUM_SINGLE_DECL(stenr_mux_enum, + M98090_REG_ADC_SIDETONE, + M98090_DSTSR_SHIFT, + stenr_mux_text); static const struct snd_kcontrol_new max98090_stenl_mux = SOC_DAPM_ENUM("STENL Mux", stenl_mux_enum); @@ -1085,9 +1104,10 @@ static const struct snd_kcontrol_new max98090_right_rcv_mixer_controls[] = { static const char *linmod_mux_text[] = { "Left Only", "Left and Right" }; -static const struct soc_enum linmod_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_LOUTR_MIXER, M98090_LINMOD_SHIFT, - ARRAY_SIZE(linmod_mux_text), linmod_mux_text); +static SOC_ENUM_SINGLE_DECL(linmod_mux_enum, + M98090_REG_LOUTR_MIXER, + M98090_LINMOD_SHIFT, + linmod_mux_text); static const struct snd_kcontrol_new max98090_linmod_mux = SOC_DAPM_ENUM("LINMOD Mux", linmod_mux_enum); @@ -1097,16 +1117,18 @@ static const char *mixhpsel_mux_text[] = { "DAC Only", "HP Mixer" }; /* * This is a mux as it selects the HP output, but to DAPM it is a Mixer enable */ -static const struct soc_enum mixhplsel_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPLSEL_SHIFT, - ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); +static SOC_ENUM_SINGLE_DECL(mixhplsel_mux_enum, + M98090_REG_HP_CONTROL, + M98090_MIXHPLSEL_SHIFT, + mixhpsel_mux_text); static const struct snd_kcontrol_new max98090_mixhplsel_mux = SOC_DAPM_ENUM("MIXHPLSEL Mux", mixhplsel_mux_enum); -static const struct soc_enum mixhprsel_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPRSEL_SHIFT, - ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); +static SOC_ENUM_SINGLE_DECL(mixhprsel_mux_enum, + M98090_REG_HP_CONTROL, + M98090_MIXHPRSEL_SHIFT, + mixhpsel_mux_text); static const struct snd_kcontrol_new max98090_mixhprsel_mux = SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); -- cgit v0.10.2 From ebe44f350e15d6142d4d74cbaec0dad976c36753 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 20 Feb 2014 02:14:23 -0500 Subject: ip_tunnel: Move ip_tunnel_get_stats64 into ip_tunnel_core.c net/built-in.o:(.rodata+0x1707c): undefined reference to `ip_tunnel_get_stats64' Reported-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 50228be..08f8cf9 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -119,52 +119,6 @@ static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) return (struct rtable *)dst; } -/* Often modified stats are per cpu, other are shared (netdev->stats) */ -struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, - struct rtnl_link_stats64 *tot) -{ - int i; - - for_each_possible_cpu(i) { - const struct pcpu_sw_netstats *tstats = - per_cpu_ptr(dev->tstats, i); - u64 rx_packets, rx_bytes, tx_packets, tx_bytes; - unsigned int start; - - do { - start = u64_stats_fetch_begin_bh(&tstats->syncp); - rx_packets = tstats->rx_packets; - tx_packets = tstats->tx_packets; - rx_bytes = tstats->rx_bytes; - tx_bytes = tstats->tx_bytes; - } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); - - tot->rx_packets += rx_packets; - tot->tx_packets += tx_packets; - tot->rx_bytes += rx_bytes; - tot->tx_bytes += tx_bytes; - } - - tot->multicast = dev->stats.multicast; - - tot->rx_crc_errors = dev->stats.rx_crc_errors; - tot->rx_fifo_errors = dev->stats.rx_fifo_errors; - tot->rx_length_errors = dev->stats.rx_length_errors; - tot->rx_frame_errors = dev->stats.rx_frame_errors; - tot->rx_errors = dev->stats.rx_errors; - - tot->tx_fifo_errors = dev->stats.tx_fifo_errors; - tot->tx_carrier_errors = dev->stats.tx_carrier_errors; - tot->tx_dropped = dev->stats.tx_dropped; - tot->tx_aborted_errors = dev->stats.tx_aborted_errors; - tot->tx_errors = dev->stats.tx_errors; - - tot->collisions = dev->stats.collisions; - - return tot; -} -EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64); - static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, __be16 flags, __be32 key) { diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 6156f4e..8d69626 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -148,3 +148,49 @@ error: return ERR_PTR(err); } EXPORT_SYMBOL_GPL(iptunnel_handle_offloads); + +/* Often modified stats are per cpu, other are shared (netdev->stats) */ +struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *tot) +{ + int i; + + for_each_possible_cpu(i) { + const struct pcpu_sw_netstats *tstats = + per_cpu_ptr(dev->tstats, i); + u64 rx_packets, rx_bytes, tx_packets, tx_bytes; + unsigned int start; + + do { + start = u64_stats_fetch_begin_bh(&tstats->syncp); + rx_packets = tstats->rx_packets; + tx_packets = tstats->tx_packets; + rx_bytes = tstats->rx_bytes; + tx_bytes = tstats->tx_bytes; + } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); + + tot->rx_packets += rx_packets; + tot->tx_packets += tx_packets; + tot->rx_bytes += rx_bytes; + tot->tx_bytes += tx_bytes; + } + + tot->multicast = dev->stats.multicast; + + tot->rx_crc_errors = dev->stats.rx_crc_errors; + tot->rx_fifo_errors = dev->stats.rx_fifo_errors; + tot->rx_length_errors = dev->stats.rx_length_errors; + tot->rx_frame_errors = dev->stats.rx_frame_errors; + tot->rx_errors = dev->stats.rx_errors; + + tot->tx_fifo_errors = dev->stats.tx_fifo_errors; + tot->tx_carrier_errors = dev->stats.tx_carrier_errors; + tot->tx_dropped = dev->stats.tx_dropped; + tot->tx_aborted_errors = dev->stats.tx_aborted_errors; + tot->tx_errors = dev->stats.tx_errors; + + tot->collisions = dev->stats.collisions; + + return tot; +} +EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64); -- cgit v0.10.2 From 8d0d21f4053c07714802cbe8b1fe26913ec296cc Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Tue, 18 Feb 2014 21:20:08 +0900 Subject: veth: Fix vlan_features so as to be able to use stacked vlan interfaces Even if we create a stacked vlan interface such as veth0.10.20, it sends single tagged frames (tagged with only vid 10). Because vlan_features of a veth interface has the NETIF_F_HW_VLAN_[CTAG/STAG]_TX bits, veth0.10 also has that feature, so dev_hard_start_xmit(veth0.10) doesn't call __vlan_put_tag() and vlan_dev_hard_start_xmit(veth0.10) overwrites vlan_tci. This prevents us from using a combination of 802.1ad and 802.1Q in containers, etc. Signed-off-by: Toshiaki Makita Acked-by: Flavio Leitner Signed-off-by: David S. Miller diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 2ec2041..5b37437 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -285,7 +285,8 @@ static void veth_setup(struct net_device *dev) dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; dev->features |= VETH_FEATURES; - dev->vlan_features = dev->features; + dev->vlan_features = dev->features & + ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX); dev->destructor = veth_dev_free; dev->hw_features = VETH_FEATURES; -- cgit v0.10.2 From 6671b2240c54585d4afb5286a29f1569fe5e40a8 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Tue, 18 Feb 2014 21:20:09 +0900 Subject: tun: remove bogus hardware vlan acceleration flags from vlan_features Even though only the outer vlan tag can be HW accelerated in the transmission path, in the TUN/TAP driver vlan_features mirrors hw_features, which happens to have the NETIF_F_HW_VLAN_?TAG_TX flags set. Because of this, during packet tranmisssion through a stacked vlan device dev_hard_start_xmit, (incorrectly) assuming that the vlan device supports hardware vlan acceleration, does not add the vlan header to the skb payload and the inner vlan tags are lost (vlan_tci contains the outer vlan tag when userspace reads the packet from the tap device). Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: Toshiaki Makita Signed-off-by: David S. Miller diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 8fe9cb7..26f8635 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1686,7 +1686,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; dev->features = dev->hw_features; - dev->vlan_features = dev->features; + dev->vlan_features = dev->features & + ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX); INIT_LIST_HEAD(&tun->disabled); err = tun_attach(tun, file, false); -- cgit v0.10.2 From 63a5d4c6a71fda7ac567627d6ac4a74e9555e97c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Feb 2014 12:13:52 +0900 Subject: ALSA: Export snd_pcm_constraint_mask64() Allow modules to use it, fixing a build failure when the newly added ADAU1977 driver is built as a module. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown Acked-by: Takashi Iwai diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a210467..5dcf88b 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1242,6 +1242,7 @@ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_par return -EINVAL; return 0; } +EXPORT_SYMBOL(snd_pcm_hw_constraint_mask64); /** * snd_pcm_hw_constraint_integer - apply an integer constraint to an interval -- cgit v0.10.2 From a9952a76bc0c24b3c9d355c053e001b8a3b65dd3 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Wed, 19 Feb 2014 20:48:56 +0200 Subject: clk: tegra: Fix vic03 mux index The vic03 mux uses a linear mapping. Signed-off-by: Peter De Schrijver diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index f5376a3..1fa5c3f 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -371,9 +371,7 @@ static const char *mux_pllp3_pllc_clkm[] = { static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = { "pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m" }; -static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = { - [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, -}; +#define mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx NULL static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = { "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4", -- cgit v0.10.2 From 1d147bfa64293b2723c4fec50922168658e613ba Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 20 Feb 2014 09:22:11 +0200 Subject: mac80211: fix AP powersave TX vs. wakeup race There is a race between the TX path and the STA wakeup: while a station is sleeping, mac80211 buffers frames until it wakes up, then the frames are transmitted. However, the RX and TX path are concurrent, so the packet indicating wakeup can be processed while a packet is being transmitted. This can lead to a situation where the buffered frames list is emptied on the one side, while a frame is being added on the other side, as the station is still seen as sleeping in the TX path. As a result, the newly added frame will not be send anytime soon. It might be sent much later (and out of order) when the station goes to sleep and wakes up the next time. Additionally, it can lead to the crash below. Fix all this by synchronising both paths with a new lock. Both path are not fastpath since they handle PS situations. In a later patch we'll remove the extra skb queue locks to reduce locking overhead. BUG: unable to handle kernel NULL pointer dereference at 000000b0 IP: [] ieee80211_report_used_skb+0x11/0x3e0 [mac80211] *pde = 00000000 Oops: 0000 [#1] SMP DEBUG_PAGEALLOC EIP: 0060:[] EFLAGS: 00210282 CPU: 1 EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211] EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000 ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000) iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9 Stack: e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0 ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210 ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002 Call Trace: [] ieee80211_free_txskb+0x15/0x20 [mac80211] [] invoke_tx_handlers+0x1661/0x1780 [mac80211] [] ieee80211_tx+0x75/0x100 [mac80211] [] ieee80211_xmit+0x8f/0xc0 [mac80211] [] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211] [] dev_hard_start_xmit+0x450/0x950 [] sch_direct_xmit+0xa9/0x250 [] __qdisc_run+0x4b/0x150 [] dev_queue_xmit+0x2c2/0xca0 Cc: stable@vger.kernel.org Reported-by: Yaara Rozenblum Signed-off-by: Emmanuel Grumbach Reviewed-by: Stanislaw Gruszka [reword commit log, use a separate lock] Signed-off-by: Johannes Berg diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index decd30c..62a5f08 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -330,6 +330,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); spin_lock_init(&sta->lock); + spin_lock_init(&sta->ps_lock); INIT_WORK(&sta->drv_unblock_wk, sta_unblock); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); @@ -1109,6 +1110,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) skb_queue_head_init(&pending); + /* sync with ieee80211_tx_h_unicast_ps_buf */ + spin_lock(&sta->ps_lock); /* Send all buffered frames to the station */ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int count = skb_queue_len(&pending), tmp; @@ -1128,6 +1131,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) } ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); + spin_unlock(&sta->ps_lock); /* This station just woke up and isn't aware of our SMPS state */ if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d77ff70..d3a6d82 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat { * @drv_unblock_wk: used for driver PS unblocking * @listen_interval: listen interval of this station, when we're acting as AP * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly + * @ps_lock: used for powersave (when mac80211 is the AP) related locking * @ps_tx_buf: buffers (per AC) of frames to transmit to this station * when it leaves power saving state or polls * @tx_filtered: buffers (per AC) of frames we already tried to @@ -356,10 +357,8 @@ struct sta_info { /* use the accessors defined below */ unsigned long _flags; - /* - * STA powersave frame queues, no more than the internal - * locking required. - */ + /* STA powersave lock and frame queues */ + spinlock_t ps_lock; struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; unsigned long driver_buffered_tids; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 97a02d3..4080c61 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -478,6 +478,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) sta->sta.addr, sta->sta.aid, ac); if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) purge_old_ps_buffers(tx->local); + + /* sync with ieee80211_sta_ps_deliver_wakeup */ + spin_lock(&sta->ps_lock); + /* + * STA woke up the meantime and all the frames on ps_tx_buf have + * been queued to pending queue. No reordering can happen, go + * ahead and Tx the packet. + */ + if (!test_sta_flag(sta, WLAN_STA_PS_STA) && + !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { + spin_unlock(&sta->ps_lock); + return TX_CONTINUE; + } + if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); ps_dbg(tx->sdata, @@ -492,6 +506,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); + spin_unlock(&sta->ps_lock); if (!timer_pending(&local->sta_cleanup)) mod_timer(&local->sta_cleanup, -- cgit v0.10.2 From 5108ca828017120981880eeec8a9ec369334a899 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 17 Feb 2014 20:49:03 +0100 Subject: mac80211: insert stations before adding to driver There's a race condition in mac80211 because we add stations to the internal lists after adding them to the driver, which means that (for example) the following can happen: 1. a station connects and is added 2. first, it is added to the driver 3. then, it is added to the mac80211 lists If the station goes to sleep between steps 2 and 3, and the firmware/hardware records it as being asleep, mac80211 will never instruct the driver to wake it up again as it never realized it went to sleep since the RX path discarded the frame as a "spurious class 3 frame", no station entry was present yet. Fix this by adding the station in software first, and only then adding it to the driver. That way, any state that the driver changes will be reflected properly in mac80211's station state. The problematic part is the roll-back if the driver fails to add the station, in that case a bit more is needed. To not make that overly complex prevent starting BA sessions in the meantime. Signed-off-by: Johannes Berg diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 62a5f08..ffc1ee6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, return -ENOENT; } -static void cleanup_single_sta(struct sta_info *sta) +static void __cleanup_single_sta(struct sta_info *sta) { int ac, i; struct tid_ampdu_tx *tid_tx; @@ -139,7 +139,14 @@ static void cleanup_single_sta(struct sta_info *sta) ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); kfree(tid_tx); } +} +static void cleanup_single_sta(struct sta_info *sta) +{ + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; + + __cleanup_single_sta(sta); sta_info_free(local, sta); } @@ -488,21 +495,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) goto out_err; } - /* notify driver */ - err = sta_info_insert_drv_state(local, sdata, sta); - if (err) - goto out_err; - local->num_sta++; local->sta_generation++; smp_mb(); + /* simplify things and don't accept BA sessions yet */ + set_sta_flag(sta, WLAN_STA_BLOCK_BA); + /* make the station visible */ sta_info_hash_add(local, sta); list_add_rcu(&sta->list, &local->sta_list); + /* notify driver */ + err = sta_info_insert_drv_state(local, sdata, sta); + if (err) + goto out_remove; + set_sta_flag(sta, WLAN_STA_INSERTED); + /* accept BA sessions now */ + clear_sta_flag(sta, WLAN_STA_BLOCK_BA); ieee80211_recalc_min_chandef(sdata); ieee80211_sta_debugfs_add(sta); @@ -523,6 +535,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) mesh_accept_plinks_update(sdata); return 0; + out_remove: + sta_info_hash_del(local, sta); + list_del_rcu(&sta->list); + local->num_sta--; + synchronize_net(); + __cleanup_single_sta(sta); out_err: mutex_unlock(&local->sta_mtx); rcu_read_lock(); -- cgit v0.10.2 From c4204960e9d0ba99459dbf1db918f99a45e7a62a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:12 +0000 Subject: Input - arizona-haptics: Fix double lock of dapm_mutex snd_soc_dapm_sync takes the dapm_mutex internally, but we currently take it externally as well. This patch fixes this. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c index 7a04f54..e7e12a5 100644 --- a/drivers/input/misc/arizona-haptics.c +++ b/drivers/input/misc/arizona-haptics.c @@ -77,16 +77,14 @@ static void arizona_haptics_work(struct work_struct *work) return; } + mutex_unlock(dapm_mutex); + ret = snd_soc_dapm_sync(arizona->dapm); if (ret != 0) { dev_err(arizona->dev, "Failed to sync DAPM: %d\n", ret); - mutex_unlock(dapm_mutex); return; } - - mutex_unlock(dapm_mutex); - } else { /* This disable sequence will be a noop if already enabled */ mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); @@ -99,16 +97,15 @@ static void arizona_haptics_work(struct work_struct *work) return; } + mutex_unlock(dapm_mutex); + ret = snd_soc_dapm_sync(arizona->dapm); if (ret != 0) { dev_err(arizona->dev, "Failed to sync DAPM: %d\n", ret); - mutex_unlock(dapm_mutex); return; } - mutex_unlock(dapm_mutex); - ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1, ARIZONA_HAP_CTRL_MASK, -- cgit v0.10.2 From 113911006442a36c2b4669faf1699d9042ef80ab Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:14 +0000 Subject: ASoC: dapm: Add locking to snd_soc_dapm_xxxx_pin functions The snd_soc_dapm_xxxx_pin all require the dapm_mutex to be held when they are called as they edit the dirty list, however very few of the callers do so. This patch adds unlocked versions of all the functions replacing the existing implementations with one that holds the lock internally. We also fix up the places where the lock was actually held on the caller side. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index c20602f..98a14f6 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -222,27 +222,19 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info) struct snd_soc_dapm_context *dapm = arizona->dapm; int ret; - mutex_lock(&dapm->card->dapm_mutex); - ret = snd_soc_dapm_force_enable_pin(dapm, widget); if (ret != 0) dev_warn(arizona->dev, "Failed to enable %s: %d\n", widget, ret); - mutex_unlock(&dapm->card->dapm_mutex); - snd_soc_dapm_sync(dapm); if (!arizona->pdata.micd_force_micbias) { - mutex_lock(&dapm->card->dapm_mutex); - ret = snd_soc_dapm_disable_pin(arizona->dapm, widget); if (ret != 0) dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret); - mutex_unlock(&dapm->card->dapm_mutex); - snd_soc_dapm_sync(dapm); } } @@ -304,16 +296,12 @@ static void arizona_stop_mic(struct arizona_extcon_info *info) ARIZONA_MICD_ENA, 0, &change); - mutex_lock(&dapm->card->dapm_mutex); - ret = snd_soc_dapm_disable_pin(dapm, widget); if (ret != 0) dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret); - mutex_unlock(&dapm->card->dapm_mutex); - snd_soc_dapm_sync(dapm); if (info->micd_reva) { diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c index e7e12a5..ef2e281 100644 --- a/drivers/input/misc/arizona-haptics.c +++ b/drivers/input/misc/arizona-haptics.c @@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *work) struct arizona_haptics, work); struct arizona *arizona = haptics->arizona; - struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex; int ret; if (!haptics->arizona->dapm) { @@ -67,18 +66,13 @@ static void arizona_haptics_work(struct work_struct *work) return; } - mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS"); if (ret != 0) { dev_err(arizona->dev, "Failed to start HAPTICS: %d\n", ret); - mutex_unlock(dapm_mutex); return; } - mutex_unlock(dapm_mutex); - ret = snd_soc_dapm_sync(arizona->dapm); if (ret != 0) { dev_err(arizona->dev, "Failed to sync DAPM: %d\n", @@ -87,18 +81,13 @@ static void arizona_haptics_work(struct work_struct *work) } } else { /* This disable sequence will be a noop if already enabled */ - mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS"); if (ret != 0) { dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n", ret); - mutex_unlock(dapm_mutex); return; } - mutex_unlock(dapm_mutex); - ret = snd_soc_dapm_sync(arizona->dapm); if (ret != 0) { dev_err(arizona->dev, "Failed to sync DAPM: %d\n", @@ -152,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data, static void arizona_haptics_close(struct input_dev *input) { struct arizona_haptics *haptics = input_get_drvdata(input); - struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex; cancel_work_sync(&haptics->work); - mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - if (haptics->arizona->dapm) snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); - - mutex_unlock(dapm_mutex); } static int arizona_haptics_probe(struct platform_device *pdev) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 68d92e3..6e89ef6 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -449,14 +449,22 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, /* dapm audio pin control and status */ int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin); int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin); int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin); int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin); int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin); void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index fd39cd2..b9dc6ac 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3210,15 +3210,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); const char *pin = (const char *)kcontrol->private_value; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - if (ucontrol->value.integer.value[0]) snd_soc_dapm_enable_pin(&card->dapm, pin); else snd_soc_dapm_disable_pin(&card->dapm, pin); - mutex_unlock(&card->dapm_mutex); - snd_soc_dapm_sync(&card->dapm); return 0; } @@ -3767,23 +3763,52 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, } /** + * snd_soc_dapm_enable_pin_unlocked - enable pin. + * @dapm: DAPM context + * @pin: pin name + * + * Enables input/output pin and its parents or children widgets iff there is + * a valid audio route and active audio stream. + * + * Requires external locking. + * + * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to + * do any widget power switching. + */ +int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin) +{ + return snd_soc_dapm_set_pin(dapm, pin, 1); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked); + +/** * snd_soc_dapm_enable_pin - enable pin. * @dapm: DAPM context * @pin: pin name * * Enables input/output pin and its parents or children widgets iff there is * a valid audio route and active audio stream. + * * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) { - return snd_soc_dapm_set_pin(dapm, pin, 1); + int ret; + + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + + ret = snd_soc_dapm_set_pin(dapm, pin, 1); + + mutex_unlock(&dapm->card->dapm_mutex); + + return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); /** - * snd_soc_dapm_force_enable_pin - force a pin to be enabled + * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled * @dapm: DAPM context * @pin: pin name * @@ -3791,11 +3816,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); * intended for use with microphone bias supplies used in microphone * jack detection. * + * Requires external locking. + * * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ -int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, - const char *pin) +int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin) { struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); @@ -3811,25 +3838,103 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, return 0; } +EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked); + +/** + * snd_soc_dapm_force_enable_pin - force a pin to be enabled + * @dapm: DAPM context + * @pin: pin name + * + * Enables input/output pin regardless of any other state. This is + * intended for use with microphone bias supplies used in microphone + * jack detection. + * + * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to + * do any widget power switching. + */ +int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, + const char *pin) +{ + int ret; + + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + + ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); + + mutex_unlock(&dapm->card->dapm_mutex); + + return ret; +} EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); /** + * snd_soc_dapm_disable_pin_unlocked - disable pin. + * @dapm: DAPM context + * @pin: pin name + * + * Disables input/output pin and its parents or children widgets. + * + * Requires external locking. + * + * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to + * do any widget power switching. + */ +int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin) +{ + return snd_soc_dapm_set_pin(dapm, pin, 0); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked); + +/** * snd_soc_dapm_disable_pin - disable pin. * @dapm: DAPM context * @pin: pin name * * Disables input/output pin and its parents or children widgets. + * * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, const char *pin) { - return snd_soc_dapm_set_pin(dapm, pin, 0); + int ret; + + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + + ret = snd_soc_dapm_set_pin(dapm, pin, 0); + + mutex_unlock(&dapm->card->dapm_mutex); + + return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); /** + * snd_soc_dapm_nc_pin_unlocked - permanently disable pin. + * @dapm: DAPM context + * @pin: pin name + * + * Marks the specified pin as being not connected, disabling it along + * any parent or child widgets. At present this is identical to + * snd_soc_dapm_disable_pin() but in future it will be extended to do + * additional things such as disabling controls which only affect + * paths through the pin. + * + * Requires external locking. + * + * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to + * do any widget power switching. + */ +int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm, + const char *pin) +{ + return snd_soc_dapm_set_pin(dapm, pin, 0); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked); + +/** * snd_soc_dapm_nc_pin - permanently disable pin. * @dapm: DAPM context * @pin: pin name @@ -3845,7 +3950,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); */ int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) { - return snd_soc_dapm_set_pin(dapm, pin, 0); + int ret; + + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + + ret = snd_soc_dapm_set_pin(dapm, pin, 0); + + mutex_unlock(&dapm->card->dapm_mutex); + + return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); -- cgit v0.10.2 From f6d5e586b416746664c01ab5d4b19ed5e2d1cbaa Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:13 +0000 Subject: ASoC: dapm: Add helpers to lock/unlock DAPM mutex Acquiring the DAPM mutex is necessary before using several DAPM functions and dereference is quite ugly. This patch provides a helper function to simplify this. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a00147..1e12b66 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1188,4 +1188,15 @@ extern struct dentry *snd_soc_debugfs_root; extern const struct dev_pm_ops snd_soc_pm_ops; +/* Helper functions */ +static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) +{ + mutex_lock(&dapm->card->dapm_mutex); +} + +static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) +{ + mutex_unlock(&dapm->card->dapm_mutex); +} + #endif -- cgit v0.10.2 From 3eb29dfb3d3bd4b600370007b96c3c675fb97aa7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:15 +0000 Subject: ASoC: dapm: Add unlocked version of snd_soc_dapm_sync We will often call sync after several functions that require the DAPM mutex to be held. Rather than release and immediately relock the mutex provide an unlocked function for this situation. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 6e89ef6..3b99176 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -461,6 +461,7 @@ int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); +int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 48a4eeb..4200f96 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2342,18 +2342,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, } /** - * snd_soc_dapm_sync - scan and power dapm paths + * snd_soc_dapm_sync_unlocked - scan and power dapm paths * @dapm: DAPM context * * Walks all dapm audio paths and powers widgets according to their * stream or path usage. * + * Requires external locking. + * * Returns 0 for success. */ -int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) +int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm) { - int ret; - /* * Suppress early reports (eg, jacks syncing their state) to avoid * silly DAPM runs during card startup. @@ -2361,8 +2361,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) if (!dapm->card || !dapm->card->instantiated) return 0; + return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked); + +/** + * snd_soc_dapm_sync - scan and power dapm paths + * @dapm: DAPM context + * + * Walks all dapm audio paths and powers widgets according to their + * stream or path usage. + * + * Returns 0 for success. + */ +int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) +{ + int ret; + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); + ret = snd_soc_dapm_sync_unlocked(dapm); mutex_unlock(&dapm->card->dapm_mutex); return ret; } -- cgit v0.10.2 From 1bf1b8cf4faf279c3643c5c8045bec53b047ca9a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:16 +0000 Subject: ASoC: adav80x: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a..ab790d5 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -541,6 +541,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, unsigned int freq, int dir) { struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (dir == SND_SOC_CLOCK_IN) { switch (clk_id) { @@ -573,7 +574,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, iclk_ctrl2); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync(dapm); } } else { unsigned int mask; @@ -600,17 +601,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, adav80x->sysclk_pd[clk_id] = false; } + snd_soc_dapm_mutex_lock(dapm); + if (adav80x->sysclk_pd[0]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1"); else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1"); if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2"); else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2"); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } return 0; -- cgit v0.10.2 From e951f267fd042ce6ca66449dd6d537b6126a10d7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:17 +0000 Subject: ASoC: wm5100: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4e3e31a..492fe84 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2100,6 +2100,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100) int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) { struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (jack) { wm5100->jack = jack; @@ -2117,9 +2118,14 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) WM5100_ACCDET_RATE_MASK); /* We need the charge pump to power MICBIAS */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "CP2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); /* We start off just enabling microphone detection - even a * plain headphone will trigger detection. -- cgit v0.10.2 From f1a3b8d9d4818b88cd7de369da3bb1804c2ad7da Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:18 +0000 Subject: ASoC: wm8962: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b4..9e62336 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3089,6 +3089,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) { struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; int irq_mask, enable; wm8962->jack = jack; @@ -3109,14 +3110,18 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) snd_soc_jack_report(wm8962->jack, 0, SND_JACK_MICROPHONE | SND_JACK_BTN_0); + snd_soc_dapm_mutex_lock(dapm); + if (jack) { - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS"); } else { - snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); + snd_soc_dapm_disable_pin_unlocked(dapm, "SYSCLK"); + snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS"); } + snd_soc_dapm_mutex_unlock(dapm); + return 0; } EXPORT_SYMBOL_GPL(wm8962_mic_detect); -- cgit v0.10.2 From babce8211b194acdc41bc47975b50969a48b84ab Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:19 +0000 Subject: ASoC: wm8994: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b9be9cb..e8daf55 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2549,43 +2549,52 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; switch (mode) { case WM8994_VMID_NORMAL: + snd_soc_dapm_mutex_lock(dapm); + if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1P Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT1N Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT1P Driver"); } if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2P Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT2N Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT2P Driver"); } /* Do the sync with the old mode to allow it to clean up */ - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); wm8994->vmid_mode = mode; + + snd_soc_dapm_mutex_unlock(dapm); break; case WM8994_VMID_FORCE: + snd_soc_dapm_mutex_lock(dapm); + if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1P Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT1N Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT1P Driver"); } if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2P Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT2N Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT2P Driver"); } wm8994->vmid_mode = mode; - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); break; default: -- cgit v0.10.2 From 02afc6a23863367f59a3c792567cf1c9bb9d626c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:20 +0000 Subject: ASoC: wm8996: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b..d565d0a 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2251,6 +2251,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, wm8996_polarity_fn polarity_cb) { struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; wm8996->jack = jack; wm8996->detecting = true; @@ -2267,8 +2268,12 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, WM8996_MICB2_DISCH, 0); /* LDO2 powers the microphones, SYSCLK clocks detection */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + + snd_soc_dapm_mutex_unlock(dapm); /* We start off just enabling microphone detection - even a * plain headphone will trigger detection. -- cgit v0.10.2 From 121df681da21cebd8915c8ad62b33b7c90d4b395 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:21 +0000 Subject: ASoC: mfld_machine: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/mfld_machine.c index d3d4c32..0cef32e 100644 --- a/sound/soc/intel/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c @@ -101,20 +101,27 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (ucontrol->value.integer.value[0] == hs_switch) return 0; + snd_soc_dapm_mutex_lock(dapm); + if (ucontrol->value.integer.value[0]) { pr_debug("hs_set HS path\n"); - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); } else { pr_debug("hs_set EP path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); } - snd_soc_dapm_sync(&codec->dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); + hs_switch = ucontrol->value.integer.value[0]; return 0; @@ -122,18 +129,20 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol, static void lo_enable_out_pins(struct snd_soc_codec *codec) { - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); + struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTL"); + snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTR"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTL"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTR"); + snd_soc_dapm_enable_pin_unlocked(dapm, "VIB1OUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "VIB2OUT"); if (hs_switch) { - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); } else { - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); } } @@ -148,44 +157,52 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (ucontrol->value.integer.value[0] == lo_dac) return 0; + snd_soc_dapm_mutex_lock(dapm); + /* we dont want to work with last state of lineout so just enable all * pins and then disable pins not required */ lo_enable_out_pins(codec); + switch (ucontrol->value.integer.value[0]) { case 0: pr_debug("set vibra path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "VIB2OUT"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); break; case 1: pr_debug("set hs path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); break; case 2: pr_debug("set spkr path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); + snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTL"); + snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTR"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); break; case 3: pr_debug("set null path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTL"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTR"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); break; } - snd_soc_dapm_sync(&codec->dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); + lo_dac = ucontrol->value.integer.value[0]; return 0; } -- cgit v0.10.2 From 03510ca07ad48941072d673321d2b009be6dfcd4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:22 +0000 Subject: ASoC: ams-delta: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. It looks like these were originally locked with the CODEC mutex and not updated since the patch "ASoC: dapm: Use DAPM mutex for DAPM ops instead of codec mutex", so remove the original CODEC mutex locking as well. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 6294464..5750de1 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -106,57 +106,59 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0] >= control->max) return -EINVAL; - mutex_lock(&codec->mutex); + snd_soc_dapm_mutex_lock(dapm); /* Translate selection to bitmap */ pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; /* Setup pins after corresponding bits if changed */ pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); + if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mouthpiece"); else - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); } pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); else - snd_soc_dapm_disable_pin(dapm, "Earpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Earpiece"); } pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Microphone"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); else - snd_soc_dapm_disable_pin(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Microphone"); } pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); } pin = !!(pins & (1 << AMS_DELTA_AGC)); if (pin != ams_delta_audio_agc) { ams_delta_audio_agc = pin; changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "AGCIN"); + snd_soc_dapm_enable_pin_unlocked(dapm, "AGCIN"); else - snd_soc_dapm_disable_pin(dapm, "AGCIN"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); } + if (changed) - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); - mutex_unlock(&codec->mutex); + snd_soc_dapm_mutex_unlock(dapm); return changed; } @@ -315,12 +317,17 @@ static void cx81801_close(struct tty_struct *tty) v253_ops.close(tty); /* Revert back to default audio input/output constellation */ - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - snd_soc_dapm_enable_pin(dapm, "Microphone"); - snd_soc_dapm_disable_pin(dapm, "Speaker"); - snd_soc_dapm_disable_pin(dapm, "AGCIN"); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(codec); } /* Line discipline .hangup() */ -- cgit v0.10.2 From 43cbbc398f027483e129c3ed4634769ca60ed264 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:23 +0000 Subject: ASoC: omap: n810: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 3fde9e4..480a39c 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -68,26 +68,30 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (n810_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (line1l) - snd_soc_dapm_enable_pin(dapm, "LINE1L"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINE1L"); else - snd_soc_dapm_disable_pin(dapm, "LINE1L"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINE1L"); if (n810_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); + + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int n810_startup(struct snd_pcm_substream *substream) -- cgit v0.10.2 From 9dd2bb3fdb38c47ce3f1be624c9e6dcba3d61898 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:24 +0000 Subject: ASoC: omap: rx51: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 611179c..7fb3d4b 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -74,26 +74,30 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (rx51_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (rx51_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (hs) - snd_soc_dapm_enable_pin(dapm, "HS Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic"); else - snd_soc_dapm_disable_pin(dapm, "HS Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic"); gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int rx51_startup(struct snd_pcm_substream *substream) -- cgit v0.10.2 From 4d9e73488d4e97b6019d178e53f8ec0a94c4e926 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:25 +0000 Subject: ASoC: pxa: corgi: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1853d41..9d9c8ad 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -47,51 +47,55 @@ static int corgi_spk_func; static void corgi_ext_control(struct snd_soc_dapm_context *dapm) { + snd_soc_dapm_mutex_lock(dapm); + /* set up jack connection */ switch (corgi_jack_func) { case CORGI_HP: /* set = unmute headphone */ gpio_set_value(CORGI_GPIO_MUTE_L, 1); gpio_set_value(CORGI_GPIO_MUTE_R, 1); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_MIC: /* reset = mute headphone */ gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_LINE: gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_HEADSET: gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 1); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); break; } if (corgi_spk_func == CORGI_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); /* signal a DAPM event */ - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int corgi_startup(struct snd_pcm_substream *substream) -- cgit v0.10.2 From f71b0fbe52f816649ab39ff329b7e4091276208a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:26 +0000 Subject: ASoC: pxa: magician: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index aace19e..31242be 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -45,27 +45,31 @@ static void magician_ext_control(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; + snd_soc_dapm_mutex_lock(dapm); + if (magician_spk_switch) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); if (magician_hp_switch) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); switch (magician_in_sel) { case MAGICIAN_MIC: - snd_soc_dapm_disable_pin(dapm, "Headset Mic"); - snd_soc_dapm_enable_pin(dapm, "Call Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Call Mic"); break; case MAGICIAN_MIC_EXT: - snd_soc_dapm_disable_pin(dapm, "Call Mic"); - snd_soc_dapm_enable_pin(dapm, "Headset Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Call Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Mic"); break; } - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int magician_startup(struct snd_pcm_substream *substream) -- cgit v0.10.2 From 1845a7255a308da0c32714a2d57d79225037ed5b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:27 +0000 Subject: ASoC: pxa: spitz: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index fc052d8..04dbb5a 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -46,61 +46,66 @@ static int spitz_mic_gpio; static void spitz_ext_control(struct snd_soc_dapm_context *dapm) { + snd_soc_dapm_mutex_lock(dapm); + if (spitz_spk_func == SPITZ_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); /* set up jack connection */ switch (spitz_jack_func) { case SPITZ_HP: /* enable and unmute hp jack, disable mic bias */ - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 1); gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_MIC: /* enable mic jack and bias, mute hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_LINE: /* enable line jack, disable mic bias and mute hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_HEADSET: /* enable and unmute headset jack enable mic bias, mute L hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_HP_OFF: /* jack removed, everything off */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; } - snd_soc_dapm_sync(dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int spitz_startup(struct snd_pcm_substream *substream) -- cgit v0.10.2 From 26e24ddce755cd6fb4b05a87ae37f7e10faa0c4b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:28 +0000 Subject: ASoC: pxa: tosa: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 1d9c2ed..2a4b438 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -48,31 +48,35 @@ static void tosa_ext_control(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; + snd_soc_dapm_mutex_lock(dapm); + /* set up jack connection */ switch (tosa_jack_func) { case TOSA_HP: - snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case TOSA_MIC_INT: - snd_soc_dapm_enable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case TOSA_HEADSET: - snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); break; } if (tosa_spk_func == TOSA_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); + + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int tosa_startup(struct snd_pcm_substream *substream) -- cgit v0.10.2 From e3685e03b40f5ec7926d9a75bf63467fc4071df9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 20 Feb 2014 11:19:58 +0100 Subject: mac80211: fix station wakeup powersave race Consider the following (relatively unlikely) scenario: 1) station goes to sleep while frames are buffered in driver 2) driver blocks wakeup (until no more frames are buffered) 3) station wakes up again 4) driver unblocks wakeup In this case, the current mac80211 code will do the following: 1) WLAN_STA_PS_STA set 2) WLAN_STA_PS_DRIVER set 3) - nothing - 4) WLAN_STA_PS_DRIVER cleared As a result, no frames will be delivered to the client, even though it is awake, until it sends another frame to us that triggers ieee80211_sta_ps_deliver_wakeup() in sta_ps_end(). Since we now take the PS spinlock, we can fix this while at the same time removing the complexity with the pending skb queue function. This was broken since my commit 50a9432daeec ("mac80211: fix powersaving clients races") due to removing the clearing of WLAN_STA_PS_STA in the RX path. While at it, fix a cleanup path issue when a station is removed while the driver is still blocking its wakeup. Signed-off-by: Johannes Berg diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3701930..5e44e317 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1692,14 +1692,8 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); void ieee80211_add_pending_skb(struct ieee80211_local *local, struct sk_buff *skb); -void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, - struct sk_buff_head *skbs, - void (*fn)(void *data), void *data); -static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, - struct sk_buff_head *skbs) -{ - ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); -} +void ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs); void ieee80211_flush_queues(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c24ca0d..3e57f96 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *sta) sta->sta.addr, sta->sta.aid); if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { + /* + * Clear the flag only if the other one is still set + * so that the TX path won't start TX'ing new frames + * directly ... In the case that the driver flag isn't + * set ieee80211_sta_ps_deliver_wakeup() will clear it. + */ + clear_sta_flag(sta, WLAN_STA_PS_STA); ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", sta->sta.addr, sta->sta.aid); return; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ffc1ee6..a023b43 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -99,7 +99,8 @@ static void __cleanup_single_sta(struct sta_info *sta) struct ieee80211_local *local = sdata->local; struct ps_data *ps; - if (test_sta_flag(sta, WLAN_STA_PS_STA)) { + if (test_sta_flag(sta, WLAN_STA_PS_STA) || + test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { if (sta->sdata->vif.type == NL80211_IFTYPE_AP || sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ps = &sdata->bss->ps; @@ -109,6 +110,7 @@ static void __cleanup_single_sta(struct sta_info *sta) return; clear_sta_flag(sta, WLAN_STA_PS_STA); + clear_sta_flag(sta, WLAN_STA_PS_DRIVER); atomic_dec(&ps->num_sta_ps); sta_info_recalc_tim(sta); @@ -1090,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, } EXPORT_SYMBOL(ieee80211_find_sta); -static void clear_sta_ps_flags(void *_sta) +/* powersave support code */ +void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) { - struct sta_info *sta = _sta; struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; + struct sk_buff_head pending; + int filtered = 0, buffered = 0, ac; + unsigned long flags; struct ps_data *ps; if (sdata->vif.type == NL80211_IFTYPE_AP || @@ -1104,20 +1110,6 @@ static void clear_sta_ps_flags(void *_sta) else return; - clear_sta_flag(sta, WLAN_STA_PS_DRIVER); - if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA)) - atomic_dec(&ps->num_sta_ps); -} - -/* powersave support code */ -void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - struct sk_buff_head pending; - int filtered = 0, buffered = 0, ac; - unsigned long flags; - clear_sta_flag(sta, WLAN_STA_SP); BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); @@ -1148,9 +1140,13 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) buffered += tmp - count; } - ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); + ieee80211_add_pending_skbs(local, &pending); + clear_sta_flag(sta, WLAN_STA_PS_DRIVER); + clear_sta_flag(sta, WLAN_STA_PS_STA); spin_unlock(&sta->ps_lock); + atomic_dec(&ps->num_sta_ps); + /* This station just woke up and isn't aware of our SMPS state */ if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, sdata->smps_mode) && diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1d1bb70..b8700d4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); } -void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, - struct sk_buff_head *skbs, - void (*fn)(void *data), void *data) +void ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs) { struct ieee80211_hw *hw = &local->hw; struct sk_buff *skb; @@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, __skb_queue_tail(&local->pending[queue], skb); } - if (fn) - fn(data); - for (i = 0; i < hw->queues; i++) __ieee80211_wake_queue(hw, i, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); -- cgit v0.10.2 From 215a14cface21ba205f6edc813be157fdf7899b8 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Wed, 19 Feb 2014 16:15:45 +0800 Subject: of: reimplement the matching method for __of_match_node() In the current implementation of __of_match_node(), it will compare each given match entry against all the node's compatible strings with of_device_is_compatible(). To achieve multiple compatible strings per node with ordering from specific to generic, this requires given matches to be ordered from specific to generic. For most of the drivers this is not true and also an alphabetical ordering is more sane there. Therefore, we define a following priority order for the match, and then scan all the entries to find the best match. 1. specific compatible && type && name 2. specific compatible && type 3. specific compatible && name 4. specific compatible 5. general compatible && type && name 6. general compatible && type 7. general compatible && name 8. general compatible 9. type && name 10. type 11. name v5: Fix nested locking bug v4: Short-circuit failure cases instead of mucking with score, and remove extra __of_device_is_compatible() wrapper stub. Move scoring logic directly into __of_device_is_compatible() v3: Also need to bail out when there does have a compatible member in match entry, but it doesn't match with the device node's compatible. v2: Fix the bug such as we get the same score for the following two match entries with the empty node 'name2 { };' struct of_device_id matches[] = { {.name = "name2", }, {.name = "name2", .type = "type1", }, {} }; Signed-off-by: Kevin Hao [grant.likely: added v4 changes] Signed-off-by: Grant Likely Tested-by: Paul Gortmaker Tested-by: Stephen Chivers Tested-by: Sachin Kamat diff --git a/drivers/of/base.c b/drivers/of/base.c index ba195fb..89e888a 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -342,27 +342,72 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) } EXPORT_SYMBOL(of_get_cpu_node); -/** Checks if the given "compat" string matches one of the strings in - * the device's "compatible" property +/** + * __of_device_is_compatible() - Check if the node matches given constraints + * @device: pointer to node + * @compat: required compatible string, NULL or "" for any match + * @type: required device_type value, NULL or "" for any match + * @name: required node name, NULL or "" for any match + * + * Checks if the given @compat, @type and @name strings match the + * properties of the given @device. A constraints can be skipped by + * passing NULL or an empty string as the constraint. + * + * Returns 0 for no match, and a positive integer on match. The return + * value is a relative score with larger values indicating better + * matches. The score is weighted for the most specific compatible value + * to get the highest score. Matching type is next, followed by matching + * name. Practically speaking, this results in the following priority + * order for matches: + * + * 1. specific compatible && type && name + * 2. specific compatible && type + * 3. specific compatible && name + * 4. specific compatible + * 5. general compatible && type && name + * 6. general compatible && type + * 7. general compatible && name + * 8. general compatible + * 9. type && name + * 10. type + * 11. name */ static int __of_device_is_compatible(const struct device_node *device, - const char *compat) -{ - const char* cp; - int cplen, l; + const char *compat, const char *type, const char *name) +{ + struct property *prop; + const char *cp; + int index = 0, score = 0; + + /* Compatible match has highest priority */ + if (compat && compat[0]) { + prop = __of_find_property(device, "compatible", NULL); + for (cp = of_prop_next_string(prop, NULL); cp; + cp = of_prop_next_string(prop, cp), index++) { + if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { + score = INT_MAX/2 - (index << 2); + break; + } + } + if (!score) + return 0; + } - cp = __of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (of_compat_cmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; + /* Matching type is better than matching name */ + if (type && type[0]) { + if (!device->type || of_node_cmp(type, device->type)) + return 0; + score += 2; } - return 0; + /* Matching name is a bit better than not */ + if (name && name[0]) { + if (!device->name || of_node_cmp(name, device->name)) + return 0; + score++; + } + + return score; } /** Checks if the given "compat" string matches one of the strings in @@ -375,7 +420,7 @@ int of_device_is_compatible(const struct device_node *device, int res; raw_spin_lock_irqsave(&devtree_lock, flags); - res = __of_device_is_compatible(device, compat); + res = __of_device_is_compatible(device, compat, NULL, NULL); raw_spin_unlock_irqrestore(&devtree_lock, flags); return res; } @@ -681,10 +726,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { - if (type - && !(np->type && (of_node_cmp(np->type, type) == 0))) - continue; - if (__of_device_is_compatible(np, compatible) && + if (__of_device_is_compatible(np, compatible, type, NULL) && of_node_get(np)) break; } @@ -734,25 +776,22 @@ static const struct of_device_id *__of_match_node(const struct of_device_id *matches, const struct device_node *node) { + const struct of_device_id *best_match = NULL; + int score, best_score = 0; + if (!matches) return NULL; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= node->name - && !strcmp(matches->name, node->name); - if (matches->type[0]) - match &= node->type - && !strcmp(matches->type, node->type); - if (matches->compatible[0]) - match &= __of_device_is_compatible(node, - matches->compatible); - if (match) - return matches; - matches++; + for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { + score = __of_device_is_compatible(node, matches->compatible, + matches->type, matches->name); + if (score > best_score) { + best_match = matches; + best_score = score; + } } - return NULL; + + return best_match; } /** -- cgit v0.10.2 From b5190516b282bee6f10569c3387d16f83447d280 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 18 Feb 2014 21:46:16 +0000 Subject: of: Move testcase FDT data into drivers/of The testcase data is usable by any platform. This patch moves it into the drivers/of directory so it can be included by any architecture. Using the test cases requires manually adding #include to the end of the boards .dtsi file and enabling CONFIG_OF_SELFTEST. Not pretty though. A useful project would be to make the testcase code easier to execute. Signed-off-by: Grant Likely diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi deleted file mode 100644 index c843720..0000000 --- a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi +++ /dev/null @@ -1,58 +0,0 @@ - -/ { - testcase-data { - interrupts { - #address-cells = <1>; - #size-cells = <1>; - test_intc0: intc0 { - interrupt-controller; - #interrupt-cells = <1>; - }; - - test_intc1: intc1 { - interrupt-controller; - #interrupt-cells = <3>; - }; - - test_intc2: intc2 { - interrupt-controller; - #interrupt-cells = <2>; - }; - - test_intmap0: intmap0 { - #interrupt-cells = <1>; - #address-cells = <0>; - interrupt-map = <1 &test_intc0 9>, - <2 &test_intc1 10 11 12>, - <3 &test_intc2 13 14>, - <4 &test_intc2 15 16>; - }; - - test_intmap1: intmap1 { - #interrupt-cells = <2>; - interrupt-map = <0x5000 1 2 &test_intc0 15>; - }; - - interrupts0 { - interrupt-parent = <&test_intc0>; - interrupts = <1>, <2>, <3>, <4>; - }; - - interrupts1 { - interrupt-parent = <&test_intmap0>; - interrupts = <1>, <2>, <3>, <4>; - }; - - interrupts-extended0 { - reg = <0x5000 0x100>; - interrupts-extended = <&test_intc0 1>, - <&test_intc1 2 3 4>, - <&test_intc2 5 6>, - <&test_intmap0 1>, - <&test_intmap0 2>, - <&test_intmap0 3>, - <&test_intmap1 1 2>; - }; - }; - }; -}; diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi deleted file mode 100644 index 0007d3c..0000000 --- a/arch/arm/boot/dts/testcases/tests-phandle.dtsi +++ /dev/null @@ -1,39 +0,0 @@ - -/ { - testcase-data { - phandle-tests { - provider0: provider0 { - #phandle-cells = <0>; - }; - - provider1: provider1 { - #phandle-cells = <1>; - }; - - provider2: provider2 { - #phandle-cells = <2>; - }; - - provider3: provider3 { - #phandle-cells = <3>; - }; - - consumer-a { - phandle-list = <&provider1 1>, - <&provider2 2 0>, - <0>, - <&provider3 4 4 3>, - <&provider2 5 100>, - <&provider0>, - <&provider1 7>; - phandle-list-names = "first", "second", "third"; - - phandle-list-bad-phandle = <12345678 0 0>; - phandle-list-bad-args = <&provider2 1 0>, - <&provider3 0>; - empty-property; - unterminated-string = [40 41 42 43]; - }; - }; - }; -}; diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi deleted file mode 100644 index 3f123ec..0000000 --- a/arch/arm/boot/dts/testcases/tests.dtsi +++ /dev/null @@ -1,2 +0,0 @@ -/include/ "tests-phandle.dtsi" -/include/ "tests-interrupts.dtsi" diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts index f43907c..65f6577 100644 --- a/arch/arm/boot/dts/versatile-pb.dts +++ b/arch/arm/boot/dts/versatile-pb.dts @@ -1,4 +1,4 @@ -/include/ "versatile-ab.dts" +#include / { model = "ARM Versatile PB"; @@ -47,4 +47,4 @@ }; }; -/include/ "testcases/tests.dtsi" +#include diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi new file mode 100644 index 0000000..3cc2f55 --- /dev/null +++ b/drivers/of/testcase-data/testcases.dtsi @@ -0,0 +1,2 @@ +#include "tests-phandle.dtsi" +#include "tests-interrupts.dtsi" diff --git a/drivers/of/testcase-data/tests-interrupts.dtsi b/drivers/of/testcase-data/tests-interrupts.dtsi new file mode 100644 index 0000000..c843720 --- /dev/null +++ b/drivers/of/testcase-data/tests-interrupts.dtsi @@ -0,0 +1,58 @@ + +/ { + testcase-data { + interrupts { + #address-cells = <1>; + #size-cells = <1>; + test_intc0: intc0 { + interrupt-controller; + #interrupt-cells = <1>; + }; + + test_intc1: intc1 { + interrupt-controller; + #interrupt-cells = <3>; + }; + + test_intc2: intc2 { + interrupt-controller; + #interrupt-cells = <2>; + }; + + test_intmap0: intmap0 { + #interrupt-cells = <1>; + #address-cells = <0>; + interrupt-map = <1 &test_intc0 9>, + <2 &test_intc1 10 11 12>, + <3 &test_intc2 13 14>, + <4 &test_intc2 15 16>; + }; + + test_intmap1: intmap1 { + #interrupt-cells = <2>; + interrupt-map = <0x5000 1 2 &test_intc0 15>; + }; + + interrupts0 { + interrupt-parent = <&test_intc0>; + interrupts = <1>, <2>, <3>, <4>; + }; + + interrupts1 { + interrupt-parent = <&test_intmap0>; + interrupts = <1>, <2>, <3>, <4>; + }; + + interrupts-extended0 { + reg = <0x5000 0x100>; + interrupts-extended = <&test_intc0 1>, + <&test_intc1 2 3 4>, + <&test_intc2 5 6>, + <&test_intmap0 1>, + <&test_intmap0 2>, + <&test_intmap0 3>, + <&test_intmap1 1 2>; + }; + }; + }; +}; diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi new file mode 100644 index 0000000..0007d3c --- /dev/null +++ b/drivers/of/testcase-data/tests-phandle.dtsi @@ -0,0 +1,39 @@ + +/ { + testcase-data { + phandle-tests { + provider0: provider0 { + #phandle-cells = <0>; + }; + + provider1: provider1 { + #phandle-cells = <1>; + }; + + provider2: provider2 { + #phandle-cells = <2>; + }; + + provider3: provider3 { + #phandle-cells = <3>; + }; + + consumer-a { + phandle-list = <&provider1 1>, + <&provider2 2 0>, + <0>, + <&provider3 4 4 3>, + <&provider2 5 100>, + <&provider0>, + <&provider1 7>; + phandle-list-names = "first", "second", "third"; + + phandle-list-bad-phandle = <12345678 0 0>; + phandle-list-bad-args = <&provider2 1 0>, + <&provider3 0>; + empty-property; + unterminated-string = [40 41 42 43]; + }; + }; + }; +}; diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 49392ec..79c059e 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -152,6 +152,7 @@ ld_flags = $(LDFLAGS) $(ldflags-y) dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \ -I$(srctree)/arch/$(SRCARCH)/boot/dts \ -I$(srctree)/arch/$(SRCARCH)/boot/dts/include \ + -I$(srctree)/drivers/of/testcase-data \ -undef -D__DTS__ # Finds the multi-part object the current object will be linked into -- cgit v0.10.2 From 1f42e5dd5065963979bb53daadf5d4f1e71f0c5f Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 18 Feb 2014 21:38:55 +0000 Subject: of: Add self test for of_match_node() Adds a selftest function for the of_match_node function. of_match_node is supposed to handle precedence for the compatible property as well as the name and device_type values. This patch adds some test case data and a function that makes sure each test node matches against the correct entry of an of_device_id table. This code was written to verify the new of_match_node() implementation that is an earlier part of this series. Signed-off-by: Grant Likely Cc: Kevin Hao diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index e21012b..6643d19 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -300,6 +300,72 @@ static void __init of_selftest_parse_interrupts_extended(void) of_node_put(np); } +static struct of_device_id match_node_table[] = { + { .data = "A", .name = "name0", }, /* Name alone is lowest priority */ + { .data = "B", .type = "type1", }, /* followed by type alone */ + + { .data = "Ca", .name = "name2", .type = "type1", }, /* followed by both together */ + { .data = "Cb", .name = "name2", }, /* Only match when type doesn't match */ + { .data = "Cc", .name = "name2", .type = "type2", }, + + { .data = "E", .compatible = "compat3" }, + { .data = "G", .compatible = "compat2", }, + { .data = "H", .compatible = "compat2", .name = "name5", }, + { .data = "I", .compatible = "compat2", .type = "type1", }, + { .data = "J", .compatible = "compat2", .type = "type1", .name = "name8", }, + { .data = "K", .compatible = "compat2", .name = "name9", }, + {} +}; + +static struct { + const char *path; + const char *data; +} match_node_tests[] = { + { .path = "/testcase-data/match-node/name0", .data = "A", }, + { .path = "/testcase-data/match-node/name1", .data = "B", }, + { .path = "/testcase-data/match-node/a/name2", .data = "Ca", }, + { .path = "/testcase-data/match-node/b/name2", .data = "Cb", }, + { .path = "/testcase-data/match-node/c/name2", .data = "Cc", }, + { .path = "/testcase-data/match-node/name3", .data = "E", }, + { .path = "/testcase-data/match-node/name4", .data = "G", }, + { .path = "/testcase-data/match-node/name5", .data = "H", }, + { .path = "/testcase-data/match-node/name6", .data = "G", }, + { .path = "/testcase-data/match-node/name7", .data = "I", }, + { .path = "/testcase-data/match-node/name8", .data = "J", }, + { .path = "/testcase-data/match-node/name9", .data = "K", }, +}; + +static void __init of_selftest_match_node(void) +{ + struct device_node *np; + const struct of_device_id *match; + int i; + + for (i = 0; i < ARRAY_SIZE(match_node_tests); i++) { + np = of_find_node_by_path(match_node_tests[i].path); + if (!np) { + selftest(0, "missing testcase node %s\n", + match_node_tests[i].path); + continue; + } + + match = of_match_node(match_node_table, np); + if (!match) { + selftest(0, "%s didn't match anything\n", + match_node_tests[i].path); + continue; + } + + if (strcmp(match->data, match_node_tests[i].data) != 0) { + selftest(0, "%s got wrong match. expected %s, got %s\n", + match_node_tests[i].path, match_node_tests[i].data, + (const char *)match->data); + continue; + } + selftest(1, "passed"); + } +} + static int __init of_selftest(void) { struct device_node *np; @@ -316,6 +382,7 @@ static int __init of_selftest(void) of_selftest_property_match_string(); of_selftest_parse_interrupts(); of_selftest_parse_interrupts_extended(); + of_selftest_match_node(); pr_info("end of selftest - %i passed, %i failed\n", selftest_results.passed, selftest_results.failed); return 0; diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi index 3cc2f55..3a5b75a 100644 --- a/drivers/of/testcase-data/testcases.dtsi +++ b/drivers/of/testcase-data/testcases.dtsi @@ -1,2 +1,3 @@ #include "tests-phandle.dtsi" #include "tests-interrupts.dtsi" +#include "tests-match.dtsi" diff --git a/drivers/of/testcase-data/tests-match.dtsi b/drivers/of/testcase-data/tests-match.dtsi new file mode 100644 index 0000000..c9e5411 --- /dev/null +++ b/drivers/of/testcase-data/tests-match.dtsi @@ -0,0 +1,19 @@ + +/ { + testcase-data { + match-node { + name0 { }; + name1 { device_type = "type1"; }; + a { name2 { device_type = "type1"; }; }; + b { name2 { }; }; + c { name2 { device_type = "type2"; }; }; + name3 { compatible = "compat3"; }; + name4 { compatible = "compat2", "compat3"; }; + name5 { compatible = "compat2", "compat3"; }; + name6 { compatible = "compat1", "compat2", "compat3"; }; + name7 { compatible = "compat2"; device_type = "type1"; }; + name8 { compatible = "compat2"; device_type = "type1"; }; + name9 { compatible = "compat2"; }; + }; + }; +}; -- cgit v0.10.2 From 972157cac528f6cfd1f7e640139287951066106e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 20 Feb 2014 12:19:08 +0100 Subject: arm/smmu: Use irqsafe spinlock for domain lock As the lock might be used through DMA-API which is allowed in interrupt context. Signed-off-by: Joerg Roedel Acked-by: Will Deacon diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 6fe7922..1d9ab39 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1159,6 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) struct arm_smmu_domain *smmu_domain = domain->priv; struct arm_smmu_device *device_smmu = dev->archdata.iommu; struct arm_smmu_master *master; + unsigned long flags; if (!device_smmu) { dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); @@ -1169,7 +1170,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) * Sanity check the domain. We don't currently support domains * that cross between different SMMU chains. */ - spin_lock(&smmu_domain->lock); + spin_lock_irqsave(&smmu_domain->lock, flags); if (!smmu_domain->leaf_smmu) { /* Now that we have a master, we can finalise the domain */ ret = arm_smmu_init_domain_context(domain, dev); @@ -1184,7 +1185,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_name(device_smmu->dev)); goto err_unlock; } - spin_unlock(&smmu_domain->lock); + spin_unlock_irqrestore(&smmu_domain->lock, flags); /* Looks ok, so add the device to the domain */ master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); @@ -1194,7 +1195,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return arm_smmu_domain_add_master(smmu_domain, master); err_unlock: - spin_unlock(&smmu_domain->lock); + spin_unlock_irqrestore(&smmu_domain->lock, flags); return ret; } @@ -1396,6 +1397,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; pgd_t *pgd = root_cfg->pgd; struct arm_smmu_device *smmu = root_cfg->smmu; + unsigned long irqflags; if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) { stage = 2; @@ -1418,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, if (paddr & ~output_mask) return -ERANGE; - spin_lock(&smmu_domain->lock); + spin_lock_irqsave(&smmu_domain->lock, irqflags); pgd += pgd_index(iova); end = iova + size; do { @@ -1434,7 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, } while (pgd++, iova != end); out_unlock: - spin_unlock(&smmu_domain->lock); + spin_unlock_irqrestore(&smmu_domain->lock, irqflags); return ret; } -- cgit v0.10.2 From 876fc03aaa4d8cc81331119d80d3e9bfbf1164e8 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 19 Feb 2014 13:33:23 +0100 Subject: ip6_vti: Fix build when NET_IP_TUNNEL is not set. Since commit 469bdcefdc47a ip6_vti uses ip_tunnel_get_stats64(), so we need to select NET_IP_TUNNEL to have this function available. Fixes: 469bdcefdc ("ipv6: fix the use of pcpu_tstats in ip6_vti.c") Signed-off-by: Steffen Klassert diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index d92e558..438a73a 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION config IPV6_VTI tristate "Virtual (secure) IPv6: tunneling" select IPV6_TUNNEL + select NET_IP_TUNNEL depends on INET6_XFRM_MODE_TUNNEL ---help--- Tunneling means encapsulating data of one protocol type within -- cgit v0.10.2 From 35ea790d7883dd660208f78eae50ebfd6b8bd14a Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 19 Feb 2014 13:33:23 +0100 Subject: xfrm: Fix NULL pointer dereference on sub policy usage xfrm_state_sort() takes the unsorted states from the src array and stores them into the dst array. We try to get the namespace from the dst array which is empty at this time, so take the namespace from the src array instead. Fixes: 283bc9f35bbbc ("xfrm: Namespacify xfrm state/policy locks") Signed-off-by: Steffen Klassert diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a26b7aa..97d117b 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1451,7 +1451,7 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, { int err = 0; struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); - struct net *net = xs_net(*dst); + struct net *net = xs_net(*src); if (!afinfo) return -EAFNOSUPPORT; -- cgit v0.10.2 From 8c0cba22e196122d26c92980943474eb53db8deb Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 19 Feb 2014 13:33:24 +0100 Subject: xfrm: Take xfrm_state_lock in xfrm_migrate_state_find A comment on xfrm_migrate_state_find() says that xfrm_state_lock is held. This is apparently not the case, but we need it to traverse through the state lists. Signed-off-by: Steffen Klassert diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 97d117b..c101023 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1215,11 +1215,12 @@ out: return NULL; } -/* net->xfrm.xfrm_state_lock is held */ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net) { unsigned int h; - struct xfrm_state *x; + struct xfrm_state *x = NULL; + + spin_lock_bh(&net->xfrm.xfrm_state_lock); if (m->reqid) { h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr, @@ -1236,7 +1237,7 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n m->old_family)) continue; xfrm_state_hold(x); - return x; + break; } } else { h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr, @@ -1251,11 +1252,13 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n m->old_family)) continue; xfrm_state_hold(x); - return x; + break; } } - return NULL; + spin_unlock_bh(&net->xfrm.xfrm_state_lock); + + return x; } EXPORT_SYMBOL(xfrm_migrate_state_find); -- cgit v0.10.2 From ee5c23176fcc820f7a56d3e86001532af0d59b1e Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 19 Feb 2014 13:33:24 +0100 Subject: xfrm: Clone states properly on migration We loose a lot of information of the original state if we clone it with xfrm_state_clone(). In particular, there is no crypto algorithm attached if the original state uses an aead algorithm. This patch add the missing information to the clone state. Signed-off-by: Steffen Klassert diff --git a/include/net/xfrm.h b/include/net/xfrm.h index afa5730..fb5654a 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1648,6 +1648,11 @@ static inline int xfrm_aevent_is_on(struct net *net) } #endif +static inline int aead_len(struct xfrm_algo_aead *alg) +{ + return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); +} + static inline int xfrm_alg_len(const struct xfrm_algo *alg) { return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); @@ -1686,6 +1691,12 @@ static inline int xfrm_replay_clone(struct xfrm_state *x, return 0; } +static inline struct xfrm_algo_aead *xfrm_algo_aead_clone(struct xfrm_algo_aead *orig) +{ + return kmemdup(orig, aead_len(orig), GFP_KERNEL); +} + + static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig) { return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index c101023..40f1b3e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1159,6 +1159,11 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) } x->props.aalgo = orig->props.aalgo; + if (orig->aead) { + x->aead = xfrm_algo_aead_clone(orig->aead); + if (!x->aead) + goto error; + } if (orig->ealg) { x->ealg = xfrm_algo_clone(orig->ealg); if (!x->ealg) @@ -1201,6 +1206,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) x->props.flags = orig->props.flags; x->props.extra_flags = orig->props.extra_flags; + x->tfcpad = orig->tfcpad; + x->replay_maxdiff = orig->replay_maxdiff; + x->replay_maxage = orig->replay_maxage; x->curlft.add_time = orig->curlft.add_time; x->km.state = orig->km.state; x->km.seq = orig->km.seq; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 1ae3ec7..c274179 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -32,11 +32,6 @@ #include #endif -static inline int aead_len(struct xfrm_algo_aead *alg) -{ - return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); -} - static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) { struct nlattr *rt = attrs[type]; -- cgit v0.10.2 From 8679059e360543b7afecd228ada6566da9f304a4 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 3 Jan 2014 16:45:13 +0800 Subject: usb: gadget: printer: using gadget_is_otg to check otg support at runtime We need to use gadget_is_otg to check if the gadget is really otg support at runtime, other composite gadget drivers have already followed this method. Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index bf7a56b..69b76ef 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1157,7 +1157,7 @@ static int __init printer_bind_config(struct usb_configuration *c) usb_gadget_set_selfpowered(gadget); - if (gadget->is_otg) { + if (gadget_is_otg(gadget)) { otg_descriptor.bmAttributes |= USB_OTG_HNP; printer_cfg_driver.descriptors = otg_desc; printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; -- cgit v0.10.2 From f0f42204d0cc04a63ac61fdaa3b6a269ea0dc08b Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 20 Jan 2014 08:33:50 +0100 Subject: usb: gadget: fix NULL pointer dereference Fix possible NULL pointer dereference introduced in commit 219580e (usb: f_fs: check quirk to pad epout buf size when not aligned to maxpacketsize) In cases we do wait with: wait_event_interruptible(epfile->wait, (ep = epfile->ep)); for endpoint to be enabled, functionfs_bind() has not been called yet and epfile->ffs->gadget is still NULL and the automatic variable 'gadget' has been initialized with NULL at the point of its definition. Later on it is used as a parameter to: usb_ep_align_maybe(gadget, ep->ep, len) which in turn dereferences it. This patch fixes it by moving the actual assignment to the local 'gadget' variable after the potential waiting has completed. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 306a2b5..2b43343 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -585,7 +585,6 @@ static ssize_t ffs_epfile_io(struct file *file, char __user *buf, size_t len, int read) { struct ffs_epfile *epfile = file->private_data; - struct usb_gadget *gadget = epfile->ffs->gadget; struct ffs_ep *ep; char *data = NULL; ssize_t ret, data_len; @@ -622,6 +621,12 @@ static ssize_t ffs_epfile_io(struct file *file, /* Allocate & copy */ if (!halt) { /* + * if we _do_ wait above, the epfile->ffs->gadget might be NULL + * before the waiting completes, so do not assign to 'gadget' earlier + */ + struct usb_gadget *gadget = epfile->ffs->gadget; + + /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. */ -- cgit v0.10.2 From e7d613d1db6f968514ccd7f0cbebba031e6394d2 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Tue, 18 Feb 2014 10:36:29 -0600 Subject: usb: phy: msm: fix compilation errors when !CONFIG_PM_SLEEP Both the PM_RUNTIME and PM_SLEEP callbacks call into the common msm_otg_{suspend,resume} routines, however these routines are only being built when CONFIG_PM_SLEEP. In addition, msm_otg_{suspend,resume} also depends on msm_hsusb_config_vddcx(), which is only built when CONFIG_PM_SLEEP. Fix the CONFIG_PM_RUNTIME, !CONFIG_PM_SLEEP case by changing the preprocessor conditional, and moving msm_hsusb_config_vddcx(). While we're here, eliminate the CONFIG_PM conditional for setting up the dev_pm_ops. This address the following errors Russell King has hit doing randconfig builds: drivers/usb/phy/phy-msm-usb.c: In function 'msm_otg_runtime_suspend': drivers/usb/phy/phy-msm-usb.c:1691:2: error: implicit declaration of function 'msm_otg_suspend' drivers/usb/phy/phy-msm-usb.c: In function 'msm_otg_runtime_resume': drivers/usb/phy/phy-msm-usb.c:1699:2: error: implicit declaration of function 'msm_otg_resume' Cc: Ivan T. Ivanov Reported-by: Russell King Signed-off-by: Josh Cartwright Signed-off-by: Felipe Balbi diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 8546c8d..d204f74 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -159,32 +159,6 @@ put_3p3: return rc; } -#ifdef CONFIG_PM_SLEEP -#define USB_PHY_SUSP_DIG_VOL 500000 -static int msm_hsusb_config_vddcx(int high) -{ - int max_vol = USB_PHY_VDD_DIG_VOL_MAX; - int min_vol; - int ret; - - if (high) - min_vol = USB_PHY_VDD_DIG_VOL_MIN; - else - min_vol = USB_PHY_SUSP_DIG_VOL; - - ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol); - if (ret) { - pr_err("%s: unable to set the voltage for regulator " - "HSUSB_VDDCX\n", __func__); - return ret; - } - - pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); - - return ret; -} -#endif - static int msm_hsusb_ldo_set_mode(int on) { int ret = 0; @@ -440,7 +414,32 @@ static int msm_otg_reset(struct usb_phy *phy) #define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000) #define PHY_RESUME_TIMEOUT_USEC (100 * 1000) -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM + +#define USB_PHY_SUSP_DIG_VOL 500000 +static int msm_hsusb_config_vddcx(int high) +{ + int max_vol = USB_PHY_VDD_DIG_VOL_MAX; + int min_vol; + int ret; + + if (high) + min_vol = USB_PHY_VDD_DIG_VOL_MIN; + else + min_vol = USB_PHY_SUSP_DIG_VOL; + + ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol); + if (ret) { + pr_err("%s: unable to set the voltage for regulator " + "HSUSB_VDDCX\n", __func__); + return ret; + } + + pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); + + return ret; +} + static int msm_otg_suspend(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; @@ -1733,22 +1732,18 @@ static int msm_otg_pm_resume(struct device *dev) } #endif -#ifdef CONFIG_PM static const struct dev_pm_ops msm_otg_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume) SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume, msm_otg_runtime_idle) }; -#endif static struct platform_driver msm_otg_driver = { .remove = msm_otg_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, -#ifdef CONFIG_PM .pm = &msm_otg_dev_pm_ops, -#endif }, }; -- cgit v0.10.2 From 9ccfaf74e766d49a64f86943f98d0a82996d4dec Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 5 Feb 2014 15:34:18 +0100 Subject: usb: musb: correct use of schedule_delayed_work() schedule_delayed_work() takes the delay in jiffies, not msecs. This bug slipped in with the recent reset logic cleanup (8ed1fb790ea: "usb: musb: finish suspend/reset work independently from musb_hub_control()"). Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b49a594..239ad0b 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -480,7 +480,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->rh_timer = jiffies + msecs_to_jiffies(20); schedule_delayed_work( - &musb->finish_resume_work, 20); + &musb->finish_resume_work, + msecs_to_jiffies(20)); musb->xceiv->state = OTG_STATE_A_HOST; musb->is_active = 1; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 32f49e1..e2d2d8c 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) /* later, GetPortStatus will stop RESUME signaling */ musb->port1_status |= MUSB_PORT_STAT_RESUME; - schedule_delayed_work(&musb->finish_resume_work, 20); + schedule_delayed_work(&musb->finish_resume_work, + msecs_to_jiffies(20)); } } @@ -171,8 +172,7 @@ void musb_port_reset(struct musb *musb, bool do_reset) if (musb->rh_timer > 0 && remain > 0) { /* take into account the minimum delay after resume */ schedule_delayed_work( - &musb->deassert_reset_work, - jiffies_to_msecs(remain)); + &musb->deassert_reset_work, remain); return; } @@ -180,7 +180,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) power & ~MUSB_POWER_RESUME); /* Give the core 1 ms to clear MUSB_POWER_RESUME */ - schedule_delayed_work(&musb->deassert_reset_work, 1); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(1)); return; } @@ -190,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) musb->port1_status |= USB_PORT_STAT_RESET; musb->port1_status &= ~USB_PORT_STAT_ENABLE; - schedule_delayed_work(&musb->deassert_reset_work, 50); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(50)); } else { dev_dbg(musb->controller, "root port reset stopped\n"); musb_writeb(mbase, MUSB_POWER, -- cgit v0.10.2 From 9085a6422900092886da8c404e1c5340c4ff1cbf Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 20 Feb 2014 10:56:45 -0500 Subject: SELinux: bigendian problems with filename trans rules When writing policy via /sys/fs/selinux/policy I wrote the type and class of filename trans rules in CPU endian instead of little endian. On x86_64 this works just fine, but it means that on big endian arch's like ppc64 and s390 userspace reads the policy and converts it from le32_to_cpu. So the values are all screwed up. Write the values in le format like it should have been to start. Signed-off-by: Eric Paris Acked-by: Stephen Smalley Cc: stable@vger.kernel.org Signed-off-by: Paul Moore diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index c0f4988..9c5cdc2ca 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -3338,10 +3338,10 @@ static int filename_write_helper(void *key, void *data, void *ptr) if (rc) return rc; - buf[0] = ft->stype; - buf[1] = ft->ttype; - buf[2] = ft->tclass; - buf[3] = otype->otype; + buf[0] = cpu_to_le32(ft->stype); + buf[1] = cpu_to_le32(ft->ttype); + buf[2] = cpu_to_le32(ft->tclass); + buf[3] = cpu_to_le32(otype->otype); rc = put_entry(buf, sizeof(u32), 4, fp); if (rc) -- cgit v0.10.2 From c7fbd4158433c1c910c62850247728cb05a94e42 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 20 Feb 2014 10:49:34 +0200 Subject: clk: tegra124: remove gr2d and gr3d clocks Tegra124 does not have gr2d and gr3d clocks. They have been replaced by the vic03 and gpu clocks respectively. Signed-off-by: Peter De Schrijver diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index b4cf650..166e02f 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -769,10 +769,8 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true }, [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true }, [tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true }, - [tegra_clk_gr2d] = { .dt_id = TEGRA124_CLK_GR_2D, .present = true }, [tegra_clk_usbd] = { .dt_id = TEGRA124_CLK_USBD, .present = true }, [tegra_clk_isp_8] = { .dt_id = TEGRA124_CLK_ISP, .present = true }, - [tegra_clk_gr3d] = { .dt_id = TEGRA124_CLK_GR_3D, .present = true }, [tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true }, [tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true }, [tegra_clk_host1x_8] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true }, diff --git a/include/dt-bindings/clock/tegra124-car.h b/include/dt-bindings/clock/tegra124-car.h index a1116a3..8c1603b 100644 --- a/include/dt-bindings/clock/tegra124-car.h +++ b/include/dt-bindings/clock/tegra124-car.h @@ -36,10 +36,10 @@ #define TEGRA124_CLK_PWM 17 #define TEGRA124_CLK_I2S2 18 /* 20 (register bit affects vi and vi_sensor) */ -#define TEGRA124_CLK_GR_2D 21 +/* 21 */ #define TEGRA124_CLK_USBD 22 #define TEGRA124_CLK_ISP 23 -#define TEGRA124_CLK_GR_3D 24 +/* 26 */ /* 25 */ #define TEGRA124_CLK_DISP2 26 #define TEGRA124_CLK_DISP1 27 -- cgit v0.10.2 From ec6f678c74dbdb06a6a775bbb00f1d26c17c404b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 18 Feb 2014 10:30:18 +0200 Subject: iwlwifi: dvm: clear IWL_STA_UCODE_INPROGRESS when assoc fails We set IWL_STA_UCODE_INPROGRESS flag when we add a station and clear it when we send the LQ command for it. But the LQ command is sent only when the association succeeds. If the association doesn't succeed, we would leave this flag set and that wouldn't indicate the station entry as vacant. This probably fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1065663 Cc: Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index c0d070c..9cdd91c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c @@ -590,6 +590,7 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id, sizeof(priv->tid_data[sta_id][tid])); priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; + priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; priv->num_stations--; -- cgit v0.10.2 From cf71d2bc0b8a473209d5c770ce560853bd720d14 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 20 Feb 2014 10:19:31 +0100 Subject: sit: fix panic with route cache in ip tunnels Bug introduced by commit 7d442fab0a67 ("ipv4: Cache dst in tunnels"). Because sit code does not call ip_tunnel_init(), the dst_cache was not initialized. CC: Tom Herbert Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 48ed75c..e77c104 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -129,6 +129,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm *p); void ip_tunnel_setup(struct net_device *dev, int net_id); +void ip_tunnel_dst_reset_all(struct ip_tunnel *t); /* Extract dsfield from inner protocol */ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 08f8cf9..78a89e6 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -93,13 +93,14 @@ static void tunnel_dst_reset(struct ip_tunnel *t) tunnel_dst_set(t, NULL); } -static void tunnel_dst_reset_all(struct ip_tunnel *t) +void ip_tunnel_dst_reset_all(struct ip_tunnel *t) { int i; for_each_possible_cpu(i) __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); } +EXPORT_SYMBOL(ip_tunnel_dst_reset_all); static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) { @@ -713,7 +714,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, if (set_mtu) dev->mtu = mtu; } - tunnel_dst_reset_all(t); + ip_tunnel_dst_reset_all(t); netdev_state_change(dev); } @@ -1042,7 +1043,7 @@ void ip_tunnel_uninit(struct net_device *dev) if (itn->fb_tunnel_dev != dev) ip_tunnel_del(netdev_priv(dev)); - tunnel_dst_reset_all(tunnel); + ip_tunnel_dst_reset_all(tunnel); } EXPORT_SYMBOL_GPL(ip_tunnel_uninit); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3dfbcf1..b4d74c8 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -475,6 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) ipip6_tunnel_unlink(sitn, tunnel); ipip6_tunnel_del_prl(tunnel, NULL); } + ip_tunnel_dst_reset_all(tunnel); dev_put(dev); } @@ -1082,6 +1083,7 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) t->parms.link = p->link; ipip6_tunnel_bind_dev(t->dev); } + ip_tunnel_dst_reset_all(t); netdev_state_change(t->dev); } @@ -1112,6 +1114,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t, t->ip6rd.relay_prefix = relay_prefix; t->ip6rd.prefixlen = ip6rd->prefixlen; t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; + ip_tunnel_dst_reset_all(t); netdev_state_change(t->dev); return 0; } @@ -1271,6 +1274,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); break; } + ip_tunnel_dst_reset_all(t); netdev_state_change(dev); break; @@ -1326,6 +1330,9 @@ static const struct net_device_ops ipip6_netdev_ops = { static void ipip6_dev_free(struct net_device *dev) { + struct ip_tunnel *tunnel = netdev_priv(dev); + + free_percpu(tunnel->dst_cache); free_percpu(dev->tstats); free_netdev(dev); } @@ -1375,6 +1382,12 @@ static int ipip6_tunnel_init(struct net_device *dev) u64_stats_init(&ipip6_tunnel_stats->syncp); } + tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); + if (!tunnel->dst_cache) { + free_percpu(dev->tstats); + return -ENOMEM; + } + return 0; } @@ -1405,6 +1418,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) u64_stats_init(&ipip6_fb_stats->syncp); } + tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); + if (!tunnel->dst_cache) { + free_percpu(dev->tstats); + return -ENOMEM; + } + dev_hold(dev); rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); return 0; -- cgit v0.10.2 From fb8ef788680d48523321e5f150b23700a1caf980 Mon Sep 17 00:00:00 2001 From: Duan Fugang-B38611 Date: Thu, 20 Feb 2014 18:14:39 +0800 Subject: net: fec: fix potential issue to avoid fec interrupt lost and crc error The current flow: Set TX BD ready, and then set "INT" and "PINS" bit to enable tx interrupt generation and crc checksum. There has potential issue like as: CPU fec uDMA Set tx ready bit uDMA start the BD transmission Set "INT" bit Set "PINS" bit ... Above situation cause fec tx interrupt lost and fec MAC don't do CRC checksum. The patch fix the potential issue. Signed-off-by: Fugang Duan Acked-by: Frank Li Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 903362a..479a7cb 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -389,12 +389,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) netdev_err(ndev, "Tx DMA memory map failed\n"); return NETDEV_TX_OK; } - /* Send it on its way. Tell FEC it's ready, interrupt when done, - * it's the last BD of the frame, and to put the CRC on the end. - */ - status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR - | BD_ENET_TX_LAST | BD_ENET_TX_TC); - bdp->cbd_sc = status; if (fep->bufdesc_ex) { @@ -416,6 +410,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) } } + /* Send it on its way. Tell FEC it's ready, interrupt when done, + * it's the last BD of the frame, and to put the CRC on the end. + */ + status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR + | BD_ENET_TX_LAST | BD_ENET_TX_TC); + bdp->cbd_sc = status; + bdp_pre = fec_enet_get_prevdesc(bdp, fep); if ((id_entry->driver_data & FEC_QUIRK_ERR006358) && !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) { -- cgit v0.10.2 From 7cce3b75682ff898c935c17d186983cbf3ed393e Mon Sep 17 00:00:00 2001 From: Matija Glavinic Pecotic Date: Thu, 20 Feb 2014 14:13:04 +0100 Subject: net: sctp: Potentially-Failed state should not be reached from unconfirmed state In current implementation it is possible to reach PF state from unconfirmed. We can interpret sctp-failover-02 in a way that PF state is meant to be reached only from active state, in the end, this is when entering PF state makes sense. Here are few quotes from sctp-failover-02, but regardless of these, same understanding can be reached from whole section 5: Section 5.1, quickfailover guide: "The PF state is an intermediate state between Active and Failed states." "Each time the T3-rtx timer expires on an active or idle destination, the error counter of that destination address will be incremented. When the value in the error counter exceeds PFMR, the endpoint should mark the destination transport address as PF." There are several concrete reasons for such interpretation. For start, rfc4960 does not take into concern quickfailover algorithm. Therefore, quickfailover must comply to 4960. Point where this compliance can be argued is following behavior: When PF is entered, association overall error counter is incremented for each missed HB. This is contradictory to rfc4960, as address, while in unconfirmed state, is subjected to probing, and while it is probed, it should not increment association overall error counter. This has as a consequence that we might end up in situation in which we drop association due path failure on unconfirmed address, in case we have wrong configuration in a way: Association.Max.Retrans == Path.Max.Retrans. Another reason is that entering PF from unconfirmed will cause a loss of address confirmed event when address is once (if) confirmed. This is fine from failover guide point of view, but it is not consistent with behavior preceding failover implementation and recommendation from 4960: 5.4. Path Verification Whenever a path is confirmed, an indication MAY be given to the upper layer. Signed-off-by: Matija Glavinic Pecotic Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bd85915..5d6883f 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -495,11 +495,12 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, } /* If the transport error count is greater than the pf_retrans - * threshold, and less than pathmaxrtx, then mark this transport - * as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1, - * point 1 + * threshold, and less than pathmaxrtx, and if the current state + * is not SCTP_UNCONFIRMED, then mark this transport as Partially + * Failed, see SCTP Quick Failover Draft, section 5.1 */ if ((transport->state != SCTP_PF) && + (transport->state != SCTP_UNCONFIRMED) && (asoc->pf_retrans < transport->pathmaxrxt) && (transport->error_count > asoc->pf_retrans)) { -- cgit v0.10.2 From 967f038e491bc0aa469c4187aab7715ee9069ae1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 20 Feb 2014 16:08:12 +0000 Subject: Sparc: sparc_cpu_model isn't in asm/system.h any more [ver #2] sparc_cpu_model isn't in asm/system.h any more, so remove a comment about it. Signed-off-by: David Howells cc: "David S. Miller" cc: sparclinux@vger.kernel.org Signed-off-by: David S. Miller diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index 6b4678a..4ccb5d8 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -507,7 +507,6 @@ static int jsflash_init(void) } /* Let us be really paranoid for modifications to probing code. */ - /* extern enum sparc_cpu sparc_cpu_model; */ /* in */ if (sparc_cpu_model != sun4m) { /* We must be on sun4m because we use MMU Bypass ASI. */ return -ENXIO; -- cgit v0.10.2 From b080e047a61f7050246ff3081f87832997170d29 Mon Sep 17 00:00:00 2001 From: Brian Campbell Date: Sun, 16 Feb 2014 22:58:12 -0500 Subject: user_namespace.c: Remove duplicated word in comment Signed-off-by: Brian Campbell Signed-off-by: Linus Torvalds diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 240fb62..dd06439 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -225,7 +225,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id) * * When there is no mapping defined for the user-namespace uid * pair INVALID_UID is returned. Callers are expected to test - * for and handle handle INVALID_UID being returned. INVALID_UID + * for and handle INVALID_UID being returned. INVALID_UID * may be tested for using uid_valid(). */ kuid_t make_kuid(struct user_namespace *ns, uid_t uid) -- cgit v0.10.2 From e284175a96e5af087ea7806b3e38282b524ff5b9 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Thu, 20 Feb 2014 17:23:16 +0800 Subject: ACPI / nouveau: fix probing regression related to _DSM Fix regression caused by commit b072e53, which breaks loading nouveau driver on optimus laptops. On some platforms, ACPI _DSM method (nouveau_op_dsm_muid, function 0) has special requirements on the fourth parameter, which is different from ACPI specifications. So revert to the private implementation to check availability of _DSM functions instead of using common acpi_check_dsm() interface. Fixes: b072e53b0a27 (ACPI / nouveau: replace open-coded _DSM code with helper functions) Reported-and-tested-by: Maarten Lankhorst [rjw: Subject] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 4ef83df..83face3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -106,6 +106,29 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * return 0; } +/* + * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special + * requirements on the fourth parameter, so a private implementation + * instead of using acpi_check_dsm(). + */ +static int nouveau_check_optimus_dsm(acpi_handle handle) +{ + int result; + + /* + * Function 0 returns a Buffer containing available functions. + * The args parameter is ignored for function 0, so just put 0 in it + */ + if (nouveau_optimus_dsm(handle, 0, 0, &result)) + return 0; + + /* + * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. + * If the n-th bit is enabled, function n is supported + */ + return result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS); +} + static int nouveau_dsm(acpi_handle handle, int func, int arg) { int ret = 0; @@ -207,8 +230,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) 1 << NOUVEAU_DSM_POWER)) retval |= NOUVEAU_DSM_HAS_MUX; - if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100, - 1 << NOUVEAU_DSM_OPTIMUS_CAPS)) + if (nouveau_check_optimus_dsm(dhandle)) retval |= NOUVEAU_DSM_HAS_OPT; if (retval & NOUVEAU_DSM_HAS_OPT) { -- cgit v0.10.2 From 72471c0d3197d02da53897868692f0b91042f8a5 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Fri, 14 Feb 2014 16:17:49 +0400 Subject: hostap: Do not free priv until timer handler has actually stopped using it Function del_timer() does not guarantee that timer was really deleted. If the timer handler is beeing executed at the moment, the function does nothing. So, it's possible to use already freed memory in the handler: [ref: Documentation/DocBook/kernel-locking.tmpl] This was found using grep and compile-tested only. Please, consider applying or something similar to it. Signed-off-by: Kirill Tkhai CC: Jouni Malinen CC: John W. Linville Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index d36e252..5965255 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -147,7 +147,7 @@ static void ap_free_sta(struct ap_data *ap, struct sta_info *sta) if (!sta->ap && sta->u.sta.challenge) kfree(sta->u.sta.challenge); - del_timer(&sta->timer); + del_timer_sync(&sta->timer); #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ kfree(sta); -- cgit v0.10.2 From 95320774fae71d7b22b970ef4267fcc4d1ad23d8 Mon Sep 17 00:00:00 2001 From: James Cameron Date: Mon, 17 Feb 2014 10:25:53 +1100 Subject: libertas: fix scan result loss if SSID IE len 0 Scan results from Marvell 8388 and 8686 have probe responses from hidden APs and OLPC XO-1 mesh with a zero length SSID IE. Bug in lbs_ret_scan discarded any remaining BSS in scan response, leading to user not seeing APs in dense environments. With LBS_DEB_SCAN, dmesg shows libertas scan: scan response: 5 BSSs (419 bytes); resp size 474 bytes libertas scan: scan: 00:1a:2b:84:de:e8, capa 0401, chan 1, qz, -51 dBm libertas scan: scan: 5c:63:bf:d8:eb:0c, capa 0411, chan 1, qw129, -23 dBm libertas scan: scan response: invalid IE fmt With LBS_DEB_HEX, dmesg shows valid BSS in scan response were not processed. Change is to ignore zero length IE and continue processing. Fixes OLPC 12757, http://dev.laptop.org/ticket/12757 Signed-off-by: James Cameron Reported-by: T Gillett Tested-by: T Gillett CC: Dan Williams Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 32f7500..cb6d189 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -621,7 +621,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, id = *pos++; elen = *pos++; left -= 2; - if (elen > left || elen == 0) { + if (elen > left) { lbs_deb_scan("scan response: invalid IE fmt\n"); goto done; } -- cgit v0.10.2 From 4f7ba432202c8330cc03ab959c6228d0de5dc4a3 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Tue, 18 Feb 2014 15:41:54 -0800 Subject: mwifiex: clean pcie ring only when device is present Write io memory to clean PCIe buffer only when PCIe device is present else this results into crash because of invalid memory access. Cc: # 3.9+ Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 13eaeed..981cf6e 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -559,7 +559,8 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) mwifiex_wmm_delete_all_ralist(priv); memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); - if (priv->adapter->if_ops.clean_pcie_ring) + if (priv->adapter->if_ops.clean_pcie_ring && + !priv->adapter->surprise_removed) priv->adapter->if_ops.clean_pcie_ring(priv->adapter); spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); } -- cgit v0.10.2 From bb8e6a1ee881d131e404f0f1f5e8dc9281002771 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 18 Feb 2014 15:41:55 -0800 Subject: mwifiex: add NULL check for PCIe Rx skb We may get a NULL pointer here if skb allocation for Rx packet was failed earlier. Cc: # 3.9+ Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 03688aa..28029b7 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -1211,6 +1211,12 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) rd_index = card->rxbd_rdptr & reg->rx_mask; skb_data = card->rx_buf_list[rd_index]; + /* If skb allocation was failed earlier for Rx packet, + * rx_buf_list[rd_index] would have been left with a NULL. + */ + if (!skb_data) + return -ENOMEM; + MWIFIEX_SKB_PACB(skb_data, &buf_pa); pci_unmap_single(card->dev, buf_pa, MWIFIEX_RX_DATA_BUF_SIZE, PCI_DMA_FROMDEVICE); -- cgit v0.10.2 From 1c97560f6d751a620978504a4a888c631192b71a Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 18 Feb 2014 15:41:56 -0800 Subject: mwifiex: fix cmd and Tx data timeout issue for PCIe cards We are sending sleep confirm done interrupt in the middle of sleep handshake. There is a corner case when Tx done interrupt is received from firmware during sleep handshake due to which host and firmware power states go out of sync causing cmd and Tx data timeout problem. Hence sleep confirm done interrupt is sent at the end of sleep handshake to fix the problem. Cc: # 3.10+ Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 28029b7..7fe7b53 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -1531,6 +1531,14 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) if (adapter->ps_state == PS_STATE_SLEEP_CFM) { mwifiex_process_sleep_confirm_resp(adapter, skb->data, skb->len); + mwifiex_pcie_enable_host_int(adapter); + if (mwifiex_write_reg(adapter, + PCIE_CPU_INT_EVENT, + CPU_INTR_SLEEP_CFM_DONE)) { + dev_warn(adapter->dev, + "Write register failed\n"); + return -1; + } while (reg->sleep_cookie && (count++ < 10) && mwifiex_pcie_ok_to_access_hw(adapter)) usleep_range(50, 60); @@ -1999,23 +2007,9 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) adapter->int_status |= pcie_ireg; spin_unlock_irqrestore(&adapter->int_lock, flags); - if (pcie_ireg & HOST_INTR_CMD_DONE) { - if ((adapter->ps_state == PS_STATE_SLEEP_CFM) || - (adapter->ps_state == PS_STATE_SLEEP)) { - mwifiex_pcie_enable_host_int(adapter); - if (mwifiex_write_reg(adapter, - PCIE_CPU_INT_EVENT, - CPU_INTR_SLEEP_CFM_DONE) - ) { - dev_warn(adapter->dev, - "Write register failed\n"); - return; - - } - } - } else if (!adapter->pps_uapsd_mode && - adapter->ps_state == PS_STATE_SLEEP && - mwifiex_pcie_ok_to_access_hw(adapter)) { + if (!adapter->pps_uapsd_mode && + adapter->ps_state == PS_STATE_SLEEP && + mwifiex_pcie_ok_to_access_hw(adapter)) { /* Potentially for PCIe we could get other * interrupts like shared. Don't change power * state until cookie is set */ -- cgit v0.10.2 From 21f8aaee0c62708654988ce092838aa7df4d25d8 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 19 Feb 2014 13:15:17 +0100 Subject: ath9k: protect tid->sched check We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That is race condition which can result of doing list_del(&tid->list) twice (second time with poisoned list node) and cause crash like shown below: [424271.637220] BUG: unable to handle kernel paging request at 00100104 [424271.637328] IP: [] ath_tx_aggr_sleep+0x62/0xe0 [ath9k] ... [424271.639953] Call Trace: [424271.639998] [] ? ath9k_get_survey+0x110/0x110 [ath9k] [424271.640083] [] ath9k_sta_notify+0x42/0x50 [ath9k] [424271.640177] [] sta_ps_start+0x8f/0x1c0 [mac80211] [424271.640258] [] ? free_compound_page+0x2e/0x40 [424271.640346] [] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211] [424271.640437] [] ? kmem_cache_free+0x1d8/0x1f0 [424271.640510] [] ? kfree_skbmem+0x34/0x90 [424271.640578] [] ? put_page+0x2c/0x40 [424271.640640] [] ? kfree_skbmem+0x34/0x90 [424271.640706] [] ? kfree_skbmem+0x34/0x90 [424271.640787] [] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211] [424271.640897] [] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211] [424271.641009] [] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211] [424271.641104] [] ? ip_output+0x7e/0xd0 [424271.641182] [] ieee80211_rx+0x307/0x7c0 [mac80211] [424271.641266] [] ath_rx_tasklet+0x88e/0xf70 [ath9k] [424271.641358] [] ? ieee80211_rx+0x1dc/0x7c0 [mac80211] [424271.641445] [] ath9k_tasklet+0xcb/0x130 [ath9k] Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=70551 Reported-and-tested-by: Max Sydorenko Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 0a75e2f..4f4ce83 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, for (tidno = 0, tid = &an->tid[tidno]; tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { - if (!tid->sched) - continue; - ac = tid->ac; txq = ac->txq; ath_txq_lock(sc, txq); + if (!tid->sched) { + ath_txq_unlock(sc, txq); + continue; + } + buffered = ath_tid_has_buffered(tid); tid->sched = false; -- cgit v0.10.2 From 1eb43018673e735ea9cd756970f4e71ca01a5f21 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 20 Feb 2014 18:55:55 +0100 Subject: brcmfmac: fix txglomming scatter-gather packet transfers The driver concatenates multiple packets in one MMC transfer. For scatter-gather to work the total length need to be multiple of 512 bytes. A pre-allocated buffer was used to add padding to accomplish that. However, the length was not properly set and it was freed after the first transfer causing a crash. Reviewed-by: Daniel (Deognyoun) Kim Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 3e99189..119ee6e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -457,7 +457,6 @@ struct brcmf_sdio { u8 tx_hdrlen; /* sdio bus header length for tx packet */ bool txglom; /* host tx glomming enable flag */ - struct sk_buff *txglom_sgpad; /* scatter-gather padding buffer */ u16 head_align; /* buffer pointer alignment */ u16 sgentry_align; /* scatter-gather buffer alignment */ }; @@ -1944,9 +1943,8 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus, if (lastfrm && chain_pad) tail_pad += blksize - chain_pad; if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) { - pkt_pad = bus->txglom_sgpad; - if (pkt_pad == NULL) - brcmu_pkt_buf_get_skb(tail_pad + tail_chop); + pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop + + bus->head_align); if (pkt_pad == NULL) return -ENOMEM; ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad); @@ -1957,6 +1955,7 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus, tail_chop); *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop; skb_trim(pkt, pkt->len - tail_chop); + skb_trim(pkt_pad, tail_pad + tail_chop); __skb_queue_after(pktq, pkt, pkt_pad); } else { ntail = pkt->data_len + tail_pad - @@ -2011,7 +2010,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, return ret; head_pad = (u16)ret; if (head_pad) - memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen); + memset(pkt_next->data + bus->tx_hdrlen, 0, head_pad); total_len += pkt_next->len; @@ -3486,10 +3485,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev) bus->txglom = false; value = 1; pad_size = bus->sdiodev->func[2]->cur_blksize << 1; - bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size); - if (!bus->txglom_sgpad) - brcmf_err("allocating txglom padding skb failed, reduced performance\n"); - err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom", &value, sizeof(u32)); if (err < 0) { @@ -4053,7 +4048,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) brcmf_sdio_chip_detach(&bus->ci); } - brcmu_pkt_buf_free_skb(bus->txglom_sgpad); kfree(bus->rxbuf); kfree(bus->hdrbuf); kfree(bus); -- cgit v0.10.2 From b3050248c167871ca52cfdb2ce78aa2460249346 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 14 Feb 2014 08:15:20 +0530 Subject: ath9k: Fix ETSI compliance for AR9462 2.0 The minimum CCA power threshold values have to be adjusted for existing cards to be in compliance with new regulations. Newer cards will make use of the values obtained from EEPROM, support for this was added earlier. To make sure that cards that are already in use and don't have proper values in EEPROM, do not violate regulations, use the initvals instead. Cc: stable@vger.kernel.org Reported-by: Jeang Daniel Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 1cc1356..1b6b4d0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -57,7 +57,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e}, {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, @@ -96,7 +96,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000}, {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000ae20, 0x000001a6, 0x000001a6, 0x000001aa, 0x000001aa}, {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, }; -- cgit v0.10.2 From 09ebb17ab476b6ac1cc07b53d07e88f4d31ee4d3 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 18 Feb 2014 12:00:21 +0100 Subject: udf: Fix data corruption on file type conversion UDF has two types of files - files with data stored in inode (ICB in UDF terminology) and files with data stored in external data blocks. We convert file from in-inode format to external format in udf_file_aio_write() when we find out data won't fit into inode any longer. However the following race between two O_APPEND writes can happen: CPU1 CPU2 udf_file_aio_write() udf_file_aio_write() down_write(&iinfo->i_data_sem); checks that i_size + count1 fits within inode => no need to convert up_write(&iinfo->i_data_sem); down_write(&iinfo->i_data_sem); checks that i_size + count2 fits within inode => no need to convert up_write(&iinfo->i_data_sem); generic_file_aio_write() - extends file by count1 bytes generic_file_aio_write() - extends file by count2 bytes Clearly if count1 + count2 doesn't fit into the inode, we overwrite kernel buffers beyond inode, possibly corrupting the filesystem as well. Fix the problem by acquiring i_mutex before checking whether write fits into the inode and using __generic_file_aio_write() afterwards which puts check and write into one critical section. Reported-by: Al Viro Signed-off-by: Jan Kara diff --git a/fs/udf/file.c b/fs/udf/file.c index c02a27a..1037637 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -144,6 +144,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, size_t count = iocb->ki_nbytes; struct udf_inode_info *iinfo = UDF_I(inode); + mutex_lock(&inode->i_mutex); down_write(&iinfo->i_data_sem); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (file->f_flags & O_APPEND) @@ -156,6 +157,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, pos + count)) { err = udf_expand_file_adinicb(inode); if (err) { + mutex_unlock(&inode->i_mutex); udf_debug("udf_expand_adinicb: err=%d\n", err); return err; } @@ -169,9 +171,17 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, } else up_write(&iinfo->i_data_sem); - retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); - if (retval > 0) + retval = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); + mutex_unlock(&inode->i_mutex); + + if (retval > 0) { + ssize_t err; + mark_inode_dirty(inode); + err = generic_write_sync(file, iocb->ki_pos - retval, retval); + if (err < 0) + retval = err; + } return retval; } diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 062b792..982ce05 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -265,6 +265,7 @@ int udf_expand_file_adinicb(struct inode *inode) .nr_to_write = 1, }; + WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); if (!iinfo->i_lenAlloc) { if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; -- cgit v0.10.2 From 1362f4ea20fa63688ba6026e586d9746ff13a846 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 20 Feb 2014 17:02:27 +0100 Subject: quota: Fix race between dqput() and dquot_scan_active() Currently last dqput() can race with dquot_scan_active() causing it to call callback for an already deactivated dquot. The race is as follows: CPU1 CPU2 dqput() spin_lock(&dq_list_lock); if (atomic_read(&dquot->dq_count) > 1) { - not taken if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { spin_unlock(&dq_list_lock); ->release_dquot(dquot); if (atomic_read(&dquot->dq_count) > 1) - not taken dquot_scan_active() spin_lock(&dq_list_lock); if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) - not taken atomic_inc(&dquot->dq_count); spin_unlock(&dq_list_lock); - proceeds to release dquot ret = fn(dquot, priv); - called for inactive dquot Fix the problem by making sure possible ->release_dquot() is finished by the time we call the callback and new calls to it will notice reference dquot_scan_active() has taken and bail out. CC: stable@vger.kernel.org # >= 2.6.29 Signed-off-by: Jan Kara diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 831d49a..cfc8dcc 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -581,9 +581,17 @@ int dquot_scan_active(struct super_block *sb, dqstats_inc(DQST_LOOKUPS); dqput(old_dquot); old_dquot = dquot; - ret = fn(dquot, priv); - if (ret < 0) - goto out; + /* + * ->release_dquot() can be racing with us. Our reference + * protects us from new calls to it so just wait for any + * outstanding call and recheck the DQ_ACTIVE_B after that. + */ + wait_on_dquot(dquot); + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { + ret = fn(dquot, priv); + if (ret < 0) + goto out; + } spin_lock(&dq_list_lock); /* We are safe to continue now because our dquot could not * be moved out of the inuse list while we hold the reference */ -- cgit v0.10.2 From ddb95145a38eb37b236d4e00f43a75d067922dda Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Feb 2014 17:51:25 -0800 Subject: qla2xxx: Fix qlt_lport_register base_vha callback race This patch closes a race between qlt_lport_register() and tcm_qla2xxx callback logic by holding qla_tgt_mutex before making the callback. In order for this to work, the qlt_add_target() and qlt_remove_target() code has been changed to avoid the accessing qla_tgt_mutex + list_[add,del] for NPIV enabled ports. This bug introduced in v3.14-rc1 code with commit 49a47f2. Cc: Sawan Chandak Cc: Quinn Tran Cc: Saurav Kashyap Cc: Giridhar Malavali Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 2eb97d7..ea3eaef 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4181,6 +4181,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX; tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX; + if (base_vha->fc_vport) + return 0; + mutex_lock(&qla_tgt_mutex); list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist); mutex_unlock(&qla_tgt_mutex); @@ -4194,6 +4197,10 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha) if (!vha->vha_tgt.qla_tgt) return 0; + if (vha->fc_vport) { + qlt_release(vha->vha_tgt.qla_tgt); + return 0; + } mutex_lock(&qla_tgt_mutex); list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry); mutex_unlock(&qla_tgt_mutex); @@ -4265,6 +4272,12 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn, spin_unlock_irqrestore(&ha->hardware_lock, flags); continue; } + if (tgt->tgt_stop) { + pr_debug("MODE_TARGET in shutdown on qla2xxx(%d)\n", + host->host_no); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + continue; + } spin_unlock_irqrestore(&ha->hardware_lock, flags); if (!scsi_host_get(host)) { @@ -4279,12 +4292,11 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn, scsi_host_put(host); continue; } - mutex_unlock(&qla_tgt_mutex); - rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn); if (rc != 0) scsi_host_put(host); + mutex_unlock(&qla_tgt_mutex); return rc; } mutex_unlock(&qla_tgt_mutex); -- cgit v0.10.2 From 3c231bdae1e7c8d366eeb133980b81dff2e1e809 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Feb 2014 17:50:22 -0800 Subject: qla2xxx: Check + fail when npiv_vports_inuse exists in shutdown This patch adds an check to qlt_stop_phase1() to avoid shutdown when the base_vha contains a non-zero fc_host->npiv_vports_inuse count. This includes holding qla_tgt_mutex in qlt_stop_phase1() between the fc_host->npiv_vports_inuse check + setting of tgt->tgt_stop to avoid a possible race between qlt_lport_register() -> tcm_qla2xxx -> tcm_qla2xxx_lport_register_npiv_cb() calling fc_vport_create(). Cc: Sawan Chandak Cc: Quinn Tran Cc: Saurav Kashyap Cc: Giridhar Malavali Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index ea3eaef..f2e1c5a 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -790,17 +790,32 @@ static inline int test_tgt_sess_count(struct qla_tgt *tgt) } /* Called by tcm_qla2xxx configfs code */ -void qlt_stop_phase1(struct qla_tgt *tgt) +int qlt_stop_phase1(struct qla_tgt *tgt) { struct scsi_qla_host *vha = tgt->vha; struct qla_hw_data *ha = tgt->ha; unsigned long flags; + mutex_lock(&qla_tgt_mutex); + if (!vha->fc_vport) { + struct Scsi_Host *sh = vha->host; + struct fc_host_attrs *fc_host = shost_to_fc_host(sh); + bool npiv_vports; + + spin_lock_irqsave(sh->host_lock, flags); + npiv_vports = (fc_host->npiv_vports_inuse); + spin_unlock_irqrestore(sh->host_lock, flags); + + if (npiv_vports) { + mutex_unlock(&qla_tgt_mutex); + return -EPERM; + } + } if (tgt->tgt_stop || tgt->tgt_stopped) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e, "Already in tgt->tgt_stop or tgt_stopped state\n"); - dump_stack(); - return; + mutex_unlock(&qla_tgt_mutex); + return -EPERM; } ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n", @@ -815,6 +830,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt) qlt_clear_tgt_db(tgt, true); spin_unlock_irqrestore(&ha->hardware_lock, flags); mutex_unlock(&vha->vha_tgt.tgt_mutex); + mutex_unlock(&qla_tgt_mutex); flush_delayed_work(&tgt->sess_del_work); @@ -841,6 +857,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt) /* Wait for sessions to clear out (just in case) */ wait_event(tgt->waitQ, test_tgt_sess_count(tgt)); + return 0; } EXPORT_SYMBOL(qlt_stop_phase1); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 66e755c..ce33d8c 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -1001,7 +1001,7 @@ extern void qlt_modify_vp_config(struct scsi_qla_host *, extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *); extern int qlt_mem_alloc(struct qla_hw_data *); extern void qlt_mem_free(struct qla_hw_data *); -extern void qlt_stop_phase1(struct qla_tgt *); +extern int qlt_stop_phase1(struct qla_tgt *); extern void qlt_stop_phase2(struct qla_tgt *); extern irqreturn_t qla83xx_msix_atio_q(int, void *); extern void qlt_83xx_iospace_config(struct qla_hw_data *); -- cgit v0.10.2 From 394d62ba4580a74afc90bf0e007e10291bf447cc Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Feb 2014 16:52:15 -0800 Subject: tcm_qla2xxx: Add NPIV specific enable/disable attribute logic This patch adds seperate logic for NPIV specific enable/disable attribute logic, as NPIV vs. non-NPIV enable/disable ends up being different enough to warrent seperate logic for setting configfs tpg_group dependencies in the non-NPIV case. Cc: Sawan Chandak Cc: Quinn Tran Cc: Saurav Kashyap Cc: Giridhar Malavali Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 75a141b..db43b289 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1053,11 +1053,64 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg) /* * Clear local TPG=1 pointer for non NPIV mode. */ - lport->tpg_1 = NULL; - + lport->tpg_1 = NULL; kfree(tpg); } +static ssize_t tcm_qla2xxx_npiv_tpg_show_enable( + struct se_portal_group *se_tpg, + char *page) +{ + return tcm_qla2xxx_tpg_show_enable(se_tpg, page); +} + +static ssize_t tcm_qla2xxx_npiv_tpg_store_enable( + struct se_portal_group *se_tpg, + const char *page, + size_t count) +{ + struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; + struct tcm_qla2xxx_lport *lport = container_of(se_wwn, + struct tcm_qla2xxx_lport, lport_wwn); + struct scsi_qla_host *vha = lport->qla_vha; + struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, + struct tcm_qla2xxx_tpg, se_tpg); + unsigned long op; + int rc; + + rc = kstrtoul(page, 0, &op); + if (rc < 0) { + pr_err("kstrtoul() returned %d\n", rc); + return -EINVAL; + } + if ((op != 1) && (op != 0)) { + pr_err("Illegal value for tpg_enable: %lu\n", op); + return -EINVAL; + } + if (op) { + if (atomic_read(&tpg->lport_tpg_enabled)) + return -EEXIST; + + atomic_set(&tpg->lport_tpg_enabled, 1); + qlt_enable_vha(vha); + } else { + if (!atomic_read(&tpg->lport_tpg_enabled)) + return count; + + atomic_set(&tpg->lport_tpg_enabled, 0); + qlt_stop_phase1(vha->vha_tgt.qla_tgt); + } + + return count; +} + +TF_TPG_BASE_ATTR(tcm_qla2xxx_npiv, enable, S_IRUGO | S_IWUSR); + +static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = { + &tcm_qla2xxx_npiv_tpg_enable.attr, + NULL, +}; + static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg( struct se_wwn *wwn, struct config_group *group, @@ -1935,7 +1988,7 @@ static int tcm_qla2xxx_register_configfs(void) */ npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = - tcm_qla2xxx_tpg_attrs; + tcm_qla2xxx_npiv_tpg_attrs; npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL; npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL; npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL; -- cgit v0.10.2 From 7474f52a82d51da2e6110e91bba8b000cb9cf803 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Feb 2014 16:53:07 -0800 Subject: tcm_qla2xxx: Perform configfs depend/undepend for base_tpg This patch performs configfs_depend_item() during TPG enable for base_tpg (eg: non-NPIV) ports, and configfs_undepend_item() during TPG disable for base_tpg. This is done to ensure that any attempt to configfs rmdir a base_tpg with active NPIV ports will fail with -EBUSY, until all associated NPIV ports have been explicitly shutdown and base_tpg disabled. Note that the actual configfs_[un]depend_item() is done from seperate process context, as these are not intended to be called directly from configfs callbacks. Cc: Sawan Chandak Cc: Quinn Tran Cc: Saurav Kashyap Cc: Giridhar Malavali Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index db43b289..5bdc440 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -941,15 +941,41 @@ static ssize_t tcm_qla2xxx_tpg_show_enable( atomic_read(&tpg->lport_tpg_enabled)); } +static void tcm_qla2xxx_depend_tpg(struct work_struct *work) +{ + struct tcm_qla2xxx_tpg *base_tpg = container_of(work, + struct tcm_qla2xxx_tpg, tpg_base_work); + struct se_portal_group *se_tpg = &base_tpg->se_tpg; + struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha; + + if (!configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys, + &se_tpg->tpg_group.cg_item)) { + atomic_set(&base_tpg->lport_tpg_enabled, 1); + qlt_enable_vha(base_vha); + } + complete(&base_tpg->tpg_base_comp); +} + +static void tcm_qla2xxx_undepend_tpg(struct work_struct *work) +{ + struct tcm_qla2xxx_tpg *base_tpg = container_of(work, + struct tcm_qla2xxx_tpg, tpg_base_work); + struct se_portal_group *se_tpg = &base_tpg->se_tpg; + struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha; + + if (!qlt_stop_phase1(base_vha->vha_tgt.qla_tgt)) { + atomic_set(&base_tpg->lport_tpg_enabled, 0); + configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys, + &se_tpg->tpg_group.cg_item); + } + complete(&base_tpg->tpg_base_comp); +} + static ssize_t tcm_qla2xxx_tpg_store_enable( struct se_portal_group *se_tpg, const char *page, size_t count) { - struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; - struct tcm_qla2xxx_lport *lport = container_of(se_wwn, - struct tcm_qla2xxx_lport, lport_wwn); - struct scsi_qla_host *vha = lport->qla_vha; struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, struct tcm_qla2xxx_tpg, se_tpg); unsigned long op; @@ -964,19 +990,28 @@ static ssize_t tcm_qla2xxx_tpg_store_enable( pr_err("Illegal value for tpg_enable: %lu\n", op); return -EINVAL; } - if (op) { - atomic_set(&tpg->lport_tpg_enabled, 1); - qlt_enable_vha(vha); + if (atomic_read(&tpg->lport_tpg_enabled)) + return -EEXIST; + + INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_depend_tpg); } else { - if (!vha->vha_tgt.qla_tgt) { - pr_err("struct qla_hw_data *vha->vha_tgt.qla_tgt is NULL\n"); - return -ENODEV; - } - atomic_set(&tpg->lport_tpg_enabled, 0); - qlt_stop_phase1(vha->vha_tgt.qla_tgt); + if (!atomic_read(&tpg->lport_tpg_enabled)) + return count; + + INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_undepend_tpg); } + init_completion(&tpg->tpg_base_comp); + schedule_work(&tpg->tpg_base_work); + wait_for_completion(&tpg->tpg_base_comp); + if (op) { + if (!atomic_read(&tpg->lport_tpg_enabled)) + return -ENODEV; + } else { + if (atomic_read(&tpg->lport_tpg_enabled)) + return -EPERM; + } return count; } @@ -1703,6 +1738,9 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, struct scsi_qla_host *npiv_vha; struct tcm_qla2xxx_lport *lport = (struct tcm_qla2xxx_lport *)target_lport_ptr; + struct tcm_qla2xxx_lport *base_lport = + (struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr; + struct tcm_qla2xxx_tpg *base_tpg; struct fc_vport_identifiers vport_id; if (!qla_tgt_mode_enabled(base_vha)) { @@ -1710,6 +1748,13 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, return -EPERM; } + if (!base_lport || !base_lport->tpg_1 || + !atomic_read(&base_lport->tpg_1->lport_tpg_enabled)) { + pr_err("qla2xxx base_lport or tpg_1 not available\n"); + return -EPERM; + } + base_tpg = base_lport->tpg_1; + memset(&vport_id, 0, sizeof(vport_id)); vport_id.port_name = npiv_wwpn; vport_id.node_name = npiv_wwnn; @@ -1728,7 +1773,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, npiv_vha = (struct scsi_qla_host *)vport->dd_data; npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr; lport->qla_vha = npiv_vha; - scsi_host_get(npiv_vha->host); return 0; } diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 275d8b9..a90966d 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -43,6 +43,9 @@ struct tcm_qla2xxx_tpg { struct tcm_qla2xxx_tpg_attrib tpg_attrib; /* Returned by tcm_qla2xxx_make_tpg() */ struct se_portal_group se_tpg; + /* Items for dealing with configfs_depend_item */ + struct completion tpg_base_comp; + struct work_struct tpg_base_work; }; struct tcm_qla2xxx_fc_loopid { -- cgit v0.10.2 From 84197a36e9d78213da17b96fb838afcca4e150ea Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 30 Jan 2014 09:52:21 -0800 Subject: tcm_qla2xxx: Fix NAA formatted name for NPIV WWPNs This patch fixes the NAA formatted name used by EVPD=0x83 device identifer to reflect the proper NPIV enabled WWPN. Cc: Sawan Chandak Cc: Quinn Tran Cc: Saurav Kashyap Cc: Giridhar Malavali Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 5bdc440..788c4fe 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -182,20 +182,6 @@ static int tcm_qla2xxx_npiv_parse_wwn( return 0; } -static ssize_t tcm_qla2xxx_npiv_format_wwn(char *buf, size_t len, - u64 wwpn, u64 wwnn) -{ - u8 b[8], b2[8]; - - put_unaligned_be64(wwpn, b); - put_unaligned_be64(wwnn, b2); - return snprintf(buf, len, - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x," - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", - b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], - b2[0], b2[1], b2[2], b2[3], b2[4], b2[5], b2[6], b2[7]); -} - static char *tcm_qla2xxx_npiv_get_fabric_name(void) { return "qla2xxx_npiv"; @@ -227,15 +213,6 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) return lport->lport_naa_name; } -static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - - return &lport->lport_npiv_name[0]; -} - static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg) { struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, @@ -1811,8 +1788,6 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( } lport->lport_npiv_wwpn = npiv_wwpn; lport->lport_npiv_wwnn = npiv_wwnn; - tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0], - TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); ret = tcm_qla2xxx_init_lport(lport); @@ -1921,7 +1896,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = { static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { .get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name, .get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident, - .tpg_get_wwn = tcm_qla2xxx_npiv_get_fabric_wwn, + .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, .tpg_get_tag = tcm_qla2xxx_get_tag, .tpg_get_default_depth = tcm_qla2xxx_get_default_depth, .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index a90966d..33aaac8 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -4,8 +4,6 @@ #define TCM_QLA2XXX_VERSION "v0.1" /* length of ASCII WWPNs including pad */ #define TCM_QLA2XXX_NAMELEN 32 -/* lenth of ASCII NPIV 'WWPN+WWNN' including pad */ -#define TCM_QLA2XXX_NPIV_NAMELEN 66 #include "qla_target.h" @@ -65,8 +63,6 @@ struct tcm_qla2xxx_lport { char lport_name[TCM_QLA2XXX_NAMELEN]; /* ASCII formatted naa WWPN for VPD page 83 etc */ char lport_naa_name[TCM_QLA2XXX_NAMELEN]; - /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */ - char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN]; /* map for fc_port pointers in 24-bit FC Port ID space */ struct btree_head32 lport_fcport_map; /* vmalloc-ed memory for fc_port pointers for 16-bit FC loop ID */ -- cgit v0.10.2 From acc3d5cec84f82ebea535fa0bd9500ac3df2aee9 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 20 Feb 2014 12:58:15 -0700 Subject: regulator: core: Change dummy supplies error message to a warning Change "dummy supplies not allowed" error message to warning instead, as this is a just warning message with no change to the behavior. [Added a CC to stable since some other bug fixes cause this to come up more frequently on PCs which is how it was noticed -- broonie] Signed-off-by: Shuah Khan Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b38a6b6..74e9fb2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1352,7 +1352,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, goto found; /* Don't log an error when called from regulator_get_optional() */ } else if (!have_full_constraints() || exclusive) { - dev_err(dev, "dummy supplies not allowed\n"); + dev_warn(dev, "dummy supplies not allowed\n"); } mutex_unlock(®ulator_list_mutex); -- cgit v0.10.2 From 4042e7570cff740460b75c6fc604c629621d3dd2 Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Wed, 12 Feb 2014 10:01:06 -0800 Subject: intel_pstate: Use LFM bus ratio as min ratio/P state LFM (max efficiency ratio) is the max frequency at minimum voltage supported by the processor. Using LFM as the minimum P state increases performmance without affecting power. By not using P states below LFM we avoid using P states that are less power efficient. Signed-off-by: Dirk Brandewie Cc: 3.13+ # 3.13+ Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index c788abf..deb04cc 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -357,7 +357,7 @@ static int byt_get_min_pstate(void) { u64 value; rdmsrl(BYT_RATIOS, value); - return value & 0xFF; + return (value >> 8) & 0xFF; } static int byt_get_max_pstate(void) -- cgit v0.10.2 From 61d8d2abc15e9232c3914c55502b73e559366583 Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Wed, 12 Feb 2014 10:01:07 -0800 Subject: intel_pstate: Add support for Baytrail turbo P states A documentation update exposed the existance of the turbo ratio register. Update baytrail support to use the turbo range. Signed-off-by: Dirk Brandewie Cc: 3.13+ # 3.13+ Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index deb04cc..e908161 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -34,8 +34,10 @@ #define SAMPLE_COUNT 3 -#define BYT_RATIOS 0x66a -#define BYT_VIDS 0x66b +#define BYT_RATIOS 0x66a +#define BYT_VIDS 0x66b +#define BYT_TURBO_RATIOS 0x66c + #define FRAC_BITS 8 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) @@ -367,6 +369,13 @@ static int byt_get_max_pstate(void) return (value >> 16) & 0xFF; } +static int byt_get_turbo_pstate(void) +{ + u64 value; + rdmsrl(BYT_TURBO_RATIOS, value); + return value & 0x3F; +} + static void byt_set_pstate(struct cpudata *cpudata, int pstate) { u64 val; @@ -469,7 +478,7 @@ static struct cpu_defaults byt_params = { .funcs = { .get_max = byt_get_max_pstate, .get_min = byt_get_min_pstate, - .get_turbo = byt_get_max_pstate, + .get_turbo = byt_get_turbo_pstate, .set = byt_set_pstate, .get_vid = byt_get_vid, }, -- cgit v0.10.2 From 423edb6fce67133d4524513954af943a75bb6ef5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Feb 2014 13:15:28 +0100 Subject: s390/compat: fix sys_sched_getattr compat wrapper Fix stupid typo. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 59c8efc..0248949 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1421,5 +1421,5 @@ ENTRY(sys_sched_setattr_wrapper) ENTRY(sys_sched_getattr_wrapper) lgfr %r2,%r2 # pid_t llgtr %r3,%r3 # const char __user * - llgfr %r3,%r3 # unsigned int + llgfr %r4,%r4 # unsigned int jg sys_sched_getattr -- cgit v0.10.2 From 5ec6d4918a45952e99b1b36c93372d79d6927c57 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Tue, 18 Feb 2014 19:47:17 +0100 Subject: s390/pci/dma: use correct segment boundary size The boundary size for iommu_area_alloc() is currently set to a constant value. This is wrong, we shouldn't use a constant value but rather the return value of dma_get_seg_boundary(), since a device driver can override the default. Reviewed-by: Sebastian Ott Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 60c11a6..f91c031 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -206,11 +206,13 @@ static void dma_cleanup_tables(struct zpci_dev *zdev) zdev->dma_table = NULL; } -static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, unsigned long start, - int size) +static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, + unsigned long start, int size) { - unsigned long boundary_size = 0x1000000; + unsigned long boundary_size; + boundary_size = ALIGN(dma_get_seg_boundary(&zdev->pdev->dev) + 1, + PAGE_SIZE) >> PAGE_SHIFT; return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages, start, size, 0, boundary_size, 0); } -- cgit v0.10.2 From 9955e8d15f53e53540aaed7bcef640142e65e900 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 19 Feb 2014 17:43:04 +0100 Subject: s390/cio: Fix missing subchannels after CHPID configure on Performing a Channel-Path configure on operation on a Channel-Path ID (CHPID) does not trigger a scan for subchannels that might have become available through that CHPID. As a result, some subchannels and associated I/O devices might be missing. Fix this by adding the missing scan. This problem was introduced by commit c820de39, "[S390] cio: Rework css driver.", but wasn't noticed earlier because the machine usually also generates a Channel-Report-Word when the first CHPID of a subchannel is configured on, resulting in a separate scan for that subchannel. The problem only becomes apparent when this first CHPID is not working properly and additional working CHPIDs are subsequently configured on without any effect on the availability of the affected subchannel. Reviewed-by: Sebastian Ott Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index f6b9188..9f0ea6c 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -610,6 +610,7 @@ void chsc_chp_online(struct chp_id chpid) css_wait_for_slow_path(); for_each_subchannel_staged(__s390_process_res_acc, NULL, &link); + css_schedule_reprobe(); } } -- cgit v0.10.2 From b3634575930857724d5c3987a2739b0637999b4e Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 18 Feb 2014 17:02:54 +0100 Subject: ARM: 7980/1: kernel: improve error message when LPAE config doesn't match CPU Currently, when the kernel is configured with LPAE support, but the CPU doesn't support it, the error message is fairly cryptic: Error: unrecognized/unsupported processor variant (0x561f5811). This messages is normally shown when there is an issue when comparing the processor ID (CP15 0, c0, c0) with the values/masks described in proc-v7.S. However, the same message is displayed when LPAE support is enabled in the kernel configuration, but not available in the CPU, after looking at ID_MMFR0 (CP15 0, c0, c1, 4). Having the same error message is highly misleading. This commit improves this by showing a different error message when this situation occurs: Error: Kernel with LPAE support, but CPU does not support LPAE. Signed-off-by: Thomas Petazzoni Signed-off-by: Russell King diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 47cd974..c96ecac 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -177,6 +177,18 @@ __lookup_processor_type_data: .long __proc_info_end .size __lookup_processor_type_data, . - __lookup_processor_type_data +__error_lpae: +#ifdef CONFIG_DEBUG_LL + adr r0, str_lpae + bl printascii + b __error +str_lpae: .asciz "\nError: Kernel with LPAE support, but CPU does not support LPAE.\n" +#else + b __error +#endif + .align +ENDPROC(__error_lpae) + __error_p: #ifdef CONFIG_DEBUG_LL adr r0, str_p1 diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 914616e..f5f381d 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -102,7 +102,7 @@ ENTRY(stext) and r3, r3, #0xf @ extract VMSA support cmp r3, #5 @ long-descriptor translation table format? THUMB( it lo ) @ force fixup-able long branch encoding - blo __error_p @ only classic page table format + blo __error_lpae @ only classic page table format #endif #ifndef CONFIG_XIP_KERNEL -- cgit v0.10.2 From fd694131bb033e7b1fd748498cd9a70e9c16420b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 20 Feb 2014 15:32:36 -0800 Subject: blk-mq: remove blk_mq_alloc_rq There's only one caller, which is a straight wrapper and fits the naming scheme of the related functions a lot better. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index 1fa9dd1..1e585e3 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -73,8 +73,8 @@ static void blk_mq_hctx_mark_pending(struct blk_mq_hw_ctx *hctx, set_bit(ctx->index_hw, hctx->ctx_map); } -static struct request *blk_mq_alloc_rq(struct blk_mq_hw_ctx *hctx, gfp_t gfp, - bool reserved) +static struct request *__blk_mq_alloc_request(struct blk_mq_hw_ctx *hctx, + gfp_t gfp, bool reserved) { struct request *rq; unsigned int tag; @@ -193,12 +193,6 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, ctx->rq_dispatched[rw_is_sync(rw_flags)]++; } -static struct request *__blk_mq_alloc_request(struct blk_mq_hw_ctx *hctx, - gfp_t gfp, bool reserved) -{ - return blk_mq_alloc_rq(hctx, gfp, reserved); -} - static struct request *blk_mq_alloc_request_pinned(struct request_queue *q, int rw, gfp_t gfp, bool reserved) -- cgit v0.10.2 From feb71dae1f9e0aeb056f7f639a21e620d327fc66 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 20 Feb 2014 15:32:37 -0800 Subject: blk-mq: merge blk_mq_insert_request and blk_mq_run_request It's almost identical to blk_mq_insert_request, so fold the two into one slightly more generic function by making the flush special case a bit smarted. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-exec.c b/block/blk-exec.c index c68613b..dbf4502 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -65,7 +65,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, * be resued after dying flag is set */ if (q->mq_ops) { - blk_mq_insert_request(q, rq, at_head, true); + blk_mq_insert_request(rq, at_head, true, false); return; } diff --git a/block/blk-flush.c b/block/blk-flush.c index 66e2b69..f598f79 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -137,7 +137,7 @@ static void mq_flush_run(struct work_struct *work) rq = container_of(work, struct request, mq_flush_work); memset(&rq->csd, 0, sizeof(rq->csd)); - blk_mq_run_request(rq, true, false); + blk_mq_insert_request(rq, false, true, false); } static bool blk_flush_queue_rq(struct request *rq) @@ -411,7 +411,7 @@ void blk_insert_flush(struct request *rq) if ((policy & REQ_FSEQ_DATA) && !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { if (q->mq_ops) { - blk_mq_run_request(rq, false, true); + blk_mq_insert_request(rq, false, false, true); } else list_add_tail(&rq->queuelist, &q->queue_head); return; diff --git a/block/blk-mq.c b/block/blk-mq.c index 1e585e3..2af8405 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -724,61 +724,28 @@ static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, blk_mq_add_timer(rq); } -void blk_mq_insert_request(struct request_queue *q, struct request *rq, - bool at_head, bool run_queue) +void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue, + bool async) { + struct request_queue *q = rq->q; struct blk_mq_hw_ctx *hctx; - struct blk_mq_ctx *ctx, *current_ctx; + struct blk_mq_ctx *ctx = rq->mq_ctx, *current_ctx; + + current_ctx = blk_mq_get_ctx(q); + if (!cpu_online(ctx->cpu)) + rq->mq_ctx = ctx = current_ctx; - ctx = rq->mq_ctx; hctx = q->mq_ops->map_queue(q, ctx->cpu); - if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) { + if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA) && + !(rq->cmd_flags & (REQ_FLUSH_SEQ))) { blk_insert_flush(rq); } else { - current_ctx = blk_mq_get_ctx(q); - - if (!cpu_online(ctx->cpu)) { - ctx = current_ctx; - hctx = q->mq_ops->map_queue(q, ctx->cpu); - rq->mq_ctx = ctx; - } spin_lock(&ctx->lock); __blk_mq_insert_request(hctx, rq, at_head); spin_unlock(&ctx->lock); - - blk_mq_put_ctx(current_ctx); } - if (run_queue) - __blk_mq_run_hw_queue(hctx); -} -EXPORT_SYMBOL(blk_mq_insert_request); - -/* - * This is a special version of blk_mq_insert_request to bypass FLUSH request - * check. Should only be used internally. - */ -void blk_mq_run_request(struct request *rq, bool run_queue, bool async) -{ - struct request_queue *q = rq->q; - struct blk_mq_hw_ctx *hctx; - struct blk_mq_ctx *ctx, *current_ctx; - - current_ctx = blk_mq_get_ctx(q); - - ctx = rq->mq_ctx; - if (!cpu_online(ctx->cpu)) { - ctx = current_ctx; - rq->mq_ctx = ctx; - } - hctx = q->mq_ops->map_queue(q, ctx->cpu); - - /* ctx->cpu might be offline */ - spin_lock(&ctx->lock); - __blk_mq_insert_request(hctx, rq, false); - spin_unlock(&ctx->lock); - blk_mq_put_ctx(current_ctx); if (run_queue) diff --git a/block/blk-mq.h b/block/blk-mq.h index ed0035c..72beba1 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -23,7 +23,6 @@ struct blk_mq_ctx { }; void __blk_mq_complete_request(struct request *rq); -void blk_mq_run_request(struct request *rq, bool run_queue, bool async); void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async); void blk_mq_init_flush(struct request_queue *q); void blk_mq_drain_queue(struct request_queue *q); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 18ba8a6..ff28fe3 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -121,8 +121,7 @@ void blk_mq_init_commands(struct request_queue *, void (*init)(void *data, struc void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule); -void blk_mq_insert_request(struct request_queue *, struct request *, - bool, bool); +void blk_mq_insert_request(struct request *, bool, bool, bool); void blk_mq_run_queues(struct request_queue *q, bool async); void blk_mq_free_request(struct request *rq); bool blk_mq_can_queue(struct blk_mq_hw_ctx *); -- cgit v0.10.2 From d6a25b31315327eef7785b895c354cc45c3f3742 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 20 Feb 2014 15:32:38 -0800 Subject: blk-mq: support partial I/O completions Add a new blk_mq_end_io_partial function to partially complete requests as needed by the SCSI layer. We do this by reusing blk_update_request to advance the bio instead of having a simplified version of it in the blk-mq code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index 2af8405..1b8b50d 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -283,38 +283,10 @@ void blk_mq_free_request(struct request *rq) __blk_mq_free_request(hctx, ctx, rq); } -static void blk_mq_bio_endio(struct request *rq, struct bio *bio, int error) +bool blk_mq_end_io_partial(struct request *rq, int error, unsigned int nr_bytes) { - if (error) - clear_bit(BIO_UPTODATE, &bio->bi_flags); - else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - error = -EIO; - - if (unlikely(rq->cmd_flags & REQ_QUIET)) - set_bit(BIO_QUIET, &bio->bi_flags); - - /* don't actually finish bio if it's part of flush sequence */ - if (!(rq->cmd_flags & REQ_FLUSH_SEQ)) - bio_endio(bio, error); -} - -void blk_mq_end_io(struct request *rq, int error) -{ - struct bio *bio = rq->bio; - unsigned int bytes = 0; - - trace_block_rq_complete(rq->q, rq); - - while (bio) { - struct bio *next = bio->bi_next; - - bio->bi_next = NULL; - bytes += bio->bi_iter.bi_size; - blk_mq_bio_endio(rq, bio, error); - bio = next; - } - - blk_account_io_completion(rq, bytes); + if (blk_update_request(rq, error, blk_rq_bytes(rq))) + return true; blk_account_io_done(rq); @@ -322,8 +294,9 @@ void blk_mq_end_io(struct request *rq, int error) rq->end_io(rq, error); else blk_mq_free_request(rq); + return false; } -EXPORT_SYMBOL(blk_mq_end_io); +EXPORT_SYMBOL(blk_mq_end_io_partial); static void __blk_mq_complete_request_remote(void *data) { diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index ff28fe3..2ff2e8d 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -133,7 +133,13 @@ struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_ind struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_reg *, unsigned int); void blk_mq_free_single_hw_queue(struct blk_mq_hw_ctx *, unsigned int); -void blk_mq_end_io(struct request *rq, int error); +bool blk_mq_end_io_partial(struct request *rq, int error, + unsigned int nr_bytes); +static inline void blk_mq_end_io(struct request *rq, int error) +{ + bool done = !blk_mq_end_io_partial(rq, error, blk_rq_bytes(rq)); + BUG_ON(!done); +} void blk_mq_complete_request(struct request *rq); -- cgit v0.10.2 From e9d6dca51823b94e1ca28cb5e9180701d4375d61 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 31 Jan 2014 05:38:21 +0400 Subject: xtensa: don't pass high memory to bootmem allocator This fixes panic when booting on machine with more than 128M memory passed from the bootloader. Signed-off-by: Max Filippov diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 479d753..aff108d 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -90,7 +90,7 @@ int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) /* - * Initialize the bootmem system and give it all the memory we have available. + * Initialize the bootmem system and give it all low memory we have available. */ void __init bootmem_init(void) @@ -142,9 +142,14 @@ void __init bootmem_init(void) /* Add all remaining memory pieces into the bootmem map */ - for (i=0; i> PAGE_SHIFT < max_low_pfn) { + unsigned long end = min(max_low_pfn << PAGE_SHIFT, + sysmem.bank[i].end); + free_bootmem(sysmem.bank[i].start, + end - sysmem.bank[i].start); + } + } } -- cgit v0.10.2 From 8e9356c6146d0bb81a6ffb02eae522e57ff29662 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 7 Feb 2014 11:09:52 +0400 Subject: xtensa: fsf: drop nonexistent GPIO32 support The toolchain for xtensa FSF core never supported GPIO32, drop it on the linux side too. Reported-by: Fengguang Wu Signed-off-by: Max Filippov Acked-by: Baruch Siach diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index ba56e11..1cfb3d5 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -80,7 +80,6 @@ choice config XTENSA_VARIANT_FSF bool "fsf - default (not generic) configuration" select MMU - select HAVE_XTENSA_GPIO32 config XTENSA_VARIANT_DC232B bool "dc232b - Diamond 232L Standard Core Rev.B (LE)" diff --git a/arch/xtensa/variants/fsf/include/variant/tie.h b/arch/xtensa/variants/fsf/include/variant/tie.h index bf40201..244cdea 100644 --- a/arch/xtensa/variants/fsf/include/variant/tie.h +++ b/arch/xtensa/variants/fsf/include/variant/tie.h @@ -18,13 +18,6 @@ #define XCHAL_CP_MASK 0x00 /* bitmask of all CPs by ID */ #define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP7_NAME "XTIOP" -#define XCHAL_CP7_IDENT XTIOP -#define XCHAL_CP7_SA_SIZE 0 /* size of state save area */ -#define XCHAL_CP7_SA_ALIGN 1 /* min alignment of save area */ -#define XCHAL_CP_ID_XTIOP 7 /* coprocessor ID (0..7) */ - /* Filler info for unassigned coprocessors, to simplify arrays etc: */ #define XCHAL_NCP_SA_SIZE 0 #define XCHAL_NCP_SA_ALIGN 1 @@ -42,6 +35,8 @@ #define XCHAL_CP5_SA_ALIGN 1 #define XCHAL_CP6_SA_SIZE 0 #define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 /* Save area for non-coprocessor optional and custom (TIE) state: */ #define XCHAL_NCP_SA_SIZE 0 -- cgit v0.10.2 From 4e3b4df839b550aec463945b10141c65c69f5135 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 9 Feb 2014 15:45:06 +0100 Subject: xtensa: no need to select USE_GENERIC_SMP_HELPERS Commit f615136c06a7 ("xtensa: add SMP support") added "select USE_GENERIC_SMP_HELPERS". But the Kconfig symbol USE_GENERIC_SMP_HELPERS was already removed in v3.13, so that select is a nop. Drop it. Signed-off-by: Paul Bolle Signed-off-by: Max Filippov diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 1cfb3d5..44f1152 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -134,7 +134,6 @@ config HAVE_SMP config SMP bool "Enable Symmetric multi-processing support" depends on HAVE_SMP - select USE_GENERIC_SMP_HELPERS select GENERIC_SMP_IDLE_THREAD help Enabled SMP Software; allows more than one CPU/CORE -- cgit v0.10.2 From bda8932d234aeaee870ac666e776a5ba03bb13a4 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 29 Jan 2014 06:20:46 +0400 Subject: xtensa: support common clock framework Signed-off-by: Max Filippov diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 44f1152..c87ae7c 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -20,6 +20,7 @@ config XTENSA select HAVE_FUNCTION_TRACER select HAVE_IRQ_TIME_ACCOUNTING select HAVE_PERF_EVENTS + select COMMON_CLK help Xtensa processors are 32-bit RISC machines designed by Tensilica primarily for embedded systems. These processors are both diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 7d12af1..84fe931 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,7 @@ void __init early_init_devtree(void *params) static int __init xtensa_device_probe(void) { + of_clk_init(NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); return 0; } -- cgit v0.10.2 From cdc9af7ccfc26d35ff8a29dded2cc2c096c0fc1e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 29 Jan 2014 07:42:46 +0400 Subject: xtensa: xtfpga: use common clock framework With this change the board needs to set up single clock object, users of this clock will get correct frequency automatically. Signed-off-by: Max Filippov diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi index 46b4f5e..d5ccbbb 100644 --- a/arch/xtensa/boot/dts/xtfpga.dtsi +++ b/arch/xtensa/boot/dts/xtfpga.dtsi @@ -35,6 +35,13 @@ interrupt-controller; }; + clocks { + osc: main-oscillator { + #clock-cells = <0>; + compatible = "fixed-clock"; + }; + }; + serial0: serial@fd050020 { device_type = "serial"; compatible = "ns16550a"; @@ -42,9 +49,7 @@ reg = <0xfd050020 0x20>; reg-shift = <2>; interrupts = <0 1>; /* external irq 0 */ - /* Filled in by platform_setup from FPGA register - * clock-frequency = <100000000>; - */ + clocks = <&osc>; }; enet0: ethoc@fd030000 { diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 8002278..0372913 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -135,11 +135,11 @@ static void __init update_local_mac(struct device_node *node) static int __init machine_setup(void) { - struct device_node *serial; + struct device_node *clock; struct device_node *eth = NULL; - for_each_compatible_node(serial, NULL, "ns16550a") - update_clock_frequency(serial); + for_each_node_by_name(clock, "main-oscillator") + update_clock_frequency(clock); if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc"))) update_local_mac(eth); -- cgit v0.10.2 From 2bc2fde63858322a942864bf6cb2d54f5aa33186 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 29 Jan 2014 07:53:44 +0400 Subject: xtensa: xtfpga: set ethoc clock frequency Connect xtfpga board ethernet MAC to the clock in the DTS. Set up MAC base frequency in the platform data in case of build w/o CONFIG_OF. Signed-off-by: Max Filippov diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi index d5ccbbb..e7370b1 100644 --- a/arch/xtensa/boot/dts/xtfpga.dtsi +++ b/arch/xtensa/boot/dts/xtfpga.dtsi @@ -57,5 +57,6 @@ reg = <0xfd030000 0x4000 0xfd800000 0x4000>; interrupts = <1 1>; /* external irq 1 */ local-mac-address = [00 50 c2 13 6f 00]; + clocks = <&osc>; }; }; diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 0372913..57fd08b 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -290,6 +290,7 @@ static int __init xtavnet_init(void) * knows whether they set it correctly on the DIP switches. */ pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr); + ethoc_pdata.eth_clkfreq = *(long *)XTFPGA_CLKFRQ_VADDR; return 0; } -- cgit v0.10.2 From f63b6d7555cd4064554b39da4d44c4cbbc9d6a4a Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 18 Feb 2014 16:00:05 +0400 Subject: xtensa: wire up sched_setattr and sched_getattr syscalls Signed-off-by: Max Filippov diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index 51940fe..b939552 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h @@ -734,7 +734,12 @@ __SYSCALL(332, sys_finit_module, 3) #define __NR_accept4 333 __SYSCALL(333, sys_accept4, 4) -#define __NR_syscall_count 334 +#define __NR_sched_setattr 334 +__SYSCALL(334, sys_sched_setattr, 2) +#define __NR_sched_getattr 335 +__SYSCALL(335, sys_sched_getattr, 3) + +#define __NR_syscall_count 336 /* * sysxtensa syscall handler -- cgit v0.10.2 From 0cb1c3e853e0d0f996f4e11863407bf31e6b7343 Mon Sep 17 00:00:00 2001 From: Stanislav Kholmanskikh Date: Mon, 27 Jan 2014 11:04:33 +0400 Subject: watchdog: w83697hf_wdt: return ENODEV if no device was found Most WDT driver modules return ENODEV during modprobe if no valid device was found, but w83697hf_wdt returns EIO. Let w83697hf_wdt return ENODEV. Signed-off-by: Stanislav Kholmanskikh Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c index aaf2995..68b45fc 100644 --- a/drivers/watchdog/w83697hf_wdt.c +++ b/drivers/watchdog/w83697hf_wdt.c @@ -402,7 +402,7 @@ static int __init wdt_init(void) if (!found) { pr_err("No W83697HF/HG could be found\n"); - ret = -EIO; + ret = -ENODEV; goto out; } -- cgit v0.10.2 From 3d5f35bdfdef5fd627afe9b4bf9c4f32d17f4593 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Thu, 20 Feb 2014 09:19:39 +0100 Subject: sched/deadline: Fix bad accounting of nr_running Rostedt writes: My test suite was locking up hard when enabling mmiotracer. This was due to the mmiotracer placing all but one CPU offline. I found this out when I was able to reproduce the bug with just my stress-cpu-hotplug test. This bug baffled me because it would not always trigger, and would only trigger on the first run after boot up. The stress-cpu-hotplug test would crash hard the first run, or never crash at all. But a new reboot may cause it to crash on the first run again. I spent all week bisecting this, as I couldn't find a consistent reproducer. I finally narrowed it down to the sched deadline patches, and even more peculiar, to the commit that added the sched deadline boot up self test to the latency tracer. Then it dawned on me to what the bug was. All it took was to run a task under sched deadline to screw up the CPU hot plugging. This explained why it would lock up only on the first run of the stress-cpu-hotplug test. The bug happened when the boot up self test of the schedule latency tracer would test a deadline task. The deadline task would corrupt something that would cause CPU hotplug to fail. If it didn't corrupt it, the stress test would always work (there's no other sched deadline tasks that would run to cause problems). If it did corrupt on boot up, the first test would lockup hard. I proved this theory by running my deadline test program on another box, and then run the stress-cpu-hotplug test, and it would now consistently lock up. I could run stress-cpu-hotplug over and over with no problem, but once I ran the deadline test, the next run of the stress-cpu-hotplug would lock hard. After adding lots of tracing to the code, I found the cause. The function tracer showed that migrate_tasks() was stuck in an infinite loop, where rq->nr_running never equaled 1 to break out of it. When I added a trace_printk() to see what that number was, it was 335 and never decrementing! Looking at the deadline code I found: static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) { dequeue_dl_entity(&p->dl); dequeue_pushable_dl_task(rq, p); } static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) { update_curr_dl(rq); __dequeue_task_dl(rq, p, flags); dec_nr_running(rq); } And this: if (dl_runtime_exceeded(rq, dl_se)) { __dequeue_task_dl(rq, curr, 0); if (likely(start_dl_timer(dl_se, curr->dl.dl_boosted))) dl_se->dl_throttled = 1; else enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH); if (!is_leftmost(curr, &rq->dl)) resched_task(curr); } Notice how we call __dequeue_task_dl() and in the else case we call enqueue_task_dl()? Also notice that dequeue_task_dl() has underscores where enqueue_task_dl() does not. The enqueue_task_dl() calls inc_nr_running(rq), but __dequeue_task_dl() does not. This is where we get nr_running out of sync. [snip] Another point where nr_running can get out of sync is when the dl_timer fires: dl_se->dl_throttled = 0; if (p->on_rq) { enqueue_task_dl(rq, p, ENQUEUE_REPLENISH); if (task_has_dl_policy(rq->curr)) check_preempt_curr_dl(rq, p, 0); else resched_task(rq->curr); This patch does two things: - correctly accounts for throttled tasks (that are now considered !running); - fixes the bug, updating nr_running from {inc,dec}_dl_tasks(), since we risk to update it twice in some situations (e.g., a task is dequeued while it has exceeded its budget). Cc: mingo@redhat.com Cc: torvalds@linux-foundation.org Cc: akpm@linux-foundation.org Reported-by: Steven Rostedt Reviewed-by: Steven Rostedt Tested-by: Steven Rostedt Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392884379-13744-1-git-send-email-juri.lelli@gmail.com Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 0dd5e09..b819577 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -717,6 +717,7 @@ void inc_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) WARN_ON(!dl_prio(prio)); dl_rq->dl_nr_running++; + inc_nr_running(rq_of_dl_rq(dl_rq)); inc_dl_deadline(dl_rq, deadline); inc_dl_migration(dl_se, dl_rq); @@ -730,6 +731,7 @@ void dec_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) WARN_ON(!dl_prio(prio)); WARN_ON(!dl_rq->dl_nr_running); dl_rq->dl_nr_running--; + dec_nr_running(rq_of_dl_rq(dl_rq)); dec_dl_deadline(dl_rq, dl_se->deadline); dec_dl_migration(dl_se, dl_rq); @@ -836,8 +838,6 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) if (!task_current(rq, p) && p->nr_cpus_allowed > 1) enqueue_pushable_dl_task(rq, p); - - inc_nr_running(rq); } static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) @@ -850,8 +850,6 @@ static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) { update_curr_dl(rq); __dequeue_task_dl(rq, p, flags); - - dec_nr_running(rq); } /* -- cgit v0.10.2 From 4df1638cfaf9b2b7ad993979a41965acab9cd156 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 19 Feb 2014 13:53:35 -0500 Subject: sched/deadline: Fix overflow to handle period==0 and deadline!=0 While debugging the crash with the bad nr_running accounting, I hit another bug where, after running my sched deadline test, I was getting failures to take a CPU offline. It was giving me a -EBUSY error. Adding a bunch of trace_printk()s around, I found that the cpu notifier that called sched_cpu_inactive() was returning a failure. The overflow value was coming up negative? Talking this over with Juri, the problem is that the total_bw update was suppose to be made by dl_overflow() which, during my tests, seemed to not be called. Adding more trace_printk()s, it wasn't that it wasn't called, but it exited out right away with the check of new_bw being equal to p->dl.dl_bw. The new_bw calculates the ratio between period and runtime. The bug is that if you set a deadline, you do not need to set a period if you plan on the period being equal to the deadline. That is, if period is zero and deadline is not, then the system call should set the period to be equal to the deadline. This is done elsewhere in the code. The fix is easy, check if period is set, and if it is not, then use the deadline. Cc: Juri Lelli Cc: Ingo Molnar Cc: Linus Torvalds Cc: Andrew Morton Signed-off-by: Steven Rostedt Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140219135335.7e74abd4@gandalf.local.home Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b46131e..2491448 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1952,7 +1952,7 @@ static int dl_overflow(struct task_struct *p, int policy, { struct dl_bw *dl_b = dl_bw_of(task_cpu(p)); - u64 period = attr->sched_period; + u64 period = attr->sched_period ?: attr->sched_deadline; u64 runtime = attr->sched_runtime; u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0; int cpus, err = -1; -- cgit v0.10.2 From e9e7cb38c21c80c82af4b16608bb4c8c5ec6a28e Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Tue, 11 Feb 2014 09:24:26 +0100 Subject: sched/core: Fix sched_rt_global_validate Don't compare sysctl_sched_rt_runtime against sysctl_sched_rt_period if the former is equal to RUNTIME_INF, otherwise disabling -rt bandwidth management (with CONFIG_RT_GROUP_SCHED=n) fails. Cc: Ingo Molnar Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392107067-19907-2-git-send-email-juri.lelli@gmail.com Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2491448..98d33c1 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7475,7 +7475,8 @@ static int sched_rt_global_validate(void) if (sysctl_sched_rt_period <= 0) return -EINVAL; - if (sysctl_sched_rt_runtime > sysctl_sched_rt_period) + if ((sysctl_sched_rt_runtime != RUNTIME_INF) && + (sysctl_sched_rt_runtime > sysctl_sched_rt_period)) return -EINVAL; return 0; -- cgit v0.10.2 From 495163420ab5398c84af96ca3eae2c6aa4a140da Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Tue, 11 Feb 2014 09:24:27 +0100 Subject: sched/core: Make dl_b->lock IRQ safe Fix this lockdep warning: [ 44.804600] ========================================================= [ 44.805746] [ INFO: possible irq lock inversion dependency detected ] [ 44.805746] 3.14.0-rc2-test+ #14 Not tainted [ 44.805746] --------------------------------------------------------- [ 44.805746] bash/3674 just changed the state of lock: [ 44.805746] (&dl_b->lock){+.....}, at: [] sched_rt_handler+0x132/0x248 [ 44.805746] but this lock was taken by another, HARDIRQ-safe lock in the past: [ 44.805746] (&rq->lock){-.-.-.} and interrupts could create inverse lock ordering between them. [ 44.805746] [ 44.805746] other info that might help us debug this: [ 44.805746] Possible interrupt unsafe locking scenario: [ 44.805746] [ 44.805746] CPU0 CPU1 [ 44.805746] ---- ---- [ 44.805746] lock(&dl_b->lock); [ 44.805746] local_irq_disable(); [ 44.805746] lock(&rq->lock); [ 44.805746] lock(&dl_b->lock); [ 44.805746] [ 44.805746] lock(&rq->lock); by making dl_b->lock acquiring always IRQ safe. Cc: Ingo Molnar Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392107067-19907-3-git-send-email-juri.lelli@gmail.com Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 98d33c1..33d030a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7422,6 +7422,7 @@ static int sched_dl_global_constraints(void) u64 period = global_rt_period(); u64 new_bw = to_ratio(period, runtime); int cpu, ret = 0; + unsigned long flags; /* * Here we want to check the bandwidth not being set to some @@ -7435,10 +7436,10 @@ static int sched_dl_global_constraints(void) for_each_possible_cpu(cpu) { struct dl_bw *dl_b = dl_bw_of(cpu); - raw_spin_lock(&dl_b->lock); + raw_spin_lock_irqsave(&dl_b->lock, flags); if (new_bw < dl_b->total_bw) ret = -EBUSY; - raw_spin_unlock(&dl_b->lock); + raw_spin_unlock_irqrestore(&dl_b->lock, flags); if (ret) break; @@ -7451,6 +7452,7 @@ static void sched_dl_do_global(void) { u64 new_bw = -1; int cpu; + unsigned long flags; def_dl_bandwidth.dl_period = global_rt_period(); def_dl_bandwidth.dl_runtime = global_rt_runtime(); @@ -7464,9 +7466,9 @@ static void sched_dl_do_global(void) for_each_possible_cpu(cpu) { struct dl_bw *dl_b = dl_bw_of(cpu); - raw_spin_lock(&dl_b->lock); + raw_spin_lock_irqsave(&dl_b->lock, flags); dl_b->bw = new_bw; - raw_spin_unlock(&dl_b->lock); + raw_spin_unlock_irqrestore(&dl_b->lock, flags); } } -- cgit v0.10.2 From 3cf1962cdbf6b3a9e3ef21116d215bbab350ea37 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Tue, 18 Feb 2014 17:12:44 -0500 Subject: sched,numa: add cond_resched to task_numa_work Normally task_numa_work scans over a fairly small amount of memory, but it is possible to run into a large unpopulated part of virtual memory, with no pages mapped. In that case, task_numa_work can run for a while, and it may make sense to reschedule as required. Cc: akpm@linux-foundation.org Cc: Andrea Arcangeli Signed-off-by: Rik van Riel Reported-by: Xing Gang Tested-by: Chegu Vinod Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392761566-24834-2-git-send-email-riel@redhat.com Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 966cc2b..7815709 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1757,6 +1757,8 @@ void task_numa_work(struct callback_head *work) start = end; if (pages <= 0) goto out; + + cond_resched(); } while (end != vma->vm_end); } -- cgit v0.10.2 From 4efbc454ba68def5ef285b26ebfcfdb605b52755 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Sun, 16 Feb 2014 22:24:17 +0100 Subject: sched: Fix information leak in sys_sched_getattr() We're copying the on-stack structure to userspace, but forgot to give the right number of bytes to copy. This allows the calling process to obtain up to PAGE_SIZE bytes from the stack (and possibly adjacent kernel memory). This fix copies only as much as we actually have on the stack (attr->size defaults to the size of the struct) and leaves the rest of the userspace-provided buffer untouched. Found using kmemcheck + trinity. Fixes: d50dde5a10f30 ("sched: Add new scheduler syscalls to support an extended scheduling parameters ABI") Cc: Dario Faggioli Cc: Juri Lelli Cc: Ingo Molnar Signed-off-by: Vegard Nossum Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392585857-10725-1-git-send-email-vegard.nossum@oracle.com Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 33d030a..a6e7470 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3786,7 +3786,7 @@ static int sched_read_attr(struct sched_attr __user *uattr, attr->size = usize; } - ret = copy_to_user(uattr, attr, usize); + ret = copy_to_user(uattr, attr, attr->size); if (ret) return -EFAULT; -- cgit v0.10.2 From 6d35ab48090b10c5ea5604ed5d6e91f302dc6060 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 14 Feb 2014 17:19:29 +0100 Subject: sched: Add 'flags' argument to sched_{set,get}attr() syscalls Because of a recent syscall design debate; its deemed appropriate for each syscall to have a flags argument for future extension; without immediately requiring new syscalls. Cc: juri.lelli@gmail.com Cc: Ingo Molnar Suggested-by: Michael Kerrisk Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140214161929.GL27965@twins.programming.kicks-ass.net Signed-off-by: Thomas Gleixner diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 40ed9e9..a747a77 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -281,13 +281,15 @@ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param __user *param); asmlinkage long sys_sched_setattr(pid_t pid, - struct sched_attr __user *attr); + struct sched_attr __user *attr, + unsigned int flags); asmlinkage long sys_sched_getscheduler(pid_t pid); asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param __user *param); asmlinkage long sys_sched_getattr(pid_t pid, struct sched_attr __user *attr, - unsigned int size); + unsigned int size, + unsigned int flags); asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long __user *user_mask_ptr); asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a6e7470..6edbef2 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3661,13 +3661,14 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) * @pid: the pid in question. * @uattr: structure containing the extended parameters. */ -SYSCALL_DEFINE2(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr) +SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, + unsigned int, flags) { struct sched_attr attr; struct task_struct *p; int retval; - if (!uattr || pid < 0) + if (!uattr || pid < 0 || flags) return -EINVAL; if (sched_copy_attr(uattr, &attr)) @@ -3804,8 +3805,8 @@ err_size: * @uattr: structure containing the extended parameters. * @size: sizeof(attr) for fwd/bwd comp. */ -SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, - unsigned int, size) +SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, + unsigned int, size, unsigned int, flags) { struct sched_attr attr = { .size = sizeof(struct sched_attr), @@ -3814,7 +3815,7 @@ SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, int retval; if (!uattr || pid < 0 || size > PAGE_SIZE || - size < SCHED_ATTR_SIZE_VER0) + size < SCHED_ATTR_SIZE_VER0 || flags) return -EINVAL; rcu_read_lock(); -- cgit v0.10.2 From 82b95800b256205cff2eeab5bbd03430d2d0f20d Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Mon, 17 Feb 2014 09:12:33 -0500 Subject: sched/deadline: Test for CPU's presence explicitly A hot-removed CPU may have ID that is numerically larger than the number of existing CPUs in the system (e.g. we can unplug CPU 4 from a system that has CPUs 0, 1 and 4). Thus the WARN_ONs should check whether the CPU in question is currently present, not whether its ID value is less than num_present_cpus(). Cc: Ingo Molnar Cc: Juri Lelli Cc: Steven Rostedt Reported-by: Konrad Rzeszutek Wilk Signed-off-by: Boris Ostrovsky Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392646353-1874-1-git-send-email-boris.ostrovsky@oracle.com Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index 045fc74..5b8838b 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -70,7 +70,7 @@ static void cpudl_heapify(struct cpudl *cp, int idx) static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl) { - WARN_ON(idx > num_present_cpus() || idx == IDX_INVALID); + WARN_ON(!cpu_present(idx) || idx == IDX_INVALID); if (dl_time_before(new_dl, cp->elements[idx].dl)) { cp->elements[idx].dl = new_dl; @@ -117,7 +117,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p, } out: - WARN_ON(best_cpu > num_present_cpus() && best_cpu != -1); + WARN_ON(!cpu_present(best_cpu) && best_cpu != -1); return best_cpu; } @@ -137,7 +137,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid) int old_idx, new_cpu; unsigned long flags; - WARN_ON(cpu > num_present_cpus()); + WARN_ON(!cpu_present(cpu)); raw_spin_lock_irqsave(&cp->lock, flags); old_idx = cp->cpu_to_idx[cpu]; -- cgit v0.10.2 From 995b9ea440862def83e8fcb1b498e68f93d4af59 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Tue, 18 Feb 2014 02:24:13 +0400 Subject: sched/deadline: Remove useless dl_nr_total In deadline class we do not have group scheduling like in RT. dl_nr_total is the same as dl_nr_running. So, one of them should be removed. Cc: Ingo Molnar Cc: Juri Lelli Signed-off-by: Kirill Tkhai Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/368631392675853@web20h.yandex.ru Signed-off-by: Thomas Gleixner diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index b819577..15cbc17 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -121,7 +121,7 @@ static inline void dl_clear_overload(struct rq *rq) static void update_dl_migration(struct dl_rq *dl_rq) { - if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_total > 1) { + if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_running > 1) { if (!dl_rq->overloaded) { dl_set_overload(rq_of_dl_rq(dl_rq)); dl_rq->overloaded = 1; @@ -137,7 +137,6 @@ static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) struct task_struct *p = dl_task_of(dl_se); dl_rq = &rq_of_dl_rq(dl_rq)->dl; - dl_rq->dl_nr_total++; if (p->nr_cpus_allowed > 1) dl_rq->dl_nr_migratory++; @@ -149,7 +148,6 @@ static void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) struct task_struct *p = dl_task_of(dl_se); dl_rq = &rq_of_dl_rq(dl_rq)->dl; - dl_rq->dl_nr_total--; if (p->nr_cpus_allowed > 1) dl_rq->dl_nr_migratory--; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c2119fd..f964add 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -462,7 +462,6 @@ struct dl_rq { } earliest_dl; unsigned long dl_nr_migratory; - unsigned long dl_nr_total; int overloaded; /* -- cgit v0.10.2 From e194fd8a5d8e0a7eeed239a8534460724b62fe2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Mon, 17 Feb 2014 13:58:29 -0800 Subject: staging: binder: Fix death notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The change (008fa749e0fe5b2fffd20b7fe4891bb80d072c6a) that moved the node release code to a separate function broke death notifications in some cases. When it encountered a reference without a death notification request, it would skip looking at the remaining references, and therefore fail to send death notifications for them. Cc: Colin Cross Cc: Android Kernel Team Cc: stable # 3.10 Signed-off-by: Arve HjønnevÃ¥g Signed-off-by: John Stultz Signed-off-by: Jeremy Compostella Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index eaec1da..1432d95 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2904,7 +2904,7 @@ static int binder_node_release(struct binder_node *node, int refs) refs++; if (!ref->death) - goto out; + continue; death++; @@ -2917,7 +2917,6 @@ static int binder_node_release(struct binder_node *node, int refs) BUG(); } -out: binder_debug(BINDER_DEBUG_DEAD_BINDER, "node %d now dead, refs %d, death %d\n", node->debug_id, refs, death); -- cgit v0.10.2 From 5bf5dbeda2454296f1984adfbfc8e6f5965ac389 Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Wed, 19 Feb 2014 13:46:31 +0800 Subject: usb: chipidea: need to mask when writting endptflush and endptprime ENDPTFLUSH and ENDPTPRIME registers are set by software and clear by hardware. There is a bit for each endpoint. When we are setting a bit for an endpoint we should make sure we do not touch other endpoint bit. There is a race condition if the hardware clear the bit between the read and the write in hw_write. Cc: stable # 3.11+ Signed-off-by: Peter Chen Signed-off-by: Matthieu CASTET Tested-by: Michael Grzeschik Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 80de2f8..4ab2cb6 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -105,7 +105,7 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) do { /* flush any pending transfer */ - hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); + hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n)); while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) cpu_relax(); } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); @@ -205,7 +205,7 @@ static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl) if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) return -EAGAIN; - hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); + hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n)); while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) cpu_relax(); -- cgit v0.10.2 From a3ef2229c94ff70998724cb64b9cb4c77db9e950 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Fri, 14 Feb 2014 16:44:08 -0800 Subject: perf, nmi: Fix unknown NMI warning When using BTS on Core i7-4*, I get the below kernel warning. $ perf record -c 1 -e branches:u ls Message from syslogd@labpc1501 at Nov 11 15:49:25 ... kernel:[ 438.317893] Uhhuh. NMI received for unknown reason 31 on CPU 2. Message from syslogd@labpc1501 at Nov 11 15:49:25 ... kernel:[ 438.317920] Do you have a strange power saving mode enabled? Message from syslogd@labpc1501 at Nov 11 15:49:25 ... kernel:[ 438.317945] Dazed and confused, but trying to continue Make intel_pmu_handle_irq() take the full exit path when returning early. Cc: eranian@google.com Cc: peterz@infradead.org Cc: mingo@kernel.org Signed-off-by: Markus Metzger Signed-off-by: Andi Kleen Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392425048-5309-1-git-send-email-andi@firstfloor.org Signed-off-by: Thomas Gleixner diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 0fa4f24..698ae77 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1361,10 +1361,8 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) intel_pmu_disable_all(); handled = intel_pmu_drain_bts_buffer(); status = intel_pmu_get_status(); - if (!status) { - intel_pmu_enable_all(0); - return handled; - } + if (!status) + goto done; loops = 0; again: -- cgit v0.10.2 From c9b08884c9c98929ec2d8abafd78e89062d01ee7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 3 Feb 2014 14:29:03 +0100 Subject: perf/x86: Correctly use FEATURE_PDCM The current code simply assumes Intel Arch PerfMon v2+ to have the IA32_PERF_CAPABILITIES MSR; the SDM specifies that we should check CPUID[1].ECX[15] (aka, FEATURE_PDCM) instead. This was found by KVM which implements v2+ but didn't provide the capabilities MSR. Change the code to DTRT; KVM will also implement the MSR and return 0. Cc: pbonzini@redhat.com Reported-by: "Michael S. Tsirkin" Suggested-by: Eduardo Habkost Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140203132903.GI8874@twins.programming.kicks-ass.net Signed-off-by: Thomas Gleixner diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 698ae77..aa333d9 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -2308,10 +2308,7 @@ __init int intel_pmu_init(void) if (version > 1) x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3); - /* - * v2 and above have a perf capabilities MSR - */ - if (version > 1) { + if (boot_cpu_has(X86_FEATURE_PDCM)) { u64 capabilities; rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); -- cgit v0.10.2 From 337397f3afc911d94d1d71371a36a53ce218b41f Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 19 Feb 2014 14:10:18 +0100 Subject: perf/x86/uncore: Fix IVT/SNB-EP uncore CBOX NID filter table This patch updates the CBOX PMU filters mapping tables for SNB-EP and IVT (model 45 and 62 respectively). The NID umask always comes in addition to another umask. When set, the NID filter is applied. The current mapping tables were missing some code/umask combinations to account for the NID umask. This patch fixes that. Cc: mingo@elte.hu Cc: ak@linux.intel.com Reviewed-by: Yan, Zheng Signed-off-by: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140219131018.GA24475@quad Signed-off-by: Thomas Gleixner diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 29c2487..c88f7f4 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -501,8 +501,11 @@ static struct extra_reg snbep_uncore_cbox_extra_regs[] = { SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN, SNBEP_CBO_PMON_CTL_TID_EN, 0x1), SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8), SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8), @@ -1178,10 +1181,15 @@ static struct extra_reg ivt_uncore_cbox_extra_regs[] = { SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN, SNBEP_CBO_PMON_CTL_TID_EN, 0x1), SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2), + SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc), + SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4), - SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc), + SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10), SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10), SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10), -- cgit v0.10.2 From d86e9af6336c0ad586a5dbd70064253d40bbb5ff Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 7 Feb 2014 00:41:58 +0100 Subject: irqchip: orion: Fix getting generic chip pointer. Enabling SPARSE_IRQ shows up a bug in the irq-orion bridge interrupt handler. The bridge interrupt is implemented using a single generic chip. Thus the parameter passed to irq_get_domain_generic_chip() should always be zero. Signed-off-by: Andrew Lunn Acked-by: Sebastian Hesselbarth Fixes: 9dbd90f17e4f ("irqchip: Add support for Marvell Orion SoCs") Cc: # v3.11+ Signed-off-by: Jason Cooper diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 0dfdc5c..8e41be6 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init); static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) { struct irq_domain *d = irq_get_handler_data(irq); - struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq); + + struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0); u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) & gc->mask_cache; -- cgit v0.10.2 From deff82e688a278eb4b822fd616c05fc62907bb71 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 17 Feb 2014 22:30:58 +0100 Subject: ARM: OMAP2+: Add support for thumb mode on DT booted N900 Without enabling the workaround for ARM errata 430973 thumb compiled userland crashes randomly on the Nokia N900. Signed-off-by: Sebastian Reichel Reviewed-by: Pavel Machek Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 3d5b24d..0cc710d 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -22,6 +22,8 @@ #include "common-board-devices.h" #include "dss-common.h" #include "control.h" +#include "omap-secure.h" +#include "soc.h" struct pdata_init { const char *compatible; @@ -169,6 +171,22 @@ static void __init am3517_evm_legacy_init(void) omap_ctrl_writel(v, AM35XX_CONTROL_IP_SW_RESET); omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */ } + +static void __init nokia_n900_legacy_init(void) +{ + hsmmc2_internal_input_clk(); + + if (omap_type() == OMAP2_DEVICE_TYPE_SEC) { + if (IS_ENABLED(CONFIG_ARM_ERRATA_430973)) { + pr_info("RX-51: Enabling ARM errata 430973 workaround\n"); + /* set IBE to 1 */ + rx51_secure_update_aux_cr(BIT(6), 0); + } else { + pr_warning("RX-51: Not enabling ARM errata 430973 workaround\n"); + pr_warning("Thumb binaries may crash randomly without this workaround\n"); + } + } +} #endif /* CONFIG_ARCH_OMAP3 */ #ifdef CONFIG_ARCH_OMAP4 @@ -259,7 +277,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { static struct pdata_init pdata_quirks[] __initdata = { #ifdef CONFIG_ARCH_OMAP3 { "compulab,omap3-sbc-t3730", omap3_sbc_t3730_legacy_init, }, - { "nokia,omap3-n900", hsmmc2_internal_input_clk, }, + { "nokia,omap3-n900", nokia_n900_legacy_init, }, { "nokia,omap3-n9", hsmmc2_internal_input_clk, }, { "nokia,omap3-n950", hsmmc2_internal_input_clk, }, { "isee,omap3-igep0020", omap3_igep0020_legacy_init, }, -- cgit v0.10.2 From 865da01cd98d67518befe854a71e432d894db279 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 17 Feb 2014 13:22:55 +0530 Subject: ARM: OMAP: Kill warning in CPUIDLE code with !CONFIG_SMP for non SMP build, NR_CPUS is 1 and hence the code complains with below warnings. arch/arm/mach-omap2/cpuidle44xx.c:207:8: warning: array subscript is above array bounds [-Warray-bounds] arch/arm/mach-omap2/cpuidle44xx.c:212:11: warning: array subscript is above array bounds [-Warray-bounds] Kill it by making array size fixed. Acked-by: Nishanth Menon Signed-off-by: Santosh Shilimkar Signed-off-by: Mugunthan V N Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index 4c158c8..01fc710 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -23,6 +23,8 @@ #include "prm.h" #include "clockdomain.h" +#define MAX_CPUS 2 + /* Machine specific information */ struct idle_statedata { u32 cpu_state; @@ -48,11 +50,11 @@ static struct idle_statedata omap4_idle_data[] = { }, }; -static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS]; -static struct clockdomain *cpu_clkdm[NR_CPUS]; +static struct powerdomain *mpu_pd, *cpu_pd[MAX_CPUS]; +static struct clockdomain *cpu_clkdm[MAX_CPUS]; static atomic_t abort_barrier; -static bool cpu_done[NR_CPUS]; +static bool cpu_done[MAX_CPUS]; static struct idle_statedata *state_ptr = &omap4_idle_data[0]; /* Private functions */ -- cgit v0.10.2 From eec70897d81bb2913e22c6792ea2739faf59c3e1 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 20 Feb 2014 00:52:01 +0000 Subject: bio-integrity: Drop bio_integrity_verify BUG_ON in post bip->bip_iter world Given that bip->bip_iter.bi_size is decremented after bio_advance() -> bio_integrity_advance() is called, the BUG_ON() in bio_integrity_verify() ends up tripping in v3.14-rc1 code with the advent of immutable biovecs in: commit d57a5f7c6605f15f3b5134837e68b448a7cea88e Author: Kent Overstreet Date: Sat Nov 23 17:20:16 2013 -0800 bio-integrity: Convert to bvec_iter Given that there is no easy way to ascertain the original bi_size value, go ahead and drop this BUG_ON(). Reported-by: Sagi Grimberg Reported-by: Akinobu Mita Acked-by: Martin K. Petersen Cc: Kent Overstreet Signed-off-by: Nicholas Bellinger Signed-off-by: Jens Axboe diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 0129b78..4f70f38 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -458,11 +458,10 @@ static int bio_integrity_verify(struct bio *bio) struct blk_integrity_exchg bix; struct bio_vec *bv; sector_t sector = bio->bi_integrity->bip_iter.bi_sector; - unsigned int sectors, total, ret; + unsigned int sectors, ret = 0; void *prot_buf = bio->bi_integrity->bip_buf; int i; - ret = total = 0; bix.disk_name = bio->bi_bdev->bd_disk->disk_name; bix.sector_size = bi->sector_size; @@ -484,8 +483,6 @@ static int bio_integrity_verify(struct bio *bio) sectors = bv->bv_len / bi->sector_size; sector += sectors; prot_buf += sectors * bi->tuple_size; - total += sectors * bi->tuple_size; - BUG_ON(total > bio->bi_integrity->bip_iter.bi_size); kunmap_atomic(kaddr); } -- cgit v0.10.2 From 0dc83bd30b0bf5410c0933cfbbf8853248eff0a9 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 21 Feb 2014 11:19:04 +0100 Subject: Revert "writeback: do not sync data dirtied after sync start" This reverts commit c4a391b53a72d2df4ee97f96f78c1d5971b47489. Dave Chinner has reported the commit may cause some inodes to be left out from sync(2). This is because we can call redirty_tail() for some inode (which sets i_dirtied_when to current time) after sync(2) has started or similarly requeue_inode() can set i_dirtied_when to current time if writeback had to skip some pages. The real problem is in the functions clobbering i_dirtied_when but fixing that isn't trivial so revert is a safer choice for now. CC: stable@vger.kernel.org # >= 3.13 Signed-off-by: Jan Kara diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e0259a1..d754e3c 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -40,18 +40,13 @@ struct wb_writeback_work { long nr_pages; struct super_block *sb; - /* - * Write only inodes dirtied before this time. Don't forget to set - * older_than_this_is_set when you set this. - */ - unsigned long older_than_this; + unsigned long *older_than_this; enum writeback_sync_modes sync_mode; unsigned int tagged_writepages:1; unsigned int for_kupdate:1; unsigned int range_cyclic:1; unsigned int for_background:1; unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ - unsigned int older_than_this_is_set:1; enum wb_reason reason; /* why was writeback initiated? */ struct list_head list; /* pending work list */ @@ -252,10 +247,10 @@ static int move_expired_inodes(struct list_head *delaying_queue, int do_sb_sort = 0; int moved = 0; - WARN_ON_ONCE(!work->older_than_this_is_set); while (!list_empty(delaying_queue)) { inode = wb_inode(delaying_queue->prev); - if (inode_dirtied_after(inode, work->older_than_this)) + if (work->older_than_this && + inode_dirtied_after(inode, *work->older_than_this)) break; list_move(&inode->i_wb_list, &tmp); moved++; @@ -742,8 +737,6 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, .sync_mode = WB_SYNC_NONE, .range_cyclic = 1, .reason = reason, - .older_than_this = jiffies, - .older_than_this_is_set = 1, }; spin_lock(&wb->list_lock); @@ -802,13 +795,12 @@ static long wb_writeback(struct bdi_writeback *wb, { unsigned long wb_start = jiffies; long nr_pages = work->nr_pages; + unsigned long oldest_jif; struct inode *inode; long progress; - if (!work->older_than_this_is_set) { - work->older_than_this = jiffies; - work->older_than_this_is_set = 1; - } + oldest_jif = jiffies; + work->older_than_this = &oldest_jif; spin_lock(&wb->list_lock); for (;;) { @@ -842,10 +834,10 @@ static long wb_writeback(struct bdi_writeback *wb, * safe. */ if (work->for_kupdate) { - work->older_than_this = jiffies - + oldest_jif = jiffies - msecs_to_jiffies(dirty_expire_interval * 10); } else if (work->for_background) - work->older_than_this = jiffies; + oldest_jif = jiffies; trace_writeback_start(wb->bdi, work); if (list_empty(&wb->b_io)) @@ -1357,21 +1349,18 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb); /** * sync_inodes_sb - sync sb inode pages - * @sb: the superblock - * @older_than_this: timestamp + * @sb: the superblock * * This function writes and waits on any dirty inode belonging to this - * superblock that has been dirtied before given timestamp. + * super_block. */ -void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this) +void sync_inodes_sb(struct super_block *sb) { DECLARE_COMPLETION_ONSTACK(done); struct wb_writeback_work work = { .sb = sb, .sync_mode = WB_SYNC_ALL, .nr_pages = LONG_MAX, - .older_than_this = older_than_this, - .older_than_this_is_set = 1, .range_cyclic = 0, .done = &done, .reason = WB_REASON_SYNC, diff --git a/fs/sync.c b/fs/sync.c index e8ba024..b28d1dd 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -27,11 +27,10 @@ * wait == 1 case since in that case write_inode() functions do * sync_dirty_buffer() and thus effectively write one block at a time. */ -static int __sync_filesystem(struct super_block *sb, int wait, - unsigned long start) +static int __sync_filesystem(struct super_block *sb, int wait) { if (wait) - sync_inodes_sb(sb, start); + sync_inodes_sb(sb); else writeback_inodes_sb(sb, WB_REASON_SYNC); @@ -48,7 +47,6 @@ static int __sync_filesystem(struct super_block *sb, int wait, int sync_filesystem(struct super_block *sb) { int ret; - unsigned long start = jiffies; /* * We need to be protected against the filesystem going from @@ -62,17 +60,17 @@ int sync_filesystem(struct super_block *sb) if (sb->s_flags & MS_RDONLY) return 0; - ret = __sync_filesystem(sb, 0, start); + ret = __sync_filesystem(sb, 0); if (ret < 0) return ret; - return __sync_filesystem(sb, 1, start); + return __sync_filesystem(sb, 1); } EXPORT_SYMBOL_GPL(sync_filesystem); static void sync_inodes_one_sb(struct super_block *sb, void *arg) { if (!(sb->s_flags & MS_RDONLY)) - sync_inodes_sb(sb, *((unsigned long *)arg)); + sync_inodes_sb(sb); } static void sync_fs_one_sb(struct super_block *sb, void *arg) @@ -104,10 +102,9 @@ static void fdatawait_one_bdev(struct block_device *bdev, void *arg) SYSCALL_DEFINE0(sync) { int nowait = 0, wait = 1; - unsigned long start = jiffies; wakeup_flusher_threads(0, WB_REASON_SYNC); - iterate_supers(sync_inodes_one_sb, &start); + iterate_supers(sync_inodes_one_sb, NULL); iterate_supers(sync_fs_one_sb, &nowait); iterate_supers(sync_fs_one_sb, &wait); iterate_bdevs(fdatawrite_one_bdev, NULL); diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index f317488..d971f49 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -913,7 +913,7 @@ xfs_flush_inodes( struct super_block *sb = mp->m_super; if (down_read_trylock(&sb->s_umount)) { - sync_inodes_sb(sb, jiffies); + sync_inodes_sb(sb); up_read(&sb->s_umount); } } diff --git a/include/linux/writeback.h b/include/linux/writeback.h index fc0e432..021b8a3 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -97,7 +97,7 @@ void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason); int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr, enum wb_reason reason); -void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this); +void sync_inodes_sb(struct super_block *); void wakeup_flusher_threads(long nr_pages, enum wb_reason reason); void inode_wait_for_writeback(struct inode *inode); diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index c7bbbe7..464ea82 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -287,11 +287,11 @@ TRACE_EVENT(writeback_queue_io, __field(int, reason) ), TP_fast_assign( - unsigned long older_than_this = work->older_than_this; + unsigned long *older_than_this = work->older_than_this; strncpy(__entry->name, dev_name(wb->bdi->dev), 32); - __entry->older = older_than_this; + __entry->older = older_than_this ? *older_than_this : 0; __entry->age = older_than_this ? - (jiffies - older_than_this) * 1000 / HZ : -1; + (jiffies - *older_than_this) * 1000 / HZ : -1; __entry->moved = moved; __entry->reason = work->reason; ), -- cgit v0.10.2 From 08221fc4e7aa585a59de90c0354da3e8d3e88d94 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 21 Feb 2014 13:12:38 +0100 Subject: regulator: max14577: Fix invalid return value on DT parse success This fixes bug introduced in 667a6b7a (regulator: max14577: Add missing of_node_put). The DTS parsing function returned number of matched regulators as success status which then was compared against 0 in probe. Result was a probe fail after successful parsing the DTS: max14577-regulator: probe of max14577-regulator failed with error 2 Signed-off-by: Krzysztof Kozlowski Reviwed-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c index 186df87..e061952 100644 --- a/drivers/regulator/max14577.c +++ b/drivers/regulator/max14577.c @@ -166,9 +166,10 @@ static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev) ret = of_regulator_match(&pdev->dev, np, max14577_regulator_matches, MAX14577_REG_MAX); - if (ret < 0) { + if (ret < 0) dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret); - } + else + ret = 0; of_node_put(np); -- cgit v0.10.2 From 9fe7ed474956944443eec57c5f75be12e10da84e Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Thu, 20 Feb 2014 11:32:49 +0800 Subject: tipc: remove all enabled flags from all tipc components When tipc module is inserted, many tipc components are initialized one by one. During the initialization period, if one of them is failed, tipc_core_stop() will be called to stop all components whatever corresponding components are created or not. To avoid to release uncreated ones, relevant components have to add necessary enabled flags indicating whether they are created or not. But in the initialization stage, if one component is unsuccessfully created, we will just destroy successfully created components before the failed component instead of all components. All enabled flags defined in components, in turn, become redundant. Additionally it's also unnecessary to identify whether table.types is NULL in tipc_nametbl_stop() because name stable has been definitely created successfully when tipc_nametbl_stop() is called. Cc: Jon Maloy Cc: Erik Hugne Signed-off-by: Ying Xue Reviewed-by: Paul Gortmaker Signed-off-by: David S. Miller diff --git a/net/tipc/core.c b/net/tipc/core.c index f9e88d8..cfd9cc1 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -122,30 +122,59 @@ static void tipc_core_stop(void) */ static int tipc_core_start(void) { - int res; + int err; get_random_bytes(&tipc_random, sizeof(tipc_random)); - res = tipc_handler_start(); - if (!res) - res = tipc_ref_table_init(tipc_max_ports, tipc_random); - if (!res) - res = tipc_nametbl_init(); - if (!res) - res = tipc_netlink_start(); - if (!res) - res = tipc_socket_init(); - if (!res) - res = tipc_register_sysctl(); - if (!res) - res = tipc_subscr_start(); - if (!res) - res = tipc_cfg_init(); - if (res) { - tipc_handler_stop(); - tipc_core_stop(); - } - return res; + err = tipc_handler_start(); + if (err) + goto out_handler; + + err = tipc_ref_table_init(tipc_max_ports, tipc_random); + if (err) + goto out_reftbl; + + err = tipc_nametbl_init(); + if (err) + goto out_nametbl; + + err = tipc_netlink_start(); + if (err) + goto out_netlink; + + err = tipc_socket_init(); + if (err) + goto out_socket; + + err = tipc_register_sysctl(); + if (err) + goto out_sysctl; + + err = tipc_subscr_start(); + if (err) + goto out_subscr; + + err = tipc_cfg_init(); + if (err) + goto out_cfg; + + return 0; +out_cfg: + tipc_subscr_stop(); +out_subscr: + tipc_unregister_sysctl(); +out_sysctl: + tipc_socket_stop(); +out_socket: + tipc_netlink_stop(); +out_netlink: + tipc_nametbl_stop(); +out_nametbl: + tipc_ref_table_stop(); +out_reftbl: + tipc_handler_stop(); +out_handler: + return err; } static int __init tipc_init(void) diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 92a1533..48302be 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -945,9 +945,6 @@ void tipc_nametbl_stop(void) { u32 i; - if (!table.types) - return; - /* Verify name table is empty, then release it */ write_lock_bh(&tipc_nametbl_lock); for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 9f72a63..3aaf73d 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -83,8 +83,6 @@ static struct genl_ops tipc_genl_ops[] = { }, }; -static int tipc_genl_family_registered; - int tipc_netlink_start(void) { int res; @@ -94,16 +92,10 @@ int tipc_netlink_start(void) pr_err("Failed to register netlink interface\n"); return res; } - - tipc_genl_family_registered = 1; return 0; } void tipc_netlink_stop(void) { - if (!tipc_genl_family_registered) - return; - genl_unregister_family(&tipc_genl_family); - tipc_genl_family_registered = 0; } diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 2a2a938..de3d593 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -126,9 +126,6 @@ int tipc_ref_table_init(u32 requested_size, u32 start) */ void tipc_ref_table_stop(void) { - if (!tipc_ref_table.entries) - return; - vfree(tipc_ref_table.entries); tipc_ref_table.entries = NULL; } diff --git a/net/tipc/server.c b/net/tipc/server.c index b635ca3..3739797 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -573,7 +573,6 @@ int tipc_server_start(struct tipc_server *s) kmem_cache_destroy(s->rcvbuf_cache); return ret; } - s->enabled = 1; return ret; } @@ -583,10 +582,6 @@ void tipc_server_stop(struct tipc_server *s) int total = 0; int id; - if (!s->enabled) - return; - - s->enabled = 0; spin_lock_bh(&s->idr_lock); for (id = 0; total < s->idr_in_use; id++) { con = idr_find(&s->conn_idr, id); diff --git a/net/tipc/server.h b/net/tipc/server.h index 98b23f2..be817b0 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h @@ -56,7 +56,6 @@ * @name: server name * @imp: message importance * @type: socket type - * @enabled: identify whether server is launched or not */ struct tipc_server { struct idr conn_idr; @@ -74,7 +73,6 @@ struct tipc_server { const char name[TIPC_SERVER_NAME_LEN]; int imp; int type; - int enabled; }; int tipc_conn_sendmsg(struct tipc_server *s, int conid, diff --git a/net/tipc/socket.c b/net/tipc/socket.c index aab4948..a4cf274 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -70,8 +70,6 @@ static const struct proto_ops msg_ops; static struct proto tipc_proto; static struct proto tipc_proto_kern; -static int sockets_enabled; - /* * Revised TIPC socket locking policy: * @@ -2027,8 +2025,6 @@ int tipc_socket_init(void) proto_unregister(&tipc_proto); goto out; } - - sockets_enabled = 1; out: return res; } @@ -2038,10 +2034,6 @@ int tipc_socket_init(void) */ void tipc_socket_stop(void) { - if (!sockets_enabled) - return; - - sockets_enabled = 0; sock_unregister(tipc_family_ops.family); proto_unregister(&tipc_proto); } -- cgit v0.10.2 From 970122fdf4b2d79c708022f2fdc0ab3840311d87 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Thu, 20 Feb 2014 11:32:50 +0800 Subject: tipc: make bearer set up in module insertion stage Accidentally a side effect is involved by commit 6e967adf7(tipc: relocate common functions from media to bearer). Now tipc stack handler of receiving packets from netdevices as well as netdevice notification handler are registered when bearer is enabled rather than tipc module initialization stage, but the two handlers are both unregistered in tipc module exit phase. If tipc module is inserted and then immediately removed, the following warning message will appear: "dev_remove_pack: ffffffffa0380940 not found" This is because in module insertion stage tipc stack packet handler is not registered at all, but in module exit phase dev_remove_pack() needs to remove it. Of course, dev_remove_pack() cannot find tipc protocol handler from the kernel protocol handler list so that the warning message is printed out. But if registering the two handlers is adjusted from enabling bearer phase into inserting module stage, the warning message will be eliminated. Due to this change, tipc_core_start_net() and tipc_core_stop_net() can be deleted as well. Reported-by: Wang Weidong Cc: Jon Maloy Cc: Erik Hugne Signed-off-by: Ying Xue Reviewed-by: Paul Gortmaker Signed-off-by: David S. Miller diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a38c899..574b861 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -610,8 +610,13 @@ static struct notifier_block notifier = { int tipc_bearer_setup(void) { + int err; + + err = register_netdevice_notifier(¬ifier); + if (err) + return err; dev_add_pack(&tipc_packet_type); - return register_netdevice_notifier(¬ifier); + return 0; } void tipc_bearer_cleanup(void) diff --git a/net/tipc/config.c b/net/tipc/config.c index c301a9a..e74eef2 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -181,7 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void) if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); - tipc_core_start_net(addr); + tipc_net_start(addr); return tipc_cfg_reply_none(); } diff --git a/net/tipc/core.c b/net/tipc/core.c index cfd9cc1..80c2064 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -77,37 +77,13 @@ struct sk_buff *tipc_buf_acquire(u32 size) } /** - * tipc_core_stop_net - shut down TIPC networking sub-systems - */ -static void tipc_core_stop_net(void) -{ - tipc_net_stop(); - tipc_bearer_cleanup(); -} - -/** - * start_net - start TIPC networking sub-systems - */ -int tipc_core_start_net(unsigned long addr) -{ - int res; - - tipc_net_start(addr); - res = tipc_bearer_setup(); - if (res < 0) - goto err; - return res; - -err: - tipc_core_stop_net(); - return res; -} - -/** * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode */ static void tipc_core_stop(void) { + tipc_handler_stop(); + tipc_net_stop(); + tipc_bearer_cleanup(); tipc_netlink_stop(); tipc_cfg_stop(); tipc_subscr_stop(); @@ -158,7 +134,13 @@ static int tipc_core_start(void) if (err) goto out_cfg; + err = tipc_bearer_setup(); + if (err) + goto out_bearer; + return 0; +out_bearer: + tipc_cfg_stop(); out_cfg: tipc_subscr_stop(); out_subscr: @@ -203,8 +185,6 @@ static int __init tipc_init(void) static void __exit tipc_exit(void) { - tipc_handler_stop(); - tipc_core_stop_net(); tipc_core_stop(); pr_info("Deactivated\n"); } diff --git a/net/tipc/core.h b/net/tipc/core.h index 5569d96..4dfe137 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -90,7 +90,6 @@ extern int tipc_random __read_mostly; /* * Routines available to privileged subsystems */ -int tipc_core_start_net(unsigned long); int tipc_handler_start(void); void tipc_handler_stop(void); int tipc_netlink_start(void); -- cgit v0.10.2 From f5ddcbbb40aa0ba7fbfe22355d287603dbeeaaac Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 20 Feb 2014 10:09:18 -0800 Subject: net-tcp: fastopen: fix high order allocations This patch fixes two bugs in fastopen : 1) The tcp_sendmsg(..., @size) argument was ignored. Code was relying on user not fooling the kernel with iovec mismatches 2) When MTU is about 64KB, tcp_send_syn_data() attempts order-5 allocations, which are likely to fail when memory gets fragmented. Fixes: 783237e8daf13 ("net-tcp: Fast Open client - sending SYN-data") Signed-off-by: Eric Dumazet Cc: Yuchung Cheng Acked-by: Yuchung Cheng Tested-by: Yuchung Cheng Signed-off-by: David S. Miller diff --git a/include/net/tcp.h b/include/net/tcp.h index 56fc366..8c4dd63 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1303,7 +1303,8 @@ struct tcp_fastopen_request { /* Fast Open cookie. Size 0 means a cookie request */ struct tcp_fastopen_cookie cookie; struct msghdr *data; /* data in MSG_FASTOPEN */ - u16 copied; /* queued in tcp_connect() */ + size_t size; + int copied; /* queued in tcp_connect() */ }; void tcp_free_fastopen_req(struct tcp_sock *tp); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9f3a2db..97c8f56 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1044,7 +1044,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp) } } -static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size) +static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, + int *copied, size_t size) { struct tcp_sock *tp = tcp_sk(sk); int err, flags; @@ -1059,11 +1060,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size) if (unlikely(tp->fastopen_req == NULL)) return -ENOBUFS; tp->fastopen_req->data = msg; + tp->fastopen_req->size = size; flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; err = __inet_stream_connect(sk->sk_socket, msg->msg_name, msg->msg_namelen, flags); - *size = tp->fastopen_req->copied; + *copied = tp->fastopen_req->copied; tcp_free_fastopen_req(tp); return err; } @@ -1083,7 +1085,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, flags = msg->msg_flags; if (flags & MSG_FASTOPEN) { - err = tcp_sendmsg_fastopen(sk, msg, &copied_syn); + err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size); if (err == -EINPROGRESS && copied_syn > 0) goto out; else if (err) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3be1672..0980581 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2908,7 +2908,12 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) - MAX_TCP_OPTION_SPACE; - syn_data = skb_copy_expand(syn, skb_headroom(syn), space, + space = min_t(size_t, space, fo->size); + + /* limit to order-0 allocations */ + space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); + + syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space, sk->sk_allocation); if (syn_data == NULL) goto fallback; -- cgit v0.10.2 From b194c1f1dbd5f2671e49e0ac801b1b78dc7de93b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 21 Feb 2014 14:52:57 +0100 Subject: neigh: fix setting of default gc_* values This patch fixes bug introduced by: commit 1d4c8c29841b9991cdf3c7cc4ba7f96a94f104ca "neigh: restore old behaviour of default parms values" The thing is that in neigh_sysctl_register, extra1 and extra2 which were previously set for NEIGH_VAR_GC_* are overwritten. That leads to nonsense int limits for gc_* variables. So fix this by not touching extra* fields for gc_* variables. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b9e9e0d..e1aa0f3 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -3046,7 +3046,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, if (!t) goto err; - for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) { + for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) { t->neigh_vars[i].data += (long) p; t->neigh_vars[i].extra1 = dev; t->neigh_vars[i].extra2 = p; -- cgit v0.10.2 From 4c47af4d5eb2c2f78f886079a3920a7078a6f0a0 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 20 Feb 2014 20:51:06 +0100 Subject: net: sctp: rework multihoming retransmission path selection to rfc4960 Problem statement: 1) both paths (primary path1 and alternate path2) are up after the association has been established i.e., HB packets are normally exchanged, 2) path2 gets inactive after path_max_retrans * max_rto timed out (i.e. path2 is down completely), 3) now, if a transmission times out on the only surviving/active path1 (any ~1sec network service impact could cause this like a channel bonding failover), then the retransmitted packets are sent over the inactive path2; this happens with partial failover and without it. Besides not being optimal in the above scenario, a small failure or timeout in the only existing path has the potential to cause long delays in the retransmission (depending on RTO_MAX) until the still active path is reselected. Further, when the T3-timeout occurs, we have active_patch == retrans_path, and even though the timeout occurred on the initial transmission of data, not a retransmit, we end up updating retransmit path. RFC4960, section 6.4. "Multi-Homed SCTP Endpoints" states under 6.4.1. "Failover from an Inactive Destination Address" the following: Some of the transport addresses of a multi-homed SCTP endpoint may become inactive due to either the occurrence of certain error conditions (see Section 8.2) or adjustments from the SCTP user. When there is outbound data to send and the primary path becomes inactive (e.g., due to failures), or where the SCTP user explicitly requests to send data to an inactive destination transport address, before reporting an error to its ULP, the SCTP endpoint should try to send the data to an alternate __active__ destination transport address if one exists. When retransmitting data that timed out, if the endpoint is multihomed, it should consider each source-destination address pair in its retransmission selection policy. When retransmitting timed-out data, the endpoint should attempt to pick the most divergent source-destination pair from the original source-destination pair to which the packet was transmitted. Note: Rules for picking the most divergent source-destination pair are an implementation decision and are not specified within this document. So, we should first reconsider to take the current active retransmission transport if we cannot find an alternative active one. If all of that fails, we can still round robin through unkown, partial failover, and inactive ones in the hope to find something still suitable. Commit 4141ddc02a92 ("sctp: retran_path update bug fix") broke that behaviour by selecting the next inactive transport when no other active transport was found besides the current assoc's peer.retran_path. Before commit 4141ddc02a92, we would have traversed through the list until we reach our peer.retran_path again, and in case that is still in state SCTP_ACTIVE, we would take it and return. Only if that is not the case either, we take the next inactive transport. Besides all that, another issue is that transports in state SCTP_UNKNOWN could be preferred over transports in state SCTP_ACTIVE in case a SCTP_ACTIVE transport appears after SCTP_UNKNOWN in the transport list yielding a weaker transport state to be used in retransmission. This patch mostly reverts 4141ddc02a92, but also rewrites this function to introduce more clarity and strictness into the code. A strict priority of transport states is enforced in this patch, hence selection is active > unkown > partial failover > inactive. Fixes: 4141ddc02a92 ("sctp: retran_path update bug fix") Signed-off-by: Daniel Borkmann Cc: Gui Jianfeng Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f558433..ee13d28 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1239,78 +1239,107 @@ void sctp_assoc_update(struct sctp_association *asoc, } /* Update the retran path for sending a retransmitted packet. - * Round-robin through the active transports, else round-robin - * through the inactive transports as this is the next best thing - * we can try. + * See also RFC4960, 6.4. Multi-Homed SCTP Endpoints: + * + * When there is outbound data to send and the primary path + * becomes inactive (e.g., due to failures), or where the + * SCTP user explicitly requests to send data to an + * inactive destination transport address, before reporting + * an error to its ULP, the SCTP endpoint should try to send + * the data to an alternate active destination transport + * address if one exists. + * + * When retransmitting data that timed out, if the endpoint + * is multihomed, it should consider each source-destination + * address pair in its retransmission selection policy. + * When retransmitting timed-out data, the endpoint should + * attempt to pick the most divergent source-destination + * pair from the original source-destination pair to which + * the packet was transmitted. + * + * Note: Rules for picking the most divergent source-destination + * pair are an implementation decision and are not specified + * within this document. + * + * Our basic strategy is to round-robin transports in priorities + * according to sctp_state_prio_map[] e.g., if no such + * transport with state SCTP_ACTIVE exists, round-robin through + * SCTP_UNKNOWN, etc. You get the picture. */ -void sctp_assoc_update_retran_path(struct sctp_association *asoc) +static const u8 sctp_trans_state_to_prio_map[] = { + [SCTP_ACTIVE] = 3, /* best case */ + [SCTP_UNKNOWN] = 2, + [SCTP_PF] = 1, + [SCTP_INACTIVE] = 0, /* worst case */ +}; + +static u8 sctp_trans_score(const struct sctp_transport *trans) { - struct sctp_transport *t, *next; - struct list_head *head = &asoc->peer.transport_addr_list; - struct list_head *pos; + return sctp_trans_state_to_prio_map[trans->state]; +} - if (asoc->peer.transport_count == 1) - return; +static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr, + struct sctp_transport *best) +{ + if (best == NULL) + return curr; - /* Find the next transport in a round-robin fashion. */ - t = asoc->peer.retran_path; - pos = &t->transports; - next = NULL; + return sctp_trans_score(curr) > sctp_trans_score(best) ? curr : best; +} - while (1) { - /* Skip the head. */ - if (pos->next == head) - pos = head->next; - else - pos = pos->next; +void sctp_assoc_update_retran_path(struct sctp_association *asoc) +{ + struct sctp_transport *trans = asoc->peer.retran_path; + struct sctp_transport *trans_next = NULL; - t = list_entry(pos, struct sctp_transport, transports); + /* We're done as we only have the one and only path. */ + if (asoc->peer.transport_count == 1) + return; + /* If active_path and retran_path are the same and active, + * then this is the only active path. Use it. + */ + if (asoc->peer.active_path == asoc->peer.retran_path && + asoc->peer.active_path->state == SCTP_ACTIVE) + return; - /* We have exhausted the list, but didn't find any - * other active transports. If so, use the next - * transport. - */ - if (t == asoc->peer.retran_path) { - t = next; + /* Iterate from retran_path's successor back to retran_path. */ + for (trans = list_next_entry(trans, transports); 1; + trans = list_next_entry(trans, transports)) { + /* Manually skip the head element. */ + if (&trans->transports == &asoc->peer.transport_addr_list) + continue; + if (trans->state == SCTP_UNCONFIRMED) + continue; + trans_next = sctp_trans_elect_best(trans, trans_next); + /* Active is good enough for immediate return. */ + if (trans_next->state == SCTP_ACTIVE) break; - } - - /* Try to find an active transport. */ - - if ((t->state == SCTP_ACTIVE) || - (t->state == SCTP_UNKNOWN)) { + /* We've reached the end, time to update path. */ + if (trans == asoc->peer.retran_path) break; - } else { - /* Keep track of the next transport in case - * we don't find any active transport. - */ - if (t->state != SCTP_UNCONFIRMED && !next) - next = t; - } } - if (t) - asoc->peer.retran_path = t; - else - t = asoc->peer.retran_path; + if (trans_next != NULL) + asoc->peer.retran_path = trans_next; - pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc, - &t->ipaddr.sa); + pr_debug("%s: association:%p updated new path to addr:%pISpc\n", + __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); } -/* Choose the transport for sending retransmit packet. */ -struct sctp_transport *sctp_assoc_choose_alter_transport( - struct sctp_association *asoc, struct sctp_transport *last_sent_to) +struct sctp_transport * +sctp_assoc_choose_alter_transport(struct sctp_association *asoc, + struct sctp_transport *last_sent_to) { /* If this is the first time packet is sent, use the active path, * else use the retran path. If the last packet was sent over the * retran path, update the retran path and use it. */ - if (!last_sent_to) + if (last_sent_to == NULL) { return asoc->peer.active_path; - else { + } else { if (last_sent_to == asoc->peer.retran_path) sctp_assoc_update_retran_path(asoc); + return asoc->peer.retran_path; } } -- cgit v0.10.2 From 916e4cf46d0204806c062c8c6c4d1f633852c5b6 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 21 Feb 2014 02:55:35 +0100 Subject: ipv6: reuse ip6_frag_id from ip6_ufo_append_data Currently we generate a new fragmentation id on UFO segmentation. It is pretty hairy to identify the correct net namespace and dst there. Especially tunnels use IFF_XMIT_DST_RELEASE and thus have no skb_dst available at all. This causes unreliable or very predictable ipv6 fragmentation id generation while segmentation. Luckily we already have pregenerated the ip6_frag_id in ip6_ufo_append_data and can use it here. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index e7359f9..b261ee8 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); fptr->nexthdr = nexthdr; fptr->reserved = 0; - ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb)); + fptr->identification = skb_shinfo(skb)->ip6_frag_id; /* Fragment the skb. ipv6 header and the remaining fields of the * fragment header are updated in ipv6_gso_segment() -- cgit v0.10.2 From 5c0a2450d695bbe32b1fb81c07751bcbea64f084 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 22 Feb 2014 14:31:04 -0800 Subject: Revert "tty: Set correct tty name in 'active' sysfs attribute" This reverts commit d8a5dc3033af2fd6d16030d2ee4fbd073460fe54. This breaks plymouth installs, either because plymouth is using the file "incorrectly" or because the patch is incorrect. Either way, this needs to be reverted until it is all figured out. Reported-by: Josh Boyer Reported-by: Ray Strode Cc: Lennart Poettering Cc: Kay Sievers Cc: Jiri Slaby Cc: David Herrmann Cc: Werner Fink Cc: Hannes Reinecke Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty index a2ccec3..ad22fb0 100644 --- a/Documentation/ABI/testing/sysfs-tty +++ b/Documentation/ABI/testing/sysfs-tty @@ -3,8 +3,7 @@ Date: Nov 2010 Contact: Kay Sievers Description: Shows the list of currently configured - tty devices used for the console, - like 'tty1 ttyS0'. + console devices, like 'tty1 ttyS0'. The last entry in the file is the active device connected to /dev/console. The file supports poll() to detect virtual diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index bd2715a..c74a00a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1267,17 +1267,16 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) * @p: output buffer of at least 7 bytes * * Generate a name from a driver reference and write it to the output - * buffer. Return the number of bytes written. + * buffer. * * Locking: None */ -static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) +static void tty_line_name(struct tty_driver *driver, int index, char *p) { if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE) - return sprintf(p, "%s", driver->name); + strcpy(p, driver->name); else - return sprintf(p, "%s%d", driver->name, - index + driver->name_base); + sprintf(p, "%s%d", driver->name, index + driver->name_base); } /** @@ -3546,19 +3545,9 @@ static ssize_t show_cons_active(struct device *dev, if (i >= ARRAY_SIZE(cs)) break; } - while (i--) { - struct tty_driver *driver; - const char *name = cs[i]->name; - int index = cs[i]->index; - - driver = cs[i]->device(cs[i], &index); - if (driver) { - count += tty_line_name(driver, index, buf + count); - count += sprintf(buf + count, "%c", i ? ' ':'\n'); - } else - count += sprintf(buf + count, "%s%d%c", - name, index, i ? ' ':'\n'); - } + while (i--) + count += sprintf(buf + count, "%s%d%c", + cs[i]->name, cs[i]->index, i ? ' ':'\n'); console_unlock(); return count; -- cgit v0.10.2 From 70ff00f82a6af0ff68f8f7b411738634ce2f20d0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:27:17 +0100 Subject: ASoC: sta32x: Fix cache sync codec->control_data contains a pointer to the regmap struct of the device, not to the device private data. Use snd_soc_codec_get_drvdata() instead. The issue was introduced in commit 29fdf4fbbe ("ASoC: sta32x: Convert to regmap"). Fixes: 29fdf4fbbe (ASoC: sta32x: Convert to regmap) Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 42c5b45..ea78c17 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -331,7 +331,7 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) static int sta32x_cache_sync(struct snd_soc_codec *codec) { - struct sta32x_priv *sta32x = codec->control_data; + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); unsigned int mute; int rc; -- cgit v0.10.2 From 9b87a5b0d4aad02e9dff299b63cd85930eb233d8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:44:17 +0100 Subject: ASoC: pxa: Remove superfluous locking The locking here was added in commit 71a295602e ("ASoC: Lock the CODEC in PXA external jack controls") to protect the DAPM changes that are made inside of ${board}_ext_control() against concurrent updates. The ASoC core was updated in commit a73fb2df01 ("ASoC: dapm: Use DAPM mutex for DAPM ops instead of codec mutex") to use a card wide lock rather the CODEC mutex to protect DAPM operations. We now have proper locking inside ${board}_ext_control() itself, so taking the CODEC lock can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1853d41..b51f880 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -99,13 +99,9 @@ static int corgi_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ corgi_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index aace19e..aeb08f5 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -73,13 +73,9 @@ static int magician_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ magician_ext_control(codec); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c93e138..27c6c03 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -76,13 +76,9 @@ static int poodle_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ poodle_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index fc052d8..0728c1eb 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -108,13 +108,9 @@ static int spitz_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ spitz_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 1d9c2ed..d6f38d7 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -80,13 +80,9 @@ static int tosa_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ tosa_ext_control(codec); - mutex_unlock(&codec->mutex); - return 0; } -- cgit v0.10.2 From d1755bb75c68abaa2024dc9507d1c78521adadeb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:16:08 +0100 Subject: ASoC: mc13783: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bb..21c8baa 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -408,8 +408,8 @@ static const char * const adcl_enum_text[] = { "MC1L", "RXINL", }; -static const struct soc_enum adcl_enum = - SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text); +static SOC_ENUM_SINGLE_DECL(adcl_enum, + 0, 0, adcl_enum_text); static const struct snd_kcontrol_new left_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcl_enum); @@ -418,8 +418,8 @@ static const char * const adcr_enum_text[] = { "MC1R", "MC2", "RXINR", "TXIN", }; -static const struct soc_enum adcr_enum = - SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text); +static SOC_ENUM_SINGLE_DECL(adcr_enum, + 0, 0, adcr_enum_text); static const struct snd_kcontrol_new right_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcr_enum); @@ -580,9 +580,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = { static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix", "Mono", "Mono Mix"}; -static const struct soc_enum mc13783_enum_3d_mixer = - SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer), - mc13783_3d_mixer); +static SOC_ENUM_SINGLE_DECL(mc13783_enum_3d_mixer, + MC13783_AUDIO_RX1, 16, + mc13783_3d_mixer); static struct snd_kcontrol_new mc13783_control_list[] = { SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0), -- cgit v0.10.2 From c8ed6504218c5a1951159033d1b1e7927665f109 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:16:31 +0100 Subject: ASoC: sgtl5000: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 0fcbe90..ab4754a 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -187,8 +187,9 @@ static const char *adc_mux_text[] = { "MIC_IN", "LINE_IN" }; -static const struct soc_enum adc_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(adc_enum, + SGTL5000_CHIP_ANA_CTRL, 2, + adc_mux_text); static const struct snd_kcontrol_new adc_mux = SOC_DAPM_ENUM("Capture Mux", adc_enum); @@ -198,8 +199,9 @@ static const char *dac_mux_text[] = { "DAC", "LINE_IN" }; -static const struct soc_enum dac_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text); +static SOC_ENUM_SINGLE_DECL(dac_enum, + SGTL5000_CHIP_ANA_CTRL, 6, + dac_mux_text); static const struct snd_kcontrol_new dac_mux = SOC_DAPM_ENUM("Headphone Mux", dac_enum); -- cgit v0.10.2 From f3c1196e16a84e81978bdf60690cb82fe33e880f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:17:24 +0100 Subject: ASoC: sn95031: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 13045f2..bca7d02 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -312,14 +312,14 @@ static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, /* mux controls */ static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; -static const struct soc_enum sn95031_micl_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_micl_enum, + SN95031_ADCCONFIG, 1, sn95031_mic_texts); static const struct snd_kcontrol_new sn95031_micl_mux_control = SOC_DAPM_ENUM("Route", sn95031_micl_enum); -static const struct soc_enum sn95031_micr_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_micr_enum, + SN95031_ADCCONFIG, 3, sn95031_mic_texts); static const struct snd_kcontrol_new sn95031_micr_mux_control = SOC_DAPM_ENUM("Route", sn95031_micr_enum); @@ -328,26 +328,26 @@ static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6", "ADC Left", "ADC Right" }; -static const struct soc_enum sn95031_input1_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input1_enum, + SN95031_AUDIOMUX12, 0, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input1_mux_control = SOC_DAPM_ENUM("Route", sn95031_input1_enum); -static const struct soc_enum sn95031_input2_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input2_enum, + SN95031_AUDIOMUX12, 4, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input2_mux_control = SOC_DAPM_ENUM("Route", sn95031_input2_enum); -static const struct soc_enum sn95031_input3_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input3_enum, + SN95031_AUDIOMUX34, 0, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input3_mux_control = SOC_DAPM_ENUM("Route", sn95031_input3_enum); -static const struct soc_enum sn95031_input4_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input4_enum, + SN95031_AUDIOMUX34, 4, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input4_mux_control = SOC_DAPM_ENUM("Route", sn95031_input4_enum); @@ -359,19 +359,19 @@ static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"}; /* 0dB to 30dB in 10dB steps */ static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0); -static const struct soc_enum sn95031_micmode1_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text); -static const struct soc_enum sn95031_micmode2_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text); +static SOC_ENUM_SINGLE_DECL(sn95031_micmode1_enum, + SN95031_MICAMP1, 1, sn95031_micmode_text); +static SOC_ENUM_SINGLE_DECL(sn95031_micmode2_enum, + SN95031_MICAMP2, 1, sn95031_micmode_text); static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; -static const struct soc_enum sn95031_dmic12_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic34_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic56_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic12_cfg_enum, + SN95031_DMICMUX, 0, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic34_cfg_enum, + SN95031_DMICMUX, 1, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic56_cfg_enum, + SN95031_DMICMUX, 2, sn95031_dmic_cfg_text); static const struct snd_kcontrol_new sn95031_snd_controls[] = { SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), -- cgit v0.10.2 From 3cd7ca58827234c40bb683de2d1d8512631be8e4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:26:27 +0100 Subject: ASoC: stac9766: Use SOC_ENUM_{SINGLE|DOUBLE}_DECL() Just replace with the helper macros. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index a5455c1..53b810d 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -62,25 +62,25 @@ static const char *stac9766_boost1[] = {"0dB", "10dB"}; static const char *stac9766_boost2[] = {"0dB", "20dB"}; static const char *stac9766_stereo_mic[] = {"Off", "On"}; -static const struct soc_enum stac9766_record_enum = - SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux); -static const struct soc_enum stac9766_mono_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux); -static const struct soc_enum stac9766_mic_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux); -static const struct soc_enum stac9766_SPDIF_enum = - SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux); -static const struct soc_enum stac9766_popbypass_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux); -static const struct soc_enum stac9766_record_all_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2, - stac9766_record_all_mux); -static const struct soc_enum stac9766_boost1_enum = - SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */ -static const struct soc_enum stac9766_boost2_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */ -static const struct soc_enum stac9766_stereo_mic_enum = - SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic); +static SOC_ENUM_DOUBLE_DECL(stac9766_record_enum, + AC97_REC_SEL, 8, 0, stac9766_record_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_mono_enum, + AC97_GENERAL_PURPOSE, 9, stac9766_mono_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_mic_enum, + AC97_GENERAL_PURPOSE, 8, stac9766_mic_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_SPDIF_enum, + AC97_STAC_DA_CONTROL, 1, stac9766_SPDIF_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_popbypass_enum, + AC97_GENERAL_PURPOSE, 15, stac9766_popbypass_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_record_all_enum, + AC97_STAC_ANALOG_SPECIAL, 12, + stac9766_record_all_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_boost1_enum, + AC97_MIC, 6, stac9766_boost1); /* 0/10dB */ +static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum, + AC97_STAC_ANALOG_SPECIAL, 2, stac9766_boost2); /* 0/20dB */ +static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum, + AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic); static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); -- cgit v0.10.2 From 6900ab55dda48825b1cddc87e5e1908d51e96b95 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:27:40 +0100 Subject: ASoC: tlv320aic26: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 94a658f..ff5f23d 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -238,8 +238,9 @@ static struct snd_soc_dai_driver aic26_dai = { * ALSA controls */ static const char *aic26_capture_src_text[] = {"Mic", "Aux"}; -static const struct soc_enum aic26_capture_src_enum = - SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text); +static SOC_ENUM_SINGLE_DECL(aic26_capture_src_enum, + AIC26_REG_AUDIO_CTRL1, 12, + aic26_capture_src_text); static const struct snd_kcontrol_new aic26_snd_controls[] = { /* Output */ -- cgit v0.10.2 From 9f04fba79781fb3ba39eac631f4bd6762f9717db Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:28:25 +0100 Subject: ASoC: twl4030: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 00665ad..e084df7 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -415,10 +415,9 @@ static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = { static const char *twl4030_handsfreel_texts[] = {"Voice", "AudioL1", "AudioL2", "AudioR2"}; -static const struct soc_enum twl4030_handsfreel_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, - ARRAY_SIZE(twl4030_handsfreel_texts), - twl4030_handsfreel_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_handsfreel_enum, + TWL4030_REG_HFL_CTL, 0, + twl4030_handsfreel_texts); static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); @@ -431,10 +430,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control = static const char *twl4030_handsfreer_texts[] = {"Voice", "AudioR1", "AudioR2", "AudioL2"}; -static const struct soc_enum twl4030_handsfreer_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, - ARRAY_SIZE(twl4030_handsfreer_texts), - twl4030_handsfreer_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_handsfreer_enum, + TWL4030_REG_HFR_CTL, 0, + twl4030_handsfreer_texts); static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); @@ -448,10 +446,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control = static const char *twl4030_vibra_texts[] = {"AudioL1", "AudioR1", "AudioL2", "AudioR2"}; -static const struct soc_enum twl4030_vibra_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2, - ARRAY_SIZE(twl4030_vibra_texts), - twl4030_vibra_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibra_enum, + TWL4030_REG_VIBRA_CTL, 2, + twl4030_vibra_texts); static const struct snd_kcontrol_new twl4030_dapm_vibra_control = SOC_DAPM_ENUM("Route", twl4030_vibra_enum); @@ -460,10 +457,9 @@ SOC_DAPM_ENUM("Route", twl4030_vibra_enum); static const char *twl4030_vibrapath_texts[] = {"Local vibrator", "Audio"}; -static const struct soc_enum twl4030_vibrapath_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4, - ARRAY_SIZE(twl4030_vibrapath_texts), - twl4030_vibrapath_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibrapath_enum, + TWL4030_REG_VIBRA_CTL, 4, + twl4030_vibrapath_texts); static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control = SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum); @@ -490,10 +486,9 @@ static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = { static const char *twl4030_micpathtx1_texts[] = {"Analog", "Digimic0"}; -static const struct soc_enum twl4030_micpathtx1_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 0, - ARRAY_SIZE(twl4030_micpathtx1_texts), - twl4030_micpathtx1_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx1_enum, + TWL4030_REG_ADCMICSEL, 0, + twl4030_micpathtx1_texts); static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control = SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); @@ -502,10 +497,9 @@ SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); static const char *twl4030_micpathtx2_texts[] = {"Analog", "Digimic1"}; -static const struct soc_enum twl4030_micpathtx2_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 2, - ARRAY_SIZE(twl4030_micpathtx2_texts), - twl4030_micpathtx2_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx2_enum, + TWL4030_REG_ADCMICSEL, 2, + twl4030_micpathtx2_texts); static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); @@ -955,10 +949,9 @@ static const char *twl4030_op_modes_texts[] = { "Option 2 (voice/audio)", "Option 1 (audio)" }; -static const struct soc_enum twl4030_op_modes_enum = - SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0, - ARRAY_SIZE(twl4030_op_modes_texts), - twl4030_op_modes_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_op_modes_enum, + TWL4030_REG_CODEC_MODE, 0, + twl4030_op_modes_texts); static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -1044,10 +1037,9 @@ static const char *twl4030_avadc_clk_priority_texts[] = { "Voice high priority", "HiFi high priority" }; -static const struct soc_enum twl4030_avadc_clk_priority_enum = - SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2, - ARRAY_SIZE(twl4030_avadc_clk_priority_texts), - twl4030_avadc_clk_priority_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_avadc_clk_priority_enum, + TWL4030_REG_AVADC_CTL, 2, + twl4030_avadc_clk_priority_texts); static const char *twl4030_rampdelay_texts[] = { "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", @@ -1055,40 +1047,36 @@ static const char *twl4030_rampdelay_texts[] = { "3495/2581/1748 ms" }; -static const struct soc_enum twl4030_rampdelay_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2, - ARRAY_SIZE(twl4030_rampdelay_texts), - twl4030_rampdelay_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_rampdelay_enum, + TWL4030_REG_HS_POPN_SET, 2, + twl4030_rampdelay_texts); /* Vibra H-bridge direction mode */ static const char *twl4030_vibradirmode_texts[] = { "Vibra H-bridge direction", "Audio data MSB", }; -static const struct soc_enum twl4030_vibradirmode_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5, - ARRAY_SIZE(twl4030_vibradirmode_texts), - twl4030_vibradirmode_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibradirmode_enum, + TWL4030_REG_VIBRA_CTL, 5, + twl4030_vibradirmode_texts); /* Vibra H-bridge direction */ static const char *twl4030_vibradir_texts[] = { "Positive polarity", "Negative polarity", }; -static const struct soc_enum twl4030_vibradir_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1, - ARRAY_SIZE(twl4030_vibradir_texts), - twl4030_vibradir_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibradir_enum, + TWL4030_REG_VIBRA_CTL, 1, + twl4030_vibradir_texts); /* Digimic Left and right swapping */ static const char *twl4030_digimicswap_texts[] = { "Not swapped", "Swapped", }; -static const struct soc_enum twl4030_digimicswap_enum = - SOC_ENUM_SINGLE(TWL4030_REG_MISC_SET_1, 0, - ARRAY_SIZE(twl4030_digimicswap_texts), - twl4030_digimicswap_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_digimicswap_enum, + TWL4030_REG_MISC_SET_1, 0, + twl4030_digimicswap_texts); static const struct snd_kcontrol_new twl4030_snd_controls[] = { /* Codec operation mode control */ -- cgit v0.10.2 From a1d0d786af587c50ea948439e610c90525af36d7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:30:20 +0100 Subject: ASoC: twl6040: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. Also, use ARRAY_SIZE() in some ASOC_ENUM_SINGLE() lines. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index cb642c9..bd3a206 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -392,8 +392,10 @@ static const char *twl6040_amicr_texts[] = {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; static const struct soc_enum twl6040_enum[] = { - SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts), - SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts), + SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, + ARRAY_SIZE(twl6040_amicl_texts), twl6040_amicl_texts), + SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, + ARRAY_SIZE(twl6040_amicr_texts), twl6040_amicr_texts), }; static const char *twl6040_hs_texts[] = { @@ -476,9 +478,8 @@ static const char *twl6040_power_mode_texts[] = { "Low-Power", "High-Performance", }; -static const struct soc_enum twl6040_power_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts), - twl6040_power_mode_texts); +static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum, + twl6040_power_mode_texts); static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v0.10.2 From 1dbb348d904baed36789078e1202344f5a6ecc84 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:32:16 +0100 Subject: ASoC: uda1380: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. Also, use ARRAY_SIZE() in some ASOC_ENUM_SINGLE() lines. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 726df6d..72ee8e1 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -237,25 +237,27 @@ static const char *uda1380_os_setting[] = { }; static const struct soc_enum uda1380_deemp_enum[] = { - SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp), - SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp), + SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, ARRAY_SIZE(uda1380_deemp), + uda1380_deemp), + SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, ARRAY_SIZE(uda1380_deemp), + uda1380_deemp), }; -static const struct soc_enum uda1380_input_sel_enum = - SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ -static const struct soc_enum uda1380_output_sel_enum = - SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */ -static const struct soc_enum uda1380_spf_enum = - SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */ -static const struct soc_enum uda1380_capture_sel_enum = - SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */ -static const struct soc_enum uda1380_sel_ns_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */ -static const struct soc_enum uda1380_mix_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */ -static const struct soc_enum uda1380_sdet_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */ -static const struct soc_enum uda1380_os_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */ +static SOC_ENUM_SINGLE_DECL(uda1380_input_sel_enum, + UDA1380_ADC, 2, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ +static SOC_ENUM_SINGLE_DECL(uda1380_output_sel_enum, + UDA1380_PM, 7, uda1380_output_sel); /* R02_EN_AVC */ +static SOC_ENUM_SINGLE_DECL(uda1380_spf_enum, + UDA1380_MODE, 14, uda1380_spf_mode); /* M */ +static SOC_ENUM_SINGLE_DECL(uda1380_capture_sel_enum, + UDA1380_IFACE, 6, uda1380_capture_sel); /* SEL_SOURCE */ +static SOC_ENUM_SINGLE_DECL(uda1380_sel_ns_enum, + UDA1380_MIXER, 14, uda1380_sel_ns); /* SEL_NS */ +static SOC_ENUM_SINGLE_DECL(uda1380_mix_enum, + UDA1380_MIXER, 12, uda1380_mix_control); /* MIX, MIX_POS */ +static SOC_ENUM_SINGLE_DECL(uda1380_sdet_enum, + UDA1380_MIXER, 4, uda1380_sdet_setting); /* SD_VALUE */ +static SOC_ENUM_SINGLE_DECL(uda1380_os_enum, + UDA1380_MIXER, 0, uda1380_os_setting); /* OS */ /* * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) -- cgit v0.10.2 From 4ec20a9700f6f4fa140d8586f4f8ff5f76ea4ba7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:33:06 +0100 Subject: ASoC: wl1273: Use SOC_ENUM_SINGLE_EXT_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index b7ab2ef..7485285 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -209,8 +209,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, return 1; } -static const struct soc_enum wl1273_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route); +static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route); static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -247,9 +246,7 @@ static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol, static const char * const wl1273_audio_strings[] = { "Digital", "Analog" }; -static const struct soc_enum wl1273_audio_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings), - wl1273_audio_strings); +static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings); static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v0.10.2 From 9614be73d810a02f23f3cc19d8eb97b81213545e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:33:59 +0100 Subject: ASoC: wm2200: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 57ba315..1e0a083 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1113,11 +1113,10 @@ static const char *wm2200_rxanc_input_sel_texts[] = { "None", "IN1", "IN2", "IN3", }; -static const struct soc_enum wm2200_rxanc_input_sel = - SOC_ENUM_SINGLE(WM2200_RXANC_SRC, - WM2200_IN_RXANC_SEL_SHIFT, - ARRAY_SIZE(wm2200_rxanc_input_sel_texts), - wm2200_rxanc_input_sel_texts); +static SOC_ENUM_SINGLE_DECL(wm2200_rxanc_input_sel, + WM2200_RXANC_SRC, + WM2200_IN_RXANC_SEL_SHIFT, + wm2200_rxanc_input_sel_texts); static const struct snd_kcontrol_new wm2200_snd_controls[] = { SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, @@ -1288,11 +1287,10 @@ static const char *wm2200_aec_loopback_texts[] = { "OUT1L", "OUT1R", "OUT2L", "OUT2R", }; -static const struct soc_enum wm2200_aec_loopback = - SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1, - WM2200_AEC_LOOPBACK_SRC_SHIFT, - ARRAY_SIZE(wm2200_aec_loopback_texts), - wm2200_aec_loopback_texts); +static SOC_ENUM_SINGLE_DECL(wm2200_aec_loopback, + WM2200_DAC_AEC_CONTROL_1, + WM2200_AEC_LOOPBACK_SRC_SHIFT, + wm2200_aec_loopback_texts); static const struct snd_kcontrol_new wm2200_aec_loopback_mux = SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback); -- cgit v0.10.2 From fed08d94bf3f930ebe9ad2f3ad7744b8e2eab6bc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:35:49 +0100 Subject: ASoC: wm8523: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 74d106d..5dfd571 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -75,8 +75,8 @@ static const char *wm8523_zd_count_text[] = { "2048", }; -static const struct soc_enum wm8523_zc_count = - SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); +static SOC_ENUM_SINGLE_DECL(wm8523_zc_count, WM8523_ZERO_DETECT, 0, + wm8523_zd_count_text); static const struct snd_kcontrol_new wm8523_controls[] = { SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, -- cgit v0.10.2 From 9e74b14ad5140837cfa0dc639dc13acaa2b05b0f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:36:16 +0100 Subject: ASoC: wm8731: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 0297203..d9655f9 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -83,8 +83,8 @@ static bool wm8731_writeable(struct device *dev, unsigned int reg) static const char *wm8731_input_select[] = {"Line In", "Mic"}; -static const struct soc_enum wm8731_insel_enum = - SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select); +static SOC_ENUM_SINGLE_DECL(wm8731_insel_enum, + WM8731_APANA, 2, wm8731_input_select); static int wm8731_deemph[] = { 0, 32000, 44100, 48000 }; -- cgit v0.10.2 From ca275811fd2eef7e0121fefbc46cc5b47d680b10 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:37:14 +0100 Subject: ASoC: wm8737: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 22de242..ecc4e87 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -99,29 +99,29 @@ static const char *micbias_enum_text[] = { "100%", }; -static const struct soc_enum micbias_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text); +static SOC_ENUM_SINGLE_DECL(micbias_enum, + WM8737_MIC_PREAMP_CONTROL, 0, micbias_enum_text); static const char *low_cutoff_text[] = { "Low", "High" }; -static const struct soc_enum low_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text); +static SOC_ENUM_SINGLE_DECL(low_3d, + WM8737_3D_ENHANCE, 6, low_cutoff_text); static const char *high_cutoff_text[] = { "High", "Low" }; -static const struct soc_enum high_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text); +static SOC_ENUM_SINGLE_DECL(high_3d, + WM8737_3D_ENHANCE, 5, high_cutoff_text); static const char *alc_fn_text[] = { "Disabled", "Right", "Left", "Stereo" }; -static const struct soc_enum alc_fn = - SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text); +static SOC_ENUM_SINGLE_DECL(alc_fn, + WM8737_ALC1, 7, alc_fn_text); static const char *alc_hold_text[] = { "0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms", @@ -129,24 +129,24 @@ static const char *alc_hold_text[] = { "10.916s", "21.832s", "43.691s" }; -static const struct soc_enum alc_hold = - SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text); +static SOC_ENUM_SINGLE_DECL(alc_hold, + WM8737_ALC2, 0, alc_hold_text); static const char *alc_atk_text[] = { "8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", "4.3s", "8.6s" }; -static const struct soc_enum alc_atk = - SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text); +static SOC_ENUM_SINGLE_DECL(alc_atk, + WM8737_ALC3, 0, alc_atk_text); static const char *alc_dcy_text[] = { "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", "4.3s", "8.6s", "17.2s", "34.41s" }; -static const struct soc_enum alc_dcy = - SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text); +static SOC_ENUM_SINGLE_DECL(alc_dcy, + WM8737_ALC3, 4, alc_dcy_text); static const struct snd_kcontrol_new wm8737_snd_controls[] = { SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, @@ -191,8 +191,8 @@ static const char *linsel_text[] = { "LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC", }; -static const struct soc_enum linsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text); +static SOC_ENUM_SINGLE_DECL(linsel_enum, + WM8737_AUDIO_PATH_L, 7, linsel_text); static const struct snd_kcontrol_new linsel_mux = SOC_DAPM_ENUM("LINSEL", linsel_enum); @@ -202,8 +202,8 @@ static const char *rinsel_text[] = { "RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC", }; -static const struct soc_enum rinsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text); +static SOC_ENUM_SINGLE_DECL(rinsel_enum, + WM8737_AUDIO_PATH_R, 7, rinsel_text); static const struct snd_kcontrol_new rinsel_mux = SOC_DAPM_ENUM("RINSEL", rinsel_enum); @@ -212,15 +212,15 @@ static const char *bypass_text[] = { "Direct", "Preamp" }; -static const struct soc_enum lbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text); +static SOC_ENUM_SINGLE_DECL(lbypass_enum, + WM8737_MIC_PREAMP_CONTROL, 2, bypass_text); static const struct snd_kcontrol_new lbypass_mux = SOC_DAPM_ENUM("Left Bypass", lbypass_enum); -static const struct soc_enum rbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text); +static SOC_ENUM_SINGLE_DECL(rbypass_enum, + WM8737_MIC_PREAMP_CONTROL, 3, bypass_text); static const struct snd_kcontrol_new rbypass_mux = SOC_DAPM_ENUM("Left Bypass", rbypass_enum); -- cgit v0.10.2 From a21bc5c5bdeb19314976b79db6dc3993c9b227c8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:40:16 +0100 Subject: ASoC: wm8903: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index eebcb1d..b82b70a 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -489,28 +489,28 @@ static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8903_ADC_DIGITAL_0, 5, 4, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(hpf_mode, + WM8903_ADC_DIGITAL_0, 5, hpf_mode_text); static const char *osr_text[] = { "Low power", "High performance" }; -static const struct soc_enum adc_osr = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_ADC_0, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(adc_osr, + WM8903_ANALOGUE_ADC_0, 0, osr_text); -static const struct soc_enum dac_osr = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(dac_osr, + WM8903_DAC_DIGITAL_1, 0, osr_text); static const char *drc_slope_text[] = { "1", "1/2", "1/4", "1/8", "1/16", "0" }; -static const struct soc_enum drc_slope_r0 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r0, + WM8903_DRC_2, 3, drc_slope_text); -static const struct soc_enum drc_slope_r1 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r1, + WM8903_DRC_2, 0, drc_slope_text); static const char *drc_attack_text[] = { "instantaneous", @@ -518,125 +518,125 @@ static const char *drc_attack_text[] = { "46.4ms", "92.8ms", "185.6ms" }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8903_DRC_1, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", "23.87s", "47.56s" }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8903_DRC_1, 8, drc_decay_text); static const char *drc_ff_delay_text[] = { "5 samples", "9 samples" }; -static const struct soc_enum drc_ff_delay = - SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text); +static SOC_ENUM_SINGLE_DECL(drc_ff_delay, + WM8903_DRC_0, 5, drc_ff_delay_text); static const char *drc_qr_decay_text[] = { "0.725ms", "1.45ms", "5.8ms" }; -static const struct soc_enum drc_qr_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_decay, + WM8903_DRC_1, 4, drc_qr_decay_text); static const char *drc_smoothing_text[] = { "Low", "Medium", "High" }; -static const struct soc_enum drc_smoothing = - SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text); +static SOC_ENUM_SINGLE_DECL(drc_smoothing, + WM8903_DRC_0, 11, drc_smoothing_text); static const char *soft_mute_text[] = { "Fast (fs/2)", "Slow (fs/32)" }; -static const struct soc_enum soft_mute = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text); +static SOC_ENUM_SINGLE_DECL(soft_mute, + WM8903_DAC_DIGITAL_1, 10, soft_mute_text); static const char *mute_mode_text[] = { "Hard", "Soft" }; -static const struct soc_enum mute_mode = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text); +static SOC_ENUM_SINGLE_DECL(mute_mode, + WM8903_DAC_DIGITAL_1, 9, mute_mode_text); static const char *companding_text[] = { "ulaw", "alaw" }; -static const struct soc_enum dac_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(dac_companding, + WM8903_AUDIO_INTERFACE_0, 0, companding_text); -static const struct soc_enum adc_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(adc_companding, + WM8903_AUDIO_INTERFACE_0, 2, companding_text); static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; -static const struct soc_enum linput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(linput_mode_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 0, input_mode_text); -static const struct soc_enum rinput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(rinput_mode_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 0, input_mode_text); static const char *linput_mux_text[] = { "IN1L", "IN2L", "IN3L" }; -static const struct soc_enum linput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 2, linput_mux_text); -static const struct soc_enum linput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_inv_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 4, linput_mux_text); static const char *rinput_mux_text[] = { "IN1R", "IN2R", "IN3R" }; -static const struct soc_enum rinput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 2, rinput_mux_text); -static const struct soc_enum rinput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_inv_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 4, rinput_mux_text); static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum lsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(lsidetone_enum, + WM8903_DAC_DIGITAL_0, 2, sidetone_text); -static const struct soc_enum rsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(rsidetone_enum, + WM8903_DAC_DIGITAL_0, 0, sidetone_text); static const char *adcinput_text[] = { "ADC", "DMIC" }; -static const struct soc_enum adcinput_enum = - SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text); +static SOC_ENUM_SINGLE_DECL(adcinput_enum, + WM8903_CLOCK_RATE_TEST_4, 9, adcinput_text); static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum lcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lcapture_enum, + WM8903_AUDIO_INTERFACE_0, 7, aif_text); -static const struct soc_enum rcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rcapture_enum, + WM8903_AUDIO_INTERFACE_0, 6, aif_text); -static const struct soc_enum lplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lplay_enum, + WM8903_AUDIO_INTERFACE_0, 5, aif_text); -static const struct soc_enum rplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rplay_enum, + WM8903_AUDIO_INTERFACE_0, 4, aif_text); static const struct snd_kcontrol_new wm8903_snd_controls[] = { -- cgit v0.10.2 From d12bfd62fa936f7549a02811b4168493c67c98be Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:40:50 +0100 Subject: ASoC: wm8904: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 53bbfac..cf12a90 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -552,18 +552,20 @@ static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; -static const struct soc_enum lin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(lin_mode, + WM8904_ANALOGUE_LEFT_INPUT_1, 0, + input_mode_text); -static const struct soc_enum rin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(rin_mode, + WM8904_ANALOGUE_RIGHT_INPUT_1, 0, + input_mode_text); static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(hpf_mode, WM8904_ADC_DIGITAL_0, 5, + hpf_mode_text); static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -611,8 +613,7 @@ static const char *drc_path_text[] = { "ADC", "DAC" }; -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8904_DRC_0, 14, 2, drc_path_text); +static SOC_ENUM_SINGLE_DECL(drc_path, WM8904_DRC_0, 14, drc_path_text); static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = { SOC_SINGLE_TLV("Digital Playback Boost Volume", @@ -858,14 +859,14 @@ static const char *lin_text[] = { "IN1L", "IN2L", "IN3L" }; -static const struct soc_enum lin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 2, 3, lin_text); +static SOC_ENUM_SINGLE_DECL(lin_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 2, + lin_text); static const struct snd_kcontrol_new lin_mux = SOC_DAPM_ENUM("Left Capture Mux", lin_enum); -static const struct soc_enum lin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 4, 3, lin_text); +static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4, + lin_text); static const struct snd_kcontrol_new lin_inv_mux = SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); @@ -874,14 +875,14 @@ static const char *rin_text[] = { "IN1R", "IN2R", "IN3R" }; -static const struct soc_enum rin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 2, 3, rin_text); +static SOC_ENUM_SINGLE_DECL(rin_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 2, + rin_text); static const struct snd_kcontrol_new rin_mux = SOC_DAPM_ENUM("Right Capture Mux", rin_enum); -static const struct soc_enum rin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 4, 3, rin_text); +static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4, + rin_text); static const struct snd_kcontrol_new rin_inv_mux = SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); @@ -890,26 +891,26 @@ static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 7, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutl_enum, WM8904_AUDIO_INTERFACE_0, 7, + aif_text); static const struct snd_kcontrol_new aifoutl_mux = SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 6, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutr_enum, WM8904_AUDIO_INTERFACE_0, 6, + aif_text); static const struct snd_kcontrol_new aifoutr_mux = SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 5, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinl_enum, WM8904_AUDIO_INTERFACE_0, 5, + aif_text); static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 4, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinr_enum, WM8904_AUDIO_INTERFACE_0, 4, + aif_text); static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); @@ -991,26 +992,26 @@ static const char *out_mux_text[] = { "DAC", "Bypass" }; -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 3, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(hpl_enum, WM8904_ANALOGUE_OUT12_ZC, 3, + out_mux_text); static const struct snd_kcontrol_new hpl_mux = SOC_DAPM_ENUM("HPL Mux", hpl_enum); -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 2, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(hpr_enum, WM8904_ANALOGUE_OUT12_ZC, 2, + out_mux_text); static const struct snd_kcontrol_new hpr_mux = SOC_DAPM_ENUM("HPR Mux", hpr_enum); -static const struct soc_enum linel_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 1, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(linel_enum, WM8904_ANALOGUE_OUT12_ZC, 1, + out_mux_text); static const struct snd_kcontrol_new linel_mux = SOC_DAPM_ENUM("LINEL Mux", linel_enum); -static const struct soc_enum liner_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(liner_enum, WM8904_ANALOGUE_OUT12_ZC, 0, + out_mux_text); static const struct snd_kcontrol_new liner_mux = SOC_DAPM_ENUM("LINER Mux", liner_enum); @@ -1019,14 +1020,14 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum dacl_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacl_sidetone_enum, WM8904_DAC_DIGITAL_0, 2, + sidetone_text); static const struct snd_kcontrol_new dacl_sidetone_mux = SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum); -static const struct soc_enum dacr_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacr_sidetone_enum, WM8904_DAC_DIGITAL_0, 0, + sidetone_text); static const struct snd_kcontrol_new dacr_sidetone_mux = SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum); -- cgit v0.10.2 From 47ef34271b8714b01ec1647d9013abf8f11fda3d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:42:06 +0100 Subject: ASoC: wm8940: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index b404c26..87f032d 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -154,22 +154,22 @@ static const struct reg_default wm8940_reg_defaults[] = { }; static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; -static const struct soc_enum wm8940_adc_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding); -static const struct soc_enum wm8940_dac_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding); +static SOC_ENUM_SINGLE_DECL(wm8940_adc_companding_enum, + WM8940_COMPANDINGCTL, 1, wm8940_companding); +static SOC_ENUM_SINGLE_DECL(wm8940_dac_companding_enum, + WM8940_COMPANDINGCTL, 3, wm8940_companding); static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"}; -static const struct soc_enum wm8940_alc_mode_enum -= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text); +static SOC_ENUM_SINGLE_DECL(wm8940_alc_mode_enum, + WM8940_ALC3, 8, wm8940_alc_mode_text); static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"}; -static const struct soc_enum wm8940_mic_bias_level_enum -= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text); +static SOC_ENUM_SINGLE_DECL(wm8940_mic_bias_level_enum, + WM8940_INPUTCTL, 8, wm8940_mic_bias_level_text); static const char *wm8940_filter_mode_text[] = {"Audio", "Application"}; -static const struct soc_enum wm8940_filter_mode_enum -= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text); +static SOC_ENUM_SINGLE_DECL(wm8940_filter_mode_enum, + WM8940_ADC, 7, wm8940_filter_mode_text); static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1); static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0); -- cgit v0.10.2 From a6616cda405c9b42732a481a71d69f0b60dafc38 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:42:45 +0100 Subject: ASoC: wm8961: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 900328e..ce8fa6e 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -317,15 +317,15 @@ static const char *adc_hpf_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3", }; -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(adc_hpf, + WM8961_ADC_DAC_CONTROL_2, 7, adc_hpf_text); static const char *dac_deemph_text[] = { "None", "32kHz", "44.1kHz", "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, + WM8961_ADC_DAC_CONTROL_1, 1, dac_deemph_text); static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); @@ -385,11 +385,11 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum dacl_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacl_sidetone, + WM8961_DSP_SIDETONE_0, 2, sidetone_text); -static const struct soc_enum dacr_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacr_sidetone, + WM8961_DSP_SIDETONE_1, 2, sidetone_text); static const struct snd_kcontrol_new dacl_mux = SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); -- cgit v0.10.2 From da6ebf83bb8f3ad5e12b2543f15962e27939ff7f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:07 +0100 Subject: ASoC: wm8962: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index c06bb50..3924ee2 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1658,16 +1658,16 @@ static const char *cap_hpf_mode_text[] = { "Hi-fi", "Application" }; -static const struct soc_enum cap_hpf_mode = - SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_hpf_mode, + WM8962_ADC_DAC_CONTROL_2, 10, cap_hpf_mode_text); static const char *cap_lhpf_mode_text[] = { "LPF", "HPF" }; -static const struct soc_enum cap_lhpf_mode = - SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_lhpf_mode, + WM8962_LHPF1, 1, cap_lhpf_mode_text); static const struct snd_kcontrol_new wm8962_snd_controls[] = { SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), @@ -2014,40 +2014,40 @@ static int dsp2_event(struct snd_soc_dapm_widget *w, static const char *st_text[] = { "None", "Left", "Right" }; -static const struct soc_enum str_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(str_enum, + WM8962_DAC_DSP_MIXING_1, 2, st_text); static const struct snd_kcontrol_new str_mux = SOC_DAPM_ENUM("Right Sidetone", str_enum); -static const struct soc_enum stl_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(stl_enum, + WM8962_DAC_DSP_MIXING_2, 2, st_text); static const struct snd_kcontrol_new stl_mux = SOC_DAPM_ENUM("Left Sidetone", stl_enum); static const char *outmux_text[] = { "DAC", "Mixer" }; -static const struct soc_enum spkoutr_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutr_enum, + WM8962_SPEAKER_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new spkoutr_mux = SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); -static const struct soc_enum spkoutl_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutl_enum, + WM8962_SPEAKER_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new spkoutl_mux = SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); -static const struct soc_enum hpoutr_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutr_enum, + WM8962_HEADPHONE_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new hpoutr_mux = SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); -static const struct soc_enum hpoutl_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutl_enum, + WM8962_HEADPHONE_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new hpoutl_mux = SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); -- cgit v0.10.2 From de461bd2908c44ac51ff3be6a7bf8d13ad23ce1f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:31 +0100 Subject: ASoC: wm8974: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 15f45c7..6e16c43 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -84,8 +84,8 @@ static const struct soc_enum wm8974_enum[] = { static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" }; -static const struct soc_enum wm8974_auxmode = - SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text); +static SOC_ENUM_SINGLE_DECL(wm8974_auxmode, + WM8974_INPUT, 3, wm8974_auxmode_text); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -- cgit v0.10.2 From 2d075611c67c7a351fead73ac6bf0864049305b3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:12 +0100 Subject: ASoC: wm8993: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 2ee23a3..1c12f2c 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -646,8 +646,8 @@ static const char *dac_deemph_text[] = { "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, + WM8993_DAC_CTRL, 4, dac_deemph_text); static const char *adc_hpf_text[] = { "Hi-Fi", @@ -656,16 +656,16 @@ static const char *adc_hpf_text[] = { "Voice 3", }; -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(adc_hpf, + WM8993_ADC_CTRL, 5, adc_hpf_text); static const char *drc_path_text[] = { "ADC", "DAC" }; -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); +static SOC_ENUM_SINGLE_DECL(drc_path, + WM8993_DRC_CONTROL_1, 14, drc_path_text); static const char *drc_r0_text[] = { "1", @@ -676,8 +676,8 @@ static const char *drc_r0_text[] = { "0", }; -static const struct soc_enum drc_r0 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); +static SOC_ENUM_SINGLE_DECL(drc_r0, + WM8993_DRC_CONTROL_3, 8, drc_r0_text); static const char *drc_r1_text[] = { "1", @@ -687,8 +687,8 @@ static const char *drc_r1_text[] = { "0", }; -static const struct soc_enum drc_r1 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); +static SOC_ENUM_SINGLE_DECL(drc_r1, + WM8993_DRC_CONTROL_4, 13, drc_r1_text); static const char *drc_attack_text[] = { "Reserved", @@ -705,8 +705,8 @@ static const char *drc_attack_text[] = { "185.6ms", }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8993_DRC_CONTROL_2, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", @@ -720,16 +720,16 @@ static const char *drc_decay_text[] = { "47.56ms", }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8993_DRC_CONTROL_2, 8, drc_decay_text); static const char *drc_ff_text[] = { "5 samples", "9 samples", }; -static const struct soc_enum drc_ff = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); +static SOC_ENUM_SINGLE_DECL(drc_ff, + WM8993_DRC_CONTROL_3, 7, drc_ff_text); static const char *drc_qr_rate_text[] = { "0.725ms", @@ -737,8 +737,8 @@ static const char *drc_qr_rate_text[] = { "5.8ms", }; -static const struct soc_enum drc_qr_rate = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_rate, + WM8993_DRC_CONTROL_3, 0, drc_qr_rate_text); static const char *drc_smooth_text[] = { "Low", @@ -746,8 +746,8 @@ static const char *drc_smooth_text[] = { "High", }; -static const struct soc_enum drc_smooth = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); +static SOC_ENUM_SINGLE_DECL(drc_smooth, + WM8993_DRC_CONTROL_1, 4, drc_smooth_text); static const struct snd_kcontrol_new wm8993_snd_controls[] = { SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, @@ -841,26 +841,26 @@ static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutl_enum, + WM8993_AUDIO_INTERFACE_1, 15, aif_text); static const struct snd_kcontrol_new aifoutl_mux = SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutr_enum, + WM8993_AUDIO_INTERFACE_1, 14, aif_text); static const struct snd_kcontrol_new aifoutr_mux = SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinl_enum, + WM8993_AUDIO_INTERFACE_2, 15, aif_text); static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinr_enum, + WM8993_AUDIO_INTERFACE_2, 14, aif_text); static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); @@ -869,14 +869,14 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum sidetonel_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetonel_enum, + WM8993_DIGITAL_SIDE_TONE, 2, sidetone_text); static const struct snd_kcontrol_new sidetonel_mux = SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); -static const struct soc_enum sidetoner_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetoner_enum, + WM8993_DIGITAL_SIDE_TONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetoner_mux = SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); -- cgit v0.10.2 From 15b49e73d375a952e34d31f7aac92944df003ca3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:47 +0100 Subject: ASoC: wm8995: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 403e1db..0c539bf 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -781,14 +781,12 @@ static const char *sidetone_text[] = { "ADC/DMIC1", "DMIC2", }; -static const struct soc_enum sidetone1_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 0, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone1_enum, WM8995_SIDETONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetone1_mux = SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); -static const struct soc_enum sidetone2_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 1, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone2_enum, WM8995_SIDETONE, 1, sidetone_text); static const struct snd_kcontrol_new sidetone2_mux = SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); @@ -884,8 +882,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static const struct soc_enum adc_enum = - SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); +static const SOC_ENUM_SINGLE_DECL(adc_enum, 0, 0, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); -- cgit v0.10.2 From 5cca5a916f7ade910e2996e3b44ddffee8e08caf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:05 +0100 Subject: ASoC: wm8996: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b..92bb021 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -311,28 +311,28 @@ static const char *sidetone_hpf_text[] = { "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" }; -static const struct soc_enum sidetone_hpf = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text); +static SOC_ENUM_SINGLE_DECL(sidetone_hpf, + WM8996_SIDETONE, 7, sidetone_hpf_text); static const char *hpf_mode_text[] = { "HiFi", "Custom", "Voice" }; -static const struct soc_enum dsp1tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 3, 3, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_mode, + WM8996_DSP1_TX_FILTERS, 3, hpf_mode_text); -static const struct soc_enum dsp2tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 3, 3, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_mode, + WM8996_DSP2_TX_FILTERS, 3, hpf_mode_text); static const char *hpf_cutoff_text[] = { "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum dsp1tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_cutoff, + WM8996_DSP1_TX_FILTERS, 0, hpf_cutoff_text); -static const struct soc_enum dsp2tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_cutoff, + WM8996_DSP2_TX_FILTERS, 0, hpf_cutoff_text); static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block) { @@ -780,14 +780,14 @@ static const char *sidetone_text[] = { "IN1", "IN2", }; -static const struct soc_enum left_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 0, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(left_sidetone_enum, + WM8996_SIDETONE, 0, sidetone_text); static const struct snd_kcontrol_new left_sidetone = SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum); -static const struct soc_enum right_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 1, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(right_sidetone_enum, + WM8996_SIDETONE, 1, sidetone_text); static const struct snd_kcontrol_new right_sidetone = SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum); @@ -796,14 +796,14 @@ static const char *spk_text[] = { "DAC1L", "DAC1R", "DAC2L", "DAC2R" }; -static const struct soc_enum spkl_enum = - SOC_ENUM_SINGLE(WM8996_LEFT_PDM_SPEAKER, 0, 4, spk_text); +static SOC_ENUM_SINGLE_DECL(spkl_enum, + WM8996_LEFT_PDM_SPEAKER, 0, spk_text); static const struct snd_kcontrol_new spkl_mux = SOC_DAPM_ENUM("SPKL", spkl_enum); -static const struct soc_enum spkr_enum = - SOC_ENUM_SINGLE(WM8996_RIGHT_PDM_SPEAKER, 0, 4, spk_text); +static SOC_ENUM_SINGLE_DECL(spkr_enum, + WM8996_RIGHT_PDM_SPEAKER, 0, spk_text); static const struct snd_kcontrol_new spkr_mux = SOC_DAPM_ENUM("SPKR", spkr_enum); @@ -812,8 +812,8 @@ static const char *dsp1rx_text[] = { "AIF1", "AIF2" }; -static const struct soc_enum dsp1rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text); +static SOC_ENUM_SINGLE_DECL(dsp1rx_enum, + WM8996_POWER_MANAGEMENT_8, 0, dsp1rx_text); static const struct snd_kcontrol_new dsp1rx = SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum); @@ -822,8 +822,8 @@ static const char *dsp2rx_text[] = { "AIF2", "AIF1" }; -static const struct soc_enum dsp2rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text); +static SOC_ENUM_SINGLE_DECL(dsp2rx_enum, + WM8996_POWER_MANAGEMENT_8, 4, dsp2rx_text); static const struct snd_kcontrol_new dsp2rx = SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum); @@ -832,8 +832,8 @@ static const char *aif2tx_text[] = { "DSP2", "DSP1", "AIF1" }; -static const struct soc_enum aif2tx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 6, 3, aif2tx_text); +static SOC_ENUM_SINGLE_DECL(aif2tx_enum, + WM8996_POWER_MANAGEMENT_8, 6, aif2tx_text); static const struct snd_kcontrol_new aif2tx = SOC_DAPM_ENUM("AIF2TX", aif2tx_enum); @@ -842,14 +842,14 @@ static const char *inmux_text[] = { "ADC", "DMIC1", "DMIC2" }; -static const struct soc_enum in1_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 0, 3, inmux_text); +static SOC_ENUM_SINGLE_DECL(in1_enum, + WM8996_POWER_MANAGEMENT_7, 0, inmux_text); static const struct snd_kcontrol_new in1_mux = SOC_DAPM_ENUM("IN1 Mux", in1_enum); -static const struct soc_enum in2_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 4, 3, inmux_text); +static SOC_ENUM_SINGLE_DECL(in2_enum, + WM8996_POWER_MANAGEMENT_7, 4, inmux_text); static const struct snd_kcontrol_new in2_mux = SOC_DAPM_ENUM("IN2 Mux", in2_enum); -- cgit v0.10.2 From abc4b4fb94a274055f5da900976d0970f73a00cc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:17 +0100 Subject: ASoC: wm_hubs: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b371066..b620966 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -50,16 +50,16 @@ static const char *speaker_ref_text[] = { "VMID", }; -static const struct soc_enum speaker_ref = - SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); +static SOC_ENUM_SINGLE_DECL(speaker_ref, + WM8993_SPEAKER_MIXER, 8, speaker_ref_text); static const char *speaker_mode_text[] = { "Class D", "Class AB", }; -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, + WM8993_SPKMIXR_ATTENUATION, 8, speaker_mode_text); static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) { @@ -735,15 +735,15 @@ static const char *hp_mux_text[] = { "DAC", }; -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); +static SOC_ENUM_SINGLE_DECL(hpl_enum, + WM8993_OUTPUT_MIXER1, 8, hp_mux_text); const struct snd_kcontrol_new wm_hubs_hpl_mux = WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum); EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux); -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); +static SOC_ENUM_SINGLE_DECL(hpr_enum, + WM8993_OUTPUT_MIXER2, 8, hp_mux_text); const struct snd_kcontrol_new wm_hubs_hpr_mux = WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum); -- cgit v0.10.2 From 7cb5e1bb9f91bf984f26b520072a22610235d869 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:34 +0100 Subject: ASoC: omap: Use SOC_ENUM_SINGLE_EXT_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 6294464..99b314d 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -194,13 +194,11 @@ static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, return 0; } -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; +static const SOC_ENUM_SINGLE_EXT_DECL(ams_delta_audio_enum, + ams_delta_audio_mode); static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], + SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum, ams_delta_get_audio_mode, ams_delta_set_audio_mode), }; -- cgit v0.10.2 From 6eb0e8f90f5156bb8441c8427b1c11ed9401178f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:13 +0100 Subject: ASoC: 88pm860x: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 75d0ad5..697d24b 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -448,38 +448,38 @@ static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"}; static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"}; -static const struct soc_enum pm860x_hs1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs1_opamp_enum, + PM860X_HS1_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_hs2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs2_opamp_enum, + PM860X_HS2_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_hs1_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs1_pa_enum, + PM860X_HS1_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_hs2_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs2_pa_enum, + PM860X_HS2_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_lo1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo1_opamp_enum, + PM860X_LO1_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_lo2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo2_opamp_enum, + PM860X_LO2_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_lo1_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo1_pa_enum, + PM860X_LO1_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_lo2_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo2_pa_enum, + PM860X_LO2_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_spk_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_spk_pa_enum, + PM860X_EAR_CTRL_1, 5, pm860x_pa_texts); -static const struct soc_enum pm860x_ear_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_ear_pa_enum, + PM860X_EAR_CTRL_2, 0, pm860x_pa_texts); -static const struct soc_enum pm860x_spk_ear_opamp_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_spk_ear_opamp_enum, + PM860X_EAR_CTRL_1, 3, pm860x_opamp_texts); static const struct snd_kcontrol_new pm860x_snd_controls[] = { SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2, @@ -561,8 +561,8 @@ static const char *aif1_text[] = { "PCM L", "PCM R", }; -static const struct soc_enum aif1_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text); +static SOC_ENUM_SINGLE_DECL(aif1_enum, + PM860X_PCM_IFACE_3, 6, aif1_text); static const struct snd_kcontrol_new aif1_mux = SOC_DAPM_ENUM("PCM Mux", aif1_enum); @@ -572,8 +572,8 @@ static const char *i2s_din_text[] = { "DIN", "DIN1", }; -static const struct soc_enum i2s_din_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text); +static SOC_ENUM_SINGLE_DECL(i2s_din_enum, + PM860X_I2S_IFACE_3, 1, i2s_din_text); static const struct snd_kcontrol_new i2s_din_mux = SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum); @@ -583,8 +583,8 @@ static const char *i2s_mic_text[] = { "Ex PA", "ADC", }; -static const struct soc_enum i2s_mic_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text); +static SOC_ENUM_SINGLE_DECL(i2s_mic_enum, + PM860X_I2S_IFACE_3, 4, i2s_mic_text); static const struct snd_kcontrol_new i2s_mic_mux = SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum); @@ -594,8 +594,8 @@ static const char *adcl_text[] = { "ADCR", "ADCL", }; -static const struct soc_enum adcl_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text); +static SOC_ENUM_SINGLE_DECL(adcl_enum, + PM860X_PCM_IFACE_3, 4, adcl_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM("ADC Left Mux", adcl_enum); @@ -605,8 +605,8 @@ static const char *adcr_text[] = { "ADCL", "ADCR", }; -static const struct soc_enum adcr_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text); +static SOC_ENUM_SINGLE_DECL(adcr_enum, + PM860X_PCM_IFACE_3, 2, adcr_text); static const struct snd_kcontrol_new adcr_mux = SOC_DAPM_ENUM("ADC Right Mux", adcr_enum); @@ -616,8 +616,8 @@ static const char *adcr_ec_text[] = { "ADCR", "EC", }; -static const struct soc_enum adcr_ec_enum = - SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text); +static SOC_ENUM_SINGLE_DECL(adcr_ec_enum, + PM860X_ADC_EN_2, 3, adcr_ec_text); static const struct snd_kcontrol_new adcr_ec_mux = SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum); @@ -627,8 +627,8 @@ static const char *ec_text[] = { "Left", "Right", "Left + Right", }; -static const struct soc_enum ec_enum = - SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text); +static SOC_ENUM_SINGLE_DECL(ec_enum, + PM860X_EC_PATH, 1, ec_text); static const struct snd_kcontrol_new ec_mux = SOC_DAPM_ENUM("EC Mux", ec_enum); @@ -638,36 +638,36 @@ static const char *dac_text[] = { }; /* DAC Headset 1 Mux / Mux10 */ -static const struct soc_enum dac_hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_hs1_enum, + PM860X_ANA_INPUT_SEL_1, 0, dac_text); static const struct snd_kcontrol_new dac_hs1_mux = SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum); /* DAC Headset 2 Mux / Mux11 */ -static const struct soc_enum dac_hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_hs2_enum, + PM860X_ANA_INPUT_SEL_1, 2, dac_text); static const struct snd_kcontrol_new dac_hs2_mux = SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum); /* DAC Lineout 1 Mux / Mux12 */ -static const struct soc_enum dac_lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_lo1_enum, + PM860X_ANA_INPUT_SEL_1, 4, dac_text); static const struct snd_kcontrol_new dac_lo1_mux = SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum); /* DAC Lineout 2 Mux / Mux13 */ -static const struct soc_enum dac_lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_lo2_enum, + PM860X_ANA_INPUT_SEL_1, 6, dac_text); static const struct snd_kcontrol_new dac_lo2_mux = SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum); /* DAC Spearker Earphone Mux / Mux14 */ -static const struct soc_enum dac_spk_ear_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_spk_ear_enum, + PM860X_ANA_INPUT_SEL_2, 0, dac_text); static const struct snd_kcontrol_new dac_spk_ear_mux = SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum); @@ -677,29 +677,29 @@ static const char *in_text[] = { "Digital", "Analog", }; -static const struct soc_enum hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text); +static SOC_ENUM_SINGLE_DECL(hs1_enum, + PM860X_ANA_TO_ANA, 0, in_text); static const struct snd_kcontrol_new hs1_mux = SOC_DAPM_ENUM("Headset1 Mux", hs1_enum); /* Headset 2 Mux / Mux16 */ -static const struct soc_enum hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text); +static SOC_ENUM_SINGLE_DECL(hs2_enum, + PM860X_ANA_TO_ANA, 1, in_text); static const struct snd_kcontrol_new hs2_mux = SOC_DAPM_ENUM("Headset2 Mux", hs2_enum); /* Lineout 1 Mux / Mux17 */ -static const struct soc_enum lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text); +static SOC_ENUM_SINGLE_DECL(lo1_enum, + PM860X_ANA_TO_ANA, 2, in_text); static const struct snd_kcontrol_new lo1_mux = SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum); /* Lineout 2 Mux / Mux18 */ -static const struct soc_enum lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text); +static SOC_ENUM_SINGLE_DECL(lo2_enum, + PM860X_ANA_TO_ANA, 3, in_text); static const struct snd_kcontrol_new lo2_mux = SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum); @@ -709,8 +709,8 @@ static const char *spk_text[] = { "Earpiece", "Speaker", }; -static const struct soc_enum spk_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text); +static SOC_ENUM_SINGLE_DECL(spk_enum, + PM860X_ANA_TO_ANA, 6, spk_text); static const struct snd_kcontrol_new spk_demux = SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum); @@ -720,8 +720,8 @@ static const char *mic_text[] = { "Mic 1", "Mic 2", }; -static const struct soc_enum mic_enum = - SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text); +static SOC_ENUM_SINGLE_DECL(mic_enum, + PM860X_ADC_ANA_4, 4, mic_text); static const struct snd_kcontrol_new mic_mux = SOC_DAPM_ENUM("MIC Mux", mic_enum); -- cgit v0.10.2 From cbf6242281069c3405b57fc10563d094aae6c9c0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:45 +0100 Subject: ASoC: ak4641: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 94cbe50..684b56f 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -113,14 +113,14 @@ static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); -static const struct soc_enum ak4641_mono_out_enum = - SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); -static const struct soc_enum ak4641_hp_out_enum = - SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); -static const struct soc_enum ak4641_mic_select_enum = - SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); -static const struct soc_enum ak4641_mic_or_dac_enum = - SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); +static SOC_ENUM_SINGLE_DECL(ak4641_mono_out_enum, + AK4641_SIG1, 6, ak4641_mono_out); +static SOC_ENUM_SINGLE_DECL(ak4641_hp_out_enum, + AK4641_MODE2, 2, ak4641_hp_out); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_select_enum, + AK4641_MIC, 1, ak4641_mic_select); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_or_dac_enum, + AK4641_BTIF, 4, ak4641_mic_or_dac); static const struct snd_kcontrol_new ak4641_snd_controls[] = { SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), -- cgit v0.10.2 From 64e6b58db9c3ee550092c73e18e36ad9dc168334 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:58 +0100 Subject: ASoC: ak4671: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 743bbe3..deb2b44 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -237,19 +237,17 @@ static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = { /* Input MUXs */ static const char *ak4671_lin_mux_texts[] = {"LIN1", "LIN2", "LIN3", "LIN4"}; -static const struct soc_enum ak4671_lin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0, - ARRAY_SIZE(ak4671_lin_mux_texts), - ak4671_lin_mux_texts); +static SOC_ENUM_SINGLE_DECL(ak4671_lin_mux_enum, + AK4671_MIC_SIGNAL_SELECT, 0, + ak4671_lin_mux_texts); static const struct snd_kcontrol_new ak4671_lin_mux_control = SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); static const char *ak4671_rin_mux_texts[] = {"RIN1", "RIN2", "RIN3", "RIN4"}; -static const struct soc_enum ak4671_rin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2, - ARRAY_SIZE(ak4671_rin_mux_texts), - ak4671_rin_mux_texts); +static SOC_ENUM_SINGLE_DECL(ak4671_rin_mux_enum, + AK4671_MIC_SIGNAL_SELECT, 2, + ak4671_rin_mux_texts); static const struct snd_kcontrol_new ak4671_rin_mux_control = SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); -- cgit v0.10.2 From e84f2463765ff34a322511be815ad235dcc1f218 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:44:32 +0100 Subject: ASoC: alc5632: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index fb001c5..d885056 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -293,51 +293,59 @@ static const char * const alc5632_i2s_out_sel[] = { "ADC LR", "Voice Stereo Digital"}; /* auxout output mux */ -static const struct soc_enum alc5632_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_aux_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 6, + alc5632_aux_out_input_sel); static const struct snd_kcontrol_new alc5632_auxout_mux_controls = SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum); /* speaker output mux */ -static const struct soc_enum alc5632_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_spkout_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 10, + alc5632_spkout_input_sel); static const struct snd_kcontrol_new alc5632_spkout_mux_controls = SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum); /* headphone left output mux */ -static const struct soc_enum alc5632_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_hpl_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 9, + alc5632_hpl_out_input_sel); static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls = SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum); /* headphone right output mux */ -static const struct soc_enum alc5632_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_hpr_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 8, + alc5632_hpr_out_input_sel); static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls = SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum); /* speaker output N select */ -static const struct soc_enum alc5632_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_spk_n_sour_enum, + ALC5632_OUTPUT_MIXER_CTRL, 14, + alc5632_spk_n_sour_sel); static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls = SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum); /* speaker amplifier */ static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5632_amp_enum = - SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names); +static SOC_ENUM_SINGLE_DECL(alc5632_amp_enum, + ALC5632_OUTPUT_MIXER_CTRL, 13, + alc5632_amp_names); static const struct snd_kcontrol_new alc5632_amp_mux_controls = SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum); /* ADC output select */ -static const struct soc_enum alc5632_adcr_func_enum = - SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_adcr_func_enum, + ALC5632_DAC_FUNC_SELECT, 5, + alc5632_adcr_func_sel); static const struct snd_kcontrol_new alc5632_adcr_func_controls = SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum); /* I2S out select */ -static const struct soc_enum alc5632_i2s_out_enum = - SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_i2s_out_enum, + ALC5632_I2S_OUT_CTL, 5, + alc5632_i2s_out_sel); static const struct snd_kcontrol_new alc5632_i2s_out_controls = SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum); -- cgit v0.10.2 From 0cd257bf9b9b0cbb4fa1a5c988a232506997867c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Feb 2014 09:04:06 +0900 Subject: ASoC: alc5623: Convert to direct regmap API usage Convert to directly use the regmap API, allowing us to eliminate the last user of the ASoC level I/O implementations (there are still open coded I/O implementations in drivers), avoiding duplicating code in regmap. We no longer cache the entire CODEC register map on probe since the more advanced cache infrastructure in regmap is able to fill the cache on demand. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index ba61c07..ed50625 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); /* codec private data */ struct alc5623_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; u8 id; unsigned int sysclk; - u16 reg_cache[ALC5623_VENDOR_ID2+2]; unsigned int add_ctrl; unsigned int jack_det_ctrl; }; -static void alc5623_fill_cache(struct snd_soc_codec *codec) -{ - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; - - /* not really efficient ... */ - codec->cache_bypass = 1; - for (i = 0 ; i < codec->driver->reg_cache_size ; i += step) - cache[i] = snd_soc_read(codec, i); - codec->cache_bypass = 0; -} - static inline int alc5623_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, ALC5623_RESET, 0); @@ -875,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = { static int alc5623_suspend(struct snd_soc_codec *codec) { + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); + regcache_cache_only(alc5623->regmap, true); + return 0; } static int alc5623_resume(struct snd_soc_codec *codec) { - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + int ret; /* Sync reg_cache with the hardware */ - for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) - snd_soc_write(codec, i, cache[i]); + regcache_cache_only(alc5623->regmap, false); + ret = regcache_sync(alc5623->regmap); + if (ret != 0) { + dev_err(codec->dev, "Failed to sync register cache: %d\n", + ret); + regcache_cache_only(alc5623->regmap, true); + return ret; + } alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -906,14 +904,14 @@ static int alc5623_probe(struct snd_soc_codec *codec) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type); + codec->control_data = alc5623->regmap; + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } alc5623_reset(codec); - alc5623_fill_cache(codec); /* power on device */ alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -986,9 +984,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = { .suspend = alc5623_suspend, .resume = alc5623_resume, .set_bias_level = alc5623_set_bias_level, - .reg_cache_size = ALC5623_VENDOR_ID2+2, - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, +}; + +static const struct regmap_config alc5623_regmap = { + .reg_bits = 8, + .val_bits = 16, + .reg_stride = 2, + + .max_register = ALC5623_VENDOR_ID2, + .cache_type = REGCACHE_RBTREE, }; /* @@ -1002,19 +1006,32 @@ static int alc5623_i2c_probe(struct i2c_client *client, { struct alc5623_platform_data *pdata; struct alc5623_priv *alc5623; - int ret, vid1, vid2; + unsigned int vid1, vid2; + int ret; - vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); - if (vid1 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; + alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), + GFP_KERNEL); + if (alc5623 == NULL) + return -ENOMEM; + + alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap); + if (IS_ERR(alc5623->regmap)) { + ret = PTR_ERR(alc5623->regmap); + dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret); + return ret; + } + + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1); + if (ret < 0) { + dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret); + return ret; } vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); - vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); - if (vid2 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2); + if (ret < 0) { + dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret); + return ret; } if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { @@ -1027,11 +1044,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); - alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), - GFP_KERNEL); - if (alc5623 == NULL) - return -ENOMEM; - pdata = client->dev.platform_data; if (pdata) { alc5623->add_ctrl = pdata->add_ctrl; @@ -1054,7 +1066,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, } i2c_set_clientdata(client, alc5623); - alc5623->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, &soc_codec_device_alc5623, &alc5623_dai, 1); -- cgit v0.10.2 From 6109ab2bfc22c903e4e8592bdcce268758f1dd5b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:44:57 +0100 Subject: ASoC: wm2200: Use SOC_ENUM_SINGLE_*_DECL() Just replace with the helper macros. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea83..1703b9c 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -135,8 +135,7 @@ static const char *chan_mix[] = { "R L", }; -static const struct soc_enum cs42l51_chan_mix = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix); +static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix); static const struct snd_kcontrol_new cs42l51_snd_controls[] = { SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", @@ -192,22 +191,22 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, static const char *cs42l51_dac_names[] = {"Direct PCM", "DSP PCM", "ADC"}; -static const struct soc_enum cs42l51_dac_mux_enum = - SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum, + CS42L51_DAC_CTL, 6, cs42l51_dac_names); static const struct snd_kcontrol_new cs42l51_dac_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum); static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left", "MIC Left", "MIC+preamp Left"}; -static const struct soc_enum cs42l51_adcl_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum, + CS42L51_ADC_INPUT, 4, cs42l51_adcl_names); static const struct snd_kcontrol_new cs42l51_adcl_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum); static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right", "MIC Right", "MIC+preamp Right"}; -static const struct soc_enum cs42l51_adcr_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum, + CS42L51_ADC_INPUT, 6, cs42l51_adcr_names); static const struct snd_kcontrol_new cs42l51_adcr_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum); -- cgit v0.10.2 From 7e5091087246b620dfbfed2ce4f17c53898b66d4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:17 +0100 Subject: ASoC: da732x: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f295b65..3219fa1 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -269,81 +269,65 @@ static const char *da732x_hpf_voice[] = { "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da732x_dac1_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; - -static const struct soc_enum da732x_dac2_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_hpf_mode_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac3_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_hpf_mode_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_adc1_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_hpf_mode_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_adc2_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_hpf_mode_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac1_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc2_hpf_mode_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac2_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_hp_filter_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac3_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_hp_filter_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_adc1_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_hp_filter_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_adc2_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_hp_filter_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac1_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc2_hp_filter_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac2_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_voice_filter_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_dac3_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_voice_filter_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_adc1_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_voice_filter_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_adc2_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_voice_filter_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); +static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); static int da732x_hpf_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -714,65 +698,65 @@ static const char *enable_text[] = { }; /* ADC1LMUX */ -static const struct soc_enum adc1l_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, - DA732X_ADCL_MUX_MAX, adcl_text); +static SOC_ENUM_SINGLE_DECL(adc1l_enum, + DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, + adcl_text); static const struct snd_kcontrol_new adc1l_mux = SOC_DAPM_ENUM("ADC Route", adc1l_enum); /* ADC1RMUX */ -static const struct soc_enum adc1r_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, - DA732X_ADCR_MUX_MAX, adcr_text); +static SOC_ENUM_SINGLE_DECL(adc1r_enum, + DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, + adcr_text); static const struct snd_kcontrol_new adc1r_mux = SOC_DAPM_ENUM("ADC Route", adc1r_enum); /* ADC2LMUX */ -static const struct soc_enum adc2l_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, - DA732X_ADCL_MUX_MAX, adcl_text); +static SOC_ENUM_SINGLE_DECL(adc2l_enum, + DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, + adcl_text); static const struct snd_kcontrol_new adc2l_mux = SOC_DAPM_ENUM("ADC Route", adc2l_enum); /* ADC2RMUX */ -static const struct soc_enum adc2r_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, - DA732X_ADCR_MUX_MAX, adcr_text); +static SOC_ENUM_SINGLE_DECL(adc2r_enum, + DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, + adcr_text); static const struct snd_kcontrol_new adc2r_mux = SOC_DAPM_ENUM("ADC Route", adc2r_enum); -static const struct soc_enum da732x_hp_left_output = - SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_hp_left_output, + DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new hpl_mux = SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); -static const struct soc_enum da732x_hp_right_output = - SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_hp_right_output, + DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new hpr_mux = SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); -static const struct soc_enum da732x_speaker_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_speaker_output, + DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new spk_mux = SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); -static const struct soc_enum da732x_lout4_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_lout4_output, + DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new lout4_mux = SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); -static const struct soc_enum da732x_lout2_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_lout2_output, + DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new lout2_mux = SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); -- cgit v0.10.2 From c3518d1bd45ebfdfd88480e5781054fed378fb22 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:36 +0100 Subject: ASoC: ml26124: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 185fa3bc..577fb87 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -73,11 +73,11 @@ static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); static const char * const ml26124_companding[] = {"16bit PCM", "u-law", "A-law"}; -static const struct soc_enum ml26124_adc_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum, + ML26124_SAI_TRANS_CTL, 6, ml26124_companding); -static const struct soc_enum ml26124_dac_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum, + ML26124_SAI_RCV_CTL, 6, ml26124_companding); static const struct snd_kcontrol_new ml26124_snd_controls[] = { SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0, @@ -136,8 +136,8 @@ static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = { static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in", "Digital MIC in", "Analog MIC Differential in"}; -static const struct soc_enum ml26124_insel_enum = - SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select); +static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum, + ML26124_MIC_IF_CTL, 0, ml26124_input_select); static const struct snd_kcontrol_new ml26124_input_mux_controls = SOC_DAPM_ENUM("Input Select", ml26124_insel_enum); -- cgit v0.10.2 From 806057cc75ef641cd9b012b0278c1f179090bab2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:53 +0100 Subject: ASoC: tlv320aic23: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc..139f11f 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -64,16 +64,16 @@ static const struct regmap_config tlv320aic23_regmap = { static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum rec_src_enum = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(rec_src_enum, + TLV320AIC23_ANLG, 2, rec_src_text); static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = SOC_DAPM_ENUM("Input Select", rec_src_enum); -static const struct soc_enum tlv320aic23_rec_src = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); -static const struct soc_enum tlv320aic23_deemph = - SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, + TLV320AIC23_ANLG, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, + TLV320AIC23_DIGT, 1, deemph_text); static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); -- cgit v0.10.2 From 0224ba6a01983a52ed809bdc8647510d02656143 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:09 +0100 Subject: ASoC: wm5100: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4e3e31a..14beefd 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -506,21 +506,21 @@ static const char *wm5100_lhpf_mode_text[] = { "Low-pass", "High-pass" }; -static const struct soc_enum wm5100_lhpf1_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf1_mode, + WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf2_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf2_mode, + WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf3_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf3_mode, + WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf4_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf4_mode, + WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, + wm5100_lhpf_mode_text); static const struct snd_kcontrol_new wm5100_snd_controls[] = { SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL, -- cgit v0.10.2 From 54db41c116c31b8829ba636895556a9fa45df987 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:22 +0100 Subject: ASoC: wm8955: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 82c8ba9..d4dcaec 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -416,22 +416,21 @@ static const char *bass_mode_text[] = { "Linear", "Adaptive", }; -static const struct soc_enum bass_mode = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text); +static SOC_ENUM_SINGLE_DECL(bass_mode, WM8955_BASS_CONTROL, 7, bass_mode_text); static const char *bass_cutoff_text[] = { "Low", "High" }; -static const struct soc_enum bass_cutoff = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text); +static SOC_ENUM_SINGLE_DECL(bass_cutoff, WM8955_BASS_CONTROL, 6, + bass_cutoff_text); static const char *treble_cutoff_text[] = { "High", "Low" }; -static const struct soc_enum treble_cutoff = - SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text); +static SOC_ENUM_SINGLE_DECL(treble_cutoff, WM8955_TREBLE_CONTROL, 2, + treble_cutoff_text); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); -- cgit v0.10.2 From b13a054aed6f6f3103df14f8bb0f9da4c4edb514 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:35 +0100 Subject: ASoC: wm8988: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index c6e4aba..0277a76 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -126,46 +126,46 @@ struct wm8988_priv { */ static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"}; -static const struct soc_enum bass_boost = - SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt); +static SOC_ENUM_SINGLE_DECL(bass_boost, + WM8988_BASS, 7, bass_boost_txt); static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; -static const struct soc_enum bass_filter = - SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt); +static SOC_ENUM_SINGLE_DECL(bass_filter, + WM8988_BASS, 6, bass_filter_txt); static const char *treble_txt[] = {"8kHz", "4kHz"}; -static const struct soc_enum treble = - SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt); +static SOC_ENUM_SINGLE_DECL(treble, + WM8988_TREBLE, 6, treble_txt); static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"}; -static const struct soc_enum stereo_3d_lc = - SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_lc, + WM8988_3D, 5, stereo_3d_lc_txt); static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"}; -static const struct soc_enum stereo_3d_uc = - SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_uc, + WM8988_3D, 6, stereo_3d_uc_txt); static const char *stereo_3d_func_txt[] = {"Capture", "Playback"}; -static const struct soc_enum stereo_3d_func = - SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_func, + WM8988_3D, 7, stereo_3d_func_txt); static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"}; -static const struct soc_enum alc_func = - SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt); +static SOC_ENUM_SINGLE_DECL(alc_func, + WM8988_ALC1, 7, alc_func_txt); static const char *ng_type_txt[] = {"Constant PGA Gain", "Mute ADC Output"}; -static const struct soc_enum ng_type = - SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt); +static SOC_ENUM_SINGLE_DECL(ng_type, + WM8988_NGATE, 1, ng_type_txt); static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum deemph = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt); +static SOC_ENUM_SINGLE_DECL(deemph, + WM8988_ADCDAC, 1, deemph_txt); static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert", "L + R Invert"}; -static const struct soc_enum adcpol = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt); +static SOC_ENUM_SINGLE_DECL(adcpol, + WM8988_ADCDAC, 5, adcpol_txt); static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); @@ -317,16 +317,16 @@ static const struct snd_kcontrol_new wm8988_right_pga_controls = /* Differential Mux */ static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"}; -static const struct soc_enum diffmux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel); +static SOC_ENUM_SINGLE_DECL(diffmux, + WM8988_ADCIN, 8, wm8988_diff_sel); static const struct snd_kcontrol_new wm8988_diffmux_controls = SOC_DAPM_ENUM("Route", diffmux); /* Mono ADC Mux */ static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)", "Mono (Right)", "Digital Mono"}; -static const struct soc_enum monomux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux); +static SOC_ENUM_SINGLE_DECL(monomux, + WM8988_ADCIN, 6, wm8988_mono_mux); static const struct snd_kcontrol_new wm8988_monomux_controls = SOC_DAPM_ENUM("Route", monomux); -- cgit v0.10.2 From aedbfd9649c5a9ee8e601f8f35e74ea617371ae5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:48 +0100 Subject: ASoC: wm9081: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 0982c1d..721cee7 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -268,8 +268,7 @@ static const char *drc_high_text[] = { "0", }; -static const struct soc_enum drc_high = - SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text); +static SOC_ENUM_SINGLE_DECL(drc_high, WM9081_DRC_3, 3, drc_high_text); static const char *drc_low_text[] = { "1", @@ -279,8 +278,7 @@ static const char *drc_low_text[] = { "0", }; -static const struct soc_enum drc_low = - SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text); +static SOC_ENUM_SINGLE_DECL(drc_low, WM9081_DRC_3, 0, drc_low_text); static const char *drc_atk_text[] = { "181us", @@ -297,8 +295,7 @@ static const char *drc_atk_text[] = { "185.6ms", }; -static const struct soc_enum drc_atk = - SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text); +static SOC_ENUM_SINGLE_DECL(drc_atk, WM9081_DRC_2, 12, drc_atk_text); static const char *drc_dcy_text[] = { "186ms", @@ -312,8 +309,7 @@ static const char *drc_dcy_text[] = { "47.56s", }; -static const struct soc_enum drc_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text); +static SOC_ENUM_SINGLE_DECL(drc_dcy, WM9081_DRC_2, 8, drc_dcy_text); static const char *drc_qr_dcy_text[] = { "0.725ms", @@ -321,8 +317,7 @@ static const char *drc_qr_dcy_text[] = { "5.8ms", }; -static const struct soc_enum drc_qr_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_dcy, WM9081_DRC_2, 4, drc_qr_dcy_text); static const char *dac_deemph_text[] = { "None", @@ -331,16 +326,16 @@ static const char *dac_deemph_text[] = { "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, WM9081_DAC_DIGITAL_2, 1, + dac_deemph_text); static const char *speaker_mode_text[] = { "Class D", "Class AB", }; -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, WM9081_ANALOGUE_SPEAKER_2, 6, + speaker_mode_text); static int speaker_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v0.10.2 From 09981dcb77eba05974eed4def32931fb12421fae Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:00 +0100 Subject: ASoC: wm9705: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 70ce6793..c0b7f45 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -67,12 +67,12 @@ static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", "Line", "Stereo Mix", "Mono Mix", "Phone"}; -static const struct soc_enum wm9705_enum_mic = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); -static const struct soc_enum wm9705_enum_rec_l = - SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); -static const struct soc_enum wm9705_enum_rec_r = - SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_mic, + AC97_GENERAL_PURPOSE, 8, wm9705_mic); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_l, + AC97_REC_SEL, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_r, + AC97_REC_SEL, 0, wm9705_rec_sel); /* Headphone Mixer */ static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { -- cgit v0.10.2 From 2e86434f9eeb4a6d9379895b889ac85fa51b0ac9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:54:31 +0100 Subject: ASoC: ad1836: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 77f4598..685998d 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -40,8 +40,8 @@ struct ad1836_priv { */ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; -static const struct soc_enum ad1836_deemp_enum = - SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); +static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum, + AD1836_DAC_CTRL1, 8, ad1836_deemp); #define AD1836_DAC_VOLUME(x) \ SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ -- cgit v0.10.2 From 52a5b545bc09ebc7b1e4a55d765ccb76286ca48d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:57:55 +0100 Subject: ASoC: cs42l73: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Acked-by: Brian Austin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 69c8e2d..06f4291 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -278,13 +278,13 @@ static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" }; static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" }; -static const struct soc_enum pgaa_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3, - ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text); +static SOC_ENUM_SINGLE_DECL(pgaa_enum, + CS42L73_ADCIPC, 3, + cs42l73_pgaa_text); -static const struct soc_enum pgab_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7, - ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text); +static SOC_ENUM_SINGLE_DECL(pgab_enum, + CS42L73_ADCIPC, 7, + cs42l73_pgab_text); static const struct snd_kcontrol_new pgaa_mux = SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum); @@ -309,9 +309,9 @@ static const struct snd_kcontrol_new input_right_mixer[] = { static const char * const cs42l73_ng_delay_text[] = { "50ms", "100ms", "150ms", "200ms" }; -static const struct soc_enum ng_delay_enum = - SOC_ENUM_SINGLE(CS42L73_NGCAB, 0, - ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text); +static SOC_ENUM_SINGLE_DECL(ng_delay_enum, + CS42L73_NGCAB, 0, + cs42l73_ng_delay_text); static const char * const cs42l73_mono_mix_texts[] = { "Left", "Right", "Mono Mix"}; @@ -357,19 +357,19 @@ static const struct snd_kcontrol_new esl_xsp_mixer = static const char * const cs42l73_ip_swap_text[] = { "Stereo", "Mono A", "Mono B", "Swap A-B"}; -static const struct soc_enum ip_swap_enum = - SOC_ENUM_SINGLE(CS42L73_MIOPC, 6, - ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text); +static SOC_ENUM_SINGLE_DECL(ip_swap_enum, + CS42L73_MIOPC, 6, + cs42l73_ip_swap_text); static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"}; -static const struct soc_enum vsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); +static SOC_ENUM_SINGLE_DECL(vsp_output_mux_enum, + CS42L73_MIXERCTL, 5, + cs42l73_spo_mixer_text); -static const struct soc_enum xsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); +static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum, + CS42L73_MIXERCTL, 4, + cs42l73_spo_mixer_text); static const struct snd_kcontrol_new vsp_output_mux = SOC_DAPM_ENUM("Route", vsp_output_mux_enum); -- cgit v0.10.2 From d77c290af76637e87dc07df28536231ee5042c98 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 11:07:32 +0100 Subject: ASoC: tlv320dac33: Use SOC_ENUM_SINGLE_*_DECL() Just replace with the helper macros. No functional change at all. Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4f35839..9ce8496 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -478,9 +478,7 @@ static const char *dac33_fifo_mode_texts[] = { "Bypass", "Mode 1", "Mode 7" }; -static const struct soc_enum dac33_fifo_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), - dac33_fifo_mode_texts); +static SOC_ENUM_SINGLE_EXT_DECL(dac33_fifo_mode_enum, dac33_fifo_mode_texts); /* L/R Line Output Gain */ static const char *lr_lineout_gain_texts[] = { @@ -488,15 +486,13 @@ static const char *lr_lineout_gain_texts[] = { "Line 0dB DAC 12dB", "Line 6dB DAC 18dB", }; -static const struct soc_enum l_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); +static SOC_ENUM_SINGLE_DECL(l_lineout_gain_enum, + DAC33_LDAC_PWR_CTRL, 0, + lr_lineout_gain_texts); -static const struct soc_enum r_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); +static SOC_ENUM_SINGLE_DECL(r_lineout_gain_enum, + DAC33_RDAC_PWR_CTRL, 0, + lr_lineout_gain_texts); /* * DACL/R digital volume control: @@ -534,18 +530,16 @@ static const struct snd_kcontrol_new dac33_dapm_abypassr_control = /* LOP L/R invert selection */ static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"}; -static const struct soc_enum dac33_left_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); +static SOC_ENUM_SINGLE_DECL(dac33_left_lom_enum, + DAC33_OUT_AMP_CTRL, 3, + dac33_lr_lom_texts); static const struct snd_kcontrol_new dac33_dapm_left_lom_control = SOC_DAPM_ENUM("Route", dac33_left_lom_enum); -static const struct soc_enum dac33_right_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); +static SOC_ENUM_SINGLE_DECL(dac33_right_lom_enum, + DAC33_OUT_AMP_CTRL, 2, + dac33_lr_lom_texts); static const struct snd_kcontrol_new dac33_dapm_right_lom_control = SOC_DAPM_ENUM("Route", dac33_right_lom_enum); -- cgit v0.10.2 From daf152a21d361967bd9d2d7a976c125de842d589 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 11:49:02 +0100 Subject: ASoC: wm5102: Use ARRAY_SIZE() for SOC_VALUE_ENUM_SINGLE() ... to make clear the meaning of the argument. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index ebffe81..293dffc 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -622,13 +622,16 @@ static const unsigned int wm5102_osr_val[] = { static const struct soc_enum wm5102_hpout_osr[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, - ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT1_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L, - ARIZONA_OUT2_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT2_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, - ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT3_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), }; -- cgit v0.10.2 From 347e5512642da44d15bf8b48ee0fe196b37a78f1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 11:49:56 +0100 Subject: ASoC: wm8997: Use ARRAY_SIZE() for SOC_VALUE_ENUM_SINGLE() ... to make clear the meaning of the argument. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 6107108..4e6442c 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -123,10 +123,12 @@ static const unsigned int wm8997_osr_val[] = { static const struct soc_enum wm8997_hpout_osr[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, - ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT1_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm8997_osr_text), wm8997_osr_text, wm8997_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, - ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT3_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm8997_osr_text), wm8997_osr_text, wm8997_osr_val), }; -- cgit v0.10.2 From 98b664e2ceddd40120e8cd2aa56f7eb9a51870cf Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:22:58 +0100 Subject: ASoC: tlv320aic32x4: Support for master clock Add support for a master clock passed through DT. The master clock of the codec is only active when the codec is in use. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt index db05510..352be7b 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -8,6 +8,8 @@ Required properties: Optional properties: - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt + - clocks/clock-names: Clock named 'mclk' for the master clock of the codec. + See clock/clock-bindings.txt for information about the detailed format. Example: @@ -15,4 +17,6 @@ Example: codec: tlv320aic32x4@18 { compatible = "ti,tlv320aic32x4"; reg = <0x18>; + clocks = <&clks 201>; + clock-names = "mclk"; }; diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 1dd50e4..643fa53 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,7 @@ struct aic32x4_priv { u32 micpga_routing; bool swapdacs; int rstn_gpio; + struct clk *mclk; }; /* 0dB min, 0.5dB steps */ @@ -487,8 +489,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute) static int aic32x4_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); + int ret; + switch (level) { case SND_SOC_BIAS_ON: + /* Switch on master clock */ + ret = clk_prepare_enable(aic32x4->mclk); + if (ret) { + dev_err(codec->dev, "Failed to enable master clock\n"); + return ret; + } + /* Switch on PLL */ snd_soc_update_bits(codec, AIC32X4_PLLPR, AIC32X4_PLLEN, AIC32X4_PLLEN); @@ -539,6 +551,9 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, /* Switch off BCLK_N Divider */ snd_soc_update_bits(codec, AIC32X4_BCLKN, AIC32X4_BCLKEN, 0); + + /* Switch off master clock */ + clk_disable_unprepare(aic32x4->mclk); break; case SND_SOC_BIAS_OFF: break; @@ -717,6 +732,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } + aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (IS_ERR(aic32x4->mclk)) { + dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); + return PTR_ERR(aic32x4->mclk); + } + if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); -- cgit v0.10.2 From 239b669b2dedc46d5e6b07d87c3d1dedf8d9477c Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:22:59 +0100 Subject: ASoC: tlv320aic32x4: Support for regulators Support regulators to power up the codec. This patch also enables the AVDD LDO if no AV regulator was found. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt index 352be7b..5e2741a 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -5,6 +5,14 @@ The tlv320aic32x4 serial control bus communicates through I2C protocols Required properties: - compatible: Should be "ti,tlv320aic32x4" - reg: I2C slave address + - supply-*: Required supply regulators are: + "iov" - digital IO power supply + "ldoin" - LDO power supply + "dv" - Digital core power supply + "av" - Analog core power supply + If you supply ldoin, dv and av are optional. Otherwise they are required + See regulator/regulator.txt for more information about the detailed binding + format. Optional properties: - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 643fa53..d69c61f 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,11 @@ struct aic32x4_priv { bool swapdacs; int rstn_gpio; struct clk *mclk; + + struct regulator *supply_ldo; + struct regulator *supply_iov; + struct regulator *supply_dv; + struct regulator *supply_av; }; /* 0dB min, 0.5dB steps */ @@ -695,6 +701,106 @@ static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, return 0; } +static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4) +{ + regulator_disable(aic32x4->supply_iov); + + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + + if (!IS_ERR(aic32x4->supply_av)) + regulator_disable(aic32x4->supply_av); +} + +static int aic32x4_setup_regulators(struct device *dev, + struct aic32x4_priv *aic32x4) +{ + int ret = 0; + + aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin"); + aic32x4->supply_iov = devm_regulator_get(dev, "iov"); + aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv"); + aic32x4->supply_av = devm_regulator_get_optional(dev, "av"); + + /* Check if the regulator requirements are fulfilled */ + + if (IS_ERR(aic32x4->supply_iov)) { + dev_err(dev, "Missing supply 'iov'\n"); + return PTR_ERR(aic32x4->supply_iov); + } + + if (IS_ERR(aic32x4->supply_ldo)) { + if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (IS_ERR(aic32x4->supply_dv)) { + dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_dv); + } + if (IS_ERR(aic32x4->supply_av)) { + dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_av); + } + } else { + if (IS_ERR(aic32x4->supply_dv) && + PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (IS_ERR(aic32x4->supply_av) && + PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) + return -EPROBE_DEFER; + } + + ret = regulator_enable(aic32x4->supply_iov); + if (ret) { + dev_err(dev, "Failed to enable regulator iov\n"); + return ret; + } + + if (!IS_ERR(aic32x4->supply_ldo)) { + ret = regulator_enable(aic32x4->supply_ldo); + if (ret) { + dev_err(dev, "Failed to enable regulator ldo\n"); + goto error_ldo; + } + } + + if (!IS_ERR(aic32x4->supply_dv)) { + ret = regulator_enable(aic32x4->supply_dv); + if (ret) { + dev_err(dev, "Failed to enable regulator dv\n"); + goto error_dv; + } + } + + if (!IS_ERR(aic32x4->supply_av)) { + ret = regulator_enable(aic32x4->supply_av); + if (ret) { + dev_err(dev, "Failed to enable regulator av\n"); + goto error_av; + } + } + + if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av)) + aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE; + + return 0; + +error_av: + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + +error_dv: + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + +error_ldo: + regulator_disable(aic32x4->supply_iov); + return ret; +} + static int aic32x4_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -745,13 +851,31 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, return ret; } + ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); + if (ret) { + dev_err(&i2c->dev, "Failed to setup regulators\n"); + return ret; + } + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_aic32x4, &aic32x4_dai, 1); - return ret; + if (ret) { + dev_err(&i2c->dev, "Failed to register codec\n"); + aic32x4_disable_regulators(aic32x4); + return ret; + } + + i2c_set_clientdata(i2c, aic32x4); + + return 0; } static int aic32x4_i2c_remove(struct i2c_client *client) { + struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); + + aic32x4_disable_regulators(aic32x4); + snd_soc_unregister_codec(&client->dev); return 0; } -- cgit v0.10.2 From 3154cc7404506700ff270b6f123ec9c734f002fd Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:23:00 +0100 Subject: ASoC: tlv320aic32x4: Rearrange clock tree shutdown Rearrange clock tree shutdown to disable them in the reversed order of startup. First disable all dividers, then PLL followed by master clock. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index d69c61f..c6bd7e7 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -534,29 +534,29 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: - /* Switch off PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, 0); - - /* Switch off NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, 0); + /* Switch off BCLK_N Divider */ + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, 0); - /* Switch off MDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_MDAC, - AIC32X4_MDACEN, 0); + /* Switch off MADC Divider */ + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, 0); /* Switch off NADC Divider */ snd_soc_update_bits(codec, AIC32X4_NADC, AIC32X4_NADCEN, 0); - /* Switch off MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, 0); + /* Switch off MDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_MDAC, + AIC32X4_MDACEN, 0); - /* Switch off BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, 0); + /* Switch off NDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, 0); + + /* Switch off PLL */ + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, 0); /* Switch off master clock */ clk_disable_unprepare(aic32x4->mclk); -- cgit v0.10.2 From 72899ad8a46a80ad5fc725afea443f94945ae370 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 14 Feb 2014 09:34:34 +0800 Subject: ASoC: binding: add tdm-slot.txt Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.txt b/Documentation/devicetree/bindings/sound/tdm-slot.txt new file mode 100644 index 0000000..6a2c842 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tdm-slot.txt @@ -0,0 +1,20 @@ +TDM slot: + +This specifies audio DAI's TDM slot. + +TDM slot properties: +dai-tdm-slot-num : Number of slots in use. +dai-tdm-slot-width : Width in bits for each slot. + +For instance: + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; + +And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() +to specify a explicit mapping of the channels and the slots. If it's absent +the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the +tx and rx masks. + +For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit +for an active slot as default, and the default active bits are at the LSB of +the masks. -- cgit v0.10.2 From 89c6785715592a6b082b3f9f28c27bb14b041c7d Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 14 Feb 2014 09:34:35 +0800 Subject: ASoC: core: add TDM slot parsing from DT supports For some CPU/CODEC DAI devices the TDM slot infomation maybe needed. This patch adds the slot parsing from DT supports. TDM slot properties: dai-tdm-slot-num : Number of slots in use. dai-tdm-slot-width : Width in bits for each slot. For instance: dai-tdm-slot-num = <2>; dai-tdm-slot-width = <8>; And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() to specify a explicit mapping of the channels and the slots. If it's absent the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the tx and rx masks. For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit for an active slot as default, and the default active bits are at the LSB of the masks. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71f27c4..d86e0fc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -142,6 +142,8 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); + int (*of_xlate_tdm_slot_mask)(unsigned int slots, + unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); diff --git a/include/sound/soc.h b/include/sound/soc.h index 465dc6e..2a878d0 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1175,6 +1175,9 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0540cb0..5b7d3ba 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3609,6 +3609,30 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); /** + * snd_soc_of_xlate_tdm_slot - generate tx/rx slot mask. + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * Generates the TDM tx and rx slot default masks for DAI. + */ +static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (*tx_mask || *rx_mask) + return 0; + + if (!slots) + return -EINVAL; + + *tx_mask = (1 << slots) - 1; + *rx_mask = (1 << slots) - 1; + + return 0; +} + +/** * snd_soc_dai_set_tdm_slot - configure DAI TDM. * @dai: DAI * @tx_mask: bitmask representing active TX slots. @@ -3622,6 +3646,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { + if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) + dai->driver->ops->of_xlate_tdm_slot_mask(slots, + &tx_mask, &rx_mask); + else + snd_soc_of_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + if (dai->driver && dai->driver->ops->set_tdm_slot) return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); @@ -4504,6 +4534,35 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width) +{ + u32 val; + int ret; + + if (of_property_read_bool(np, "dai-tdm-slot-num")) { + ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); + if (ret) + return ret; + + if (slots) + *slots = val; + } + + if (of_property_read_bool(np, "dai-tdm-slot-width")) { + ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); + if (ret) + return ret; + + if (slot_width) + *slot_width = val; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) { -- cgit v0.10.2 From 6ff62eedce4f7756b092d276165d8e11edab9f28 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 14 Feb 2014 09:34:36 +0800 Subject: ASoC: simple-card: add slot information parsing supports For some CPU/CODEC DAI devices the slot information maybe needed. This patch adds the slot information parsing for simple-card driver. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index 0527358..b30c222 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -18,6 +18,8 @@ Optional properties: Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. +- dai-tdm-slot-num : Please refer to tdm-slot.txt. +- dai-tdm-slot-width : Please refer to tdm-slot.txt. Required subnodes: @@ -56,6 +58,9 @@ sound { "Headphone Jack", "HP_OUT", "External Speaker", "LINE_OUT"; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; + simple-audio-card,cpu { sound-dai = <&sh_fsi2 0>; }; diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index e1ac996..9b0ac77 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -18,6 +18,8 @@ struct asoc_simple_dai { const char *name; unsigned int fmt; unsigned int sysclk; + int slots; + int slot_width; }; struct asoc_simple_card_info { diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 4fe8abc..bdd176d 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -9,11 +9,14 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include #include #include +#include +#include struct simple_card_data { struct snd_soc_card snd_card; @@ -44,6 +47,16 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, } } + if (set->slots) { + ret = snd_soc_dai_set_tdm_slot(dai, 0, 0, + set->slots, + set->slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); + goto err; + } + } + ret = 0; err: @@ -94,6 +107,11 @@ asoc_simple_card_sub_parse_of(struct device_node *np, if (ret < 0) goto parse_error; + /* parse TDM slot */ + ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); + if (ret) + goto parse_error; + /* * bitclock-inversion, frame-inversion * bitclock-master, frame-master -- cgit v0.10.2 From a3db2bba6d1933a1398357ba6728c743bdab03e1 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 14 Feb 2014 10:15:03 -0500 Subject: MAINTAINERS: add additional ARM BCM281xx/BCM11xxx maintainer Add myself as an additional maintainer for the Broadcom mobile SoCs. Signed-off-by: Matt Porter Acked-by: Christian Daudt Signed-off-by: Olof Johansson diff --git a/MAINTAINERS b/MAINTAINERS index fb08dce..1d6e219 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1860,6 +1860,7 @@ F: drivers/net/ethernet/broadcom/bnx2x/ BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE M: Christian Daudt +M: Matt Porter L: bcm-kernel-feedback-list@broadcom.com T: git git://git.github.com/broadcom/bcm11351 S: Maintained -- cgit v0.10.2 From 44a589ca2de4d7980f8b335481a09bf818065dbe Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 6 Feb 2014 11:28:31 -0800 Subject: NFC: NCI: Fix NULL pointer dereference The check should be for setup function pointer. This patch fixes NULL pointer dereference issue for NCI based NFC driver which doesn't define setup handler. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Samuel Ortiz diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 46bda01..56db888 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -301,7 +301,7 @@ static int nci_open_device(struct nci_dev *ndev) rc = __nci_request(ndev, nci_reset_req, 0, msecs_to_jiffies(NCI_RESET_TIMEOUT)); - if (ndev->ops->setup(ndev)) + if (ndev->ops->setup) ndev->ops->setup(ndev); if (!rc) { -- cgit v0.10.2 From eae39cb4934d3daab3ec828c5201c955b2e56af9 Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Mon, 17 Feb 2014 13:11:23 +0530 Subject: mtd: nand: omap: fix ecclayout to be in sync with u-boot NAND driver Fixes: commit a919e51161b58ed7e6e663daba99ab7d558808f3 mtd: nand: omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe Fixes ecclayout mismatch introduced in above commit for following ecc-schemes: - OMAP_ECC_BCH4_CODE_HW_DETECTION_SW - OMAP_ECC_BCH8_CODE_HW_DETECTION_SW However, this patch also touches other ecc-schemes as the fix required refactoring common code, into ecc-scheme specific code. This patch aligns ecc-layout for below ecc-schemes as per reference [1],[2],[3] +---+------------+-------------++-------------+-------------+ |OOB|BCH8_CODE_HW|BCH8_CODE_HW_||HAM1_CODE_HW |HAM1_CODE_HW | |pos| | DETECTION_SW||(x8 device) |(x16 device) | +---+------------+-------------++-------------+-------------+ | 0 |BADBLK_MARK | BADBLK_MARK || BADBLK_MARK | BADBLK_MARK | | 1 |BADBLK_MARK | BADBLK_MARK || eccpos[0] | BADBLK_MARK | | 2 | eccpos[0] | eccpos[0] || eccpos[1] | eccpos[0] | | 3 | eccpos[1] | eccpos[1] || eccpos[2] | eccpos[1] | | 4 | eccpos[2] | eccpos[2] || eccpos[3] | eccpos[2] | | 5 | eccpos[3] | eccpos[3] || eccpos[4] | eccpos[3] | | 6 | eccpos[4] | eccpos[4] || eccpos[5] | eccpos[4] | | 7 | eccpos[5] | eccpos[5] || eccpos[6] | eccpos[5] | | 8 | eccpos[6] | eccpos[6] || eccpos[7] | eccpos[6] | | 9 | eccpos[7] | eccpos[7] || eccpos[8] | eccpos[7] | |10 | eccpos[8] | eccpos[8] || eccpos[9] | eccpos[8] | |11 | eccpos[9] | eccpos[9] || eccpos[10] | eccpos[9] | |12 | eccpos[10] | eccpos[10] || eccpos[11] | eccpos[10] | |13 | eccpos[11] | eccpos[11] || oobfree[0] | eccpos[11] | |14 | eccpos[12] | eccpos[12] || oobfree[1] | oobfree[0] | |15 | eccpos[13] | || oobfree[2] | oobfree[1] | +---+------------+-------------++-------------+-------------+ |16 | eccpos[14] | eccpos[13] || oobfree[3] | oobfree[2] | |...| [...] | [...] || [...] | [...] | |56 | eccpos[54] | eccpos[51] || oobfree[43] | oobfree[42] | |57 | eccpos[55] | || oobfree[44] | oobfree[43] | +===+============+=============+==============+=============+ |58 | oobfree[0] | oobfree[0] || oobfree[45] | oobfree[44] | |59 | oobfree[1] | oobfree[1] || oobfree[46] | oobfree[45] | |60 | oobfree[2] | oobfree[2] || oobfree[47] | oobfree[46] | |61 | oobfree[3] | oobfree[3] || oobfree[48] | oobfree[47] | |62 | oobfree[4] | oobfree[4] || oobfree[49] | oobfree[48] | |63 | oobfree[5] | oobfree[5] || oobfree[50] | oobfree[49] | +---+------------+-------------+--------------+-------------+ [1] ecc-layout expected by ROM code, as specified in SoC TRM under: Chapter="Initialization" Section="Device Initialization by ROM code" Sub-Section="Memory Booting" Heading="NAND" Figure="ECC Locations in NAND Spare Areas" [2] ecc-layout updates in u-boot http://lists.denx.de/pipermail/u-boot/2013-November/167551.html [3] u-boot configurations to match above ecc-layout are documented at https://processors.wiki.ti.com/index.php/Linux_Core_NAND_User%27s_Guide CC: # 3.13.x+ Reported-by: Enric Balletbo Serra Tested-by: Enric Balletbo i Serra Tested-by: Stefan Roese Signed-off-by: Pekon Gupta Signed-off-by: Brian Norris diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ef4190a..34ef941 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1633,6 +1633,7 @@ static int omap_nand_probe(struct platform_device *pdev) int i; dma_cap_mask_t mask; unsigned sig; + unsigned oob_index; struct resource *res; struct mtd_part_parser_data ppdata = {}; @@ -1826,9 +1827,11 @@ static int omap_nand_probe(struct platform_device *pdev) (mtd->writesize / nand_chip->ecc.size); if (nand_chip->options & NAND_BUSWIDTH_16) - ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; + oob_index = BADBLOCK_MARKER_LENGTH; else - ecclayout->eccpos[0] = 1; + oob_index = 1; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; ecclayout->oobfree->offset = ecclayout->eccpos[0] + ecclayout->eccbytes; break; @@ -1847,7 +1850,12 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->eccbytes = nand_chip->ecc.bytes * (mtd->writesize / nand_chip->ecc.size); - ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { + ecclayout->eccpos[i] = oob_index; + if (((i + 1) % nand_chip->ecc.bytes) == 0) + oob_index++; + } ecclayout->oobfree->offset = ecclayout->eccpos[0] + ecclayout->eccbytes; /* software bch library is used for locating errors */ @@ -1883,7 +1891,9 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->eccbytes = nand_chip->ecc.bytes * (mtd->writesize / nand_chip->ecc.size); - ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; ecclayout->oobfree->offset = ecclayout->eccpos[0] + ecclayout->eccbytes; /* This ECC scheme requires ELM H/W block */ @@ -1913,7 +1923,12 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->eccbytes = nand_chip->ecc.bytes * (mtd->writesize / nand_chip->ecc.size); - ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { + ecclayout->eccpos[i] = oob_index; + if (((i + 1) % nand_chip->ecc.bytes) == 0) + oob_index++; + } ecclayout->oobfree->offset = ecclayout->eccpos[0] + ecclayout->eccbytes; /* software bch library is used for locating errors */ @@ -1956,7 +1971,9 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->eccbytes = nand_chip->ecc.bytes * (mtd->writesize / nand_chip->ecc.size); - ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; ecclayout->oobfree->offset = ecclayout->eccpos[0] + ecclayout->eccbytes; break; @@ -1975,8 +1992,6 @@ static int omap_nand_probe(struct platform_device *pdev) /* populate remaining ECC layout data */ ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH + ecclayout->eccbytes); - for (i = 1; i < ecclayout->eccbytes; i++) - ecclayout->eccpos[i] = ecclayout->eccpos[0] + i; /* check if NAND device's OOB is enough to store ECC signatures */ if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) { pr_err("not enough OOB bytes required = %d, available=%d\n", -- cgit v0.10.2 From aa6092f9835893290e77c3e24649def49dac1583 Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Mon, 17 Feb 2014 13:11:24 +0530 Subject: mtd: nand: omap: fix ecclayout->oobfree->offset 1) In current implementation, ecclayout->oobfree->offset is calculated with respect to ecclayout->eccpos[0] which is incorrect because ECC bytes may not be stored contiguously in OOB. So, this patch calculates ecclayout->oobfree->offset with respect to last ECC byte-position 'eccpos[ecclayout->eccbytes-1]'. 2) ECC layout of some ecc-schemes expects reserved-markers at specific eccpos[] which should not be over-written by any file-system metadata. So this patch aligns oobfree->offset taking into account of such markers. CC: # 3.13.x+ Tested-by: Enric Balletbo i Serra Tested-by: Stefan Roese Signed-off-by: Pekon Gupta Signed-off-by: Brian Norris diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 34ef941..58685ab 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1832,8 +1832,9 @@ static int omap_nand_probe(struct platform_device *pdev) oob_index = 1; for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) ecclayout->eccpos[i] = oob_index; - ecclayout->oobfree->offset = ecclayout->eccpos[0] + - ecclayout->eccbytes; + /* no reserved-marker in ecclayout for this ecc-scheme */ + ecclayout->oobfree->offset = + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; break; case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: @@ -1856,8 +1857,9 @@ static int omap_nand_probe(struct platform_device *pdev) if (((i + 1) % nand_chip->ecc.bytes) == 0) oob_index++; } - ecclayout->oobfree->offset = ecclayout->eccpos[0] + - ecclayout->eccbytes; + /* include reserved-marker in ecclayout->oobfree calculation */ + ecclayout->oobfree->offset = 1 + + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; /* software bch library is used for locating errors */ nand_chip->ecc.priv = nand_bch_init(mtd, nand_chip->ecc.size, @@ -1894,8 +1896,9 @@ static int omap_nand_probe(struct platform_device *pdev) oob_index = BADBLOCK_MARKER_LENGTH; for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) ecclayout->eccpos[i] = oob_index; - ecclayout->oobfree->offset = ecclayout->eccpos[0] + - ecclayout->eccbytes; + /* reserved marker already included in ecclayout->eccbytes */ + ecclayout->oobfree->offset = + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; /* This ECC scheme requires ELM H/W block */ if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) { pr_err("nand: error: could not initialize ELM\n"); @@ -1929,8 +1932,9 @@ static int omap_nand_probe(struct platform_device *pdev) if (((i + 1) % nand_chip->ecc.bytes) == 0) oob_index++; } - ecclayout->oobfree->offset = ecclayout->eccpos[0] + - ecclayout->eccbytes; + /* include reserved-marker in ecclayout->oobfree calculation */ + ecclayout->oobfree->offset = 1 + + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; /* software bch library is used for locating errors */ nand_chip->ecc.priv = nand_bch_init(mtd, nand_chip->ecc.size, @@ -1974,8 +1978,9 @@ static int omap_nand_probe(struct platform_device *pdev) oob_index = BADBLOCK_MARKER_LENGTH; for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) ecclayout->eccpos[i] = oob_index; - ecclayout->oobfree->offset = ecclayout->eccpos[0] + - ecclayout->eccbytes; + /* reserved marker already included in ecclayout->eccbytes */ + ecclayout->oobfree->offset = + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; break; #else pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); -- cgit v0.10.2 From bb38eefb6858ce16b34716145b9597a5680aa54c Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Mon, 17 Feb 2014 13:11:25 +0530 Subject: mtd: nand: omap: fix ecclayout->oobfree->length This patch excludes reserved-marker byte-position from oobfree->length calculation. Thus all bytes from oobfree->offset till end of OOB are free. CC: # 3.13.x+ Signed-off-by: Pekon Gupta Signed-off-by: Brian Norris diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 58685ab..bf642ce 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1994,9 +1994,8 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } - /* populate remaining ECC layout data */ - ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH + - ecclayout->eccbytes); + /* all OOB bytes from oobfree->offset till end off OOB are free */ + ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset; /* check if NAND device's OOB is enough to store ECC signatures */ if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) { pr_err("not enough OOB bytes required = %d, available=%d\n", -- cgit v0.10.2 From 10762e80489e73e2d52bf78e0869f253f42821bd Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 23 Feb 2014 12:52:44 +0000 Subject: target/sbc: Fix sbc_dif_copy_prot addr offset bug This patch fixes a bug in sbc_dif_copy_prot() where the updated addr offset did not take into account the case where the associated scatterlist had not been incremented. This addresses the case where incoming protection scatterlists may contain a length smaller than PAGE_SIZE across multiple entires, when the target protection scatterlists are always being explicitly filled up to PAGE_SIZE before adding another entry. Cc: Martin K. Petersen Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Sagi Grimberg Cc: Or Gerlitz Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a448944..ef1a58a 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -1074,7 +1074,7 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, struct scatterlist *psg; void *paddr, *addr; unsigned int i, len, left; - unsigned int offset = 0; + unsigned int offset = sg_off; left = sectors * dev->prot_length; @@ -1084,11 +1084,10 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, if (offset >= sg->length) { sg = sg_next(sg); offset = 0; - sg_off = sg->offset; } paddr = kmap_atomic(sg_page(psg)) + psg->offset; - addr = kmap_atomic(sg_page(sg)) + sg_off; + addr = kmap_atomic(sg_page(sg)) + sg->offset + offset; if (read) memcpy(paddr, addr, len); -- cgit v0.10.2 From 94387aa7cec8c5386b405b852cf3e5be38456fc7 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 23 Feb 2014 14:04:09 +0000 Subject: target: Add DIF sense codes in transport_generic_request_failure This patch adds the three missing DIF related sense codes within transport_generic_request_failure(), which are required to ensure that the correct ASC/ASQC is generated by the subsequent call to transport_send_check_condition_and_sense(). Cc: Martin K. Petersen Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Sagi Grimberg Cc: Or Gerlitz Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 24b4f65d..2956250 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1601,6 +1601,9 @@ void transport_generic_request_failure(struct se_cmd *cmd, case TCM_CHECK_CONDITION_ABORT_CMD: case TCM_CHECK_CONDITION_UNIT_ATTENTION: case TCM_CHECK_CONDITION_NOT_READY: + case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: + case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: + case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: break; case TCM_OUT_OF_RESOURCES: sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; -- cgit v0.10.2 From fc272ec7a2dfe002b823c78f8ef0eb88042e2762 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Sun, 23 Feb 2014 14:20:08 +0200 Subject: Target/sbc: Don't use sg as iterator in sbc_verify_read Because then this sg is passed to sbc_copy_prot which will hit a protection fault in cases we have more than a single sg. Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index ef1a58a..42f18fc 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -1162,7 +1162,7 @@ sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors, { struct se_device *dev = cmd->se_dev; struct se_dif_v1_tuple *sdt; - struct scatterlist *dsg; + struct scatterlist *dsg, *psg = sg; sector_t sector = start; void *daddr, *paddr; int i, j, offset = sg_off; @@ -1170,14 +1170,14 @@ sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors, for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) { daddr = kmap_atomic(sg_page(dsg)) + dsg->offset; - paddr = kmap_atomic(sg_page(sg)) + sg->offset; + paddr = kmap_atomic(sg_page(psg)) + sg->offset; for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) { - if (offset >= sg->length) { + if (offset >= psg->length) { kunmap_atomic(paddr); - sg = sg_next(sg); - paddr = kmap_atomic(sg_page(sg)) + sg->offset; + psg = sg_next(psg); + paddr = kmap_atomic(sg_page(psg)) + psg->offset; offset = 0; } -- cgit v0.10.2 From cfbf8d4857c26a8a307fb7cd258074c9dcd8c691 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 23 Feb 2014 17:40:03 -0800 Subject: Linux 3.14-rc4 diff --git a/Makefile b/Makefile index 893d6f0..831b36a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v0.10.2 From eeecf1a3f9f4791371bf35035ab9b95ab6aab5e7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 24 Feb 2014 11:38:11 +0900 Subject: ASoC: da732x: Remove leftover cache size setting The da732x driver no longer uses the ASoC level register cache but the cache size setting had been left in the driver by mistake. Remove it. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 3219fa1..05f07fb 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1538,7 +1538,6 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = { .dapm_routes = da732x_dapm_routes, .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), .set_pll = da732x_set_dai_pll, - .reg_cache_size = ARRAY_SIZE(da732x_reg_cache), }; static int da732x_i2c_probe(struct i2c_client *i2c, -- cgit v0.10.2 From ea9f8535a46d3753649b6e28f47e3109ca63284a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 24 Feb 2014 00:20:43 -0300 Subject: ASoC: fsl: imx-pcm-fiq: Remove unneeded 'out' label Instead of jumping to the 'out' label, just return the error code immediately. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 6553202..7abf6a0 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c @@ -270,18 +270,17 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) - goto out; + return ret; } if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) - goto out; + return ret; } -out: - return ret; + return 0; } static int ssi_irq = 0; -- cgit v0.10.2 From 963a1852fbac4f75a2d938fa2e734ef1e6d4c044 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 21 Feb 2014 20:34:34 +0100 Subject: mac80211: don't validate unchanged AP bandwidth while tracking The MLME code in mac80211 must track whether or not the AP changed bandwidth, but if there's no change while tracking it shouldn't do anything, otherwise regulatory updates can make it impossible to connect to certain APs if the regulatory database doesn't match the information from the AP. See the precise scenario described in the code. This still leaves some possible problems with CSA or if the AP actually changed bandwidth, but those cases are less common and won't completely prevent using it. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=70881 Cc: stable@vger.kernel.org Reported-and-tested-by: Nate Carlson Signed-off-by: Johannes Berg diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 57d5482..c415f00 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -271,6 +271,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ret = 0; out: + /* + * When tracking the current AP, don't do any further checks if the + * new chandef is identical to the one we're currently using for the + * connection. This keeps us from playing ping-pong with regulatory, + * without it the following can happen (for example): + * - connect to an AP with 80 MHz, world regdom allows 80 MHz + * - AP advertises regdom US + * - CRDA loads regdom US with 80 MHz prohibited (old database) + * - the code below detects an unsupported channel, downgrades, and + * we disconnect from the AP in the caller + * - disconnect causes CRDA to reload world regdomain and the game + * starts anew. + * (see https://bugzilla.kernel.org/show_bug.cgi?id=70881) + * + * It seems possible that there are still scenarios with CSA or real + * bandwidth changes where a this could happen, but those cases are + * less common and wouldn't completely prevent using the AP. + */ + if (tracking && + cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) + return ret; + /* don't print the message below for VHT mismatch if VHT is disabled */ if (ret & IEEE80211_STA_DISABLE_VHT) vht_chandef = *chandef; -- cgit v0.10.2 From e6cfc0295c7d51b008999a8b13a44fb43f8685ea Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 3 Feb 2014 15:33:37 +0000 Subject: asm-generic: add sched_setattr/sched_getattr syscalls Add the sched_setattr and sched_getattr syscalls to the generic syscall list, which is used by the following architectures: arc, arm64, c6x, hexagon, metag, openrisc, score, tile, unicore32. Signed-off-by: James Hogan Acked-by: Arnd Bergmann Acked-by: Catalin Marinas Cc: linux-arch@vger.kernel.org Cc: Vineet Gupta Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: Mark Salter Cc: Aurelien Jacquiot Cc: linux-c6x-dev@linux-c6x.org Cc: Richard Kuo Cc: linux-hexagon@vger.kernel.org Cc: linux-metag@vger.kernel.org Cc: Jonas Bonn Cc: linux@lists.openrisc.net Cc: Chen Liqin Cc: Lennox Wu Cc: Chris Metcalf Cc: Guan Xuetao diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index a20a9b4..dde8041 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -692,9 +692,13 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ __SYSCALL(__NR_kcmp, sys_kcmp) #define __NR_finit_module 273 __SYSCALL(__NR_finit_module, sys_finit_module) +#define __NR_sched_setattr 274 +__SYSCALL(__NR_sched_setattr, sys_sched_setattr) +#define __NR_sched_getattr 275 +__SYSCALL(__NR_sched_getattr, sys_sched_getattr) #undef __NR_syscalls -#define __NR_syscalls 274 +#define __NR_syscalls 276 /* * All syscalls below here should go away really, -- cgit v0.10.2 From b29dd35909c4ac074e84e8e7000fe525fe33c1a1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 7 Jan 2014 13:54:26 +0100 Subject: clk: shmobile: rcar-gen2: Fix clock parent for all non-PLL clocks The lb, qspi, sdh, sd0 and sd1 clocks have the PLL1 (divided by 2) as their parent, not the main clock. Fix it. This bug introduced in v3.14-rc1 breaks various devices on the Lager and Kolesh shmobile boards and should thus be considered as a regression for which a fix during the -rc series is appropriate. Reported-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Acked-by: Simon Horman diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index a59ec21..8c7bcbd 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -186,7 +186,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, const char *name) { const struct clk_div_table *table = NULL; - const char *parent_name = "main"; + const char *parent_name; unsigned int shift; unsigned int mult = 1; unsigned int div = 1; @@ -201,23 +201,31 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, * the multiplier value. */ u32 value = clk_readl(cpg->reg + CPG_PLL0CR); + parent_name = "main"; mult = ((value >> 24) & ((1 << 7) - 1)) + 1; } else if (!strcmp(name, "pll1")) { + parent_name = "main"; mult = config->pll1_mult / 2; } else if (!strcmp(name, "pll3")) { + parent_name = "main"; mult = config->pll3_mult; } else if (!strcmp(name, "lb")) { + parent_name = "pll1_div2"; div = cpg_mode & BIT(18) ? 36 : 24; } else if (!strcmp(name, "qspi")) { + parent_name = "pll1_div2"; div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ? 16 : 20; } else if (!strcmp(name, "sdh")) { + parent_name = "pll1_div2"; table = cpg_sdh_div_table; shift = 8; } else if (!strcmp(name, "sd0")) { + parent_name = "pll1_div2"; table = cpg_sd01_div_table; shift = 4; } else if (!strcmp(name, "sd1")) { + parent_name = "pll1_div2"; table = cpg_sd01_div_table; shift = 0; } else if (!strcmp(name, "z")) { -- cgit v0.10.2 From 4a9c3ce1d293fe67123102f0b6734d6067c665fd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 7 Jan 2014 13:54:26 +0100 Subject: clk: shmobile: rcar-gen2: Fix qspi divisor The qspi clock divisor is incorrectly set to twice the value it should have, possibly because it has been computed based on PLL1 as the clock parent instead of PLL1 / 2 (the datasheets specifies the qspi nominal frequencies, not the divisor values). Fix it. This bug introduced in v3.14-rc1 breaks various devices on the Lager and Kolesh shmobile boards and should thus be considered as a regression for which a fix during the -rc series is appropriate. Reported-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Acked-by: Simon Horman diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index 8c7bcbd..dd272a0 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -215,7 +215,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, } else if (!strcmp(name, "qspi")) { parent_name = "pll1_div2"; div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) - ? 16 : 20; + ? 8 : 10; } else if (!strcmp(name, "sdh")) { parent_name = "pll1_div2"; table = cpg_sdh_div_table; -- cgit v0.10.2 From 60480994c70981d0336aadb3f46b052977d3d19f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 19 Feb 2014 18:13:24 +0100 Subject: clk: shmobile: Fix typo in MSTP clock DT bindings The DT bindings document a renesas,indices property, while the code, the DT example and the DT sources all use renesas,clock-indices. Fix the documentation. The shmobile mstp DT bindings have been merged in v3.14-rc1 with a bug in the DT ABI, a fix during the -rc series is appropriate. Reported-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Acked-by: Simon Horman diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt index a6a352c..5992dce 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt @@ -21,9 +21,9 @@ Required Properties: must appear in the same order as the output clocks. - #clock-cells: Must be 1 - clock-output-names: The name of the clocks as free-form strings - - renesas,indices: Indices of the gate clocks into the group (0 to 31) + - renesas,clock-indices: Indices of the gate clocks into the group (0 to 31) -The clocks, clock-output-names and renesas,indices properties contain one +The clocks, clock-output-names and renesas,clock-indices properties contain one entry per gate clock. The MSTP groups are sparsely populated. Unimplemented gate clocks must not be declared. -- cgit v0.10.2 From 48c65bda95d692076de7e5eae3188ddae8635dca Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Feb 2014 10:32:53 +0900 Subject: perf annotate: Check availability of annotate when processing samples The TUI of perf report and top support annotation, but stdio and GTK don't. So it should be checked before calling hist_entry__inc_addr_ samples() to avoid wasting resources that will never be used. perf annotate need it regardless of UI and sort keys, so the check of whether to allocate resources should be on the tools that have annotate as an option in the TUI, 'report' and 'top', not on the function called by all of them. It caused perf annotate on ppc64 to produce zero output, since the buckets were not being allocated. Reported-by: Anton Blanchard Signed-off-by: Namhyung Kim Cc: Anton Blanchard Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1392859976-32760-1-git-send-email-namhyung@kernel.org [ Renamed (report,top)__needs_annotate() to ui__has_annotation() ] Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3c53ec2..02f985f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -113,14 +113,16 @@ static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_locati if (!he) return -ENOMEM; - err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); - if (err) - goto out; + if (ui__has_annotation()) { + err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); + if (err) + goto out; - mx = he->mem_info; - err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx); - if (err) - goto out; + mx = he->mem_info; + err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx); + if (err) + goto out; + } evsel->hists.stats.total_period += cost; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); @@ -164,14 +166,18 @@ static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_loc he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL, 1, 1, 0); if (he) { - bx = he->branch_info; - err = addr_map_symbol__inc_samples(&bx->from, evsel->idx); - if (err) - goto out; - - err = addr_map_symbol__inc_samples(&bx->to, evsel->idx); - if (err) - goto out; + if (ui__has_annotation()) { + bx = he->branch_info; + err = addr_map_symbol__inc_samples(&bx->from, + evsel->idx); + if (err) + goto out; + + err = addr_map_symbol__inc_samples(&bx->to, + evsel->idx); + if (err) + goto out; + } evsel->hists.stats.total_period += 1; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); @@ -205,7 +211,9 @@ static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evs if (err) goto out; - err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); + if (ui__has_annotation()) + err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); + evsel->hists.stats.total_period += sample->period; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); out: diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 76cd510..5f989a7 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -176,7 +176,7 @@ static void perf_top__record_precise_ip(struct perf_top *top, { struct annotation *notes; struct symbol *sym; - int err; + int err = 0; if (he == NULL || he->ms.sym == NULL || ((top->sym_filter_entry == NULL || @@ -190,7 +190,9 @@ static void perf_top__record_precise_ip(struct perf_top *top, return; ip = he->ms.map->map_ip(he->ms.map, ip); - err = hist_entry__inc_addr_samples(he, counter, ip); + + if (ui__has_annotation()) + err = hist_entry__inc_addr_samples(he, counter, ip); pthread_mutex_unlock(¬es->lock); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 469eb67..3aa555f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -8,6 +8,8 @@ */ #include "util.h" +#include "ui/ui.h" +#include "sort.h" #include "build-id.h" #include "color.h" #include "cache.h" @@ -489,7 +491,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, { struct annotation *notes; - if (sym == NULL || use_browser != 1 || !sort__has_sym) + if (sym == NULL) return 0; notes = symbol__annotation(sym); @@ -1399,3 +1401,8 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize) { return symbol__annotate(he->ms.sym, he->ms.map, privsize); } + +bool ui__has_annotation(void) +{ + return use_browser == 1 && sort__has_sym; +} diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index b2aef59..56ad4f5 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -151,6 +151,8 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); void disasm__purge(struct list_head *head); +bool ui__has_annotation(void); + int symbol__tty_annotate(struct symbol *sym, struct map *map, struct perf_evsel *evsel, bool print_lines, bool full_paths, int min_pcnt, int max_lines); -- cgit v0.10.2 From 98e9f03bbf2cb21a60f94b8b700eb5d38470819d Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 20 Feb 2014 10:32:54 +0900 Subject: perf symbols: Destroy unused symsrcs Stephane reported that perf report and annotate failed to process data using lots of (> 500) shared libraries. It was because of the limit on number of open files (ulimit -n). Currently when perf loads a DSO, it'll look for normal and dynamic symbol tables. And if it fails to find out both tables, it'll iterate all of possible symtab types. But many of them are useless since they have no additional information and the problem is that it's not closing those files even though they're not used. Fix it. Reported-by: Stephane Eranian Signed-off-by: Namhyung Kim Cc: Cody P Schafer Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1392859976-32760-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index a9d758a..e89afc0 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1336,6 +1336,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) if (syms_ss && runtime_ss) break; + } else { + symsrc__destroy(ss); } } -- cgit v0.10.2 From 1acacc0784aab45627b6009e0e9224886279ac0b Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Wed, 19 Feb 2014 20:32:33 -0500 Subject: dm thin: fix the error path for the thin device constructor dm_pool_close_thin_device() must be called if dm_set_target_max_io_len() fails in thin_ctr(). Otherwise __pool_destroy() will fail because the pool will still have an open thin device: device-mapper: thin metadata: attempt to close pmd when 1 device(s) are still open device-mapper: thin: __pool_destroy: dm_pool_metadata_close() failed. Also, must establish error code if failing thin_ctr() because the pool is in fail_io mode. Signed-off-by: Mike Snitzer Acked-by: Joe Thornber Cc: stable@vger.kernel.org diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index d501e43..4cf4b19 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2895,6 +2895,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) if (get_pool_mode(tc->pool) == PM_FAIL) { ti->error = "Couldn't open thin device, Pool is in fail mode"; + r = -EINVAL; goto bad_thin_open; } @@ -2906,7 +2907,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) r = dm_set_target_max_io_len(ti, tc->pool->sectors_per_block); if (r) - goto bad_thin_open; + goto bad_target_max_io_len; ti->num_flush_bios = 1; ti->flush_supported = true; @@ -2927,6 +2928,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) return 0; +bad_target_max_io_len: + dm_pool_close_thin_device(tc->td); bad_thin_open: __pool_dec(tc->pool); bad_pool_lookup: -- cgit v0.10.2 From e4ceb0f40da5dc26f84025d121c2fe6ff7d8a947 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 21 Feb 2014 12:23:00 -0800 Subject: mwifiex: rename usb driver name registerring to usb core Both libertas USB driver and mwifiex_usb driver are registerring with name 'usb8xxx'. The following conflict happens while trying to load both drivers. [6.211307] Error: Driver 'usb8xxx' is already registered... [6.217261] mwifiex_usb: Driver register failed! Fix it by renaming mwifiex_usb driver's name. Reported-by: Fengguang Wu Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index e8ebbd4..cb6b70a 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -22,8 +22,6 @@ #define USB_VERSION "1.0" -static const char usbdriver_name[] = "usb8xxx"; - static struct mwifiex_if_ops usb_ops; static struct semaphore add_remove_card_sem; static struct usb_card_rec *usb_card; @@ -567,7 +565,7 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf) } static struct usb_driver mwifiex_usb_driver = { - .name = usbdriver_name, + .name = "mwifiex_usb", .probe = mwifiex_usb_probe, .disconnect = mwifiex_usb_disconnect, .id_table = mwifiex_usb_table, -- cgit v0.10.2 From 558ff225de80ac95b132d3a115ddadcd64498b4f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 22 Feb 2014 13:48:19 +0100 Subject: ath9k: fix ps-poll responses under a-mpdu sessions When passing tx frames to the U-APSD queue for powersave poll responses, the ath_atx_tid pointer needs to be passed to ath_tx_setup_buffer for proper sequence number accounting. This fixes high latency and connection stability issues with ath9k running as AP and a few kinds of mobile phones as client, when PS-Poll is heavily used Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4f4ce83..f042a18 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2186,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, txq->stopped = true; } + if (txctl->an) + tid = ath_get_skb_tid(sc, txctl->an, skb); + if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) { ath_txq_unlock(sc, txq); txq = sc->tx.uapsdq; ath_txq_lock(sc, txq); } else if (txctl->an && ieee80211_is_data_present(hdr->frame_control)) { - tid = ath_get_skb_tid(sc, txctl->an, skb); - WARN_ON(tid->ac->txq != txctl->txq); if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) -- cgit v0.10.2 From 6f58c780e5a5b43a6d2121e0d43cdcba1d3cc5fc Mon Sep 17 00:00:00 2001 From: "Dr. Greg Wettstein" Date: Mon, 24 Feb 2014 13:59:53 -0600 Subject: qla2xxx: Fix kernel panic on selective retransmission request A selective retransmission request (SRR) is a fibre-channel protocol control request which provides support for requesting retransmission of a data sequence in response to an issue such as frame loss or corruption. These events are experienced infrequently in fibre-channel based networks which makes it difficult to test and assess codepaths which handle these events. We were fortunate enough, for some definition of fortunate, to have a metro-area single-mode SAN link which, at 10 GBPS sustained load levels, would consistently generate SRR's in a SCST based target implementation using our SCST/in-kernel Qlogic target interface driver. In response to an SRR the in-kernel Qlogic target driver immediately panics resulting in a catastrophic storage failure for serviced initiators. The culprit was a debug statement in the qla_target.c file which does not verify that a pointer to the SCSI CDB is not null. The unchecked pointer dereference results in the kernel panic and resultant system failure. The other two references to the SCSI CDB by the SRR handling code use a ternary operator to verify a non-null pointer is being acted on. This patch simply adds a similar test to the implicated debug statement. This patch is a candidate for any stable kernel being maintained since it addresses a potentially catastrophic event with minimal downside. Signed-off-by: Dr. Greg Wettstein Cc: #3.5+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index f2e1c5a..0cb7307 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3202,7 +3202,8 @@ restart: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c, "SRR cmd %p (se_cmd %p, tag %d, op %x), " "sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag, - se_cmd->t_task_cdb[0], cmd->sg_cnt, cmd->offset); + se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, + cmd->sg_cnt, cmd->offset); qlt_handle_srr(vha, sctio, imm); -- cgit v0.10.2 From 760dbe1dcb6d3dd3ead73dc69b23f206b52273bb Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 24 Feb 2014 14:39:00 +0000 Subject: staging:iio:adc:MXS:LRADC: fix touchscreen statemachine Releasing the touchscreen lets the internal statemachine left in a wrong state. Due to this the release coordinate will be reported again by accident when the next touchscreen event happens. This change sets up the correct state when waiting for the next touchscreen event. This has led to reported issues with calibrating the touchscreen. Bug was introduced somewhere in the series that began with 18da755de59b406ce2371a55fb15ed676eb08ed2 Staging/iio/adc/touchscreen/MXS: add proper clock handling in which the way this driver worked was substantially changed to be interrupt driven rather than relying on a busy loop. This was a regression in the 3.13 kernel. Signed-off-by: Juergen Beisert Tested-by: Alexandre Belloni Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 7fc66a6..514844e 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -757,6 +757,7 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) } /* if it is released, wait for the next touch via IRQ */ + lradc->cur_plate = LRADC_TOUCH; mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); } -- cgit v0.10.2 From 0e7ede80d929ff0f830c44a543daa1acd590c749 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 21 Feb 2014 13:08:04 +0800 Subject: virtio-net: alloc big buffers also when guest can receive UFO We should alloc big buffers also when guest can receive UFO packets to let the big packets fit into guest rx buffer. Fixes 5c5167515d80f78f6bb538492c423adcae31ad65 (virtio-net: Allow UFO feature to be set and advertised.) Cc: Rusty Russell Cc: Michael S. Tsirkin Cc: Sridhar Samudrala Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Acked-by: Rusty Russell Signed-off-by: David S. Miller diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d75f8ed..5632a99 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1711,7 +1711,8 @@ static int virtnet_probe(struct virtio_device *vdev) /* If we can receive ANY GSO packets, we must allocate large ones. */ if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || - virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN)) + virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) || + virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO)) vi->big_packets = true; if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) -- cgit v0.10.2 From 7262b7b26de1495f77edbe1e71cb15b8198adb9d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sat, 22 Feb 2014 13:09:03 +0100 Subject: net: stmmac: Check return value of alloc_dma_desc_resources() alloc_dma_desc_resources() returns an error value and the next line actually checks for it, so assign the return value properly. Found by the coverity scanner. Signed-off-by: Tobias Klauser Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a2e7d2c..078ad0e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1705,7 +1705,7 @@ static int stmmac_open(struct net_device *dev) priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); - alloc_dma_desc_resources(priv); + ret = alloc_dma_desc_resources(priv); if (ret < 0) { pr_err("%s: DMA descriptors allocation failed\n", __func__); goto dma_desc_error; -- cgit v0.10.2 From d10473d4e3f9d1b81b50a60c8465d6f59a095c46 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 22 Feb 2014 22:25:57 -0800 Subject: tcp: reduce the bloat caused by tcp_is_cwnd_limited() tcp_is_cwnd_limited() allows GSO/TSO enabled flows to increase their cwnd to allow a full size (64KB) TSO packet to be sent. Non GSO flows only allow an extra room of 3 MSS. For most flows with a BDP below 10 MSS, this results in a bloat of cwnd reaching 90, and an inflate of RTT. Thanks to TSO auto sizing, we can restrict the bloat to the number of MSS contained in a TSO packet (tp->xmit_size_goal_segs), to keep original intent without performance impact. Because we keep cwnd small, it helps to keep TSO packet size to their optimal value. Example for a 10Mbit flow, with low TCP Small queue limits (no more than 2 skb in qdisc/device tx ring) Before patch : lpk51:~# ./ss -i dst lpk52:44862 | grep cwnd cubic wscale:6,6 rto:215 rtt:15.875/2.5 mss:1448 cwnd:96 ssthresh:96 send 70.1Mbps unacked:14 rcv_space:29200 After patch : lpk51:~# ./ss -i dst lpk52:52916 | grep cwnd cubic wscale:6,6 rto:206 rtt:5.206/0.036 mss:1448 cwnd:15 ssthresh:14 send 33.4Mbps unacked:4 rcv_space:29200 Signed-off-by: Eric Dumazet Cc: Yuchung Cheng Cc: Neal Cardwell Cc: Nandita Dukkipati Cc: Van Jacobson Acked-by: Neal Cardwell Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index ad37bf1..2388275 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -290,8 +290,7 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) left = tp->snd_cwnd - in_flight; if (sk_can_gso(sk) && left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && - left * tp->mss_cache < sk->sk_gso_max_size && - left < sk->sk_gso_max_segs) + left < tp->xmit_size_goal_segs) return true; return left <= tcp_max_tso_deferred_mss(tp); } -- cgit v0.10.2 From 7fe412d07d881020022a188b95c63a19b651a391 Mon Sep 17 00:00:00 2001 From: Venkatesh Srinivas Date: Mon, 24 Feb 2014 14:13:32 -0800 Subject: vhost/scsi: Check LUN structure byte 0 is set to 1, per spec The virtio spec requires byte 0 of the virtio-scsi LUN structure to be '1'. Signed-off-by: Venkatesh Srinivas Reviewed-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 0a025b8..e48d4a6 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1001,6 +1001,12 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) break; } + /* virtio-scsi spec requires byte 0 of the lun to be 1 */ + if (unlikely(v_req.lun[0] != 1)) { + vhost_scsi_send_bad_target(vs, vq, head, out); + continue; + } + /* Extract the tpgt */ target = v_req.lun[1]; tpg = ACCESS_ONCE(vs_tpg[target]); -- cgit v0.10.2 From 260ea9c2e2d330303163e286ab01b66dbcfe3a6f Mon Sep 17 00:00:00 2001 From: Manu Gupta Date: Mon, 24 Feb 2014 12:12:28 -0600 Subject: staging: r8188eu: Add new device ID The D-Link DWA-123 REV D1 with USB ID 2001:3310 uses this driver. Signed-off-by: Manu Gupta Signed-off-by: Larry Finger Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index a70dcef..2f40ff5 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -55,6 +55,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { /****** 8188EUS ********/ {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ + {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ {} /* Terminating entry */ }; -- cgit v0.10.2 From 30c219710358c5cca2f8bd2e9e547c6aadf7cf8b Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 17:36:03 +0100 Subject: regulator: core: Replace direct ops->enable usage There are some direct ops->enable in the regulator core driver. This is a potential issue as the function _regulator_do_enable() handles gpio regulators and the normal ops->enable calls. These gpio regulators are simply ignored when ops->enable is called directly. One possible bug is that boot-on and always-on gpio regulators are not enabled on registration. This patch replaces all ops->enable calls by _regulator_do_enable. [Handle missing enable operations -- broonie] Cc: # 3.10+ Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown regulator: Handle invalid enable operation for always/boot on regulators Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 74e9fb2..00feec3 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -953,6 +953,8 @@ static int machine_constraints_current(struct regulator_dev *rdev, return 0; } +static int _regulator_do_enable(struct regulator_dev *rdev); + /** * set_machine_constraints - sets regulator constraints * @rdev: regulator source @@ -1013,10 +1015,9 @@ static int set_machine_constraints(struct regulator_dev *rdev, /* If the constraints say the regulator should be on at this point * and we have control then make sure it is enabled. */ - if ((rdev->constraints->always_on || rdev->constraints->boot_on) && - ops->enable) { - ret = ops->enable(rdev); - if (ret < 0) { + if (rdev->constraints->always_on || rdev->constraints->boot_on) { + ret = _regulator_do_enable(rdev); + if (ret < 0 && ret != -EINVAL) { rdev_err(rdev, "failed to enable\n"); goto out; } @@ -3626,9 +3627,8 @@ int regulator_suspend_finish(void) struct regulator_ops *ops = rdev->desc->ops; mutex_lock(&rdev->mutex); - if ((rdev->use_count > 0 || rdev->constraints->always_on) && - ops->enable) { - error = ops->enable(rdev); + if (rdev->use_count > 0 || rdev->constraints->always_on) { + error = _regulator_do_enable(rdev); if (error) ret = error; } else { -- cgit v0.10.2 From 66fda75f47dc583f1c187556e9a2c082dd64f8c6 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 17:36:04 +0100 Subject: regulator: core: Replace direct ops->disable usage There are many places where ops->disable is called directly. Instead we should use _regulator_do_disable() which also handles gpio regulators. To be able to use the wrapper function from _regulator_force_disable(), I moved the _notifier_call_chain() call from _regulator_do_disable() to _regulator_disable(). This way, _regulator_force_disable() can use different flags for _notifier_call_chain() without calling it twice. Cc: # 3.10+ Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 00feec3..6f71985 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1901,8 +1901,6 @@ static int _regulator_do_disable(struct regulator_dev *rdev) trace_regulator_disable_complete(rdev_get_name(rdev)); - _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, - NULL); return 0; } @@ -1926,6 +1924,8 @@ static int _regulator_disable(struct regulator_dev *rdev) rdev_err(rdev, "failed to disable\n"); return ret; } + _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, + NULL); } rdev->use_count = 0; @@ -1978,20 +1978,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev) { int ret = 0; - /* force disable */ - if (rdev->desc->ops->disable) { - /* ah well, who wants to live forever... */ - ret = rdev->desc->ops->disable(rdev); - if (ret < 0) { - rdev_err(rdev, "failed to force disable\n"); - return ret; - } - /* notify other consumers that power has been forced off */ - _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | - REGULATOR_EVENT_DISABLE, NULL); + ret = _regulator_do_disable(rdev); + if (ret < 0) { + rdev_err(rdev, "failed to force disable\n"); + return ret; } - return ret; + _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | + REGULATOR_EVENT_DISABLE, NULL); + + return 0; } /** @@ -3624,8 +3620,6 @@ int regulator_suspend_finish(void) mutex_lock(®ulator_list_mutex); list_for_each_entry(rdev, ®ulator_list, list) { - struct regulator_ops *ops = rdev->desc->ops; - mutex_lock(&rdev->mutex); if (rdev->use_count > 0 || rdev->constraints->always_on) { error = _regulator_do_enable(rdev); @@ -3634,12 +3628,10 @@ int regulator_suspend_finish(void) } else { if (!have_full_constraints()) goto unlock; - if (!ops->disable) - goto unlock; if (!_regulator_is_enabled(rdev)) goto unlock; - error = ops->disable(rdev); + error = _regulator_do_disable(rdev); if (error) ret = error; } @@ -3813,7 +3805,7 @@ static int __init regulator_init_complete(void) ops = rdev->desc->ops; c = rdev->constraints; - if (!ops->disable || (c && c->always_on)) + if (c && c->always_on) continue; mutex_lock(&rdev->mutex); @@ -3834,7 +3826,7 @@ static int __init regulator_init_complete(void) /* We log since this may kill the system if it * goes wrong. */ rdev_info(rdev, "disabling\n"); - ret = ops->disable(rdev); + ret = _regulator_do_disable(rdev); if (ret != 0) rdev_err(rdev, "couldn't disable: %d\n", ret); } else { -- cgit v0.10.2 From 340fea3d7f6a2657ddd0b48413cd81e8513357ed Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 24 Feb 2014 20:12:28 -0500 Subject: r8169: initialize rtl8169_stats seqlock Boris reports he's seeing: > [ 9.195943] INFO: trying to register non-static key. > [ 9.196031] the code is fine but needs lockdep annotation. > [ 9.196031] turning off the locking correctness validator. > [ 9.196031] CPU: 1 PID: 933 Comm: modprobe Not tainted 3.14.0-rc4+ #1 with the r8169 driver. These are occuring because the seqcount embedded in u64_stats_sync on 32-bit SMP is uninitialized which is making lockdep unhappy. Signed-off-by: Kyle McMartin Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 91a67ae..e977965 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -7118,6 +7118,8 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } mutex_init(&tp->wk.mutex); + u64_stats_init(&tp->rx_stats.syncp); + u64_stats_init(&tp->tx_stats.syncp); /* Get MAC address */ for (i = 0; i < ETH_ALEN; i++) -- cgit v0.10.2 From a2530060c1157a7863abbe1fea3cfdd5da55bd48 Mon Sep 17 00:00:00 2001 From: Sherman Yin Date: Thu, 23 Jan 2014 12:44:47 -0800 Subject: Update dtsi with new pinctrl compatible string This commit updates bcm11351.dtsi with the new compatible string for the same driver. Signed-off-by: Sherman Yin Reviewed-by: Matt Porter Acked-by: Linus Walleij Signed-off-by: Christian Daudt diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi index e491b82..792fde1 100644 --- a/arch/arm/boot/dts/bcm11351.dtsi +++ b/arch/arm/boot/dts/bcm11351.dtsi @@ -147,7 +147,7 @@ }; pinctrl@35004800 { - compatible = "brcm,capri-pinctrl"; + compatible = "brcm,bcm11351-pinctrl"; reg = <0x35004800 0x430>; }; -- cgit v0.10.2 From d0deca0276807740f3e688d97196122511b8f765 Mon Sep 17 00:00:00 2001 From: Christian Daudt Date: Mon, 24 Feb 2014 09:15:35 -0800 Subject: pinctrl: refer to updated dt binding string. Bring the driver in line with the bcm-based dt name for pinctrl. This is being done to keep consistency with other Broadcom mobile SoC drivers. Signed-off-by: Christian Daudt Reviewed-by: Matt Porter diff --git a/drivers/pinctrl/pinctrl-capri.c b/drivers/pinctrl/pinctrl-capri.c index 4669c53..eb25002 100644 --- a/drivers/pinctrl/pinctrl-capri.c +++ b/drivers/pinctrl/pinctrl-capri.c @@ -1435,7 +1435,7 @@ int __init capri_pinctrl_probe(struct platform_device *pdev) } static struct of_device_id capri_pinctrl_of_match[] = { - { .compatible = "brcm,capri-pinctrl", }, + { .compatible = "brcm,bcm11351-pinctrl", }, { }, }; -- cgit v0.10.2 From 735ea23c4868bf3123a4c79184e9206e0cc60211 Mon Sep 17 00:00:00 2001 From: Sherman Yin Date: Thu, 23 Jan 2014 12:44:44 -0800 Subject: pinctrl: Rename Broadcom Capri pinctrl binding The compatible string of the Broadcom Capri pinctrl driver is renamed to "brcm,bcm11351-pinctrl" to match the machine binding here: Documentation/devicetree/bindings/arm/bcm/bcm11351.txt Signed-off-by: Sherman Yin Reviewed-by: Matt Porter Acked-by: Linus Walleij Signed-off-by: Christian Daudt diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt new file mode 100644 index 0000000..c119deb --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt @@ -0,0 +1,461 @@ +Broadcom BCM281xx Pin Controller + +This is a pin controller for the Broadcom BCM281xx SoC family, which includes +BCM11130, BCM11140, BCM11351, BCM28145, and BCM28155 SoCs. + +=== Pin Controller Node === + +Required Properties: + +- compatible: Must be "brcm,bcm11351-pinctrl" +- reg: Base address of the PAD Controller register block and the size + of the block. + +For example, the following is the bare minimum node: + + pinctrl@35004800 { + compatible = "brcm,bcm11351-pinctrl"; + reg = <0x35004800 0x430>; + }; + +As a pin controller device, in addition to the required properties, this node +should also contain the pin configuration nodes that client devices reference, +if any. + +=== Pin Configuration Node === + +Each pin configuration node is a sub-node of the pin controller node and is a +container of an arbitrary number of subnodes, called pin group nodes in this +document. + +Please refer to the pinctrl-bindings.txt in this directory for details of the +common pinctrl bindings used by client devices, including the definition of a +"pin configuration node". + +=== Pin Group Node === + +A pin group node specifies the desired pin mux and/or pin configuration for an +arbitrary number of pins. The name of the pin group node is optional and not +used. + +A pin group node only affects the properties specified in the node, and has no +effect on any properties that are omitted. + +The pin group node accepts a subset of the generic pin config properties. For +details generic pin config properties, please refer to pinctrl-bindings.txt +and . + +Each pin controlled by this pin controller belong to one of three types: +Standard, I2C, and HDMI. Each type accepts a different set of pin config +properties. A list of pins and their types is provided below. + +Required Properties (applicable to all pins): + +- pins: Multiple strings. Specifies the name(s) of one or more pins to + be configured by this node. + +Optional Properties (for standard pins): + +- function: String. Specifies the pin mux selection. Values + must be one of: "alt1", "alt2", "alt3", "alt4" +- input-schmitt-enable: No arguments. Enable schmitt-trigger mode. +- input-schmitt-disable: No arguments. Disable schmitt-trigger mode. +- bias-pull-up: No arguments. Pull up on pin. +- bias-pull-down: No arguments. Pull down on pin. +- bias-disable: No arguments. Disable pin bias. +- slew-rate: Integer. Meaning depends on configured pin mux: + *_SCL or *_SDA: + 0: Standard(100kbps)& Fast(400kbps) mode + 1: Highspeed (3.4Mbps) mode + IC_DM or IC_DP: + 0: normal slew rate + 1: fast slew rate + Otherwise: + 0: fast slew rate + 1: normal slew rate +- input-enable: No arguements. Enable input (does not affect + output.) +- input-disable: No arguements. Disable input (does not affect + output.) +- drive-strength: Integer. Drive strength in mA. Valid values are + 2, 4, 6, 8, 10, 12, 14, 16 mA. + +Optional Properties (for I2C pins): + +- function: String. Specifies the pin mux selection. Values + must be one of: "alt1", "alt2", "alt3", "alt4" +- bias-pull-up: Integer. Pull up strength in Ohm. There are 3 + pull-up resisitors (1.2k, 1.8k, 2.7k) available + in parallel for I2C pins, so the valid values + are: 568, 720, 831, 1080, 1200, 1800, 2700 Ohm. +- bias-disable: No arguments. Disable pin bias. +- slew-rate: Integer. Meaning depends on configured pin mux: + *_SCL or *_SDA: + 0: Standard(100kbps)& Fast(400kbps) mode + 1: Highspeed (3.4Mbps) mode + IC_DM or IC_DP: + 0: normal slew rate + 1: fast slew rate + Otherwise: + 0: fast slew rate + 1: normal slew rate +- input-enable: No arguements. Enable input (does not affect + output.) +- input-disable: No arguements. Disable input (does not affect + output.) + +Optional Properties (for HDMI pins): + +- function: String. Specifies the pin mux selection. Values + must be one of: "alt1", "alt2", "alt3", "alt4" +- slew-rate: Integer. Controls slew rate. + 0: Standard(100kbps)& Fast(400kbps) mode + 1: Highspeed (3.4Mbps) mode +- input-enable: No arguements. Enable input (does not affect + output.) +- input-disable: No arguements. Disable input (does not affect + output.) + +Example: +// pin controller node +pinctrl@35004800 { + compatible = "brcmbcm11351-pinctrl"; + reg = <0x35004800 0x430>; + + // pin configuration node + dev_a_default: dev_a_active { + //group node defining 1 standard pin + grp_1 { + pins = "std_pin1"; + function = "alt1"; + input-schmitt-enable; + bias-disable; + slew-rate = <1>; + drive-strength = <4>; + }; + + // group node defining 2 I2C pins + grp_2 { + pins = "i2c_pin1", "i2c_pin2"; + function = "alt2"; + bias-pull-up = <720>; + input-enable; + }; + + // group node defining 2 HDMI pins + grp_3 { + pins = "hdmi_pin1", "hdmi_pin2"; + function = "alt3"; + slew-rate = <1>; + }; + + // other pin group nodes + ... + }; + + // other pin configuration nodes + ... +}; + +In the example above, "dev_a_active" is a pin configuration node with a number +of sub-nodes. In the pin group node "grp_1", one pin, "std_pin1", is defined in +the "pins" property. Thus, the remaining properties in the "grp_1" node applies +only to this pin, including the following settings: + - setting pinmux to "alt1" + - enabling schmitt-trigger (hystersis) mode + - disabling pin bias + - setting the slew-rate to 1 + - setting the drive strength to 4 mA +Note that neither "input-enable" nor "input-disable" was specified - the pinctrl +subsystem will therefore leave this property unchanged from whatever state it +was in before applying these changes. + +The "pins" property in the pin group node "grp_2" specifies two pins - +"i2c_pin1" and "i2c_pin2"; the remaining properties in this pin group node, +therefore, applies to both of these pins. The properties include: + - setting pinmux to "alt2" + - setting pull-up resistance to 720 Ohm (ie. enabling 1.2k and 1.8k resistors + in parallel) + - enabling both pins' input +"slew-rate" is not specified in this pin group node, so the slew-rate for these +pins are left as-is. + +Finally, "grp_3" defines two HDMI pins. The following properties are applied to +both pins: + - setting pinmux to "alt3" + - setting slew-rate to 1; for HDMI pins, this corresponds to the 3.4 Mbps + Highspeed mode +The input is neither enabled or disabled, and is left untouched. + +=== Pin Names and Type === + +The following are valid pin names and their pin types: + + "adcsync", Standard + "bat_rm", Standard + "bsc1_scl", I2C + "bsc1_sda", I2C + "bsc2_scl", I2C + "bsc2_sda", I2C + "classgpwr", Standard + "clk_cx8", Standard + "clkout_0", Standard + "clkout_1", Standard + "clkout_2", Standard + "clkout_3", Standard + "clkreq_in_0", Standard + "clkreq_in_1", Standard + "cws_sys_req1", Standard + "cws_sys_req2", Standard + "cws_sys_req3", Standard + "digmic1_clk", Standard + "digmic1_dq", Standard + "digmic2_clk", Standard + "digmic2_dq", Standard + "gpen13", Standard + "gpen14", Standard + "gpen15", Standard + "gpio00", Standard + "gpio01", Standard + "gpio02", Standard + "gpio03", Standard + "gpio04", Standard + "gpio05", Standard + "gpio06", Standard + "gpio07", Standard + "gpio08", Standard + "gpio09", Standard + "gpio10", Standard + "gpio11", Standard + "gpio12", Standard + "gpio13", Standard + "gpio14", Standard + "gps_pablank", Standard + "gps_tmark", Standard + "hdmi_scl", HDMI + "hdmi_sda", HDMI + "ic_dm", Standard + "ic_dp", Standard + "kp_col_ip_0", Standard + "kp_col_ip_1", Standard + "kp_col_ip_2", Standard + "kp_col_ip_3", Standard + "kp_row_op_0", Standard + "kp_row_op_1", Standard + "kp_row_op_2", Standard + "kp_row_op_3", Standard + "lcd_b_0", Standard + "lcd_b_1", Standard + "lcd_b_2", Standard + "lcd_b_3", Standard + "lcd_b_4", Standard + "lcd_b_5", Standard + "lcd_b_6", Standard + "lcd_b_7", Standard + "lcd_g_0", Standard + "lcd_g_1", Standard + "lcd_g_2", Standard + "lcd_g_3", Standard + "lcd_g_4", Standard + "lcd_g_5", Standard + "lcd_g_6", Standard + "lcd_g_7", Standard + "lcd_hsync", Standard + "lcd_oe", Standard + "lcd_pclk", Standard + "lcd_r_0", Standard + "lcd_r_1", Standard + "lcd_r_2", Standard + "lcd_r_3", Standard + "lcd_r_4", Standard + "lcd_r_5", Standard + "lcd_r_6", Standard + "lcd_r_7", Standard + "lcd_vsync", Standard + "mdmgpio0", Standard + "mdmgpio1", Standard + "mdmgpio2", Standard + "mdmgpio3", Standard + "mdmgpio4", Standard + "mdmgpio5", Standard + "mdmgpio6", Standard + "mdmgpio7", Standard + "mdmgpio8", Standard + "mphi_data_0", Standard + "mphi_data_1", Standard + "mphi_data_2", Standard + "mphi_data_3", Standard + "mphi_data_4", Standard + "mphi_data_5", Standard + "mphi_data_6", Standard + "mphi_data_7", Standard + "mphi_data_8", Standard + "mphi_data_9", Standard + "mphi_data_10", Standard + "mphi_data_11", Standard + "mphi_data_12", Standard + "mphi_data_13", Standard + "mphi_data_14", Standard + "mphi_data_15", Standard + "mphi_ha0", Standard + "mphi_hat0", Standard + "mphi_hat1", Standard + "mphi_hce0_n", Standard + "mphi_hce1_n", Standard + "mphi_hrd_n", Standard + "mphi_hwr_n", Standard + "mphi_run0", Standard + "mphi_run1", Standard + "mtx_scan_clk", Standard + "mtx_scan_data", Standard + "nand_ad_0", Standard + "nand_ad_1", Standard + "nand_ad_2", Standard + "nand_ad_3", Standard + "nand_ad_4", Standard + "nand_ad_5", Standard + "nand_ad_6", Standard + "nand_ad_7", Standard + "nand_ale", Standard + "nand_cen_0", Standard + "nand_cen_1", Standard + "nand_cle", Standard + "nand_oen", Standard + "nand_rdy_0", Standard + "nand_rdy_1", Standard + "nand_wen", Standard + "nand_wp", Standard + "pc1", Standard + "pc2", Standard + "pmu_int", Standard + "pmu_scl", I2C + "pmu_sda", I2C + "rfst2g_mtsloten3g", Standard + "rgmii_0_rx_ctl", Standard + "rgmii_0_rxc", Standard + "rgmii_0_rxd_0", Standard + "rgmii_0_rxd_1", Standard + "rgmii_0_rxd_2", Standard + "rgmii_0_rxd_3", Standard + "rgmii_0_tx_ctl", Standard + "rgmii_0_txc", Standard + "rgmii_0_txd_0", Standard + "rgmii_0_txd_1", Standard + "rgmii_0_txd_2", Standard + "rgmii_0_txd_3", Standard + "rgmii_1_rx_ctl", Standard + "rgmii_1_rxc", Standard + "rgmii_1_rxd_0", Standard + "rgmii_1_rxd_1", Standard + "rgmii_1_rxd_2", Standard + "rgmii_1_rxd_3", Standard + "rgmii_1_tx_ctl", Standard + "rgmii_1_txc", Standard + "rgmii_1_txd_0", Standard + "rgmii_1_txd_1", Standard + "rgmii_1_txd_2", Standard + "rgmii_1_txd_3", Standard + "rgmii_gpio_0", Standard + "rgmii_gpio_1", Standard + "rgmii_gpio_2", Standard + "rgmii_gpio_3", Standard + "rtxdata2g_txdata3g1", Standard + "rtxen2g_txdata3g2", Standard + "rxdata3g0", Standard + "rxdata3g1", Standard + "rxdata3g2", Standard + "sdio1_clk", Standard + "sdio1_cmd", Standard + "sdio1_data_0", Standard + "sdio1_data_1", Standard + "sdio1_data_2", Standard + "sdio1_data_3", Standard + "sdio4_clk", Standard + "sdio4_cmd", Standard + "sdio4_data_0", Standard + "sdio4_data_1", Standard + "sdio4_data_2", Standard + "sdio4_data_3", Standard + "sim_clk", Standard + "sim_data", Standard + "sim_det", Standard + "sim_resetn", Standard + "sim2_clk", Standard + "sim2_data", Standard + "sim2_det", Standard + "sim2_resetn", Standard + "sri_c", Standard + "sri_d", Standard + "sri_e", Standard + "ssp_extclk", Standard + "ssp0_clk", Standard + "ssp0_fs", Standard + "ssp0_rxd", Standard + "ssp0_txd", Standard + "ssp2_clk", Standard + "ssp2_fs_0", Standard + "ssp2_fs_1", Standard + "ssp2_fs_2", Standard + "ssp2_fs_3", Standard + "ssp2_rxd_0", Standard + "ssp2_rxd_1", Standard + "ssp2_txd_0", Standard + "ssp2_txd_1", Standard + "ssp3_clk", Standard + "ssp3_fs", Standard + "ssp3_rxd", Standard + "ssp3_txd", Standard + "ssp4_clk", Standard + "ssp4_fs", Standard + "ssp4_rxd", Standard + "ssp4_txd", Standard + "ssp5_clk", Standard + "ssp5_fs", Standard + "ssp5_rxd", Standard + "ssp5_txd", Standard + "ssp6_clk", Standard + "ssp6_fs", Standard + "ssp6_rxd", Standard + "ssp6_txd", Standard + "stat_1", Standard + "stat_2", Standard + "sysclken", Standard + "traceclk", Standard + "tracedt00", Standard + "tracedt01", Standard + "tracedt02", Standard + "tracedt03", Standard + "tracedt04", Standard + "tracedt05", Standard + "tracedt06", Standard + "tracedt07", Standard + "tracedt08", Standard + "tracedt09", Standard + "tracedt10", Standard + "tracedt11", Standard + "tracedt12", Standard + "tracedt13", Standard + "tracedt14", Standard + "tracedt15", Standard + "txdata3g0", Standard + "txpwrind", Standard + "uartb1_ucts", Standard + "uartb1_urts", Standard + "uartb1_urxd", Standard + "uartb1_utxd", Standard + "uartb2_urxd", Standard + "uartb2_utxd", Standard + "uartb3_ucts", Standard + "uartb3_urts", Standard + "uartb3_urxd", Standard + "uartb3_utxd", Standard + "uartb4_ucts", Standard + "uartb4_urts", Standard + "uartb4_urxd", Standard + "uartb4_utxd", Standard + "vc_cam1_scl", I2C + "vc_cam1_sda", I2C + "vc_cam2_scl", I2C + "vc_cam2_sda", I2C + "vc_cam3_scl", I2C + "vc_cam3_sda", I2C diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,capri-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,capri-pinctrl.txt deleted file mode 100644 index 9e9e9ef..0000000 --- a/Documentation/devicetree/bindings/pinctrl/brcm,capri-pinctrl.txt +++ /dev/null @@ -1,461 +0,0 @@ -Broadcom Capri Pin Controller - -This is a pin controller for the Broadcom BCM281xx SoC family, which includes -BCM11130, BCM11140, BCM11351, BCM28145, and BCM28155 SoCs. - -=== Pin Controller Node === - -Required Properties: - -- compatible: Must be "brcm,capri-pinctrl". -- reg: Base address of the PAD Controller register block and the size - of the block. - -For example, the following is the bare minimum node: - - pinctrl@35004800 { - compatible = "brcm,capri-pinctrl"; - reg = <0x35004800 0x430>; - }; - -As a pin controller device, in addition to the required properties, this node -should also contain the pin configuration nodes that client devices reference, -if any. - -=== Pin Configuration Node === - -Each pin configuration node is a sub-node of the pin controller node and is a -container of an arbitrary number of subnodes, called pin group nodes in this -document. - -Please refer to the pinctrl-bindings.txt in this directory for details of the -common pinctrl bindings used by client devices, including the definition of a -"pin configuration node". - -=== Pin Group Node === - -A pin group node specifies the desired pin mux and/or pin configuration for an -arbitrary number of pins. The name of the pin group node is optional and not -used. - -A pin group node only affects the properties specified in the node, and has no -effect on any properties that are omitted. - -The pin group node accepts a subset of the generic pin config properties. For -details generic pin config properties, please refer to pinctrl-bindings.txt -and . - -Each pin controlled by this pin controller belong to one of three types: -Standard, I2C, and HDMI. Each type accepts a different set of pin config -properties. A list of pins and their types is provided below. - -Required Properties (applicable to all pins): - -- pins: Multiple strings. Specifies the name(s) of one or more pins to - be configured by this node. - -Optional Properties (for standard pins): - -- function: String. Specifies the pin mux selection. Values - must be one of: "alt1", "alt2", "alt3", "alt4" -- input-schmitt-enable: No arguments. Enable schmitt-trigger mode. -- input-schmitt-disable: No arguments. Disable schmitt-trigger mode. -- bias-pull-up: No arguments. Pull up on pin. -- bias-pull-down: No arguments. Pull down on pin. -- bias-disable: No arguments. Disable pin bias. -- slew-rate: Integer. Meaning depends on configured pin mux: - *_SCL or *_SDA: - 0: Standard(100kbps)& Fast(400kbps) mode - 1: Highspeed (3.4Mbps) mode - IC_DM or IC_DP: - 0: normal slew rate - 1: fast slew rate - Otherwise: - 0: fast slew rate - 1: normal slew rate -- input-enable: No arguements. Enable input (does not affect - output.) -- input-disable: No arguements. Disable input (does not affect - output.) -- drive-strength: Integer. Drive strength in mA. Valid values are - 2, 4, 6, 8, 10, 12, 14, 16 mA. - -Optional Properties (for I2C pins): - -- function: String. Specifies the pin mux selection. Values - must be one of: "alt1", "alt2", "alt3", "alt4" -- bias-pull-up: Integer. Pull up strength in Ohm. There are 3 - pull-up resisitors (1.2k, 1.8k, 2.7k) available - in parallel for I2C pins, so the valid values - are: 568, 720, 831, 1080, 1200, 1800, 2700 Ohm. -- bias-disable: No arguments. Disable pin bias. -- slew-rate: Integer. Meaning depends on configured pin mux: - *_SCL or *_SDA: - 0: Standard(100kbps)& Fast(400kbps) mode - 1: Highspeed (3.4Mbps) mode - IC_DM or IC_DP: - 0: normal slew rate - 1: fast slew rate - Otherwise: - 0: fast slew rate - 1: normal slew rate -- input-enable: No arguements. Enable input (does not affect - output.) -- input-disable: No arguements. Disable input (does not affect - output.) - -Optional Properties (for HDMI pins): - -- function: String. Specifies the pin mux selection. Values - must be one of: "alt1", "alt2", "alt3", "alt4" -- slew-rate: Integer. Controls slew rate. - 0: Standard(100kbps)& Fast(400kbps) mode - 1: Highspeed (3.4Mbps) mode -- input-enable: No arguements. Enable input (does not affect - output.) -- input-disable: No arguements. Disable input (does not affect - output.) - -Example: -// pin controller node -pinctrl@35004800 { - compatible = "brcm,capri-pinctrl"; - reg = <0x35004800 0x430>; - - // pin configuration node - dev_a_default: dev_a_active { - //group node defining 1 standard pin - grp_1 { - pins = "std_pin1"; - function = "alt1"; - input-schmitt-enable; - bias-disable; - slew-rate = <1>; - drive-strength = <4>; - }; - - // group node defining 2 I2C pins - grp_2 { - pins = "i2c_pin1", "i2c_pin2"; - function = "alt2"; - bias-pull-up = <720>; - input-enable; - }; - - // group node defining 2 HDMI pins - grp_3 { - pins = "hdmi_pin1", "hdmi_pin2"; - function = "alt3"; - slew-rate = <1>; - }; - - // other pin group nodes - ... - }; - - // other pin configuration nodes - ... -}; - -In the example above, "dev_a_active" is a pin configuration node with a number -of sub-nodes. In the pin group node "grp_1", one pin, "std_pin1", is defined in -the "pins" property. Thus, the remaining properties in the "grp_1" node applies -only to this pin, including the following settings: - - setting pinmux to "alt1" - - enabling schmitt-trigger (hystersis) mode - - disabling pin bias - - setting the slew-rate to 1 - - setting the drive strength to 4 mA -Note that neither "input-enable" nor "input-disable" was specified - the pinctrl -subsystem will therefore leave this property unchanged from whatever state it -was in before applying these changes. - -The "pins" property in the pin group node "grp_2" specifies two pins - -"i2c_pin1" and "i2c_pin2"; the remaining properties in this pin group node, -therefore, applies to both of these pins. The properties include: - - setting pinmux to "alt2" - - setting pull-up resistance to 720 Ohm (ie. enabling 1.2k and 1.8k resistors - in parallel) - - enabling both pins' input -"slew-rate" is not specified in this pin group node, so the slew-rate for these -pins are left as-is. - -Finally, "grp_3" defines two HDMI pins. The following properties are applied to -both pins: - - setting pinmux to "alt3" - - setting slew-rate to 1; for HDMI pins, this corresponds to the 3.4 Mbps - Highspeed mode -The input is neither enabled or disabled, and is left untouched. - -=== Pin Names and Type === - -The following are valid pin names and their pin types: - - "adcsync", Standard - "bat_rm", Standard - "bsc1_scl", I2C - "bsc1_sda", I2C - "bsc2_scl", I2C - "bsc2_sda", I2C - "classgpwr", Standard - "clk_cx8", Standard - "clkout_0", Standard - "clkout_1", Standard - "clkout_2", Standard - "clkout_3", Standard - "clkreq_in_0", Standard - "clkreq_in_1", Standard - "cws_sys_req1", Standard - "cws_sys_req2", Standard - "cws_sys_req3", Standard - "digmic1_clk", Standard - "digmic1_dq", Standard - "digmic2_clk", Standard - "digmic2_dq", Standard - "gpen13", Standard - "gpen14", Standard - "gpen15", Standard - "gpio00", Standard - "gpio01", Standard - "gpio02", Standard - "gpio03", Standard - "gpio04", Standard - "gpio05", Standard - "gpio06", Standard - "gpio07", Standard - "gpio08", Standard - "gpio09", Standard - "gpio10", Standard - "gpio11", Standard - "gpio12", Standard - "gpio13", Standard - "gpio14", Standard - "gps_pablank", Standard - "gps_tmark", Standard - "hdmi_scl", HDMI - "hdmi_sda", HDMI - "ic_dm", Standard - "ic_dp", Standard - "kp_col_ip_0", Standard - "kp_col_ip_1", Standard - "kp_col_ip_2", Standard - "kp_col_ip_3", Standard - "kp_row_op_0", Standard - "kp_row_op_1", Standard - "kp_row_op_2", Standard - "kp_row_op_3", Standard - "lcd_b_0", Standard - "lcd_b_1", Standard - "lcd_b_2", Standard - "lcd_b_3", Standard - "lcd_b_4", Standard - "lcd_b_5", Standard - "lcd_b_6", Standard - "lcd_b_7", Standard - "lcd_g_0", Standard - "lcd_g_1", Standard - "lcd_g_2", Standard - "lcd_g_3", Standard - "lcd_g_4", Standard - "lcd_g_5", Standard - "lcd_g_6", Standard - "lcd_g_7", Standard - "lcd_hsync", Standard - "lcd_oe", Standard - "lcd_pclk", Standard - "lcd_r_0", Standard - "lcd_r_1", Standard - "lcd_r_2", Standard - "lcd_r_3", Standard - "lcd_r_4", Standard - "lcd_r_5", Standard - "lcd_r_6", Standard - "lcd_r_7", Standard - "lcd_vsync", Standard - "mdmgpio0", Standard - "mdmgpio1", Standard - "mdmgpio2", Standard - "mdmgpio3", Standard - "mdmgpio4", Standard - "mdmgpio5", Standard - "mdmgpio6", Standard - "mdmgpio7", Standard - "mdmgpio8", Standard - "mphi_data_0", Standard - "mphi_data_1", Standard - "mphi_data_2", Standard - "mphi_data_3", Standard - "mphi_data_4", Standard - "mphi_data_5", Standard - "mphi_data_6", Standard - "mphi_data_7", Standard - "mphi_data_8", Standard - "mphi_data_9", Standard - "mphi_data_10", Standard - "mphi_data_11", Standard - "mphi_data_12", Standard - "mphi_data_13", Standard - "mphi_data_14", Standard - "mphi_data_15", Standard - "mphi_ha0", Standard - "mphi_hat0", Standard - "mphi_hat1", Standard - "mphi_hce0_n", Standard - "mphi_hce1_n", Standard - "mphi_hrd_n", Standard - "mphi_hwr_n", Standard - "mphi_run0", Standard - "mphi_run1", Standard - "mtx_scan_clk", Standard - "mtx_scan_data", Standard - "nand_ad_0", Standard - "nand_ad_1", Standard - "nand_ad_2", Standard - "nand_ad_3", Standard - "nand_ad_4", Standard - "nand_ad_5", Standard - "nand_ad_6", Standard - "nand_ad_7", Standard - "nand_ale", Standard - "nand_cen_0", Standard - "nand_cen_1", Standard - "nand_cle", Standard - "nand_oen", Standard - "nand_rdy_0", Standard - "nand_rdy_1", Standard - "nand_wen", Standard - "nand_wp", Standard - "pc1", Standard - "pc2", Standard - "pmu_int", Standard - "pmu_scl", I2C - "pmu_sda", I2C - "rfst2g_mtsloten3g", Standard - "rgmii_0_rx_ctl", Standard - "rgmii_0_rxc", Standard - "rgmii_0_rxd_0", Standard - "rgmii_0_rxd_1", Standard - "rgmii_0_rxd_2", Standard - "rgmii_0_rxd_3", Standard - "rgmii_0_tx_ctl", Standard - "rgmii_0_txc", Standard - "rgmii_0_txd_0", Standard - "rgmii_0_txd_1", Standard - "rgmii_0_txd_2", Standard - "rgmii_0_txd_3", Standard - "rgmii_1_rx_ctl", Standard - "rgmii_1_rxc", Standard - "rgmii_1_rxd_0", Standard - "rgmii_1_rxd_1", Standard - "rgmii_1_rxd_2", Standard - "rgmii_1_rxd_3", Standard - "rgmii_1_tx_ctl", Standard - "rgmii_1_txc", Standard - "rgmii_1_txd_0", Standard - "rgmii_1_txd_1", Standard - "rgmii_1_txd_2", Standard - "rgmii_1_txd_3", Standard - "rgmii_gpio_0", Standard - "rgmii_gpio_1", Standard - "rgmii_gpio_2", Standard - "rgmii_gpio_3", Standard - "rtxdata2g_txdata3g1", Standard - "rtxen2g_txdata3g2", Standard - "rxdata3g0", Standard - "rxdata3g1", Standard - "rxdata3g2", Standard - "sdio1_clk", Standard - "sdio1_cmd", Standard - "sdio1_data_0", Standard - "sdio1_data_1", Standard - "sdio1_data_2", Standard - "sdio1_data_3", Standard - "sdio4_clk", Standard - "sdio4_cmd", Standard - "sdio4_data_0", Standard - "sdio4_data_1", Standard - "sdio4_data_2", Standard - "sdio4_data_3", Standard - "sim_clk", Standard - "sim_data", Standard - "sim_det", Standard - "sim_resetn", Standard - "sim2_clk", Standard - "sim2_data", Standard - "sim2_det", Standard - "sim2_resetn", Standard - "sri_c", Standard - "sri_d", Standard - "sri_e", Standard - "ssp_extclk", Standard - "ssp0_clk", Standard - "ssp0_fs", Standard - "ssp0_rxd", Standard - "ssp0_txd", Standard - "ssp2_clk", Standard - "ssp2_fs_0", Standard - "ssp2_fs_1", Standard - "ssp2_fs_2", Standard - "ssp2_fs_3", Standard - "ssp2_rxd_0", Standard - "ssp2_rxd_1", Standard - "ssp2_txd_0", Standard - "ssp2_txd_1", Standard - "ssp3_clk", Standard - "ssp3_fs", Standard - "ssp3_rxd", Standard - "ssp3_txd", Standard - "ssp4_clk", Standard - "ssp4_fs", Standard - "ssp4_rxd", Standard - "ssp4_txd", Standard - "ssp5_clk", Standard - "ssp5_fs", Standard - "ssp5_rxd", Standard - "ssp5_txd", Standard - "ssp6_clk", Standard - "ssp6_fs", Standard - "ssp6_rxd", Standard - "ssp6_txd", Standard - "stat_1", Standard - "stat_2", Standard - "sysclken", Standard - "traceclk", Standard - "tracedt00", Standard - "tracedt01", Standard - "tracedt02", Standard - "tracedt03", Standard - "tracedt04", Standard - "tracedt05", Standard - "tracedt06", Standard - "tracedt07", Standard - "tracedt08", Standard - "tracedt09", Standard - "tracedt10", Standard - "tracedt11", Standard - "tracedt12", Standard - "tracedt13", Standard - "tracedt14", Standard - "tracedt15", Standard - "txdata3g0", Standard - "txpwrind", Standard - "uartb1_ucts", Standard - "uartb1_urts", Standard - "uartb1_urxd", Standard - "uartb1_utxd", Standard - "uartb2_urxd", Standard - "uartb2_utxd", Standard - "uartb3_ucts", Standard - "uartb3_urts", Standard - "uartb3_urxd", Standard - "uartb3_utxd", Standard - "uartb4_ucts", Standard - "uartb4_urts", Standard - "uartb4_urxd", Standard - "uartb4_utxd", Standard - "vc_cam1_scl", I2C - "vc_cam1_sda", I2C - "vc_cam2_scl", I2C - "vc_cam2_sda", I2C - "vc_cam3_scl", I2C - "vc_cam3_sda", I2C -- cgit v0.10.2 From 30812cca63600a3e4b44b93ed2ec7e00ce572ee0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:34:45 +0100 Subject: ASoC: da732x: Use da732x->regmap instead of codec->control_data With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the da732x driver for this by using da732x->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Acked-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 05f07fb..cf9b154 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1471,8 +1471,8 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, da732x_hp_dc_offset_cancellation(codec); - regcache_cache_only(codec->control_data, false); - regcache_sync(codec->control_data); + regcache_cache_only(da732x->regmap, false); + regcache_sync(da732x->regmap); } else { snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_BOOST_MASK, @@ -1483,7 +1483,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, } break; case SND_SOC_BIAS_OFF: - regcache_cache_only(codec->control_data, true); + regcache_cache_only(da732x->regmap, true); da732x_set_charge_pump(codec, DA732X_DISABLE_CP); snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, DA732X_BIAS_DIS); -- cgit v0.10.2 From 180c275eb8a65c919d09af49179b99e4c01a3d1e Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Sat, 22 Feb 2014 16:00:16 +0100 Subject: ASoC: wm8993: Remove unused pointer in wm8993_remove() Commit 88b5bdfd (ASoC: wm8993: drop regulator_bulk_free of devm_ allocated data) eliminated the last user of driver data pointer 'wm8993' in function wm8993_remove() - Thus remove it. Detected by Coverity: CID 1186208. Signed-off-by: Christian Engelmayer Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 1c12f2c..7b0630a 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1559,8 +1559,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) static int wm8993_remove(struct snd_soc_codec *codec) { - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -- cgit v0.10.2 From b7c1b73097b48a7922d1320d5a8c8315ff4fae71 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:32:04 +0100 Subject: ASoC: wm8996: Replace codec->control_data with wm8996->regmap With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the wm8996 driver for this by using wm8996->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 92bb021..36a52b9 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1608,8 +1608,8 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, msleep(5); } - regcache_cache_only(codec->control_data, false); - regcache_sync(codec->control_data); + regcache_cache_only(wm8996->regmap, false); + regcache_sync(wm8996->regmap); } /* Bypass the MICBIASes for lowest power */ @@ -1620,10 +1620,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - regcache_cache_only(codec->control_data, true); + regcache_cache_only(wm8996->regmap, true); if (wm8996->pdata.ldo_ena >= 0) { gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); - regcache_cache_only(codec->control_data, true); + regcache_cache_only(wm8996->regmap, true); } regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); -- cgit v0.10.2 From d7f31d3c898e3e621a34d5d64966f7b830df66f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:32:05 +0100 Subject: ASoC: wm8962: Replace codec->control_data with wm8962->regmap With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the wm8962 driver for this by using wm8962->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 3924ee2..6ff1ff8 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1479,7 +1479,9 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) { - return regcache_sync_region(codec->control_data, + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + return regcache_sync_region(wm8962->regmap, WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER); } -- cgit v0.10.2 From 548da08fc1e245faf9b0d7c41ecd8e07984fc332 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:30:13 +0100 Subject: ASoC: wm8958-dsp: Fix firmware block loading The codec->control_data contains a pointer to the device's regmap struct. But wm8994_bulk_write() expects a pointer to the parent wm8998 device. The issue was introduced in commit d9a7666f ("ASoC: Remove ASoC-specific WM8994 I/O code"). Fixes: d9a7666f ("ASoC: Remove ASoC-specific WM8994 I/O code") Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index b7488f1..d4248e0 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -153,7 +153,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name, data32 &= 0xffffff; - wm8994_bulk_write(codec->control_data, + wm8994_bulk_write(wm8994->wm8994, data32 & 0xffffff, block_len / 2, (void *)(data + 8)); -- cgit v0.10.2 From 00efcb1c8e1c3c5e5d3ce6f0682d66402911a84f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 7 Jan 2014 13:03:43 +0100 Subject: clk: Correct handling of NULL clk in __clk_{get, put} Ensure clk->kref is dereferenced only when clk is not NULL. Signed-off-by: Sylwester Nawrocki Tested-by: Sachin Kamat Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5517944..c42e608 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2226,24 +2226,25 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister); */ int __clk_get(struct clk *clk) { - if (clk && !try_module_get(clk->owner)) - return 0; + if (clk) { + if (!try_module_get(clk->owner)) + return 0; - kref_get(&clk->ref); + kref_get(&clk->ref); + } return 1; } void __clk_put(struct clk *clk) { - if (WARN_ON_ONCE(IS_ERR(clk))) + if (!clk || WARN_ON_ONCE(IS_ERR(clk))) return; clk_prepare_lock(); kref_put(&clk->ref, __clk_release); clk_prepare_unlock(); - if (clk) - module_put(clk->owner); + module_put(clk->owner); } /*** clk rate change notifiers ***/ -- cgit v0.10.2 From c0f5eeed0f4cef4f05b74883a7160e7edde58b6a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 24 Feb 2014 09:39:27 +0100 Subject: i7core_edac: Fix PCI device reference count The reference count changes done by pci_get_device can be a little misleading when the usage diverges from the most common scheme. The reference count of the device passed as the last parameter is always decreased, even if the function returns no new device. So if we are going to try alternative device IDs, we must manually increment the device reference count before each retry. If we don't, we end up decreasing the reference count, and after a few modprobe/rmmod cycles the PCI devices will vanish. In other words and as Alan put it: without this fix the EDAC code corrupts the PCI device list. This fixes kernel bug #50491: https://bugzilla.kernel.org/show_bug.cgi?id=50491 Signed-off-by: Jean Delvare Link: http://lkml.kernel.org/r/20140224093927.7659dd9d@endymion.delvare Reviewed-by: Alan Cox Cc: Mauro Carvalho Chehab Cc: Doug Thompson Cc: stable@vger.kernel.org Signed-off-by: Borislav Petkov diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 87533ca..d871275 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1334,14 +1334,19 @@ static int i7core_get_onedevice(struct pci_dev **prev, * is at addr 8086:2c40, instead of 8086:2c41. So, we need * to probe for the alternate address in case of failure */ - if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) + if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) { + pci_dev_get(*prev); /* pci_get_device will put it */ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); + } - if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev) + if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && + !pdev) { + pci_dev_get(*prev); /* pci_get_device will put it */ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT, *prev); + } if (!pdev) { if (*prev) { -- cgit v0.10.2 From 75135da0d68419ef8a925f4c1d5f63d8046e314d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 25 Feb 2014 09:43:13 +0100 Subject: i7300_edac: Fix device reference count pci_get_device() decrements the reference count of "from" (last argument) so when we break off the loop successfully we have only one device reference - and we don't know which device we have. If we want a reference to each device, we must take them explicitly and let the pci_get_device() walk complete to avoid duplicate references. This is serious, as over-putting device references will cause the device to eventually disappear. Without this fix, the kernel crashes after a few insmod/rmmod cycles. Tested on an Intel S7000FC4UR system with a 7300 chipset. Signed-off-by: Jean Delvare Link: http://lkml.kernel.org/r/20140224111656.09bbb7ed@endymion.delvare Cc: Mauro Carvalho Chehab Cc: Doug Thompson Cc: stable@vger.kernel.org Signed-off-by: Borislav Petkov diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index d63f479..57e96a3 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -943,33 +943,35 @@ static int i7300_get_devices(struct mem_ctl_info *mci) /* Attempt to 'get' the MCH register we want */ pdev = NULL; - while (!pvt->pci_dev_16_1_fsb_addr_map || - !pvt->pci_dev_16_2_fsb_err_regs) { - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev); - if (!pdev) { - /* End of list, leave */ - i7300_printk(KERN_ERR, - "'system address,Process Bus' " - "device not found:" - "vendor 0x%x device 0x%x ERR funcs " - "(broken BIOS?)\n", - PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_I7300_MCH_ERR); - goto error; - } - + while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, + pdev))) { /* Store device 16 funcs 1 and 2 */ switch (PCI_FUNC(pdev->devfn)) { case 1: - pvt->pci_dev_16_1_fsb_addr_map = pdev; + if (!pvt->pci_dev_16_1_fsb_addr_map) + pvt->pci_dev_16_1_fsb_addr_map = + pci_dev_get(pdev); break; case 2: - pvt->pci_dev_16_2_fsb_err_regs = pdev; + if (!pvt->pci_dev_16_2_fsb_err_regs) + pvt->pci_dev_16_2_fsb_err_regs = + pci_dev_get(pdev); break; } } + if (!pvt->pci_dev_16_1_fsb_addr_map || + !pvt->pci_dev_16_2_fsb_err_regs) { + /* At least one device was not found */ + i7300_printk(KERN_ERR, + "'system address,Process Bus' device not found:" + "vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7300_MCH_ERR); + goto error; + } + edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", pci_name(pvt->pci_dev_16_0_fsb_ctlr), pvt->pci_dev_16_0_fsb_ctlr->vendor, -- cgit v0.10.2 From 2513190a926f093dbdc301c68e6ade0bcf293f9a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 21 Feb 2014 19:02:34 +0100 Subject: fsnotify: Fix detection whether overflow event is queued Currently we didn't initialize event's list head when we removed it from the event list. Thus a detection whether overflow event is already queued wasn't working. Fix it by always initializing the list head when deleting event from a list. Signed-off-by: Jan Kara diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 18b3c44..6bec2f4 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -132,7 +132,11 @@ struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group event = list_first_entry(&group->notification_list, struct fsnotify_event, list); - list_del(&event->list); + /* + * We need to init list head for the case of overflow event so that + * check in fsnotify_add_notify_events() works + */ + list_del_init(&event->list); group->q_len--; return event; -- cgit v0.10.2 From 482ef06c5e946aae360f247dc69471ec031e09d2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 21 Feb 2014 19:07:54 +0100 Subject: fanotify: Handle overflow in case of permission events If the event queue overflows when we are handling permission event, we will never get response from userspace. So we must avoid waiting for it. Change fsnotify_add_notify_event() to return whether overflow has happened so that we can detect it in fanotify_handle_event() and act accordingly. Signed-off-by: Jan Kara diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 205dc21..dc638f7 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -192,10 +192,12 @@ static int fanotify_handle_event(struct fsnotify_group *group, ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge); if (ret) { - BUG_ON(mask & FAN_ALL_PERM_EVENTS); + /* Permission events shouldn't be merged */ + BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS); /* Our event wasn't used in the end. Free it. */ fsnotify_destroy_event(group, fsn_event); - ret = 0; + + return 0; } #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 6bec2f4..6a4ba17 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -80,7 +80,8 @@ void fsnotify_destroy_event(struct fsnotify_group *group, /* * Add an event to the group notification queue. The group can later pull this * event off the queue to deal with. The function returns 0 if the event was - * added to the queue, 1 if the event was merged with some other queued event. + * added to the queue, 1 if the event was merged with some other queued event, + * 2 if the queue of events has overflown. */ int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event, @@ -95,10 +96,14 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, mutex_lock(&group->notification_mutex); if (group->q_len >= group->max_events) { + ret = 2; /* Queue overflow event only if it isn't already queued */ - if (list_empty(&group->overflow_event.list)) - event = &group->overflow_event; - ret = 1; + if (!list_empty(&group->overflow_event.list)) { + mutex_unlock(&group->notification_mutex); + return ret; + } + event = &group->overflow_event; + goto queue; } if (!list_empty(list) && merge) { @@ -109,6 +114,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, } } +queue: group->q_len++; list_add_tail(&event->list, list); mutex_unlock(&group->notification_mutex); -- cgit v0.10.2 From ff57cd5863cf3014c1c5ed62ce2715294f065b17 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 21 Feb 2014 19:14:11 +0100 Subject: fsnotify: Allocate overflow events with proper type Commit 7053aee26a35 "fsnotify: do not share events between notification groups" used overflow event statically allocated in a group with the size of the generic notification event. This causes problems because some code looks at type specific parts of event structure and gets confused by a random data it sees there and causes crashes. Fix the problem by allocating overflow event with type corresponding to the group type so code cannot get confused. Signed-off-by: Jan Kara diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index b6175fa..287a22c 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -698,6 +698,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) struct fsnotify_group *group; int f_flags, fd; struct user_struct *user; + struct fanotify_event_info *oevent; pr_debug("%s: flags=%d event_f_flags=%d\n", __func__, flags, event_f_flags); @@ -730,8 +731,20 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) group->fanotify_data.user = user; atomic_inc(&user->fanotify_listeners); + oevent = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL); + if (unlikely(!oevent)) { + fd = -ENOMEM; + goto out_destroy_group; + } + group->overflow_event = &oevent->fse; + fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW); + oevent->tgid = get_pid(task_tgid(current)); + oevent->path.mnt = NULL; + oevent->path.dentry = NULL; + group->fanotify_data.f_flags = event_f_flags; #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS + oevent->response = 0; mutex_init(&group->fanotify_data.access_mutex); init_waitqueue_head(&group->fanotify_data.access_waitq); INIT_LIST_HEAD(&group->fanotify_data.access_list); diff --git a/fs/notify/group.c b/fs/notify/group.c index ee674fe..ad19959 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -55,6 +55,13 @@ void fsnotify_destroy_group(struct fsnotify_group *group) /* clear the notification queue of all events */ fsnotify_flush_notify(group); + /* + * Destroy overflow event (we cannot use fsnotify_destroy_event() as + * that deliberately ignores overflow events. + */ + if (group->overflow_event) + group->ops->free_event(group->overflow_event); + fsnotify_put_group(group); } @@ -99,7 +106,6 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) INIT_LIST_HEAD(&group->marks_list); group->ops = ops; - fsnotify_init_event(&group->overflow_event, NULL, FS_Q_OVERFLOW); return group; } diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 6528b5a..78a2ca3 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -633,11 +633,23 @@ static int inotify_update_watch(struct fsnotify_group *group, struct inode *inod static struct fsnotify_group *inotify_new_group(unsigned int max_events) { struct fsnotify_group *group; + struct inotify_event_info *oevent; group = fsnotify_alloc_group(&inotify_fsnotify_ops); if (IS_ERR(group)) return group; + oevent = kmalloc(sizeof(struct inotify_event_info), GFP_KERNEL); + if (unlikely(!oevent)) { + fsnotify_destroy_group(group); + return ERR_PTR(-ENOMEM); + } + group->overflow_event = &oevent->fse; + fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW); + oevent->wd = -1; + oevent->sync_cookie = 0; + oevent->name_len = 0; + group->max_events = max_events; spin_lock_init(&group->inotify_data.idr_lock); diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 6a4ba17..1e58402 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -98,11 +98,11 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, if (group->q_len >= group->max_events) { ret = 2; /* Queue overflow event only if it isn't already queued */ - if (!list_empty(&group->overflow_event.list)) { + if (!list_empty(&group->overflow_event->list)) { mutex_unlock(&group->notification_mutex); return ret; } - event = &group->overflow_event; + event = group->overflow_event; goto queue; } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index c84bc7c..64cf3ef 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -160,7 +160,7 @@ struct fsnotify_group { struct fasync_struct *fsn_fa; /* async notification */ - struct fsnotify_event overflow_event; /* Event we queue when the + struct fsnotify_event *overflow_event; /* Event we queue when the * notification list is too * full */ -- cgit v0.10.2 From 8d971691834fd5506cb2d7aef71a3717b7ed597d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 25 Feb 2014 15:10:39 +0530 Subject: ASoC: samsung: Remove invalid file reference Remove file references rendered invalid due to relocation. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h index 9efc04d..709c6f7 100644 --- a/include/linux/platform_data/asoc-s3c.h +++ b/include/linux/platform_data/asoc-s3c.h @@ -1,5 +1,4 @@ -/* arch/arm/plat-samsung/include/plat/audio.h - * +/* * Copyright (c) 2009 Samsung Electronics Co. Ltd * Author: Jaswinder Singh * -- cgit v0.10.2 From c3c125e294fd4276add6f80d2b333ca7c55e935d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 25 Feb 2014 15:10:40 +0530 Subject: ASoC: s3c24xx: Remove invalid file reference Remove file references rendered invalid due to relocation. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown diff --git a/include/linux/platform_data/asoc-s3c24xx_simtec.h b/include/linux/platform_data/asoc-s3c24xx_simtec.h index 376af52..d220e54 100644 --- a/include/linux/platform_data/asoc-s3c24xx_simtec.h +++ b/include/linux/platform_data/asoc-s3c24xx_simtec.h @@ -1,5 +1,4 @@ -/* arch/arm/plat-samsung/include/plat/audio-simtec.h - * +/* * Copyright 2008 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks -- cgit v0.10.2 From 092008abeed1e4168c08826262695ea67657e1aa Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Fri, 14 Feb 2014 08:54:00 +0100 Subject: cfg80211: regulatory: reset regdomain in case of error Reset regdomain to world regdomain in case of errors in set_regdom() function. This will fix a problem with such scenario: - iw reg set US - iw reg set 00 - iw reg set US The last step always fail and we get deadlock in kernel regulatory code. Next setting new regulatory wasn't possible due to: Pending regulatory request, waiting for it to be processed... Signed-off-by: Janusz Dziedzic Acked-by: Luis R. Rodriguez Signed-off-by: Johannes Berg diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4c50c21..f054137 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, int set_regdom(const struct ieee80211_regdomain *rd) { struct regulatory_request *lr; + bool user_reset = false; int r; if (!reg_is_valid_request(rd->alpha2)) { @@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) break; case NL80211_REGDOM_SET_BY_USER: r = reg_set_rd_user(rd, lr); + user_reset = true; break; case NL80211_REGDOM_SET_BY_DRIVER: r = reg_set_rd_driver(rd, lr); @@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd) } if (r) { - if (r == -EALREADY) + switch (r) { + case -EALREADY: reg_set_request_processed(); + break; + default: + /* Back to world regulatory in case of errors */ + restore_regulatory_settings(user_reset); + } kfree(rd); return r; -- cgit v0.10.2 From fed95bab8d29b928fcf6225be72d37ded452e8a2 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 25 Feb 2014 19:28:44 +0800 Subject: sysfs: fix namespace refcnt leak As mount() and kill_sb() is not a one-to-one match, we shoudn't get ns refcnt unconditionally in sysfs_mount(), and instead we should get the refcnt only when kernfs_mount() allocated a new superblock. v2: - Changed the name of the new argument, suggested by Tejun. - Made the argument optional, suggested by Tejun. v3: - Make the new argument as second-to-last arg, suggested by Tejun. Signed-off-by: Li Zefan Acked-by: Tejun Heo --- fs/kernfs/mount.c | 8 +++++++- fs/sysfs/mount.c | 5 +++-- include/linux/kernfs.h | 9 +++++---- 3 files changed, 15 insertions(+), 7 deletions(-) Signed-off-by: Greg Kroah-Hartman diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index 0d6ce89..0f4152d 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -94,6 +94,7 @@ const void *kernfs_super_ns(struct super_block *sb) * @fs_type: file_system_type of the fs being mounted * @flags: mount flags specified for the mount * @root: kernfs_root of the hierarchy being mounted + * @new_sb_created: tell the caller if we allocated a new superblock * @ns: optional namespace tag of the mount * * This is to be called from each kernfs user's file_system_type->mount() @@ -104,7 +105,8 @@ const void *kernfs_super_ns(struct super_block *sb) * The return value can be passed to the vfs layer verbatim. */ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, - struct kernfs_root *root, const void *ns) + struct kernfs_root *root, bool *new_sb_created, + const void *ns) { struct super_block *sb; struct kernfs_super_info *info; @@ -122,6 +124,10 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, kfree(info); if (IS_ERR(sb)) return ERR_CAST(sb); + + if (new_sb_created) + *new_sb_created = !sb->s_root; + if (!sb->s_root) { error = kernfs_fill_super(sb); if (error) { diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 6211230..3eaf5c6 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -27,6 +27,7 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, { struct dentry *root; void *ns; + bool new_sb; if (!(flags & MS_KERNMOUNT)) { if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type)) @@ -37,8 +38,8 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, } ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET); - root = kernfs_mount_ns(fs_type, flags, sysfs_root, ns); - if (IS_ERR(root)) + root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns); + if (IS_ERR(root) || !new_sb) kobj_ns_drop(KOBJ_NS_TYPE_NET, ns); return root; } diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index 5be9f02..d267623 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -249,7 +249,8 @@ void kernfs_notify(struct kernfs_node *kn); const void *kernfs_super_ns(struct super_block *sb); struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, - struct kernfs_root *root, const void *ns); + struct kernfs_root *root, bool *new_sb_created, + const void *ns); void kernfs_kill_sb(struct super_block *sb); void kernfs_init(void); @@ -317,7 +318,7 @@ static inline const void *kernfs_super_ns(struct super_block *sb) static inline struct dentry * kernfs_mount_ns(struct file_system_type *fs_type, int flags, - struct kernfs_root *root, const void *ns) + struct kernfs_root *root, bool *new_sb_created, const void *ns) { return ERR_PTR(-ENOSYS); } static inline void kernfs_kill_sb(struct super_block *sb) { } @@ -368,9 +369,9 @@ static inline int kernfs_remove_by_name(struct kernfs_node *parent, static inline struct dentry * kernfs_mount(struct file_system_type *fs_type, int flags, - struct kernfs_root *root) + struct kernfs_root *root, bool *new_sb_created) { - return kernfs_mount_ns(fs_type, flags, root, NULL); + return kernfs_mount_ns(fs_type, flags, root, new_sb_created, NULL); } #endif /* __LINUX_KERNFS_H */ -- cgit v0.10.2 From da87ca4d4ca101f177fffd84f1f0a5e4c0343557 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 19 Feb 2014 16:19:35 -0800 Subject: ioat: fix tasklet tear down Since commit 77873803363c "net_dma: mark broken" we no longer pin dma engines active for the network-receive-offload use case. As a result the ->free_chan_resources() that occurs after the driver self test no longer has a NET_DMA induced ->alloc_chan_resources() to back it up. A late firing irq can lead to ksoftirqd spinning indefinitely due to the tasklet_disable() performed by ->free_chan_resources(). Only ->alloc_chan_resources() can clear this condition in affected kernels. This problem has been present since commit 3e037454bcfa "I/OAT: Add support for MSI and MSI-X" in 2.6.24, but is now exposed. Given the NET_DMA use case is deprecated we can revisit moving the driver to use threaded irqs. For now, just tear down the irq and tasklet properly by: 1/ Disable the irq from triggering the tasklet 2/ Disable the irq from re-arming 3/ Flush inflight interrupts 4/ Flush the timer 5/ Flush inflight tasklets References: https://lkml.org/lkml/2014/1/27/282 https://lkml.org/lkml/2014/2/19/672 Cc: Ingo Molnar Cc: Steven Rostedt Cc: Reported-by: Mike Galbraith Reported-by: Stanislav Fomichev Tested-by: Mike Galbraith Tested-by: Stanislav Fomichev Reviewed-by: Thomas Gleixner Signed-off-by: Dan Williams diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 8752918..4e3549a 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -77,7 +77,8 @@ static irqreturn_t ioat_dma_do_interrupt(int irq, void *data) attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET); for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) { chan = ioat_chan_by_index(instance, bit); - tasklet_schedule(&chan->cleanup_task); + if (test_bit(IOAT_RUN, &chan->state)) + tasklet_schedule(&chan->cleanup_task); } writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET); @@ -93,7 +94,8 @@ static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data) { struct ioat_chan_common *chan = data; - tasklet_schedule(&chan->cleanup_task); + if (test_bit(IOAT_RUN, &chan->state)) + tasklet_schedule(&chan->cleanup_task); return IRQ_HANDLED; } @@ -116,7 +118,6 @@ void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *c chan->timer.function = device->timer_fn; chan->timer.data = data; tasklet_init(&chan->cleanup_task, device->cleanup_fn, data); - tasklet_disable(&chan->cleanup_task); } /** @@ -354,13 +355,49 @@ static int ioat1_dma_alloc_chan_resources(struct dma_chan *c) writel(((u64) chan->completion_dma) >> 32, chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH); - tasklet_enable(&chan->cleanup_task); + set_bit(IOAT_RUN, &chan->state); ioat1_dma_start_null_desc(ioat); /* give chain to dma device */ dev_dbg(to_dev(chan), "%s: allocated %d descriptors\n", __func__, ioat->desccount); return ioat->desccount; } +void ioat_stop(struct ioat_chan_common *chan) +{ + struct ioatdma_device *device = chan->device; + struct pci_dev *pdev = device->pdev; + int chan_id = chan_num(chan); + struct msix_entry *msix; + + /* 1/ stop irq from firing tasklets + * 2/ stop the tasklet from re-arming irqs + */ + clear_bit(IOAT_RUN, &chan->state); + + /* flush inflight interrupts */ + switch (device->irq_mode) { + case IOAT_MSIX: + msix = &device->msix_entries[chan_id]; + synchronize_irq(msix->vector); + break; + case IOAT_MSI: + case IOAT_INTX: + synchronize_irq(pdev->irq); + break; + default: + break; + } + + /* flush inflight timers */ + del_timer_sync(&chan->timer); + + /* flush inflight tasklet runs */ + tasklet_kill(&chan->cleanup_task); + + /* final cleanup now that everything is quiesced and can't re-arm */ + device->cleanup_fn((unsigned long) &chan->common); +} + /** * ioat1_dma_free_chan_resources - release all the descriptors * @chan: the channel to be cleaned @@ -379,9 +416,7 @@ static void ioat1_dma_free_chan_resources(struct dma_chan *c) if (ioat->desccount == 0) return; - tasklet_disable(&chan->cleanup_task); - del_timer_sync(&chan->timer); - ioat1_cleanup(ioat); + ioat_stop(chan); /* Delay 100ms after reset to allow internal DMA logic to quiesce * before removing DMA descriptor resources. @@ -526,8 +561,11 @@ ioat1_dma_prep_memcpy(struct dma_chan *c, dma_addr_t dma_dest, static void ioat1_cleanup_event(unsigned long data) { struct ioat_dma_chan *ioat = to_ioat_chan((void *) data); + struct ioat_chan_common *chan = &ioat->base; ioat1_cleanup(ioat); + if (!test_bit(IOAT_RUN, &chan->state)) + return; writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); } diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 11fb877..e982f00 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -356,6 +356,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan, void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type); void ioat_kobject_del(struct ioatdma_device *device); int ioat_dma_setup_interrupts(struct ioatdma_device *device); +void ioat_stop(struct ioat_chan_common *chan); extern const struct sysfs_ops ioat_sysfs_ops; extern struct ioat_sysfs_entry ioat_version_attr; extern struct ioat_sysfs_entry ioat_cap_attr; diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 5d3affe..8d10580 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -190,8 +190,11 @@ static void ioat2_cleanup(struct ioat2_dma_chan *ioat) void ioat2_cleanup_event(unsigned long data) { struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); + struct ioat_chan_common *chan = &ioat->base; ioat2_cleanup(ioat); + if (!test_bit(IOAT_RUN, &chan->state)) + return; writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); } @@ -553,10 +556,10 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) ioat->issued = 0; ioat->tail = 0; ioat->alloc_order = order; + set_bit(IOAT_RUN, &chan->state); spin_unlock_bh(&ioat->prep_lock); spin_unlock_bh(&chan->cleanup_lock); - tasklet_enable(&chan->cleanup_task); ioat2_start_null_desc(ioat); /* check that we got off the ground */ @@ -566,7 +569,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) } while (i++ < 20 && !is_ioat_active(status) && !is_ioat_idle(status)); if (is_ioat_active(status) || is_ioat_idle(status)) { - set_bit(IOAT_RUN, &chan->state); return 1 << ioat->alloc_order; } else { u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); @@ -809,11 +811,8 @@ void ioat2_free_chan_resources(struct dma_chan *c) if (!ioat->ring) return; - tasklet_disable(&chan->cleanup_task); - del_timer_sync(&chan->timer); - device->cleanup_fn((unsigned long) c); + ioat_stop(chan); device->reset_hw(chan); - clear_bit(IOAT_RUN, &chan->state); spin_lock_bh(&chan->cleanup_lock); spin_lock_bh(&ioat->prep_lock); diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 820817e9..b9b38a1 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -464,8 +464,11 @@ static void ioat3_cleanup(struct ioat2_dma_chan *ioat) static void ioat3_cleanup_event(unsigned long data) { struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); + struct ioat_chan_common *chan = &ioat->base; ioat3_cleanup(ioat); + if (!test_bit(IOAT_RUN, &chan->state)) + return; writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); } -- cgit v0.10.2 From d31a36a6d87f68c3b97193bfca11e99d0cc385f7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 24 Feb 2014 22:26:05 +0100 Subject: ath9k: reduce baseband hang detection false positive rate Check if the baseband state remains stable, and add a small delay between register reads. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 11eab9f..303ce27 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav); bool ath9k_hw_check_alive(struct ath_hw *ah) { int count = 50; - u32 reg; + u32 reg, last_val; if (AR_SREV_9300(ah)) return !ath9k_hw_detect_mac_hang(ah); @@ -1542,9 +1542,13 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) if (AR_SREV_9285_12_OR_LATER(ah)) return true; + last_val = REG_READ(ah, AR_OBS_BUS_1); do { reg = REG_READ(ah, AR_OBS_BUS_1); + if (reg != last_val) + return true; + last_val = reg; if ((reg & 0x7E7FFFEF) == 0x00702400) continue; @@ -1556,6 +1560,8 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) default: return true; } + + udelay(1); } while (count-- > 0); return false; -- cgit v0.10.2 From b7b146c9c9a0248cc57da71244f672ebc54bbef1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 24 Feb 2014 22:26:06 +0100 Subject: ath9k: fix invalid descriptor discarding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only set sc->rx.discard_next to rx_stats->rs_more when actually discarding the current descriptor. Also, fix a detection of broken descriptors: First the code checks if the current descriptor is not done. Then it checks if the next descriptor is done. Add a check that afterwards checks the first descriptor again, because it might have been completed in the mean time. This fixes a regression introduced in commit 723e711356b5a8a95728a890e254e8b0d47b55cf "ath9k: fix handling of broken descriptors" Cc: stable@vger.kernel.org Reported-by: Marco André Dinis Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a0ebdd0..82e340d 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -732,11 +732,18 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc, return NULL; /* - * mark descriptor as zero-length and set the 'more' - * flag to ensure that both buffers get discarded + * Re-check previous descriptor, in case it has been filled + * in the mean time. */ - rs->rs_datalen = 0; - rs->rs_more = true; + ret = ath9k_hw_rxprocdesc(ah, ds, rs); + if (ret == -EINPROGRESS) { + /* + * mark descriptor as zero-length and set the 'more' + * flag to ensure that both buffers get discarded + */ + rs->rs_datalen = 0; + rs->rs_more = true; + } } list_del(&bf->list); @@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_hdr *hdr; bool discard_current = sc->rx.discard_next; - int ret = 0; /* * Discard corrupt descriptors which are marked in * ath_get_next_rx_buf(). */ - sc->rx.discard_next = rx_stats->rs_more; if (discard_current) - return -EINVAL; + goto corrupt; + + sc->rx.discard_next = false; /* * Discard zero-length packets. */ if (!rx_stats->rs_datalen) { RX_STAT_INC(rx_len_err); - return -EINVAL; + goto corrupt; } - /* - * rs_status follows rs_datalen so if rs_datalen is too large - * we can take a hint that hardware corrupted it, so ignore - * those frames. - */ + /* + * rs_status follows rs_datalen so if rs_datalen is too large + * we can take a hint that hardware corrupted it, so ignore + * those frames. + */ if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) { RX_STAT_INC(rx_len_err); - return -EINVAL; + goto corrupt; } /* Only use status info from the last fragment */ @@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, * This is different from the other corrupt descriptor * condition handled above. */ - if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) { - ret = -EINVAL; - goto exit; - } + if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) + goto corrupt; hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); @@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime)) RX_STAT_INC(rx_spectral); - ret = -EINVAL; - goto exit; + return -EINVAL; } /* * everything but the rate is checked here, the rate check is done * separately to avoid doing two lookups for a rate for each frame. */ - if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) { - ret = -EINVAL; - goto exit; - } + if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) + return -EINVAL; if (ath_is_mybeacon(common, hdr)) { RX_STAT_INC(rx_beacons); @@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, /* * This shouldn't happen, but have a safety check anyway. */ - if (WARN_ON(!ah->curchan)) { - ret = -EINVAL; - goto exit; - } + if (WARN_ON(!ah->curchan)) + return -EINVAL; - if (ath9k_process_rate(common, hw, rx_stats, rx_status)) { - ret =-EINVAL; - goto exit; - } + if (ath9k_process_rate(common, hw, rx_stats, rx_status)) + return -EINVAL; ath9k_process_rssi(common, hw, rx_stats, rx_status); @@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, sc->rx.num_pkts++; #endif -exit: - sc->rx.discard_next = false; - return ret; + return 0; + +corrupt: + sc->rx.discard_next = rx_stats->rs_more; + return -EINVAL; } static void ath9k_rx_skb_postprocess(struct ath_common *common, -- cgit v0.10.2 From 169a1d85d084edeb0736ad80fe439639ac938dcd Mon Sep 17 00:00:00 2001 From: Amir Vadai Date: Wed, 19 Feb 2014 17:47:31 +0200 Subject: net,IB/mlx: Bump all Mellanox driver versions Bump all Mellanox driver versions. Signed-off-by: Amir Vadai Signed-off-by: David S. Miller diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index e81c554..f9c12e9 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -53,8 +53,8 @@ #include "user.h" #define DRV_NAME MLX4_IB_DRV_NAME -#define DRV_VERSION "1.0" -#define DRV_RELDATE "April 4, 2008" +#define DRV_VERSION "2.2-1" +#define DRV_RELDATE "Feb 2014" #define MLX4_IB_FLOW_MAX_PRIO 0xFFF #define MLX4_IB_FLOW_QPN_MASK 0xFFFFFF diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index aa03e73..bf90057 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -46,8 +46,8 @@ #include "mlx5_ib.h" #define DRIVER_NAME "mlx5_ib" -#define DRIVER_VERSION "1.0" -#define DRIVER_RELDATE "June 2013" +#define DRIVER_VERSION "2.2-1" +#define DRIVER_RELDATE "Feb 2014" MODULE_AUTHOR("Eli Cohen "); MODULE_DESCRIPTION("Mellanox Connect-IB HCA IB driver"); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 6b65f77..7aec6c8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -51,8 +51,8 @@ #define DRV_NAME "mlx4_core" #define PFX DRV_NAME ": " -#define DRV_VERSION "1.1" -#define DRV_RELDATE "Dec, 2011" +#define DRV_VERSION "2.2-1" +#define DRV_RELDATE "Feb, 2014" #define MLX4_FS_UDP_UC_EN (1 << 1) #define MLX4_FS_TCP_UC_EN (1 << 2) diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 9ca223b..b57e8c8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -57,8 +57,8 @@ #include "en_port.h" #define DRV_NAME "mlx4_en" -#define DRV_VERSION "2.0" -#define DRV_RELDATE "Dec 2011" +#define DRV_VERSION "2.2-1" +#define DRV_RELDATE "Feb 2014" #define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index a064f06..23b7e2d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -46,8 +46,8 @@ #include "mlx5_core.h" #define DRIVER_NAME "mlx5_core" -#define DRIVER_VERSION "1.0" -#define DRIVER_RELDATE "June 2013" +#define DRIVER_VERSION "2.2-1" +#define DRIVER_RELDATE "Feb 2014" MODULE_AUTHOR("Eli Cohen "); MODULE_DESCRIPTION("Mellanox ConnectX-IB HCA core library"); -- cgit v0.10.2 From f229006ec6beabf7b844653d92fa61f025fe3dcf Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 25 Feb 2014 22:05:35 +0000 Subject: irq-metag*: stop set_affinity vectoring to offline cpus Fix irq_set_affinity callbacks in the Meta IRQ chip drivers to AND cpu_online_mask into the cpumask when picking a CPU to vector the interrupt to. As Thomas pointed out, the /proc/irq/$N/smp_affinity interface doesn't filter out offline CPUs, so without this patch if you offline CPU0 and set an IRQ affinity to 0x3 it vectors the interrupt onto CPU0 even though it is offline. Reported-by: Thomas Gleixner Signed-off-by: James Hogan Cc: Thomas Gleixner Cc: linux-metag@vger.kernel.org Cc: stable@vger.kernel.org diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c index 92c41ab..2cb474a 100644 --- a/drivers/irqchip/irq-metag-ext.c +++ b/drivers/irqchip/irq-metag-ext.c @@ -515,7 +515,7 @@ static int meta_intc_set_affinity(struct irq_data *data, * one cpu (the interrupt code doesn't support it), so we just * pick the first cpu we find in 'cpumask'. */ - cpu = cpumask_any(cpumask); + cpu = cpumask_any_and(cpumask, cpu_online_mask); thread = cpu_2_hwthread_id[cpu]; metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); diff --git a/drivers/irqchip/irq-metag.c b/drivers/irqchip/irq-metag.c index 8e94d7a..c16c186 100644 --- a/drivers/irqchip/irq-metag.c +++ b/drivers/irqchip/irq-metag.c @@ -201,7 +201,7 @@ static int metag_internal_irq_set_affinity(struct irq_data *data, * one cpu (the interrupt code doesn't support it), so we just * pick the first cpu we find in 'cpumask'. */ - cpu = cpumask_any(cpumask); + cpu = cpumask_any_and(cpumask, cpu_online_mask); thread = cpu_2_hwthread_id[cpu]; metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)), -- cgit v0.10.2 From 33b6c7765f0c20da9d61246a095acad0f98a1da5 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 25 Feb 2014 15:01:39 -0800 Subject: mm, hwpoison: release page on PageHWPoison() in __do_fault() It seems we forget to release page after detecting HW error. Signed-off-by: Kirill A. Shutemov Cc: Mel Gorman Cc: Rik van Riel Cc: Andi Kleen Cc: Matthew Wilcox Cc: Dave Hansen Cc: Naoya Horiguchi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/memory.c b/mm/memory.c index be6a0c0..5f2001a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3348,6 +3348,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (ret & VM_FAULT_LOCKED) unlock_page(vmf.page); ret = VM_FAULT_HWPOISON; + page_cache_release(vmf.page); goto uncharge_out; } -- cgit v0.10.2 From ff3a2b73b7d6d79038512d60690de18cd7aa4e21 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 25 Feb 2014 15:01:40 -0800 Subject: drivers/iommu/omap-iommu-debug.c: fix decimal permissions These should have been octal. Signed-off-by: Joe Perches Cc: Joerg Roedel Cc: Hiroshi DOYU Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index d97fbe4..80fffba 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -354,8 +354,8 @@ DEBUG_FOPS(mem); return -ENOMEM; \ } -#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600) -#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400) +#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 0600) +#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 0400) static int iommu_debug_register(struct device *dev, void *data) { -- cgit v0.10.2 From 01412886b735ef241f9a41adf9f707ce1522eb61 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 25 Feb 2014 15:01:41 -0800 Subject: drivers/fmc/fmc-write-eeprom.c: fix decimal permissions This 444 should have been octal. Signed-off-by: Joe Perches Cc: Alessandro Rubini Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/fmc/fmc-write-eeprom.c b/drivers/fmc/fmc-write-eeprom.c index ee5b479..9bb2cbd 100644 --- a/drivers/fmc/fmc-write-eeprom.c +++ b/drivers/fmc/fmc-write-eeprom.c @@ -27,7 +27,7 @@ FMC_PARAM_BUSID(fwe_drv); /* The "file=" is like the generic "gateware=" used elsewhere */ static char *fwe_file[FMC_MAX_CARDS]; static int fwe_file_n; -module_param_array_named(file, fwe_file, charp, &fwe_file_n, 444); +module_param_array_named(file, fwe_file, charp, &fwe_file_n, 0444); static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw, int write) -- cgit v0.10.2 From 9845cbbd113fbb5b769a45d8e88dc47bc12df4e0 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 25 Feb 2014 15:01:42 -0800 Subject: mm, thp: fix infinite loop on memcg OOM Masayoshi Mizuma reported a bug with the hang of an application under the memcg limit. It happens on write-protection fault to huge zero page If we successfully allocate a huge page to replace zero page but hit the memcg limit we need to split the zero page with split_huge_page_pmd() and fallback to small pages. The other part of the problem is that VM_FAULT_OOM has special meaning in do_huge_pmd_wp_page() context. __handle_mm_fault() expects the page to be split if it sees VM_FAULT_OOM and it will will retry page fault handling. This causes an infinite loop if the page was not split. do_huge_pmd_wp_zero_page_fallback() can return VM_FAULT_OOM if it failed to allocate one small page, so fallback to small pages will not help. The solution for this part is to replace VM_FAULT_OOM with VM_FAULT_FALLBACK is fallback required. Signed-off-by: Kirill A. Shutemov Reported-by: Masayoshi Mizuma Reviewed-by: Michal Hocko Cc: Johannes Weiner Cc: Andrea Arcangeli Cc: David Rientjes Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/huge_memory.c b/mm/huge_memory.c index da23eb9..4df39b1 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1166,8 +1166,10 @@ alloc: } else { ret = do_huge_pmd_wp_page_fallback(mm, vma, address, pmd, orig_pmd, page, haddr); - if (ret & VM_FAULT_OOM) + if (ret & VM_FAULT_OOM) { split_huge_page(page); + ret |= VM_FAULT_FALLBACK; + } put_page(page); } count_vm_event(THP_FAULT_FALLBACK); @@ -1179,9 +1181,10 @@ alloc: if (page) { split_huge_page(page); put_page(page); - } + } else + split_huge_page_pmd(vma, address, pmd); + ret |= VM_FAULT_FALLBACK; count_vm_event(THP_FAULT_FALLBACK); - ret |= VM_FAULT_OOM; goto out; } diff --git a/mm/memory.c b/mm/memory.c index 5f2001a..22dfa61 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3704,7 +3704,6 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(is_vm_hugetlb_page(vma))) return hugetlb_fault(mm, vma, address, flags); -retry: pgd = pgd_offset(mm, address); pud = pud_alloc(mm, pgd, address); if (!pud) @@ -3742,20 +3741,13 @@ retry: if (dirty && !pmd_write(orig_pmd)) { ret = do_huge_pmd_wp_page(mm, vma, address, pmd, orig_pmd); - /* - * If COW results in an oom, the huge pmd will - * have been split, so retry the fault on the - * pte for a smaller charge. - */ - if (unlikely(ret & VM_FAULT_OOM)) - goto retry; - return ret; + if (!(ret & VM_FAULT_FALLBACK)) + return ret; } else { huge_pmd_set_accessed(mm, vma, address, pmd, orig_pmd, dirty); + return 0; } - - return 0; } } -- cgit v0.10.2 From 08088cb9ac0a9c28d4cf3efa4f6848a9b053ccfd Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Tue, 25 Feb 2014 15:01:44 -0800 Subject: memcg: change oom_info_lock to mutex Kirill has reported the following: Task in /test killed as a result of limit of /test memory: usage 10240kB, limit 10240kB, failcnt 51 memory+swap: usage 10240kB, limit 10240kB, failcnt 0 kmem: usage 0kB, limit 18014398509481983kB, failcnt 0 Memory cgroup stats for /test: BUG: sleeping function called from invalid context at kernel/cpu.c:68 in_atomic(): 1, irqs_disabled(): 0, pid: 66, name: memcg_test 2 locks held by memcg_test/66: #0: (memcg_oom_lock#2){+.+...}, at: [] pagefault_out_of_memory+0x14/0x90 #1: (oom_info_lock){+.+...}, at: [] mem_cgroup_print_oom_info+0x2a/0x390 CPU: 2 PID: 66 Comm: memcg_test Not tainted 3.14.0-rc1-dirty #745 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS Bochs 01/01/2011 Call Trace: __might_sleep+0x16a/0x210 get_online_cpus+0x1c/0x60 mem_cgroup_read_stat+0x27/0xb0 mem_cgroup_print_oom_info+0x260/0x390 dump_header+0x88/0x251 ? trace_hardirqs_on+0xd/0x10 oom_kill_process+0x258/0x3d0 mem_cgroup_oom_synchronize+0x656/0x6c0 ? mem_cgroup_charge_common+0xd0/0xd0 pagefault_out_of_memory+0x14/0x90 mm_fault_error+0x91/0x189 __do_page_fault+0x48e/0x580 do_page_fault+0xe/0x10 page_fault+0x22/0x30 which complains that mem_cgroup_read_stat cannot be called from an atomic context but mem_cgroup_print_oom_info takes a spinlock. Change oom_info_lock to a mutex. This was introduced by 947b3dd1a84b ("memcg, oom: lock mem_cgroup_print_oom_info"). Signed-off-by: Michal Hocko Reported-by: "Kirill A. Shutemov" Cc: Johannes Weiner Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 53385cd..ce7a8cc 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1687,7 +1687,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p) * protects memcg_name and makes sure that parallel ooms do not * interleave */ - static DEFINE_SPINLOCK(oom_info_lock); + static DEFINE_MUTEX(oom_info_lock); struct cgroup *task_cgrp; struct cgroup *mem_cgrp; static char memcg_name[PATH_MAX]; @@ -1698,7 +1698,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p) if (!p) return; - spin_lock(&oom_info_lock); + mutex_lock(&oom_info_lock); rcu_read_lock(); mem_cgrp = memcg->css.cgroup; @@ -1767,7 +1767,7 @@ done: pr_cont("\n"); } - spin_unlock(&oom_info_lock); + mutex_unlock(&oom_info_lock); } /* -- cgit v0.10.2 From f3713fd9cff733d9df83116422d8e4af6e86b2bb Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Tue, 25 Feb 2014 15:01:45 -0800 Subject: ipc,mqueue: remove limits for the amount of system-wide queues Commit 93e6f119c0ce ("ipc/mqueue: cleanup definition names and locations") added global hardcoded limits to the amount of message queues that can be created. While these limits are per-namespace, reality is that it ends up breaking userspace applications. Historically users have, at least in theory, been able to create up to INT_MAX queues, and limiting it to just 1024 is way too low and dramatic for some workloads and use cases. For instance, Madars reports: "This update imposes bad limits on our multi-process application. As our app uses approaches that each process opens its own set of queues (usually something about 3-5 queues per process). In some scenarios we might run up to 3000 processes or more (which of-course for linux is not a problem). Thus we might need up to 9000 queues or more. All processes run under one user." Other affected users can be found in launchpad bug #1155695: https://bugs.launchpad.net/ubuntu/+source/manpages/+bug/1155695 Instead of increasing this limit, revert it entirely and fallback to the original way of dealing queue limits -- where once a user's resource limit is reached, and all memory is used, new queues cannot be created. Signed-off-by: Davidlohr Bueso Reported-by: Madars Vitolins Acked-by: Doug Ledford Cc: Manfred Spraul Cc: [3.5+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index e7831d2..35e7eca 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -118,9 +118,7 @@ extern int mq_init_ns(struct ipc_namespace *ns); * the new maximum will handle anyone else. I may have to revisit this * in the future. */ -#define MIN_QUEUESMAX 1 #define DFLT_QUEUESMAX 256 -#define HARD_QUEUESMAX 1024 #define MIN_MSGMAX 1 #define DFLT_MSG 10U #define DFLT_MSGMAX 10 diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c index 383d638..5bb8bfe 100644 --- a/ipc/mq_sysctl.c +++ b/ipc/mq_sysctl.c @@ -22,6 +22,16 @@ static void *get_mq(ctl_table *table) return which; } +static int proc_mq_dointvec(ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct ctl_table mq_table; + memcpy(&mq_table, table, sizeof(mq_table)); + mq_table.data = get_mq(table); + + return proc_dointvec(&mq_table, write, buffer, lenp, ppos); +} + static int proc_mq_dointvec_minmax(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -33,12 +43,10 @@ static int proc_mq_dointvec_minmax(ctl_table *table, int write, lenp, ppos); } #else +#define proc_mq_dointvec NULL #define proc_mq_dointvec_minmax NULL #endif -static int msg_queues_limit_min = MIN_QUEUESMAX; -static int msg_queues_limit_max = HARD_QUEUESMAX; - static int msg_max_limit_min = MIN_MSGMAX; static int msg_max_limit_max = HARD_MSGMAX; @@ -51,9 +59,7 @@ static ctl_table mq_sysctls[] = { .data = &init_ipc_ns.mq_queues_max, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_mq_dointvec_minmax, - .extra1 = &msg_queues_limit_min, - .extra2 = &msg_queues_limit_max, + .proc_handler = proc_mq_dointvec, }, { .procname = "msg_max", diff --git a/ipc/mqueue.c b/ipc/mqueue.c index ccf1f9f..c3b3117 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -433,9 +433,9 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry, error = -EACCES; goto out_unlock; } - if (ipc_ns->mq_queues_count >= HARD_QUEUESMAX || - (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max && - !capable(CAP_SYS_RESOURCE))) { + + if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max && + !capable(CAP_SYS_RESOURCE)) { error = -ENOSPC; goto out_unlock; } -- cgit v0.10.2 From 27b2a49a1493f5199a4c2f84abc6aebf81184e2b Mon Sep 17 00:00:00 2001 From: Fathi Boudra Date: Tue, 25 Feb 2014 15:01:46 -0800 Subject: Makefile: fix extra parenthesis typo when CC_STACKPROTECTOR_REGULAR is enabled An extra parenthesis typo introduced in 19952a92037e ("stackprotector: Unify the HAVE_CC_STACKPROTECTOR logic between architectures") is causing the following error when CONFIG_CC_STACKPROTECTOR_REGULAR is enabled: Makefile:608: Cannot use CONFIG_CC_STACKPROTECTOR: -fstack-protector not supported by compiler Makefile:608: *** missing separator. Stop. Signed-off-by: Fathi Boudra Acked-by: Kees Cook Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Makefile b/Makefile index 831b36a..15e90be 100644 --- a/Makefile +++ b/Makefile @@ -606,7 +606,7 @@ ifdef CONFIG_CC_STACKPROTECTOR_REGULAR stackp-flag := -fstack-protector ifeq ($(call cc-option, $(stackp-flag)),) $(warning Cannot use CONFIG_CC_STACKPROTECTOR: \ - -fstack-protector not supported by compiler)) + -fstack-protector not supported by compiler) endif else ifdef CONFIG_CC_STACKPROTECTOR_STRONG stackp-flag := -fstack-protector-strong -- cgit v0.10.2 From cf015e9f279f100e3c2a826217a4ab5dba3eb5ed Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 25 Feb 2014 15:01:47 -0800 Subject: MAINTAINERS: update L: misuses L: lines are for the email addresses of traditional mailing lists. W: lines are for URLs. Convert two L: misuses to W: links. Signed-off-by: Joe Perches Reported-by: Paul Bolle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 85b3dd8..eab0088 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2611,9 +2611,9 @@ DC395x SCSI driver M: Oliver Neukum M: Ali Akcaagac M: Jamie Lenehan -W: http://twibble.org/dist/dc395x/ L: dc395x@twibble.org -L: http://lists.twibble.org/mailman/listinfo/dc395x/ +W: http://twibble.org/dist/dc395x/ +W: http://lists.twibble.org/mailman/listinfo/dc395x/ S: Maintained F: Documentation/scsi/dc395x.txt F: drivers/scsi/dc395x.* @@ -8443,8 +8443,8 @@ TARGET SUBSYSTEM M: Nicholas A. Bellinger L: linux-scsi@vger.kernel.org L: target-devel@vger.kernel.org -L: http://groups.google.com/group/linux-iscsi-target-dev W: http://www.linux-iscsi.org +W: http://groups.google.com/group/linux-iscsi-target-dev T: git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master S: Supported F: drivers/target/ -- cgit v0.10.2 From 6c15b327ccbdce45878d4689f4d938f29dd309db Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 25 Feb 2014 15:01:48 -0800 Subject: Makefile: fix build with make 3.80 again According to Documentation/Changes, make 3.80 is still being supported for building the kernel, hence make files must not make (unconditional) use of features introduced only in newer versions. Commit 8779657d29c0 ("stackprotector: Introduce CONFIG_CC_STACKPROTECTOR_STRONG") however introduced an "else ifdef" construct which make 3.80 doesn't understand. Also correct a warning message still referencing the old config option name. Apart from that I question the use of "ifdef" here (but it was used that way already prior to said commit): ifeq (,y) would seem more to the point. Signed-off-by: Jan Beulich Acked-by: Kees Cook Cc: Ingo Molnar Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Makefile b/Makefile index 15e90be..81f1bf3 100644 --- a/Makefile +++ b/Makefile @@ -605,10 +605,11 @@ endif ifdef CONFIG_CC_STACKPROTECTOR_REGULAR stackp-flag := -fstack-protector ifeq ($(call cc-option, $(stackp-flag)),) - $(warning Cannot use CONFIG_CC_STACKPROTECTOR: \ + $(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \ -fstack-protector not supported by compiler) endif -else ifdef CONFIG_CC_STACKPROTECTOR_STRONG +else +ifdef CONFIG_CC_STACKPROTECTOR_STRONG stackp-flag := -fstack-protector-strong ifeq ($(call cc-option, $(stackp-flag)),) $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \ @@ -618,6 +619,7 @@ else # Force off for distro compilers that enable stack protector by default. stackp-flag := $(call cc-option, -fno-stack-protector) endif +endif KBUILD_CFLAGS += $(stackp-flag) # This warning generated too much noise in a regular build. -- cgit v0.10.2 From 61bd0943bc410c9f0daf0965535cb92ce76e1e8a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 25 Feb 2014 15:01:49 -0800 Subject: MAINTAINERS: change mailing list address for Altera UART drivers The nios2-dev list has been moved to the RocketBoards infrastructure, so adjust the address accordingly. Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index eab0088..df8869d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -538,7 +538,7 @@ F: arch/alpha/ ALTERA UART/JTAG UART SERIAL DRIVERS M: Tobias Klauser L: linux-serial@vger.kernel.org -L: nios2-dev@sopc.et.ntust.edu.tw (moderated for non-subscribers) +L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) S: Maintained F: drivers/tty/serial/altera_uart.c F: drivers/tty/serial/altera_jtaguart.c -- cgit v0.10.2 From 91a48a2e85a3b70ce10ead34b4ab5347f8d215c9 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 24 Feb 2014 00:48:05 +0100 Subject: ipv4: ipv6: better estimate tunnel header cut for correct ufo handling Currently the UFO fragmentation process does not correctly handle inner UDP frames. (The following tcpdumps are captured on the parent interface with ufo disabled while tunnel has ufo enabled, 2000 bytes payload, mtu 1280, both sit device): IPv6: 16:39:10.031613 IP (tos 0x0, ttl 64, id 3208, offset 0, flags [DF], proto IPv6 (41), length 1300) 192.168.122.151 > 1.1.1.1: IP6 (hlim 64, next-header Fragment (44) payload length: 1240) 2001::1 > 2001::8: frag (0x00000001:0|1232) 44883 > distinct: UDP, length 2000 16:39:10.031709 IP (tos 0x0, ttl 64, id 3209, offset 0, flags [DF], proto IPv6 (41), length 844) 192.168.122.151 > 1.1.1.1: IP6 (hlim 64, next-header Fragment (44) payload length: 784) 2001::1 > 2001::8: frag (0x00000001:0|776) 58979 > 46366: UDP, length 5471 We can see that fragmentation header offset is not correctly updated. (fragmentation id handling is corrected by 916e4cf46d0204 ("ipv6: reuse ip6_frag_id from ip6_ufo_append_data")). IPv4: 16:39:57.737761 IP (tos 0x0, ttl 64, id 3209, offset 0, flags [DF], proto IPIP (4), length 1296) 192.168.122.151 > 1.1.1.1: IP (tos 0x0, ttl 64, id 57034, offset 0, flags [none], proto UDP (17), length 1276) 192.168.99.1.35961 > 192.168.99.2.distinct: UDP, length 2000 16:39:57.738028 IP (tos 0x0, ttl 64, id 3210, offset 0, flags [DF], proto IPIP (4), length 792) 192.168.122.151 > 1.1.1.1: IP (tos 0x0, ttl 64, id 57035, offset 0, flags [none], proto UDP (17), length 772) 192.168.99.1.13531 > 192.168.99.2.20653: UDP, length 51109 In this case fragmentation id is incremented and offset is not updated. First, I aligned inet_gso_segment and ipv6_gso_segment: * align naming of flags * ipv6_gso_segment: setting skb->encapsulation is unnecessary, as we always ensure that the state of this flag is left untouched when returning from upper gso segmenation function * ipv6_gso_segment: move skb_reset_inner_headers below updating the fragmentation header data, we don't care for updating fragmentation header data * remove currently unneeded comment indicating skb->encapsulation might get changed by upper gso_segment callback (gre and udp-tunnel reset encapsulation after segmentation on each fragment) If we encounter an IPIP or SIT gso skb we now check for the protocol == IPPROTO_UDP and that we at least have already traversed another ip(6) protocol header. The reason why we have to special case GSO_IPIP and GSO_SIT is that we reset skb->encapsulation to 0 while skb_mac_gso_segment the inner protocol of GSO_UDP_TUNNEL or GSO_GRE packets. Reported-by: Wolfgang Walter Cc: Cong Wang Cc: Tom Herbert Cc: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index ecd2c3f..19ab78a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1296,8 +1296,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, segs = ERR_PTR(-EPROTONOSUPPORT); - /* Note : following gso_segment() might change skb->encapsulation */ - udpfrag = !skb->encapsulation && proto == IPPROTO_UDP; + if (skb->encapsulation && + skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) + udpfrag = proto == IPPROTO_UDP && encap; + else + udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; ops = rcu_dereference(inet_offloads[proto]); if (likely(ops && ops->callbacks.gso_segment)) diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 1e8683b..59f95af 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -89,7 +89,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, unsigned int unfrag_ip6hlen; u8 *prevhdr; int offset = 0; - bool tunnel; + bool encap, udpfrag; int nhoff; if (unlikely(skb_shinfo(skb)->gso_type & @@ -110,8 +110,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) goto out; - tunnel = SKB_GSO_CB(skb)->encap_level > 0; - if (tunnel) + encap = SKB_GSO_CB(skb)->encap_level > 0; + if (encap) features = skb->dev->hw_enc_features & netif_skb_features(skb); SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); @@ -121,6 +121,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); + if (skb->encapsulation && + skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) + udpfrag = proto == IPPROTO_UDP && encap; + else + udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; + ops = rcu_dereference(inet6_offloads[proto]); if (likely(ops && ops->callbacks.gso_segment)) { skb_reset_transport_header(skb); @@ -133,13 +139,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, for (skb = segs; skb; skb = skb->next) { ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); - if (tunnel) { - skb_reset_inner_headers(skb); - skb->encapsulation = 1; - } skb->network_header = (u8 *)ipv6h - skb->head; - if (!tunnel && proto == IPPROTO_UDP) { + if (udpfrag) { unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); fptr->frag_off = htons(offset); @@ -148,6 +150,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, offset += (ntohs(ipv6h->payload_len) - sizeof(struct frag_hdr)); } + if (encap) + skb_reset_inner_headers(skb); } out: -- cgit v0.10.2 From 22ae27906da3e6f15bf2a55aba3216f717e21671 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Mon, 24 Feb 2014 13:12:06 +0100 Subject: qeth: postpone freeing of qdio memory To guarantee that a qdio ccw_device no longer touches the qdio memory shared with Linux, the qdio ccw_device should be offline when freeing the qdio memory. Thus this patch postpones freeing of qdio memory. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Reviewed-by: Sebastian Ott Signed-off-by: David S. Miller diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index c3a83df..795ed61 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1660,7 +1660,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) QDIO_FLAG_CLEANUP_USING_CLEAR); if (rc) QETH_CARD_TEXT_(card, 3, "1err%d", rc); - qdio_free(CARD_DDEV(card)); atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); break; case QETH_QDIO_CLEANING: @@ -2605,6 +2604,7 @@ static int qeth_mpc_initialize(struct qeth_card *card) return 0; out_qdio: qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD); + qdio_free(CARD_DDEV(card)); return rc; } @@ -4906,9 +4906,11 @@ retry: if (retries < 3) QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", dev_name(&card->gdev->dev)); + rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD); ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); + qdio_free(CARD_DDEV(card)); rc = ccw_device_set_online(CARD_RDEV(card)); if (rc) goto retriable; @@ -4918,7 +4920,6 @@ retry: rc = ccw_device_set_online(CARD_DDEV(card)); if (rc) goto retriable; - rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD); retriable: if (rc == -ERESTARTSYS) { QETH_DBF_TEXT(SETUP, 2, "break1"); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 0710550..908d825 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1091,6 +1091,7 @@ out_remove: ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); + qdio_free(CARD_DDEV(card)); if (recover_flag == CARD_STATE_RECOVER) card->state = CARD_STATE_RECOVER; else @@ -1132,6 +1133,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, rc = (rc2) ? rc2 : rc3; if (rc) QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); + qdio_free(CARD_DDEV(card)); if (recover_flag == CARD_STATE_UP) card->state = CARD_STATE_RECOVER; /* let user_space know that device is offline */ @@ -1194,6 +1196,7 @@ static void qeth_l2_shutdown(struct ccwgroup_device *gdev) qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); qeth_qdio_clear_card(card, 0); qeth_clear_qdio_buffers(card); + qdio_free(CARD_DDEV(card)); } static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 0f43042..3524d34 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3447,6 +3447,7 @@ out_remove: ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); + qdio_free(CARD_DDEV(card)); if (recover_flag == CARD_STATE_RECOVER) card->state = CARD_STATE_RECOVER; else @@ -3493,6 +3494,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, rc = (rc2) ? rc2 : rc3; if (rc) QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); + qdio_free(CARD_DDEV(card)); if (recover_flag == CARD_STATE_UP) card->state = CARD_STATE_RECOVER; /* let user_space know that device is offline */ @@ -3545,6 +3547,7 @@ static void qeth_l3_shutdown(struct ccwgroup_device *gdev) qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); qeth_qdio_clear_card(card, 0); qeth_clear_qdio_buffers(card); + qdio_free(CARD_DDEV(card)); } static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) -- cgit v0.10.2 From fc49beaee2a410402f49fd21c81a37a863b7a9ba Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Mon, 24 Feb 2014 08:54:46 -0500 Subject: qlcnic: Fix function return error check Driver was treating -ve return value as success in case of qlcnic_enable_msi_legacy() failure Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index ba78c74..149c4b6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -818,7 +818,7 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter) qlcnic_disable_multi_tx(adapter); err = qlcnic_enable_msi_legacy(adapter); - if (!err) + if (err) return err; } } -- cgit v0.10.2 From b7520d2b59b09eb284e5fc9080d13145f0a8d9fd Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Mon, 24 Feb 2014 08:54:47 -0500 Subject: qlcnic: Fix usage of use_msi and use_msi_x module parameters Once interrupts are enabled, instead of using module parameters, use flags (QLCNIC_MSI_ENABLED and QLCNIC_MSIX_ENABLED) set by driver to check interrupt mode. Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 149c4b6..e10fc8e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -3863,7 +3863,7 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt, strcpy(buf, "Tx"); } - if (!qlcnic_use_msi_x && !qlcnic_use_msi) { + if (!QLCNIC_IS_MSI_FAMILY(adapter)) { netdev_err(netdev, "No RSS/TSS support in INT-x mode\n"); return -EINVAL; } -- cgit v0.10.2 From 46428228b55df144f04cbad023907c177aa00d5f Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Mon, 24 Feb 2014 08:54:48 -0500 Subject: qlcnic: Allow any VLAN to be configured from VF. o This patch reverts commit 1414abea048e0835c43600d62808ed8163897227 (qlcnic: Restrict VF from configuring any VLAN mode.) This will allow same multicast address to be used with any VLAN instead of programming seperate (MAC, VLAN) tuples in adapter. This will help save some multicast filters. Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 09acf15..e5277a6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -13,8 +13,6 @@ #define QLC_VF_MIN_TX_RATE 100 #define QLC_VF_MAX_TX_RATE 9999 #define QLC_MAC_OPCODE_MASK 0x7 -#define QLC_MAC_STAR_ADD 6 -#define QLC_MAC_STAR_DEL 7 #define QLC_VF_FLOOD_BIT BIT_16 #define QLC_FLOOD_MODE 0x5 @@ -1206,13 +1204,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter, struct qlcnic_vport *vp = vf->vp; u8 op, new_op; - if (((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_ADD) || - ((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_DEL)) { - netdev_err(adapter->netdev, "MAC + any VLAN filter not allowed from VF %d\n", - vf->pci_func); - return -EINVAL; - } - if (!(cmd->req.arg[1] & BIT_8)) return -EINVAL; -- cgit v0.10.2 From 42beb3f2836a6063ceb8134dbac0e32df1deea26 Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Mon, 24 Feb 2014 08:54:49 -0500 Subject: qlcnic: Fix number of rings when we fall back from msix to legacy. o Driver was not re-setting sds ring count to 1 after failing to allocate msi-x interrupts. Signed-off-by: Rajesh Borundia Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 4146664..27c4f13 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -340,6 +340,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter) if (qlcnic_sriov_vf_check(adapter)) return -EINVAL; num_msix = 1; + adapter->drv_sds_rings = QLCNIC_SINGLE_RING; adapter->drv_tx_rings = QLCNIC_SINGLE_RING; } } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index e10fc8e..1222865 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -816,6 +816,7 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter) if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { qlcnic_disable_multi_tx(adapter); + adapter->drv_sds_rings = QLCNIC_SINGLE_RING; err = qlcnic_enable_msi_legacy(adapter); if (err) -- cgit v0.10.2 From 687d705c031916b83953b714917b04d899e23cf5 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 24 Feb 2014 17:04:52 -0300 Subject: net/cxgb4: use remove handler as shutdown handler Without a shutdown handler, T4 cards behave very badly after a kexec. Some firmware calls return errors indicating allocation failures, for example. This is probably because thouse resources were not released by a BYE message to the firmware, for example. Using the remove handler guarantees we will use a well tested path. With this patch I applied, I managed to use kexec multiple times and probe and iSCSI login worked every time. Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 43ab35f..34e2488 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -6179,6 +6179,7 @@ static struct pci_driver cxgb4_driver = { .id_table = cxgb4_pci_tbl, .probe = init_one, .remove = remove_one, + .shutdown = remove_one, .err_handler = &cxgb4_eeh, }; -- cgit v0.10.2 From 46833a86f7ab30101096d81117dd250bfae74c6f Mon Sep 17 00:00:00 2001 From: Mike Pecovnik Date: Mon, 24 Feb 2014 21:11:16 +0100 Subject: net: Fix permission check in netlink_connect() netlink_sendmsg() was changed to prevent non-root processes from sending messages with dst_pid != 0. netlink_connect() however still only checks if nladdr->nl_groups is set. This patch modifies netlink_connect() to check for the same condition. Signed-off-by: Mike Pecovnik Signed-off-by: David S. Miller diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index fdf5135..04748ab6 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1489,8 +1489,8 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, if (addr->sa_family != AF_NETLINK) return -EINVAL; - /* Only superuser is allowed to send multicasts */ - if (nladdr->nl_groups && !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) + if ((nladdr->nl_groups || nladdr->nl_pid) && + !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) return -EPERM; if (!nlk->portid) -- cgit v0.10.2 From a4572e0c23266d01949a1c134475e3bfa7f788e1 Mon Sep 17 00:00:00 2001 From: Cristian Bercaru Date: Tue, 25 Feb 2014 10:22:48 +0200 Subject: phy: unmask link partner capabilities Masking the link partner's capabilities with local capabilities can be misleading in autonegotiation scenarios such as PAUSE frame autonegotiation. This patch calculates the join between the local capabilities and the link parner capabilities, when it determines the speed and duplex settings, but does not mask any of the link partner capabilities when it calculates PAUSE frame settings. Signed-off-by: Cristian Bercaru Signed-off-by: David S. Miller diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 82514e7..4b970f7 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -916,6 +916,8 @@ int genphy_read_status(struct phy_device *phydev) int err; int lpa; int lpagb = 0; + int common_adv; + int common_adv_gb = 0; /* Update the link, but return if there was an error */ err = genphy_update_link(phydev); @@ -937,7 +939,7 @@ int genphy_read_status(struct phy_device *phydev) phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb); - lpagb &= adv << 2; + common_adv_gb = lpagb & adv << 2; } lpa = phy_read(phydev, MII_LPA); @@ -950,25 +952,25 @@ int genphy_read_status(struct phy_device *phydev) if (adv < 0) return adv; - lpa &= adv; + common_adv = lpa & adv; phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = 0; phydev->asym_pause = 0; - if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { + if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) { phydev->speed = SPEED_1000; - if (lpagb & LPA_1000FULL) + if (common_adv_gb & LPA_1000FULL) phydev->duplex = DUPLEX_FULL; - } else if (lpa & (LPA_100FULL | LPA_100HALF)) { + } else if (common_adv & (LPA_100FULL | LPA_100HALF)) { phydev->speed = SPEED_100; - if (lpa & LPA_100FULL) + if (common_adv & LPA_100FULL) phydev->duplex = DUPLEX_FULL; } else - if (lpa & LPA_10FULL) + if (common_adv & LPA_10FULL) phydev->duplex = DUPLEX_FULL; if (phydev->duplex == DUPLEX_FULL) { -- cgit v0.10.2 From 13cde090030c7d00e991c85b87c12891cc8e4df4 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 25 Feb 2014 17:54:51 +0800 Subject: ASoC: fsl-sai: fix Freescale SAI DAI format setting. o Fix some bugs of fsl_sai_set_dai_fmt_tr(). o Add SND_SOC_DAIFMT_LEFT_J support. o Add SND_SOC_DAIFMT_CBS_CFM support. o Add SND_SOC_DAIFMT_CBM_CFS support. o And SND_SOC_DAIFMT_RIGHT_J need to be done in the future. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index faa65af..26d9f5e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -105,35 +105,47 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, else val_cr4 |= FSL_SAI_CR4_MF; + /* DAI mode */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - val_cr4 |= FSL_SAI_CR4_FSE; + /* Data on rising edge of bclk, frame low, 1clk before data */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP; + break; + case SND_SOC_DAIFMT_LEFT_J: + /* Data on rising edge of bclk, frame high, 0clk before data */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); break; + case SND_SOC_DAIFMT_RIGHT_J: + /* To be done */ default: return -EINVAL; } + /* DAI clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_IF: - val_cr4 |= FSL_SAI_CR4_FSP; - val_cr2 &= ~FSL_SAI_CR2_BCP; + /* Invert both clocks */ + val_cr2 ^= FSL_SAI_CR2_BCP; + val_cr4 ^= FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_IB_NF: - val_cr4 &= ~FSL_SAI_CR4_FSP; - val_cr2 &= ~FSL_SAI_CR2_BCP; + /* Invert bit clock */ + val_cr2 ^= FSL_SAI_CR2_BCP; break; case SND_SOC_DAIFMT_NB_IF: - val_cr4 |= FSL_SAI_CR4_FSP; - val_cr2 |= FSL_SAI_CR2_BCP; + /* Invert frame clock */ + val_cr4 ^= FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_NB_NF: - val_cr4 &= ~FSL_SAI_CR4_FSP; - val_cr2 |= FSL_SAI_CR2_BCP; + /* Nothing to do for both normal cases */ break; default: return -EINVAL; } + /* DAI clock master masks */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: val_cr2 |= FSL_SAI_CR2_BCD_MSTR; @@ -143,6 +155,14 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; break; + case SND_SOC_DAIFMT_CBS_CFM: + val_cr2 |= FSL_SAI_CR2_BCD_MSTR; + val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; + break; + case SND_SOC_DAIFMT_CBM_CFS: + val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; + val_cr4 |= FSL_SAI_CR4_FSD_MSTR; + break; default: return -EINVAL; } -- cgit v0.10.2 From e66c176837462928a05a135bbe16cdce70536d6e Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Tue, 25 Feb 2014 10:35:37 -0800 Subject: intel_pstate: Change busy calculation to use fixed point math. Commit fcb6a15c2e (intel_pstate: Take core C0 time into account for core busy calculation) introduced a regression on some processor SKUs supported by intel_pstate. This was due to the truncation caused by using integer math to calculate core busy and C0 percentages. On a i7-4770K processor operating at 800Mhz going to 100% utilization the percent busy of the CPU using integer math is 22%, but it actually is 22.85%. This value scaled to the current frequency returned 97 which the PID interpreted as no error and did not adjust the P state. Tested on i7-4770K, i7-2600, i5-3230M. Fixes: fcb6a15c2e7e (intel_pstate: Take core C0 time into account for core busy calculation) References: https://lkml.org/lkml/2014/2/19/626 References: https://bugzilla.kernel.org/show_bug.cgi?id=70941 Signed-off-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index e908161..2cd36b9 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -39,9 +39,10 @@ #define BYT_TURBO_RATIOS 0x66c -#define FRAC_BITS 8 +#define FRAC_BITS 6 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) #define fp_toint(X) ((X) >> FRAC_BITS) +#define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS) static inline int32_t mul_fp(int32_t x, int32_t y) { @@ -556,18 +557,20 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) static inline void intel_pstate_calc_busy(struct cpudata *cpu, struct sample *sample) { - u64 core_pct; - u64 c0_pct; + int32_t core_pct; + int32_t c0_pct; - core_pct = div64_u64(sample->aperf * 100, sample->mperf); + core_pct = div_fp(int_tofp((sample->aperf)), + int_tofp((sample->mperf))); + core_pct = mul_fp(core_pct, int_tofp(100)); + FP_ROUNDUP(core_pct); + + c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc)); - c0_pct = div64_u64(sample->mperf * 100, sample->tsc); sample->freq = fp_toint( - mul_fp(int_tofp(cpu->pstate.max_pstate), - int_tofp(core_pct * 1000))); + mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); - sample->core_pct_busy = mul_fp(int_tofp(core_pct), - div_fp(int_tofp(c0_pct + 1), int_tofp(100))); + sample->core_pct_busy = mul_fp(core_pct, c0_pct); } static inline void intel_pstate_sample(struct cpudata *cpu) @@ -579,6 +582,10 @@ static inline void intel_pstate_sample(struct cpudata *cpu) rdmsrl(MSR_IA32_MPERF, mperf); tsc = native_read_tsc(); + aperf = aperf >> FRAC_BITS; + mperf = mperf >> FRAC_BITS; + tsc = tsc >> FRAC_BITS; + cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; cpu->samples[cpu->sample_ptr].aperf = aperf; cpu->samples[cpu->sample_ptr].mperf = mperf; @@ -610,7 +617,8 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; max_pstate = int_tofp(cpu->pstate.max_pstate); current_pstate = int_tofp(cpu->pstate.current_pstate); - return mul_fp(core_busy, div_fp(max_pstate, current_pstate)); + core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); + return FP_ROUNDUP(core_busy); } static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) -- cgit v0.10.2 From 17cb37aafdc11b875b915292ae21ac3a4f1425a7 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 25 Feb 2014 22:01:54 +0400 Subject: ASoC: cirrus: Remove excess dependencies on SND_SOC Configuration for Cirrus Logic audio support is included only if SND_SOC symbol selected, so no reason to check it once more. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938d..c872dac 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -1,6 +1,6 @@ config SND_EP93XX_SOC tristate "SoC Audio support for the Cirrus Logic EP93xx series" - depends on (ARCH_EP93XX || COMPILE_TEST) && SND_SOC + depends on ARCH_EP93XX || COMPILE_TEST select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for codecs attached to -- cgit v0.10.2 From f8d5b9e9e5372f0deb7bc1ab1088a9b60b0a793d Mon Sep 17 00:00:00 2001 From: Sebastian Capella Date: Tue, 18 Feb 2014 17:52:08 -0800 Subject: PM / hibernate: Fix restore hang in freeze_processes() During restore, pm_notifier chain are called with PM_RESTORE_PREPARE. The firmware_class driver handler fw_pm_notify does not have a handler for this. As a result, it keeps a reader on the kmod.c umhelper_sem. During freeze_processes, the call to __usermodehelper_disable tries to take a write lock on this semaphore and hangs waiting. Signed-off-by: Sebastian Capella Acked-by: Ming Lei Cc: All applicable Signed-off-by: Rafael J. Wysocki diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8a97ddf..c30df50e 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1580,6 +1580,7 @@ static int fw_pm_notify(struct notifier_block *notify_block, switch (mode) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: + case PM_RESTORE_PREPARE: kill_requests_without_uevent(); device_cache_fw_images(); break; -- cgit v0.10.2 From b6085a865762236bb84934161273cdac6dd11c2d Mon Sep 17 00:00:00 2001 From: Eugene Surovegin Date: Thu, 23 Jan 2014 09:31:20 -0800 Subject: x86, kaslr: export offset in VMCOREINFO ELF notes Include kASLR offset in VMCOREINFO ELF notes to assist in debugging. [ hpa: pushing this for v3.14 to avoid having a kernel version with kASLR where we can't debug output. ] Signed-off-by: Eugene Surovegin Link: http://lkml.kernel.org/r/20140123173120.GA25474@www.outflux.net Signed-off-by: Kees Cook Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 4eabc16..679cef0 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -279,5 +279,7 @@ void arch_crash_save_vmcoreinfo(void) VMCOREINFO_SYMBOL(node_data); VMCOREINFO_LENGTH(node_data, MAX_NUMNODES); #endif + vmcoreinfo_append_str("KERNELOFFSET=%lx\n", + (unsigned long)&_text - __START_KERNEL); } -- cgit v0.10.2 From e290e8c59dbc2a15088d868170d799f763202fef Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sun, 9 Feb 2014 13:56:44 -0800 Subject: x86, kaslr: add missed "static" declarations This silences build warnings about unexported variables and functions. Signed-off-by: Kees Cook Link: http://lkml.kernel.org/r/20140209215644.GA30339@www.outflux.net Signed-off-by: H. Peter Anvin diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c index 90a21f4..4dbf967 100644 --- a/arch/x86/boot/compressed/aslr.c +++ b/arch/x86/boot/compressed/aslr.c @@ -111,7 +111,7 @@ struct mem_vector { }; #define MEM_AVOID_MAX 5 -struct mem_vector mem_avoid[MEM_AVOID_MAX]; +static struct mem_vector mem_avoid[MEM_AVOID_MAX]; static bool mem_contains(struct mem_vector *region, struct mem_vector *item) { @@ -180,7 +180,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, } /* Does this memory vector overlap a known avoided area? */ -bool mem_avoid_overlap(struct mem_vector *img) +static bool mem_avoid_overlap(struct mem_vector *img) { int i; @@ -192,8 +192,9 @@ bool mem_avoid_overlap(struct mem_vector *img) return false; } -unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / CONFIG_PHYSICAL_ALIGN]; -unsigned long slot_max = 0; +static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / + CONFIG_PHYSICAL_ALIGN]; +static unsigned long slot_max; static void slots_append(unsigned long addr) { -- cgit v0.10.2 From 3a9016f97fdc8bfbb26ff36ba8f3dc9162eb691b Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 19 Feb 2014 10:07:34 +0100 Subject: xfrm: Fix unlink race when policies are deleted. When a policy is unlinked from the lists in thread context, the xfrm timer can fire before we can mark this policy as dead. So reinitialize the bydst hlist, then hlist_unhashed() will notice that this policy is not linked and will avoid a doulble unlink of that policy. Reported-by: Xianpeng Zhao <673321875@qq.com> Signed-off-by: Steffen Klassert diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4b98b25..1d5c7bf 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1158,7 +1158,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, if (hlist_unhashed(&pol->bydst)) return NULL; - hlist_del(&pol->bydst); + hlist_del_init(&pol->bydst); hlist_del(&pol->byidx); list_del(&pol->walk.all); net->xfrm.policy_count[dir]--; -- cgit v0.10.2 From fce0a0c72618e021e29ed4e051ce6b42b218c5e6 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Wed, 26 Feb 2014 15:23:19 +0800 Subject: ALSA: hda/realtek - Add more entry for enable HP mute led I lost this SSID. Add it into the fixup table. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0b4ea6c..ec304f3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4359,6 +4359,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x228a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x228c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x228d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x22c6, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), -- cgit v0.10.2 From 75306820248e26d15d84acf4e297b9fb27dd3bb2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 24 Feb 2014 11:59:14 +0900 Subject: ASoC: da732x: Mark DC offset control registers volatile The driver reads from the DC offset control registers during callibration but since the registers are marked as volatile and there is a register cache the values will not be read from the hardware after the first reading rendering the callibration ineffective. It appears that the driver was originally written for the ASoC level register I/O code but converted to regmap prior to merge and this issue was missed during the conversion as the framework level volatile register functionality was not being used. Signed-off-by: Mark Brown Acked-by: Adam Thomson Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f295b65..f4d965ebc 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1268,11 +1268,23 @@ static struct snd_soc_dai_driver da732x_dai[] = { }, }; +static bool da732x_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case DA732X_REG_HPL_DAC_OFF_CNTL: + case DA732X_REG_HPR_DAC_OFF_CNTL: + return true; + default: + return false; + } +} + static const struct regmap_config da732x_regmap = { .reg_bits = 8, .val_bits = 8, .max_register = DA732X_MAX_REG, + .volatile_reg = da732x_volatile, .reg_defaults = da732x_reg_cache, .num_reg_defaults = ARRAY_SIZE(da732x_reg_cache), .cache_type = REGCACHE_RBTREE, -- cgit v0.10.2 From a1989b330093578ea5470bea0a00f940c444c466 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 26 Feb 2014 10:07:04 +0100 Subject: dm mpath: fix stalls when handling invalid ioctls An invalid ioctl will never be valid, irrespective of whether multipath has active paths or not. So for invalid ioctls we do not have to wait for multipath to activate any paths, but can rather return an error code immediately. This fix resolves numerous instances of: udevd[]: worker [] unexpectedly returned with status 0x0100 that have been seen during testing. Signed-off-by: Hannes Reinecke Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 6eb9dc9..422a9fd 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1626,8 +1626,11 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, /* * Only pass ioctls through if the device sizes match exactly. */ - if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) - r = scsi_verify_blk_ioctl(NULL, cmd); + if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) { + int err = scsi_verify_blk_ioctl(NULL, cmd); + if (err) + r = err; + } if (r == -ENOTCONN && !fatal_signal_pending(current)) queue_work(kmultipathd, &m->process_queued_ios); -- cgit v0.10.2 From 0b7d25c347900e2550398e29e25caf0fefe3cab2 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Thu, 23 Jan 2014 22:32:20 +0100 Subject: pwm: lp3943: Fix potential memory leak during request Fix a memory leak in the lp3943_pwm_request_map() error handling path. Make sure already allocated pwm map memory is freed correctly. Detected by Coverity: CID 1162829. Signed-off-by: Christian Engelmayer Acked-by: Milo Kim Signed-off-by: Thierry Reding diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c index 8a843a0..a40b9c3 100644 --- a/drivers/pwm/pwm-lp3943.c +++ b/drivers/pwm/pwm-lp3943.c @@ -52,8 +52,10 @@ lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm) offset = pwm_map->output[i]; /* Return an error if the pin is already assigned */ - if (test_and_set_bit(offset, &lp3943->pin_used)) + if (test_and_set_bit(offset, &lp3943->pin_used)) { + kfree(pwm_map); return ERR_PTR(-EBUSY); + } } return pwm_map; -- cgit v0.10.2 From 404381c5839d67aa0c275ad1da96ef3d3928ca2c Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 24 Feb 2014 13:59:32 -0300 Subject: KVM: MMU: drop read-only large sptes when creating lower level sptes Read-only large sptes can be created due to read-only faults as follows: - QEMU pagetable entry that maps guest memory is read-only due to COW. - Guest read faults such memory, COW is not broken, because it is a read-only fault. - Enable dirty logging, large spte not nuked because it is read-only. - Write-fault on such memory causes guest to loop endlessly (which must go down to level 1 because dirty logging is enabled). Fix by dropping large spte when necessary. Signed-off-by: Marcelo Tosatti Signed-off-by: Paolo Bonzini diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index e50425d..9b53135 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -2672,6 +2672,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, break; } + drop_large_spte(vcpu, iterator.sptep); if (!is_shadow_present_pte(*iterator.sptep)) { u64 base_addr = iterator.addr; -- cgit v0.10.2 From ec6deea1a147a10baf1672dc66025a13bc259680 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 21 Jan 2014 09:06:21 +0100 Subject: clk: nomadik: fix multiplatform problem The Nomadik debugfs screws up multiplatform boots if debugfs is enabled on the multiplatform image, since it's a simple initcall that is unconditionally executed and reads from certain memory locations. Fix this by checking that the driver has been properly initialized, so a base offset to the Nomadik SRC controller exists, before proceeding to register debugfs files. Reported-by: Andrew Lunn Signed-off-by: Linus Walleij Reviewed-by: Andrew Lunn Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c index 6a934a5..05e04ce 100644 --- a/drivers/clk/clk-nomadik.c +++ b/drivers/clk/clk-nomadik.c @@ -494,6 +494,9 @@ static const struct file_operations nomadik_src_clk_debugfs_ops = { static int __init nomadik_src_clk_init_debugfs(void) { + /* Vital for multiplatform */ + if (!src_base) + return -ENODEV; src_pcksr0_boot = readl(src_base + SRC_PCKSR0); src_pcksr1_boot = readl(src_base + SRC_PCKSR1); debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO, -- cgit v0.10.2 From 9a9bfd032f0207dd6e63c84b7676b58f160af04b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 25 Feb 2014 04:31:03 -0800 Subject: net: tcp: use NET_INC_STATS() While LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES can only be incremented in tcp_transmit_skb() from softirq (incoming message or timer activation), it is better to use NET_INC_STATS() instead of NET_INC_STATS_BH() as tcp_transmit_skb() can be called from process context. This will avoid copy/paste confusion when/if we want to add other SNMP counters in tcp_transmit_skb() Signed-off-by: Eric Dumazet Cc: Hannes Frederic Sowa Cc: Florian Westphal Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 0980581..d718482 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -864,8 +864,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, if (unlikely(skb->fclone == SKB_FCLONE_ORIG && fclone->fclone == SKB_FCLONE_CLONE)) - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); + NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); if (unlikely(skb_cloned(skb))) skb = pskb_copy(skb, gfp_mask); -- cgit v0.10.2 From 8f355e5cee63c2c0c145d8206c4245d0189f47ff Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Tue, 25 Feb 2014 13:17:59 +0000 Subject: sfc: check for NULL efx->ptp_data in efx_ptp_event If we receive a PTP event from the NIC when we haven't set up PTP state in the driver, we attempt to read through a NULL pointer efx->ptp_data, triggering a panic. Signed-off-by: Edward Cree Acked-by: Shradha Shah Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index eb75fbd..d7a3682 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1668,6 +1668,13 @@ void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) struct efx_ptp_data *ptp = efx->ptp_data; int code = EFX_QWORD_FIELD(*ev, MCDI_EVENT_CODE); + if (!ptp) { + if (net_ratelimit()) + netif_warn(efx, drv, efx->net_dev, + "Received PTP event but PTP not set up\n"); + return; + } + if (!ptp->enabled) return; -- cgit v0.10.2 From bc90d2918b343e114ddda91802f05a05dfed559e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 25 Feb 2014 13:35:53 -0800 Subject: MAINTAINERS: Intel nic drivers Add a new F: line for the intel subdirectories. This allows get_maintainers to avoid using git log and cc'ing people that have submitted clean-up style patches for all first level directories under drivers/net/ethernet/intel/ This does not make e100.c maintained. Signed-off-by: Joe Perches Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index 0dba50b..fec577d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4545,6 +4545,7 @@ F: Documentation/networking/ixgbevf.txt F: Documentation/networking/i40e.txt F: Documentation/networking/i40evf.txt F: drivers/net/ethernet/intel/ +F: drivers/net/ethernet/intel/*/ INTEL-MID GPIO DRIVER M: David Cohen -- cgit v0.10.2 From 5e5b066535f0ee58e5de3a2db5fb56fa3cd7e3b1 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Wed, 26 Feb 2014 11:05:22 +0800 Subject: bonding: Fix RTNL: assertion failed at net/core/rtnetlink.c for 802.3ad mode The problem was introduced by the commit 1d3ee88ae0d (bonding: add netlink attributes to slave link dev). The bond_set_active_slave() and bond_set_backup_slave() will use rtmsg_ifinfo to send slave's states, so these two functions should be called in RTNL. In 802.3ad mode, acquiring RTNL for the __enable_port and __disable_port cases is difficult, as those calls generally already hold the state machine lock, and cannot unconditionally call rtnl_lock because either they already hold RTNL (for calls via bond_3ad_unbind_slave) or due to the potential for deadlock with bond_3ad_adapter_speed_changed, bond_3ad_adapter_duplex_changed, bond_3ad_link_change, or bond_3ad_update_lacp_rate. All four of those are called with RTNL held, and acquire the state machine lock second. The calling contexts for __enable_port and __disable_port already hold the state machine lock, and may or may not need RTNL. According to the Jay's opinion, I don't think it is a problem that the slave don't send notify message synchronously when the status changed, normally the state machine is running every 100 ms, send the notify message at the end of the state machine if the slave's state changed should be better. I fix the problem through these steps: 1). add a new function bond_set_slave_state() which could change the slave's state and call rtmsg_ifinfo() according to the input parameters called notify. 2). Add a new slave parameter which called should_notify, if the slave's state changed and don't notify yet, the parameter will be set to 1, and then if the slave's state changed again, the param will be set to 0, it indicate that the slave's state has been restored, no need to notify any one. 3). the __enable_port and __disable_port should not call rtmsg_ifinfo in the state machine lock, any change in the state of slave could set a flag in the slave, it will indicated that an rtmsg_ifinfo should be called at the end of the state machine. Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 6d20fbd..6826e4f 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -181,7 +181,7 @@ static inline int __agg_has_partner(struct aggregator *agg) */ static inline void __disable_port(struct port *port) { - bond_set_slave_inactive_flags(port->slave); + bond_set_slave_inactive_flags(port->slave, BOND_SLAVE_NOTIFY_LATER); } /** @@ -193,7 +193,7 @@ static inline void __enable_port(struct port *port) struct slave *slave = port->slave; if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) - bond_set_slave_active_flags(slave); + bond_set_slave_active_flags(slave, BOND_SLAVE_NOTIFY_LATER); } /** @@ -2062,6 +2062,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) struct list_head *iter; struct slave *slave; struct port *port; + bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER; read_lock(&bond->lock); rcu_read_lock(); @@ -2119,8 +2120,25 @@ void bond_3ad_state_machine_handler(struct work_struct *work) } re_arm: + bond_for_each_slave_rcu(bond, slave, iter) { + if (slave->should_notify) { + should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW; + break; + } + } rcu_read_unlock(); read_unlock(&bond->lock); + + if (should_notify_rtnl && rtnl_trylock()) { + bond_for_each_slave(bond, slave, iter) { + if (slave->should_notify) { + rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, + GFP_KERNEL); + slave->should_notify = 0; + } + } + rtnl_unlock(); + } queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1c6104d..e02029b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -829,21 +829,25 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) if (bond_is_lb(bond)) { bond_alb_handle_active_change(bond, new_active); if (old_active) - bond_set_slave_inactive_flags(old_active); + bond_set_slave_inactive_flags(old_active, + BOND_SLAVE_NOTIFY_NOW); if (new_active) - bond_set_slave_active_flags(new_active); + bond_set_slave_active_flags(new_active, + BOND_SLAVE_NOTIFY_NOW); } else { rcu_assign_pointer(bond->curr_active_slave, new_active); } if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { if (old_active) - bond_set_slave_inactive_flags(old_active); + bond_set_slave_inactive_flags(old_active, + BOND_SLAVE_NOTIFY_NOW); if (new_active) { bool should_notify_peers = false; - bond_set_slave_active_flags(new_active); + bond_set_slave_active_flags(new_active, + BOND_SLAVE_NOTIFY_NOW); if (bond->params.fail_over_mac) bond_do_fail_over_mac(bond, new_active, @@ -1463,14 +1467,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) switch (bond->params.mode) { case BOND_MODE_ACTIVEBACKUP: - bond_set_slave_inactive_flags(new_slave); + bond_set_slave_inactive_flags(new_slave, + BOND_SLAVE_NOTIFY_NOW); break; case BOND_MODE_8023AD: /* in 802.3ad mode, the internal mechanism * will activate the slaves in the selected * aggregator */ - bond_set_slave_inactive_flags(new_slave); + bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); /* if this is the first slave */ if (!prev_slave) { SLAVE_AD_INFO(new_slave).id = 1; @@ -1488,7 +1493,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) case BOND_MODE_TLB: case BOND_MODE_ALB: bond_set_active_slave(new_slave); - bond_set_slave_inactive_flags(new_slave); + bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); break; default: pr_debug("This slave is always active in trunk mode\n"); @@ -2015,7 +2020,8 @@ static void bond_miimon_commit(struct bonding *bond) if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || bond->params.mode == BOND_MODE_8023AD) - bond_set_slave_inactive_flags(slave); + bond_set_slave_inactive_flags(slave, + BOND_SLAVE_NOTIFY_NOW); pr_info("%s: link status definitely down for interface %s, disabling it\n", bond->dev->name, slave->dev->name); @@ -2562,7 +2568,8 @@ static void bond_ab_arp_commit(struct bonding *bond) slave->link = BOND_LINK_UP; if (bond->current_arp_slave) { bond_set_slave_inactive_flags( - bond->current_arp_slave); + bond->current_arp_slave, + BOND_SLAVE_NOTIFY_NOW); bond->current_arp_slave = NULL; } @@ -2582,7 +2589,8 @@ static void bond_ab_arp_commit(struct bonding *bond) slave->link_failure_count++; slave->link = BOND_LINK_DOWN; - bond_set_slave_inactive_flags(slave); + bond_set_slave_inactive_flags(slave, + BOND_SLAVE_NOTIFY_NOW); pr_info("%s: link status definitely down for interface %s, disabling it\n", bond->dev->name, slave->dev->name); @@ -2657,7 +2665,7 @@ static bool bond_ab_arp_probe(struct bonding *bond) } } - bond_set_slave_inactive_flags(curr_arp_slave); + bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_NOW); bond_for_each_slave(bond, slave, iter) { if (!found && !before && IS_UP(slave->dev)) @@ -2677,7 +2685,8 @@ static bool bond_ab_arp_probe(struct bonding *bond) if (slave->link_failure_count < UINT_MAX) slave->link_failure_count++; - bond_set_slave_inactive_flags(slave); + bond_set_slave_inactive_flags(slave, + BOND_SLAVE_NOTIFY_NOW); pr_info("%s: backup interface %s is now down.\n", bond->dev->name, slave->dev->name); @@ -2695,7 +2704,7 @@ static bool bond_ab_arp_probe(struct bonding *bond) } new_slave->link = BOND_LINK_BACK; - bond_set_slave_active_flags(new_slave); + bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); bond_arp_send_all(bond, new_slave); new_slave->jiffies = jiffies; rcu_assign_pointer(bond->current_arp_slave, new_slave); @@ -3046,9 +3055,11 @@ static int bond_open(struct net_device *bond_dev) bond_for_each_slave(bond, slave, iter) { if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) && (slave != bond->curr_active_slave)) { - bond_set_slave_inactive_flags(slave); + bond_set_slave_inactive_flags(slave, + BOND_SLAVE_NOTIFY_NOW); } else { - bond_set_slave_active_flags(slave); + bond_set_slave_active_flags(slave, + BOND_SLAVE_NOTIFY_NOW); } } read_unlock(&bond->curr_slave_lock); diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 86ccfb9..9b280ac 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -195,7 +195,8 @@ struct slave { s8 new_link; u8 backup:1, /* indicates backup slave. Value corresponds with BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ - inactive:1; /* indicates inactive slave */ + inactive:1, /* indicates inactive slave */ + should_notify:1; /* indicateds whether the state changed */ u8 duplex; u32 original_mtu; u32 link_failure_count; @@ -303,6 +304,24 @@ static inline void bond_set_backup_slave(struct slave *slave) } } +static inline void bond_set_slave_state(struct slave *slave, + int slave_state, bool notify) +{ + if (slave->backup == slave_state) + return; + + slave->backup = slave_state; + if (notify) { + rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_KERNEL); + slave->should_notify = 0; + } else { + if (slave->should_notify) + slave->should_notify = 0; + else + slave->should_notify = 1; + } +} + static inline void bond_slave_state_change(struct bonding *bond) { struct list_head *iter; @@ -343,6 +362,9 @@ static inline bool bond_is_active_slave(struct slave *slave) #define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \ BOND_ARP_VALIDATE_BACKUP) +#define BOND_SLAVE_NOTIFY_NOW true +#define BOND_SLAVE_NOTIFY_LATER false + static inline int slave_do_arp_validate(struct bonding *bond, struct slave *slave) { @@ -394,17 +416,19 @@ static inline void bond_netpoll_send_skb(const struct slave *slave, } #endif -static inline void bond_set_slave_inactive_flags(struct slave *slave) +static inline void bond_set_slave_inactive_flags(struct slave *slave, + bool notify) { if (!bond_is_lb(slave->bond)) - bond_set_backup_slave(slave); + bond_set_slave_state(slave, BOND_STATE_BACKUP, notify); if (!slave->bond->params.all_slaves_active) slave->inactive = 1; } -static inline void bond_set_slave_active_flags(struct slave *slave) +static inline void bond_set_slave_active_flags(struct slave *slave, + bool notify) { - bond_set_active_slave(slave); + bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify); slave->inactive = 0; } -- cgit v0.10.2 From b0929915e0356acedf59504521c097ecada88b19 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Wed, 26 Feb 2014 11:05:23 +0800 Subject: bonding: Fix RTNL: assertion failed at net/core/rtnetlink.c for ab arp monitor Veaceslav has reported and fix this problem by commit f2ebd477f141bc0 (bonding: restructure locking of bond_ab_arp_probe()). According Jay's opinion, the current solution is not very well, because the notification is to indicate that the interface has actually changed state in a meaningful way, but these calls in the ab ARP monitor are internal settings of the flags to allow the ARP monitor to search for a slave to become active when there are no active slaves. The flag setting to active or backup is to permit the ARP monitor's response logic to do the right thing when deciding if the test slave (current_arp_slave) is up or not. So the best way to fix the problem is that we should not send a notification when the slave is in testing state, and check the state at the end of the monitor, if the slave's state recover, avoid to send pointless notification twice. And RTNL is really a big lock, hold it regardless the slave's state changed or not when the current_active_slave is null will loss performance (every 100ms), so we should hold it only when the slave's state changed and need to notify. I revert the old commit and add new modifications. Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 6826e4f..dcde5605 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2130,13 +2130,7 @@ re_arm: read_unlock(&bond->lock); if (should_notify_rtnl && rtnl_trylock()) { - bond_for_each_slave(bond, slave, iter) { - if (slave->should_notify) { - rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, - GFP_KERNEL); - slave->should_notify = 0; - } - } + bond_slave_state_notify(bond); rtnl_unlock(); } queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e02029b..82b70ff 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2623,17 +2623,17 @@ do_failover: /* * Send ARP probes for active-backup mode ARP monitor. + * + * Called with rcu_read_lock hold. */ static bool bond_ab_arp_probe(struct bonding *bond) { struct slave *slave, *before = NULL, *new_slave = NULL, - *curr_arp_slave, *curr_active_slave; + *curr_arp_slave = rcu_dereference(bond->current_arp_slave), + *curr_active_slave = rcu_dereference(bond->curr_active_slave); struct list_head *iter; bool found = false; - - rcu_read_lock(); - curr_arp_slave = rcu_dereference(bond->current_arp_slave); - curr_active_slave = rcu_dereference(bond->curr_active_slave); + bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER; if (curr_arp_slave && curr_active_slave) pr_info("PROBE: c_arp %s && cas %s BAD\n", @@ -2642,32 +2642,23 @@ static bool bond_ab_arp_probe(struct bonding *bond) if (curr_active_slave) { bond_arp_send_all(bond, curr_active_slave); - rcu_read_unlock(); - return true; + return should_notify_rtnl; } - rcu_read_unlock(); /* if we don't have a curr_active_slave, search for the next available * backup slave from the current_arp_slave and make it the candidate * for becoming the curr_active_slave */ - if (!rtnl_trylock()) - return false; - /* curr_arp_slave might have gone away */ - curr_arp_slave = ACCESS_ONCE(bond->current_arp_slave); - if (!curr_arp_slave) { - curr_arp_slave = bond_first_slave(bond); - if (!curr_arp_slave) { - rtnl_unlock(); - return true; - } + curr_arp_slave = bond_first_slave_rcu(bond); + if (!curr_arp_slave) + return should_notify_rtnl; } - bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_NOW); + bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER); - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { if (!found && !before && IS_UP(slave->dev)) before = slave; @@ -2686,7 +2677,7 @@ static bool bond_ab_arp_probe(struct bonding *bond) slave->link_failure_count++; bond_set_slave_inactive_flags(slave, - BOND_SLAVE_NOTIFY_NOW); + BOND_SLAVE_NOTIFY_LATER); pr_info("%s: backup interface %s is now down.\n", bond->dev->name, slave->dev->name); @@ -2698,26 +2689,31 @@ static bool bond_ab_arp_probe(struct bonding *bond) if (!new_slave && before) new_slave = before; - if (!new_slave) { - rtnl_unlock(); - return true; - } + if (!new_slave) + goto check_state; new_slave->link = BOND_LINK_BACK; - bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); + bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER); bond_arp_send_all(bond, new_slave); new_slave->jiffies = jiffies; rcu_assign_pointer(bond->current_arp_slave, new_slave); - rtnl_unlock(); - return true; +check_state: + bond_for_each_slave_rcu(bond, slave, iter) { + if (slave->should_notify) { + should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW; + break; + } + } + return should_notify_rtnl; } static void bond_activebackup_arp_mon(struct work_struct *work) { struct bonding *bond = container_of(work, struct bonding, arp_work.work); - bool should_notify_peers = false, should_commit = false; + bool should_notify_peers = false; + bool should_notify_rtnl = false; int delta_in_ticks; delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); @@ -2726,11 +2722,12 @@ static void bond_activebackup_arp_mon(struct work_struct *work) goto re_arm; rcu_read_lock(); + should_notify_peers = bond_should_notify_peers(bond); - should_commit = bond_ab_arp_inspect(bond); - rcu_read_unlock(); - if (should_commit) { + if (bond_ab_arp_inspect(bond)) { + rcu_read_unlock(); + /* Race avoidance with bond_close flush of workqueue */ if (!rtnl_trylock()) { delta_in_ticks = 1; @@ -2739,23 +2736,28 @@ static void bond_activebackup_arp_mon(struct work_struct *work) } bond_ab_arp_commit(bond); + rtnl_unlock(); + rcu_read_lock(); } - if (!bond_ab_arp_probe(bond)) { - /* rtnl locking failed, re-arm */ - delta_in_ticks = 1; - should_notify_peers = false; - } + should_notify_rtnl = bond_ab_arp_probe(bond); + rcu_read_unlock(); re_arm: if (bond->params.arp_interval) queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); - if (should_notify_peers) { + if (should_notify_peers || should_notify_rtnl) { if (!rtnl_trylock()) return; - call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev); + + if (should_notify_peers) + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, + bond->dev); + if (should_notify_rtnl) + bond_slave_state_notify(bond); + rtnl_unlock(); } } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 9b280ac..2b0fdec 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -335,6 +335,19 @@ static inline void bond_slave_state_change(struct bonding *bond) } } +static inline void bond_slave_state_notify(struct bonding *bond) +{ + struct list_head *iter; + struct slave *tmp; + + bond_for_each_slave(bond, tmp, iter) { + if (tmp->should_notify) { + rtmsg_ifinfo(RTM_NEWLINK, tmp->dev, 0, GFP_KERNEL); + tmp->should_notify = 0; + } + } +} + static inline int bond_slave_state(struct slave *slave) { return slave->backup; -- cgit v0.10.2 From e5fe0cd442e50f156bb54f5385b19eda50a13ccd Mon Sep 17 00:00:00 2001 From: Freddy Xin Date: Wed, 26 Feb 2014 16:54:31 +0800 Subject: AX88179_178A: Add VID:DID for Lenovo OneLinkDock Gigabit LAN Add VID:DID for Lenovo OneLinkDock Gigabit LAN Signed-off-by: Freddy Xin Signed-off-by: David S. Miller diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 955df81..460e823 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1421,6 +1421,19 @@ static const struct driver_info samsung_info = { .tx_fixup = ax88179_tx_fixup, }; +static const struct driver_info lenovo_info = { + .description = "Lenovo OneLinkDock Gigabit LAN", + .bind = ax88179_bind, + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, +}; + static const struct usb_device_id products[] = { { /* ASIX AX88179 10/100/1000 */ @@ -1438,6 +1451,10 @@ static const struct usb_device_id products[] = { /* Samsung USB Ethernet Adapter */ USB_DEVICE(0x04e8, 0xa100), .driver_info = (unsigned long)&samsung_info, +}, { + /* Lenovo OneLinkDock Gigabit LAN */ + USB_DEVICE(0x17ef, 0x304b), + .driver_info = (unsigned long)&lenovo_info, }, { }, }; -- cgit v0.10.2 From ee6154e11eeccd4ae32c4881415dbd902a869592 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 26 Feb 2014 14:20:30 +0100 Subject: bonding: fix a div error caused by the slave release path There's a bug in the slave release function which leads the transmit functions which use the bond->slave_cnt to a div by 0 because we might just have released our last slave and made slave_cnt == 0 but at the same time we may have a transmitter after the check for an empty list which will fetch it and use it in the slave id calculation. Fix it by moving the slave_cnt after synchronize_rcu so if this was our last slave any new transmitters will see an empty slave list which is checked after rcu lock but before calling the mode transmit functions which rely on bond->slave_cnt. Fixes: 278b208375 ("bonding: initial RCU conversion") CC: Veaceslav Falico CC: Andy Gospodarek CC: Jay Vosburgh CC: David S. Miller Signed-off-by: Nikolay Aleksandrov Acked-by: Veaceslav Falico Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 82b70ff..b47fa04 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1659,9 +1659,6 @@ static int __bond_release_one(struct net_device *bond_dev, return -EINVAL; } - /* release the slave from its bond */ - bond->slave_cnt--; - bond_sysfs_slave_del(slave); bond_upper_dev_unlink(bond_dev, slave_dev); @@ -1743,6 +1740,7 @@ static int __bond_release_one(struct net_device *bond_dev, unblock_netpoll_tx(); synchronize_rcu(); + bond->slave_cnt--; if (!bond_has_slaves(bond)) { call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); -- cgit v0.10.2 From f3ca4164529b875374c410193bbbac0ee960895f Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 26 Feb 2014 21:03:05 +0800 Subject: ACPI / processor: Rework processor throttling with work_on_cpu() acpi_processor_set_throttling() uses set_cpus_allowed_ptr() to make sure that the (struct acpi_processor)->acpi_processor_set_throttling() callback will run on the right CPU. However, the function may be called from a worker thread already bound to a different CPU in which case that won't work. Make acpi_processor_set_throttling() use work_on_cpu() as appropriate instead of abusing set_cpus_allowed_ptr(). Reported-and-tested-by: Jiri Olsa Signed-off-by: Lan Tianyu Cc: All applicable [rjw: Changelog] Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 28baa05..84243c3 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -56,6 +56,12 @@ struct throttling_tstate { int target_state; /* target T-state */ }; +struct acpi_processor_throttling_arg { + struct acpi_processor *pr; + int target_state; + bool force; +}; + #define THROTTLING_PRECHANGE (1) #define THROTTLING_POSTCHANGE (2) @@ -1060,16 +1066,24 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, return 0; } +static long acpi_processor_throttling_fn(void *data) +{ + struct acpi_processor_throttling_arg *arg = data; + struct acpi_processor *pr = arg->pr; + + return pr->throttling.acpi_processor_set_throttling(pr, + arg->target_state, arg->force); +} + int acpi_processor_set_throttling(struct acpi_processor *pr, int state, bool force) { - cpumask_var_t saved_mask; int ret = 0; unsigned int i; struct acpi_processor *match_pr; struct acpi_processor_throttling *p_throttling; + struct acpi_processor_throttling_arg arg; struct throttling_tstate t_state; - cpumask_var_t online_throttling_cpus; if (!pr) return -EINVAL; @@ -1080,14 +1094,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, if ((state < 0) || (state > (pr->throttling.state_count - 1))) return -EINVAL; - if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL)) - return -ENOMEM; - - if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) { - free_cpumask_var(saved_mask); - return -ENOMEM; - } - if (cpu_is_offline(pr->id)) { /* * the cpu pointed by pr->id is offline. Unnecessary to change @@ -1096,17 +1102,15 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, return -ENODEV; } - cpumask_copy(saved_mask, ¤t->cpus_allowed); t_state.target_state = state; p_throttling = &(pr->throttling); - cpumask_and(online_throttling_cpus, cpu_online_mask, - p_throttling->shared_cpu_map); + /* * The throttling notifier will be called for every * affected cpu in order to get one proper T-state. * The notifier event is THROTTLING_PRECHANGE. */ - for_each_cpu(i, online_throttling_cpus) { + for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) { t_state.cpu = i; acpi_processor_throttling_notifier(THROTTLING_PRECHANGE, &t_state); @@ -1118,21 +1122,18 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, * it can be called only for the cpu pointed by pr. */ if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { - /* FIXME: use work_on_cpu() */ - if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { - /* Can't migrate to the pr->id CPU. Exit */ - ret = -ENODEV; - goto exit; - } - ret = p_throttling->acpi_processor_set_throttling(pr, - t_state.target_state, force); + arg.pr = pr; + arg.target_state = state; + arg.force = force; + ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg); } else { /* * When the T-state coordination is SW_ALL or HW_ALL, * it is necessary to set T-state for every affected * cpus. */ - for_each_cpu(i, online_throttling_cpus) { + for_each_cpu_and(i, cpu_online_mask, + p_throttling->shared_cpu_map) { match_pr = per_cpu(processors, i); /* * If the pointer is invalid, we will report the @@ -1153,13 +1154,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, "on CPU %d\n", i)); continue; } - t_state.cpu = i; - /* FIXME: use work_on_cpu() */ - if (set_cpus_allowed_ptr(current, cpumask_of(i))) - continue; - ret = match_pr->throttling. - acpi_processor_set_throttling( - match_pr, t_state.target_state, force); + + arg.pr = match_pr; + arg.target_state = state; + arg.force = force; + ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, + &arg); } } /* @@ -1168,17 +1168,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, * affected cpu to update the T-states. * The notifier event is THROTTLING_POSTCHANGE */ - for_each_cpu(i, online_throttling_cpus) { + for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) { t_state.cpu = i; acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE, &t_state); } - /* restore the previous state */ - /* FIXME: use work_on_cpu() */ - set_cpus_allowed_ptr(current, saved_mask); -exit: - free_cpumask_var(online_throttling_cpus); - free_cpumask_var(saved_mask); + return ret; } -- cgit v0.10.2 From 6dbd46c849e071e6afc1e0cad489b0175bca9318 Mon Sep 17 00:00:00 2001 From: Joerg Dorchain Date: Fri, 21 Feb 2014 20:29:33 +0100 Subject: USB: ftdi_sio: add Cressi Leonardo PID Hello, the following patch adds an entry for the PID of a Cressi Leonardo diving computer interface to kernel 3.13.0. It is detected as FT232RL. Works with subsurface. Signed-off-by: Joerg Dorchain Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ee1f00f..44ab129 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -907,6 +907,8 @@ static const struct usb_device_id id_table_combined[] = { /* Crucible Devices */ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, + /* Cressi Devices */ + { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 1e2d369..e599fbf 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1320,3 +1320,9 @@ * Manufacturer: Smart GSM Team */ #define FTDI_Z3X_PID 0x0011 + +/* + * Product: Cressi PC Interface + * Manufacturer: Cressi + */ +#define FTDI_CRESSI_PID 0x87d0 -- cgit v0.10.2 From a1227f3c1030e96ebc51d677d2f636268845c5fb Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 19 Feb 2014 10:29:01 +0100 Subject: usb: ehci: fix deadlock when threadirqs option is used ehci_irq() and ehci_hrtimer_func() can deadlock on ehci->lock when threadirqs option is used. To prevent the deadlock use spin_lock_irqsave() in ehci_irq(). This change can be reverted when hrtimer callbacks become threaded. Signed-off-by: Stanislaw Gruszka Cc: stable Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 4711427..81cda09 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -685,8 +685,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 status, masked_status, pcd_status = 0, cmd; int bh; + unsigned long flags; - spin_lock (&ehci->lock); + /* + * For threadirqs option we use spin_lock_irqsave() variant to prevent + * deadlock with ehci hrtimer callback, because hrtimer callbacks run + * in interrupt context even when threadirqs is specified. We can go + * back to spin_lock() variant when hrtimer callbacks become threaded. + */ + spin_lock_irqsave(&ehci->lock, flags); status = ehci_readl(ehci, &ehci->regs->status); @@ -704,7 +711,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* Shared IRQ? */ if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) { - spin_unlock(&ehci->lock); + spin_unlock_irqrestore(&ehci->lock, flags); return IRQ_NONE; } @@ -815,7 +822,7 @@ dead: if (bh) ehci_work (ehci); - spin_unlock (&ehci->lock); + spin_unlock_irqrestore(&ehci->lock, flags); if (pcd_status) usb_hcd_poll_rh_status(hcd); return IRQ_HANDLED; -- cgit v0.10.2 From f63fcc90a379a269a07a1111f5b7ba28ebcb1eb4 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 11 Feb 2014 22:15:07 +0900 Subject: clk:at91: Fix memory leak in of_at91_clk_master_setup() cppcheck detected following error [clk-master.c:245]: (error) Memory leak: characteristics The original code forgot to free characteristics when irq_of_parse_and_map() failed. Signed-off-by: Masanari Iida Acked-by Boris BREZILLON Acked-by: Alexandre Belloni Signed-off-by: Mike Turquette diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index bd313f7..c1af80b 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -242,7 +242,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, irq = irq_of_parse_and_map(np, 0); if (!irq) - return; + goto out_free_characteristics; clk = at91_clk_register_master(pmc, irq, name, num_parents, parent_names, layout, -- cgit v0.10.2 From 367d896dafe1b5f49bee75d3a419b9eb9936ae26 Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Fri, 31 Jan 2014 15:30:54 -0800 Subject: tools/liblockdep: Fix initialization code path This makes initialization actually happen. Without it, initialization is always skipped due to an incorrect conditional statement. Signed-off-by: Ira W. Snyder Signed-off-by: Sasha Levin diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c index f8465a8..23bd69c 100644 --- a/tools/lib/lockdep/preload.c +++ b/tools/lib/lockdep/preload.c @@ -418,7 +418,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) __attribute__((constructor)) static void init_preload(void) { - if (__init_state != done) + if (__init_state == done) return; #ifndef __GLIBC__ -- cgit v0.10.2 From 75759827bbe78e53330de2c5e061ecec7fa6f86e Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Fri, 31 Jan 2014 13:35:31 -0800 Subject: tools/liblockdep: Fix include of asm/hash.h Commit 71ae8aac ("lib: introduce arch optimized hash library") added an include to for setting up an architecture specific fast hash. This patch mirrors the fix used for perf, titled "tools: perf: util: fix include for non x86 architectures". Signed-off-by: Ira W. Snyder Signed-off-by: Sasha Levin diff --git a/tools/lib/lockdep/uinclude/asm/hash.h b/tools/lib/lockdep/uinclude/asm/hash.h new file mode 100644 index 0000000..d82b170b --- /dev/null +++ b/tools/lib/lockdep/uinclude/asm/hash.h @@ -0,0 +1,6 @@ +#ifndef __ASM_GENERIC_HASH_H +#define __ASM_GENERIC_HASH_H + +/* Stub */ + +#endif /* __ASM_GENERIC_HASH_H */ -- cgit v0.10.2 From aef5976fc52a497ac8161f54164c786c771d3ae8 Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Fri, 31 Jan 2014 13:35:32 -0800 Subject: tools/liblockdep: Add include directory to allow tests to compile All of the programs in the tests directory require the liblockdep/mutex.h header in order to compile. Add the include directory to the compiler options so that the tests can be built with the provided Makefile. Signed-off-by: Ira W. Snyder Signed-off-by: Sasha Levin diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile index da8b7aa..e8dd749 100644 --- a/tools/lib/lockdep/Makefile +++ b/tools/lib/lockdep/Makefile @@ -112,7 +112,7 @@ export Q VERBOSE LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION) -INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES) +INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include $(CONFIG_INCLUDES) # Set compile option CFLAGS if not set elsewhere CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g -- cgit v0.10.2 From 1ddc1ffa2f8219e0c55c7f800048533e1ce8dee5 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 5 Feb 2014 17:53:13 -0500 Subject: tools/liblockdep: Mark runtests.sh as executable runtests.sh is used to run the sanity tests for liblockdep and should be set +x. Signed-off-by: Sasha Levin diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh old mode 100644 new mode 100755 -- cgit v0.10.2 From 9e3513b7af9ef3b6225f539181c2d94328bd18f7 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 5 Feb 2014 17:58:37 -0500 Subject: tools/liblockdep: Add a stub for new rcu_is_watching Stub out rcu_is_watching(), prevents build error with the updated tree. Signed-off-by: Sasha Levin diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/lib/lockdep/uinclude/linux/rcu.h index 4c99fcb..042ee8e 100644 --- a/tools/lib/lockdep/uinclude/linux/rcu.h +++ b/tools/lib/lockdep/uinclude/linux/rcu.h @@ -13,4 +13,9 @@ static inline int rcu_is_cpu_idle(void) return 1; } +static inline bool rcu_is_watching(void) +{ + return false; +} + #endif -- cgit v0.10.2 From 7b8853419d3344b06cff64b4dc926805698eeba5 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 8 Feb 2014 09:43:40 +0800 Subject: tools/liblockdep: Use realpath for srctree and objtree If BUILD_SRC or CURDIR contains tailing '/', the file names passed to gcc will contain '//'. It will be contained .o's in debuginfo, then confuse debugedit: https://bugzilla.redhat.com/show_bug.cgi?id=304121 This patch uses realpath command to makesure potential tailing '/'s are removed. Signed-off-by: Wang Nan Cc: Ingo Molnar Cc: Andrew Morton Cc: Geng Hui Signed-off-by: Sasha Levin diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile index e8dd749..07b0b75 100644 --- a/tools/lib/lockdep/Makefile +++ b/tools/lib/lockdep/Makefile @@ -87,8 +87,8 @@ endif # BUILD_SRC # We process the rest of the Makefile if this is the final invocation of make ifeq ($(skip-makefile),) -srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)) -objtree := $(CURDIR) +srctree := $(realpath $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))) +objtree := $(realpath $(CURDIR)) src := $(srctree) obj := $(objtree) -- cgit v0.10.2 From 09a89c219baf0f116387efc928e325cf23630f20 Mon Sep 17 00:00:00 2001 From: Jiri Bohac Date: Wed, 26 Feb 2014 18:20:13 +0100 Subject: bonding: disallow enslaving a bond to itself Enslaving a bond to itself leads to an endless loop and hangs the kernel. Signed-off-by: Jiri Bohac Tested-by: Ding Tianhong Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b47fa04..e5628fc 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1197,6 +1197,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) return -EBUSY; } + if (bond_dev == slave_dev) { + pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name); + return -EPERM; + } + /* vlan challenged mutual exclusion */ /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { -- cgit v0.10.2 From ac5630b504be8918f42f4bd62f75063e469adf8b Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Wed, 26 Feb 2014 17:14:33 +0100 Subject: ASoC: tlv320aic3x: Remove tlv320aic32x4 from compatibles of tlv320aic3x This reverts tlv320aic32x4 as compatible for tlv320aic3x as it has its own bindings now. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt index 9d8ea14..5e6040c 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt @@ -6,7 +6,6 @@ Required properties: - compatible - "string" - One of: "ti,tlv320aic3x" - Generic TLV320AIC3x device - "ti,tlv320aic32x4" - TLV320AIC32x4 "ti,tlv320aic33" - TLV320AIC33 "ti,tlv320aic3007" - TLV320AIC3007 "ti,tlv320aic3106" - TLV320AIC3106 -- cgit v0.10.2 From a3f7dcc9cc0392528bff75b17adfcd74fb8a0ecd Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 27 Feb 2014 08:45:01 +0800 Subject: ASoC: fsl-sai: Add SND_SOC_DAIFMT_DSP_A/B support. o Add SND_SOC_DAIFMT_DSP_A support. o Add SND_SOC_DAIFMT_DSP_B support. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 26d9f5e..c4a4231 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -108,15 +108,44 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, /* DAI mode */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - /* Data on rising edge of bclk, frame low, 1clk before data */ + /* + * Frame low, 1clk before data, one word length for frame sync, + * frame sync starts one serial clock cycle earlier, + * that is, together with the last bit of the previous + * data word. + */ val_cr2 &= ~FSL_SAI_CR2_BCP; val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_LEFT_J: - /* Data on rising edge of bclk, frame high, 0clk before data */ + /* + * Frame high, one word length for frame sync, + * frame sync asserts with the first bit of the frame. + */ val_cr2 &= ~FSL_SAI_CR2_BCP; val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); break; + case SND_SOC_DAIFMT_DSP_A: + /* + * Frame high, 1clk before data, one bit for frame sync, + * frame sync starts one serial clock cycle earlier, + * that is, together with the last bit of the previous + * data word. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~FSL_SAI_CR4_FSP; + val_cr4 |= FSL_SAI_CR4_FSE; + sai->is_dsp_mode = true; + break; + case SND_SOC_DAIFMT_DSP_B: + /* + * Frame high, one bit for frame sync, + * frame sync asserts with the first bit of the frame. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); + sai->is_dsp_mode = true; + break; case SND_SOC_DAIFMT_RIGHT_J: /* To be done */ default: @@ -219,7 +248,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; - val_cr4 |= FSL_SAI_CR4_SYWD(word_width); + if (!sai->is_dsp_mode) + val_cr4 |= FSL_SAI_CR4_SYWD(word_width); + val_cr5 |= FSL_SAI_CR5_WNW(word_width); val_cr5 |= FSL_SAI_CR5_W0W(word_width); @@ -245,6 +276,10 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); u32 tcsr, rcsr; + /* + * The transmitter bit clock and frame sync are to be + * used by both the transmitter and receiver. + */ regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, ~FSL_SAI_CR2_SYNC); regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, @@ -261,6 +296,10 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, tcsr &= ~FSL_SAI_CSR_FRDE; } + /* + * It is recommended that the transmitter is the last enabled + * and the first disabled. + */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 1571459..e432260 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -103,6 +103,7 @@ struct fsl_sai { bool big_endian_regs; bool big_endian_data; + bool is_dsp_mode; struct snd_dmaengine_dai_dma_data dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_tx; -- cgit v0.10.2 From 7995d74ab297e4f5526c8df70007e1e39f0d1f5c Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 26 Feb 2014 16:31:19 +0100 Subject: spi-topcliff-pch: Fix probing when DMA mode is used If during registering SPI master due to SPI device probing a SPI transfer is issued the DMA buffers are not allocated yet. This fixes the following oops: pch_spi 0000:02:0c.1: enabling device (0000 -> 0002) pch_spi 0000:02:0c.1: master is unqueued, this is deprecated BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] pch_spi_handle_dma+0x15c/0x6f4 [...] Signed-off-by: Alexander Stein Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 3383008c..88eb57e 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1452,6 +1452,11 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev) pch_spi_set_master_mode(master); + if (use_dma) { + dev_info(&plat_dev->dev, "Use DMA for data transfers\n"); + pch_alloc_dma_buf(board_dat, data); + } + ret = spi_register_master(master); if (ret != 0) { dev_err(&plat_dev->dev, @@ -1459,14 +1464,10 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev) goto err_spi_register_master; } - if (use_dma) { - dev_info(&plat_dev->dev, "Use DMA for data transfers\n"); - pch_alloc_dma_buf(board_dat, data); - } - return 0; err_spi_register_master: + pch_free_dma_buf(board_dat, data); free_irq(board_dat->pdev->irq, data); err_request_irq: pch_spi_free_resources(board_dat, data); -- cgit v0.10.2 From 566f59394d7b4808f0fa9b64c4c9db1ac2d10cbd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 10:03:43 -0500 Subject: MAINTAINERS: add entry for drm radeon driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an entry for radeon. Signed-off-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Dave Airlie diff --git a/MAINTAINERS b/MAINTAINERS index fb08dce..e03da03 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2851,6 +2851,16 @@ F: drivers/gpu/drm/ F: include/drm/ F: include/uapi/drm/ +RADEON DRM DRIVERS +M: Alex Deucher +M: Christian König +L: dri-devel@lists.freedesktop.org +T: git git://people.freedesktop.org/~agd5f/linux +S: Supported +F: drivers/gpu/drm/radeon/ +F: include/drm/radeon* +F: include/uapi/drm/radeon* + INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets) M: Daniel Vetter M: Jani Nikula -- cgit v0.10.2 From b0447888dc29f4fb91c3b3b02e3f1f0bfc6e1222 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 10:03:44 -0500 Subject: MAINTAINERS: update drm git tree entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix Dave's git tree. Signed-off-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Dave Airlie diff --git a/MAINTAINERS b/MAINTAINERS index e03da03..623ba85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2845,7 +2845,7 @@ F: lib/kobj* DRM DRIVERS M: David Airlie L: dri-devel@lists.freedesktop.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git +T: git git://people.freedesktop.org/~airlied/linux S: Maintained F: drivers/gpu/drm/ F: include/drm/ -- cgit v0.10.2 From e7eb65cac0720df8b3946af7f7a9dc363cf0a814 Mon Sep 17 00:00:00 2001 From: Max Stepanov Date: Sun, 16 Feb 2014 16:36:57 +0200 Subject: iwlwifi: mvm: change of listen interval from 70 to 10 Some APs reject STA association request if a listen interval value exceeds a threshold of 10. Thus, for example, Cisco APs may deny STA associations returning status code 12 (Association denied due to reason outside the scope of 802.11 standard) in the association response frame. Fixing the issue by setting the default IWL_CONN_MAX_LISTEN_INTERVAL value from 70 to 10. Cc: [3.10+] Signed-off-by: Max Stepanov Reviewed-by: Alexander Bondar Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index e4ead86..2b0ba1f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -152,7 +152,7 @@ enum iwl_power_scheme { IWL_POWER_SCHEME_LP }; -#define IWL_CONN_MAX_LISTEN_INTERVAL 70 +#define IWL_CONN_MAX_LISTEN_INTERVAL 10 #define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\ IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\ -- cgit v0.10.2 From b3619b288b621e63f66908045f48495869a996a6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 27 Feb 2014 07:41:32 +0100 Subject: ASoC: sta32x: Fix wrong enum for limiter2 release rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a typo in the Limiter2 Release Rate control, a wrong enum for Limiter1 is assigned. It must point to Limiter2. Spotted by a compile warning: In file included from sound/soc/codecs/sta32x.c:34:0: sound/soc/codecs/sta32x.c:223:29: warning: ‘sta32x_limiter2_release_rate_enum’ defined but not used [-Wunused-variable] static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum, ^ include/sound/soc.h:275:18: note: in definition of macro ‘SOC_ENUM_DOUBLE_DECL’ struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \ ^ sound/soc/codecs/sta32x.c:223:8: note: in expansion of macro ‘SOC_ENUM_SINGLE_DECL’ static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum, ^ Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Cc: diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index ea78c17..2735361 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -434,7 +434,7 @@ SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum), SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum), SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), -SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), +SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter2_release_rate_enum), /* depending on mode, the attack/release thresholds have * two different enum definitions; provide both -- cgit v0.10.2 From 143582c6847cb285b361804c613127c25de60ca4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 25 Feb 2014 10:37:15 +0100 Subject: iwlwifi: fix TX status for aggregated packets Only the first packet is currently handled correctly, but then all others are assumed to have failed which is problematic. Fix this, marking them all successful instead (since if they're not then the firmware will have transmitted them as single frames.) This fixes the lost packet reporting. Also do a tiny variable scoping cleanup. Cc: Signed-off-by: Johannes Berg [Add the dvm part] Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index a6839df..398dd09 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -1291,8 +1291,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data; struct iwl_ht_agg *agg; struct sk_buff_head reclaimed_skbs; - struct ieee80211_tx_info *info; - struct ieee80211_hdr *hdr; struct sk_buff *skb; int sta_id; int tid; @@ -1379,22 +1377,28 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, freed = 0; skb_queue_walk(&reclaimed_skbs, skb) { - hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (ieee80211_is_data_qos(hdr->frame_control)) freed++; else WARN_ON_ONCE(1); - info = IEEE80211_SKB_CB(skb); iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); + memset(&info->status, 0, sizeof(info->status)); + /* Packet was transmitted successfully, failures come as single + * frames because before failing a frame the firmware transmits + * it without aggregation at least once. + */ + info->flags |= IEEE80211_TX_STAT_ACK; + if (freed == 1) { /* this is the first skb we deliver in this batch */ /* put the rate scaling data there */ info = IEEE80211_SKB_CB(skb); memset(&info->status, 0, sizeof(info->status)); - info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; info->status.ampdu_ack_len = ba_resp->txed_2_done; info->status.ampdu_len = ba_resp->txed; diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 4df12fa..76ee486 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -822,16 +822,12 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, struct iwl_mvm_ba_notif *ba_notif = (void *)pkt->data; struct sk_buff_head reclaimed_skbs; struct iwl_mvm_tid_data *tid_data; - struct ieee80211_tx_info *info; struct ieee80211_sta *sta; struct iwl_mvm_sta *mvmsta; - struct ieee80211_hdr *hdr; struct sk_buff *skb; int sta_id, tid, freed; - /* "flow" corresponds to Tx queue */ u16 scd_flow = le16_to_cpu(ba_notif->scd_flow); - /* "ssn" is start of block-ack Tx window, corresponds to index * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_notif->scd_ssn); @@ -888,22 +884,26 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, freed = 0; skb_queue_walk(&reclaimed_skbs, skb) { - hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (ieee80211_is_data_qos(hdr->frame_control)) freed++; else WARN_ON_ONCE(1); - info = IEEE80211_SKB_CB(skb); iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); + memset(&info->status, 0, sizeof(info->status)); + /* Packet was transmitted successfully, failures come as single + * frames because before failing a frame the firmware transmits + * it without aggregation at least once. + */ + info->flags |= IEEE80211_TX_STAT_ACK; + if (freed == 1) { /* this is the first skb we deliver in this batch */ /* put the rate scaling data there */ - info = IEEE80211_SKB_CB(skb); - memset(&info->status, 0, sizeof(info->status)); - info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; info->status.ampdu_ack_len = ba_notif->txed_2_done; info->status.ampdu_len = ba_notif->txed; -- cgit v0.10.2 From c685689fd24d310343ac33942e9a54a974ae9c43 Mon Sep 17 00:00:00 2001 From: Chuansheng Liu Date: Mon, 24 Feb 2014 11:29:50 +0800 Subject: genirq: Remove racy waitqueue_active check We hit one rare case below: T1 calling disable_irq(), but hanging at synchronize_irq() always; The corresponding irq thread is in sleeping state; And all CPUs are in idle state; After analysis, we found there is one possible scenerio which causes T1 is waiting there forever: CPU0 CPU1 synchronize_irq() wait_event() spin_lock() atomic_dec_and_test(&threads_active) insert the __wait into queue spin_unlock() if(waitqueue_active) atomic_read(&threads_active) wake_up() Here after inserted the __wait into queue on CPU0, and before test if queue is empty on CPU1, there is no barrier, it maybe cause it is not visible for CPU1 immediately, although CPU0 has updated the queue list. It is similar for CPU0 atomic_read() threads_active also. So we'd need one smp_mb() before waitqueue_active.that, but removing the waitqueue_active() check solves it as wel l and it makes things simple and clear. Signed-off-by: Chuansheng Liu Cc: Xiaoming Wang Link: http://lkml.kernel.org/r/1393212590-32543-1-git-send-email-chuansheng.liu@intel.com Cc: stable@vger.kernel.org Signed-off-by: Thomas Gleixner diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 481a13c..d3bf660 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -802,8 +802,7 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc, static void wake_threads_waitq(struct irq_desc *desc) { - if (atomic_dec_and_test(&desc->threads_active) && - waitqueue_active(&desc->wait_for_threads)) + if (atomic_dec_and_test(&desc->threads_active)) wake_up(&desc->wait_for_threads); } -- cgit v0.10.2 From 791c9e0292671a3bfa95286bb5c08129d8605618 Mon Sep 17 00:00:00 2001 From: George McCollister Date: Tue, 18 Feb 2014 17:56:51 -0600 Subject: sched: Fix double normalization of vruntime dequeue_entity() is called when p->on_rq and sets se->on_rq = 0 which appears to guarentee that the !se->on_rq condition is met. If the task has done set_current_state(TASK_INTERRUPTIBLE) without schedule() the second condition will be met and vruntime will be incorrectly adjusted twice. In certain cases this can result in the task's vruntime never increasing past the vruntime of other tasks on the CFS' run queue, starving them of CPU time. This patch changes switched_from_fair() to use !p->on_rq instead of !se->on_rq. I'm able to cause a task with a priority of 120 to starve all other tasks with the same priority on an ARM platform running 3.2.51-rt72 PREEMPT RT by writing one character at time to a serial tty (16550 UART) in a tight loop. I'm also able to verify making this change corrects the problem on that platform and kernel version. Signed-off-by: George McCollister Signed-off-by: Peter Zijlstra Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1392767811-28916-1-git-send-email-george.mccollister@gmail.com Signed-off-by: Ingo Molnar diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 7815709..9b4c4f3 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7001,15 +7001,15 @@ static void switched_from_fair(struct rq *rq, struct task_struct *p) struct cfs_rq *cfs_rq = cfs_rq_of(se); /* - * Ensure the task's vruntime is normalized, so that when its + * Ensure the task's vruntime is normalized, so that when it's * switched back to the fair class the enqueue_entity(.flags=0) will * do the right thing. * - * If it was on_rq, then the dequeue_entity(.flags=0) will already - * have normalized the vruntime, if it was !on_rq, then only when + * If it's on_rq, then the dequeue_entity(.flags=0) will already + * have normalized the vruntime, if it's !on_rq, then only when * the task is sleeping will it still have non-normalized vruntime. */ - if (!se->on_rq && p->state != TASK_RUNNING) { + if (!p->on_rq && p->state != TASK_RUNNING) { /* * Fix up our vruntime so that the current sleep doesn't * cause 'unlimited' sleep bonus. -- cgit v0.10.2 From 3908ac13b550c93f97d8db136ff572be5495bc06 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Tue, 25 Feb 2014 19:52:23 +0400 Subject: sched/deadline: Cleanup RT leftovers from {inc/dec}_dl_migration In deadline class we do not have group scheduling. So, let's remove unnecessary X = X; equations. Signed-off-by: Kirill Tkhai Signed-off-by: Peter Zijlstra Cc: Juri Lelli Link: http://lkml.kernel.org/r/1393343543.4089.5.camel@tkhai Signed-off-by: Ingo Molnar diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 15cbc17..aecf930 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -135,7 +135,6 @@ static void update_dl_migration(struct dl_rq *dl_rq) static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { struct task_struct *p = dl_task_of(dl_se); - dl_rq = &rq_of_dl_rq(dl_rq)->dl; if (p->nr_cpus_allowed > 1) dl_rq->dl_nr_migratory++; @@ -146,7 +145,6 @@ static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) static void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) { struct task_struct *p = dl_task_of(dl_se); - dl_rq = &rq_of_dl_rq(dl_rq)->dl; if (p->nr_cpus_allowed > 1) dl_rq->dl_nr_migratory--; -- cgit v0.10.2 From eec751ed41a0ae7e92a43c33a458d7bd1b941631 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Mon, 24 Feb 2014 11:47:12 +0100 Subject: sched/deadline: Switch CPU's presence test order Commit 82b9580 ("sched/deadline: Test for CPU's presence explicitly") changed how we check if a CPU returned by cpudeadline machinery is valid. But, we don't want to call cpu_present() if best_cpu is equal to -1. So, switch the order of tests inside WARN_ON(). Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Cc: boris.ostrovsky@oracle.com Cc: konrad.wilk@oracle.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1393238832-9100-1-git-send-email-juri.lelli@gmail.com Signed-off-by: Ingo Molnar diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index 5b8838b..5b9bb42 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -70,7 +70,7 @@ static void cpudl_heapify(struct cpudl *cp, int idx) static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl) { - WARN_ON(!cpu_present(idx) || idx == IDX_INVALID); + WARN_ON(idx == IDX_INVALID || !cpu_present(idx)); if (dl_time_before(new_dl, cp->elements[idx].dl)) { cp->elements[idx].dl = new_dl; @@ -117,7 +117,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p, } out: - WARN_ON(!cpu_present(best_cpu) && best_cpu != -1); + WARN_ON(best_cpu != -1 && !cpu_present(best_cpu)); return best_cpu; } -- cgit v0.10.2 From faa5993736d9b44b508cab4f1f3a77d66641c6f4 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 21 Feb 2014 11:37:15 +0100 Subject: sched/deadline: Prevent rt_time growth to infinity Kirill Tkhai noted: Since deadline tasks share rt bandwidth, we must care about bandwidth timer set. Otherwise rt_time may grow up to infinity in update_curr_dl(), if there are no other available RT tasks on top level bandwidth. RT task were in fact throttled right after they got enqueued, and never executed again (rt_time never again went below rt_runtime). Peter then proposed to accrue DL execution on rt_time only when rt timer is active, and proposed a patch (this patch is a slight modification of that) to implement that behavior. While this solves Kirill problem, it has a drawback. Indeed, Kirill noted again: It looks we may get into a situation, when all CPU time is shared between RT and DL tasks: rt_runtime = n rt_period = 2n | RT working, DL sleeping | DL working, RT sleeping | ----------------------------------------------------------- | (1) duration = n | (2) duration = n | (repeat) |--------------------------|------------------------------| | (rt_bw timer is running) | (rt_bw timer is not running) | No time for fair tasks at all. While this can happen during the first period, if rq is always backlogged, RT tasks won't have the opportunity to execute anymore: rt_time reached rt_runtime during (1), suppose after (2) RT is enqueued back, it gets throttled since rt timer didn't fire, replenishment is from now on eaten up by DL tasks that accrue their execution on rt_time (while rt timer is active - we have an RT task waiting for replenishment). FAIR tasks are not touched after this first period. Ok, this is not ideal, and the situation is even worse! What above (the nice case), practically never happens in reality, where your rt timer is not aligned to tasks periods, tasks are in general not periodic, etc.. Long story short, you always risk to overload your system. This patch is based on Peter's idea, but exploits an additional fact: if you don't have RT tasks enqueued, it makes little sense to continue incrementing rt_time once you reached the upper limit (DL tasks have their own mechanism for throttling). This cures both problems: - no matter how many DL instances in the past, you'll have an rt_time slightly above rt_runtime when an RT task is enqueued, and from that point on (after the first replenishment), the task will normally execute; - you can still eat up all bandwidth during the first period, but not anymore after that, remember that DL execution will increment rt_time till the upper limit is reached. The situation is still not perfect! But, we have a simple solution for now, that limits how much you can jeopardize your system, as we keep working towards the right answer: RT groups scheduled using deadline servers. Reported-by: Kirill Tkhai Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20140225151515.617714e2f2cd6c558531ba61@gmail.com Signed-off-by: Ingo Molnar diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index aecf930..6e79b3f 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -562,6 +562,8 @@ int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se) return 1; } +extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq); + /* * Update the current task's runtime statistics (provided it is still * a -deadline task and has not been removed from the dl_rq). @@ -625,11 +627,13 @@ static void update_curr_dl(struct rq *rq) struct rt_rq *rt_rq = &rq->rt; raw_spin_lock(&rt_rq->rt_runtime_lock); - rt_rq->rt_time += delta_exec; /* * We'll let actual RT tasks worry about the overflow here, we - * have our own CBS to keep us inline -- see above. + * have our own CBS to keep us inline; only account when RT + * bandwidth is relevant. */ + if (sched_rt_bandwidth_account(rt_rq)) + rt_rq->rt_time += delta_exec; raw_spin_unlock(&rt_rq->rt_runtime_lock); } } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index a2740b7..1999021 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -538,6 +538,14 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq) #endif /* CONFIG_RT_GROUP_SCHED */ +bool sched_rt_bandwidth_account(struct rt_rq *rt_rq) +{ + struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); + + return (hrtimer_active(&rt_b->rt_period_timer) || + rt_rq->rt_time < rt_b->rt_runtime); +} + #ifdef CONFIG_SMP /* * We ran out of runtime, see if we can borrow some from our neighbours. -- cgit v0.10.2 From 26e61e8939b1fe8729572dabe9a9e97d930dd4f6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 21 Feb 2014 16:03:12 +0100 Subject: perf/x86: Fix event scheduling Vince "Super Tester" Weaver reported a new round of syscall fuzzing (Trinity) failures, with perf WARN_ON()s triggering. He also provided traces of the failures. This is I think the relevant bit: > pec_1076_warn-2804 [000] d... 147.926153: x86_pmu_disable: x86_pmu_disable > pec_1076_warn-2804 [000] d... 147.926153: x86_pmu_state: Events: { > pec_1076_warn-2804 [000] d... 147.926156: x86_pmu_state: 0: state: .R config: ffffffffffffffff ( (null)) > pec_1076_warn-2804 [000] d... 147.926158: x86_pmu_state: 33: state: AR config: 0 (ffff88011ac99800) > pec_1076_warn-2804 [000] d... 147.926159: x86_pmu_state: } > pec_1076_warn-2804 [000] d... 147.926160: x86_pmu_state: n_events: 1, n_added: 0, n_txn: 1 > pec_1076_warn-2804 [000] d... 147.926161: x86_pmu_state: Assignment: { > pec_1076_warn-2804 [000] d... 147.926162: x86_pmu_state: 0->33 tag: 1 config: 0 (ffff88011ac99800) > pec_1076_warn-2804 [000] d... 147.926163: x86_pmu_state: } > pec_1076_warn-2804 [000] d... 147.926166: collect_events: Adding event: 1 (ffff880119ec8800) So we add the insn:p event (fd[23]). At this point we should have: n_events = 2, n_added = 1, n_txn = 1 > pec_1076_warn-2804 [000] d... 147.926170: collect_events: Adding event: 0 (ffff8800c9e01800) > pec_1076_warn-2804 [000] d... 147.926172: collect_events: Adding event: 4 (ffff8800cbab2c00) We try and add the {BP,cycles,br_insn} group (fd[3], fd[4], fd[15]). These events are 0:cycles and 4:br_insn, the BP event isn't x86_pmu so that's not visible. group_sched_in() pmu->start_txn() /* nop - BP pmu */ event_sched_in() event->pmu->add() So here we should end up with: 0: n_events = 3, n_added = 2, n_txn = 2 4: n_events = 4, n_added = 3, n_txn = 3 But seeing the below state on x86_pmu_enable(), the must have failed, because the 0 and 4 events aren't there anymore. Looking at group_sched_in(), since the BP is the leader, its event_sched_in() must have succeeded, for otherwise we would not have seen the sibling adds. But since neither 0 or 4 are in the below state; their event_sched_in() must have failed; but I don't see why, the complete state: 0,0,1:p,4 fits perfectly fine on a core2. However, since we try and schedule 4 it means the 0 event must have succeeded! Therefore the 4 event must have failed, its failure will have put group_sched_in() into the fail path, which will call: event_sched_out() event->pmu->del() on 0 and the BP event. Now x86_pmu_del() will reduce n_events; but it will not reduce n_added; giving what we see below: n_event = 2, n_added = 2, n_txn = 2 > pec_1076_warn-2804 [000] d... 147.926177: x86_pmu_enable: x86_pmu_enable > pec_1076_warn-2804 [000] d... 147.926177: x86_pmu_state: Events: { > pec_1076_warn-2804 [000] d... 147.926179: x86_pmu_state: 0: state: .R config: ffffffffffffffff ( (null)) > pec_1076_warn-2804 [000] d... 147.926181: x86_pmu_state: 33: state: AR config: 0 (ffff88011ac99800) > pec_1076_warn-2804 [000] d... 147.926182: x86_pmu_state: } > pec_1076_warn-2804 [000] d... 147.926184: x86_pmu_state: n_events: 2, n_added: 2, n_txn: 2 > pec_1076_warn-2804 [000] d... 147.926184: x86_pmu_state: Assignment: { > pec_1076_warn-2804 [000] d... 147.926186: x86_pmu_state: 0->33 tag: 1 config: 0 (ffff88011ac99800) > pec_1076_warn-2804 [000] d... 147.926188: x86_pmu_state: 1->0 tag: 1 config: 1 (ffff880119ec8800) > pec_1076_warn-2804 [000] d... 147.926188: x86_pmu_state: } > pec_1076_warn-2804 [000] d... 147.926190: x86_pmu_enable: S0: hwc->idx: 33, hwc->last_cpu: 0, hwc->last_tag: 1 hwc->state: 0 So the problem is that x86_pmu_del(), when called from a group_sched_in() that fails (for whatever reason), and without x86_pmu TXN support (because the leader is !x86_pmu), will corrupt the n_added state. Reported-and-Tested-by: Vince Weaver Signed-off-by: Peter Zijlstra Cc: Paul Mackerras Cc: Steven Rostedt Cc: Stephane Eranian Cc: Dave Jones Cc: Link: http://lkml.kernel.org/r/20140221150312.GF3104@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 895604f..79f9f84 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1192,6 +1192,9 @@ static void x86_pmu_del(struct perf_event *event, int flags) for (i = 0; i < cpuc->n_events; i++) { if (event == cpuc->event_list[i]) { + if (i >= cpuc->n_events - cpuc->n_added) + --cpuc->n_added; + if (x86_pmu.put_event_constraints) x86_pmu.put_event_constraints(cpuc, event); -- cgit v0.10.2 From e3703f8cdfcf39c25c4338c3ad8e68891cca3731 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 24 Feb 2014 12:06:12 +0100 Subject: perf: Fix hotplug splat Drew Richardson reported that he could make the kernel go *boom* when hotplugging while having perf events active. It turned out that when you have a group event, the code in __perf_event_exit_context() fails to remove the group siblings from the context. We then proceed with destroying and freeing the event, and when you re-plug the CPU and try and add another event to that CPU, things go *boom* because you've still got dead entries there. Reported-by: Drew Richardson Signed-off-by: Peter Zijlstra Cc: Will Deacon Cc: Link: http://lkml.kernel.org/n/tip-k6v5wundvusvcseqj1si0oz0@git.kernel.org Signed-off-by: Ingo Molnar diff --git a/kernel/events/core.c b/kernel/events/core.c index 56003c6..fa0b2d4 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7856,14 +7856,14 @@ static void perf_pmu_rotate_stop(struct pmu *pmu) static void __perf_event_exit_context(void *__info) { struct perf_event_context *ctx = __info; - struct perf_event *event, *tmp; + struct perf_event *event; perf_pmu_rotate_stop(ctx->pmu); - list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry) - __perf_remove_from_context(event); - list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry) + rcu_read_lock(); + list_for_each_entry_rcu(event, &ctx->event_list, event_entry) __perf_remove_from_context(event); + rcu_read_unlock(); } static void perf_event_exit_cpu_context(int cpu) @@ -7887,11 +7887,11 @@ static void perf_event_exit_cpu(int cpu) { struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); + perf_event_exit_cpu_context(cpu); + mutex_lock(&swhash->hlist_mutex); swevent_hlist_release(swhash); mutex_unlock(&swhash->hlist_mutex); - - perf_event_exit_cpu_context(cpu); } #else static inline void perf_event_exit_cpu(int cpu) { } -- cgit v0.10.2 From 64be38ab03e9b238a1299857fef8b3707c0ed045 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 27 Feb 2014 17:10:12 +0530 Subject: genirq: Include missing header file in irqdomain.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include appropriate header file include/linux/of_irq.h in kernel/irq/irqdomain.c because it contains prototype definition of function define in kernel/irq/irqdomain.c. This eliminates the following warning in kernel/irq/irqdomain.c: kernel/irq/irqdomain.c:468:14: warning: no previous prototype for ‘irq_create_of_mapping’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Cc: Benjamin Herrenschmidt Link: http://lkml.kernel.org/r/eb89aebea7ff1a46122918ac389ebecf8248be9a.1393493276.git.rashika.kheria@gmail.com Signed-off-by: Thomas Gleixner diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index cf68bb3..f140337 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From 4729583006772b9530404bc1bb7c3aa4a10ffd4d Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Thu, 27 Feb 2014 18:19:03 +0800 Subject: cpuset: fix a locking issue in cpuset_migrate_mm() I can trigger a lockdep warning: # mount -t cgroup -o cpuset xxx /cgroup # mkdir /cgroup/cpuset # mkdir /cgroup/tmp # echo 0 > /cgroup/tmp/cpuset.cpus # echo 0 > /cgroup/tmp/cpuset.mems # echo 1 > /cgroup/tmp/cpuset.memory_migrate # echo $$ > /cgroup/tmp/tasks # echo 1 > /cgruop/tmp/cpuset.mems =============================== [ INFO: suspicious RCU usage. ] 3.14.0-rc1-0.1-default+ #32 Not tainted ------------------------------- include/linux/cgroup.h:682 suspicious rcu_dereference_check() usage! ... [] dump_stack+0x72/0x86 [] lockdep_rcu_suspicious+0x101/0x140 [] cpuset_migrate_mm+0xb1/0xe0 ... We used to hold cgroup_mutex when calling cpuset_migrate_mm(), but now we hold cpuset_mutex, which causes task_css() to complain. This is not a false-positive but a real issue. Holding cpuset_mutex won't prevent a task from migrating to another cpuset, and it won't prevent the original task->cgroup from destroying during this change. Fixes: 5d21cc2db040 (cpuset: replace cgroup_mutex locking with cpuset internal locking) Cc: # 3.9+ Signed-off-by: Li Zefan Sigend-off-by: Tejun Heo diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 4410ac6..dba9e4a 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -974,12 +974,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, * Temporarilly set tasks mems_allowed to target nodes of migration, * so that the migration code can allocate pages on these nodes. * - * Call holding cpuset_mutex, so current's cpuset won't change - * during this call, as manage_mutex holds off any cpuset_attach() - * calls. Therefore we don't need to take task_lock around the - * call to guarantee_online_mems(), as we know no one is changing - * our task's cpuset. - * * While the mm_struct we are migrating is typically from some * other task, the task_struct mems_allowed that we are hacking * is for our current task, which must allocate new pages for that @@ -996,8 +990,10 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from, do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL); + rcu_read_lock(); mems_cs = effective_nodemask_cpuset(task_cs(tsk)); guarantee_online_mems(mems_cs, &tsk->mems_allowed); + rcu_read_unlock(); } /* -- cgit v0.10.2 From 99afb0fd5f05aac467ffa85c36778fec4396209b Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Thu, 27 Feb 2014 18:19:36 +0800 Subject: cpuset: fix a race condition in __cpuset_node_allowed_softwall() It's not safe to access task's cpuset after releasing task_lock(). Holding callback_mutex won't help. Cc: Signed-off-by: Li Zefan Signed-off-by: Tejun Heo diff --git a/kernel/cpuset.c b/kernel/cpuset.c index dba9e4a..e6b1b66 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2482,9 +2482,9 @@ int __cpuset_node_allowed_softwall(int node, gfp_t gfp_mask) task_lock(current); cs = nearest_hardwall_ancestor(task_cs(current)); + allowed = node_isset(node, cs->mems_allowed); task_unlock(current); - allowed = node_isset(node, cs->mems_allowed); mutex_unlock(&callback_mutex); return allowed; } -- cgit v0.10.2 From 7d48935eff401bb7970e73e822871a10e3643df1 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Wed, 12 Feb 2014 23:58:15 -0500 Subject: dm thin: allow metadata space larger than supported to go unused It was always intended that a user could provide a thin metadata device that is larger than the max supported by the on-disk format. The extra space would just go unused. Unfortunately that never worked. If the user attempted to use a larger metadata device on creation they would get an error like the following: device-mapper: space map common: space map too large device-mapper: transaction manager: couldn't create metadata space map device-mapper: thin metadata: tm_create_with_sm failed device-mapper: table: 252:17: thin-pool: Error creating metadata object device-mapper: ioctl: error adding target to table Fix this by allowing the initial metadata space map creation to cap its size at the max number of blocks supported (DM_SM_METADATA_MAX_BLOCKS). get_metadata_dev_size() must also impose DM_SM_METADATA_MAX_BLOCKS (via THIN_METADATA_MAX_SECTORS), otherwise extending metadata would cap at THIN_METADATA_MAX_SECTORS_WARNING (which is larger than supported). Also, the calculation for THIN_METADATA_MAX_SECTORS didn't account for the sizeof the disk_bitmap_header. So the supported maximum metadata size is a bit smaller (reduced from 33423360 to 33292800 sectors). Lastly, remove the "excess space will not be used" warning message from get_metadata_dev_size(); it resulted in printing the warning multiple times. Factor out warn_if_metadata_device_too_big(), call it from pool_ctr() and maybe_resize_metadata_dev(). Signed-off-by: Mike Snitzer Acked-by: Joe Thornber diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 3bb4506..baa87ff 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -483,7 +483,7 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd) disk_super->data_mapping_root = cpu_to_le64(pmd->root); disk_super->device_details_root = cpu_to_le64(pmd->details_root); - disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); + disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE); disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT); disk_super->data_block_size = cpu_to_le32(pmd->data_block_size); @@ -651,7 +651,7 @@ static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool f { int r; - pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE, + pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT, THIN_METADATA_CACHE_SIZE, THIN_MAX_CONCURRENT_LOCKS); if (IS_ERR(pmd->bm)) { diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h index dd6088a..82ea384 100644 --- a/drivers/md/dm-thin-metadata.h +++ b/drivers/md/dm-thin-metadata.h @@ -9,16 +9,14 @@ #include "persistent-data/dm-block-manager.h" #include "persistent-data/dm-space-map.h" +#include "persistent-data/dm-space-map-metadata.h" -#define THIN_METADATA_BLOCK_SIZE 4096 +#define THIN_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE /* * The metadata device is currently limited in size. - * - * We have one block of index, which can hold 255 index entries. Each - * index entry contains allocation info about 16k metadata blocks. */ -#define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT))) +#define THIN_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS /* * A metadata device larger than 16GB triggers a warning. diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 4cf4b19..7e84bac 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2000,16 +2000,27 @@ static void metadata_low_callback(void *context) dm_table_event(pool->ti->table); } -static sector_t get_metadata_dev_size(struct block_device *bdev) +static sector_t get_dev_size(struct block_device *bdev) +{ + return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; +} + +static void warn_if_metadata_device_too_big(struct block_device *bdev) { - sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; + sector_t metadata_dev_size = get_dev_size(bdev); char buffer[BDEVNAME_SIZE]; - if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) { + if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.", bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS); - metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING; - } +} + +static sector_t get_metadata_dev_size(struct block_device *bdev) +{ + sector_t metadata_dev_size = get_dev_size(bdev); + + if (metadata_dev_size > THIN_METADATA_MAX_SECTORS) + metadata_dev_size = THIN_METADATA_MAX_SECTORS; return metadata_dev_size; } @@ -2018,7 +2029,7 @@ static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev) { sector_t metadata_dev_size = get_metadata_dev_size(bdev); - sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); + sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE); return metadata_dev_size; } @@ -2096,12 +2107,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) ti->error = "Error opening metadata block device"; goto out_unlock; } - - /* - * Run for the side-effect of possibly issuing a warning if the - * device is too big. - */ - (void) get_metadata_dev_size(metadata_dev->bdev); + warn_if_metadata_device_too_big(metadata_dev->bdev); r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev); if (r) { @@ -2288,6 +2294,7 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit) return -EINVAL; } else if (metadata_dev_size > sb_metadata_dev_size) { + warn_if_metadata_device_too_big(pool->md_dev); DMINFO("%s: growing the metadata device from %llu to %llu blocks", dm_device_name(pool->pool_md), sb_metadata_dev_size, metadata_dev_size); diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 536782e..e9bdd46 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -680,6 +680,8 @@ int dm_sm_metadata_create(struct dm_space_map *sm, if (r) return r; + if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS) + nr_blocks = DM_SM_METADATA_MAX_BLOCKS; r = sm_ll_extend(&smm->ll, nr_blocks); if (r) return r; diff --git a/drivers/md/persistent-data/dm-space-map-metadata.h b/drivers/md/persistent-data/dm-space-map-metadata.h index 39bba08..64df923 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.h +++ b/drivers/md/persistent-data/dm-space-map-metadata.h @@ -9,6 +9,17 @@ #include "dm-transaction-manager.h" +#define DM_SM_METADATA_BLOCK_SIZE (4096 >> SECTOR_SHIFT) + +/* + * The metadata device is currently limited in size. + * + * We have one block of index, which can hold 255 index entries. Each + * index entry contains allocation info about ~16k metadata blocks. + */ +#define DM_SM_METADATA_MAX_BLOCKS (255 * ((1 << 14) - 64)) +#define DM_SM_METADATA_MAX_SECTORS (DM_SM_METADATA_MAX_BLOCKS * DM_SM_METADATA_BLOCK_SIZE) + /* * Unfortunately we have to use two-phase construction due to the cycle * between the tm and sm. -- cgit v0.10.2 From 724b9e1d75ab3401aaa081bd4efb440c1b3509db Mon Sep 17 00:00:00 2001 From: Hiroaki SHIMODA Date: Wed, 26 Feb 2014 21:43:42 +0900 Subject: sch_tbf: Fix potential memory leak in tbf_change(). The allocated child qdisc is not freed in error conditions. Defer the allocation after user configuration turns out to be valid and acceptable. Fixes: cc106e441a63b ("net: sched: tbf: fix the calculation of max_size") Signed-off-by: Hiroaki SHIMODA Cc: Yang Yingliang Acked-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 1cb413f..4f505a0 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -334,18 +334,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB])); - if (q->qdisc != &noop_qdisc) { - err = fifo_set_limit(q->qdisc, qopt->limit); - if (err) - goto done; - } else if (qopt->limit > 0) { - child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); - if (IS_ERR(child)) { - err = PTR_ERR(child); - goto done; - } - } - buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); @@ -390,6 +378,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) goto done; } + if (q->qdisc != &noop_qdisc) { + err = fifo_set_limit(q->qdisc, qopt->limit); + if (err) + goto done; + } else if (qopt->limit > 0) { + child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); + if (IS_ERR(child)) { + err = PTR_ERR(child); + goto done; + } + } + sch_tree_lock(sch); if (child) { qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); -- cgit v0.10.2 From b20c9f29c5c25921c6ad18b50d4b61e6d181c3cc Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 26 Feb 2014 18:47:36 +0000 Subject: arm/arm64: KVM: detect CPU reset on CPU_PM_EXIT Commit 1fcf7ce0c602 (arm: kvm: implement CPU PM notifier) added support for CPU power-management, using a cpu_notifier to re-init KVM on a CPU that entered CPU idle. The code assumed that a CPU entering idle would actually be powered off, loosing its state entierely, and would then need to be reinitialized. It turns out that this is not always the case, and some HW performs CPU PM without actually killing the core. In this case, we try to reinitialize KVM while it is still live. It ends up badly, as reported by Andre Przywara (using a Calxeda Midway): [ 3.663897] Kernel panic - not syncing: unexpected prefetch abort in Hyp mode at: 0x685760 [ 3.663897] unexpected data abort in Hyp mode at: 0xc067d150 [ 3.663897] unexpected HVC/SVC trap in Hyp mode at: 0xc0901dd0 The trick here is to detect if we've been through a full re-init or not by looking at HVBAR (VBAR_EL2 on arm64). This involves implementing the backend for __hyp_get_vectors in the main KVM HYP code (rather small), and checking the return value against the default one when the CPU notifier is called on CPU_PM_EXIT. Reported-by: Andre Przywara Tested-by: Andre Przywara Cc: Lorenzo Pieralisi Cc: Rob Herring Acked-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Paolo Bonzini diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248e..bd18bb8 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -878,7 +878,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd, void *v) { - if (cmd == CPU_PM_EXIT) { + if (cmd == CPU_PM_EXIT && + __hyp_get_vectors() == hyp_default_vectors) { cpu_init_hyp_mode(NULL); return NOTIFY_OK; } diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S index ddc1553..0d68d40 100644 --- a/arch/arm/kvm/interrupts.S +++ b/arch/arm/kvm/interrupts.S @@ -220,6 +220,10 @@ after_vfp_restore: * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c). Return values are * passed in r0 and r1. * + * A function pointer with a value of 0xffffffff has a special meaning, + * and is used to implement __hyp_get_vectors in the same way as in + * arch/arm/kernel/hyp_stub.S. + * * The calling convention follows the standard AAPCS: * r0 - r3: caller save * r12: caller save @@ -363,6 +367,11 @@ hyp_hvc: host_switch_to_hyp: pop {r0, r1, r2} + /* Check for __hyp_get_vectors */ + cmp r0, #-1 + mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR + beq 1f + push {lr} mrs lr, SPSR push {lr} @@ -378,7 +387,7 @@ THUMB( orr lr, #1) pop {lr} msr SPSR_csxf, lr pop {lr} - eret +1: eret guest_trap: load_vcpu @ Load VCPU pointer to r0 diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S index 3b47c36..2c56012 100644 --- a/arch/arm64/kvm/hyp.S +++ b/arch/arm64/kvm/hyp.S @@ -694,6 +694,24 @@ __hyp_panic_str: .align 2 +/* + * u64 kvm_call_hyp(void *hypfn, ...); + * + * This is not really a variadic function in the classic C-way and care must + * be taken when calling this to ensure parameters are passed in registers + * only, since the stack will change between the caller and the callee. + * + * Call the function with the first argument containing a pointer to the + * function you wish to call in Hyp mode, and subsequent arguments will be + * passed as x0, x1, and x2 (a maximum of 3 arguments in addition to the + * function pointer can be passed). The function being called must be mapped + * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c). Return values are + * passed in r0 and r1. + * + * A function pointer with a value of 0 has a special meaning, and is + * used to implement __hyp_get_vectors in the same way as in + * arch/arm64/kernel/hyp_stub.S. + */ ENTRY(kvm_call_hyp) hvc #0 ret @@ -737,7 +755,12 @@ el1_sync: // Guest trapped into EL2 pop x2, x3 pop x0, x1 - push lr, xzr + /* Check for __hyp_get_vectors */ + cbnz x0, 1f + mrs x0, vbar_el2 + b 2f + +1: push lr, xzr /* * Compute the function address in EL2, and shuffle the parameters. @@ -750,7 +773,7 @@ el1_sync: // Guest trapped into EL2 blr lr pop lr, xzr - eret +2: eret el1_trap: /* -- cgit v0.10.2 From a08d3b3b99efd509133946056531cdf8f3a0c09b Mon Sep 17 00:00:00 2001 From: Andrew Honig Date: Thu, 27 Feb 2014 19:35:14 +0100 Subject: kvm: x86: fix emulator buffer overflow (CVE-2014-0049) The problem occurs when the guest performs a pusha with the stack address pointing to an mmio address (or an invalid guest physical address) to start with, but then extending into an ordinary guest physical address. When doing repeated emulated pushes emulator_read_write sets mmio_needed to 1 on the first one. On a later push when the stack points to regular memory, mmio_nr_fragments is set to 0, but mmio_is_needed is not set to 0. As a result, KVM exits to userspace, and then returns to complete_emulated_mmio. In complete_emulated_mmio vcpu->mmio_cur_fragment is incremented. The termination condition of vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments is never achieved. The code bounces back and fourth to userspace incrementing mmio_cur_fragment past it's buffer. If the guest does nothing else it eventually leads to a a crash on a memcpy from invalid memory address. However if a guest code can cause the vm to be destroyed in another vcpu with excellent timing, then kvm_clear_async_pf_completion_queue can be used by the guest to control the data that's pointed to by the call to cancel_work_item, which can be used to gain execution. Fixes: f78146b0f9230765c6315b2e14f56112513389ad Signed-off-by: Andrew Honig Cc: stable@vger.kernel.org (3.5+) Signed-off-by: Paolo Bonzini diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 39c28f09..2b85784 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6186,7 +6186,7 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu) frag->len -= len; } - if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) { + if (vcpu->mmio_cur_fragment >= vcpu->mmio_nr_fragments) { vcpu->mmio_needed = 0; /* FIXME: return into emulator if single-stepping. */ -- cgit v0.10.2 From 9f050c7f9738ffa746c63415136645ad231b1348 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 20 Feb 2014 09:16:01 -0500 Subject: drm/radeon: print the supported atpx function mask Print the supported functions mask in addition to the version. This is useful in debugging PX problems since we can see what functions are available. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 485848f..fa9a9c0 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -219,7 +219,8 @@ static int radeon_atpx_verify_interface(struct radeon_atpx *atpx) memcpy(&output, info->buffer.pointer, size); /* TODO: check version? */ - printk("ATPX version %u\n", output.version); + printk("ATPX version %u, functions 0x%08x\n", + output.version, output.function_bits); radeon_atpx_parse_functions(&atpx->functions, output.function_bits); -- cgit v0.10.2 From 5e386b574cf7e1593e1296e5b0feea4108ed6ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 20 Feb 2014 18:47:14 +0100 Subject: drm/radeon: fix missing bo reservation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we might get a crash here. Signed-off-by: Christian König Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 114d167..2aecd6d 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -537,6 +537,10 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) radeon_vm_init(rdev, &fpriv->vm); + r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); + if (r) + return r; + /* map the ib pool buffer read only into * virtual address space */ bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, @@ -544,6 +548,8 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, RADEON_VM_PAGE_READABLE | RADEON_VM_PAGE_SNOOPED); + + radeon_bo_unreserve(rdev->ring_tmp_bo.bo); if (r) { radeon_vm_fini(rdev, &fpriv->vm); kfree(fpriv); -- cgit v0.10.2 From 9ef4e1d000a5b335fcebfcf8aef3405e59574c89 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Feb 2014 10:21:43 -0500 Subject: drm/radeon: disable pll sharing for DP on DCE4.1 Causes display problems. We had already disabled sharing for non-DP displays. Based on a patch from: Niels Ole Salscheider bug: https://bugzilla.kernel.org/show_bug.cgi?id=58121 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 0d19f4f..daa4dd3 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1774,6 +1774,20 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) return ATOM_PPLL1; DRM_ERROR("unable to allocate a PPLL\n"); return ATOM_PPLL_INVALID; + } else if (ASIC_IS_DCE41(rdev)) { + /* Don't share PLLs on DCE4.1 chips */ + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { + if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ + return ATOM_PPLL_INVALID; + } + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; } else if (ASIC_IS_DCE4(rdev)) { /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, * depending on the asic: @@ -1801,7 +1815,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) if (pll != ATOM_PPLL_INVALID) return pll; } - } else if (!ASIC_IS_DCE41(rdev)) { /* Don't share PLLs on DCE4.1 chips */ + } else { /* use the same PPLL for all monitors with the same clock */ pll = radeon_get_shared_nondp_ppll(crtc); if (pll != ATOM_PPLL_INVALID) -- cgit v0.10.2 From d965441342f3b7d63db784cad852328d17d47942 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 26 Feb 2014 19:22:47 -0500 Subject: drm/radeon: free uvd ring on unload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to free the uvd ring. Also reshuffle gart tear down to happen after uvd tear down. Signed-off-by: Jérôme Glisse Cc: stable@vger.kernel.org Reviewed-by: Christian König Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 5623e75..8a2c010 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -5475,9 +5475,9 @@ void evergreen_fini(struct radeon_device *rdev) radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); - evergreen_pcie_gart_fini(rdev); uvd_v1_0_fini(rdev); radeon_uvd_fini(rdev); + evergreen_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 6781fee..3e6804b 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -171,6 +171,8 @@ void radeon_uvd_fini(struct radeon_device *rdev) radeon_bo_unref(&rdev->uvd.vcpu_bo); + radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]); + release_firmware(rdev->uvd_fw); } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 6c772e5..4e37a42 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1955,9 +1955,9 @@ void rv770_fini(struct radeon_device *rdev) radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); - rv770_pcie_gart_fini(rdev); uvd_v1_0_fini(rdev); radeon_uvd_fini(rdev); + rv770_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); -- cgit v0.10.2 From d7eb0a0940618f36e5937d81c06ad7bf438a99e2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 10:25:39 -0500 Subject: drm/radeon: fix audio disable on dce6+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly clear the enable bit when audio disable is requested. Signed-off-by: Alex Deucher Reviewed-by: Christian König Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 713a5d3..36e8f10 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -283,7 +283,7 @@ static void dce6_audio_enable(struct radeon_device *rdev, bool enable) { WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL, - AUDIO_ENABLED); + enable ? AUDIO_ENABLED : 0); DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id); } -- cgit v0.10.2 From 832eafaf34ff7d0348fe701e417900c6cf1f5656 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 11:07:55 -0500 Subject: drm/radeon: change audio enable logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable audio around audio hw setup. This may avoid hangs on certain asics. Signed-off-by: Alex Deucher Reviewed-by: Christian König diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 36e8f10..94e8587 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -278,13 +278,15 @@ static int dce6_audio_chipset_supported(struct radeon_device *rdev) return !ASIC_IS_NODCE(rdev); } -static void dce6_audio_enable(struct radeon_device *rdev, - struct r600_audio_pin *pin, - bool enable) +void dce6_audio_enable(struct radeon_device *rdev, + struct r600_audio_pin *pin, + bool enable) { + if (!pin) + return; + WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL, enable ? AUDIO_ENABLED : 0); - DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id); } static const u32 pin_offsets[7] = @@ -323,7 +325,8 @@ int dce6_audio_init(struct radeon_device *rdev) rdev->audio.pin[i].connected = false; rdev->audio.pin[i].offset = pin_offsets[i]; rdev->audio.pin[i].id = i; - dce6_audio_enable(rdev, &rdev->audio.pin[i], true); + /* disable audio. it will be set up later */ + dce6_audio_enable(rdev, &rdev->audio.pin[i], false); } return 0; diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 0c6d5ce..05b0c95 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -306,6 +306,15 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode return; offset = dig->afmt->offset; + /* disable audio prior to setting up hw */ + if (ASIC_IS_DCE6(rdev)) { + dig->afmt->pin = dce6_audio_get_pin(rdev); + dce6_audio_enable(rdev, dig->afmt->pin, false); + } else { + dig->afmt->pin = r600_audio_get_pin(rdev); + r600_audio_enable(rdev, dig->afmt->pin, false); + } + evergreen_audio_set_dto(encoder, mode->clock); WREG32(HDMI_VBI_PACKET_CONTROL + offset, @@ -409,12 +418,16 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001); WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001); + + /* enable audio after to setting up hw */ + if (ASIC_IS_DCE6(rdev)) + dce6_audio_enable(rdev, dig->afmt->pin, true); + else + r600_audio_enable(rdev, dig->afmt->pin, true); } void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) { - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; @@ -427,15 +440,6 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) if (!enable && !dig->afmt->enabled) return; - if (enable) { - if (ASIC_IS_DCE6(rdev)) - dig->afmt->pin = dce6_audio_get_pin(rdev); - else - dig->afmt->pin = r600_audio_get_pin(rdev); - } else { - dig->afmt->pin = NULL; - } - dig->afmt->enabled = enable; DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index 47fc2b8..bffac10 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -142,12 +142,15 @@ void r600_audio_update_hdmi(struct work_struct *work) } /* enable the audio stream */ -static void r600_audio_enable(struct radeon_device *rdev, - struct r600_audio_pin *pin, - bool enable) +void r600_audio_enable(struct radeon_device *rdev, + struct r600_audio_pin *pin, + bool enable) { u32 value = 0; + if (!pin) + return; + if (ASIC_IS_DCE4(rdev)) { if (enable) { value |= 0x81000000; /* Required to enable audio */ @@ -158,7 +161,6 @@ static void r600_audio_enable(struct radeon_device *rdev, WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000); } - DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id); } /* @@ -178,8 +180,8 @@ int r600_audio_init(struct radeon_device *rdev) rdev->audio.pin[0].status_bits = 0; rdev->audio.pin[0].category_code = 0; rdev->audio.pin[0].id = 0; - - r600_audio_enable(rdev, &rdev->audio.pin[0], true); + /* disable audio. it will be set up later */ + r600_audio_enable(rdev, &rdev->audio.pin[0], false); return 0; } diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 3016fc1..ec810cd 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -460,6 +460,10 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod return; offset = dig->afmt->offset; + /* disable audio prior to setting up hw */ + dig->afmt->pin = r600_audio_get_pin(rdev); + r600_audio_enable(rdev, dig->afmt->pin, false); + r600_audio_set_dto(encoder, mode->clock); WREG32(HDMI0_VBI_PACKET_CONTROL + offset, @@ -531,6 +535,9 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); r600_hdmi_audio_workaround(encoder); + + /* enable audio after to setting up hw */ + r600_audio_enable(rdev, dig->afmt->pin, true); } /* @@ -651,11 +658,6 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable) if (!enable && !dig->afmt->enabled) return; - if (enable) - dig->afmt->pin = r600_audio_get_pin(rdev); - else - dig->afmt->pin = NULL; - /* Older chipsets require setting HDMI and routing manually */ if (!ASIC_IS_DCE3(rdev)) { if (enable) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 024db37..e887d02 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2747,6 +2747,12 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, void r600_audio_update_hdmi(struct work_struct *work); struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev); struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev); +void r600_audio_enable(struct radeon_device *rdev, + struct r600_audio_pin *pin, + bool enable); +void dce6_audio_enable(struct radeon_device *rdev, + struct r600_audio_pin *pin, + bool enable); /* * R600 vram scratch functions -- cgit v0.10.2 From 3803c8e5b50946dd6bc18972d9190757d05648f0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 11:12:11 -0500 Subject: drm/radeon: enable speaker allocation setup on dce3.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we disable audio while setting up the audio hw, we should be able to set this up without hangs. Signed-off-by: Alex Deucher Reviewed-by: Christian König diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index ec810cd..85a2bb2 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -329,9 +329,6 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) u8 *sadb; int sad_count; - /* XXX: setting this register causes hangs on some asics */ - return; - list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { if (connector->encoder == encoder) { radeon_connector = to_radeon_connector(connector); -- cgit v0.10.2 From cb664981607a6b5b3d670ad57bbda893b2528d96 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 27 Feb 2014 20:47:53 +0100 Subject: mac80211: fix association to 20/40 MHz VHT networks When a VHT network uses 20 or 40 MHz as per the HT operation information, the channel center frequency segment 0 field in the VHT operation information is reserved, so ignore it. This fixes association with such networks when the AP puts 0 into the field, previously we'd disconnect due to an invalid channel with the message wlan0: AP VHT information is invalid, disable VHT Cc: stable@vger.kernel.org Fixes: f2d9d270c15ae ("mac80211: support VHT association") Reported-by: Tim Nelson Signed-off-by: Johannes Berg diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c415f00..245dce9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, switch (vht_oper->chan_width) { case IEEE80211_VHT_CHANWIDTH_USE_HT: vht_chandef.width = chandef->width; + vht_chandef.center_freq1 = chandef->center_freq1; break; case IEEE80211_VHT_CHANWIDTH_80MHZ: vht_chandef.width = NL80211_CHAN_WIDTH_80; -- cgit v0.10.2 From bf439b3154ce49d81a79b14f9fab18af99018ae2 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 27 Feb 2014 13:38:26 +0900 Subject: net: ipv6: ping: Use socket mark in routing lookup Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index fb9beb7..587bbdc 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -135,6 +135,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, fl6.flowi6_proto = IPPROTO_ICMPV6; fl6.saddr = np->saddr; fl6.daddr = *daddr; + fl6.flowi6_mark = sk->sk_mark; fl6.fl6_icmp_type = user_icmph.icmp6_type; fl6.fl6_icmp_code = user_icmph.icmp6_code; security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); -- cgit v0.10.2 From 280e7c48c3b873e4987a63da276ecab25383f494 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 11 Jan 2014 11:42:51 -0800 Subject: perf tools: fix BFD detection on opensuse opensuse libbfd requires -lz -liberty to build. Add those to the BFD feature detection. Signed-off-by: Andi Kleen Acked-by: David Ahern Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1389469379-13340-2-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index c48d449..0331ea2 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -478,7 +478,7 @@ else endif ifeq ($(feature-libbfd), 1) - EXTLIBS += -lbfd + EXTLIBS += -lbfd -lz -liberty endif ifdef NO_DEMANGLE diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile index 12e5513..523b7bc 100644 --- a/tools/perf/config/feature-checks/Makefile +++ b/tools/perf/config/feature-checks/Makefile @@ -121,7 +121,7 @@ test-libpython-version.bin: $(BUILD) $(FLAGS_PYTHON_EMBED) test-libbfd.bin: - $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl + $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl test-liberty.bin: $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -- cgit v0.10.2 From 1b385cbdd74aa803e966e01e5fe49490d6044e30 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Feb 2014 22:54:11 +0100 Subject: kvm, vmx: Really fix lazy FPU on nested guest Commit e504c9098ed6 (kvm, vmx: Fix lazy FPU on nested guest, 2013-11-13) highlighted a real problem, but the fix was subtly wrong. nested_read_cr0 is the CR0 as read by L2, but here we want to look at the CR0 value reflecting L1's setup. In other words, L2 might think that TS=0 (so nested_read_cr0 has the bit clear); but if L1 is actually running it with TS=1, we should inject the fault into L1. The effective value of CR0 in L2 is contained in vmcs12->guest_cr0, use it. Fixes: e504c9098ed6acd9e1079c5e10e4910724ad429f Reported-by: Kashyap Chamarty Reported-by: Stefan Bader Tested-by: Kashyap Chamarty Tested-by: Anthoine Bourgeois Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a06f101..3927528 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -6688,7 +6688,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) else if (is_page_fault(intr_info)) return enable_ept; else if (is_no_device(intr_info) && - !(nested_read_cr0(vmcs12) & X86_CR0_TS)) + !(vmcs12->guest_cr0 & X86_CR0_TS)) return 0; return vmcs12->exception_bitmap & (1u << (intr_info & INTR_INFO_VECTOR_MASK)); -- cgit v0.10.2 From babe723d6d733a1045bb44ab82fbe27bdfa2bff8 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Thu, 27 Feb 2014 15:42:26 +0200 Subject: bnx2x: Add missing bit in default Tx switching Commit c14db2025 "bnx2x: Correct default Tx switching behaviour" supposedly changed the default Tx switching behaviour, but was missing the fastpath change required for FW to pass packets from PFs to VFs. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 66c0df7..dbcff50 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -3875,7 +3875,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) xmit_type); } - /* Add the macs to the parsing BD this is a vf */ + /* Add the macs to the parsing BD if this is a vf or if + * Tx Switching is enabled. + */ if (IS_VF(bp)) { /* override GRE parameters in BD */ bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.src_hi, @@ -3887,6 +3889,11 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) &pbd_e2->data.mac_addr.dst_mid, &pbd_e2->data.mac_addr.dst_lo, eth->h_dest); + } else if (bp->flags & TX_SWITCHING) { + bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.dst_hi, + &pbd_e2->data.mac_addr.dst_mid, + &pbd_e2->data.mac_addr.dst_lo, + eth->h_dest); } SET_FLAG(pbd_e2_parsing_data, -- cgit v0.10.2 From feff9ab2e7fa773b6a3965f77375fe89f7fd85cf Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Thu, 27 Feb 2014 17:14:41 +0800 Subject: neigh: recompute reachabletime before returning from neigh_periodic_work() If the neigh table's entries is less than gc_thresh1, the function will return directly, and the reachabletime will not be recompute, so the reachabletime can be guessed. Signed-off-by: Duan Jiong Signed-off-by: David S. Miller diff --git a/net/core/neighbour.c b/net/core/neighbour.c index e1aa0f3..e161290 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -766,9 +766,6 @@ static void neigh_periodic_work(struct work_struct *work) nht = rcu_dereference_protected(tbl->nht, lockdep_is_held(&tbl->lock)); - if (atomic_read(&tbl->entries) < tbl->gc_thresh1) - goto out; - /* * periodically recompute ReachableTime from random function */ @@ -781,6 +778,9 @@ static void neigh_periodic_work(struct work_struct *work) neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); } + if (atomic_read(&tbl->entries) < tbl->gc_thresh1) + goto out; + for (i = 0 ; i < (1 << nht->hash_shift); i++) { np = &nht->hash_buckets[i]; -- cgit v0.10.2 From accfe0e356327da5bd53da8852b93fc22de9b5fc Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Thu, 27 Feb 2014 12:57:58 +0100 Subject: ipv6: ipv6_find_hdr restore prev functionality The commit 9195bb8e381d81d5a315f911904cdf0cfcc919b8 ("ipv6: improve ipv6_find_hdr() to skip empty routing headers") broke ipv6_find_hdr(). When a target is specified like IPPROTO_ICMPV6 ipv6_find_hdr() returns -ENOENT when it's found, not the header as expected. A part of IPVS is broken and possible also nft_exthdr_eval(). When target is -1 which it is most cases, it works. This patch exits the do while loop if the specific header is found so the nexthdr could be returned as expected. Reported-by: Art -kwaak- van Breemen Signed-off-by: Hans Schillstrom CC:Ansis Atteka Signed-off-by: David S. Miller diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 140748d..8af3eb5 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -212,7 +212,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, found = (nexthdr == target); if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { - if (target < 0) + if (target < 0 || found) break; return -ENOENT; } -- cgit v0.10.2 From 4b41636878ee32d4c45a49de7749abca9721bd6a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 27 Feb 2014 15:35:48 -0800 Subject: ARM: OMAP3: Fix pinctrl interrupts for core2 After splitting padconf core into two parts to avoid exposing unaccessable registers, the new padconf core2 domain was left without a wake-up interrupt. Fix the issue by passing the shared wake-up interrupt in platform data like we do for padconf core and wkup domains already. Fixes: 3d49538364 (ARM: dts: Split omap3 pinmux core device) Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 0cc710d..c33e07e 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -257,6 +257,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { #endif #ifdef CONFIG_ARCH_OMAP3 OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002030, "48002030.pinmux", &pcs_pdata), + OF_DEV_AUXDATA("ti,omap3-padconf", 0x480025a0, "480025a0.pinmux", &pcs_pdata), OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002a00, "48002a00.pinmux", &pcs_pdata), /* Only on am3517 */ OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL), -- cgit v0.10.2 From f687d900d30a61dda38db2a99239f5284a86a309 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 27 Feb 2014 18:25:24 -0800 Subject: ASoC: simple-card: cpu_dai_name creates confusion when DT case Basically, soc_bind_dai_link() checks cpu_dai->dev->of_node and dai_link->cpu_of_node in DT case. But after that it will check cpu_dai->name and dai_link->cpu_dai_name too. On the other hand, snd_soc_dai :: name is created by fmt_single_name() or fmt_multiple_name(). There is no confusion if dai name is created by fmt_multiple_name(), since cpu_dai->name is same as dai_link->cpu_dai_name. but, if dai name is created by fmt_single_name(), CPU DAI never match. Thus, simple-card not set dai_link->cpu_dai_name if DT case to skip naming match on soc_bind_dai_link() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index bdd176d..034a2b7 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -234,6 +234,17 @@ static int asoc_simple_card_parse_of(struct device_node *node, priv->codec_dai.fmt, priv->codec_dai.sysclk); + /* + * soc_bind_dai_link() will check cpu name + * after of_node matching if dai_link has cpu_dai_name. + * but, it will never match if name was created by fmt_single_name() + * remove cpu_dai_name to escape name matching. + * see + * fmt_single_name() + * fmt_multiple_name() + */ + dai_link->cpu_dai_name = NULL; + return 0; } -- cgit v0.10.2 From fd40dccb1a170ba689664481a3de83617b7194d2 Mon Sep 17 00:00:00 2001 From: Philippe De Muyter Date: Thu, 27 Feb 2014 10:16:15 +0100 Subject: spi: spi-imx: spi_imx_remove: do not disable disabled clocks Currently, at module removal, one gets the following warnings: ------------[ cut here ]------------ WARNING: at drivers/clk/clk.c:780 clk_disable+0x18/0x24() Modules linked in: spi_imx(-) [last unloaded: ev76c560] CPU: 1 PID: 16337 Comm: rmmod Tainted: G W 3.10.17-80548-g90191eb-dirty #33 [<80013b4c>] (unwind_backtrace+0x0/0xf8) from [<800115dc>] (show_stack+0x10/0x14) [<800115dc>] (show_stack+0x10/0x14) from [<800257b8>] (warn_slowpath_common+0x4c/0x68) [<800257b8>] (warn_slowpath_common+0x4c/0x68) from [<800257f0>] (warn_slowpath_null+0x1c/0x24) [<800257f0>] (warn_slowpath_null+0x1c/0x24) from [<803f60ec>] (clk_disable+0x18/0x24) [<803f60ec>] (clk_disable+0x18/0x24) from [<7f02c9cc>] (spi_imx_remove+0x54/0x9c [spi_imx]) [<7f02c9cc>] (spi_imx_remove+0x54/0x9c [spi_imx]) from [<8025868c>] (platform_drv_remove+0x18/0x1c) [<8025868c>] (platform_drv_remove+0x18/0x1c) from [<80256f60>] (__device_release_driver+0x70/0xcc) [<80256f60>] (__device_release_driver+0x70/0xcc) from [<80257770>] (driver_detach+0xcc/0xd0) [<80257770>] (driver_detach+0xcc/0xd0) from [<80256d90>] (bus_remove_driver+0x7c/0xc0) [<80256d90>] (bus_remove_driver+0x7c/0xc0) from [<80068668>] (SyS_delete_module+0x144/0x1f8) [<80068668>] (SyS_delete_module+0x144/0x1f8) from [<8000e080>] (ret_fast_syscall+0x0/0x30) ---[ end trace 1f5df9ad54996300 ]--- ------------[ cut here ]------------ WARNING: at drivers/clk/clk.c:780 clk_disable+0x18/0x24() Modules linked in: spi_imx(-) [last unloaded: ev76c560] CPU: 1 PID: 16337 Comm: rmmod Tainted: G W 3.10.17-80548-g90191eb-dirty #33 [<80013b4c>] (unwind_backtrace+0x0/0xf8) from [<800115dc>] (show_stack+0x10/0x14) [<800115dc>] (show_stack+0x10/0x14) from [<800257b8>] (warn_slowpath_common+0x4c/0x68) [<800257b8>] (warn_slowpath_common+0x4c/0x68) from [<800257f0>] (warn_slowpath_null+0x1c/0x24) [<800257f0>] (warn_slowpath_null+0x1c/0x24) from [<803f60ec>] (clk_disable+0x18/0x24) [<803f60ec>] (clk_disable+0x18/0x24) from [<7f02c9e8>] (spi_imx_remove+0x70/0x9c [spi_imx]) [<7f02c9e8>] (spi_imx_remove+0x70/0x9c [spi_imx]) from [<8025868c>] (platform_drv_remove+0x18/0x1c) [<8025868c>] (platform_drv_remove+0x18/0x1c) from [<80256f60>] (__device_release_driver+0x70/0xcc) [<80256f60>] (__device_release_driver+0x70/0xcc) from [<80257770>] (driver_detach+0xcc/0xd0) [<80257770>] (driver_detach+0xcc/0xd0) from [<80256d90>] (bus_remove_driver+0x7c/0xc0) [<80256d90>] (bus_remove_driver+0x7c/0xc0) from [<80068668>] (SyS_delete_module+0x144/0x1f8) [<80068668>] (SyS_delete_module+0x144/0x1f8) from [<8000e080>] (ret_fast_syscall+0x0/0x30) ---[ end trace 1f5df9ad54996301 ]--- Since commit 9e556dcc55774c9a1032f32baa0e5cfafede8b70, "spi: spi-imx: only enable the clocks when we start to transfer a message", clocks are always disabled except when transmitting messages. There is thus no need to disable them at module removal. Fixes: 9e556dcc55774 (spi: spi-imx: only enable the clocks when we start to transfer a message) Signed-off-by: Philippe De Muyter Acked-by: Huang Shijie Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index a5474ef..47f15d9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -948,8 +948,8 @@ static int spi_imx_remove(struct platform_device *pdev) spi_bitbang_stop(&spi_imx->bitbang); writel(0, spi_imx->base + MXC_CSPICTRL); - clk_disable_unprepare(spi_imx->clk_ipg); - clk_disable_unprepare(spi_imx->clk_per); + clk_unprepare(spi_imx->clk_ipg); + clk_unprepare(spi_imx->clk_per); spi_master_put(master); return 0; -- cgit v0.10.2 From 41dd03a94c7d408d2ef32530545097f7d1befe5c Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Thu, 20 Feb 2014 21:13:52 +1100 Subject: powerpc/le: Ensure that the 'stop-self' RTAS token is handled correctly Currently we're storing a host endian RTAS token in rtas_stop_self_args.token. We then pass that directly to rtas. This is fine on big endian however on little endian the token is not what we expect. This will typically result in hitting: panic("Alas, I survived.\n"); To fix this we always use the stop-self token in host order and always convert it to be32 before passing this to rtas. Signed-off-by: Tony Breeds Cc: stable@vger.kernel.org Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 82789e7..0ea99e3 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -35,12 +35,7 @@ #include "offline_states.h" /* This version can't take the spinlock, because it never returns */ -static struct rtas_args rtas_stop_self_args = { - .token = RTAS_UNKNOWN_SERVICE, - .nargs = 0, - .nret = 1, - .rets = &rtas_stop_self_args.args[0], -}; +static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE; static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) = CPU_STATE_OFFLINE; @@ -93,15 +88,20 @@ void set_default_offline_state(int cpu) static void rtas_stop_self(void) { - struct rtas_args *args = &rtas_stop_self_args; + struct rtas_args args = { + .token = cpu_to_be32(rtas_stop_self_token), + .nargs = 0, + .nret = 1, + .rets = &args.args[0], + }; local_irq_disable(); - BUG_ON(args->token == RTAS_UNKNOWN_SERVICE); + BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE); printk("cpu %u (hwid %u) Ready to die...\n", smp_processor_id(), hard_smp_processor_id()); - enter_rtas(__pa(args)); + enter_rtas(__pa(&args)); panic("Alas, I survived.\n"); } @@ -392,10 +392,10 @@ static int __init pseries_cpu_hotplug_init(void) } } - rtas_stop_self_args.token = rtas_token("stop-self"); + rtas_stop_self_token = rtas_token("stop-self"); qcss_tok = rtas_token("query-cpu-stopped-state"); - if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE || + if (rtas_stop_self_token == RTAS_UNKNOWN_SERVICE || qcss_tok == RTAS_UNKNOWN_SERVICE) { printk(KERN_INFO "CPU Hotplug not supported by firmware " "- disabling.\n"); -- cgit v0.10.2 From f5295bd8ea8a65dc5eac608b151386314cb978f1 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Mon, 24 Feb 2014 17:30:55 +0100 Subject: powerpc/crashdump : Fix page frame number check in copy_oldmem_page In copy_oldmem_page, the current check using max_pfn and min_low_pfn to decide if the page is backed or not, is not valid when the memory layout is not continuous. This happens when running as a QEMU/KVM guest, where RTAS is mapped higher in the memory. In that case max_pfn points to the end of RTAS, and a hole between the end of the kdump kernel and RTAS is not backed by PTEs. As a consequence, the kdump kernel is crashing in copy_oldmem_page when accessing in a direct way the pages in that hole. This fix relies on the memblock's service memblock_is_region_memory to check if the read page is part or not of the directly accessible memory. Signed-off-by: Laurent Dufour Tested-by: Mahesh Salgaonkar CC: Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 11c1d06..7a13f37 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -98,17 +98,19 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize, unsigned long offset, int userbuf) { void *vaddr; + phys_addr_t paddr; if (!csize) return 0; csize = min_t(size_t, csize, PAGE_SIZE); + paddr = pfn << PAGE_SHIFT; - if ((min_low_pfn < pfn) && (pfn < max_pfn)) { - vaddr = __va(pfn << PAGE_SHIFT); + if (memblock_is_region_memory(paddr, csize)) { + vaddr = __va(paddr); csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); } else { - vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0); + vaddr = __ioremap(paddr, PAGE_SIZE, 0); csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); iounmap(vaddr); } -- cgit v0.10.2 From a95fc58549e8f462e560868a16b1fa97b12d5db6 Mon Sep 17 00:00:00 2001 From: Liu Ping Fan Date: Wed, 26 Feb 2014 10:23:01 +0800 Subject: powerpc/ftrace: bugfix for test_24bit_addr The branch target should be the func addr, not the addr of func_descr_t. So using ppc_function_entry() to generate the right target addr. Signed-off-by: Liu Ping Fan Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 9b27b29..b0ded97 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -74,6 +74,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new) */ static int test_24bit_addr(unsigned long ip, unsigned long addr) { + addr = ppc_function_entry((void *)addr); /* use the create_branch to verify that this offset can be branched */ return create_branch((unsigned int *)ip, addr, 0); -- cgit v0.10.2 From 573ebfa6601fa58b439e7f15828762839ccd306a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 26 Feb 2014 17:07:38 +1100 Subject: powerpc: Increase stack redzone for 64-bit userspace to 512 bytes The new ELFv2 little-endian ABI increases the stack redzone -- the area below the stack pointer that can be used for storing data -- from 288 bytes to 512 bytes. This means that we need to allow more space on the user stack when delivering a signal to a 64-bit process. To make the code a bit clearer, we define new USER_REDZONE_SIZE and KERNEL_REDZONE_SIZE symbols in ptrace.h. For now, we leave the kernel redzone size at 288 bytes, since increasing it to 512 bytes would increase the size of interrupt stack frames correspondingly. Gcc currently only makes use of 288 bytes of redzone even when compiling for the new little-endian ABI, and the kernel cannot currently be compiled with the new ABI anyway. In the future, hopefully gcc will provide an option to control the amount of redzone used, and then we could reduce it even more. This also changes the code in arch_compat_alloc_user_space() to preserve the expanded redzone. It is not clear why this function would ever be used on a 64-bit process, though. Signed-off-by: Paul Mackerras CC: [v3.13] Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 84fdf68..a613d2c 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -200,10 +200,11 @@ static inline void __user *arch_compat_alloc_user_space(long len) /* * We can't access below the stack pointer in the 32bit ABI and - * can access 288 bytes in the 64bit ABI + * can access 288 bytes in the 64bit big-endian ABI, + * or 512 bytes with the new ELFv2 little-endian ABI. */ if (!is_32bit_task()) - usp -= 288; + usp -= USER_REDZONE_SIZE; return (void __user *) (usp - len); } diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index becc08e..279b80f 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -28,11 +28,23 @@ #ifdef __powerpc64__ +/* + * Size of redzone that userspace is allowed to use below the stack + * pointer. This is 288 in the 64-bit big-endian ELF ABI, and 512 in + * the new ELFv2 little-endian ABI, so we allow the larger amount. + * + * For kernel code we allow a 288-byte redzone, in order to conserve + * kernel stack space; gcc currently only uses 288 bytes, and will + * hopefully allow explicit control of the redzone size in future. + */ +#define USER_REDZONE_SIZE 512 +#define KERNEL_REDZONE_SIZE 288 + #define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ #define STACK_FRAME_LR_SAVE 2 /* Location of LR in stack frame */ #define STACK_FRAME_REGS_MARKER ASM_CONST(0x7265677368657265) #define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + \ - STACK_FRAME_OVERHEAD + 288) + STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE) #define STACK_FRAME_MARKER 12 /* Size of dummy stack frame allocated when calling signal handler. */ @@ -41,6 +53,8 @@ #else /* __powerpc64__ */ +#define USER_REDZONE_SIZE 0 +#define KERNEL_REDZONE_SIZE 0 #define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */ #define STACK_FRAME_LR_SAVE 1 /* Location of LR in stack frame */ #define STACK_FRAME_REGS_MARKER ASM_CONST(0x72656773) diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index e35bf77..8d253c2 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -65,8 +65,8 @@ struct rt_sigframe { struct siginfo __user *pinfo; void __user *puc; struct siginfo info; - /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ - char abigap[288]; + /* New 64 bit little-endian ABI allows redzone of 512 bytes below sp */ + char abigap[USER_REDZONE_SIZE]; } __attribute__ ((aligned (16))); static const char fmt32[] = KERN_INFO \ -- cgit v0.10.2 From 947166043732b69878123bf31f51933ad0316080 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 25 Feb 2014 15:28:37 +0800 Subject: powerpc/powernv: Dump PHB diag-data immediately The PHB diag-data is important to help locating the root cause for EEH errors such as frozen PE or fenced PHB. However, the EEH core enables IO path by clearing part of HW registers before collecting this data causing it to be corrupted. This patch fixes this by dumping the PHB diag-data immediately when frozen/fenced state on PE or PHB is detected for the first time in eeh_ops::get_state() or next_error() backend. Signed-off-by: Gavin Shan CC: Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index f514743..253fefe 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -114,6 +114,7 @@ DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_dbgfs_ops, ioda_eeh_inbB_dbgfs_get, ioda_eeh_inbB_dbgfs_set, "0x%llx\n"); #endif /* CONFIG_DEBUG_FS */ + /** * ioda_eeh_post_init - Chip dependent post initialization * @hose: PCI controller @@ -221,6 +222,22 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option) return ret; } +static void ioda_eeh_phb_diag(struct pci_controller *hose) +{ + struct pnv_phb *phb = hose->private_data; + long rc; + + rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, + PNV_PCI_DIAG_BUF_SIZE); + if (rc != OPAL_SUCCESS) { + pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n", + __func__, hose->global_number, rc); + return; + } + + pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); +} + /** * ioda_eeh_get_state - Retrieve the state of PE * @pe: EEH PE @@ -272,6 +289,9 @@ static int ioda_eeh_get_state(struct eeh_pe *pe) result |= EEH_STATE_DMA_ACTIVE; result |= EEH_STATE_MMIO_ENABLED; result |= EEH_STATE_DMA_ENABLED; + } else if (!(pe->state & EEH_PE_ISOLATED)) { + eeh_pe_state_mark(pe, EEH_PE_ISOLATED); + ioda_eeh_phb_diag(hose); } return result; @@ -315,6 +335,15 @@ static int ioda_eeh_get_state(struct eeh_pe *pe) __func__, fstate, hose->global_number, pe_no); } + /* Dump PHB diag-data for frozen PE */ + if (result != EEH_STATE_NOT_SUPPORT && + (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) != + (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) && + !(pe->state & EEH_PE_ISOLATED)) { + eeh_pe_state_mark(pe, EEH_PE_ISOLATED); + ioda_eeh_phb_diag(hose); + } + return result; } @@ -530,42 +559,6 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) } /** - * ioda_eeh_get_log - Retrieve error log - * @pe: EEH PE - * @severity: Severity level of the log - * @drv_log: buffer to store the log - * @len: space of the log buffer - * - * The function is used to retrieve error log from P7IOC. - */ -static int ioda_eeh_get_log(struct eeh_pe *pe, int severity, - char *drv_log, unsigned long len) -{ - s64 ret; - unsigned long flags; - struct pci_controller *hose = pe->phb; - struct pnv_phb *phb = hose->private_data; - - spin_lock_irqsave(&phb->lock, flags); - - ret = opal_pci_get_phb_diag_data2(phb->opal_id, - phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE); - if (ret) { - spin_unlock_irqrestore(&phb->lock, flags); - pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n", - __func__, hose->global_number, pe->addr, ret); - return -EIO; - } - - /* The PHB diag-data is always indicative */ - pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); - - spin_unlock_irqrestore(&phb->lock, flags); - - return 0; -} - -/** * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE * @pe: EEH PE * @@ -646,22 +639,6 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) } } -static void ioda_eeh_phb_diag(struct pci_controller *hose) -{ - struct pnv_phb *phb = hose->private_data; - long rc; - - rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, - PNV_PCI_DIAG_BUF_SIZE); - if (rc != OPAL_SUCCESS) { - pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n", - __func__, hose->global_number, rc); - return; - } - - pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); -} - static int ioda_eeh_get_phb_pe(struct pci_controller *hose, struct eeh_pe **pe) { @@ -835,6 +812,20 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) } /* + * EEH core will try recover from fenced PHB or + * frozen PE. In the time for frozen PE, EEH core + * enable IO path for that before collecting logs, + * but it ruins the site. So we have to dump the + * log in advance here. + */ + if ((ret == EEH_NEXT_ERR_FROZEN_PE || + ret == EEH_NEXT_ERR_FENCED_PHB) && + !((*pe)->state & EEH_PE_ISOLATED)) { + eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); + ioda_eeh_phb_diag(hose); + } + + /* * If we have no errors on the specific PHB or only * informative error there, we continue poking it. * Otherwise, we need actions to be taken by upper @@ -852,7 +843,6 @@ struct pnv_eeh_ops ioda_eeh_ops = { .set_option = ioda_eeh_set_option, .get_state = ioda_eeh_get_state, .reset = ioda_eeh_reset, - .get_log = ioda_eeh_get_log, .configure_bridge = ioda_eeh_configure_bridge, .next_error = ioda_eeh_next_error }; -- cgit v0.10.2 From af87d2fe95444d107e0c0cf0ba7e20e6716a7bfd Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 25 Feb 2014 15:28:38 +0800 Subject: powerpc/powernv: Refactor PHB diag-data dump As Ben suggested, the patch prints PHB diag-data with multiple fields in one line and omits the line if the fields of that line are all zero. With the patch applied, the PHB3 diag-data dump looks like: PHB3 PHB#3 Diag-data (Version: 1) brdgCtl: 00000002 RootSts: 0000000f 00400000 b0830008 00100147 00002000 nFir: 0000000000000000 0030006e00000000 0000000000000000 PhbSts: 0000001c00000000 0000000000000000 Lem: 0000000000100000 42498e327f502eae 0000000000000000 InAErr: 8000000000000000 8000000000000000 0402030000000000 0000000000000000 PE[ 8] A/B: 8480002b00000000 8000000000000000 [ The current diag data is so big that it overflows the printk buffer pretty quickly in cases when we get a handful of errors at once which can happen. --BenH ] Signed-off-by: Gavin Shan CC: Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 95633d7..8518817 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -134,57 +134,72 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose, pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n", hose->global_number, common->version); - pr_info(" brdgCtl: %08x\n", data->brdgCtl); - - pr_info(" portStatusReg: %08x\n", data->portStatusReg); - pr_info(" rootCmplxStatus: %08x\n", data->rootCmplxStatus); - pr_info(" busAgentStatus: %08x\n", data->busAgentStatus); - - pr_info(" deviceStatus: %08x\n", data->deviceStatus); - pr_info(" slotStatus: %08x\n", data->slotStatus); - pr_info(" linkStatus: %08x\n", data->linkStatus); - pr_info(" devCmdStatus: %08x\n", data->devCmdStatus); - pr_info(" devSecStatus: %08x\n", data->devSecStatus); - - pr_info(" rootErrorStatus: %08x\n", data->rootErrorStatus); - pr_info(" uncorrErrorStatus: %08x\n", data->uncorrErrorStatus); - pr_info(" corrErrorStatus: %08x\n", data->corrErrorStatus); - pr_info(" tlpHdr1: %08x\n", data->tlpHdr1); - pr_info(" tlpHdr2: %08x\n", data->tlpHdr2); - pr_info(" tlpHdr3: %08x\n", data->tlpHdr3); - pr_info(" tlpHdr4: %08x\n", data->tlpHdr4); - pr_info(" sourceId: %08x\n", data->sourceId); - pr_info(" errorClass: %016llx\n", data->errorClass); - pr_info(" correlator: %016llx\n", data->correlator); - pr_info(" p7iocPlssr: %016llx\n", data->p7iocPlssr); - pr_info(" p7iocCsr: %016llx\n", data->p7iocCsr); - pr_info(" lemFir: %016llx\n", data->lemFir); - pr_info(" lemErrorMask: %016llx\n", data->lemErrorMask); - pr_info(" lemWOF: %016llx\n", data->lemWOF); - pr_info(" phbErrorStatus: %016llx\n", data->phbErrorStatus); - pr_info(" phbFirstErrorStatus: %016llx\n", data->phbFirstErrorStatus); - pr_info(" phbErrorLog0: %016llx\n", data->phbErrorLog0); - pr_info(" phbErrorLog1: %016llx\n", data->phbErrorLog1); - pr_info(" mmioErrorStatus: %016llx\n", data->mmioErrorStatus); - pr_info(" mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus); - pr_info(" mmioErrorLog0: %016llx\n", data->mmioErrorLog0); - pr_info(" mmioErrorLog1: %016llx\n", data->mmioErrorLog1); - pr_info(" dma0ErrorStatus: %016llx\n", data->dma0ErrorStatus); - pr_info(" dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus); - pr_info(" dma0ErrorLog0: %016llx\n", data->dma0ErrorLog0); - pr_info(" dma0ErrorLog1: %016llx\n", data->dma0ErrorLog1); - pr_info(" dma1ErrorStatus: %016llx\n", data->dma1ErrorStatus); - pr_info(" dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus); - pr_info(" dma1ErrorLog0: %016llx\n", data->dma1ErrorLog0); - pr_info(" dma1ErrorLog1: %016llx\n", data->dma1ErrorLog1); + if (data->brdgCtl) + pr_info(" brdgCtl: %08x\n", + data->brdgCtl); + if (data->portStatusReg || data->rootCmplxStatus || + data->busAgentStatus) + pr_info(" UtlSts: %08x %08x %08x\n", + data->portStatusReg, data->rootCmplxStatus, + data->busAgentStatus); + if (data->deviceStatus || data->slotStatus || + data->linkStatus || data->devCmdStatus || + data->devSecStatus) + pr_info(" RootSts: %08x %08x %08x %08x %08x\n", + data->deviceStatus, data->slotStatus, + data->linkStatus, data->devCmdStatus, + data->devSecStatus); + if (data->rootErrorStatus || data->uncorrErrorStatus || + data->corrErrorStatus) + pr_info(" RootErrSts: %08x %08x %08x\n", + data->rootErrorStatus, data->uncorrErrorStatus, + data->corrErrorStatus); + if (data->tlpHdr1 || data->tlpHdr2 || + data->tlpHdr3 || data->tlpHdr4) + pr_info(" RootErrLog: %08x %08x %08x %08x\n", + data->tlpHdr1, data->tlpHdr2, + data->tlpHdr3, data->tlpHdr4); + if (data->sourceId || data->errorClass || + data->correlator) + pr_info(" RootErrLog1: %08x %016llx %016llx\n", + data->sourceId, data->errorClass, + data->correlator); + if (data->p7iocPlssr || data->p7iocCsr) + pr_info(" PhbSts: %016llx %016llx\n", + data->p7iocPlssr, data->p7iocCsr); + if (data->lemFir || data->lemErrorMask || + data->lemWOF) + pr_info(" Lem: %016llx %016llx %016llx\n", + data->lemFir, data->lemErrorMask, + data->lemWOF); + if (data->phbErrorStatus || data->phbFirstErrorStatus || + data->phbErrorLog0 || data->phbErrorLog1) + pr_info(" PhbErr: %016llx %016llx %016llx %016llx\n", + data->phbErrorStatus, data->phbFirstErrorStatus, + data->phbErrorLog0, data->phbErrorLog1); + if (data->mmioErrorStatus || data->mmioFirstErrorStatus || + data->mmioErrorLog0 || data->mmioErrorLog1) + pr_info(" OutErr: %016llx %016llx %016llx %016llx\n", + data->mmioErrorStatus, data->mmioFirstErrorStatus, + data->mmioErrorLog0, data->mmioErrorLog1); + if (data->dma0ErrorStatus || data->dma0FirstErrorStatus || + data->dma0ErrorLog0 || data->dma0ErrorLog1) + pr_info(" InAErr: %016llx %016llx %016llx %016llx\n", + data->dma0ErrorStatus, data->dma0FirstErrorStatus, + data->dma0ErrorLog0, data->dma0ErrorLog1); + if (data->dma1ErrorStatus || data->dma1FirstErrorStatus || + data->dma1ErrorLog0 || data->dma1ErrorLog1) + pr_info(" InBErr: %016llx %016llx %016llx %016llx\n", + data->dma1ErrorStatus, data->dma1FirstErrorStatus, + data->dma1ErrorLog0, data->dma1ErrorLog1); for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { if ((data->pestA[i] >> 63) == 0 && (data->pestB[i] >> 63) == 0) continue; - pr_info(" PE[%3d] PESTA: %016llx\n", i, data->pestA[i]); - pr_info(" PESTB: %016llx\n", data->pestB[i]); + pr_info(" PE[%3d] A/B: %016llx %016llx\n", + i, data->pestA[i], data->pestB[i]); } } @@ -197,62 +212,77 @@ static void pnv_pci_dump_phb3_diag_data(struct pci_controller *hose, data = (struct OpalIoPhb3ErrorData*)common; pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n", hose->global_number, common->version); - - pr_info(" brdgCtl: %08x\n", data->brdgCtl); - - pr_info(" portStatusReg: %08x\n", data->portStatusReg); - pr_info(" rootCmplxStatus: %08x\n", data->rootCmplxStatus); - pr_info(" busAgentStatus: %08x\n", data->busAgentStatus); - - pr_info(" deviceStatus: %08x\n", data->deviceStatus); - pr_info(" slotStatus: %08x\n", data->slotStatus); - pr_info(" linkStatus: %08x\n", data->linkStatus); - pr_info(" devCmdStatus: %08x\n", data->devCmdStatus); - pr_info(" devSecStatus: %08x\n", data->devSecStatus); - - pr_info(" rootErrorStatus: %08x\n", data->rootErrorStatus); - pr_info(" uncorrErrorStatus: %08x\n", data->uncorrErrorStatus); - pr_info(" corrErrorStatus: %08x\n", data->corrErrorStatus); - pr_info(" tlpHdr1: %08x\n", data->tlpHdr1); - pr_info(" tlpHdr2: %08x\n", data->tlpHdr2); - pr_info(" tlpHdr3: %08x\n", data->tlpHdr3); - pr_info(" tlpHdr4: %08x\n", data->tlpHdr4); - pr_info(" sourceId: %08x\n", data->sourceId); - pr_info(" errorClass: %016llx\n", data->errorClass); - pr_info(" correlator: %016llx\n", data->correlator); - - pr_info(" nFir: %016llx\n", data->nFir); - pr_info(" nFirMask: %016llx\n", data->nFirMask); - pr_info(" nFirWOF: %016llx\n", data->nFirWOF); - pr_info(" PhbPlssr: %016llx\n", data->phbPlssr); - pr_info(" PhbCsr: %016llx\n", data->phbCsr); - pr_info(" lemFir: %016llx\n", data->lemFir); - pr_info(" lemErrorMask: %016llx\n", data->lemErrorMask); - pr_info(" lemWOF: %016llx\n", data->lemWOF); - pr_info(" phbErrorStatus: %016llx\n", data->phbErrorStatus); - pr_info(" phbFirstErrorStatus: %016llx\n", data->phbFirstErrorStatus); - pr_info(" phbErrorLog0: %016llx\n", data->phbErrorLog0); - pr_info(" phbErrorLog1: %016llx\n", data->phbErrorLog1); - pr_info(" mmioErrorStatus: %016llx\n", data->mmioErrorStatus); - pr_info(" mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus); - pr_info(" mmioErrorLog0: %016llx\n", data->mmioErrorLog0); - pr_info(" mmioErrorLog1: %016llx\n", data->mmioErrorLog1); - pr_info(" dma0ErrorStatus: %016llx\n", data->dma0ErrorStatus); - pr_info(" dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus); - pr_info(" dma0ErrorLog0: %016llx\n", data->dma0ErrorLog0); - pr_info(" dma0ErrorLog1: %016llx\n", data->dma0ErrorLog1); - pr_info(" dma1ErrorStatus: %016llx\n", data->dma1ErrorStatus); - pr_info(" dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus); - pr_info(" dma1ErrorLog0: %016llx\n", data->dma1ErrorLog0); - pr_info(" dma1ErrorLog1: %016llx\n", data->dma1ErrorLog1); + if (data->brdgCtl) + pr_info(" brdgCtl: %08x\n", + data->brdgCtl); + if (data->portStatusReg || data->rootCmplxStatus || + data->busAgentStatus) + pr_info(" UtlSts: %08x %08x %08x\n", + data->portStatusReg, data->rootCmplxStatus, + data->busAgentStatus); + if (data->deviceStatus || data->slotStatus || + data->linkStatus || data->devCmdStatus || + data->devSecStatus) + pr_info(" RootSts: %08x %08x %08x %08x %08x\n", + data->deviceStatus, data->slotStatus, + data->linkStatus, data->devCmdStatus, + data->devSecStatus); + if (data->rootErrorStatus || data->uncorrErrorStatus || + data->corrErrorStatus) + pr_info(" RootErrSts: %08x %08x %08x\n", + data->rootErrorStatus, data->uncorrErrorStatus, + data->corrErrorStatus); + if (data->tlpHdr1 || data->tlpHdr2 || + data->tlpHdr3 || data->tlpHdr4) + pr_info(" RootErrLog: %08x %08x %08x %08x\n", + data->tlpHdr1, data->tlpHdr2, + data->tlpHdr3, data->tlpHdr4); + if (data->sourceId || data->errorClass || + data->correlator) + pr_info(" RootErrLog1: %08x %016llx %016llx\n", + data->sourceId, data->errorClass, + data->correlator); + if (data->nFir || data->nFirMask || + data->nFirWOF) + pr_info(" nFir: %016llx %016llx %016llx\n", + data->nFir, data->nFirMask, + data->nFirWOF); + if (data->phbPlssr || data->phbCsr) + pr_info(" PhbSts: %016llx %016llx\n", + data->phbPlssr, data->phbCsr); + if (data->lemFir || data->lemErrorMask || + data->lemWOF) + pr_info(" Lem: %016llx %016llx %016llx\n", + data->lemFir, data->lemErrorMask, + data->lemWOF); + if (data->phbErrorStatus || data->phbFirstErrorStatus || + data->phbErrorLog0 || data->phbErrorLog1) + pr_info(" PhbErr: %016llx %016llx %016llx %016llx\n", + data->phbErrorStatus, data->phbFirstErrorStatus, + data->phbErrorLog0, data->phbErrorLog1); + if (data->mmioErrorStatus || data->mmioFirstErrorStatus || + data->mmioErrorLog0 || data->mmioErrorLog1) + pr_info(" OutErr: %016llx %016llx %016llx %016llx\n", + data->mmioErrorStatus, data->mmioFirstErrorStatus, + data->mmioErrorLog0, data->mmioErrorLog1); + if (data->dma0ErrorStatus || data->dma0FirstErrorStatus || + data->dma0ErrorLog0 || data->dma0ErrorLog1) + pr_info(" InAErr: %016llx %016llx %016llx %016llx\n", + data->dma0ErrorStatus, data->dma0FirstErrorStatus, + data->dma0ErrorLog0, data->dma0ErrorLog1); + if (data->dma1ErrorStatus || data->dma1FirstErrorStatus || + data->dma1ErrorLog0 || data->dma1ErrorLog1) + pr_info(" InBErr: %016llx %016llx %016llx %016llx\n", + data->dma1ErrorStatus, data->dma1FirstErrorStatus, + data->dma1ErrorLog0, data->dma1ErrorLog1); for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) { if ((data->pestA[i] >> 63) == 0 && (data->pestB[i] >> 63) == 0) continue; - pr_info(" PE[%3d] PESTA: %016llx\n", i, data->pestA[i]); - pr_info(" PESTB: %016llx\n", data->pestB[i]); + pr_info(" PE[%3d] A/B: %016llx %016llx\n", + i, data->pestA[i], data->pestB[i]); } } -- cgit v0.10.2 From 2f3f38e4d3d03dd4125cc9a1f49ab3cc91d8d670 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 28 Feb 2014 16:20:29 +1100 Subject: powerpc/powernv: Fix opal_xscom_{read,write} prototype The OPAL firmware functions opal_xscom_read and opal_xscom_write take a 64-bit argument for the XSCOM (PCB) address in order to support the indirect mode on P8. Signed-off-by: Benjamin Herrenschmidt CC: [v3.13] diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 40157e2..ed82142 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -816,8 +816,8 @@ int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe, int64_t opal_pci_poll(uint64_t phb_id); int64_t opal_return_cpu(void); -int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, __be64 *val); -int64_t opal_xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val); +int64_t opal_xscom_read(uint32_t gcid, uint64_t pcb_addr, __be64 *val); +int64_t opal_xscom_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val); int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type, uint32_t addr, uint32_t data, uint32_t sz); -- cgit v0.10.2 From e0cf957614976896111e676e5134ac98ee227d3d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 28 Feb 2014 16:20:38 +1100 Subject: powerpc/powernv: Fix indirect XSCOM unmangling We need to unmangle the full address, not just the register number, and we also need to support the real indirect bit being set for in-kernel uses. Signed-off-by: Benjamin Herrenschmidt CC: [v3.13] diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c index 4fbf276..4cd2ea6 100644 --- a/arch/powerpc/platforms/powernv/opal-xscom.c +++ b/arch/powerpc/platforms/powernv/opal-xscom.c @@ -71,11 +71,11 @@ static int opal_xscom_err_xlate(int64_t rc) } } -static u64 opal_scom_unmangle(u64 reg) +static u64 opal_scom_unmangle(u64 addr) { /* * XSCOM indirect addresses have the top bit set. Additionally - * the reset of the top 3 nibbles is always 0. + * the rest of the top 3 nibbles is always 0. * * Because the debugfs interface uses signed offsets and shifts * the address left by 3, we basically cannot use the top 4 bits @@ -86,10 +86,13 @@ static u64 opal_scom_unmangle(u64 reg) * conversion here. To leave room for further xscom address * expansion, we only clear out the top byte * + * For in-kernel use, we also support the real indirect bit, so + * we test for any of the top 5 bits + * */ - if (reg & (1ull << 59)) - reg = (reg & ~(0xffull << 56)) | (1ull << 63); - return reg; + if (addr & (0x1full << 59)) + addr = (addr & ~(0xffull << 56)) | (1ull << 63); + return addr; } static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) @@ -98,8 +101,8 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) int64_t rc; __be64 v; - reg = opal_scom_unmangle(reg); - rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v)); + reg = opal_scom_unmangle(m->addr + reg); + rc = opal_xscom_read(m->chip, reg, (__be64 *)__pa(&v)); *value = be64_to_cpu(v); return opal_xscom_err_xlate(rc); } @@ -109,8 +112,8 @@ static int opal_scom_write(scom_map_t map, u64 reg, u64 value) struct opal_scom_map *m = map; int64_t rc; - reg = opal_scom_unmangle(reg); - rc = opal_xscom_write(m->chip, m->addr + reg, value); + reg = opal_scom_unmangle(m->addr + reg); + rc = opal_xscom_write(m->chip, reg, value); return opal_xscom_err_xlate(rc); } -- cgit v0.10.2 From 8987583366ae9e03c306c2b7d73bdb952df1d08d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 18 Feb 2014 22:25:15 +0100 Subject: firewire: net: fix use after free Commit 8408dc1c14c1 "firewire: net: use dev_printk API" introduced a use-after-free in a failure path. fwnet_transmit_packet_failed(ptask) may free ptask, then the dev_err() call dereferenced it. The fix is straightforward; simply reorder the two calls. Reported-by: Dan Carpenter Cc: stable@vger.kernel.org # v3.4+ Signed-off-by: Stefan Richter diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 6b89598..4af0a7b 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -929,8 +929,6 @@ static void fwnet_write_complete(struct fw_card *card, int rcode, if (rcode == RCODE_COMPLETE) { fwnet_transmit_packet_done(ptask); } else { - fwnet_transmit_packet_failed(ptask); - if (printk_timed_ratelimit(&j, 1000) || rcode != last_rcode) { dev_err(&ptask->dev->netdev->dev, "fwnet_write_complete failed: %x (skipped %d)\n", @@ -938,8 +936,10 @@ static void fwnet_write_complete(struct fw_card *card, int rcode, errors_skipped = 0; last_rcode = rcode; - } else + } else { errors_skipped++; + } + fwnet_transmit_packet_failed(ptask); } } -- cgit v0.10.2 From b39c2a57a00a841f057a75b41df4c26173288b66 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 26 Feb 2014 18:14:26 +0100 Subject: perf tools: Fix strict alias issue for find_first_bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling perf tool code with gcc 4.4.7 I'm getting following error: CC util/session.o cc1: warnings being treated as errors util/session.c: In function ‘perf_session_deliver_event’: tools/perf/util/include/linux/bitops.h:109: error: dereferencing pointer ‘p’ does break strict-aliasing rules tools/perf/util/include/linux/bitops.h:101: error: dereferencing pointer ‘p’ does break strict-aliasing rules util/session.c:697: note: initialized from here tools/perf/util/include/linux/bitops.h:101: note: initialized from here make[1]: *** [util/session.o] Error 1 make: *** [util/session.o] Error 2 The aliased types here are u64 and unsigned long pointers, which is safe for the find_first_bit processing. This error shows up for me only for gcc 4.4 on 32bit x86, even for -Wstrict-aliasing=3, while newer gcc are quiet and scream here for -Wstrict-aliasing={2,1}. Looks like newer gcc changed the rules for strict alias warnings. The gcc documentation offers workaround for valid aliasing by using __may_alias__ attribute: http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Type-Attributes.html Using this workaround for the find_first_bit function. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1393434867-20271-1-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index 45cf10a..dadfa7e 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h @@ -87,13 +87,15 @@ static __always_inline unsigned long __ffs(unsigned long word) return num; } +typedef const unsigned long __attribute__((__may_alias__)) long_alias_t; + /* * Find the first set bit in a memory region. */ static inline unsigned long find_first_bit(const unsigned long *addr, unsigned long size) { - const unsigned long *p = addr; + long_alias_t *p = (long_alias_t *) addr; unsigned long result = 0; unsigned long tmp; -- cgit v0.10.2 From e0d849fad746cb36a6822e4595d8ba9bf0adf7fa Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Thu, 27 Feb 2014 22:46:48 +0100 Subject: dm cache: fix truncation bug when mapping I/O to >2TB fast device When remapping a block to the cache's fast device that is larger than 2TB we must not truncate the destination sector to 32bits. The 32bit temporary result of from_cblock() was being overflowed in remap_to_cache() due to the logical left shift. Use an intermediate 64bit type to store the 32bit from_cblock() result to fix the overflow. Signed-off-by: Heinz Mauelshagen Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index db09444..1af7014 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -671,15 +671,16 @@ static void remap_to_cache(struct cache *cache, struct bio *bio, dm_cblock_t cblock) { sector_t bi_sector = bio->bi_iter.bi_sector; + sector_t block = from_cblock(cblock); bio->bi_bdev = cache->cache_dev->bdev; if (!block_size_is_power_of_two(cache)) bio->bi_iter.bi_sector = - (from_cblock(cblock) * cache->sectors_per_block) + + (block * cache->sectors_per_block) + sector_div(bi_sector, cache->sectors_per_block); else bio->bi_iter.bi_sector = - (from_cblock(cblock) << cache->sectors_per_block_shift) | + (block << cache->sectors_per_block_shift) | (bi_sector & (cache->sectors_per_block - 1)); } -- cgit v0.10.2 From 84fe6826c28f69d8708bd575faed7f75e6b6f57f Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Tue, 25 Feb 2014 11:38:53 +0000 Subject: arm64: mm: Add double logical invert to pte accessors Page table entries on ARM64 are 64 bits, and some pte functions such as pte_dirty return a bitwise-and of a flag with the pte value. If the flag to be tested resides in the upper 32 bits of the pte, then we run into the danger of the result being dropped if downcast. For example: gather_stats(page, md, pte_dirty(*pte), 1); where pte_dirty(*pte) is downcast to an int. This patch adds a double logical invert to all the pte_ accessors to ensure predictable downcasting. Signed-off-by: Steve Capper Cc: Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index b524dcd..aa3917c 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -136,11 +136,11 @@ extern struct page *empty_zero_page; /* * The following only work if pte_present(). Undefined behaviour otherwise. */ -#define pte_present(pte) (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)) -#define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) -#define pte_young(pte) (pte_val(pte) & PTE_AF) -#define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) -#define pte_write(pte) (pte_val(pte) & PTE_WRITE) +#define pte_present(pte) (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))) +#define pte_dirty(pte) (!!(pte_val(pte) & PTE_DIRTY)) +#define pte_young(pte) (!!(pte_val(pte) & PTE_AF)) +#define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL)) +#define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE)) #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) #define pte_valid_user(pte) \ -- cgit v0.10.2 From b57fc9e80692043e2a3a74e1d2c047eb700dcd0c Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 28 Feb 2014 16:12:25 +0000 Subject: arm64: Fix !CONFIG_SMP kernel build Commit fb4a96029c8a (arm64: kernel: fix per-cpu offset restore on resume) uses per_cpu_offset() unconditionally during CPU wakeup, however, this is only defined for the SMP case. Signed-off-by: Catalin Marinas Reported-by: Dave P Martin diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h index 13fb0b3..453a179 100644 --- a/arch/arm64/include/asm/percpu.h +++ b/arch/arm64/include/asm/percpu.h @@ -16,6 +16,8 @@ #ifndef __ASM_PERCPU_H #define __ASM_PERCPU_H +#ifdef CONFIG_SMP + static inline void set_my_cpu_offset(unsigned long off) { asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory"); @@ -36,6 +38,12 @@ static inline unsigned long __my_cpu_offset(void) } #define __my_cpu_offset __my_cpu_offset() +#else /* !CONFIG_SMP */ + +#define set_my_cpu_offset(x) do { } while (0) + +#endif /* CONFIG_SMP */ + #include #endif /* __ASM_PERCPU_H */ -- cgit v0.10.2 From 14f398ca2f26a2ed6236aec54395e0fa06ec8a82 Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Fri, 28 Feb 2014 12:02:56 -0500 Subject: dm cache mq: fix memory allocation failure for large cache devices The memory allocated for the multiqueue policy's hash table doesn't need to be physically contiguous. Use vzalloc() instead of kzalloc(). Fedora has been carrying this fix since 10/10/2013. Failure seen during creation of a 10TB cached device with a 2048 sector block size and 411GB cache size: dmsetup: page allocation failure: order:9, mode:0x10c0d0 CPU: 11 PID: 29235 Comm: dmsetup Not tainted 3.10.4 #3 Hardware name: Supermicro X8DTL/X8DTL, BIOS 2.1a 12/30/2011 000000000010c0d0 ffff880090941898 ffffffff81387ab4 ffff880090941928 ffffffff810bb26f 0000000000000009 000000000010c0d0 ffff880090941928 ffffffff81385dbc ffffffff815f3840 ffffffff00000000 000002000010c0d0 Call Trace: [] dump_stack+0x19/0x1b [] warn_alloc_failed+0x110/0x124 [] ? __alloc_pages_direct_compact+0x17c/0x18e [] __alloc_pages_nodemask+0x6c7/0x75e [] __get_free_pages+0x12/0x3f [] kmalloc_order_trace+0x29/0x88 [] __kmalloc+0x36/0x11b [] ? mq_create+0x1dc/0x2cf [dm_cache_mq] [] mq_create+0x2af/0x2cf [dm_cache_mq] [] dm_cache_policy_create+0xa7/0xd2 [dm_cache] [] ? cache_ctr+0x245/0xa13 [dm_cache] [] cache_ctr+0x353/0xa13 [dm_cache] [] dm_table_add_target+0x227/0x2ce [dm_mod] [] table_load+0x286/0x2ac [dm_mod] [] ? dev_wait+0x8a/0x8a [dm_mod] [] ctl_ioctl+0x39a/0x3c2 [dm_mod] [] dm_ctl_ioctl+0xe/0x12 [dm_mod] [] vfs_ioctl+0x21/0x34 [] do_vfs_ioctl+0x3b1/0x3f4 [] ? ____fput+0x9/0xb [] ? task_work_run+0x7e/0x92 [] SyS_ioctl+0x52/0x82 [] system_call_fastpath+0x16/0x1b Signed-off-by: Heinz Mauelshagen Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c index 1e018e9..0e385e4 100644 --- a/drivers/md/dm-cache-policy-mq.c +++ b/drivers/md/dm-cache-policy-mq.c @@ -872,7 +872,7 @@ static void mq_destroy(struct dm_cache_policy *p) { struct mq_policy *mq = to_mq_policy(p); - kfree(mq->table); + vfree(mq->table); epool_exit(&mq->cache_pool); epool_exit(&mq->pre_cache_pool); kfree(mq); @@ -1245,7 +1245,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size, mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16); mq->hash_bits = ffs(mq->nr_buckets) - 1; - mq->table = kzalloc(sizeof(*mq->table) * mq->nr_buckets, GFP_KERNEL); + mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets); if (!mq->table) goto bad_alloc_table; -- cgit v0.10.2 From adb07df1e039e9fe43e66aeea8b4771f83659dbb Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 26 Feb 2014 20:11:22 -0800 Subject: mwifiex: do not advertise usb autosuspend support As many Surface Pro I & II users have found out, the mwifiex_usb doesn't support usb autosuspend, and it has caused some system stability issues. Bug 69661 - mwifiex_usb on MS Surface Pro 1 is unstable Bug 60815 - Interface hangs in mwifiex_usb Bug 64111 - mwifiex_usb USB8797 crash failed to get signal information USB autosuspend get triggered when Surface Pro's AC power is removed or powertop enables power saving on USB8797 device. Driver's suspend handler is called here, but resume handler won't be called until the AC power is put back on or powertop disables power saving for USB8797. We need to refactor the suspend/resume handlers to support usb autosuspend properly. For now let's just remove it. Cc: # 3.5+ Signed-off-by: Bing Zhao Signed-off-by: Amitkumar Karwar Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index cb6b70a..2087488 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -525,13 +525,6 @@ static int mwifiex_usb_resume(struct usb_interface *intf) MWIFIEX_BSS_ROLE_ANY), MWIFIEX_ASYNC_CMD); -#ifdef CONFIG_PM - /* Resume handler may be called due to remote wakeup, - * force to exit suspend anyway - */ - usb_disable_autosuspend(card->udev); -#endif /* CONFIG_PM */ - return 0; } @@ -571,7 +564,6 @@ static struct usb_driver mwifiex_usb_driver = { .id_table = mwifiex_usb_table, .suspend = mwifiex_usb_suspend, .resume = mwifiex_usb_resume, - .supports_autosuspend = 1, }; static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) -- cgit v0.10.2 From fb0cfecf67cc1cec4487efb6267317de432add2f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Sat, 22 Feb 2014 10:59:36 -0300 Subject: ARM: dts: omap3-igep: fix boot fail due wrong compatible match This patch is based on commit: 016c12d2 ("ARM: OMAP3: Fix hardware detection for omap3630 when booted with device tree") and fixes a boot hang due the IGEP board being wrongly initialized as an OMAP3430 platform instead of an OMAP3630. Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-igep0020.dts b/arch/arm/boot/dts/omap3-igep0020.dts index 25a2b5f..f2779ac 100644 --- a/arch/arm/boot/dts/omap3-igep0020.dts +++ b/arch/arm/boot/dts/omap3-igep0020.dts @@ -14,7 +14,7 @@ / { model = "IGEPv2 (TI OMAP AM/DM37x)"; - compatible = "isee,omap3-igep0020", "ti,omap3"; + compatible = "isee,omap3-igep0020", "ti,omap36xx", "ti,omap3"; leds { pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/omap3-igep0030.dts b/arch/arm/boot/dts/omap3-igep0030.dts index 145c58c..2793749 100644 --- a/arch/arm/boot/dts/omap3-igep0030.dts +++ b/arch/arm/boot/dts/omap3-igep0030.dts @@ -13,7 +13,7 @@ / { model = "IGEP COM MODULE (TI OMAP AM/DM37x)"; - compatible = "isee,omap3-igep0030", "ti,omap3"; + compatible = "isee,omap3-igep0030", "ti,omap36xx", "ti,omap3"; leds { pinctrl-names = "default"; -- cgit v0.10.2 From 014325e933b43844f5d01fcef39bbc3301320e59 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 20 Feb 2014 14:37:20 -0700 Subject: ARM: tegra: add LED options back into tegra_defconfig The last time tegra_defconfig was rebuilt, various LEDs options were somehow selected by other options, and hence their entries in tegra_defconfig were removed by "make savedefconfig". However, for some reason this is no longer happening, so we need to add the entries back into tegra_defconfig so the they are enabled in .config. Fixes: db079b1811d1 ("ARM: tegra: rebuild tegra_defconfig to add DEBUG_FS)" Reported-by: Marc Dietrich Signed-off-by: Stephen Warren Signed-off-by: Arnd Bergmann diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 00fe9e9..27d69b5 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -204,7 +204,10 @@ CONFIG_MMC_BLOCK_MINORS=16 CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_TEGRA=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_ONESHOT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y -- cgit v0.10.2 From d7b95315cc7f441418845a165ee56df723941487 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 28 Feb 2014 15:05:10 -0800 Subject: tg3: Don't check undefined error bits in RXBD Redefine the RXD_ERR_MASK to include only relevant error bits. This fixes a customer reported issue of randomly dropping packets on the 5719. Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 3167ed6..3b6d0ba 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6843,8 +6843,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) work_mask |= opaque_key; - if ((desc->err_vlan & RXD_ERR_MASK) != 0 && - (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) { + if (desc->err_vlan & RXD_ERR_MASK) { drop_it: tg3_recycle_rx(tnapi, tpr, opaque_key, desc_idx, *post_ptr); diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index ef47238..04321e5 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2608,7 +2608,11 @@ struct tg3_rx_buffer_desc { #define RXD_ERR_TOO_SMALL 0x00400000 #define RXD_ERR_NO_RESOURCES 0x00800000 #define RXD_ERR_HUGE_FRAME 0x01000000 -#define RXD_ERR_MASK 0xffff0000 + +#define RXD_ERR_MASK (RXD_ERR_BAD_CRC | RXD_ERR_COLLISION | \ + RXD_ERR_LINK_LOST | RXD_ERR_PHY_DECODE | \ + RXD_ERR_MAC_ABRT | RXD_ERR_TOO_SMALL | \ + RXD_ERR_NO_RESOURCES | RXD_ERR_HUGE_FRAME) u32 reserved; u32 opaque; -- cgit v0.10.2 From 877767dccf5c35d4ed245701956effb72af77d52 Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Fri, 28 Feb 2014 14:14:03 +0100 Subject: bna: fix vlan tag stripping and implement its toggling The recent commit "fe1624c bna: RX Filter Enhancements" disables VLAN tag stripping if the NIC is in promiscuous mode. This causes __vlan_hwaccel_put_tag() is called when the stripping is disabled. Because of this VLAN over bna does not work and causes BUGs in conjunction with openvswitch like this: Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index cf64f3d..4ad1187 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -707,7 +707,8 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget) else skb_checksum_none_assert(skb); - if (flags & BNA_CQ_EF_VLAN) + if ((flags & BNA_CQ_EF_VLAN) && + (bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(cmpl->vlan_tag)); if (BNAD_RXBUF_IS_SK_BUFF(unmap_q->type)) @@ -2094,7 +2095,9 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config) rx_config->q1_buf_size = BFI_SMALL_RXBUF_SIZE; } - rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED; + rx_config->vlan_strip_status = + (bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) ? + BNA_STATUS_T_ENABLED : BNA_STATUS_T_DISABLED; } static void @@ -3245,11 +3248,6 @@ bnad_set_rx_mode(struct net_device *netdev) BNA_RXMODE_ALLMULTI; bna_rx_mode_set(bnad->rx_info[0].rx, new_mode, mode_mask, NULL); - if (bnad->cfg_flags & BNAD_CF_PROMISC) - bna_rx_vlan_strip_disable(bnad->rx_info[0].rx); - else - bna_rx_vlan_strip_enable(bnad->rx_info[0].rx); - spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -3374,6 +3372,27 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) return 0; } +static int bnad_set_features(struct net_device *dev, netdev_features_t features) +{ + struct bnad *bnad = netdev_priv(dev); + netdev_features_t changed = features ^ dev->features; + + if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(dev)) { + unsigned long flags; + + spin_lock_irqsave(&bnad->bna_lock, flags); + + if (features & NETIF_F_HW_VLAN_CTAG_RX) + bna_rx_vlan_strip_enable(bnad->rx_info[0].rx); + else + bna_rx_vlan_strip_disable(bnad->rx_info[0].rx); + + spin_unlock_irqrestore(&bnad->bna_lock, flags); + } + + return 0; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void bnad_netpoll(struct net_device *netdev) @@ -3421,6 +3440,7 @@ static const struct net_device_ops bnad_netdev_ops = { .ndo_change_mtu = bnad_change_mtu, .ndo_vlan_rx_add_vid = bnad_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = bnad_vlan_rx_kill_vid, + .ndo_set_features = bnad_set_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = bnad_netpoll #endif @@ -3433,14 +3453,14 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac) netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_TX; + NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; netdev->vlan_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6; - netdev->features |= netdev->hw_features | - NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; + netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER; if (using_dac) netdev->features |= NETIF_F_HIGHDMA; -- cgit v0.10.2 From 8427defd087ae6c5eaea9d609dfe7f165568accd Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 28 Feb 2014 22:40:53 +0000 Subject: MAINTAINERS: add maintainer entry for Armada DRM driver Add a maintainers entry for the Armada DRM driver. Signed-off-by: Russell King Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index df8869d..4f42ace 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5501,6 +5501,11 @@ W: http://www.kernel.org/doc/man-pages L: linux-man@vger.kernel.org S: Maintained +MARVELL ARMADA DRM SUPPORT +M: Russell King +S: Maintained +F: drivers/gpu/drm/armada/ + MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) M: Mirko Lindner M: Stephen Hemminger -- cgit v0.10.2 From 8303d769ea9e9626c4f0c3bd13e35e904a1253ab Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:02 +0100 Subject: ASoC: Remove unused 'reg2' field from soc_enum struct Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 01bd80a..49d6c10 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1101,7 +1101,6 @@ struct soc_mreg_control { /* enumerated kcontrol */ struct soc_enum { unsigned short reg; - unsigned short reg2; unsigned char shift_l; unsigned char shift_r; unsigned int items; -- cgit v0.10.2 From 29ae2fa5533e607a7d97b7564dc015252f1e73f4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:03 +0100 Subject: ASoC: Consolidate enum and value enum controls The implementations for enum and value enum controls are almost identical. The only difference is that the value enum uses an additional look-up table to map the control value to the register value, while the enum control uses a direct mapping. Enums and value enums can easily be distinguished at runtime, for value enums the values field of the snd_soc_enum struct contains the look-up table, while for enums it is NULL. This patch adds two new small helper functions called snd_soc_enum_item_to_val() and snd_soc_enum_val_to_item() which map between register value and control item. If the items field of the snd_soc_enum struct is NULL the function will do a direct mapping otherwise they'll use the look-up table to do the mapping. Using these small helper functions it is possible to use the same kcontrol handlers for both enums and value enums. The functions are added a inline functions in soc.h so they can also be used by the DAPM code to accomplish similar consolidation. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 49d6c10..60c700c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -195,11 +195,7 @@ .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \ .private_value = (unsigned long)&xenum } #define SOC_VALUE_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_get_value_enum_double, \ - .put = snd_soc_put_value_enum_double, \ - .private_value = (unsigned long)&xenum } + SOC_ENUM(xname, xenum) #define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -510,10 +506,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); #define snd_soc_info_bool_ext snd_ctl_boolean_mono_info @@ -1182,6 +1174,30 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, + unsigned int val) +{ + unsigned int i; + + if (!e->values) + return val; + + for (i = 0; i < e->items; i++) + if (val == e->values[i]) + return i; + + return 0; +} + +static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, + unsigned int item) +{ + if (!e->values) + return item; + + return e->values[item]; +} + int snd_soc_util_init(void); void snd_soc_util_exit(void); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8517338..2ddc7a4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2596,14 +2596,18 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; + unsigned int val, item; + unsigned int reg_val; - val = snd_soc_read(codec, e->reg); - ucontrol->value.enumerated.item[0] - = (val >> e->shift_l) & e->mask; - if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & e->mask; + reg_val = snd_soc_read(codec, e->reg); + val = (reg_val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[0] = item; + if (e->shift_l != e->shift_r) { + val = (reg_val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[1] = item; + } return 0; } @@ -2623,17 +2627,18 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; unsigned int val; unsigned int mask; - if (ucontrol->value.enumerated.item[0] >= e->items) + if (item[0] >= e->items) return -EINVAL; - val = ucontrol->value.enumerated.item[0] << e->shift_l; + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) + if (item[1] >= e->items) return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; + val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; mask |= e->mask << e->shift_r; } @@ -2642,80 +2647,6 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); /** - * snd_soc_get_value_enum_double - semi enumerated double mixer get callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value of a double semi enumerated mixer. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; - - reg_val = snd_soc_read(codec, e->reg); - val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[0] = mux; - if (e->shift_l != e->shift_r) { - val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[1] = mux; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double); - -/** - * snd_soc_put_value_enum_double - semi enumerated double mixer put callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value of a double semi enumerated mixer. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - unsigned int mask; - - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) - return -EINVAL; - val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - return snd_soc_update_bits_locked(codec, e->reg, mask, val); -} -EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); - -/** * snd_soc_read_signed - Read a codec register and interprete as signed value * @codec: codec * @reg: Register to read -- cgit v0.10.2 From 3727b4968453dbab8fe18f979d67285eb6b66801 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:04 +0100 Subject: ASoC: dapm: Consolidate MUXs and value MUXs MUXs and value MUXs are almost identical, the only difference is that a value MUX uses a look-up table to map from the selected control item to a register value, while MUXs use a direct mapping. This patch uses snd_soc_enum_item_to_val() and snd_soc_enum_val_to_item(), which where earlier introduced during the consolidation of enum and value enum controls, to hide this difference. This allows us to use the same code path for both MUXs and value MUXs and a lot of nearly duplicated code can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 3b99176..2ec14cb 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -112,9 +112,7 @@ struct device; SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_value_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1} + SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ @@ -324,11 +322,7 @@ struct device; .put = xput, \ .private_value = (unsigned long)&xenum } #define SOC_DAPM_VALUE_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_value_enum_double, \ - .put = snd_soc_dapm_put_value_enum_double, \ - .private_value = (unsigned long)&xenum } + SOC_DAPM_ENUM(xname, xenum) #define SOC_DAPM_PIN_SWITCH(xname) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \ .info = snd_soc_dapm_info_pin_switch, \ @@ -396,10 +390,6 @@ int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, @@ -486,7 +476,6 @@ enum snd_soc_dapm_type { snd_soc_dapm_output, /* output pin */ snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */ - snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_mixer, /* mixes several analog signals together */ snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 96a97a3df..f23eeee 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -71,7 +71,6 @@ static int dapm_up_seq[] = { [snd_soc_dapm_mic] = 5, [snd_soc_dapm_mux] = 6, [snd_soc_dapm_virt_mux] = 6, - [snd_soc_dapm_value_mux] = 6, [snd_soc_dapm_dac] = 7, [snd_soc_dapm_switch] = 8, [snd_soc_dapm_mixer] = 8, @@ -103,7 +102,6 @@ static int dapm_down_seq[] = { [snd_soc_dapm_micbias] = 8, [snd_soc_dapm_mux] = 9, [snd_soc_dapm_virt_mux] = 9, - [snd_soc_dapm_value_mux] = 9, [snd_soc_dapm_aif_in] = 10, [snd_soc_dapm_aif_out] = 10, [snd_soc_dapm_dai_in] = 10, @@ -534,7 +532,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, unsigned int val, item; soc_widget_read(w, e->reg, &val); - item = (val >> e->shift_l) & e->mask; + val = (val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; @@ -557,24 +556,6 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, p->connect = 1; } break; - case snd_soc_dapm_value_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - unsigned int val, item; - - soc_widget_read(w, e->reg, &val); - val = (val >> e->shift_l) & e->mask; - for (item = 0; item < e->items; item++) { - if (val == e->values[item]) - break; - } - - if (item < e->items && !strcmp(p->name, e->texts[item])) - p->connect = 1; - else - p->connect = 0; - } - break; /* does not affect routing - always connected */ case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: @@ -725,7 +706,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: wname_in_long_name = true; kcname_in_long_name = false; break; @@ -2463,7 +2443,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, return 0; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: ret = dapm_connect_mux(dapm, wsource, wsink, path, control, &wsink->kcontrol_news[0]); if (ret != 0) @@ -2791,7 +2770,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: dapm_new_mux(w); break; case snd_soc_dapm_pga: @@ -2953,13 +2931,16 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; + unsigned int reg_val, val; - val = snd_soc_read(codec, e->reg); - ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; - if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & e->mask; + reg_val = snd_soc_read(codec, e->reg); + val = (reg_val >> e->shift_l) & e->mask; + ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); + if (e->shift_l != e->shift_r) { + val = (reg_val >> e->shift_r) & e->mask; + val = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[1] = val; + } return 0; } @@ -2980,20 +2961,21 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux, change; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, change; unsigned int mask; struct snd_soc_dapm_update update; int ret = 0; - if (ucontrol->value.enumerated.item[0] >= e->items) + if (item[0] >= e->items) return -EINVAL; - mux = ucontrol->value.enumerated.item[0]; - val = mux << e->shift_l; + + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) + if (item[1] > e->items) return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; + val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l; mask |= e->mask << e->shift_r; } @@ -3007,7 +2989,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, update.val = val; card->update = &update; - ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); + ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); card->update = NULL; } @@ -3074,106 +3056,6 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); /** - * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get - * callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value of a dapm semi enumerated double mixer control. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; - - reg_val = snd_soc_read(codec, e->reg); - val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[0] = mux; - if (e->shift_l != e->shift_r) { - val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[1] = mux; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); - -/** - * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set - * callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value of a dapm semi enumerated double mixer control. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux, change; - unsigned int mask; - struct snd_soc_dapm_update update; - int ret = 0; - - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - mux = ucontrol->value.enumerated.item[0]; - val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) - return -EINVAL; - val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - - change = snd_soc_test_bits(codec, e->reg, mask, val); - if (change) { - update.kcontrol = kcontrol; - update.reg = e->reg; - update.mask = mask; - update.val = val; - card->update = &update; - - ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); - - card->update = NULL; - } - - mutex_unlock(&card->dapm_mutex); - - if (ret > 0) - soc_dpcm_runtime_update(card); - - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); - -/** * snd_soc_dapm_info_pin_switch - Info for a pin switch * * @kcontrol: mixer control @@ -3302,7 +3184,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_dai_out: -- cgit v0.10.2 From b948837a32cc2a510c2baf90111c8c5dde801a66 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:05 +0100 Subject: ASoC: Add macros for defining virtual enums With the upcoming consolidation of normal MUXs and virtual MUXs we need to be able to distinguish between enums with and without a backing register at the enum level. Use the same approach as used for virtual mixer controls by setting the reg field of the enum to SND_SOC_NOPM for enums without a backing register. This patch adds a set of helper macros that can be used to define such enums. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 60c700c..08cb677 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -189,6 +189,8 @@ .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} #define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues) +#define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \ + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ .info = snd_soc_info_enum_double, \ @@ -293,6 +295,8 @@ ARRAY_SIZE(xtexts), xtexts, xvalues) #define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) +#define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ + const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) /* * Component probe and remove ordering levels for components with runtime @@ -1092,7 +1096,7 @@ struct soc_mreg_control { /* enumerated kcontrol */ struct soc_enum { - unsigned short reg; + int reg; unsigned char shift_l; unsigned char shift_r; unsigned int items; -- cgit v0.10.2 From 28963178427386e83788d314d2a05f0c093f836a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:06 +0100 Subject: ASoC: adau1373: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 5765c22..5223800 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = { "DMIC1", }; -static SOC_ENUM_SINGLE_DECL(adau1373_decimator_enum, - 0, 0, adau1373_decimator_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adau1373_decimator_enum, + adau1373_decimator_text); static const struct snd_kcontrol_new adau1373_decimator_mux = SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); -- cgit v0.10.2 From ba513116403bc93072dd54a1f89dacdb4d89fcab Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:07 +0100 Subject: ASoC: max98090: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index c7b9e90..1686ade 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -871,7 +871,7 @@ static const struct snd_kcontrol_new max98090_mic2_mux = static const char *dmic_mux_text[] = { "ADC", "DMIC" }; -static SOC_ENUM_SINGLE_EXT_DECL(dmic_mux_enum, dmic_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text); static const struct snd_kcontrol_new max98090_dmic_mux = SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); -- cgit v0.10.2 From 15ab40a9a83035d92b4f4c83cb88c7529bf73c71 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:08 +0100 Subject: ASoC: mc13783: Use SOC_ENUM_SINGLE_VIRT_DECL() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Tested-by: Philippe Rétornaz Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index c605036..ec89b8f 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -408,8 +408,7 @@ static const char * const adcl_enum_text[] = { "MC1L", "RXINL", }; -static SOC_ENUM_SINGLE_DECL(adcl_enum, - 0, 0, adcl_enum_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adcl_enum, adcl_enum_text); static const struct snd_kcontrol_new left_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcl_enum); @@ -418,8 +417,7 @@ static const char * const adcr_enum_text[] = { "MC1R", "MC2", "RXINR", "TXIN", }; -static SOC_ENUM_SINGLE_DECL(adcr_enum, - 0, 0, adcr_enum_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adcr_enum, adcr_enum_text); static const struct snd_kcontrol_new right_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcr_enum); -- cgit v0.10.2 From 86d4c9ab28b73f9eeb8cbd3b11cb2f2aee079a00 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:09 +0100 Subject: ASoC: wm8994: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 699b527..79854cb 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1344,8 +1344,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static SOC_ENUM_SINGLE_DECL(adc_enum, - 0, 0, adc_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); -- cgit v0.10.2 From f6b45c28f451e8e415db49f693b2fec90c2cb557 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:10 +0100 Subject: ASoC: wm8995: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 33ff361..ddb197d 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -882,7 +882,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static const SOC_ENUM_SINGLE_DECL(adc_enum, 0, 0, adc_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); -- cgit v0.10.2 From 236aaa6863581634bd6d599ccf7f7b38deeafdc0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:11 +0100 Subject: ASoC: dapm: Consolidate MUXs and virtual MUXs MUXs and virtual MUXs are almost identical, the only difference is that for virtual MUX there is no hardware backing register in which setting is stored. This patch adds code, which is similar to what we already do for DAPM mixer controls to support virtual mixer controls, to DAPM enum controls. The new code will check if the enum does a hardware backing register and skip over reading and writing to the register if it has not. This allows us to use the same code path for both MUXs and virtual MUXs and a lot of nearly identical code can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 2ec14cb..04d32d8 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -108,9 +108,7 @@ struct device; SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_virt_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1} + SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) @@ -170,10 +168,8 @@ struct device; .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ wevent, wflags) \ -{ .id = snd_soc_dapm_virt_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1, \ - .event = wevent, .event_flags = wflags} + SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, wevent, \ + wflags) /* additional sequencing control within an event type */ #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ @@ -309,12 +305,8 @@ struct device; .get = snd_soc_dapm_get_enum_double, \ .put = snd_soc_dapm_put_enum_double, \ .private_value = (unsigned long)&xenum } -#define SOC_DAPM_ENUM_VIRT(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_virt, \ - .put = snd_soc_dapm_put_enum_virt, \ - .private_value = (unsigned long)&xenum } +#define SOC_DAPM_ENUM_VIRT(xname, xenum) \ + SOC_DAPM_ENUM(xname, xenum) #define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_enum_double, \ @@ -386,10 +378,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, @@ -475,7 +463,6 @@ enum snd_soc_dapm_type { snd_soc_dapm_input = 0, /* input pin */ snd_soc_dapm_output, /* output pin */ snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ - snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */ snd_soc_dapm_mixer, /* mixes several analog signals together */ snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f23eeee..c07c7fb 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -70,7 +70,6 @@ static int dapm_up_seq[] = { [snd_soc_dapm_aif_out] = 4, [snd_soc_dapm_mic] = 5, [snd_soc_dapm_mux] = 6, - [snd_soc_dapm_virt_mux] = 6, [snd_soc_dapm_dac] = 7, [snd_soc_dapm_switch] = 8, [snd_soc_dapm_mixer] = 8, @@ -101,7 +100,6 @@ static int dapm_down_seq[] = { [snd_soc_dapm_mic] = 7, [snd_soc_dapm_micbias] = 8, [snd_soc_dapm_mux] = 9, - [snd_soc_dapm_virt_mux] = 9, [snd_soc_dapm_aif_in] = 10, [snd_soc_dapm_aif_out] = 10, [snd_soc_dapm_dai_in] = 10, @@ -531,9 +529,19 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, w->kcontrol_news[i].private_value; unsigned int val, item; - soc_widget_read(w, e->reg, &val); - val = (val >> e->shift_l) & e->mask; - item = snd_soc_enum_val_to_item(e, val); + if (e->reg != SND_SOC_NOPM) { + soc_widget_read(w, e->reg, &val); + val = (val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + } else { + /* since a virtual mux has no backing registers to + * decide which path to connect, it will try to match + * with the first enumeration. This is to ensure + * that the default mux choice (the first) will be + * correctly powered up during initialization. + */ + item = 0; + } if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; @@ -541,21 +549,6 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, p->connect = 0; } break; - case snd_soc_dapm_virt_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - - p->connect = 0; - /* since a virtual mux has no backing registers to - * decide which path to connect, it will try to match - * with the first enumeration. This is to ensure - * that the default mux choice (the first) will be - * correctly powered up during initialization. - */ - if (!strcmp(p->name, e->texts[0])) - p->connect = 1; - } - break; /* does not affect routing - always connected */ case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: @@ -705,7 +698,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, kcname_in_long_name = true; break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: wname_in_long_name = true; kcname_in_long_name = false; break; @@ -2442,7 +2434,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, path->connect = 1; return 0; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: ret = dapm_connect_mux(dapm, wsource, wsink, path, control, &wsink->kcontrol_news[0]); if (ret != 0) @@ -2769,7 +2760,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) dapm_new_mixer(w); break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: dapm_new_mux(w); break; case snd_soc_dapm_pga: @@ -2933,7 +2923,11 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int reg_val, val; - reg_val = snd_soc_read(codec, e->reg); + if (e->reg != SND_SOC_NOPM) + reg_val = snd_soc_read(codec, e->reg); + else + reg_val = dapm_kcontrol_get_value(kcontrol); + val = (reg_val >> e->shift_l) & e->mask; ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); if (e->shift_l != e->shift_r) { @@ -2981,13 +2975,19 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - change = snd_soc_test_bits(codec, e->reg, mask, val); + if (e->reg != SND_SOC_NOPM) + change = snd_soc_test_bits(codec, e->reg, mask, val); + else + change = dapm_kcontrol_set_value(kcontrol, val); + if (change) { - update.kcontrol = kcontrol; - update.reg = e->reg; - update.mask = mask; - update.val = val; - card->update = &update; + if (e->reg != SND_SOC_NOPM) { + update.kcontrol = kcontrol; + update.reg = e->reg; + update.mask = mask; + update.val = val; + card->update = &update; + } ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); @@ -3004,58 +3004,6 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); /** - * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Returns 0 for success. - */ -int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol); - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); - -/** - * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Returns 0 for success. - */ -int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; - unsigned int value; - struct soc_enum *e = - (struct soc_enum *)kcontrol->private_value; - int change; - int ret = 0; - - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - - value = ucontrol->value.enumerated.item[0]; - change = dapm_kcontrol_set_value(kcontrol, value); - if (change) - ret = soc_dapm_mux_update_power(card, kcontrol, value, e); - - mutex_unlock(&card->dapm_mutex); - - if (ret > 0) - soc_dpcm_runtime_update(card); - - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); - -/** * snd_soc_dapm_info_pin_switch - Info for a pin switch * * @kcontrol: mixer control @@ -3183,7 +3131,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_dai_out: -- cgit v0.10.2 From 234c0b8fb0db790aaebec07d1d190e789d8ec7b9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:12 +0100 Subject: ASoC: dapm: Break dapm_set_path_status() appart There are three different completely independent code paths in dapm_set_path_status(). One of them is never used at all and the other two (one for mixers, one for MUXs) have their distincive callsites that always go onto the same path. Breaking the function into two parts allows us to reduce the code size and in the MUX case also do some optimizations to avoid having to calcualte the selected item for each item again. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c07c7fb..3651a37 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -495,93 +495,6 @@ out: return ret; } -/* set up initial codec paths */ -static void dapm_set_path_status(struct snd_soc_dapm_widget *w, - struct snd_soc_dapm_path *p, int i) -{ - switch (w->id) { - case snd_soc_dapm_switch: - case snd_soc_dapm_mixer: - case snd_soc_dapm_mixer_named_ctl: { - unsigned int val; - struct soc_mixer_control *mc = (struct soc_mixer_control *) - w->kcontrol_news[i].private_value; - int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - if (reg != SND_SOC_NOPM) { - soc_widget_read(w, reg, &val); - val = (val >> shift) & mask; - if (invert) - val = max - val; - p->connect = !!val; - } else { - p->connect = 0; - } - - } - break; - case snd_soc_dapm_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - unsigned int val, item; - - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(w, e->reg, &val); - val = (val >> e->shift_l) & e->mask; - item = snd_soc_enum_val_to_item(e, val); - } else { - /* since a virtual mux has no backing registers to - * decide which path to connect, it will try to match - * with the first enumeration. This is to ensure - * that the default mux choice (the first) will be - * correctly powered up during initialization. - */ - item = 0; - } - - if (item < e->items && !strcmp(p->name, e->texts[item])) - p->connect = 1; - else - p->connect = 0; - } - break; - /* does not affect routing - always connected */ - case snd_soc_dapm_pga: - case snd_soc_dapm_out_drv: - case snd_soc_dapm_output: - case snd_soc_dapm_adc: - case snd_soc_dapm_input: - case snd_soc_dapm_siggen: - case snd_soc_dapm_dac: - case snd_soc_dapm_micbias: - case snd_soc_dapm_vmid: - case snd_soc_dapm_supply: - case snd_soc_dapm_regulator_supply: - case snd_soc_dapm_clock_supply: - case snd_soc_dapm_aif_in: - case snd_soc_dapm_aif_out: - case snd_soc_dapm_dai_in: - case snd_soc_dapm_dai_out: - case snd_soc_dapm_hp: - case snd_soc_dapm_mic: - case snd_soc_dapm_spk: - case snd_soc_dapm_line: - case snd_soc_dapm_dai_link: - case snd_soc_dapm_kcontrol: - p->connect = 1; - break; - /* does affect routing - dynamically connected */ - case snd_soc_dapm_pre: - case snd_soc_dapm_post: - p->connect = 0; - break; - } -} - /* connect mux widget to its interconnecting audio paths */ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, @@ -589,15 +502,33 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, const struct snd_kcontrol_new *kcontrol) { struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val, item; int i; + if (e->reg != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg, &val); + val = (val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + } else { + /* since a virtual mux has no backing registers to + * decide which path to connect, it will try to match + * with the first enumeration. This is to ensure + * that the default mux choice (the first) will be + * correctly powered up during initialization. + */ + item = 0; + } + for (i = 0; i < e->items; i++) { if (!(strcmp(control_name, e->texts[i]))) { list_add(&path->list, &dapm->card->paths); list_add(&path->list_sink, &dest->sources); list_add(&path->list_source, &src->sinks); path->name = (char*)e->texts[i]; - dapm_set_path_status(dest, path, 0); + if (i == item) + path->connect = 1; + else + path->connect = 0; return 0; } } @@ -605,6 +536,30 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, return -ENODEV; } +/* set up initial codec paths */ +static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_path *p, int i) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *) + w->kcontrol_news[i].private_value; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int val; + + if (reg != SND_SOC_NOPM) { + soc_widget_read(w, reg, &val); + val = (val >> shift) & mask; + if (invert) + val = max - val; + p->connect = !!val; + } else { + p->connect = 0; + } +} + /* connect mixer widget to its interconnecting audio paths */ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, @@ -619,7 +574,7 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, list_add(&path->list_sink, &dest->sources); list_add(&path->list_source, &src->sinks); path->name = dest->kcontrol_news[i].name; - dapm_set_path_status(dest, path, i); + dapm_set_mixer_path_status(dest, path, i); return 0; } } -- cgit v0.10.2 From b7e63a1079b266866a732cf699d8c4d61391bbda Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 26 Feb 2014 11:19:14 -0800 Subject: NFSv4: Fix another nfs4_sequence corruptor nfs4_release_lockowner needs to set the rpc_message reply to point to the nfs4_sequence_res in order to avoid another Oopsable situation in nfs41_assign_slot. Fixes: fbd4bfd1d9d21 (NFS: Add nfs4_sequence calls for RELEASE_LOCKOWNER) Cc: stable@vger.kernel.org # 3.12+ Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 2da6a69..44e088d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5828,8 +5828,7 @@ struct nfs_release_lockowner_data { struct nfs4_lock_state *lsp; struct nfs_server *server; struct nfs_release_lockowner_args args; - struct nfs4_sequence_args seq_args; - struct nfs4_sequence_res seq_res; + struct nfs_release_lockowner_res res; unsigned long timestamp; }; @@ -5837,7 +5836,7 @@ static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata { struct nfs_release_lockowner_data *data = calldata; nfs40_setup_sequence(data->server, - &data->seq_args, &data->seq_res, task); + &data->args.seq_args, &data->res.seq_res, task); data->timestamp = jiffies; } @@ -5846,7 +5845,7 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) struct nfs_release_lockowner_data *data = calldata; struct nfs_server *server = data->server; - nfs40_sequence_done(task, &data->seq_res); + nfs40_sequence_done(task, &data->res.seq_res); switch (task->tk_status) { case 0: @@ -5887,7 +5886,6 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st data = kmalloc(sizeof(*data), GFP_NOFS); if (!data) return -ENOMEM; - nfs4_init_sequence(&data->seq_args, &data->seq_res, 0); data->lsp = lsp; data->server = server; data->args.lock_owner.clientid = server->nfs_client->cl_clientid; @@ -5895,6 +5893,8 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st data->args.lock_owner.s_dev = server->s_dev; msg.rpc_argp = &data->args; + msg.rpc_resp = &data->res; + nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); return 0; } diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index b2fb167..5624e4e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -467,9 +467,14 @@ struct nfs_lockt_res { }; struct nfs_release_lockowner_args { + struct nfs4_sequence_args seq_args; struct nfs_lowner lock_owner; }; +struct nfs_release_lockowner_res { + struct nfs4_sequence_res seq_res; +}; + struct nfs4_delegreturnargs { struct nfs4_sequence_args seq_args; const struct nfs_fh *fhandle; -- cgit v0.10.2 From b355cee88e3b1a193f0e9a81db810f6f83ad728b Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 27 Feb 2014 11:37:15 +0800 Subject: ACPI / resources: ignore invalid ACPI device resources ACPI table may export resource entry with 0 length. But the current code interprets this kind of resource in a wrong way. It will create a resource structure with res->end = acpi_resource->start + acpi_resource->len - 1; This patch fixes a problem on my machine that a platform device fails to be created because one of its ACPI IO resource entry (start = 0, end = 0, length = 0) is translated into a generic resource with start = 0, end = 0xffffffff. Signed-off-by: Zhang Rui Cc: All applicable Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index b7201fc..0bdacc5 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -77,18 +77,24 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) switch (ares->type) { case ACPI_RESOURCE_TYPE_MEMORY24: memory24 = &ares->data.memory24; + if (!memory24->address_length) + return false; acpi_dev_get_memresource(res, memory24->minimum, memory24->address_length, memory24->write_protect); break; case ACPI_RESOURCE_TYPE_MEMORY32: memory32 = &ares->data.memory32; + if (!memory32->address_length) + return false; acpi_dev_get_memresource(res, memory32->minimum, memory32->address_length, memory32->write_protect); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: fixed_memory32 = &ares->data.fixed_memory32; + if (!fixed_memory32->address_length) + return false; acpi_dev_get_memresource(res, fixed_memory32->address, fixed_memory32->address_length, fixed_memory32->write_protect); @@ -144,12 +150,16 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) switch (ares->type) { case ACPI_RESOURCE_TYPE_IO: io = &ares->data.io; + if (!io->address_length) + return false; acpi_dev_get_ioresource(res, io->minimum, io->address_length, io->io_decode); break; case ACPI_RESOURCE_TYPE_FIXED_IO: fixed_io = &ares->data.fixed_io; + if (!fixed_io->address_length) + return false; acpi_dev_get_ioresource(res, fixed_io->address, fixed_io->address_length, ACPI_DECODE_10); -- cgit v0.10.2 From ae2045694b3353bf2b2980817303c9e9feb8cfff Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 28 Feb 2014 13:31:04 +0100 Subject: drm/vmwgfx: Remove some unused surface formats These formats are deprecated. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul diff --git a/drivers/gpu/drm/vmwgfx/svga3d_reg.h b/drivers/gpu/drm/vmwgfx/svga3d_reg.h index bb594c1..f58dc7d 100644 --- a/drivers/gpu/drm/vmwgfx/svga3d_reg.h +++ b/drivers/gpu/drm/vmwgfx/svga3d_reg.h @@ -261,12 +261,7 @@ typedef enum SVGA3dSurfaceFormat { /* Planar video formats. */ SVGA3D_YV12 = 121, - /* Shader constant formats. */ - SVGA3D_SURFACE_SHADERCONST_FLOAT = 122, - SVGA3D_SURFACE_SHADERCONST_INT = 123, - SVGA3D_SURFACE_SHADERCONST_BOOL = 124, - - SVGA3D_FORMAT_MAX = 125, + SVGA3D_FORMAT_MAX = 122, } SVGA3dSurfaceFormat; typedef uint32 SVGA3dColor; /* a, r, g, b */ -- cgit v0.10.2 From a34417f6be521d1027b803f0b550ce622c971f41 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 28 Feb 2014 13:33:21 +0100 Subject: drm/vmwgfx: Make sure backing mobs are cleared when allocated. Update driver date. Backing mob contents is propagated to user-space, so make sure backing mobs are cleared when allocated. This also accidently fix rendering errors with celestia when emulating legacy mode. Also update driver date. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 9e4be17..0783155 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -40,7 +40,7 @@ #include #include "vmwgfx_fence.h" -#define VMWGFX_DRIVER_DATE "20121114" +#define VMWGFX_DRIVER_DATE "20140228" #define VMWGFX_DRIVER_MAJOR 2 #define VMWGFX_DRIVER_MINOR 5 #define VMWGFX_DRIVER_PATCHLEVEL 0 diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 2aa4bc6..9757b57 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -427,8 +427,7 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, INIT_LIST_HEAD(&vmw_bo->res_list); ret = ttm_bo_init(bdev, &vmw_bo->base, size, - (user) ? ttm_bo_type_device : - ttm_bo_type_kernel, placement, + ttm_bo_type_device, placement, 0, interruptible, NULL, acc_size, NULL, bo_free); return ret; -- cgit v0.10.2 From 6950e23e54b1c94abf8c60c1ddfac79133d41de2 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 1 Mar 2014 01:20:18 +0400 Subject: drm/vmwgfx: avoid null pointer dereference at failure paths vmw_takedown_otable_base() and vmw_mob_unbind() check for potential vmw_fifo_reserve() failure and print error message, but then immediately dereference NULL pointer. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Reviewed-by: Thomas Hellstrom diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c index d4a5a19..04a64b8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c @@ -188,18 +188,20 @@ static void vmw_takedown_otable_base(struct vmw_private *dev_priv, bo = otable->page_table->pt_bo; cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) - DRM_ERROR("Failed reserving FIFO space for OTable setup.\n"); - - memset(cmd, 0, sizeof(*cmd)); - cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE; - cmd->header.size = sizeof(cmd->body); - cmd->body.type = type; - cmd->body.baseAddress = 0; - cmd->body.sizeInBytes = 0; - cmd->body.validSizeInBytes = 0; - cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID; - vmw_fifo_commit(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) { + DRM_ERROR("Failed reserving FIFO space for OTable " + "takedown.\n"); + } else { + memset(cmd, 0, sizeof(*cmd)); + cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE; + cmd->header.size = sizeof(cmd->body); + cmd->body.type = type; + cmd->body.baseAddress = 0; + cmd->body.sizeInBytes = 0; + cmd->body.validSizeInBytes = 0; + cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID; + vmw_fifo_commit(dev_priv, sizeof(*cmd)); + } if (bo) { int ret; @@ -562,11 +564,12 @@ void vmw_mob_unbind(struct vmw_private *dev_priv, if (unlikely(cmd == NULL)) { DRM_ERROR("Failed reserving FIFO space for Memory " "Object unbinding.\n"); + } else { + cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB; + cmd->header.size = sizeof(cmd->body); + cmd->body.mobid = mob->id; + vmw_fifo_commit(dev_priv, sizeof(*cmd)); } - cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB; - cmd->header.size = sizeof(cmd->body); - cmd->body.mobid = mob->id; - vmw_fifo_commit(dev_priv, sizeof(*cmd)); if (bo) { vmw_fence_single_bo(bo, NULL); ttm_bo_unreserve(bo); -- cgit v0.10.2 From ae41a3030ce8901853b3cfd5e118a4b0288aa068 Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Sat, 1 Mar 2014 14:58:48 +0100 Subject: ARM: dts: omap3-gta04: Add ti,omap36xx to compatible property to avoid problems with booting Without that change booting leads to crash with more warnings like below: [ 0.284454] omap_hwmod: uart4: cannot clk_get main_clk uart4_fck [ 0.284484] omap_hwmod: uart4: cannot _init_clocks [ 0.284484] ------------[ cut here ]------------ [ 0.284545] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/omap_hwmod.c:2543 _init+0x300/0x3e4() [ 0.284545] omap_hwmod: uart4: couldn't init clocks [ 0.284576] Modules linked in: [ 0.284606] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.13.0-next-20140124-00020-gd2aefec-dirty #26 [ 0.284637] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [ 0.284667] [] (show_stack) from [] (dump_stack+0x7c/0x94) [ 0.284729] [] (dump_stack) from [] (warn_slowpath_common+0x6c/0x90) [ 0.284729] [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) [ 0.284759] [] (warn_slowpath_fmt) from [] (_init+0x300/0x3e4) [ 0.284790] [] (_init) from [] (__omap_hwmod_setup_all+0x40/0x8c) [ 0.284820] [] (__omap_hwmod_setup_all) from [] (do_one_initcall+0xe8/0x14c) [ 0.284851] [] (do_one_initcall) from [] (kernel_init_freeable+0x104/0x1c8) [ 0.284881] [] (kernel_init_freeable) from [] (kernel_init+0x8/0x118) [ 0.284912] [] (kernel_init) from [] (ret_from_fork+0x14/0x2c) [ 0.285064] ---[ end trace 63de210ad43b627d ]--- Reference: https://lkml.org/lkml/2013/10/8/553 Signed-off-by: Marek Belisko Signed-off-by: Tony Lindgren diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index c551e4a..d3b253b 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts @@ -13,7 +13,7 @@ / { model = "OMAP3 GTA04"; - compatible = "ti,omap3-gta04", "ti,omap3"; + compatible = "ti,omap3-gta04", "ti,omap36xx", "ti,omap3"; cpus { cpu@0 { -- cgit v0.10.2 From 3130497f5babd42b24a7febda46b46116e0adc83 Mon Sep 17 00:00:00 2001 From: "Li, Aubrey" Date: Sun, 2 Mar 2014 08:53:57 +0800 Subject: ACPI / sleep: pm_power_off needs more sanity checks to be installed Sleep control and status registers need santity checks as well before ACPI installs acpi_power_off to pm_power_off hook. The checking code in acpi_enter_sleep_state() is too late, we should not allow a not-working pm_power_off function to be hooked up. Signed-off-by: Aubrey Li Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index b718806..b0f6c4a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -807,7 +807,12 @@ int __init acpi_sleep_init(void) acpi_sleep_hibernate_setup(); status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { + /* + * Check both ACPI S5 object and ACPI sleep registers to + * install pm_power_off_prepare/pm_power_off hook + */ + if (ACPI_SUCCESS(status) && acpi_gbl_FADT.sleep_control.address + && acpi_gbl_FADT.sleep_status.address) { sleep_states[ACPI_STATE_S5] = 1; pm_power_off_prepare = acpi_power_off_prepare; pm_power_off = acpi_power_off; -- cgit v0.10.2 From 25d54fe5657f74766f2c79ad1267320793403f9e Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 2 Mar 2014 17:29:33 +0100 Subject: b44: add calls to phy_{start,stop} When support for external phys was added to b44, the calls to start and stop the phy were missing in the mac driver. This adds the calls to phy_start() and phy_stop(). Signed-off-by: Hauke Mehrtens Acked-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 1f7b5aa..e8046e1 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -1484,6 +1484,10 @@ static int b44_open(struct net_device *dev) add_timer(&bp->timer); b44_enable_ints(bp); + + if (bp->flags & B44_FLAG_EXTERNAL_PHY) + phy_start(bp->phydev); + netif_start_queue(dev); out: return err; @@ -1646,6 +1650,9 @@ static int b44_close(struct net_device *dev) netif_stop_queue(dev); + if (bp->flags & B44_FLAG_EXTERNAL_PHY) + phy_stop(bp->phydev); + napi_disable(&bp->napi); del_timer_sync(&bp->timer); -- cgit v0.10.2 From 1d3f41ea0e95bed0502a7ac3f42fdc23ca6b7b82 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 2 Mar 2014 17:29:34 +0100 Subject: b44: always set duplex mode why phy changes Without this patch b44_check_phy() was called when the phy called the adjust callback. This method only change the mac duplex mode when the carrier was off. When the phy changed the duplex mode after the carrier was on the mac was not changed. This happened when an external phy was used. Signed-off-by: Hauke Mehrtens Acked-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index e8046e1..8a7bf7d 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -2229,7 +2229,12 @@ static void b44_adjust_link(struct net_device *dev) } if (status_changed) { - b44_check_phy(bp); + u32 val = br32(bp, B44_TX_CTRL); + if (bp->flags & B44_FLAG_FULL_DUPLEX) + val |= TX_CTRL_DUPLEX; + else + val &= ~TX_CTRL_DUPLEX; + bw32(bp, B44_TX_CTRL, val); phy_print_status(phydev); } } -- cgit v0.10.2 From 498480731e232d7c9a96a338924b5a275121e091 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:14:33 -0800 Subject: ASoC: rsnd: move priv member settings to upper side There is no big meaning, but preparation for platform dai support Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f316a66..a8e6aa6 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -594,6 +594,10 @@ static int rsnd_dai_probe(struct platform_device *pdev, return -ENOMEM; } + priv->dai_nr = dai_nr; + priv->daidrv = drv; + priv->rdai = rdai; + for (i = 0; i < dai_nr; i++) { pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); @@ -630,10 +634,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, cmod ? "capture" : " -- "); } - priv->dai_nr = dai_nr; - priv->daidrv = drv; - priv->rdai = rdai; - return 0; } -- cgit v0.10.2 From d870a91e9d0eae524ac2da7cbdc7e399a71b86c4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:14:41 -0800 Subject: ASoC: rsnd: move rsnd_mod_call() macro core.c is the only user of rsnd_mod_call() macro. Move it to core.c from rsnd.h Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index a8e6aa6..5f6d9fe 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -291,16 +291,30 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * rsnd_dai functions */ -#define rsnd_dai_call(rdai, io, fn) \ -({ \ - struct rsnd_mod *mod, *n; \ - int ret = 0; \ - for_each_rsnd_mod(mod, n, io) { \ - ret = rsnd_mod_call(mod, fn, rdai, io); \ - if (ret < 0) \ - break; \ - } \ - ret; \ +#define __rsnd_mod_call(mod, func, rdai, io) \ +({ \ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ + struct device *dev = rsnd_priv_to_dev(priv); \ + dev_dbg(dev, "%s [%d] %s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + (mod)->ops->func(mod, rdai, io); \ +}) + +#define rsnd_mod_call(mod, func, rdai, io) \ + (!(mod) ? -ENODEV : \ + !((mod)->ops->func) ? 0 : \ + __rsnd_mod_call(mod, func, (rdai), (io))) + +#define rsnd_dai_call(rdai, io, fn) \ +({ \ + struct rsnd_mod *mod, *n; \ + int ret = 0; \ + for_each_rsnd_mod(mod, n, (io)) { \ + ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ + if (ret < 0) \ + break; \ + } \ + ret; \ }) int rsnd_dai_connect(struct rsnd_dai *rdai, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d409390..fb1e0ce 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -169,19 +169,6 @@ struct rsnd_mod { #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) -#define __rsnd_mod_call(mod, func, rdai, io) \ -({ \ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ - struct device *dev = rsnd_priv_to_dev(priv); \ - dev_dbg(dev, "%s-%d-%s\n", \ - rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ - (mod)->ops->func(mod, rdai, io); \ -}) - -#define rsnd_mod_call(mod, func, rdai, io) \ - (!(mod) ? -ENODEV : \ - !((mod)->ops->func) ? 0 : \ - __rsnd_mod_call(mod, func, rdai, io)) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, -- cgit v0.10.2 From 5da39cf30454bbf3e92f56935e7d137e5bd2c830 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:00 -0800 Subject: ASoC: rsnd: remove verbose function parameter priv has rcar_snd_info pointer. having priv and info in same time is verbose. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index af9e440..69d9394 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -391,7 +391,6 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) } int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct rsnd_adg *adg; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 5f6d9fe..b2370f6 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -577,7 +577,6 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { }; static int rsnd_dai_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; @@ -773,23 +772,23 @@ static int rsnd_probe(struct platform_device *pdev) /* * init each module */ - ret = rsnd_gen_probe(pdev, info, priv); + ret = rsnd_gen_probe(pdev, priv); if (ret) return ret; - ret = rsnd_ssi_probe(pdev, info, priv); + ret = rsnd_ssi_probe(pdev, priv); if (ret) return ret; - ret = rsnd_scu_probe(pdev, info, priv); + ret = rsnd_scu_probe(pdev, priv); if (ret) return ret; - ret = rsnd_adg_probe(pdev, info, priv); + ret = rsnd_adg_probe(pdev, priv); if (ret) return ret; - ret = rsnd_dai_probe(pdev, info, priv); + ret = rsnd_dai_probe(pdev, priv); if (ret) return ret; diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 0a43b90..bcb98f4 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -276,7 +276,6 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen2_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -374,7 +373,6 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen1_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -419,7 +417,6 @@ static int rsnd_gen1_probe(struct platform_device *pdev, * Gen */ int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -436,9 +433,9 @@ int rsnd_gen_probe(struct platform_device *pdev, ret = -ENODEV; if (rsnd_is_gen1(priv)) - ret = rsnd_gen1_probe(pdev, info, priv); + ret = rsnd_gen1_probe(pdev, priv); else if (rsnd_is_gen2(priv)) - ret = rsnd_gen2_probe(pdev, info, priv); + ret = rsnd_gen2_probe(pdev, priv); if (ret < 0) dev_err(dev, "unknown generation R-Car sound device\n"); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index fb1e0ce..8ac28ac 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -226,7 +226,6 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); * R-Car Gen1/Gen2 */ int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -248,7 +247,6 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -305,6 +303,7 @@ struct rsnd_priv { }; #define rsnd_priv_to_dev(priv) ((priv)->dev) +#define rsnd_priv_to_info(priv) ((priv)->info) #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) @@ -312,7 +311,6 @@ struct rsnd_priv { * R-Car SCU */ int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -327,7 +325,6 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, * R-Car SSI */ int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_priv *priv); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 3984d4b..82d8b20 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -604,9 +604,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) } int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_scu *scu; struct rsnd_mod_ops *ops; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d3371d7..2460c9f 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -511,9 +511,9 @@ static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *s } int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_ssi_platform_info *pinfo; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; -- cgit v0.10.2 From 98455ed5ddbfbcbcd0adb300c6cb1964ed0a6931 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:07 -0800 Subject: ASoC: rsnd: remove verbose debug message from scu/ssi scu/ssi probe() already have more detail debug message. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 82d8b20..882e837 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -663,7 +663,6 @@ int rsnd_scu_probe(struct platform_device *pdev, dev_dbg(dev, "SCU%d probed\n", i); } - dev_dbg(dev, "scu probed\n"); return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2460c9f..38a62a8 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -589,8 +589,6 @@ int rsnd_ssi_probe(struct platform_device *pdev, rsnd_ssi_parent_clk_setup(priv, ssi); } - dev_dbg(dev, "ssi probed\n"); - return 0; } -- cgit v0.10.2 From ecba9e724c5775aebd3a28e831643160c7146e83 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:18 -0800 Subject: ASoC: rsnd: unify rdai naming struct rsnd_dai is called as "rdai", but its size has been called as "dai_nr". Unify these as "rdai" Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index b2370f6..f0745af 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -352,7 +352,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) { int id = rdai - priv->rdai; - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return -EINVAL; return id; @@ -360,7 +360,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) { - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return NULL; return priv->rdai + id; @@ -607,7 +607,7 @@ static int rsnd_dai_probe(struct platform_device *pdev, return -ENOMEM; } - priv->dai_nr = dai_nr; + priv->rdai_nr = dai_nr; priv->daidrv = drv; priv->rdai = rdai; @@ -802,7 +802,7 @@ static int rsnd_probe(struct platform_device *pdev) } ret = snd_soc_register_component(dev, &rsnd_soc_component, - priv->daidrv, rsnd_dai_nr(priv)); + priv->daidrv, rsnd_rdai_nr(priv)); if (ret < 0) { dev_err(dev, "cannot snd dai register\n"); goto exit_snd_soc; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8ac28ac..3962a50 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -202,10 +202,10 @@ struct rsnd_dai { unsigned int data_alignment:1; }; -#define rsnd_dai_nr(priv) ((priv)->dai_nr) +#define rsnd_rdai_nr(priv) ((priv)->rdai_nr) #define for_each_rsnd_dai(rdai, priv, i) \ for (i = 0; \ - (i < rsnd_dai_nr(priv)) && \ + (i < rsnd_rdai_nr(priv)) && \ ((rdai) = rsnd_dai_get(priv, i)); \ i++) @@ -299,7 +299,7 @@ struct rsnd_priv { */ struct snd_soc_dai_driver *daidrv; struct rsnd_dai *rdai; - int dai_nr; + int rdai_nr; }; #define rsnd_priv_to_dev(priv) ((priv)->dev) -- cgit v0.10.2 From 697dce94ed37e0653e5bba593f11e2b14877cd63 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:33 -0800 Subject: ASoC: rsnd: tidyup RSND_SSI_xxx flags 6f3ab6c1c022e7a4877d38940cd45ae7804a15e2 (ASoC: rsnd: remove pin sync option) added unused RSND_SSI_CLK_FROM_ADG flag. It should remove RSND_SSI_SYNC. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 2be05ae..e3d585c 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -34,9 +34,6 @@ * B : SSI direction */ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) -#define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */ -#define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */ - #define RSND_SSI_PLAY (1 << 24) #define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \ -- cgit v0.10.2 From 635d61a3735e05c8da72740006670f819e5b6a5f Mon Sep 17 00:00:00 2001 From: Gerry Demaret Date: Fri, 28 Feb 2014 18:50:46 +0100 Subject: USB AX88179/178A: Support D-Link DUB-1312 Add the USB device ID for the D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter to the AX88179/178A driver. Signed-off-by: Gerry Demaret Signed-off-by: David S. Miller diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 460e823..d2e6fdb 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1395,6 +1395,19 @@ static const struct driver_info ax88178a_info = { .tx_fixup = ax88179_tx_fixup, }; +static const struct driver_info dlink_dub1312_info = { + .description = "D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter", + .bind = ax88179_bind, + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, +}; + static const struct driver_info sitecom_info = { .description = "Sitecom USB 3.0 to Gigabit Adapter", .bind = ax88179_bind, @@ -1444,6 +1457,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0b95, 0x178a), .driver_info = (unsigned long)&ax88178a_info, }, { + /* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */ + USB_DEVICE(0x2001, 0x4a00), + .driver_info = (unsigned long)&dlink_dub1312_info, +}, { /* Sitecom USB 3.0 to Gigabit Adapter */ USB_DEVICE(0x0df6, 0x0072), .driver_info = (unsigned long)&sitecom_info, -- cgit v0.10.2 From 61e7fe2577479a1f2650c3fe41c6c842797dddf6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 16:17:02 +0100 Subject: ASoC: neo1973_wm8753: Post gta01 support removal cleanup With GTA01 support gone from the driver there is no need to keep a separate initilization routine for the GTA02 specific bits. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 98a04c1..0125d9d 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -192,44 +192,6 @@ static struct snd_soc_ops neo1973_voice_ops = { .hw_free = neo1973_voice_hw_free, }; -/* Shared routes and controls */ - -static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { - SND_SOC_DAPM_LINE("GSM Line Out", NULL), - SND_SOC_DAPM_LINE("GSM Line In", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Handset Mic", NULL), -}; - -static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { - /* Connections to the GSM Module */ - {"GSM Line Out", NULL, "MONO1"}, - {"GSM Line Out", NULL, "MONO2"}, - {"RXP", NULL, "GSM Line In"}, - {"RXN", NULL, "GSM Line In"}, - - /* Connections to Headset */ - {"MIC1", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Headset Mic"}, - - /* Call Mic */ - {"MIC2", NULL, "Mic Bias"}, - {"MIC2N", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Handset Mic"}, - - /* Connect the ALC pins */ - {"ACIN", NULL, "ACOP"}, -}; - -static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { - SOC_DAPM_PIN_SWITCH("GSM Line Out"), - SOC_DAPM_PIN_SWITCH("GSM Line In"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Handset Mic"), -}; - -/* GTA02 specific routes and controls */ - static int gta02_speaker_enabled; static int lm4853_set_spk(struct snd_kcontrol *kcontrol, @@ -257,7 +219,34 @@ static int lm4853_event(struct snd_soc_dapm_widget *w, return 0; } -static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { +static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { + SND_SOC_DAPM_LINE("GSM Line Out", NULL), + SND_SOC_DAPM_LINE("GSM Line In", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Handset Mic", NULL), + SND_SOC_DAPM_SPK("Handset Spk", NULL), + SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), +}; + +static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { + /* Connections to the GSM Module */ + {"GSM Line Out", NULL, "MONO1"}, + {"GSM Line Out", NULL, "MONO2"}, + {"RXP", NULL, "GSM Line In"}, + {"RXN", NULL, "GSM Line In"}, + + /* Connections to Headset */ + {"MIC1", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Headset Mic"}, + + /* Call Mic */ + {"MIC2", NULL, "Mic Bias"}, + {"MIC2N", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Handset Mic"}, + + /* Connect the ALC pins */ + {"ACIN", NULL, "ACOP"}, + /* Connections to the amp */ {"Stereo Out", NULL, "LOUT1"}, {"Stereo Out", NULL, "ROUT1"}, @@ -267,7 +256,11 @@ static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { {"Handset Spk", NULL, "ROUT2"}, }; -static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { +static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { + SOC_DAPM_PIN_SWITCH("GSM Line Out"), + SOC_DAPM_PIN_SWITCH("GSM Line In"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Handset Mic"), SOC_DAPM_PIN_SWITCH("Handset Spk"), SOC_DAPM_PIN_SWITCH("Stereo Out"), @@ -276,39 +269,6 @@ static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { lm4853_set_spk), }; -static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Handset Spk", NULL), - SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), -}; - -static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets, - ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets)); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes, - ARRAY_SIZE(neo1973_gta02_routes)); - if (ret) - return ret; - - ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls, - ARRAY_SIZE(neo1973_gta02_wm8753_controls)); - if (ret) - return ret; - - snd_soc_dapm_disable_pin(dapm, "Stereo Out"); - snd_soc_dapm_disable_pin(dapm, "Handset Spk"); - snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); - - return 0; -} - static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; @@ -344,18 +304,16 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_disable_pin(dapm, "GSM Line In"); snd_soc_dapm_disable_pin(dapm, "Headset Mic"); snd_soc_dapm_disable_pin(dapm, "Handset Mic"); + snd_soc_dapm_disable_pin(dapm, "Stereo Out"); + snd_soc_dapm_disable_pin(dapm, "Handset Spk"); /* allow audio paths from the GSM modem to run during suspend */ snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); - - if (machine_is_neo1973_gta02()) { - ret = neo1973_gta02_wm8753_init(codec); - if (ret) - return ret; - } + snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); + snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); return 0; } -- cgit v0.10.2 From 4f07c9ccdf92155dd8a216eee262f2954a6d69a2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 16:17:03 +0100 Subject: ASoC: neo1973_wm8753: Convert to table based setup Use table based setup to register the controls and DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 0125d9d..b080033 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -272,48 +272,29 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; + struct snd_soc_card *card = rtd->card; /* set up NC codec pins */ - snd_soc_dapm_nc_pin(dapm, "OUT3"); - snd_soc_dapm_nc_pin(dapm, "OUT4"); - snd_soc_dapm_nc_pin(dapm, "LINE1"); - snd_soc_dapm_nc_pin(dapm, "LINE2"); - - /* Add neo1973 specific widgets */ - ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets, - ARRAY_SIZE(neo1973_wm8753_dapm_widgets)); - if (ret) - return ret; - - /* add neo1973 specific controls */ - ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls, - ARRAY_SIZE(neo1973_wm8753_controls)); - if (ret) - return ret; - - /* set up neo1973 specific audio routes */ - ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, - ARRAY_SIZE(neo1973_wm8753_routes)); - if (ret) - return ret; + snd_soc_dapm_nc_pin(&codec->dapm, "OUT3"); + snd_soc_dapm_nc_pin(&codec->dapm, "OUT4"); + snd_soc_dapm_nc_pin(&codec->dapm, "LINE1"); + snd_soc_dapm_nc_pin(&codec->dapm, "LINE2"); /* set endpoints to default off mode */ - snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); - snd_soc_dapm_disable_pin(dapm, "GSM Line In"); - snd_soc_dapm_disable_pin(dapm, "Headset Mic"); - snd_soc_dapm_disable_pin(dapm, "Handset Mic"); - snd_soc_dapm_disable_pin(dapm, "Stereo Out"); - snd_soc_dapm_disable_pin(dapm, "Handset Spk"); + snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out"); + snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In"); + snd_soc_dapm_disable_pin(&card->dapm, "Headset Mic"); + snd_soc_dapm_disable_pin(&card->dapm, "Handset Mic"); + snd_soc_dapm_disable_pin(&card->dapm, "Stereo Out"); + snd_soc_dapm_disable_pin(&card->dapm, "Handset Spk"); /* allow audio paths from the GSM modem to run during suspend */ - snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); - snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); - snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); - snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); + snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line Out"); + snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line In"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Mic"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Stereo Out"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Spk"); return 0; } @@ -367,6 +348,13 @@ static struct snd_soc_card neo1973 = { .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs), .codec_conf = neo1973_codec_conf, .num_configs = ARRAY_SIZE(neo1973_codec_conf), + + .controls = neo1973_wm8753_controls, + .num_controls = ARRAY_SIZE(neo1973_wm8753_controls), + .dapm_widgets = neo1973_wm8753_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets), + .dapm_routes = neo1973_wm8753_routes, + .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes), }; static struct platform_device *neo1973_snd_device; -- cgit v0.10.2 From e14de47ac95fb25818294325cd77d520c90c6ced Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:13 +0100 Subject: ASoC: pxa: Pass correct DAPM context to {corgi,poodle,spitz}_ext_control When calling {corgi,poodle,spitz}_ext_control() from the startup callback we pass the CODEC's DAPM context instead of the card's DAPM context. This is not a problem per se since all the DAPM functions in ext_control() fallback to widgets from other DAPM contexts, but passing the card's context is more consistent. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index b51f880..916ff63 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -97,10 +97,9 @@ static void corgi_ext_control(struct snd_soc_dapm_context *dapm) static int corgi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - corgi_ext_control(&codec->dapm); + corgi_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 27c6c03..c6bdc6c 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -74,10 +74,9 @@ static void poodle_ext_control(struct snd_soc_dapm_context *dapm) static int poodle_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - poodle_ext_control(&codec->dapm); + poodle_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 0728c1eb..d1b6bf9 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -106,10 +106,9 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) static int spitz_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - spitz_ext_control(&codec->dapm); + spitz_ext_control(&rtd->card->dapm); return 0; } -- cgit v0.10.2 From 23d8f2253c5ebe975465a61dd416a35b5ebda4b0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:14 +0100 Subject: ASoC: pxa: e740_wm9705: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 44b5c09..c29feda 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -103,11 +103,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e740_dapm_widgets, - ARRAY_SIZE(e740_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -136,6 +131,11 @@ static struct snd_soc_card e740 = { .owner = THIS_MODULE, .dai_link = e740_dai, .num_links = ARRAY_SIZE(e740_dai), + + .dapm_widgets = e740_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e740_audio_gpios[] = { -- cgit v0.10.2 From 98308c825ba856796bf52b3c6d6955e62f1fc45c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:15 +0100 Subject: ASoC: pxa: e750_wm9705: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index c34e447..ee36aba 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -85,11 +85,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e750_dapm_widgets, - ARRAY_SIZE(e750_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -119,6 +114,11 @@ static struct snd_soc_card e750 = { .owner = THIS_MODULE, .dai_link = e750_dai, .num_links = ARRAY_SIZE(e750_dai), + + .dapm_widgets = e750_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e750_audio_gpios[] = { -- cgit v0.10.2 From 1bdd301f791e047ed36c18656890c0001f8ce5a3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:16 +0100 Subject: ASoC: pxa: e800_wm9712: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 3137f80..24c2078 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -71,19 +71,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC2", NULL, "Mic (Internal2)"}, }; -static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, e800_dapm_widgets, - ARRAY_SIZE(e800_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - static struct snd_soc_dai_link e800_dai[] = { { .name = "AC97", @@ -92,7 +79,6 @@ static struct snd_soc_dai_link e800_dai[] = { .codec_dai_name = "wm9712-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm9712-codec", - .init = e800_ac97_init, }, { .name = "AC97 Aux", @@ -109,6 +95,11 @@ static struct snd_soc_card e800 = { .owner = THIS_MODULE, .dai_link = e800_dai, .num_links = ARRAY_SIZE(e800_dai), + + .dapm_widgets = e800_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e800_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e800_audio_gpios[] = { -- cgit v0.10.2 From f6b2a04590bb3f7323a45b183956e63574d1f14b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:18 +0100 Subject: ASoC: pxa: mioa701_wm9713: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Also remove the snd_soc_dapm_enable_pin() calls, since pins are enabled by default and there are no matching snd_soc_dapm_disable_pin() calls. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 160c524..595eee3 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -127,16 +127,8 @@ static const struct snd_soc_dapm_route audio_map[] = { static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; unsigned short reg; - /* Add mioa701 specific widgets */ - snd_soc_dapm_new_controls(dapm, mioa701_dapm_widgets, - ARRAY_SIZE(mioa701_dapm_widgets)); - - /* Set up mioa701 specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - /* Prepare GPIO8 for rear speaker amplifier */ reg = codec->driver->read(codec, AC97_GPIO_CFG); codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); @@ -145,12 +137,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) reg = codec->driver->read(codec, AC97_3D_CONTROL); codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); - snd_soc_dapm_enable_pin(dapm, "Front Speaker"); - snd_soc_dapm_enable_pin(dapm, "Rear Speaker"); - snd_soc_dapm_enable_pin(dapm, "Front Mic"); - snd_soc_dapm_enable_pin(dapm, "GSM Line In"); - snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); - return 0; } @@ -183,6 +169,11 @@ static struct snd_soc_card mioa701 = { .owner = THIS_MODULE, .dai_link = mioa701_dai, .num_links = ARRAY_SIZE(mioa701_dai), + + .dapm_widgets = mioa701_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mioa701_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int mioa701_wm9713_probe(struct platform_device *pdev) -- cgit v0.10.2 From a9576cbbbafa2c687121638dadebfb136562a522 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:20 +0100 Subject: ASoC: pxa: zylonite: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Also drop the two snd_soc_dapm_enable_pin() since pins are enabled by default and there is no matching snd_soc_dapm_disable_pin() in the driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index db8aadf..23bf991 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -71,22 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = { static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - if (clk_pout) snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, clk_get_rate(pout), 0); - snd_soc_dapm_new_controls(dapm, zylonite_dapm_widgets, - ARRAY_SIZE(zylonite_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - /* Static setup for now */ - snd_soc_dapm_enable_pin(dapm, "Headphone"); - snd_soc_dapm_enable_pin(dapm, "Headset Earpiece"); - return 0; } @@ -256,6 +244,11 @@ static struct snd_soc_card zylonite = { .resume_pre = &zylonite_resume_pre, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), + + .dapm_widgets = zylonite_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(zylonite_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *zylonite_snd_ac97_device; -- cgit v0.10.2 From 0414855fdc4a40da05221fc6062cccbc0c30f169 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 2 Mar 2014 18:56:16 -0800 Subject: Linux 3.14-rc5 diff --git a/Makefile b/Makefile index 81f1bf3..78209ee 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v0.10.2 From 755a48a7a4eb05b9c8424e3017d947b2961a60e0 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 2 Mar 2014 22:03:12 -0500 Subject: NFS: Fix a delegation callback race The clean-up in commit 36281caa839f ended up removing a NULL pointer check that is needed in order to prevent an Oops in nfs_async_inode_return_delegation(). Reported-by: "Yan, Zheng" Link: http://lkml.kernel.org/r/5313E9F6.2020405@intel.com Fixes: 36281caa839f (NFSv4: Further clean-ups of delegation stateid validation) Cc: stable@vger.kernel.org # 3.4+ Signed-off-by: Trond Myklebust diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index ef792f2..5d8ccec 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -659,16 +659,19 @@ int nfs_async_inode_return_delegation(struct inode *inode, rcu_read_lock(); delegation = rcu_dereference(NFS_I(inode)->delegation); + if (delegation == NULL) + goto out_enoent; - if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) { - rcu_read_unlock(); - return -ENOENT; - } + if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) + goto out_enoent; nfs_mark_return_delegation(server, delegation); rcu_read_unlock(); nfs_delegation_run_state_manager(clp); return 0; +out_enoent: + rcu_read_unlock(); + return -ENOENT; } static struct inode * -- cgit v0.10.2 From 878eaf61be20a78dd4a0a14ac5b1a3a78298cba7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 27 Feb 2014 14:51:55 +1000 Subject: MAINTAINERS: update AGP tree to point at drm tree Signed-off-by: Dave Airlie diff --git a/MAINTAINERS b/MAINTAINERS index c6d0e93..e9d85f6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -473,7 +473,7 @@ F: net/rxrpc/af_rxrpc.c AGPGART DRIVER M: David Airlie -T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git +T: git git://people.freedesktop.org/~airlied/linux (part of drm maint) S: Maintained F: drivers/char/agp/ F: include/linux/agp* -- cgit v0.10.2 From 66f232908de2f7393a1f7c4c300f73534af57f07 Mon Sep 17 00:00:00 2001 From: Denis Carikli Date: Wed, 15 Jan 2014 18:23:25 +0100 Subject: ASoC: eukrea-tlv320: Add DT support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Eric Bénard Cc: Ian Campbell Cc: Liam Girdwood Cc: Mark Brown Cc: Mark Rutland Cc: Pawel Moll Cc: Rob Herring Cc: alsa-devel@alsa-project.org Cc: devicetree@vger.kernel.org Signed-off-by: Denis Carikli Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt new file mode 100644 index 0000000..0d7985c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt @@ -0,0 +1,21 @@ +Audio complex for Eukrea boards with tlv320aic23 codec. + +Required properties: +- compatible : "eukrea,asoc-tlv320" +- eukrea,model : The user-visible name of this sound complex. +- ssi-controller : The phandle of the SSI controller. +- fsl,mux-int-port : The internal port of the i.MX audio muxer (AUDMUX). +- fsl,mux-ext-port : The external port of the i.MX audio muxer. + +Note: The AUDMUX port numbering should start at 1, which is consistent with +hardware manual. + +Example: + + sound { + compatible = "eukrea,asoc-tlv320"; + eukrea,model = "imx51-eukrea-tlv320aic23"; + ssi-controller = <&ssi2>; + fsl,mux-int-port = <2>; + fsl,mux-ext-port = <3>; + }; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f14..b8f8703 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -168,12 +168,15 @@ config SND_SOC_EUKREA_TLV320 depends on MACH_EUKREA_MBIMX27_BASEBOARD \ || MACH_EUKREA_MBIMXSD25_BASEBOARD \ || MACH_EUKREA_MBIMXSD35_BASEBOARD \ - || MACH_EUKREA_MBIMXSD51_BASEBOARD + || MACH_EUKREA_MBIMXSD51_BASEBOARD \ + || (OF && ARM) depends on I2C select SND_SOC_TLV320AIC23 select SND_SOC_IMX_PCM_FIQ select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI + select SND_SOC_FSL_SSI + select SND_SOC_IMX_PCM_DMA help Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 5983740..eb093d5 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -15,8 +15,11 @@ * */ +#include #include #include +#include +#include #include #include #include @@ -26,6 +29,7 @@ #include "../codecs/tlv320aic23.h" #include "imx-ssi.h" +#include "fsl_ssi.h" #include "imx-audmux.h" #define CODEC_CLOCK 12000000 @@ -41,7 +45,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret) { + /* fsl_ssi lacks the set_fmt ops. */ + if (ret && ret != -ENOTSUPP) { dev_err(cpu_dai->dev, "Failed to set the cpu dai format.\n"); return ret; @@ -63,11 +68,13 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, "Failed to set the codec sysclk.\n"); return ret; } + snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); - if (ret) { + /* fsl_ssi lacks the set_sysclk ops */ + if (ret && ret != -EINVAL) { dev_err(cpu_dai->dev, "Can't set the IMX_SSP_SYS_CLK CPU system clock.\n"); return ret; @@ -84,14 +91,10 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "imx-ssi.0", - .codec_name = "tlv320aic23-codec.0-001a", - .cpu_dai_name = "imx-ssi.0", .ops = &eukrea_tlv320_snd_ops, }; static struct snd_soc_card eukrea_tlv320 = { - .name = "cpuimx-audio", .owner = THIS_MODULE, .dai_link = &eukrea_tlv320_dai, .num_links = 1, @@ -101,8 +104,65 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) { int ret; int int_port = 0, ext_port; + struct device_node *np = pdev->dev.of_node; + struct device_node *ssi_np, *codec_np; - if (machine_is_eukrea_cpuimx27()) { + eukrea_tlv320.dev = &pdev->dev; + if (np) { + ret = snd_soc_of_parse_card_name(&eukrea_tlv320, + "eukrea,model"); + if (ret) { + dev_err(&pdev->dev, + "eukrea,model node missing or invalid.\n"); + goto err; + } + + ssi_np = of_parse_phandle(pdev->dev.of_node, + "ssi-controller", 0); + if (!ssi_np) { + dev_err(&pdev->dev, + "ssi-controller missing or invalid.\n"); + ret = -ENODEV; + goto err; + } + + codec_np = of_parse_phandle(ssi_np, "codec-handle", 0); + if (codec_np) + eukrea_tlv320_dai.codec_of_node = codec_np; + else + dev_err(&pdev->dev, "codec-handle node missing or invalid.\n"); + + ret = of_property_read_u32(np, "fsl,mux-int-port", &int_port); + if (ret) { + dev_err(&pdev->dev, + "fsl,mux-int-port node missing or invalid.\n"); + return ret; + } + ret = of_property_read_u32(np, "fsl,mux-ext-port", &ext_port); + if (ret) { + dev_err(&pdev->dev, + "fsl,mux-ext-port node missing or invalid.\n"); + return ret; + } + + /* + * The port numbering in the hardware manual starts at 1, while + * the audmux API expects it starts at 0. + */ + int_port--; + ext_port--; + + eukrea_tlv320_dai.cpu_of_node = ssi_np; + eukrea_tlv320_dai.platform_of_node = ssi_np; + } else { + eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0"; + eukrea_tlv320_dai.platform_name = "imx-ssi.0"; + eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a"; + eukrea_tlv320.name = "cpuimx-audio"; + } + + if (machine_is_eukrea_cpuimx27() || + of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux")) { imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, IMX_AUDMUX_V1_PCR_SYN | IMX_AUDMUX_V1_PCR_TFSDIR | @@ -119,8 +179,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) ); } else if (machine_is_eukrea_cpuimx25sd() || machine_is_eukrea_cpuimx35sd() || - machine_is_eukrea_cpuimx51sd()) { - ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3; + machine_is_eukrea_cpuimx51sd() || + of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux")) { + if (!np) + ext_port = machine_is_eukrea_cpuimx25sd() ? + 4 : 3; + imx_audmux_v2_configure_port(int_port, IMX_AUDMUX_V2_PTCR_SYN | IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -134,14 +198,27 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) ); } else { - /* return happy. We might run on a totally different machine */ - return 0; + if (np) { + /* The eukrea,asoc-tlv320 driver was explicitely + * requested (through the device tree). + */ + dev_err(&pdev->dev, + "Missing or invalid audmux DT node.\n"); + return -ENODEV; + } else { + /* Return happy. + * We might run on a totally different machine. + */ + return 0; + } } - eukrea_tlv320.dev = &pdev->dev; ret = snd_soc_register_card(&eukrea_tlv320); +err: if (ret) dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + if (np) + of_node_put(ssi_np); return ret; } @@ -153,10 +230,17 @@ static int eukrea_tlv320_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id imx_tlv320_dt_ids[] = { + { .compatible = "eukrea,asoc-tlv320"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_tlv320_dt_ids); + static struct platform_driver eukrea_tlv320_driver = { .driver = { .name = "eukrea_tlv320", .owner = THIS_MODULE, + .of_match_table = imx_tlv320_dt_ids, }, .probe = eukrea_tlv320_probe, .remove = eukrea_tlv320_remove, -- cgit v0.10.2 From 61d1cf163c8653934cc8cd5d0b2a562d0990c265 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sun, 2 Mar 2014 20:54:42 +0100 Subject: spi: spi-ath79: fix initial GPIO CS line setup The 'ath79_spi_setup_cs' function initializes the chip select line of a given SPI device in order to make sure that the device is inactive. If the SPI_CS_HIGH bit is set for a given device, it means that the CS line of that device is active HIGH so it must be set to LOW initially. In case of GPIO CS lines, the 'ath79_spi_setup_cs' function does the opposite of that due to the wrong GPIO flags. Fix the code to use the correct GPIO flags. Reported-by: Ronald Wahl Signed-off-by: Gabor Juhos Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 31534b5..c3b2fb9 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -132,9 +132,9 @@ static int ath79_spi_setup_cs(struct spi_device *spi) flags = GPIOF_DIR_OUT; if (spi->mode & SPI_CS_HIGH) - flags |= GPIOF_INIT_HIGH; - else flags |= GPIOF_INIT_LOW; + else + flags |= GPIOF_INIT_HIGH; status = gpio_request_one(cdata->gpio, flags, dev_name(&spi->dev)); -- cgit v0.10.2 From 57996358f4d679b2bc39d4cd15166bb89fc8d981 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 2 Mar 2014 00:04:02 +0800 Subject: ASoC: dapm: Power off all widgets in the snd_soc_dapm_shutdown The widgets generated by the machine driver need to power off too. Signed-off-by: Xiang Xiao Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 4200f96..d856e7c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4116,7 +4116,7 @@ void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) } EXPORT_SYMBOL_GPL(snd_soc_dapm_free); -static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) +static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) { struct snd_soc_card *card = dapm->card; struct snd_soc_dapm_widget *w; @@ -4156,12 +4156,12 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) */ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_dapm_context *dapm; - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - soc_dapm_shutdown_codec(&codec->dapm); - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) - snd_soc_dapm_set_bias_level(&codec->dapm, + list_for_each_entry(dapm, &card->dapm_list, list) { + soc_dapm_shutdown_dapm(dapm); + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_OFF); } } -- cgit v0.10.2 From 17282ba4310cdad05f172d4dc1ebcb63d0b5de98 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 2 Mar 2014 00:04:03 +0800 Subject: ASoC: dapm: Reorder the bias update sequence The new sequence ensure that dapm_pre_sequence_async work on the card before all codecs and dapm_post_sequence_async work on the card after all codecs. So the machine driver could utilize the determinate sequence to do the gloabl setup and teardown in the right place. Signed-off-by: Xiang Xiao Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d856e7c..77743e5 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1898,10 +1898,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) trace_snd_soc_dapm_walk_done(card); - /* Run all the bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) - async_schedule_domain(dapm_pre_sequence_async, d, - &async_domain); + /* Run card bias changes at first */ + dapm_pre_sequence_async(&card->dapm, 0); + /* Run other bias changes in parallel */ + list_for_each_entry(d, &card->dapm_list, list) { + if (d != &card->dapm) + async_schedule_domain(dapm_pre_sequence_async, d, + &async_domain); + } async_synchronize_full_domain(&async_domain); list_for_each_entry(w, &down_list, power_list) { @@ -1921,10 +1925,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) dapm_seq_run(card, &up_list, event, true); /* Run all the bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) - async_schedule_domain(dapm_post_sequence_async, d, - &async_domain); + list_for_each_entry(d, &card->dapm_list, list) { + if (d != &card->dapm) + async_schedule_domain(dapm_post_sequence_async, d, + &async_domain); + } async_synchronize_full_domain(&async_domain); + /* Run card bias changes at last */ + dapm_post_sequence_async(&card->dapm, 0); /* do we need to notify any clients that DAPM event is complete */ list_for_each_entry(d, &card->dapm_list, list) { @@ -4159,11 +4167,18 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) struct snd_soc_dapm_context *dapm; list_for_each_entry(dapm, &card->dapm_list, list) { - soc_dapm_shutdown_dapm(dapm); - if (dapm->bias_level == SND_SOC_BIAS_STANDBY) - snd_soc_dapm_set_bias_level(dapm, - SND_SOC_BIAS_OFF); + if (dapm != &card->dapm) { + soc_dapm_shutdown_dapm(dapm); + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(dapm, + SND_SOC_BIAS_OFF); + } } + + soc_dapm_shutdown_dapm(&card->dapm); + if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(&card->dapm, + SND_SOC_BIAS_OFF); } /* Module information */ -- cgit v0.10.2 From 112ad7f28e7ed2e9966ab464274b143c29d3ce15 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Mar 2014 08:17:08 +0100 Subject: ASoC: wm1133-ev1: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index fce6325..804749a 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c @@ -214,12 +214,6 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - snd_soc_dapm_new_controls(dapm, wm1133_ev1_widgets, - ARRAY_SIZE(wm1133_ev1_widgets)); - - snd_soc_dapm_add_routes(dapm, wm1133_ev1_map, - ARRAY_SIZE(wm1133_ev1_map)); - /* Headphone jack detection */ snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), @@ -257,6 +251,11 @@ static struct snd_soc_card wm1133_ev1 = { .owner = THIS_MODULE, .dai_link = &wm1133_ev1_dai, .num_links = 1, + + .dapm_widgets = wm1133_ev1_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm1133_ev1_widgets), + .dapm_routes = wm1133_ev1_map, + .num_dapm_routes = ARRAY_SIZE(wm1133_ev1_map), }; static struct platform_device *wm1133_ev1_snd_device; -- cgit v0.10.2 From a6b92b6650d010d58b6e6fe42c6271266e0b1134 Mon Sep 17 00:00:00 2001 From: Marius Knaust Date: Mon, 3 Mar 2014 01:48:58 +0100 Subject: ALSA: hda - Added inverted digital-mic handling for Acer TravelMate 8371 Signed-off-by: Marius Knaust Cc: Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ec304f3..7ba7a11f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4253,6 +4253,7 @@ static const struct hda_fixup alc269_fixups[] = { }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0283, "Acer TravelMate 8371", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), -- cgit v0.10.2 From b6ab66aa5d376583a17137cbb2d3a728f29acae2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 25 Feb 2014 13:11:47 +0200 Subject: drm/i915: use backlight legacy combination mode also for i915gm/i945gm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i915gm and i945gm also seem to use and need the legacy combination mode bit in BLC_PWM_CTL. v2: Also do this for i915gm (Ville). Reported-and-tested-by: Luis Ortega Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75001 Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 350de35..079ea38 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -698,7 +698,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector) freq /= 0xff; ctl = freq << 17; - if (IS_GEN2(dev) && panel->backlight.combination_mode) + if (panel->backlight.combination_mode) ctl |= BLM_LEGACY_MODE; if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) ctl |= BLM_POLARITY_PNV; @@ -979,7 +979,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector) ctl = I915_READ(BLC_PWM_CTL); - if (IS_GEN2(dev)) + if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev)) panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; if (IS_PINEVIEW(dev)) -- cgit v0.10.2 From 3617dc9675f0184b7bb210cfa34f3cac928d8055 Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Mon, 13 Jan 2014 16:25:21 +0530 Subject: drm/i915: Resolving the memory region conflict for Stolen area There is a conflict seen when requesting the kernel to reserve the physical space used for the stolen area. This is because some BIOS are wrapping the stolen area in the root PCI bus, but have an off-by-one error. As a workaround we retry the reservation with an offset of 1 instead of 0. v2: updated commit message & the comment in source file (Daniel) Signed-off-by: Akash Goel Reviewed-by: Jesse Barnes Tested-by: Arjan van de Ven Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 1a24e84..d58b4e2 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -82,9 +82,22 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size, "Graphics Stolen Memory"); if (r == NULL) { - DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", - base, base + (uint32_t)dev_priv->gtt.stolen_size); - base = 0; + /* + * One more attempt but this time requesting region from + * base + 1, as we have seen that this resolves the region + * conflict with the PCI Bus. + * This is a BIOS w/a: Some BIOS wrap stolen in the root + * PCI bus, but have an off-by-one error. Hence retry the + * reservation starting from 1 instead of 0. + */ + r = devm_request_mem_region(dev->dev, base + 1, + dev_priv->gtt.stolen_size - 1, + "Graphics Stolen Memory"); + if (r == NULL) { + DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", + base, base + (uint32_t)dev_priv->gtt.stolen_size); + base = 0; + } } return base; -- cgit v0.10.2 From bcdb72ac7c00d2b56359fc82bcc8fe50454717d5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 14 Feb 2014 20:23:54 +0200 Subject: drm/i915: fix pch pci device enumeration pci_get_class(class, from) drops the refcount for 'from', so the extra pci_dev_put we do on it will result in a use after free bug starting with the WARN below. Regression introduced in commit 6a9c4b35e6696a63805b6da5e4889c6986e9ee1b Author: Rui Guo Date: Wed Jun 19 21:10:23 2013 +0800 drm/i915: Fix PCH detect with multiple ISA bridges in VM [ 164.338460] WARNING: CPU: 1 PID: 2094 at include/linux/kref.h:47 klist_next+0xae/0x110() [ 164.347731] CPU: 1 PID: 2094 Comm: modprobe Tainted: G O 3.13.0-imre+ #354 [ 164.356468] Hardware name: Intel Corp. VALLEYVIEW B0 PLATFORM/NOTEBOOK, BIOS BYTICRB1.X64.0062.R70.1310112051 10/11/2013 [ 164.368796] Call Trace: [ 164.371609] [] dump_stack+0x4e/0x7a [ 164.377447] [] warn_slowpath_common+0x7d/0xa0 [ 164.384238] [] warn_slowpath_null+0x1a/0x20 [ 164.390851] [] klist_next+0xae/0x110 [ 164.396777] [] ? pci_do_find_bus+0x70/0x70 [ 164.403286] [] bus_find_device+0x89/0xc0 [ 164.409719] [] pci_get_dev_by_id+0x63/0xa0 [ 164.416238] [] pci_get_class+0x44/0x50 [ 164.422433] [] intel_dsm_detect+0x16f/0x1f0 [i915] [ 164.429801] [] intel_register_dsm_handler+0xe/0x10 [i915] [ 164.437831] [] i915_driver_load+0xafe/0xf30 [i915] [ 164.445126] [] ? intel_alloc_coherent+0x110/0x110 [ 164.452340] [] drm_dev_register+0xc7/0x150 [drm] [ 164.459462] [] drm_get_pci_dev+0x11f/0x1f0 [drm] [ 164.466554] [] ? _raw_spin_unlock_irqrestore+0x51/0x70 [ 164.474287] [] i915_pci_probe+0x56/0x60 [i915] [ 164.481185] [] pci_device_probe+0x78/0xf0 [ 164.487603] [] driver_probe_device+0x155/0x350 [ 164.494505] [] __driver_attach+0x6e/0xa0 [ 164.500826] [] ? __device_attach+0x50/0x50 [ 164.507333] [] bus_for_each_dev+0x6e/0xc0 [ 164.513752] [] driver_attach+0x1e/0x20 [ 164.519870] [] bus_add_driver+0x138/0x260 [ 164.526289] [] ? 0xffffffffa0187fff [ 164.532116] [] driver_register+0x98/0xe0 [ 164.538558] [] ? 0xffffffffa0187fff [ 164.544389] [] __pci_register_driver+0x60/0x70 [ 164.551336] [] drm_pci_init+0x6d/0x120 [drm] [ 164.558040] [] ? 0xffffffffa0187fff [ 164.563928] [] i915_init+0x6a/0x6c [i915] [ 164.570363] [] do_one_initcall+0xaa/0x160 [ 164.576783] [] ? set_memory_nx+0x40/0x50 [ 164.583100] [] load_module+0x1fb5/0x2550 [ 164.589410] [] ? store_uevent+0x40/0x40 [ 164.595628] [] SyS_init_module+0xed/0x100 [ 164.602048] [] system_call_fastpath+0x16/0x1b v2: simplify the loop further (Chris) Signed-off-by: Imre Deak Cc: Jesse Barnes Reported-by: Jesse Barnes Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65652 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74161 Reviewed-by: Chris Wilson Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 04f1f02..ec7bb0f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -403,7 +403,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist); void intel_detect_pch(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct pci_dev *pch; + struct pci_dev *pch = NULL; /* In all current cases, num_pipes is equivalent to the PCH_NOP setting * (which really amounts to a PCH but no South Display). @@ -424,12 +424,9 @@ void intel_detect_pch(struct drm_device *dev) * all the ISA bridge devices and check for the first match, instead * of only checking the first one. */ - pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); - while (pch) { - struct pci_dev *curr = pch; + while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { if (pch->vendor == PCI_VENDOR_ID_INTEL) { - unsigned short id; - id = pch->device & INTEL_PCH_DEVICE_ID_MASK; + unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK; dev_priv->pch_id = id; if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { @@ -461,18 +458,16 @@ void intel_detect_pch(struct drm_device *dev) DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); WARN_ON(!IS_HASWELL(dev)); WARN_ON(!IS_ULT(dev)); - } else { - goto check_next; - } - pci_dev_put(pch); + } else + continue; + break; } -check_next: - pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, curr); - pci_dev_put(curr); } if (!pch) - DRM_DEBUG_KMS("No PCH found?\n"); + DRM_DEBUG_KMS("No PCH found.\n"); + + pci_dev_put(pch); } bool i915_semaphore_is_enabled(struct drm_device *dev) -- cgit v0.10.2 From 5be93bdda64e85450598c6e97f79fb8f6acf30e0 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 19 Feb 2014 12:00:51 +0100 Subject: can: flexcan: fix shutdown: first disable chip, then all interrupts When shutting down the CAN interface (ifconfig canX down) during high CAN bus loads, the CAN core might hang and freeze the whole CPU. This patch fixes the shutdown sequence by first disabling the CAN core then disabling all interrupts. Cc: linux-stable Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 320bef2..dcd69c9 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -827,14 +827,16 @@ static void flexcan_chip_stop(struct net_device *dev) struct flexcan_regs __iomem *regs = priv->base; u32 reg; - /* Disable all interrupts */ - flexcan_write(0, ®s->imask1); - /* Disable + halt module */ reg = flexcan_read(®s->mcr); reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT; flexcan_write(reg, ®s->mcr); + /* Disable all interrupts */ + flexcan_write(0, ®s->imask1); + flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, + ®s->ctrl); + if (priv->reg_xceiver) regulator_disable(priv->reg_xceiver); priv->can.state = CAN_STATE_STOPPED; -- cgit v0.10.2 From 7e9e148af01ef388efb6e2490805970be4622792 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 28 Feb 2014 14:52:01 +0100 Subject: can: flexcan: flexcan_open(): fix error path if flexcan_chip_start() fails If flexcan_chip_start() in flexcan_open() fails, the interrupt is not freed, this patch adds the missing cleanup. Cc: linux-stable Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index dcd69c9..30af702 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -868,7 +868,7 @@ static int flexcan_open(struct net_device *dev) /* start chip and queuing */ err = flexcan_chip_start(dev); if (err) - goto out_close; + goto out_free_irq; can_led_event(dev, CAN_LED_EVENT_OPEN); @@ -877,6 +877,8 @@ static int flexcan_open(struct net_device *dev) return 0; + out_free_irq: + free_irq(dev->irq, dev); out_close: close_candev(dev); out_disable_per: -- cgit v0.10.2 From 9b00b300e7bce032c467c36ca47fe2a776887fc2 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 28 Feb 2014 15:30:18 +0100 Subject: can: flexcan: fix transition from and to low power mode in chip_{en,dis}able In flexcan_chip_enable() and flexcan_chip_disable() fixed delays are used. Experiments have shown that the transition from and to low power mode may take several microseconds. This patch adds a while loop which polls the Low Power Mode ACK bit (LPM_ACK) that indicates a successfull mode change. If the function runs into a timeout a error value is returned. Cc: linux-stable Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 30af702..5af60ab 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -144,6 +144,8 @@ #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) +#define FLEXCAN_TIMEOUT_US (50) + /* * FLEXCAN hardware feature flags * @@ -269,26 +271,42 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv, (reg_esr & FLEXCAN_ESR_ERR_BUS); } -static inline void flexcan_chip_enable(struct flexcan_priv *priv) +static int flexcan_chip_enable(struct flexcan_priv *priv) { struct flexcan_regs __iomem *regs = priv->base; + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; reg = flexcan_read(®s->mcr); reg &= ~FLEXCAN_MCR_MDIS; flexcan_write(reg, ®s->mcr); - udelay(10); + while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + usleep_range(10, 20); + + if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) + return -ETIMEDOUT; + + return 0; } -static inline void flexcan_chip_disable(struct flexcan_priv *priv) +static int flexcan_chip_disable(struct flexcan_priv *priv) { struct flexcan_regs __iomem *regs = priv->base; + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; reg = flexcan_read(®s->mcr); reg |= FLEXCAN_MCR_MDIS; flexcan_write(reg, ®s->mcr); + + while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + usleep_range(10, 20); + + if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + return -ETIMEDOUT; + + return 0; } static int flexcan_get_berr_counter(const struct net_device *dev, @@ -709,7 +727,9 @@ static int flexcan_chip_start(struct net_device *dev) u32 reg_mcr, reg_ctrl; /* enable module */ - flexcan_chip_enable(priv); + err = flexcan_chip_enable(priv); + if (err) + return err; /* soft reset */ flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); @@ -949,12 +969,16 @@ static int register_flexcandev(struct net_device *dev) goto out_disable_ipg; /* select "bus clock", chip must be disabled */ - flexcan_chip_disable(priv); + err = flexcan_chip_disable(priv); + if (err) + goto out_disable_per; reg = flexcan_read(®s->ctrl); reg |= FLEXCAN_CTRL_CLK_SRC; flexcan_write(reg, ®s->ctrl); - flexcan_chip_enable(priv); + err = flexcan_chip_enable(priv); + if (err) + goto out_chip_disable; /* set freeze, halt and activate FIFO, restrict register access */ reg = flexcan_read(®s->mcr); @@ -971,14 +995,15 @@ static int register_flexcandev(struct net_device *dev) if (!(reg & FLEXCAN_MCR_FEN)) { netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); err = -ENODEV; - goto out_disable_per; + goto out_chip_disable; } err = register_candev(dev); - out_disable_per: /* disable core and turn off clocks */ + out_chip_disable: flexcan_chip_disable(priv); + out_disable_per: clk_disable_unprepare(priv->clk_per); out_disable_ipg: clk_disable_unprepare(priv->clk_ipg); @@ -1121,8 +1146,11 @@ static int flexcan_suspend(struct device *device) { struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); + int err; - flexcan_chip_disable(priv); + err = flexcan_chip_disable(priv); + if (err) + return err; if (netif_running(dev)) { netif_stop_queue(dev); @@ -1143,9 +1171,7 @@ static int flexcan_resume(struct device *device) netif_device_attach(dev); netif_start_queue(dev); } - flexcan_chip_enable(priv); - - return 0; + return flexcan_chip_enable(priv); } #endif /* CONFIG_PM_SLEEP */ -- cgit v0.10.2 From f003698e23f6f56a791774f14d0ac35d04872490 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 28 Feb 2014 17:18:27 +0100 Subject: can: flexcan: factor out transceiver {en,dis}able into seperate functions This patch moves the transceiver enable and disable into seperate functions, where the NULL pointer check is hidden. Cc: linux-stable Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 5af60ab..6b0fecd 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -264,6 +264,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr) } #endif +static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv) +{ + if (!priv->reg_xceiver) + return 0; + + return regulator_enable(priv->reg_xceiver); +} + +static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv) +{ + if (!priv->reg_xceiver) + return 0; + + return regulator_disable(priv->reg_xceiver); +} + static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv, u32 reg_esr) { @@ -808,11 +824,9 @@ static int flexcan_chip_start(struct net_device *dev) if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) flexcan_write(0x0, ®s->rxfgmask); - if (priv->reg_xceiver) { - err = regulator_enable(priv->reg_xceiver); - if (err) - goto out; - } + err = flexcan_transceiver_enable(priv); + if (err) + goto out; /* synchronize with the can bus */ reg_mcr = flexcan_read(®s->mcr); @@ -857,8 +871,7 @@ static void flexcan_chip_stop(struct net_device *dev) flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, ®s->ctrl); - if (priv->reg_xceiver) - regulator_disable(priv->reg_xceiver); + flexcan_transceiver_disable(priv); priv->can.state = CAN_STATE_STOPPED; return; -- cgit v0.10.2 From b1aa1c7a2165b44ecce66286a3095cc6c7667d1c Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 28 Feb 2014 17:08:21 +0100 Subject: can: flexcan: fix transition from and to freeze mode in chip_{,un}freeze This patch factors out freeze and unfreeze of the CAN core into seperate functions. Experiments have shown that the transition from and to freeze mode may take several microseconds, especially the time entering the freeze mode depends on the current bitrate. This patch adds a while loop which polls the Freeze Mode ACK bit (FRZ_ACK) that indicates a successfull mode change. If the function runs into a timeout a error value is returned. Cc: linux-stable Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 6b0fecd..330b5b9 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -325,6 +325,44 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) return 0; } +static int flexcan_chip_freeze(struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs = priv->base; + unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; + u32 reg; + + reg = flexcan_read(®s->mcr); + reg |= FLEXCAN_MCR_HALT; + flexcan_write(reg, ®s->mcr); + + while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + usleep_range(100, 200); + + if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + return -ETIMEDOUT; + + return 0; +} + +static int flexcan_chip_unfreeze(struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs = priv->base; + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; + u32 reg; + + reg = flexcan_read(®s->mcr); + reg &= ~FLEXCAN_MCR_HALT; + flexcan_write(reg, ®s->mcr); + + while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + usleep_range(10, 20); + + if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) + return -ETIMEDOUT; + + return 0; +} + static int flexcan_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { @@ -756,7 +794,7 @@ static int flexcan_chip_start(struct net_device *dev) netdev_err(dev, "Failed to softreset can module (mcr=0x%08x)\n", reg_mcr); err = -ENODEV; - goto out; + goto out_chip_disable; } flexcan_set_bittiming(dev); @@ -826,12 +864,12 @@ static int flexcan_chip_start(struct net_device *dev) err = flexcan_transceiver_enable(priv); if (err) - goto out; + goto out_chip_disable; /* synchronize with the can bus */ - reg_mcr = flexcan_read(®s->mcr); - reg_mcr &= ~FLEXCAN_MCR_HALT; - flexcan_write(reg_mcr, ®s->mcr); + err = flexcan_chip_unfreeze(priv); + if (err) + goto out_transceiver_disable; priv->can.state = CAN_STATE_ERROR_ACTIVE; @@ -844,7 +882,9 @@ static int flexcan_chip_start(struct net_device *dev) return 0; - out: + out_transceiver_disable: + flexcan_transceiver_disable(priv); + out_chip_disable: flexcan_chip_disable(priv); return err; } @@ -859,12 +899,10 @@ static void flexcan_chip_stop(struct net_device *dev) { struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->base; - u32 reg; - /* Disable + halt module */ - reg = flexcan_read(®s->mcr); - reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT; - flexcan_write(reg, ®s->mcr); + /* freeze + disable module */ + flexcan_chip_freeze(priv); + flexcan_chip_disable(priv); /* Disable all interrupts */ flexcan_write(0, ®s->imask1); -- cgit v0.10.2 From d96e43e8fce28cf97df576a07af9d65657a41a6f Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 28 Feb 2014 20:48:36 +0100 Subject: can: flexcan: flexcan_remove(): add missing netif_napi_del() This patch adds the missing netif_napi_del() to the flexcan_remove() function. Cc: linux-stable Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 330b5b9..dff4fa4 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -1184,9 +1184,10 @@ static int flexcan_probe(struct platform_device *pdev) static int flexcan_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); + struct flexcan_priv *priv = netdev_priv(dev); unregister_flexcandev(dev); - + netif_napi_del(&priv->napi); free_candev(dev); return 0; -- cgit v0.10.2 From 4b5b82274a17f0ebbf02378df2ba7f36a3f5af19 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 28 Feb 2014 15:16:59 +0100 Subject: can: flexcan: factor out soft reset into seperate funtion This patch moves the soft reset into a seperate function. Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index dff4fa4..61376ab 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -363,6 +363,21 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv) return 0; } +static int flexcan_chip_softreset(struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs = priv->base; + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; + + flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); + while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) + usleep_range(10, 20); + + if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST) + return -ETIMEDOUT; + + return 0; +} + static int flexcan_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { @@ -786,16 +801,9 @@ static int flexcan_chip_start(struct net_device *dev) return err; /* soft reset */ - flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); - udelay(10); - - reg_mcr = flexcan_read(®s->mcr); - if (reg_mcr & FLEXCAN_MCR_SOFTRST) { - netdev_err(dev, "Failed to softreset can module (mcr=0x%08x)\n", - reg_mcr); - err = -ENODEV; + err = flexcan_chip_softreset(priv); + if (err) goto out_chip_disable; - } flexcan_set_bittiming(dev); -- cgit v0.10.2 From 821047c4055cca833c4674f172a9d73003563eb6 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Sat, 1 Mar 2014 15:31:53 +0100 Subject: can: remove CAN FD compatibility for CAN 2.0 sockets In commit e2d265d3b587 (canfd: add support for CAN FD in CAN_RAW sockets) CAN FD frames with a payload length up to 8 byte are passed to legacy sockets where the CAN FD support was not enabled by the application. After some discussions with developers at a fair this well meant feature leads to confusion as no clean switch for CAN / CAN FD is provided to the application programmer. Additionally a compatibility like this for legacy CAN_RAW sockets requires some compatibility handling for the sending, e.g. make CAN2.0 frames a CAN FD frame with BRS at transmission time (?!?). This will become a mess when people start to develop applications with real CAN FD hardware. This patch reverts the bad compatibility code together with the documentation describing the removed feature. Acked-by: Stephane Grosjean Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt index f3089d4..0cbe6ec 100644 --- a/Documentation/networking/can.txt +++ b/Documentation/networking/can.txt @@ -554,12 +554,6 @@ solution for a couple of reasons: not specified in the struct can_frame and therefore it is only valid in CANFD_MTU sized CAN FD frames. - As long as the payload length is <=8 the received CAN frames from CAN FD - capable CAN devices can be received and read by legacy sockets too. When - user-generated CAN FD frames have a payload length <=8 these can be send - by legacy CAN network interfaces too. Sending CAN FD frames with payload - length > 8 to a legacy CAN network interface returns an -EMSGSIZE error. - Implementation hint for new CAN applications: To build a CAN FD aware application use struct canfd_frame as basic CAN diff --git a/net/can/raw.c b/net/can/raw.c index 8be757c..081e81f 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -121,13 +121,9 @@ static void raw_rcv(struct sk_buff *oskb, void *data) if (!ro->recv_own_msgs && oskb->sk == sk) return; - /* do not pass frames with DLC > 8 to a legacy socket */ - if (!ro->fd_frames) { - struct canfd_frame *cfd = (struct canfd_frame *)oskb->data; - - if (unlikely(cfd->len > CAN_MAX_DLEN)) - return; - } + /* do not pass non-CAN2.0 frames to a legacy socket */ + if (!ro->fd_frames && oskb->len != CAN_MTU) + return; /* clone the given skb to be able to enqueue it into the rcv queue */ skb = skb_clone(oskb, GFP_ATOMIC); @@ -738,9 +734,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; - struct raw_sock *ro = raw_sk(sk); struct sk_buff *skb; - int rxmtu; int err = 0; int noblock; @@ -751,20 +745,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) return err; - /* - * when serving a legacy socket the DLC <= 8 is already checked inside - * raw_rcv(). Now check if we need to pass a canfd_frame to a legacy - * socket and cut the possible CANFD_MTU/CAN_MTU length to CAN_MTU - */ - if (!ro->fd_frames) - rxmtu = CAN_MTU; - else - rxmtu = skb->len; - - if (size < rxmtu) + if (size < skb->len) msg->msg_flags |= MSG_TRUNC; else - size = rxmtu; + size = skb->len; err = memcpy_toiovec(msg->msg_iov, skb->data, size); if (err < 0) { -- cgit v0.10.2 From 7693decce869a94821bed1fa6c237c7224096b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 3 Mar 2014 09:25:52 -0500 Subject: ARM: XEN depends on having a MMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arch/arm/xen/enlighten.c (and maybe others) use MMU-specific functions like pte_mkspecial which are only available on MMU builds. So let XEN depend on MMU. Suggested-by: Arnd Bergmann Signed-off-by: Uwe Kleine-König Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 24307dc..8b78465 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1883,6 +1883,7 @@ config XEN depends on ARM && AEABI && OF depends on CPU_V7 && !CPU_V6 depends on !GENERIC_ATOMIC64 + depends on MMU select ARM_PSCI select SWIOTLB_XEN select ARCH_DMA_ADDR_T_64BIT -- cgit v0.10.2 From 37d6a82bd99d3354e59a9a629fa48fc75ca51c66 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 3 Mar 2014 23:05:15 +0800 Subject: Thermal: update INT3404 thermal driver help text Signed-off-by: Zhang Rui diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 35c0664..7932294 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -210,8 +210,16 @@ config ACPI_INT3403_THERMAL tristate "ACPI INT3403 thermal driver" depends on X86 && ACPI help - This driver uses ACPI INT3403 device objects. If present, it will - register each INT3403 thermal sensor as a thermal zone. + Newer laptops and tablets that use ACPI may have thermal sensors + outside the core CPU/SOC for thermal safety reasons. These + temperature sensors are also exposed for the OS to use via the so + called INT3403 ACPI object. This driver will, on devices that have + such sensors, expose the temperature information from these sensors + to userspace via the normal thermal framework. This means that a wide + range of applications and GUI widgets can show this information to + the user or use this information for making decisions. For example, + the Intel Thermal Daemon can use this information to allow the user + to select his laptop to run without turning on the fans. menu "Texas Instruments thermal drivers" source "drivers/thermal/ti-soc-thermal/Kconfig" -- cgit v0.10.2 From 79786880a47a8c5b4c8146c03432b3387a07a169 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 2 Mar 2014 15:33:35 +0100 Subject: x86_pkg_temp_thermal: Do not expose as a hwmon device The temperature value reported by x86_pkg_temp_thermal is already reported by the coretemp driver. So, do not expose this thermal zone as a hwmon device, because it would be redundant. Signed-off-by: Jean Delvare Cc: Zhang Rui Cc: Eduardo Valentin Acked-by: Guenter Roeck Signed-off-by: Zhang Rui diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index 972e1c7..3d8d972 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -68,6 +68,10 @@ struct phy_dev_entry { struct thermal_zone_device *tzone; }; +static const struct thermal_zone_params pkg_temp_tz_params = { + .no_hwmon = true, +}; + /* List maintaining number of package instances */ static LIST_HEAD(phy_dev_list); static DEFINE_MUTEX(phy_dev_list_mutex); @@ -446,7 +450,7 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) thres_count, (thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01, - phy_dev_entry, &tzone_ops, NULL, 0, 0); + phy_dev_entry, &tzone_ops, &pkg_temp_tz_params, 0, 0); if (IS_ERR(phy_dev_entry->tzone)) { err = PTR_ERR(phy_dev_entry->tzone); goto err_ret_free; -- cgit v0.10.2 From 3e4216531c442ea99cb32a69e5ef4af723e7b5a9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 2 Mar 2014 15:05:49 +0100 Subject: x86_pkg_temp_thermal: Fix the thermal zone type The thermal zone type should not include an instance number. Otherwise each zone is considered a different type and the thermal-to-hwmon bridge fails to group them all in a single hwmon device. I also changed the type to "x86_pkg_temp", because "pkg" was too generic, and other thermal drivers use an underscore, not a dash, as a separator. Or maybe "cpu_pkg_temp" would be better? Signed-off-by: Jean Delvare Cc: Zhang Rui Cc: Eduardo Valentin Signed-off-by: Zhang Rui diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index 3d8d972..081fd7e 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -398,7 +398,6 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) int err; u32 tj_max; struct phy_dev_entry *phy_dev_entry; - char buffer[30]; int thres_count; u32 eax, ebx, ecx, edx; u8 *temp; @@ -444,9 +443,7 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) phy_dev_entry->first_cpu = cpu; phy_dev_entry->tj_max = tj_max; phy_dev_entry->ref_cnt = 1; - snprintf(buffer, sizeof(buffer), "pkg-temp-%d\n", - phy_dev_entry->phys_proc_id); - phy_dev_entry->tzone = thermal_zone_device_register(buffer, + phy_dev_entry->tzone = thermal_zone_device_register("x86_pkg_temp", thres_count, (thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01, -- cgit v0.10.2 From d1c8b0410b77f1e43f97cd22bc7e0a71a5305840 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 27 Jan 2014 09:40:58 +0100 Subject: thermal,rcar_thermal: Add dependency on HAS_IOMEM Commit beeb5a1e (thermal: rcar-thermal: Enable driver compilation with COMPILE_TEST) broke build on archs wihout io memory. On archs like S390 or um this driver cannot build nor work. Make it depend on HAS_IOMEM to bypass build failures. drivers/thermal/rcar_thermal.c:404: undefined reference to `devm_ioremap_resource' drivers/thermal/rcar_thermal.c:426: undefined reference to `devm_ioremap_resource' Signed-off-by: Richard Weinberger Acked-by: Laurent Pinchart Acked-by: Kuninori Morimoto Signed-off-by: Zhang Rui diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 7932294..5f88d76 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -136,6 +136,7 @@ config SPEAR_THERMAL config RCAR_THERMAL tristate "Renesas R-Car thermal driver" depends on ARCH_SHMOBILE || COMPILE_TEST + depends on HAS_IOMEM help Enable this to plug the R-Car thermal sensor driver into the Linux thermal framework. -- cgit v0.10.2 From 5ca0cce5622bf476e3e6bf627fe8e9381d6ae174 Mon Sep 17 00:00:00 2001 From: Ni Wade Date: Mon, 17 Feb 2014 11:02:55 +0800 Subject: Thermal: Allow first update of cooling device state In initialization, if the cooling device is initialized at max cooling state, and the thermal zone temperature is below the first trip point, then the cooling state can't be updated to the right state, untill the first trip point be triggered. To fix this issue, allow first update of cooling device state during registration, initialized "updated" device field as "false" (instead of "true"). Signed-off-by: Wei Ni Signed-off-by: Zhang Rui diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 338a88b..02f57af 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1107,7 +1107,7 @@ __thermal_cooling_device_register(struct device_node *np, INIT_LIST_HEAD(&cdev->thermal_instances); cdev->np = np; cdev->ops = ops; - cdev->updated = true; + cdev->updated = false; cdev->device.class = &thermal_class; cdev->devdata = devdata; dev_set_name(&cdev->device, "cooling_device%d", cdev->id); -- cgit v0.10.2 From f2234bcd03ad031225d7dc37dd18852a2f2ff2bf Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 24 Jan 2014 10:23:19 +0800 Subject: Thermal: thermal zone governor fix This patch does a cleanup about the thermal zone govenor, setting and make the following rule. 1. For thermal zone devices that are registered w/o tz->tzp, they can use the default thermal governor only. 2. For thermal zone devices w/ governor name specified in tz->tzp->governor_name, we will use the default govenor if the governor specified is not available at the moment, and update tz->governor when the matched governor is registered. This also fixes a problem that OF registered thermal zones are running with no governor. Signed-off-by: Zhang Rui Acked-by: Javi Merino diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 02f57af..71b0ec0 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -56,10 +56,15 @@ static LIST_HEAD(thermal_governor_list); static DEFINE_MUTEX(thermal_list_lock); static DEFINE_MUTEX(thermal_governor_lock); +static struct thermal_governor *def_governor; + static struct thermal_governor *__find_governor(const char *name) { struct thermal_governor *pos; + if (!name || !name[0]) + return def_governor; + list_for_each_entry(pos, &thermal_governor_list, governor_list) if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH)) return pos; @@ -82,17 +87,23 @@ int thermal_register_governor(struct thermal_governor *governor) if (__find_governor(governor->name) == NULL) { err = 0; list_add(&governor->governor_list, &thermal_governor_list); + if (!def_governor && !strncmp(governor->name, + DEFAULT_THERMAL_GOVERNOR, THERMAL_NAME_LENGTH)) + def_governor = governor; } mutex_lock(&thermal_list_lock); list_for_each_entry(pos, &thermal_tz_list, node) { + /* + * only thermal zones with specified tz->tzp->governor_name + * may run with tz->govenor unset + */ if (pos->governor) continue; - if (pos->tzp) - name = pos->tzp->governor_name; - else - name = DEFAULT_THERMAL_GOVERNOR; + + name = pos->tzp->governor_name; + if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH)) pos->governor = governor; } @@ -342,8 +353,8 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz) static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip, enum thermal_trip_type trip_type) { - if (tz->governor) - tz->governor->throttle(tz, trip); + tz->governor ? tz->governor->throttle(tz, trip) : + def_governor->throttle(tz, trip); } static void handle_critical_trips(struct thermal_zone_device *tz, @@ -1533,7 +1544,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, if (tz->tzp) tz->governor = __find_governor(tz->tzp->governor_name); else - tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR); + tz->governor = def_governor; mutex_unlock(&thermal_governor_lock); -- cgit v0.10.2 From 2a26ebef841bac72a4c5776e920496e07b405628 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Mon, 3 Mar 2014 05:57:26 +0100 Subject: rt,blk,mq: Make blk_mq_cpu_notify_lock a raw spinlock [ 365.164040] BUG: sleeping function called from invalid context at kernel/rtmutex.c:674 [ 365.164041] in_atomic(): 1, irqs_disabled(): 1, pid: 26, name: migration/1 [ 365.164043] no locks held by migration/1/26. [ 365.164044] irq event stamp: 6648 [ 365.164056] hardirqs last enabled at (6647): [] restore_args+0x0/0x30 [ 365.164062] hardirqs last disabled at (6648): [] multi_cpu_stop+0x9d/0x120 [ 365.164070] softirqs last enabled at (0): [] copy_process.part.28+0x6fc/0x1920 [ 365.164072] softirqs last disabled at (0): [< (null)>] (null) [ 365.164076] CPU: 1 PID: 26 Comm: migration/1 Tainted: GF N 3.12.12-rt19-0.gcb6c4a2-rt #3 [ 365.164078] Hardware name: QCI QSSC-S4R/QSSC-S4R, BIOS QSSC-S4R.QCI.01.00.S013.032920111005 03/29/2011 [ 365.164091] 0000000000000001 ffff880a42ea7c30 ffffffff815367e6 ffffffff81a086c0 [ 365.164099] ffff880a42ea7c40 ffffffff8108919c ffff880a42ea7c60 ffffffff8153c24f [ 365.164107] ffff880a42ea91f0 00000000ffffffe1 ffff880a42ea7c88 ffffffff81297ec0 [ 365.164108] Call Trace: [ 365.164119] [] try_stack_unwind+0x191/0x1a0 [ 365.164127] [] dump_trace+0x92/0x360 [ 365.164133] [] show_trace_log_lvl+0x48/0x60 [ 365.164138] [] show_stack_log_lvl+0xd8/0x1d0 [ 365.164143] [] show_stack+0x20/0x50 [ 365.164153] [] dump_stack+0x54/0x9a [ 365.164163] [] __might_sleep+0xfc/0x140 [ 365.164173] [] rt_spin_lock+0x1f/0x70 [ 365.164182] [] blk_mq_main_cpu_notify+0x20/0x70 [ 365.164191] [] notifier_call_chain+0x4c/0x70 [ 365.164201] [] __raw_notifier_call_chain+0x9/0x10 [ 365.164207] [] cpu_notify+0x1e/0x40 [ 365.164217] [] take_cpu_down+0x22/0x40 [ 365.164223] [] multi_cpu_stop+0xd6/0x120 [ 365.164229] [] cpu_stopper_thread+0xd7/0x1e0 [ 365.164235] [] smpboot_thread_fn+0x203/0x380 [ 365.164241] [] kthread+0xc8/0xd0 [ 365.164250] [] ret_from_fork+0x7c/0xb0 [ 365.164429] smpboot: CPU 1 is now offline Signed-off-by: Mike Galbraith Signed-off-by: Jens Axboe diff --git a/block/blk-mq-cpu.c b/block/blk-mq-cpu.c index 3146bef..136ef86 100644 --- a/block/blk-mq-cpu.c +++ b/block/blk-mq-cpu.c @@ -11,7 +11,7 @@ #include "blk-mq.h" static LIST_HEAD(blk_mq_cpu_notify_list); -static DEFINE_SPINLOCK(blk_mq_cpu_notify_lock); +static DEFINE_RAW_SPINLOCK(blk_mq_cpu_notify_lock); static int blk_mq_main_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) @@ -19,12 +19,12 @@ static int blk_mq_main_cpu_notify(struct notifier_block *self, unsigned int cpu = (unsigned long) hcpu; struct blk_mq_cpu_notifier *notify; - spin_lock(&blk_mq_cpu_notify_lock); + raw_spin_lock(&blk_mq_cpu_notify_lock); list_for_each_entry(notify, &blk_mq_cpu_notify_list, list) notify->notify(notify->data, action, cpu); - spin_unlock(&blk_mq_cpu_notify_lock); + raw_spin_unlock(&blk_mq_cpu_notify_lock); return NOTIFY_OK; } @@ -32,16 +32,16 @@ void blk_mq_register_cpu_notifier(struct blk_mq_cpu_notifier *notifier) { BUG_ON(!notifier->notify); - spin_lock(&blk_mq_cpu_notify_lock); + raw_spin_lock(&blk_mq_cpu_notify_lock); list_add_tail(¬ifier->list, &blk_mq_cpu_notify_list); - spin_unlock(&blk_mq_cpu_notify_lock); + raw_spin_unlock(&blk_mq_cpu_notify_lock); } void blk_mq_unregister_cpu_notifier(struct blk_mq_cpu_notifier *notifier) { - spin_lock(&blk_mq_cpu_notify_lock); + raw_spin_lock(&blk_mq_cpu_notify_lock); list_del(¬ifier->list); - spin_unlock(&blk_mq_cpu_notify_lock); + raw_spin_unlock(&blk_mq_cpu_notify_lock); } void blk_mq_init_cpu_notifier(struct blk_mq_cpu_notifier *notifier, -- cgit v0.10.2 From 17b0c1f7865d8bf4f5e5aa94e2aeafb35d23e4e9 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 11 Feb 2014 21:39:06 +0200 Subject: drm/i915: vlv: reserve GT power context early We reserve the space for the power context in stolen memory at a fixed address from a delayed work. This races with the subsequent driver init/resume code which could allocate something at that address, so the reservation for the power context fails. Reserve the space up-front, so this can't happen. This also adds a missing struct_mutex lock around the stolen allocation, which wasn't taken in the delayed work path. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d77cc81..e1fc35a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3493,6 +3493,8 @@ static void valleyview_setup_pctx(struct drm_device *dev) u32 pcbr; int pctx_size = 24*1024; + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + pcbr = I915_READ(VLV_PCBR); if (pcbr) { /* BIOS set it up already, grab the pre-alloc'd space */ @@ -3542,8 +3544,6 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GTFIFODBG, gtfifodbg); } - valleyview_setup_pctx(dev); - /* If VLV, Forcewake all wells, else re-direct to regular path */ gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); @@ -4395,6 +4395,8 @@ void intel_enable_gt_powersave(struct drm_device *dev) ironlake_enable_rc6(dev); intel_init_emon(dev); } else if (IS_GEN6(dev) || IS_GEN7(dev)) { + if (IS_VALLEYVIEW(dev)) + valleyview_setup_pctx(dev); /* * PCU communication is slow and this doesn't need to be * done at any specific time, so do this out of our fast path -- cgit v0.10.2 From d9d820810d4eeac336c515dfb62561c21b296f07 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 27 Feb 2014 16:30:56 -0300 Subject: drm/i915: fix assert_cursor on BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to read the correct register, not a register that doesn't exist and will trigger "Unclaimed register" messages when we touch it. Also rearrange the checks in an attempt to prevent this error from happening again. Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä [Jani: dropped an extra empty line introduced.] Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4c16728..9b8a7c7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1092,12 +1092,12 @@ static void assert_cursor(struct drm_i915_private *dev_priv, struct drm_device *dev = dev_priv->dev; bool cur_state; - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) - cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE; - else if (IS_845G(dev) || IS_I865G(dev)) + if (IS_845G(dev) || IS_I865G(dev)) cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE; - else + else if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; + else + cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE; WARN(cur_state != state, "cursor on pipe %c assertion failure (expected %s, current %s)\n", -- cgit v0.10.2 From 6375b768a9850b6154478993e5fb566fa4614a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 3 Mar 2014 11:33:36 +0200 Subject: drm/i915: Reject >165MHz modes w/ DVI monitors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single-link DVI max dotclock is 165MHz. Filter out modes with higher dotclock when the monitor doesn't support HDMI. Modes higher than 165 MHz were allowed in commit 7d148ef51a657fd04036c3ed7803da600dd0d451 Author: Daniel Vetter Date: Mon Jul 22 18:02:39 2013 +0200 drm/i915: fix hdmi portclock limits Also don't attempt to use 12bpc mode with DVI monitors. Cc: Adam Nielsen Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75345 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=70331 Tested-by: Ralf Jung Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Signed-off-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 6db0d9d..ee3181e 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -845,7 +845,7 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi) { struct drm_device *dev = intel_hdmi_to_dev(hdmi); - if (IS_G4X(dev)) + if (!hdmi->has_hdmi_sink || IS_G4X(dev)) return 165000; else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) return 300000; @@ -899,8 +899,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, * outputs. We also need to check that the higher clock still fits * within limits. */ - if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= portclock_limit - && HAS_PCH_SPLIT(dev)) { + if (pipe_config->pipe_bpp > 8*3 && intel_hdmi->has_hdmi_sink && + clock_12bpc <= portclock_limit && HAS_PCH_SPLIT(dev)) { DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); desired_bpp = 12*3; -- cgit v0.10.2 From d13c46c67e546bb1dc1c4dc7c43e388d0119276b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 3 Mar 2014 14:49:51 +0000 Subject: DRM: armada: fix use of kfifo_put() The kfifo_put() API changed in 498d319bb512 (kfifo API type safety) which now results in the wrong pointer being added to the kfifo ring, which then causes an oops. Fix this. Cc: # 3.13 Signed-off-by: Russell King diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 62d0ff3..073dbf3 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -68,15 +68,7 @@ void __armada_drm_queue_unref_work(struct drm_device *dev, { struct armada_private *priv = dev->dev_private; - /* - * Yes, we really must jump through these hoops just to store a - * _pointer_ to something into the kfifo. This is utterly insane - * and idiotic, because it kfifo requires the _data_ pointed to by - * the pointer const, not the pointer itself. Not only that, but - * you have to pass a pointer _to_ the pointer you want stored. - */ - const struct drm_framebuffer *silly_api_alert = fb; - WARN_ON(!kfifo_put(&priv->fb_unref, &silly_api_alert)); + WARN_ON(!kfifo_put(&priv->fb_unref, fb)); schedule_work(&priv->fb_unref_work); } -- cgit v0.10.2 From de39d7a4f3693c4247135cbce42716bf2a113577 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 1 Mar 2014 02:18:57 +0300 Subject: hsr: off by one sanity check in hsr_register_frame_in() This is a sanity check and we never pass invalid values so this patch doesn't change anything. However the node->time_in[] array has HSR_MAX_SLAVE (2) elements and not HSR_MAX_DEV (3). Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 327060c..7ae0d7f6 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -297,7 +297,7 @@ static bool seq_nr_after(u16 a, u16 b) void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) { - if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) { + if ((dev_idx < 0) || (dev_idx >= HSR_MAX_SLAVE)) { WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); return; } -- cgit v0.10.2 From c84a57113f59486e6688be1cd443b96e3118efa0 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Fri, 28 Feb 2014 16:42:26 -0800 Subject: tcp: fix bogus RTT on special retransmission RTT may be bogus with tall loss probe (TLP) when a packet is retransmitted and latter (s)acked without TCPCB_SACKED_RETRANS flag. For example, TLP calls __tcp_retransmit_skb() instead of tcp_retransmit_skb(). The skb timestamps are updated but the sacked flag is not marked with TCPCB_SACKED_RETRANS. As a result we'll get bogus RTT in tcp_clean_rtx_queue() or in tcp_sacktag_one() on spurious retransmission. The fix is to apply the sticky flag TCP_EVER_RETRANS to enforce Karn's check on RTT sampling. However this will disable F-RTO if timeout occurs after TLP, by resetting undo_marker in tcp_enter_loss(). We relax this check to only if any pending retransmists are still in-flight. Signed-off-by: Yuchung Cheng Acked-by: Eric Dumazet Acked-by: Neal Cardwell Acked-by: Nandita Dukkipati Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 227cba7..eeaac39 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1945,8 +1945,9 @@ void tcp_enter_loss(struct sock *sk, int how) if (skb == tcp_send_head(sk)) break; - if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS) + if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) tp->undo_marker = 0; + TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) { TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index d718482..f0eb4e3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2337,6 +2337,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); unsigned int cur_mss; + int err; /* Inconslusive MTU probe */ if (icsk->icsk_mtup.probe_size) { @@ -2400,11 +2401,15 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) skb_headroom(skb) >= 0xFFFF)) { struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, GFP_ATOMIC); - return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : - -ENOBUFS; + err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : + -ENOBUFS; } else { - return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); + err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); } + + if (likely(!err)) + TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS; + return err; } int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) -- cgit v0.10.2 From e842b068bf9a9eb7b38e0e1875357440a1fd2169 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 1 Mar 2014 16:54:36 +0300 Subject: qlcnic: dcb: a couple off by one bugs The ->tc_cfg[] array has QLC_DCB_MAX_TC (8) elements so the check is off by one. These functions are always called with valid values though so it doesn't affect how the code works. Signed-off-by: Dan Carpenter Acked-by: Sucheta Chakraborty Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c index 77f1bce..7d4f549 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c @@ -807,7 +807,7 @@ qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio, !type->tc_param_valid) return; - if (tc < 0 || (tc > QLC_DCB_MAX_TC)) + if (tc < 0 || (tc >= QLC_DCB_MAX_TC)) return; tc_cfg = &type->tc_cfg[tc]; @@ -843,7 +843,7 @@ static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, !type->tc_param_valid) return; - if (pgid < 0 || pgid > QLC_DCB_MAX_PG) + if (pgid < 0 || pgid >= QLC_DCB_MAX_PG) return; pgcfg = &type->pg_cfg[pgid]; -- cgit v0.10.2 From c502224efb2eaec47f16da39235079598a0f3ed2 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Mon, 3 Mar 2014 14:24:20 +0530 Subject: be2net: Fix to reset transparent vlan tagging For disabling transparent tagging issue SET_HSW_CONFIG with pvid_valid=1 and pvid=0xFFFF and not with the default pvid as this case would fail in Lancer. Hence removing the get_hsw_config call from be_vf_setup() as it's only use of getting default pvid is no longer needed. Also do proper housekeeping only if the FW command succeeds. Signed-off-by: Kalesh AP Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 8d09615..05529e2 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -350,11 +350,13 @@ struct be_drv_stats { u32 roce_drops_crc; }; +/* A vlan-id of 0xFFFF must be used to clear transparent vlan-tagging */ +#define BE_RESET_VLAN_TAG_ID 0xFFFF + struct be_vf_cfg { unsigned char mac_addr[ETH_ALEN]; int if_handle; int pmac_id; - u16 def_vid; u16 vlan_tag; u32 tx_rate; }; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 04ac9c6..45662af 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1287,24 +1287,20 @@ static int be_set_vf_vlan(struct net_device *netdev, if (vlan || qos) { vlan |= qos << VLAN_PRIO_SHIFT; - if (vf_cfg->vlan_tag != vlan) { - /* If this is new value, program it. Else skip. */ - vf_cfg->vlan_tag = vlan; + if (vf_cfg->vlan_tag != vlan) status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_cfg->if_handle, 0); - } } else { /* Reset Transparent Vlan Tagging. */ - vf_cfg->vlan_tag = 0; - vlan = vf_cfg->def_vid; - status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, - vf_cfg->if_handle, 0); + status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, + vf + 1, vf_cfg->if_handle, 0); } - - if (status) + if (!status) + vf_cfg->vlan_tag = vlan; + else dev_info(&adapter->pdev->dev, - "VLAN %d config on VF %d failed\n", vlan, vf); + "VLAN %d config on VF %d failed\n", vlan, vf); return status; } @@ -3013,11 +3009,11 @@ static int be_vf_setup_init(struct be_adapter *adapter) static int be_vf_setup(struct be_adapter *adapter) { + struct device *dev = &adapter->pdev->dev; struct be_vf_cfg *vf_cfg; - u16 def_vlan, lnk_speed; int status, old_vfs, vf; - struct device *dev = &adapter->pdev->dev; u32 privileges; + u16 lnk_speed; old_vfs = pci_num_vf(adapter->pdev); if (old_vfs) { @@ -3084,12 +3080,6 @@ static int be_vf_setup(struct be_adapter *adapter) if (!status) vf_cfg->tx_rate = lnk_speed; - status = be_cmd_get_hsw_config(adapter, &def_vlan, - vf + 1, vf_cfg->if_handle, NULL); - if (status) - goto err; - vf_cfg->def_vid = def_vlan; - if (!old_vfs) be_cmd_enable_vf(adapter, vf + 1); } -- cgit v0.10.2 From 7ad09458a5be9a0990457c1a198e702559ac25ca Mon Sep 17 00:00:00 2001 From: Somnath kotur Date: Mon, 3 Mar 2014 14:24:43 +0530 Subject: be2net: clear promiscuous bits in adapter->flags while disabling promiscuous mode We should clear promiscuous bits in adapter->flags while disabling promiscuous mode. Else we will not put interface back into VLAN promisc mode if the vlans already added exceeds the maximum limit. Signed-off-by: Kalesh AP Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 45662af..9e6d678 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1157,6 +1157,14 @@ ret: return status; } +static void be_clear_promisc(struct be_adapter *adapter) +{ + adapter->promiscuous = false; + adapter->flags &= ~BE_FLAGS_VLAN_PROMISC; + + be_cmd_rx_filter(adapter, IFF_PROMISC, OFF); +} + static void be_set_rx_mode(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -1170,9 +1178,7 @@ static void be_set_rx_mode(struct net_device *netdev) /* BE was previously in promiscuous mode; disable it */ if (adapter->promiscuous) { - adapter->promiscuous = false; - be_cmd_rx_filter(adapter, IFF_PROMISC, OFF); - + be_clear_promisc(adapter); if (adapter->vlans_added) be_vid_config(adapter); } -- cgit v0.10.2 From c91289510602baf9a05b3501d97dc70efa269e01 Mon Sep 17 00:00:00 2001 From: Vasundhara Volam Date: Mon, 3 Mar 2014 14:25:07 +0530 Subject: be2net: Fix skb double free in be_xmit_wrokarounds() failure path skb_padto(), skb_share_check() and __vlan_put_tag() routines free skb when they return an error. This patch fixes be_xmit_workarounds() to not free skb again in such cases. Signed-off-by: Vasundhara Volam Signed-off-by: Sathya Perla Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 9e6d678..a9da6f9 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -927,7 +927,7 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, */ if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) { if (skb_padto(skb, 36)) - goto tx_drop; + goto err; skb->len = 36; } @@ -959,7 +959,7 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, vlan_tx_tag_present(skb)) { skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); if (unlikely(!skb)) - goto tx_drop; + goto err; } /* HW may lockup when VLAN HW tagging is requested on @@ -981,12 +981,13 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, be_vlan_tag_tx_chk(adapter, skb)) { skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); if (unlikely(!skb)) - goto tx_drop; + goto err; } return skb; tx_drop: dev_kfree_skb_any(skb); +err: return NULL; } -- cgit v0.10.2 From ec495fac119f2eaea8b8c6e6db17ba163c7af1f4 Mon Sep 17 00:00:00 2001 From: Vasundhara Volam Date: Mon, 3 Mar 2014 14:25:38 +0530 Subject: be2net: isolate TX workarounds not applicable to Skyhawk-R Some of TX workarounds in be_xmit_workarounds() routine are not applicable (and result in HW errors) to Skyhawk-R chip. Isolate BE3-R/Lancer specific workarounds to a separate routine. Signed-off-by: Vasundhara Volam Signed-off-by: Sathya Perla Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index a9da6f9..36c8061 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -913,24 +913,14 @@ static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, return BE3_chip(adapter) && be_ipv6_exthdr_check(skb); } -static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, - struct sk_buff *skb, - bool *skip_hw_vlan) +static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter, + struct sk_buff *skb, + bool *skip_hw_vlan) { struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; unsigned int eth_hdr_len; struct iphdr *ip; - /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or less - * may cause a transmit stall on that port. So the work-around is to - * pad short packets (<= 32 bytes) to a 36-byte length. - */ - if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) { - if (skb_padto(skb, 36)) - goto err; - skb->len = 36; - } - /* For padded packets, BE HW modifies tot_len field in IP header * incorrecly when VLAN tag is inserted by HW. * For padded packets, Lancer computes incorrect checksum. @@ -991,6 +981,29 @@ err: return NULL; } +static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, + struct sk_buff *skb, + bool *skip_hw_vlan) +{ + /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or + * less may cause a transmit stall on that port. So the work-around is + * to pad short packets (<= 32 bytes) to a 36-byte length. + */ + if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) { + if (skb_padto(skb, 36)) + return NULL; + skb->len = 36; + } + + if (BEx_chip(adapter) || lancer_chip(adapter)) { + skb = be_lancer_xmit_workarounds(adapter, skb, skip_hw_vlan); + if (!skb) + return NULL; + } + + return skb; +} + static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); -- cgit v0.10.2 From 3995d265b3640fb7dc843a3c5f62ced4f121fb89 Mon Sep 17 00:00:00 2001 From: Schuyler Patton Date: Mon, 3 Mar 2014 16:19:06 +0530 Subject: net: cpsw: fix cpdma rx descriptor leak on down interface This patch fixes a CPDMA RX Descriptor leak that occurs after taking the interface down when the CPSW is in Dual MAC mode. Previously the CPSW_ALE port was left open up which causes packets to be received and processed by the RX interrupt handler and were passed to the non active network interface where they were ignored. The fix is for the slave_stop function of the selected interface to disable the respective CPSW_ALE Port from forwarding packets. This blocks traffic from being received on the inactive interface. Signed-off-by: Schuyler Patton Reviewed-by: Felipe Balbi Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 651087b..ffd4d12 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1164,11 +1164,17 @@ static void cpsw_init_host_port(struct cpsw_priv *priv) static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv) { + u32 slave_port; + + slave_port = cpsw_get_slave_port(priv, slave->slave_num); + if (!slave->phy) return; phy_stop(slave->phy); phy_disconnect(slave->phy); slave->phy = NULL; + cpsw_ale_control_set(priv->ale, slave_port, + ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); } static int cpsw_ndo_open(struct net_device *ndev) -- cgit v0.10.2 From 10ddceb22bab11dab10ba645c7df2e4a8e7a5db5 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Mon, 3 Mar 2014 20:18:36 +0800 Subject: ip_tunnel:multicast process cause panic due to skb->_skb_refdst NULL pointer when ip_tunnel process multicast packets, it may check if the packet is looped back packet though 'rt_is_output_route(skb_rtable(skb))' in ip_tunnel_rcv(), but before that , skb->_skb_refdst has been dropped in iptunnel_pull_header(), so which leads to a panic. fix the bug: https://bugzilla.kernel.org/show_bug.cgi?id=70681 Signed-off-by: Xin Long Signed-off-by: David S. Miller diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 8d69626..6f847dd 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -108,7 +108,6 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto) nf_reset(skb); secpath_reset(skb); skb_clear_hash_if_not_l4(skb); - skb_dst_drop(skb); skb->vlan_tci = 0; skb_set_queue_mapping(skb, 0); skb->pkt_type = PACKET_HOST; -- cgit v0.10.2 From ec0223ec48a90cb605244b45f7c62de856403729 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 3 Mar 2014 17:23:04 +0100 Subject: net: sctp: fix sctp_sf_do_5_1D_ce to verify if we/peer is AUTH capable RFC4895 introduced AUTH chunks for SCTP; during the SCTP handshake RANDOM; CHUNKS; HMAC-ALGO are negotiated (CHUNKS being optional though): ---------- INIT[RANDOM; CHUNKS; HMAC-ALGO] ----------> <------- INIT-ACK[RANDOM; CHUNKS; HMAC-ALGO] --------- -------------------- COOKIE-ECHO --------------------> <-------------------- COOKIE-ACK --------------------- A special case is when an endpoint requires COOKIE-ECHO chunks to be authenticated: ---------- INIT[RANDOM; CHUNKS; HMAC-ALGO] ----------> <------- INIT-ACK[RANDOM; CHUNKS; HMAC-ALGO] --------- ------------------ AUTH; COOKIE-ECHO ----------------> <-------------------- COOKIE-ACK --------------------- RFC4895, section 6.3. Receiving Authenticated Chunks says: The receiver MUST use the HMAC algorithm indicated in the HMAC Identifier field. If this algorithm was not specified by the receiver in the HMAC-ALGO parameter in the INIT or INIT-ACK chunk during association setup, the AUTH chunk and all the chunks after it MUST be discarded and an ERROR chunk SHOULD be sent with the error cause defined in Section 4.1. [...] If no endpoint pair shared key has been configured for that Shared Key Identifier, all authenticated chunks MUST be silently discarded. [...] When an endpoint requires COOKIE-ECHO chunks to be authenticated, some special procedures have to be followed because the reception of a COOKIE-ECHO chunk might result in the creation of an SCTP association. If a packet arrives containing an AUTH chunk as a first chunk, a COOKIE-ECHO chunk as the second chunk, and possibly more chunks after them, and the receiver does not have an STCB for that packet, then authentication is based on the contents of the COOKIE-ECHO chunk. In this situation, the receiver MUST authenticate the chunks in the packet by using the RANDOM parameters, CHUNKS parameters and HMAC_ALGO parameters obtained from the COOKIE-ECHO chunk, and possibly a local shared secret as inputs to the authentication procedure specified in Section 6.3. If authentication fails, then the packet is discarded. If the authentication is successful, the COOKIE-ECHO and all the chunks after the COOKIE-ECHO MUST be processed. If the receiver has an STCB, it MUST process the AUTH chunk as described above using the STCB from the existing association to authenticate the COOKIE-ECHO chunk and all the chunks after it. [...] Commit bbd0d59809f9 introduced the possibility to receive and verification of AUTH chunk, including the edge case for authenticated COOKIE-ECHO. On reception of COOKIE-ECHO, the function sctp_sf_do_5_1D_ce() handles processing, unpacks and creates a new association if it passed sanity checks and also tests for authentication chunks being present. After a new association has been processed, it invokes sctp_process_init() on the new association and walks through the parameter list it received from the INIT chunk. It checks SCTP_PARAM_RANDOM, SCTP_PARAM_HMAC_ALGO and SCTP_PARAM_CHUNKS, and copies them into asoc->peer meta data (peer_random, peer_hmacs, peer_chunks) in case sysctl -w net.sctp.auth_enable=1 is set. If in INIT's SCTP_PARAM_SUPPORTED_EXT parameter SCTP_CID_AUTH is set, peer_random != NULL and peer_hmacs != NULL the peer is to be assumed asoc->peer.auth_capable=1, in any other case asoc->peer.auth_capable=0. Now, if in sctp_sf_do_5_1D_ce() chunk->auth_chunk is available, we set up a fake auth chunk and pass that on to sctp_sf_authenticate(), which at latest in sctp_auth_calculate_hmac() reliably dereferences a NULL pointer at position 0..0008 when setting up the crypto key in crypto_hash_setkey() by using asoc->asoc_shared_key that is NULL as condition key_id == asoc->active_key_id is true if the AUTH chunk was injected correctly from remote. This happens no matter what net.sctp.auth_enable sysctl says. The fix is to check for net->sctp.auth_enable and for asoc->peer.auth_capable before doing any operations like sctp_sf_authenticate() as no key is activated in sctp_auth_asoc_init_active_key() for each case. Now as RFC4895 section 6.3 states that if the used HMAC-ALGO passed from the INIT chunk was not used in the AUTH chunk, we SHOULD send an error; however in this case it would be better to just silently discard such a maliciously prepared handshake as we didn't even receive a parameter at all. Also, as our endpoint has no shared key configured, section 6.3 says that MUST silently discard, which we are doing from now onwards. Before calling sctp_sf_pdiscard(), we need not only to free the association, but also the chunk->auth_chunk skb, as commit bbd0d59809f9 created a skb clone in that case. I have tested this locally by using netfilter's nfqueue and re-injecting packets into the local stack after maliciously modifying the INIT chunk (removing RANDOM; HMAC-ALGO param) and the SCTP packet containing the COOKIE_ECHO (injecting AUTH chunk before COOKIE_ECHO). Fixed with this patch applied. Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") Signed-off-by: Daniel Borkmann Cc: Vlad Yasevich Cc: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 591b44d..ae65b6b 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -758,6 +758,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, struct sctp_chunk auth; sctp_ierror_t ret; + /* Make sure that we and the peer are AUTH capable */ + if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { + kfree_skb(chunk->auth_chunk); + sctp_association_free(new_asoc); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + } + /* set-up our fake chunk so that we can process it */ auth.skb = chunk->auth_chunk; auth.asoc = chunk->asoc; -- cgit v0.10.2 From 8b4703e9bd1172a5f8244276ebb94302e6153e26 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 3 Mar 2014 15:33:53 -0500 Subject: macvlan: Add support for 'always_on' offload features Macvlan currently inherits all of its features from the lower device. When lower device disables offload support, this causes macvlan to disable offload support as well. This causes performance regression when using macvlan/macvtap in bridge mode. It can be easily demonstrated by creating 2 namespaces using macvlan in bridge mode and running netperf between them: MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.0.0.1 () port 0 AF_INET Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 20.00 1204.61 To restore the performance, we add software offload features to the list of "always_on" features for macvlan. This way when a namespace or a guest using macvtap initially sends a packet, this packet will not be segmented at macvlan level. It will only be segmented when macvlan sends the packet to the lower device. MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.0.0.1 () port 0 AF_INET Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 20.00 5507.35 Fixes: 6acf54f1cf0a6747bac9fea26f34cfc5a9029523 (macvtap: Add support of packet capture on macvtap device.) Fixes: 797f87f83b60685ff8a13fa0572d2f10393c50d3 (macvlan: fix netdev feature propagation from lower device) CC: Florian Westphal CC: Christian Borntraeger CC: Jason Wang CC: Michael S. Tsirkin Tested-by: Christian Borntraeger Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index a5d2189..1831fb7 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -506,6 +506,9 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu) static struct lock_class_key macvlan_netdev_xmit_lock_key; static struct lock_class_key macvlan_netdev_addr_lock_key; +#define ALWAYS_ON_FEATURES \ + (NETIF_F_SG | NETIF_F_GEN_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX) + #define MACVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ @@ -539,7 +542,7 @@ static int macvlan_init(struct net_device *dev) dev->state = (dev->state & ~MACVLAN_STATE_MASK) | (lowerdev->state & MACVLAN_STATE_MASK); dev->features = lowerdev->features & MACVLAN_FEATURES; - dev->features |= NETIF_F_LLTX; + dev->features |= ALWAYS_ON_FEATURES; dev->gso_max_size = lowerdev->gso_max_size; dev->iflink = lowerdev->ifindex; dev->hard_header_len = lowerdev->hard_header_len; @@ -699,7 +702,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev, features = netdev_increment_features(vlan->lowerdev->features, features, mask); - features |= NETIF_F_LLTX; + features |= ALWAYS_ON_FEATURES; return features; } -- cgit v0.10.2 From c64d240df31513522901539a3206a41e9e6d00c8 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Mon, 3 Mar 2014 10:57:56 -0500 Subject: dm: fix Kconfig indentation Since DM_DEBUG_BLOCK_STACK_TRACING is a DM_PERSISTENT_DATA config option move it from drivers/md/Kconfig to drivers/md/persistent-data/Kconfig. Doing so fixes indentation for other DM config options. Signed-off-by: Mike Snitzer diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 9a06fe8..95ad936 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -254,16 +254,6 @@ config DM_THIN_PROVISIONING ---help--- Provides thin provisioning and snapshots that share a data store. -config DM_DEBUG_BLOCK_STACK_TRACING - boolean "Keep stack trace of persistent data block lock holders" - depends on STACKTRACE_SUPPORT && DM_PERSISTENT_DATA - select STACKTRACE - ---help--- - Enable this for messages that may help debug problems with the - block manager locking used by thin provisioning and caching. - - If unsure, say N. - config DM_CACHE tristate "Cache target (EXPERIMENTAL)" depends on BLK_DEV_DM diff --git a/drivers/md/persistent-data/Kconfig b/drivers/md/persistent-data/Kconfig index 19b2687..0c2dec7 100644 --- a/drivers/md/persistent-data/Kconfig +++ b/drivers/md/persistent-data/Kconfig @@ -6,3 +6,13 @@ config DM_PERSISTENT_DATA ---help--- Library providing immutable on-disk data structure support for device-mapper targets such as the thin provisioning target. + +config DM_DEBUG_BLOCK_STACK_TRACING + boolean "Keep stack trace of persistent data block lock holders" + depends on STACKTRACE_SUPPORT && DM_PERSISTENT_DATA + select STACKTRACE + ---help--- + Enable this for messages that may help debug problems with the + block manager locking used by thin provisioning and caching. + + If unsure, say N. -- cgit v0.10.2 From 2564338b13e6e132ee224edb63e1e872adf431f4 Mon Sep 17 00:00:00 2001 From: Marios Andreopoulos Date: Mon, 3 Mar 2014 18:19:59 +0200 Subject: libata: disable queued TRIM for Crucial M500 mSATA SSDs Queued TRIM commands cause problems and silent file system corruption on Crucial M500 SSDs. This patch disables them for the mSATA model of the drive. Signed-off-by: Marios Andreopoulos Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org # 3.12+ Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=71371 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 1a3dbd1..191cdfb 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4225,6 +4225,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* devices that don't properly handle queued TRIM commands */ { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, { "Crucial_CT???M500SSD1", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT???M500SSD3", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, /* * Some WD SATA-I drives spin up and down erratically when the link -- cgit v0.10.2 From 2c945820cab96ebf265598d998e63ef22393d0d4 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 3 Mar 2014 17:19:22 -0500 Subject: dm snapshot: fix metadata corruption Commit 55494bf2947dccdf2 ("dm snapshot: use dm-bufio") broke snapshots. Before that 3.14-rc1 commit, loading a snapshot's list of exceptions involved reading exception areas one by one into ps->area and inserting those exceptions into the hash table. Commit 55494bf2947dccdf2 changed it so that dm-bufio with prefetch is used to load exceptions in batchs. Exceptions are loaded correctly, but ps->area is left uninitialized. When a new exception is allocated, it is stored in this uninitialized ps->area which will be written to the disk. This causes metadata corruption. Fix this corruption by copying the last area that was read via dm-bufio into ps->area. Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index afc3d01..d6e8817 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -546,6 +546,9 @@ static int read_exceptions(struct pstore *ps, r = insert_exceptions(ps, area, callback, callback_context, &full); + if (!full) + memcpy(ps->area, area, ps->store->chunk_size << SECTOR_SHIFT); + dm_bufio_release(bp); dm_bufio_forget(client, chunk); -- cgit v0.10.2 From 45ab2813d40d88fc575e753c38478de242d03f88 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 26 Feb 2014 13:37:38 -0500 Subject: tracing: Do not add event files for modules that fail tracepoints If a module fails to add its tracepoints due to module tainting, do not create the module event infrastructure in the debugfs directory. As the events will not work and worse yet, they will silently fail, making the user wonder why the events they enable do not display anything. Having a warning on module load and the events not visible to the users will make the cause of the problem much clearer. Link: http://lkml.kernel.org/r/20140227154923.265882695@goodmis.org Fixes: 6d723736e472 "tracing/events: add support for modules to TRACE_EVENT" Acked-by: Mathieu Desnoyers Cc: stable@vger.kernel.org # 2.6.31+ Cc: Rusty Russell Signed-off-by: Steven Rostedt diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index accc497..7159a0a 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -60,6 +60,12 @@ struct tp_module { unsigned int num_tracepoints; struct tracepoint * const *tracepoints_ptrs; }; +bool trace_module_has_bad_taint(struct module *mod); +#else +static inline bool trace_module_has_bad_taint(struct module *mod) +{ + return false; +} #endif /* CONFIG_MODULES */ struct tracepoint_iter { diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index e71ffd4..f3989ce 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1777,6 +1777,16 @@ static void trace_module_add_events(struct module *mod) { struct ftrace_event_call **call, **start, **end; + if (!mod->num_trace_events) + return; + + /* Don't add infrastructure for mods without tracepoints */ + if (trace_module_has_bad_taint(mod)) { + pr_err("%s: module has bad taint, not creating trace events\n", + mod->name); + return; + } + start = mod->trace_events; end = mod->trace_events + mod->num_trace_events; diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 29f2654..031cc56 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -631,6 +631,11 @@ void tracepoint_iter_reset(struct tracepoint_iter *iter) EXPORT_SYMBOL_GPL(tracepoint_iter_reset); #ifdef CONFIG_MODULES +bool trace_module_has_bad_taint(struct module *mod) +{ + return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP)); +} + static int tracepoint_module_coming(struct module *mod) { struct tp_module *tp_mod, *iter; @@ -641,7 +646,7 @@ static int tracepoint_module_coming(struct module *mod) * module headers (for forced load), to make sure we don't cause a crash. * Staging and out-of-tree GPL modules are fine. */ - if (mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP))) + if (trace_module_has_bad_taint(mod)) return 0; mutex_lock(&tracepoints_mutex); tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL); -- cgit v0.10.2 From 939d9f16994166156fa3d6dfece9c46b92e368e0 Mon Sep 17 00:00:00 2001 From: Nenghua Cao Date: Mon, 3 Mar 2014 19:08:23 +0800 Subject: ASoC: core: fix coccinelle warnings sound/soc/soc-core.c:2708:6-13: WARNING: Assignment of bool to 0/1 sound/soc/soc-core.c:2726:3-10: WARNING: Assignment of bool to 0/1 More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Nenghua Cao Signed-off-by: Mark Brown diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 393ff06..45a1faf 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2818,7 +2818,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; - bool type_2r = 0; + bool type_2r = false; unsigned int val2 = 0; unsigned int val, val_mask; @@ -2836,7 +2836,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, val |= val2 << rshift; } else { val2 = val2 << shift; - type_2r = 1; + type_2r = true; } } err = snd_soc_update_bits_locked(codec, reg, val_mask, val); -- cgit v0.10.2 From 48b5e1fb883c8c72b50ee1ccd3ee51e4f53f632f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 13:46:44 +0100 Subject: ASoC: wm8753: Remove superfluous 'codec->cache_sync = 1' The wm8763 driver uses regmap for IO which means that codec->cache_sync is not used. The line was added in commit d3398ff ('ASoC: Convert WM8753 to direct regmap API usage'). Presumably this was meant to be regcache_mark_dirty(), but since we already call regcache_mark_dirty() in the core when suspending the CODEC it is safe to just remove the line. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index be85da9..a02e76c 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1440,7 +1440,6 @@ static void wm8753_work(struct work_struct *work) static int wm8753_suspend(struct snd_soc_codec *codec) { wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); - codec->cache_sync = 1; return 0; } -- cgit v0.10.2 From 055bbe2df957343fece60fe1f60553a9c1005217 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 13:45:32 +0100 Subject: ASoC: wm{5102, 5110, 8997}: Replace codec->control_data with arizona->regmap With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the wm5192, wm5110 and wm8997 drivers for this by using arizona->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 293dffc..3410905 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -582,7 +582,7 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 4de2bf1..d7bf884 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -136,7 +136,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 4e6442c..e10f44d 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -86,7 +86,7 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; -- cgit v0.10.2 From 9bfed6cf4fa2cd2c5e80431244348b0c5d933cf5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:42:47 -0800 Subject: ASoC: rsnd: run rsnd_path_init() when probe() timing Current rsnd SSIU/SSI/SCU/SRU path is set when playback/capture starts up. But it is meaningless method, since the path is based on platform and can be set in probe() timing. This patch sets the path on probe() timing. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f0745af..96cb786 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -317,9 +317,9 @@ void rsnd_dma_quit(struct rsnd_priv *priv, ret; \ }) -int rsnd_dai_connect(struct rsnd_dai *rdai, - struct rsnd_mod *mod, - struct rsnd_dai_stream *io) +static int rsnd_dai_connect(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { if (!mod) return -EIO; @@ -340,7 +340,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, return 0; } -int rsnd_dai_disconnect(struct rsnd_mod *mod) +static int rsnd_dai_disconnect(struct rsnd_mod *mod) { list_del_init(&mod->list); mod->io = NULL; @@ -418,10 +418,6 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, { struct snd_pcm_runtime *runtime = substream->runtime; - if (!list_empty(&io->head)) - return -EIO; - - INIT_LIST_HEAD(&io->head); io->substream = substream; io->byte_pos = 0; io->period_pos = 0; @@ -476,10 +472,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_init(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_dai_call(rdai, io, init); if (ret < 0) goto dai_trigger_end; @@ -497,10 +489,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_exit(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_platform_call(priv, dai, stop, ssi_id); if (ret < 0) goto dai_trigger_end; @@ -576,6 +564,70 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .set_fmt = rsnd_soc_dai_set_fmt, }; +static int rsnd_path_init(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod; + int ret; + int id; + + /* + * Gen1 is created by SRU/SSI, and this SRU is base module of + * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) + * + * Easy image is.. + * Gen1 SRU = Gen2 SCU + SSIU + etc + * + * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is + * using fixed path. + * + * Then, SSI id = SCU id here + */ + /* get SSI's ID */ + mod = rsnd_ssi_mod_get_frm_dai(priv, + rsnd_dai_id(priv, rdai), + rsnd_dai_is_play(rdai, io)); + if (!mod) + return 0; + id = rsnd_mod_id(mod); + ret = 0; + + /* SCU */ + mod = rsnd_scu_mod_get(priv, id); + if (mod) { + ret = rsnd_dai_connect(rdai, mod, io); + if (ret < 0) + return ret; + } + + /* SSI */ + mod = rsnd_ssi_mod_get(priv, id); + if (mod) { + ret = rsnd_dai_connect(rdai, mod, io); + if (ret < 0) + return ret; + } + + return ret; +} + +static int rsnd_path_exit(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod, *n; + int ret = 0; + + /* + * remove all mod from rdai + */ + for_each_rsnd_mod(mod, n, io) + ret |= rsnd_dai_disconnect(mod); + + return ret; +} + static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { @@ -634,12 +686,14 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].playback.formats = RSND_FMTS; drv[i].playback.channels_min = 2; drv[i].playback.channels_max = 2; + rsnd_path_init(priv, &rdai[i], &rdai[i].playback); } if (cmod) { drv[i].capture.rates = RSND_RATES; drv[i].capture.formats = RSND_FMTS; drv[i].capture.channels_min = 2; drv[i].capture.channels_max = 2; + rsnd_path_init(priv, &rdai[i], &rdai[i].capture); } dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name, @@ -653,6 +707,14 @@ static int rsnd_dai_probe(struct platform_device *pdev, static void rsnd_dai_remove(struct platform_device *pdev, struct rsnd_priv *priv) { + struct rsnd_dai *rdai; + int i; + + for (i = 0; i < rsnd_rdai_nr(priv); i++) { + rdai = rsnd_dai_get(priv, i); + rsnd_path_exit(priv, rdai, &rdai->playback); + rsnd_path_exit(priv, rdai, &rdai->capture); + } } /* diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index bcb98f4..4f2c1d0 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -155,62 +155,6 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, return 0; } -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod; - int ret; - int id; - - /* - * Gen1 is created by SRU/SSI, and this SRU is base module of - * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) - * - * Easy image is.. - * Gen1 SRU = Gen2 SCU + SSIU + etc - * - * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is - * using fixed path. - * - * Then, SSI id = SCU id here - */ - - /* get SSI's ID */ - mod = rsnd_ssi_mod_get_frm_dai(priv, - rsnd_dai_id(priv, rdai), - rsnd_dai_is_play(rdai, io)); - id = rsnd_mod_id(mod); - - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - if (ret < 0) - return ret; - - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - - return ret; -} - -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod, *n; - int ret = 0; - - /* - * remove all mod from rdai - */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); - - return ret; -} - /* * Gen2 */ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3962a50..6a25203 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -210,9 +210,6 @@ struct rsnd_dai { i++) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); -int rsnd_dai_disconnect(struct rsnd_mod *mod); -int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, - struct rsnd_dai_stream *io); int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) @@ -229,12 +226,6 @@ int rsnd_gen_probe(struct platform_device *pdev, struct rsnd_priv *priv); void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv); -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); -- cgit v0.10.2 From a126021d144bae88a563db2b57b0ad5eb1ee66d9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:42:55 -0800 Subject: ASoC: rsnd: use mod array instead of list on rdai struct rsnd_dai_stream used list for mod list. It added only odd flexibility to current driver, and it is a factor which makes extendibility difficult. rsnd use mod array instead of list from now. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 96cb786..416b078 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -121,12 +121,13 @@ char *rsnd_mod_name(struct rsnd_mod *mod) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id) { mod->priv = priv; mod->id = id; mod->ops = ops; - INIT_LIST_HEAD(&mod->list); + mod->type = type; } /* @@ -307,9 +308,12 @@ void rsnd_dma_quit(struct rsnd_priv *priv, #define rsnd_dai_call(rdai, io, fn) \ ({ \ - struct rsnd_mod *mod, *n; \ - int ret = 0; \ - for_each_rsnd_mod(mod, n, (io)) { \ + struct rsnd_mod *mod; \ + int ret = 0, i; \ + for (i = 0; i < RSND_MOD_MAX; i++) { \ + mod = (io)->mod[i]; \ + if (!mod) \ + continue; \ ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ if (ret < 0) \ break; \ @@ -317,14 +321,13 @@ void rsnd_dma_quit(struct rsnd_priv *priv, ret; \ }) -static int rsnd_dai_connect(struct rsnd_dai *rdai, - struct rsnd_mod *mod, +static int rsnd_dai_connect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { if (!mod) return -EIO; - if (!list_empty(&mod->list)) { + if (io->mod[mod->type]) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); @@ -334,15 +337,15 @@ static int rsnd_dai_connect(struct rsnd_dai *rdai, return -EIO; } - list_add_tail(&mod->list, &io->head); + io->mod[mod->type] = mod; mod->io = io; return 0; } -static int rsnd_dai_disconnect(struct rsnd_mod *mod) +static int rsnd_dai_disconnect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { - list_del_init(&mod->list); + io->mod[mod->type] = NULL; mod->io = NULL; return 0; @@ -596,7 +599,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, /* SCU */ mod = rsnd_scu_mod_get(priv, id); if (mod) { - ret = rsnd_dai_connect(rdai, mod, io); + ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } @@ -604,7 +607,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, /* SSI */ mod = rsnd_ssi_mod_get(priv, id); if (mod) { - ret = rsnd_dai_connect(rdai, mod, io); + ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } @@ -616,14 +619,18 @@ static int rsnd_path_exit(struct rsnd_priv *priv, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_mod *mod, *n; - int ret = 0; + struct rsnd_mod *mod; + int ret = 0, i; /* * remove all mod from rdai */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); + for (i = 0; i < RSND_MOD_MAX; i++) { + mod = io->mod[i]; + if (!mod) + continue; + ret |= rsnd_dai_disconnect(mod, io); + } return ret; } @@ -671,9 +678,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, /* * init rsnd_dai */ - INIT_LIST_HEAD(&rdai[i].playback.head); - INIT_LIST_HEAD(&rdai[i].capture.head); - snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); /* diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 6a25203..7767a8f 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -135,6 +135,11 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * R-Car sound mod */ +enum rsnd_mod_type { + RSND_MOD_SCU = 0, + RSND_MOD_SSI, + RSND_MOD_MAX, +}; struct rsnd_mod_ops { char *name; @@ -155,9 +160,9 @@ struct rsnd_mod_ops { struct rsnd_dai_stream; struct rsnd_mod { int id; + enum rsnd_mod_type type; struct rsnd_priv *priv; struct rsnd_mod_ops *ops; - struct list_head list; /* connect to rsnd_dai playback/capture */ struct rsnd_dma dma; struct rsnd_dai_stream *io; }; @@ -167,12 +172,11 @@ struct rsnd_mod { #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) #define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) -#define for_each_rsnd_mod(pos, n, io) \ - list_for_each_entry_safe(pos, n, &(io)->head, list) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id); char *rsnd_mod_name(struct rsnd_mod *mod); @@ -181,8 +185,8 @@ char *rsnd_mod_name(struct rsnd_mod *mod); */ #define RSND_DAI_NAME_SIZE 16 struct rsnd_dai_stream { - struct list_head head; /* head of rsnd_mod list */ struct snd_pcm_substream *substream; + struct rsnd_mod *mod[RSND_MOD_MAX]; int byte_pos; int period_pos; int byte_per_period; diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 882e837..81264ec 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -659,7 +659,7 @@ int rsnd_scu_probe(struct platform_device *pdev, ops = &rsnd_scu_non_gen2_ops; } - rsnd_mod_init(priv, &scu->mod, ops, i); + rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); dev_dbg(dev, "SCU%d probed\n", i); } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 38a62a8..480dde5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -584,7 +584,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, dev_dbg(dev, "SSI%d use PIO transfer\n", i); } - rsnd_mod_init(priv, &ssi->mod, ops, i); + rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); rsnd_ssi_parent_clk_setup(priv, ssi); } -- cgit v0.10.2 From 374e5426377604a94d672650ef22dd2b4285de17 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:03 -0800 Subject: ASoC: rsnd: get ssi/scu from rsnd_dai_stream Current driver is assuming that SSI id = SCU id. But, now, it can get correct SSI/SCU from rsnd_dai_stream. use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 7767a8f..cbc38a2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -192,6 +192,8 @@ struct rsnd_dai_stream { int byte_per_period; int next_period_byte; }; +#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) +#define rsnd_io_to_mod_scu(io) ((io)->mod[RSND_MOD_SCU]) struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -311,7 +313,7 @@ void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); #define rsnd_scu_nr(priv) ((priv)->scu_nr) diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 81264ec..1073d35 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -121,7 +121,8 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + int ssi_id = rsnd_mod_id(ssi_mod); u32 convert_rate = rsnd_scu_convert_rate(scu); if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { @@ -134,15 +135,15 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, /* * SSI_MODE0 */ - rsnd_mod_bset(mod, SSI_MODE0, (1 << id), - rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << id)); + rsnd_mod_bset(mod, SSI_MODE0, (1 << ssi_id), + rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << ssi_id)); /* * SSI_MODE1 */ - if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + if (rsnd_ssi_is_pin_sharing(ssi_mod)) { int shift = -1; - switch (id) { + switch (ssi_id) { case 1: shift = 0; break; @@ -165,14 +166,13 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, } unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) { struct rsnd_scu *scu; unsigned int rate; - /* this function is assuming SSI id = SCU id here */ - scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); + scu = rsnd_mod_to_scu(rsnd_io_to_mod_scu(io)); /* * return convert rate if SRC is used, @@ -583,8 +583,10 @@ static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + /* enable PIO interrupt */ - rsnd_mod_write(mod, INT_ENABLE, 0x0f000000); + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 480dde5..25a7d44 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -121,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; - unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime); + unsigned int rate = rsnd_scu_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG -- cgit v0.10.2 From 468be93eb4e28c5710ed8acc1b938937707e537c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:11 -0800 Subject: ASoC: rsnd: use devm_clk_get() instead of clk_get() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 69d9394..a05ad81 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -405,11 +405,11 @@ int rsnd_adg_probe(struct platform_device *pdev, return -ENOMEM; } - clk_orig = clk_get(dev, NULL); - adg->clk[CLKA] = clk_get(dev, "clk_a"); - adg->clk[CLKB] = clk_get(dev, "clk_b"); - adg->clk[CLKC] = clk_get(dev, "clk_c"); - adg->clk[CLKI] = clk_get(dev, "clk_i"); + clk_orig = devm_clk_get(dev, NULL); + adg->clk[CLKA] = devm_clk_get(dev, "clk_a"); + adg->clk[CLKB] = devm_clk_get(dev, "clk_b"); + adg->clk[CLKC] = devm_clk_get(dev, "clk_c"); + adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); /* * It request device dependent audio clock. @@ -432,10 +432,10 @@ int rsnd_adg_probe(struct platform_device *pdev, * but will be removed soon */ if (use_old_style) { - adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); - adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); - adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); - adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + adg->clk[CLKA] = devm_clk_get(NULL, "audio_clk_a"); + adg->clk[CLKB] = devm_clk_get(NULL, "audio_clk_b"); + adg->clk[CLKC] = devm_clk_get(NULL, "audio_clk_c"); + adg->clk[CLKI] = devm_clk_get(NULL, "audio_clk_internal"); } for_each_rsnd_clk(clk, adg, i) { @@ -457,10 +457,4 @@ int rsnd_adg_probe(struct platform_device *pdev, void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_adg *adg = priv->adg; - struct clk *clk; - int i; - - for_each_rsnd_clk(clk, adg, i) - clk_put(clk); } -- cgit v0.10.2 From d1ac970f5de94bef9e094b46f016899d04e8178b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:18 -0800 Subject: ASoC: rsnd: use function pointer for each probe R-Car sound consists of many devices. It will have more device support in the future. Thus, for each probe become now function pointer array. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 416b078..ea74761 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -814,7 +814,15 @@ static int rsnd_probe(struct platform_device *pdev) struct rcar_snd_info *info; struct rsnd_priv *priv; struct device *dev = &pdev->dev; - int ret; + int (*probe_func[])(struct platform_device *pdev, + struct rsnd_priv *priv) = { + rsnd_gen_probe, + rsnd_ssi_probe, + rsnd_scu_probe, + rsnd_adg_probe, + rsnd_dai_probe, + }; + int ret, i; info = pdev->dev.platform_data; if (!info) { @@ -838,25 +846,11 @@ static int rsnd_probe(struct platform_device *pdev) /* * init each module */ - ret = rsnd_gen_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_ssi_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_scu_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_adg_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_dai_probe(pdev, priv); - if (ret) - return ret; + for (i = 0; i < ARRAY_SIZE(probe_func); i++) { + ret = probe_func[i](pdev, priv); + if (ret) + return ret; + } /* * asoc register -- cgit v0.10.2 From 685fb3eb31445bd872ab30ae301404b2cac7cd75 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:26 -0800 Subject: ASoC: rsnd: remove unused SSI_CONTROL Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 4f2c1d0..92d1bc9 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -173,7 +173,6 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), /* FIXME: it needs SSI_MODE2/3 in the future */ - RSND_GEN2_S_REG(gen, SSIU, SSI_CONTROL, 0x810), RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index cbc38a2..e16acd2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -39,7 +39,6 @@ enum rsnd_reg { RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ RSND_REG_SRC_CTRL, /* for Gen2 */ RSND_REG_SSI_CTRL, /* for Gen2 */ - RSND_REG_SSI_CONTROL, RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, -- cgit v0.10.2 From 8467dedc9dae3630a2ede49a43120af3ed54ba19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:33 -0800 Subject: ASoC: rsnd: modify rsnd_adg_ssi_ws_timing_gen2() parameter rsnd_adg_ssi_ws_timing_gen2() returns SSI WS timing, and it used "mod" as parameter. but, this "mod" is sometimes not ssi mod. Get SSI mod from rsnd_dai_stream Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a05ad81..8df00ac 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -32,8 +32,9 @@ struct rsnd_adg { #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_mod *mod) +static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) { + struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); int id = rsnd_mod_id(mod); int ws = id; @@ -67,7 +68,7 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, u32 mask, ws; u32 in, out; - ws = rsnd_adg_ssi_ws_timing_gen2(mod); + ws = rsnd_adg_ssi_ws_timing_gen2(io); in = (is_play) ? timsel : ws; out = (is_play) ? ws : timsel; @@ -174,7 +175,7 @@ int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - u32 val = rsnd_adg_ssi_ws_timing_gen2(mod); + u32 val = rsnd_adg_ssi_ws_timing_gen2(io); return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); } -- cgit v0.10.2 From c82e1c8874e5abaf52f9ed886386cbe08ec98a5b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:40 -0800 Subject: ASoC: rsnd: share reg_field and reduce memory Gen1/Gen2 code never be used in same time. Thus, driver can share Gen1 only register and Gen2 only register. It can reduce memory too. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e16acd2..d5afdee 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -32,18 +32,8 @@ */ enum rsnd_reg { /* SRU/SCU/SSIU */ - RSND_REG_SRC_ROUTE_SEL, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL0, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ - RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ - RSND_REG_SRC_CTRL, /* for Gen2 */ - RSND_REG_SSI_CTRL, /* for Gen2 */ - RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ - RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, - RSND_REG_INT_ENABLE, /* for Gen2 */ RSND_REG_SRC_BUSIF_MODE, RSND_REG_SRC_ROUTE_MODE0, RSND_REG_SRC_SWRSR, @@ -52,9 +42,6 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, - RSND_REG_SRC_MNFSR, /* for Gen1 */ - RSND_REG_SRC_BSDSR, /* for Gen2 */ - RSND_REG_SRC_BSISR, /* for Gen2 */ /* ADG */ RSND_REG_BRRA, @@ -62,21 +49,6 @@ enum rsnd_reg { RSND_REG_SSICKR, RSND_REG_AUDIO_CLK_SEL0, RSND_REG_AUDIO_CLK_SEL1, - RSND_REG_AUDIO_CLK_SEL2, - RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ - RSND_REG_DIV_EN, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ /* SSI */ RSND_REG_SSICR, @@ -85,9 +57,62 @@ enum rsnd_reg { RSND_REG_SSIRDR, RSND_REG_SSIWSR, + /* SHARE see below */ + RSND_REG_SHARE01, + RSND_REG_SHARE02, + RSND_REG_SHARE03, + RSND_REG_SHARE04, + RSND_REG_SHARE05, + RSND_REG_SHARE06, + RSND_REG_SHARE07, + RSND_REG_SHARE08, + RSND_REG_SHARE09, + RSND_REG_SHARE10, + RSND_REG_SHARE11, + RSND_REG_SHARE12, + RSND_REG_SHARE13, + RSND_REG_SHARE14, + RSND_REG_SHARE15, + RSND_REG_SHARE16, + RSND_REG_SHARE17, + RSND_REG_SHARE18, + RSND_REG_SHARE19, + RSND_REG_MAX, }; +/* Gen1 only */ +#define RSND_REG_SRC_ROUTE_SEL RSND_REG_SHARE01 +#define RSND_REG_SRC_TMG_SEL0 RSND_REG_SHARE02 +#define RSND_REG_SRC_TMG_SEL1 RSND_REG_SHARE03 +#define RSND_REG_SRC_TMG_SEL2 RSND_REG_SHARE04 +#define RSND_REG_SRC_ROUTE_CTRL RSND_REG_SHARE05 +#define RSND_REG_SRC_MNFSR RSND_REG_SHARE06 +#define RSND_REG_AUDIO_CLK_SEL3 RSND_REG_SHARE07 +#define RSND_REG_AUDIO_CLK_SEL4 RSND_REG_SHARE08 +#define RSND_REG_AUDIO_CLK_SEL5 RSND_REG_SHARE09 + +/* Gen2 only */ +#define RSND_REG_SRC_CTRL RSND_REG_SHARE01 +#define RSND_REG_SSI_CTRL RSND_REG_SHARE02 +#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 +#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 +#define RSND_REG_INT_ENABLE RSND_REG_SHARE05 +#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 +#define RSND_REG_SRC_BSISR RSND_REG_SHARE07 +#define RSND_REG_DIV_EN RSND_REG_SHARE08 +#define RSND_REG_SRCIN_TIMSEL0 RSND_REG_SHARE09 +#define RSND_REG_SRCIN_TIMSEL1 RSND_REG_SHARE10 +#define RSND_REG_SRCIN_TIMSEL2 RSND_REG_SHARE11 +#define RSND_REG_SRCIN_TIMSEL3 RSND_REG_SHARE12 +#define RSND_REG_SRCIN_TIMSEL4 RSND_REG_SHARE13 +#define RSND_REG_SRCOUT_TIMSEL0 RSND_REG_SHARE14 +#define RSND_REG_SRCOUT_TIMSEL1 RSND_REG_SHARE15 +#define RSND_REG_SRCOUT_TIMSEL2 RSND_REG_SHARE16 +#define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 +#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 +#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 + struct rsnd_priv; struct rsnd_mod; struct rsnd_dai; -- cgit v0.10.2 From ea2787f350ea5f649fda6bb708c4182cf4ec06ca Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 4 Mar 2014 00:45:18 +0200 Subject: ASoC: n810: fix init with DT boot Since 3.14-rc1 only DT boot has been supported on N810, so this file fails to init. Make a minimal fix to retain functionality. This file should be properly converted to DT in longer term. There seems to be still other unresolved issues with N810 audio support, but this patch is needed at minimum as otherwise the machine driver probing would completely fail. Signed-off-by: Aaro Koskinen Acked-by: Jarkko Nikula Signed-off-by: Mark Brown diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 3fde9e4..d163e18 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -305,7 +305,9 @@ static int __init n810_soc_init(void) int err; struct device *dev; - if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) + if (!of_have_populated_dt() || + (!of_machine_is_compatible("nokia,n810") && + !of_machine_is_compatible("nokia,n810-wimax"))) return -ENODEV; n810_snd_device = platform_device_alloc("soc-audio", -1); -- cgit v0.10.2 From 931f27c6e892fdfe98896055e0df7962e21969d9 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 28 Feb 2014 10:48:19 +0800 Subject: ASoC: cache: Do the codec->reg_cache zero pionter check For the snd_soc_cache_init(), the reg_size maybe zero and then the value of codec->reg_cache, which is alloced via kzalloc, maybe equal to ZERO_SIZE_PTR. If the reg parameter of snd_soc_cache_write() is large enough, the cache[idx] = val maybe cause the kernel crash... So this patch fix this via doing the zero pionter check of it. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 375dc6d..bfed3e4 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -96,8 +96,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) { dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", codec->name); - if (!codec->reg_cache) - return 0; + kfree(codec->reg_cache); codec->reg_cache = NULL; return 0; @@ -117,8 +116,9 @@ int snd_soc_cache_read(struct snd_soc_codec *codec, return -EINVAL; mutex_lock(&codec->cache_rw_mutex); - *value = snd_soc_get_cache_val(codec->reg_cache, reg, - codec->driver->reg_word_size); + if (!ZERO_OR_NULL_PTR(codec->reg_cache)) + *value = snd_soc_get_cache_val(codec->reg_cache, reg, + codec->driver->reg_word_size); mutex_unlock(&codec->cache_rw_mutex); return 0; @@ -136,8 +136,9 @@ int snd_soc_cache_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { mutex_lock(&codec->cache_rw_mutex); - snd_soc_set_cache_val(codec->reg_cache, reg, value, - codec->driver->reg_word_size); + if (!ZERO_OR_NULL_PTR(codec->reg_cache)) + snd_soc_set_cache_val(codec->reg_cache, reg, value, + codec->driver->reg_word_size); mutex_unlock(&codec->cache_rw_mutex); return 0; -- cgit v0.10.2 From 3b4467522630b7ea0d65a691007ef0a93d471f8f Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Tue, 4 Mar 2014 16:20:18 +0800 Subject: ALSA: hda - add automute fix for another dell AIO model When plugging a headphone or headset, lots of noise is heard from internal speaker, after changing the automute via amp instead of pinctl, the noise disappears. BugLink: https://bugs.launchpad.net/bugs/1268468 Cc: David Henningsson Cc: stable@vger.kernel.org Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7ba7a11f..850296a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5164,7 +5164,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE), - SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP), SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP), -- cgit v0.10.2 From aa15aa0e869cb218f68faff8f229fa6b6b5cdf08 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 3 Mar 2014 15:38:17 -0800 Subject: MAINTAINERS: EDAC: add Mauro and Borislav as interim patch collectors We're more or less collecting EDAC patches already anyway so let's hold it down so that get_maintainer sees it too. Signed-off-by: Borislav Petkov Acked-by: Mauro Carvalho Chehab Cc: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index c6d0e93..7abe81e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3095,6 +3095,8 @@ F: fs/ecryptfs/ EDAC-CORE M: Doug Thompson +M: Borislav Petkov +M: Mauro Carvalho Chehab L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Supported -- cgit v0.10.2 From 668f9abbd4334e6c29fa8acd71635c4f9101caa7 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 3 Mar 2014 15:38:18 -0800 Subject: mm: close PageTail race Commit bf6bddf1924e ("mm: introduce compaction and migration for ballooned pages") introduces page_count(page) into memory compaction which dereferences page->first_page if PageTail(page). This results in a very rare NULL pointer dereference on the aforementioned page_count(page). Indeed, anything that does compound_head(), including page_count() is susceptible to racing with prep_compound_page() and seeing a NULL or dangling page->first_page pointer. This patch uses Andrea's implementation of compound_trans_head() that deals with such a race and makes it the default compound_head() implementation. This includes a read memory barrier that ensures that if PageTail(head) is true that we return a head page that is neither NULL nor dangling. The patch then adds a store memory barrier to prep_compound_page() to ensure page->first_page is set. This is the safest way to ensure we see the head page that we are expecting, PageTail(page) is already in the unlikely() path and the memory barriers are unfortunately required. Hugetlbfs is the exception, we don't enforce a store memory barrier during init since no race is possible. Signed-off-by: David Rientjes Cc: Holger Kiehl Cc: Christoph Lameter Cc: Rafael Aquini Cc: Vlastimil Babka Cc: Michal Hocko Cc: Mel Gorman Cc: Andrea Arcangeli Cc: Rik van Riel Cc: "Kirill A. Shutemov" Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 8184451..422b7d8 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -874,7 +874,7 @@ bio_pageinc(struct bio *bio) /* Non-zero page count for non-head members of * compound pages is no longer allowed by the kernel. */ - page = compound_trans_head(bv.bv_page); + page = compound_head(bv.bv_page); atomic_inc(&page->_count); } } @@ -887,7 +887,7 @@ bio_pagedec(struct bio *bio) struct bvec_iter iter; bio_for_each_segment(bv, bio, iter) { - page = compound_trans_head(bv.bv_page); + page = compound_head(bv.bv_page); atomic_dec(&page->_count); } } diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 4fb7a8f..54af4e9 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -186,12 +186,12 @@ static bool is_invalid_reserved_pfn(unsigned long pfn) if (pfn_valid(pfn)) { bool reserved; struct page *tail = pfn_to_page(pfn); - struct page *head = compound_trans_head(tail); + struct page *head = compound_head(tail); reserved = !!(PageReserved(head)); if (head != tail) { /* * "head" is not a dangling pointer - * (compound_trans_head takes care of that) + * (compound_head takes care of that) * but the hugepage may have been split * from under us (and we may not hold a * reference count on the head page so it can diff --git a/fs/proc/page.c b/fs/proc/page.c index 02174a6..e647c55 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c @@ -121,9 +121,8 @@ u64 stable_page_flags(struct page *page) * just checks PG_head/PG_tail, so we need to check PageLRU/PageAnon * to make sure a given page is a thp, not a non-huge compound page. */ - else if (PageTransCompound(page) && - (PageLRU(compound_trans_head(page)) || - PageAnon(compound_trans_head(page)))) + else if (PageTransCompound(page) && (PageLRU(compound_head(page)) || + PageAnon(compound_head(page)))) u |= 1 << KPF_THP; /* diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index db51201..b826239 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -157,46 +157,6 @@ static inline int hpage_nr_pages(struct page *page) return HPAGE_PMD_NR; return 1; } -/* - * compound_trans_head() should be used instead of compound_head(), - * whenever the "page" passed as parameter could be the tail of a - * transparent hugepage that could be undergoing a - * __split_huge_page_refcount(). The page structure layout often - * changes across releases and it makes extensive use of unions. So if - * the page structure layout will change in a way that - * page->first_page gets clobbered by __split_huge_page_refcount, the - * implementation making use of smp_rmb() will be required. - * - * Currently we define compound_trans_head as compound_head, because - * page->private is in the same union with page->first_page, and - * page->private isn't clobbered. However this also means we're - * currently leaving dirt into the page->private field of anonymous - * pages resulting from a THP split, instead of setting page->private - * to zero like for every other page that has PG_private not set. But - * anonymous pages don't use page->private so this is not a problem. - */ -#if 0 -/* This will be needed if page->private will be clobbered in split_huge_page */ -static inline struct page *compound_trans_head(struct page *page) -{ - if (PageTail(page)) { - struct page *head; - head = page->first_page; - smp_rmb(); - /* - * head may be a dangling pointer. - * __split_huge_page_refcount clears PageTail before - * overwriting first_page, so if PageTail is still - * there it means the head pointer isn't dangling. - */ - if (PageTail(page)) - return head; - } - return page; -} -#else -#define compound_trans_head(page) compound_head(page) -#endif extern int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, pmd_t pmd, pmd_t *pmdp); @@ -226,7 +186,6 @@ static inline int split_huge_page(struct page *page) do { } while (0) #define split_huge_page_pmd_mm(__mm, __address, __pmd) \ do { } while (0) -#define compound_trans_head(page) compound_head(page) static inline int hugepage_madvise(struct vm_area_struct *vma, unsigned long *vm_flags, int advice) { diff --git a/include/linux/mm.h b/include/linux/mm.h index f28f46e..03ab3e5 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -399,8 +399,18 @@ static inline void compound_unlock_irqrestore(struct page *page, static inline struct page *compound_head(struct page *page) { - if (unlikely(PageTail(page))) - return page->first_page; + if (unlikely(PageTail(page))) { + struct page *head = page->first_page; + + /* + * page->first_page may be a dangling pointer to an old + * compound page, so recheck that it is still a tail + * page before returning. + */ + smp_rmb(); + if (likely(PageTail(page))) + return head; + } return page; } diff --git a/mm/ksm.c b/mm/ksm.c index aa4c7c7..68710e8 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -444,7 +444,7 @@ static void break_cow(struct rmap_item *rmap_item) static struct page *page_trans_compound_anon(struct page *page) { if (PageTransCompound(page)) { - struct page *head = compound_trans_head(page); + struct page *head = compound_head(page); /* * head may actually be splitted and freed from under * us but it's ok here. diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 2f2f34a..90002ea 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1651,7 +1651,7 @@ int soft_offline_page(struct page *page, int flags) { int ret; unsigned long pfn = page_to_pfn(page); - struct page *hpage = compound_trans_head(page); + struct page *hpage = compound_head(page); if (PageHWPoison(page)) { pr_info("soft offline: %#lx page already poisoned\n", pfn); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e3758a0..3d1bf88 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -369,9 +369,11 @@ void prep_compound_page(struct page *page, unsigned long order) __SetPageHead(page); for (i = 1; i < nr_pages; i++) { struct page *p = page + i; - __SetPageTail(p); set_page_count(p, 0); p->first_page = page; + /* Make sure p->first_page is always valid for PageTail() */ + smp_wmb(); + __SetPageTail(p); } } diff --git a/mm/swap.c b/mm/swap.c index b31ba67..0092097 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -98,7 +98,7 @@ static void put_compound_page(struct page *page) } /* __split_huge_page_refcount can run under us */ - page_head = compound_trans_head(page); + page_head = compound_head(page); /* * THP can not break up slab pages so avoid taking @@ -253,7 +253,7 @@ bool __get_page_tail(struct page *page) */ unsigned long flags; bool got; - struct page *page_head = compound_trans_head(page); + struct page *page_head = compound_head(page); /* Ref to put_compound_page() comment. */ if (!__compound_tail_refcounted(page_head)) { -- cgit v0.10.2 From 3b7a6418c7494b8bf0bf0537ddee1dedbca10f51 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 3 Mar 2014 15:38:21 -0800 Subject: dma debug: account for cachelines and read-only mappings in overlap tracking While debug_dma_assert_idle() checks if a given *page* is actively undergoing dma the valid granularity of a dma mapping is a *cacheline*. Sander's testing shows that the warning message "DMA-API: exceeded 7 overlapping mappings of pfn..." is falsely triggering. The test is simply mapping multiple cachelines in a given page. Ultimately we want overlap tracking to be valid as it is a real api violation, so we need to track active mappings by cachelines. Update the active dma tracking to use the page-frame-relative cacheline of the mapping as the key, and update debug_dma_assert_idle() to check for all possible mapped cachelines for a given page. However, the need to track active mappings is only relevant when the dma-mapping is writable by the device. In fact it is fairly standard for read-only mappings to have hundreds or thousands of overlapping mappings at once. Limiting the overlap tracking to writable (!DMA_TO_DEVICE) eliminates this class of false-positive overlap reports. Note, the radix gang lookup is sub-optimal. It would be best if it stopped fetching entries once the search passed a page boundary. Nevertheless, this implementation does not perturb the original net_dma failing case. That is to say the extra overhead does not show up in terms of making the failing case pass due to a timing change. References: http://marc.info/?l=linux-netdev&m=139232263419315&w=2 http://marc.info/?l=linux-netdev&m=139217088107122&w=2 Signed-off-by: Dan Williams Reported-by: Sander Eikelenboom Reported-by: Dave Jones Tested-by: Dave Jones Tested-by: Sander Eikelenboom Cc: Konrad Rzeszutek Wilk Cc: Francois Romieu Cc: Eric Dumazet Cc: Wei Liu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 2defd13..98f2d7e 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -424,111 +424,134 @@ void debug_dma_dump_mappings(struct device *dev) EXPORT_SYMBOL(debug_dma_dump_mappings); /* - * For each page mapped (initial page in the case of - * dma_alloc_coherent/dma_map_{single|page}, or each page in a - * scatterlist) insert into this tree using the pfn as the key. At + * For each mapping (initial cacheline in the case of + * dma_alloc_coherent/dma_map_page, initial cacheline in each page of a + * scatterlist, or the cacheline specified in dma_map_single) insert + * into this tree using the cacheline as the key. At * dma_unmap_{single|sg|page} or dma_free_coherent delete the entry. If - * the pfn already exists at insertion time add a tag as a reference + * the entry already exists at insertion time add a tag as a reference * count for the overlapping mappings. For now, the overlap tracking - * just ensures that 'unmaps' balance 'maps' before marking the pfn - * idle, but we should also be flagging overlaps as an API violation. + * just ensures that 'unmaps' balance 'maps' before marking the + * cacheline idle, but we should also be flagging overlaps as an API + * violation. * * Memory usage is mostly constrained by the maximum number of available * dma-debug entries in that we need a free dma_debug_entry before - * inserting into the tree. In the case of dma_map_{single|page} and - * dma_alloc_coherent there is only one dma_debug_entry and one pfn to - * track per event. dma_map_sg(), on the other hand, - * consumes a single dma_debug_entry, but inserts 'nents' entries into - * the tree. + * inserting into the tree. In the case of dma_map_page and + * dma_alloc_coherent there is only one dma_debug_entry and one + * dma_active_cacheline entry to track per event. dma_map_sg(), on the + * other hand, consumes a single dma_debug_entry, but inserts 'nents' + * entries into the tree. * * At any time debug_dma_assert_idle() can be called to trigger a - * warning if the given page is in the active set. + * warning if any cachelines in the given page are in the active set. */ -static RADIX_TREE(dma_active_pfn, GFP_NOWAIT); +static RADIX_TREE(dma_active_cacheline, GFP_NOWAIT); static DEFINE_SPINLOCK(radix_lock); -#define ACTIVE_PFN_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1) +#define ACTIVE_CACHELINE_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1) +#define CACHELINE_PER_PAGE_SHIFT (PAGE_SHIFT - L1_CACHE_SHIFT) +#define CACHELINES_PER_PAGE (1 << CACHELINE_PER_PAGE_SHIFT) -static int active_pfn_read_overlap(unsigned long pfn) +static phys_addr_t to_cacheline_number(struct dma_debug_entry *entry) +{ + return (entry->pfn << CACHELINE_PER_PAGE_SHIFT) + + (entry->offset >> L1_CACHE_SHIFT); +} + +static int active_cacheline_read_overlap(phys_addr_t cln) { int overlap = 0, i; for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--) - if (radix_tree_tag_get(&dma_active_pfn, pfn, i)) + if (radix_tree_tag_get(&dma_active_cacheline, cln, i)) overlap |= 1 << i; return overlap; } -static int active_pfn_set_overlap(unsigned long pfn, int overlap) +static int active_cacheline_set_overlap(phys_addr_t cln, int overlap) { int i; - if (overlap > ACTIVE_PFN_MAX_OVERLAP || overlap < 0) + if (overlap > ACTIVE_CACHELINE_MAX_OVERLAP || overlap < 0) return overlap; for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--) if (overlap & 1 << i) - radix_tree_tag_set(&dma_active_pfn, pfn, i); + radix_tree_tag_set(&dma_active_cacheline, cln, i); else - radix_tree_tag_clear(&dma_active_pfn, pfn, i); + radix_tree_tag_clear(&dma_active_cacheline, cln, i); return overlap; } -static void active_pfn_inc_overlap(unsigned long pfn) +static void active_cacheline_inc_overlap(phys_addr_t cln) { - int overlap = active_pfn_read_overlap(pfn); + int overlap = active_cacheline_read_overlap(cln); - overlap = active_pfn_set_overlap(pfn, ++overlap); + overlap = active_cacheline_set_overlap(cln, ++overlap); /* If we overflowed the overlap counter then we're potentially * leaking dma-mappings. Otherwise, if maps and unmaps are * balanced then this overflow may cause false negatives in - * debug_dma_assert_idle() as the pfn may be marked idle + * debug_dma_assert_idle() as the cacheline may be marked idle * prematurely. */ - WARN_ONCE(overlap > ACTIVE_PFN_MAX_OVERLAP, - "DMA-API: exceeded %d overlapping mappings of pfn %lx\n", - ACTIVE_PFN_MAX_OVERLAP, pfn); + WARN_ONCE(overlap > ACTIVE_CACHELINE_MAX_OVERLAP, + "DMA-API: exceeded %d overlapping mappings of cacheline %pa\n", + ACTIVE_CACHELINE_MAX_OVERLAP, &cln); } -static int active_pfn_dec_overlap(unsigned long pfn) +static int active_cacheline_dec_overlap(phys_addr_t cln) { - int overlap = active_pfn_read_overlap(pfn); + int overlap = active_cacheline_read_overlap(cln); - return active_pfn_set_overlap(pfn, --overlap); + return active_cacheline_set_overlap(cln, --overlap); } -static int active_pfn_insert(struct dma_debug_entry *entry) +static int active_cacheline_insert(struct dma_debug_entry *entry) { + phys_addr_t cln = to_cacheline_number(entry); unsigned long flags; int rc; + /* If the device is not writing memory then we don't have any + * concerns about the cpu consuming stale data. This mitigates + * legitimate usages of overlapping mappings. + */ + if (entry->direction == DMA_TO_DEVICE) + return 0; + spin_lock_irqsave(&radix_lock, flags); - rc = radix_tree_insert(&dma_active_pfn, entry->pfn, entry); + rc = radix_tree_insert(&dma_active_cacheline, cln, entry); if (rc == -EEXIST) - active_pfn_inc_overlap(entry->pfn); + active_cacheline_inc_overlap(cln); spin_unlock_irqrestore(&radix_lock, flags); return rc; } -static void active_pfn_remove(struct dma_debug_entry *entry) +static void active_cacheline_remove(struct dma_debug_entry *entry) { + phys_addr_t cln = to_cacheline_number(entry); unsigned long flags; + /* ...mirror the insert case */ + if (entry->direction == DMA_TO_DEVICE) + return; + spin_lock_irqsave(&radix_lock, flags); /* since we are counting overlaps the final put of the - * entry->pfn will occur when the overlap count is 0. - * active_pfn_dec_overlap() returns -1 in that case + * cacheline will occur when the overlap count is 0. + * active_cacheline_dec_overlap() returns -1 in that case */ - if (active_pfn_dec_overlap(entry->pfn) < 0) - radix_tree_delete(&dma_active_pfn, entry->pfn); + if (active_cacheline_dec_overlap(cln) < 0) + radix_tree_delete(&dma_active_cacheline, cln); spin_unlock_irqrestore(&radix_lock, flags); } /** * debug_dma_assert_idle() - assert that a page is not undergoing dma - * @page: page to lookup in the dma_active_pfn tree + * @page: page to lookup in the dma_active_cacheline tree * * Place a call to this routine in cases where the cpu touching the page * before the dma completes (page is dma_unmapped) will lead to data @@ -536,22 +559,38 @@ static void active_pfn_remove(struct dma_debug_entry *entry) */ void debug_dma_assert_idle(struct page *page) { + static struct dma_debug_entry *ents[CACHELINES_PER_PAGE]; + struct dma_debug_entry *entry = NULL; + void **results = (void **) &ents; + unsigned int nents, i; unsigned long flags; - struct dma_debug_entry *entry; + phys_addr_t cln; if (!page) return; + cln = (phys_addr_t) page_to_pfn(page) << CACHELINE_PER_PAGE_SHIFT; spin_lock_irqsave(&radix_lock, flags); - entry = radix_tree_lookup(&dma_active_pfn, page_to_pfn(page)); + nents = radix_tree_gang_lookup(&dma_active_cacheline, results, cln, + CACHELINES_PER_PAGE); + for (i = 0; i < nents; i++) { + phys_addr_t ent_cln = to_cacheline_number(ents[i]); + + if (ent_cln == cln) { + entry = ents[i]; + break; + } else if (ent_cln >= cln + CACHELINES_PER_PAGE) + break; + } spin_unlock_irqrestore(&radix_lock, flags); if (!entry) return; + cln = to_cacheline_number(entry); err_printk(entry->dev, entry, - "DMA-API: cpu touching an active dma mapped page " - "[pfn=0x%lx]\n", entry->pfn); + "DMA-API: cpu touching an active dma mapped cacheline [cln=%pa]\n", + &cln); } /* @@ -568,9 +607,9 @@ static void add_dma_entry(struct dma_debug_entry *entry) hash_bucket_add(bucket, entry); put_hash_bucket(bucket, &flags); - rc = active_pfn_insert(entry); + rc = active_cacheline_insert(entry); if (rc == -ENOMEM) { - pr_err("DMA-API: pfn tracking ENOMEM, dma-debug disabled\n"); + pr_err("DMA-API: cacheline tracking ENOMEM, dma-debug disabled\n"); global_disable = true; } @@ -631,7 +670,7 @@ static void dma_entry_free(struct dma_debug_entry *entry) { unsigned long flags; - active_pfn_remove(entry); + active_cacheline_remove(entry); /* * add to beginning of the list - this way the entries are -- cgit v0.10.2 From 5f30fc94ca985974fd54de454c7a6070388443db Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 3 Mar 2014 15:38:23 -0800 Subject: lib/radix-tree.c: swapoff tmpfs radix_tree: remember to rcu_read_unlock Running fsx on tmpfs with concurrent memhog-swapoff-swapon, lots of BUG: sleeping function called from invalid context at kernel/fork.c:606 in_atomic(): 0, irqs_disabled(): 0, pid: 1394, name: swapoff 1 lock held by swapoff/1394: #0: (rcu_read_lock){.+.+.+}, at: [] radix_tree_locate_item+0x1f/0x2b6 followed by ================================================ [ BUG: lock held when returning to user space! ] 3.14.0-rc1 #3 Not tainted ------------------------------------------------ swapoff/1394 is leaving the kernel with locks still held! 1 lock held by swapoff/1394: #0: (rcu_read_lock){.+.+.+}, at: [] radix_tree_locate_item+0x1f/0x2b6 after which the system recovered nicely. Whoops, I long ago forgot the rcu_read_unlock() on one unlikely branch. Fixes e504f3fdd63d ("tmpfs radix_tree: locate_item to speed up swapoff") Signed-off-by: Hugh Dickins Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 7811ed3..bd4a8df 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -1253,8 +1253,10 @@ unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item) node = indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); - if (cur_index > max_index) + if (cur_index > max_index) { + rcu_read_unlock(); break; + } cur_index = __locate(node, item, cur_index, &found_index); rcu_read_unlock(); -- cgit v0.10.2 From ce48225fe3b1b0d1fc9fceb96ac3d8a879e45114 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 3 Mar 2014 15:38:24 -0800 Subject: memcg: fix endless loop in __mem_cgroup_iter_next() Commit 0eef615665ed ("memcg: fix css reference leak and endless loop in mem_cgroup_iter") got the interaction with the commit a few before it d8ad30559715 ("mm/memcg: iteration skip memcgs not yet fully initialized") slightly wrong, and we didn't notice at the time. It's elusive, and harder to get than the original, but for a couple of days before rc1, I several times saw a endless loop similar to that supposedly being fixed. This time it was a tighter loop in __mem_cgroup_iter_next(): because we can get here when our root has already been offlined, and the ordering of conditions was such that we then just cycled around forever. Fixes: 0eef615665ed ("memcg: fix css reference leak and endless loop in mem_cgroup_iter"). Signed-off-by: Hugh Dickins Acked-by: Michal Hocko Cc: Johannes Weiner Cc: Greg Thelen Cc: [3.12+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ce7a8cc..9d17310 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1127,8 +1127,8 @@ skip_node: * skipping css reference should be safe. */ if (next_css) { - if ((next_css->flags & CSS_ONLINE) && - (next_css == &root->css || css_tryget(next_css))) + if ((next_css == &root->css) || + ((next_css->flags & CSS_ONLINE) && css_tryget(next_css))) return mem_cgroup_from_css(next_css); prev_css = next_css; -- cgit v0.10.2 From 4fb1a86fb5e4209a7d4426d4e586c58e9edc74ac Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Mon, 3 Mar 2014 15:38:25 -0800 Subject: memcg: reparent charges of children before processing parent Sometimes the cleanup after memcg hierarchy testing gets stuck in mem_cgroup_reparent_charges(), unable to bring non-kmem usage down to 0. There may turn out to be several causes, but a major cause is this: the workitem to offline parent can get run before workitem to offline child; parent's mem_cgroup_reparent_charges() circles around waiting for the child's pages to be reparented to its lrus, but it's holding cgroup_mutex which prevents the child from reaching its mem_cgroup_reparent_charges(). Further testing showed that an ordered workqueue for cgroup_destroy_wq is not always good enough: percpu_ref_kill_and_confirm's call_rcu_sched stage on the way can mess up the order before reaching the workqueue. Instead, when offlining a memcg, call mem_cgroup_reparent_charges() on all its children (and grandchildren, in the correct order) to have their charges reparented first. Fixes: e5fca243abae ("cgroup: use a dedicated workqueue for cgroup destruction") Signed-off-by: Filipe Brandenburger Signed-off-by: Hugh Dickins Reviewed-by: Tejun Heo Acked-by: Michal Hocko Cc: Johannes Weiner Cc: [v3.10+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9d17310..5b6b003 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -6595,6 +6595,7 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css) { struct mem_cgroup *memcg = mem_cgroup_from_css(css); struct mem_cgroup_event *event, *tmp; + struct cgroup_subsys_state *iter; /* * Unregister events and notify userspace. @@ -6611,7 +6612,14 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css) kmem_cgroup_css_offline(memcg); mem_cgroup_invalidate_reclaim_iterators(memcg); - mem_cgroup_reparent_charges(memcg); + + /* + * This requires that offlining is serialized. Right now that is + * guaranteed because css_killed_work_fn() holds the cgroup_mutex. + */ + css_for_each_descendant_post(iter, css) + mem_cgroup_reparent_charges(mem_cgroup_from_css(iter)); + mem_cgroup_destroy_all_caches(memcg); vmpressure_cleanup(&memcg->vmpressure); } -- cgit v0.10.2 From 9050d7eba40b3d79551668f54e68fd6f51945ef3 Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Mon, 3 Mar 2014 15:38:27 -0800 Subject: mm: include VM_MIXEDMAP flag in the VM_SPECIAL list to avoid m(un)locking Daniel Borkmann reported a VM_BUG_ON assertion failing: ------------[ cut here ]------------ kernel BUG at mm/mlock.c:528! invalid opcode: 0000 [#1] SMP Modules linked in: ccm arc4 iwldvm [...] video CPU: 3 PID: 2266 Comm: netsniff-ng Not tainted 3.14.0-rc2+ #8 Hardware name: LENOVO 2429BP3/2429BP3, BIOS G4ET37WW (1.12 ) 05/29/2012 task: ffff8801f87f9820 ti: ffff88002cb44000 task.ti: ffff88002cb44000 RIP: 0010:[] [] munlock_vma_pages_range+0x2e0/0x2f0 Call Trace: do_munmap+0x18f/0x3b0 vm_munmap+0x41/0x60 SyS_munmap+0x22/0x30 system_call_fastpath+0x1a/0x1f RIP munlock_vma_pages_range+0x2e0/0x2f0 ---[ end trace a0088dcf07ae10f2 ]--- because munlock_vma_pages_range() thinks it's unexpectedly in the middle of a THP page. This can be reproduced with default config since 3.11 kernels. A reproducer can be found in the kernel's selftest directory for networking by running ./psock_tpacket. The problem is that an order=2 compound page (allocated by alloc_one_pg_vec_page() is part of the munlocked VM_MIXEDMAP vma (mapped by packet_mmap()) and mistaken for a THP page and assumed to be order=9. The checks for THP in munlock came with commit ff6a6da60b89 ("mm: accelerate munlock() treatment of THP pages"), i.e. since 3.9, but did not trigger a bug. It just makes munlock_vma_pages_range() skip such compound pages until the next 512-pages-aligned page, when it encounters a head page. This is however not a problem for vma's where mlocking has no effect anyway, but it can distort the accounting. Since commit 7225522bb429 ("mm: munlock: batch non-THP page isolation and munlock+putback using pagevec") this can trigger a VM_BUG_ON in PageTransHuge() check. This patch fixes the issue by adding VM_MIXEDMAP flag to VM_SPECIAL, a list of flags that make vma's non-mlockable and non-mergeable. The reasoning is that VM_MIXEDMAP vma's are similar to VM_PFNMAP, which is already on the VM_SPECIAL list, and both are intended for non-LRU pages where mlocking makes no sense anyway. Related Lkml discussion can be found in [2]. [1] tools/testing/selftests/net/psock_tpacket [2] https://lkml.org/lkml/2014/1/10/427 Signed-off-by: Vlastimil Babka Signed-off-by: Daniel Borkmann Reported-by: Daniel Borkmann Tested-by: Daniel Borkmann Cc: Thomas Hellstrom Cc: John David Anglin Cc: HATAYAMA Daisuke Cc: Konstantin Khlebnikov Cc: Carsten Otte Cc: Jared Hulbert Tested-by: Hannes Frederic Sowa Cc: Kirill A. Shutemov Acked-by: Rik van Riel Cc: Andrea Arcangeli Cc: [3.11.x+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/mm.h b/include/linux/mm.h index 03ab3e5..a1fe251 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -175,7 +175,7 @@ extern unsigned int kobjsize(const void *objp); * Special vmas that are non-mergable, non-mlock()able. * Note: mm/huge_memory.c VM_NO_THP depends on this definition. */ -#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP) +#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP | VM_MIXEDMAP) /* * mapping from the currently active vm_flags protection bits (the diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 4df39b1..1546655 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1961,7 +1961,7 @@ out: return ret; } -#define VM_NO_THP (VM_SPECIAL|VM_MIXEDMAP|VM_HUGETLB|VM_SHARED|VM_MAYSHARE) +#define VM_NO_THP (VM_SPECIAL | VM_HUGETLB | VM_SHARED | VM_MAYSHARE) int hugepage_madvise(struct vm_area_struct *vma, unsigned long *vm_flags, int advice) -- cgit v0.10.2 From 5ec384d45b42fc9274df835be435e964f885b6ed Mon Sep 17 00:00:00 2001 From: "Daniel M. Weeks" Date: Mon, 3 Mar 2014 15:38:28 -0800 Subject: scripts/gen_initramfs_list.sh: fix flags for initramfs LZ4 compression LZ4 as implemented in the kernel differs from the default method now used by the reference implementation of LZ4. Until the in-kernel method is updated to support the new default, passing the legacy flag (-l) to the compressor is necessary. Without this flag the kernel-generated, LZ4-compressed initramfs is junk. Kyungsik said: : It seems that lz4 supports legacy format with the same option as lz4c : does. Just looking at the first few bytes of lz4 compressed image, we can : see whether it is new format or not. : : It shows new format magic number without this patch. New format magic : number is 0x184d2204. : : $ hexdump -C ./initramfs_data.cpio.lz4 |more : 00000000 04 22 4d 18 64 70 b9 69 (Little Endian) : ... : : Currently kernel supports legacy format only. Signed-off-by: Daniel M. Weeks Cc: Michal Marek Acked-by: Kyungsik Lee Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index ef47409..17fa901 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -257,7 +257,7 @@ case "$arg" in && compr="lzop -9 -f" echo "$output_file" | grep -q "\.lz4$" \ && [ -x "`which lz4 2> /dev/null`" ] \ - && compr="lz4 -9 -f" + && compr="lz4 -l -9 -f" echo "$output_file" | grep -q "\.cpio$" && compr="cat" shift ;; -- cgit v0.10.2 From 0f55159d091cb1e555ee52abc1b2455f301b99a8 Mon Sep 17 00:00:00 2001 From: Andy Honig Date: Mon, 3 Mar 2014 15:38:30 -0800 Subject: kallsyms: fix absolute addresses for kASLR Currently symbols that are absolute addresses are incorrectly displayed in /proc/kallsyms if the kernel is loaded with kASLR. The problem was that the scripts/kallsyms.c file which generates the array of symbol names and addresses uses an relocatable value for all symbols, even absolute symbols. This patch fixes that. Several kallsyms output in different boot states for comparison: $ egrep '_(stext|_per_cpu_(start|end))' /root/kallsyms.nokaslr 0000000000000000 D __per_cpu_start 0000000000014280 D __per_cpu_end ffffffff810001c8 T _stext $ egrep '_(stext|_per_cpu_(start|end))' /root/kallsyms.kaslr1 000000001f200000 D __per_cpu_start 000000001f214280 D __per_cpu_end ffffffffa02001c8 T _stext $ egrep '_(stext|_per_cpu_(start|end))' /root/kallsyms.kaslr2 000000000d400000 D __per_cpu_start 000000000d414280 D __per_cpu_end ffffffff8e4001c8 T _stext $ egrep '_(stext|_per_cpu_(start|end))' /root/kallsyms.kaslr-fixed 0000000000000000 D __per_cpu_start 0000000000014280 D __per_cpu_end ffffffffadc001c8 T _stext Signed-off-by: Andy Honig Signed-off-by: Kees Cook Cc: Michal Marek Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 10085de..276e84b 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -330,8 +330,7 @@ static void write_src(void) printf("\tPTR\t_text + %#llx\n", table[i].addr - _text); else - printf("\tPTR\t_text - %#llx\n", - _text - table[i].addr); + printf("\tPTR\t%#llx\n", table[i].addr); } else { printf("\tPTR\t%#llx\n", table[i].addr); } -- cgit v0.10.2 From 40d2d968e99aa267ac1e5d70deb97faa41a7dfc8 Mon Sep 17 00:00:00 2001 From: Vikas Sajjan Date: Mon, 3 Mar 2014 15:38:31 -0800 Subject: drivers/rtc/rtc-s3c.c: fix incorrect way of save/restore of S3C2410_TICNT for TYPE_S3C64XX On exynos5250, exynos5420 and exynos5260 it was observed that, after 1 cycle of S2R, the rtc-tick occurs at a very fast rate as compared to the rtc-tick occuring before S2R. This patch fixes the above issue by correcting the wrong way of save/restore of S3C2410_TICNT for TYPE_S3C64XX. Signed-off-by: Vikas Sajjan Cc: Grant Likely Cc: Rob Herring Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 7afd373..c4cde9c 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -580,10 +580,12 @@ static int s3c_rtc_suspend(struct device *dev) clk_enable(rtc_clk); /* save TICNT for anyone using periodic interrupts */ - ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); if (s3c_rtc_cpu_type == TYPE_S3C64XX) { ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); ticnt_en_save &= S3C64XX_RTCCON_TICEN; + ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT); + } else { + ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); } s3c_rtc_enable(pdev, 0); @@ -605,10 +607,15 @@ static int s3c_rtc_resume(struct device *dev) clk_enable(rtc_clk); s3c_rtc_enable(pdev, 1); - writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); - if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { - tmp = readw(s3c_rtc_base + S3C2410_RTCCON); - writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); + if (s3c_rtc_cpu_type == TYPE_S3C64XX) { + writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT); + if (ticnt_en_save) { + tmp = readw(s3c_rtc_base + S3C2410_RTCCON); + writew(tmp | ticnt_en_save, + s3c_rtc_base + S3C2410_RTCCON); + } + } else { + writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); } if (device_may_wakeup(dev) && wake_en) { -- cgit v0.10.2 From 15c34a760630ca2c803848fba90ca0646a9907dd Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 3 Mar 2014 15:38:32 -0800 Subject: ocfs2: fix quota file corruption Global quota files are accessed from different nodes. Thus we cannot cache offset of quota structure in the quota file after we drop our node reference count to it because after that moment quota structure may be freed and reallocated elsewhere by a different node resulting in corruption of quota file. Fix the problem by clearing dq_off when we are releasing dquot structure. We also remove the DB_READ_B handling because it is useless - DQ_ACTIVE_B is set iff DQ_READ_B is set. Signed-off-by: Jan Kara Cc: Goldwyn Rodrigues Cc: Joel Becker Reviewed-by: Mark Fasheh Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index aaa5061..d7b5108 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -717,6 +717,12 @@ static int ocfs2_release_dquot(struct dquot *dquot) */ if (status < 0) mlog_errno(status); + /* + * Clear dq_off so that we search for the structure in quota file next + * time we acquire it. The structure might be deleted and reallocated + * elsewhere by another node while our dquot structure is on freelist. + */ + dquot->dq_off = 0; clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); out_trans: ocfs2_commit_trans(osb, handle); @@ -756,16 +762,17 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) status = ocfs2_lock_global_qf(info, 1); if (status < 0) goto out; - if (!test_bit(DQ_READ_B, &dquot->dq_flags)) { - status = ocfs2_qinfo_lock(info, 0); - if (status < 0) - goto out_dq; - status = qtree_read_dquot(&info->dqi_gi, dquot); - ocfs2_qinfo_unlock(info, 0); - if (status < 0) - goto out_dq; - } - set_bit(DQ_READ_B, &dquot->dq_flags); + status = ocfs2_qinfo_lock(info, 0); + if (status < 0) + goto out_dq; + /* + * We always want to read dquot structure from disk because we don't + * know what happened with it while it was on freelist. + */ + status = qtree_read_dquot(&info->dqi_gi, dquot); + ocfs2_qinfo_unlock(info, 0); + if (status < 0) + goto out_dq; OCFS2_DQUOT(dquot)->dq_use_count++; OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 2e4344b..2001862 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -1303,10 +1303,6 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot) ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh); out: - /* Clear the read bit so that next time someone uses this - * dquot he reads fresh info from disk and allocates local - * dquot structure */ - clear_bit(DQ_READ_B, &dquot->dq_flags); return status; } -- cgit v0.10.2 From a5f6ea29f9a918403629f8369ae55fac6b09cb53 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 3 Mar 2014 15:38:33 -0800 Subject: sh: prefix sh-specific "CCR" and "CCR2" by "SH_" Commit bcf24e1daa94 ("mmc: omap_hsmmc: use the generic config for omap2plus devices"), enabled the build for other platforms for compile testing. sh-allmodconfig now fails with: include/linux/omap-dma.h:171:8: error: expected identifier before numeric constant make[4]: *** [drivers/mmc/host/omap_hsmmc.o] Error 1 This happens because SuperH #defines "CCR", which is one of the enum values in include/linux/omap-dma.h. There's a similar issue with "CCR2" on sh2a. As "CCR" and "CCR2" are too generic names for global #defines, prefix them with "SH_" to fix this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/sh/include/cpu-sh2/cpu/cache.h b/arch/sh/include/cpu-sh2/cpu/cache.h index 673515b..aa1b2b9 100644 --- a/arch/sh/include/cpu-sh2/cpu/cache.h +++ b/arch/sh/include/cpu-sh2/cpu/cache.h @@ -18,7 +18,7 @@ #define SH_CACHE_ASSOC 8 #if defined(CONFIG_CPU_SUBTYPE_SH7619) -#define CCR 0xffffffec +#define SH_CCR 0xffffffec #define CCR_CACHE_CE 0x01 /* Cache enable */ #define CCR_CACHE_WT 0x02 /* CCR[bit1=1,bit2=1] */ diff --git a/arch/sh/include/cpu-sh2a/cpu/cache.h b/arch/sh/include/cpu-sh2a/cpu/cache.h index defb0ba..b27ce92 100644 --- a/arch/sh/include/cpu-sh2a/cpu/cache.h +++ b/arch/sh/include/cpu-sh2a/cpu/cache.h @@ -17,8 +17,8 @@ #define SH_CACHE_COMBINED 4 #define SH_CACHE_ASSOC 8 -#define CCR 0xfffc1000 /* CCR1 */ -#define CCR2 0xfffc1004 +#define SH_CCR 0xfffc1000 /* CCR1 */ +#define SH_CCR2 0xfffc1004 /* * Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not diff --git a/arch/sh/include/cpu-sh3/cpu/cache.h b/arch/sh/include/cpu-sh3/cpu/cache.h index bee2d81..29700fd 100644 --- a/arch/sh/include/cpu-sh3/cpu/cache.h +++ b/arch/sh/include/cpu-sh3/cpu/cache.h @@ -17,7 +17,7 @@ #define SH_CACHE_COMBINED 4 #define SH_CACHE_ASSOC 8 -#define CCR 0xffffffec /* Address of Cache Control Register */ +#define SH_CCR 0xffffffec /* Address of Cache Control Register */ #define CCR_CACHE_CE 0x01 /* Cache Enable */ #define CCR_CACHE_WT 0x02 /* Write-Through (for P0,U0,P3) (else writeback) */ diff --git a/arch/sh/include/cpu-sh4/cpu/cache.h b/arch/sh/include/cpu-sh4/cpu/cache.h index 7bfb9e8..92c4cd1 100644 --- a/arch/sh/include/cpu-sh4/cpu/cache.h +++ b/arch/sh/include/cpu-sh4/cpu/cache.h @@ -17,7 +17,7 @@ #define SH_CACHE_COMBINED 4 #define SH_CACHE_ASSOC 8 -#define CCR 0xff00001c /* Address of Cache Control Register */ +#define SH_CCR 0xff00001c /* Address of Cache Control Register */ #define CCR_CACHE_OCE 0x0001 /* Operand Cache Enable */ #define CCR_CACHE_WT 0x0002 /* Write-Through (for P0,U0,P3) (else writeback)*/ #define CCR_CACHE_CB 0x0004 /* Copy-Back (for P1) (else writethrough) */ diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index ecf83cd..0d7360d 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -112,7 +112,7 @@ static void cache_init(void) unsigned long ccr, flags; jump_to_uncached(); - ccr = __raw_readl(CCR); + ccr = __raw_readl(SH_CCR); /* * At this point we don't know whether the cache is enabled or not - a @@ -189,7 +189,7 @@ static void cache_init(void) l2_cache_init(); - __raw_writel(flags, CCR); + __raw_writel(flags, SH_CCR); back_to_cached(); } #else diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c index 1157251..777e50f 100644 --- a/arch/sh/mm/cache-debugfs.c +++ b/arch/sh/mm/cache-debugfs.c @@ -36,7 +36,7 @@ static int cache_seq_show(struct seq_file *file, void *iter) */ jump_to_uncached(); - ccr = __raw_readl(CCR); + ccr = __raw_readl(SH_CCR); if ((ccr & CCR_CACHE_ENABLE) == 0) { back_to_cached(); diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c index defcf71..a74259f 100644 --- a/arch/sh/mm/cache-sh2.c +++ b/arch/sh/mm/cache-sh2.c @@ -63,9 +63,9 @@ static void sh2__flush_invalidate_region(void *start, int size) local_irq_save(flags); jump_to_uncached(); - ccr = __raw_readl(CCR); + ccr = __raw_readl(SH_CCR); ccr |= CCR_CACHE_INVALIDATE; - __raw_writel(ccr, CCR); + __raw_writel(ccr, SH_CCR); back_to_cached(); local_irq_restore(flags); diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c index 949e2d3..ee87d08 100644 --- a/arch/sh/mm/cache-sh2a.c +++ b/arch/sh/mm/cache-sh2a.c @@ -134,7 +134,8 @@ static void sh2a__flush_invalidate_region(void *start, int size) /* If there are too many pages then just blow the cache */ if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) { - __raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR); + __raw_writel(__raw_readl(SH_CCR) | CCR_OCACHE_INVALIDATE, + SH_CCR); } else { for (v = begin; v < end; v += L1_CACHE_BYTES) sh2a_invalidate_line(CACHE_OC_ADDRESS_ARRAY, v); @@ -167,7 +168,8 @@ static void sh2a_flush_icache_range(void *args) /* I-Cache invalidate */ /* If there are too many pages then just blow the cache */ if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) { - __raw_writel(__raw_readl(CCR) | CCR_ICACHE_INVALIDATE, CCR); + __raw_writel(__raw_readl(SH_CCR) | CCR_ICACHE_INVALIDATE, + SH_CCR); } else { for (v = start; v < end; v += L1_CACHE_BYTES) sh2a_invalidate_line(CACHE_IC_ADDRESS_ARRAY, v); diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index 0e52928..51d8f7f 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -133,9 +133,9 @@ static void flush_icache_all(void) jump_to_uncached(); /* Flush I-cache */ - ccr = __raw_readl(CCR); + ccr = __raw_readl(SH_CCR); ccr |= CCR_CACHE_ICI; - __raw_writel(ccr, CCR); + __raw_writel(ccr, SH_CCR); /* * back_to_cached() will take care of the barrier for us, don't add diff --git a/arch/sh/mm/cache-shx3.c b/arch/sh/mm/cache-shx3.c index c0adbee..24c58b7 100644 --- a/arch/sh/mm/cache-shx3.c +++ b/arch/sh/mm/cache-shx3.c @@ -19,7 +19,7 @@ void __init shx3_cache_init(void) { unsigned int ccr; - ccr = __raw_readl(CCR); + ccr = __raw_readl(SH_CCR); /* * If we've got cache aliases, resolve them in hardware. @@ -40,5 +40,5 @@ void __init shx3_cache_init(void) ccr |= CCR_CACHE_IBE; #endif - writel_uncached(ccr, CCR); + writel_uncached(ccr, SH_CCR); } diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index 616966a..097c2cd 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -285,8 +285,8 @@ void __init cpu_cache_init(void) { unsigned int cache_disabled = 0; -#ifdef CCR - cache_disabled = !(__raw_readl(CCR) & CCR_CACHE_ENABLE); +#ifdef SH_CCR + cache_disabled = !(__raw_readl(SH_CCR) & CCR_CACHE_ENABLE); #endif compute_alias(&boot_cpu_data.icache); -- cgit v0.10.2 From db5d711e2db776f18219b033e5dc4fb7e4264dd7 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Mon, 3 Mar 2014 15:38:34 -0800 Subject: zram: avoid null access when fail to alloc meta zram_meta_alloc could fail so caller should check it. Otherwise, your system will hang. Signed-off-by: Minchan Kim Acked-by: Jerome Marchand Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 011e55d..51c557c 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -612,6 +612,8 @@ static ssize_t disksize_store(struct device *dev, disksize = PAGE_ALIGN(disksize); meta = zram_meta_alloc(disksize); + if (!meta) + return -ENOMEM; down_write(&zram->init_lock); if (zram->init_done) { up_write(&zram->init_lock); -- cgit v0.10.2 From bd2c00353286d63542a8a0896a8c747f7c880edd Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Mon, 3 Mar 2014 15:38:35 -0800 Subject: hfsplus: fix remount issue Current implementation of HFS+ driver has small issue with remount option. Namely, for example, you are unable to remount from RO mode into RW mode by means of command "mount -o remount,rw /dev/loop0 /mnt/hfsplus". Trying to execute sequence of commands results in an error message: mount /dev/loop0 /mnt/hfsplus mount -o remount,ro /dev/loop0 /mnt/hfsplus mount -o remount,rw /dev/loop0 /mnt/hfsplus mount: you must specify the filesystem type mount -t hfsplus -o remount,rw /dev/loop0 /mnt/hfsplus mount: /mnt/hfsplus not mounted or bad option The reason of such issue is failure of mount syscall: mount("/dev/loop0", "/mnt/hfsplus", 0x2282a60, MS_MGC_VAL|MS_REMOUNT, NULL) = -1 EINVAL (Invalid argument) Namely, hfsplus_parse_options_remount() method receives empty "input" argument and return false in such case. As a result, hfsplus_remount() returns -EINVAL error code. This patch fixes the issue by means of return true for the case of empty "input" argument in hfsplus_parse_options_remount() method. Signed-off-by: Vyacheslav Dubeyko Cc: Al Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index 968eab5..68537e8 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c @@ -75,7 +75,7 @@ int hfsplus_parse_options_remount(char *input, int *force) int token; if (!input) - return 0; + return 1; while ((p = strsep(&input, ",")) != NULL) { if (!*p) -- cgit v0.10.2 From 04379dffdd4da820d51a1566ad2e86f3b1ad97ed Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Mon, 3 Mar 2014 15:38:36 -0800 Subject: rapidio/tsi721: fix tasklet termination in dma channel release This patch is a modification of the patch originally proposed by Xiaotian Feng : https://lkml.org/lkml/2012/11/5/413 This new version disables DMA channel interrupts and ensures that the tasklet wil not be scheduled again before calling tasklet_kill(). Unfortunately the updated patch was not released at that time due to planned rework of Tsi721 mport driver to use threaded interrupts (which has yet to happen). Recently the issue was reported again: https://lkml.org/lkml/2014/2/19/762. Description from the original Xiaotian's patch: "Some drivers use tasklet_disable in device remove/release process, tasklet_disable will inc tasklet->count and return. If the tasklet is not handled yet under some softirq pressure, the tasklet will be placed on the tasklet_vec, never have a chance to be excuted. This might lead to a heavy loaded ksoftirqd, wakeup with pending_softirq, but tasklet is disabled. tasklet_kill should be used in this case." This patch is applicable to kernel versions starting from v3.5. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Xiaotian Feng Reviewed-by: Thomas Gleixner Cc: Mike Galbraith Cc: [3.5+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index b4b0d83..7061ac0 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h @@ -678,6 +678,7 @@ struct tsi721_bdma_chan { struct list_head free_list; dma_cookie_t completed_cookie; struct tasklet_struct tasklet; + bool active; }; #endif /* CONFIG_RAPIDIO_DMA_ENGINE */ diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c index 502663f..91245f5 100644 --- a/drivers/rapidio/devices/tsi721_dma.c +++ b/drivers/rapidio/devices/tsi721_dma.c @@ -206,8 +206,8 @@ void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan) { /* Disable BDMA channel interrupts */ iowrite32(0, bdma_chan->regs + TSI721_DMAC_INTE); - - tasklet_schedule(&bdma_chan->tasklet); + if (bdma_chan->active) + tasklet_schedule(&bdma_chan->tasklet); } #ifdef CONFIG_PCI_MSI @@ -562,7 +562,7 @@ static int tsi721_alloc_chan_resources(struct dma_chan *dchan) } #endif /* CONFIG_PCI_MSI */ - tasklet_enable(&bdma_chan->tasklet); + bdma_chan->active = true; tsi721_bdma_interrupt_enable(bdma_chan, 1); return bdma_chan->bd_num - 1; @@ -576,9 +576,7 @@ err_out: static void tsi721_free_chan_resources(struct dma_chan *dchan) { struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); -#ifdef CONFIG_PCI_MSI struct tsi721_device *priv = to_tsi721(dchan->device); -#endif LIST_HEAD(list); dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); @@ -589,14 +587,25 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan) BUG_ON(!list_empty(&bdma_chan->active_list)); BUG_ON(!list_empty(&bdma_chan->queue)); - tasklet_disable(&bdma_chan->tasklet); + tsi721_bdma_interrupt_enable(bdma_chan, 0); + bdma_chan->active = false; + +#ifdef CONFIG_PCI_MSI + if (priv->flags & TSI721_USING_MSIX) { + synchronize_irq(priv->msix[TSI721_VECT_DMA0_DONE + + bdma_chan->id].vector); + synchronize_irq(priv->msix[TSI721_VECT_DMA0_INT + + bdma_chan->id].vector); + } else +#endif + synchronize_irq(priv->pdev->irq); + + tasklet_kill(&bdma_chan->tasklet); spin_lock_bh(&bdma_chan->lock); list_splice_init(&bdma_chan->free_list, &list); spin_unlock_bh(&bdma_chan->lock); - tsi721_bdma_interrupt_enable(bdma_chan, 0); - #ifdef CONFIG_PCI_MSI if (priv->flags & TSI721_USING_MSIX) { free_irq(priv->msix[TSI721_VECT_DMA0_DONE + @@ -790,6 +799,7 @@ int tsi721_register_dma(struct tsi721_device *priv) bdma_chan->dchan.cookie = 1; bdma_chan->dchan.chan_id = i; bdma_chan->id = i; + bdma_chan->active = false; spin_lock_init(&bdma_chan->lock); @@ -799,7 +809,6 @@ int tsi721_register_dma(struct tsi721_device *priv) tasklet_init(&bdma_chan->tasklet, tsi721_dma_tasklet, (unsigned long)bdma_chan); - tasklet_disable(&bdma_chan->tasklet); list_add_tail(&bdma_chan->dchan.device_node, &mport->dma.channels); } -- cgit v0.10.2 From b75f005076234311301c6241125cb29d5f124eff Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 3 Mar 2014 15:38:37 -0800 Subject: MAINTAINERS: use tab for separator Convert whitespace to single tab for separators. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 7abe81e..b392889 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1612,11 +1612,11 @@ S: Maintained F: drivers/net/wireless/atmel* ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER -M: Bradley Grove -L: linux-scsi@vger.kernel.org -W: http://www.attotech.com -S: Supported -F: drivers/scsi/esas2r +M: Bradley Grove +L: linux-scsi@vger.kernel.org +W: http://www.attotech.com +S: Supported +F: drivers/scsi/esas2r AUDIT SUBSYSTEM M: Eric Paris @@ -2179,9 +2179,9 @@ S: Supported F: drivers/net/ethernet/cisco/enic/ CISCO VIC LOW LATENCY NIC DRIVER -M: Upinder Malhi -S: Supported -F: drivers/infiniband/hw/usnic +M: Upinder Malhi +S: Supported +F: drivers/infiniband/hw/usnic CIRRUS LOGIC EP93XX ETHERNET DRIVER M: Hartley Sweeten @@ -2378,13 +2378,13 @@ F: drivers/cpufreq/arm_big_little.c F: drivers/cpufreq/arm_big_little_dt.c CPUIDLE DRIVER - ARM BIG LITTLE -M: Lorenzo Pieralisi -M: Daniel Lezcano -L: linux-pm@vger.kernel.org -L: linux-arm-kernel@lists.infradead.org -T: git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git -S: Maintained -F: drivers/cpuidle/cpuidle-big_little.c +M: Lorenzo Pieralisi +M: Daniel Lezcano +L: linux-pm@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org +T: git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git +S: Maintained +F: drivers/cpuidle/cpuidle-big_little.c CPUIDLE DRIVERS M: Rafael J. Wysocki @@ -2458,9 +2458,9 @@ S: Maintained F: sound/pci/cs5535audio/ CW1200 WLAN driver -M: Solomon Peachy -S: Maintained -F: drivers/net/wireless/cw1200/ +M: Solomon Peachy +S: Maintained +F: drivers/net/wireless/cw1200/ CX18 VIDEO4LINUX DRIVER M: Andy Walls @@ -5473,11 +5473,11 @@ S: Maintained F: drivers/media/tuners/m88ts2022* MA901 MASTERKIT USB FM RADIO DRIVER -M: Alexey Klimov -L: linux-media@vger.kernel.org -T: git git://linuxtv.org/media_tree.git -S: Maintained -F: drivers/media/radio/radio-ma901.c +M: Alexey Klimov +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/radio/radio-ma901.c MAC80211 M: Johannes Berg @@ -5638,7 +5638,7 @@ F: drivers/scsi/megaraid/ MELLANOX ETHERNET DRIVER (mlx4_en) M: Amir Vadai -L: netdev@vger.kernel.org +L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com Q: http://patchwork.ozlabs.org/project/netdev/list/ @@ -5679,7 +5679,7 @@ F: include/linux/mtd/ F: include/uapi/mtd/ MEN A21 WATCHDOG DRIVER -M: Johannes Thumshirn +M: Johannes Thumshirn L: linux-watchdog@vger.kernel.org S: Supported F: drivers/watchdog/mena21_wdt.c @@ -5741,14 +5741,14 @@ F: drivers/net/ethernet/mellanox/mlx5/core/ F: include/linux/mlx5/ Mellanox MLX5 IB driver -M: Eli Cohen -L: linux-rdma@vger.kernel.org -W: http://www.mellanox.com -Q: http://patchwork.kernel.org/project/linux-rdma/list/ -T: git://openfabrics.org/~eli/connect-ib.git -S: Supported -F: include/linux/mlx5/ -F: drivers/infiniband/hw/mlx5/ +M: Eli Cohen +L: linux-rdma@vger.kernel.org +W: http://www.mellanox.com +Q: http://patchwork.kernel.org/project/linux-rdma/list/ +T: git://openfabrics.org/~eli/connect-ib.git +S: Supported +F: include/linux/mlx5/ +F: drivers/infiniband/hw/mlx5/ MODULE SUPPORT M: Rusty Russell @@ -8702,17 +8702,17 @@ S: Maintained F: drivers/media/radio/radio-raremono.c THERMAL -M: Zhang Rui -M: Eduardo Valentin -L: linux-pm@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git -Q: https://patchwork.kernel.org/project/linux-pm/list/ -S: Supported -F: drivers/thermal/ -F: include/linux/thermal.h -F: include/linux/cpu_cooling.h -F: Documentation/devicetree/bindings/thermal/ +M: Zhang Rui +M: Eduardo Valentin +L: linux-pm@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git +Q: https://patchwork.kernel.org/project/linux-pm/list/ +S: Supported +F: drivers/thermal/ +F: include/linux/thermal.h +F: include/linux/cpu_cooling.h +F: Documentation/devicetree/bindings/thermal/ THINGM BLINK(1) USB RGB LED DRIVER M: Vivien Didelot -- cgit v0.10.2 From cea8321cd7f730f96a419cc6a8e9f763df69a7f2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 3 Mar 2014 15:38:38 -0800 Subject: MAINTAINERS: add and correct types of some "T:" entries Tree location entries should start with the appropriate type. Add git to some, hg to another. Neaten tree type description. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index b392889..99d5b4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -73,7 +73,8 @@ Descriptions of section entries: L: Mailing list that is relevant to this area W: Web-page with status/info Q: Patchwork web based patch tracking system site - T: SCM tree type and location. Type is one of: git, hg, quilt, stgit, topgit. + T: SCM tree type and location. + Type is one of: git, hg, quilt, stgit, topgit S: Status, one of the following: Supported: Someone is actually paid to look after this. Maintained: Someone actually looks after it. @@ -2159,7 +2160,7 @@ F: Documentation/zh_CN/ CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER M: Peter Chen -T: git://github.com/hzpeterchen/linux-usb.git +T: git git://github.com/hzpeterchen/linux-usb.git L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/chipidea/ @@ -2382,7 +2383,7 @@ M: Lorenzo Pieralisi M: Daniel Lezcano L: linux-pm@vger.kernel.org L: linux-arm-kernel@lists.infradead.org -T: git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git S: Maintained F: drivers/cpuidle/cpuidle-big_little.c @@ -2391,7 +2392,7 @@ M: Rafael J. Wysocki M: Daniel Lezcano L: linux-pm@vger.kernel.org S: Maintained -T: git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git F: drivers/cpuidle/* F: include/linux/cpuidle.h @@ -4916,7 +4917,7 @@ F: drivers/staging/ktap/ KCONFIG M: "Yann E. MORIN" L: linux-kbuild@vger.kernel.org -T: git://gitorious.org/linux-kconfig/linux-kconfig +T: git git://gitorious.org/linux-kconfig/linux-kconfig S: Maintained F: Documentation/kbuild/kconfig-language.txt F: scripts/kconfig/ @@ -5735,7 +5736,7 @@ L: linux-rdma@vger.kernel.org W: http://www.mellanox.com Q: http://patchwork.ozlabs.org/project/netdev/list/ Q: http://patchwork.kernel.org/project/linux-rdma/list/ -T: git://openfabrics.org/~eli/connect-ib.git +T: git git://openfabrics.org/~eli/connect-ib.git S: Supported F: drivers/net/ethernet/mellanox/mlx5/core/ F: include/linux/mlx5/ @@ -5745,7 +5746,7 @@ M: Eli Cohen L: linux-rdma@vger.kernel.org W: http://www.mellanox.com Q: http://patchwork.kernel.org/project/linux-rdma/list/ -T: git://openfabrics.org/~eli/connect-ib.git +T: git git://openfabrics.org/~eli/connect-ib.git S: Supported F: include/linux/mlx5/ F: drivers/infiniband/hw/mlx5/ @@ -9814,7 +9815,7 @@ ZR36067 VIDEO FOR LINUX DRIVER L: mjpeg-users@lists.sourceforge.net L: linux-media@vger.kernel.org W: http://mjpeg.sourceforge.net/driver-zoran/ -T: Mercurial http://linuxtv.org/hg/v4l-dvb +T: hg http://linuxtv.org/hg/v4l-dvb S: Odd Fixes F: drivers/media/pci/zoran/ -- cgit v0.10.2 From 1ae71d03194ea7424cbd14e449581f67c463d20d Mon Sep 17 00:00:00 2001 From: Liu Ping Fan Date: Mon, 3 Mar 2014 15:38:39 -0800 Subject: mm: numa: bugfix for LAST_CPUPID_NOT_IN_PAGE_FLAGS When doing some numa tests on powerpc, I triggered an oops bug. I find it is caused by using page->_last_cpupid. It should be initialized as "-1 & LAST_CPUPID_MASK", but not "-1". Otherwise, in task_numa_fault(), we will miss the checking (last_cpupid == (-1 & LAST_CPUPID_MASK)). And finally cause an oops bug in task_numa_group(), since the online cpu is less than possible cpu. This happen with CONFIG_SPARSE_VMEMMAP disabled Call trace: SMP NR_CPUS=64 NUMA PowerNV Modules linked in: CPU: 24 PID: 804 Comm: systemd-udevd Not tainted3.13.0-rc1+ #32 task: c000001e2746aa80 ti: c000001e32c50000 task.ti:c000001e32c50000 REGS: c000001e32c53510 TRAP: 0300 Not tainted(3.13.0-rc1+) MSR: 9000000000009032 CR:28024424 XER: 20000000 CFAR: c000000000009324 DAR: 7265717569726857 DSISR:40000000 SOFTE: 1 NIP .task_numa_fault+0x1470/0x2370 LR .task_numa_fault+0x1468/0x2370 Call Trace: .task_numa_fault+0x1468/0x2370 (unreliable) .do_numa_page+0x480/0x4a0 .handle_mm_fault+0x4ec/0xc90 .do_page_fault+0x3a8/0x890 handle_page_fault+0x10/0x30 Instruction dump: 3c82fefb 3884b138 48d9cff1 60000000 48000574 3c62fefb3863af78 3c82fefb 3884b138 48d9cfd5 60000000 e93f0100 <812902e4> 7d2907b45529063e 7d2a07b4 ---[ end trace 15f2510da5ae07cf ]--- Signed-off-by: Liu Ping Fan Signed-off-by: Aneesh Kumar K.V Acked-by: Peter Zijlstra Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/mm.h b/include/linux/mm.h index a1fe251..c1b7414 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -767,7 +767,7 @@ static inline bool __cpupid_match_pid(pid_t task_pid, int cpupid) #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS static inline int page_cpupid_xchg_last(struct page *page, int cpupid) { - return xchg(&page->_last_cpupid, cpupid); + return xchg(&page->_last_cpupid, cpupid & LAST_CPUPID_MASK); } static inline int page_cpupid_last(struct page *page) @@ -776,7 +776,7 @@ static inline int page_cpupid_last(struct page *page) } static inline void page_cpupid_reset_last(struct page *page) { - page->_last_cpupid = -1; + page->_last_cpupid = -1 & LAST_CPUPID_MASK; } #else static inline int page_cpupid_last(struct page *page) -- cgit v0.10.2 From 27329369c9ecf37771b2a65202cbf5578cff3331 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Mon, 3 Mar 2014 15:38:41 -0800 Subject: mm: page_alloc: exempt GFP_THISNODE allocations from zone fairness Jan Stancek reports manual page migration encountering allocation failures after some pages when there is still plenty of memory free, and bisected the problem down to commit 81c0a2bb515f ("mm: page_alloc: fair zone allocator policy"). The problem is that GFP_THISNODE obeys the zone fairness allocation batches on one hand, but doesn't reset them and wake kswapd on the other hand. After a few of those allocations, the batches are exhausted and the allocations fail. Fixing this means either having GFP_THISNODE wake up kswapd, or GFP_THISNODE not participating in zone fairness at all. The latter seems safer as an acute bugfix, we can clean up later. Reported-by: Jan Stancek Signed-off-by: Johannes Weiner Acked-by: Rik van Riel Acked-by: Mel Gorman Cc: [3.12+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3d1bf88..3bac76a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1238,6 +1238,15 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp) } local_irq_restore(flags); } +static bool gfp_thisnode_allocation(gfp_t gfp_mask) +{ + return (gfp_mask & GFP_THISNODE) == GFP_THISNODE; +} +#else +static bool gfp_thisnode_allocation(gfp_t gfp_mask) +{ + return false; +} #endif /* @@ -1574,7 +1583,13 @@ again: get_pageblock_migratetype(page)); } - __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order)); + /* + * NOTE: GFP_THISNODE allocations do not partake in the kswapd + * aging protocol, so they can't be fair. + */ + if (!gfp_thisnode_allocation(gfp_flags)) + __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order)); + __count_zone_vm_events(PGALLOC, zone, 1 << order); zone_statistics(preferred_zone, zone, gfp_flags); local_irq_restore(flags); @@ -1946,8 +1961,12 @@ zonelist_scan: * ultimately fall back to remote zones that do not * partake in the fairness round-robin cycle of this * zonelist. + * + * NOTE: GFP_THISNODE allocations do not partake in + * the kswapd aging protocol, so they can't be fair. */ - if (alloc_flags & ALLOC_WMARK_LOW) { + if ((alloc_flags & ALLOC_WMARK_LOW) && + !gfp_thisnode_allocation(gfp_mask)) { if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0) continue; if (!zone_local(preferred_zone, zone)) @@ -2503,8 +2522,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, * allowed per node queues are empty and that nodes are * over allocated. */ - if (IS_ENABLED(CONFIG_NUMA) && - (gfp_mask & GFP_THISNODE) == GFP_THISNODE) + if (gfp_thisnode_allocation(gfp_mask)) goto nopage; restart: -- cgit v0.10.2 From cdc2b4158405f1975f9d5205096f08430eda1c0e Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 14 Feb 2014 18:10:55 -0500 Subject: dm thin: synchronize the pool mode during suspend Commit b5330655 ("dm thin: handle metadata failures more consistently") increased potential for the pool's mode to be changed in response to metadata operation failures. When the pool mode is changed it isn't synchronized with the mode in pool_features stored in the target's context (ti->private) that is used as the basis for (re)establishing the pool mode during resume via bind_control_target. It is important that we synchronize the pool mode when it is changed otherwise the pool may experience and unexpected mode transition on the next resume (especially if there was no new table load). Signed-off-by: Mike Snitzer Acked-by: Joe Thornber diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 7e84bac..dfa48ec 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1402,6 +1402,7 @@ static enum pool_mode get_pool_mode(struct pool *pool) static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) { int r; + struct pool_c *pt = pool->ti->private; enum pool_mode old_mode = pool->pf.mode; switch (new_mode) { @@ -1448,6 +1449,11 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) } pool->pf.mode = new_mode; + /* + * The pool mode may have changed, sync it so bind_control_target() + * doesn't cause an unexpected mode transition on resume. + */ + pt->adjusted_pf.mode = new_mode; } /* -- cgit v0.10.2 From ae72758f1dd93bd367dc7719702f24a9bfb3bad9 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Mon, 11 Nov 2013 08:28:33 -0500 Subject: c6x: fix build failure caused by cache.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A patch to linux/irqflags.h uncovered a problem with c6x asm/cache.h which causes a build failure: /arch/c6x/include/asm/cache.h:63:20: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘c6x_cache_init’ extern void __init c6x_cache_init(void); The asm/cache.h was relying on linux/irqflags.h to pull in linux/init.h but the recent patch changed that. The c6x header should have included linux/init.h all along. Signed-off-by: Mark Salter diff --git a/arch/c6x/include/asm/cache.h b/arch/c6x/include/asm/cache.h index 09c5a0f..86648c0 100644 --- a/arch/c6x/include/asm/cache.h +++ b/arch/c6x/include/asm/cache.h @@ -12,6 +12,7 @@ #define _ASM_C6X_CACHE_H #include +#include /* * Cache line size -- cgit v0.10.2 From a5d90c923bcfb9632d998ed06e9569216ad695f3 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 4 Mar 2014 17:02:17 +0100 Subject: x86/efi: Quirk out SGI UV Alex reported hitting the following BUG after the EFI 1:1 virtual mapping work was merged, kernel BUG at arch/x86/mm/init_64.c:351! invalid opcode: 0000 [#1] SMP Call Trace: [] init_extra_mapping_uc+0x13/0x15 [] uv_system_init+0x22b/0x124b [] ? clockevents_register_device+0x138/0x13d [] ? setup_APIC_timer+0xc5/0xc7 [] ? clockevent_delta2ns+0xb/0xd [] ? setup_boot_APIC_clock+0x4a8/0x4b7 [] ? printk+0x72/0x74 [] native_smp_prepare_cpus+0x389/0x3d6 [] kernel_init_freeable+0xb7/0x1fb [] ? rest_init+0x74/0x74 [] kernel_init+0x9/0xff [] ret_from_fork+0x7c/0xb0 [] ? rest_init+0x74/0x74 Getting this thing to work with the new mapping scheme would need more work, so automatically switch to the old memmap layout for SGI UV. Acked-by: Russ Anderson Cc: Alex Thorlton Signed-off-by: Matt Fleming diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 3d6b9f8..acd86c8 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -134,6 +134,7 @@ extern void efi_setup_page_tables(void); extern void __init old_map_region(efi_memory_desc_t *md); extern void __init runtime_code_page_mkexec(void); extern void __init efi_runtime_mkexec(void); +extern void __init efi_apply_memmap_quirks(void); struct efi_setup_data { u64 fw_vendor; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 06853e6..ce72964 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1239,14 +1239,8 @@ void __init setup_arch(char **cmdline_p) register_refined_jiffies(CLOCK_TICK_RATE); #ifdef CONFIG_EFI - /* Once setup is done above, unmap the EFI memory map on - * mismatched firmware/kernel archtectures since there is no - * support for runtime services. - */ - if (efi_enabled(EFI_BOOT) && !efi_is_native()) { - pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); - efi_unmap_memmap(); - } + if (efi_enabled(EFI_BOOT)) + efi_apply_memmap_quirks(); #endif } diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 1a201ac..b97acec 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -52,6 +52,7 @@ #include #include #include +#include #define EFI_DEBUG @@ -1210,3 +1211,22 @@ static int __init parse_efi_cmdline(char *str) return 0; } early_param("efi", parse_efi_cmdline); + +void __init efi_apply_memmap_quirks(void) +{ + /* + * Once setup is done earlier, unmap the EFI memory map on mismatched + * firmware/kernel architectures since there is no support for runtime + * services. + */ + if (!efi_is_native()) { + pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); + efi_unmap_memmap(); + } + + /* + * UV doesn't support the new EFI pagetable mapping yet. + */ + if (is_uv_system()) + set_bit(EFI_OLD_MEMMAP, &x86_efi_facility); +} -- cgit v0.10.2 From 0ac09f9f8cd1fb028a48330edba6023d347d3cea Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 28 Feb 2014 17:05:26 +0100 Subject: x86, trace: Fix CR2 corruption when tracing page faults The trace_do_page_fault function trigger tracepoint and then handles the actual page fault. This could lead to error if the tracepoint caused page fault. The original cr2 value gets lost and the original page fault handler kills current process with SIGSEGV. This happens if you record page faults with callchain data, the user part of it will cause tracepoint handler to page fault: # perf record -g -e exceptions:page_fault_user ls Fixing this by saving the original cr2 value and using it after tracepoint handler is done. v2: Moving the cr2 read before exception_enter, because it could trigger tracepoint as well. Reported-by: Arnaldo Carvalho de Melo Reported-by: Vince Weaver Tested-by: Vince Weaver Acked-by: Steven Rostedt Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Seiji Aguchi Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1402211701380.6395@vincent-weaver-1.um.maine.edu Link: http://lkml.kernel.org/r/20140228160526.GD1133@krava.brq.redhat.com diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 6dea040..e7fa28b 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -1022,11 +1022,11 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) * routines. */ static void __kprobes -__do_page_fault(struct pt_regs *regs, unsigned long error_code) +__do_page_fault(struct pt_regs *regs, unsigned long error_code, + unsigned long address) { struct vm_area_struct *vma; struct task_struct *tsk; - unsigned long address; struct mm_struct *mm; int fault; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; @@ -1034,9 +1034,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) tsk = current; mm = tsk->mm; - /* Get the faulting address: */ - address = read_cr2(); - /* * Detect and handle instructions that would cause a page fault for * both a tracked kernel page and a userspace page. @@ -1252,9 +1249,11 @@ dotraplinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) { enum ctx_state prev_state; + /* Get the faulting address: */ + unsigned long address = read_cr2(); prev_state = exception_enter(); - __do_page_fault(regs, error_code); + __do_page_fault(regs, error_code, address); exception_exit(prev_state); } @@ -1271,9 +1270,16 @@ dotraplinkage void __kprobes trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) { enum ctx_state prev_state; + /* + * The exception_enter and tracepoint processing could + * trigger another page faults (user space callchain + * reading) and destroy the original cr2 value, so read + * the faulting address now. + */ + unsigned long address = read_cr2(); prev_state = exception_enter(); trace_page_fault_entries(regs, error_code); - __do_page_fault(regs, error_code); + __do_page_fault(regs, error_code, address); exception_exit(prev_state); } -- cgit v0.10.2 From 084b6e7765b9554699afa23a50e702a3d0ae4b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salva=20Peir=C3=B3?= Date: Mon, 3 Mar 2014 08:44:04 +0100 Subject: staging/cxt1e1/linux.c: Correct arbitrary memory write in c4_ioctl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function c4_ioctl() writes data from user in ifr->ifr_data to the kernel struct data arg, without any iolen bounds checking. This can lead to a arbitrary write outside of the struct data arg. Corrected by adding bounds-checking of iolen before the copy_from_user(). Signed-off-by: Salva Peiró Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c index 4a08e16..79206cb 100644 --- a/drivers/staging/cxt1e1/linux.c +++ b/drivers/staging/cxt1e1/linux.c @@ -866,6 +866,8 @@ c4_ioctl (struct net_device *ndev, struct ifreq *ifr, int cmd) _IOC_SIZE (iocmd)); #endif iolen = _IOC_SIZE (iocmd); + if (iolen > sizeof(arg)) + return -EFAULT; data = ifr->ifr_data + sizeof (iocmd); if (copy_from_user (&arg, data, iolen)) return -EFAULT; -- cgit v0.10.2 From d433570d9cac9c98de4c71b38d47b759f9168dea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 5 Mar 2014 09:10:02 +0800 Subject: ASoC: fsl: Don't select FIQ from Eukrea There is no point in using FIQ if DMA is available (it is selected) and selecting FIQ currently breaks the build on non-i.MX platforms. If FIQ is actually required the build will need to be restricted or have a select for the relevant FIQ code adding. Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index b8f8703..c26ff34 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -172,7 +172,6 @@ config SND_SOC_EUKREA_TLV320 || (OF && ARM) depends on I2C select SND_SOC_TLV320AIC23 - select SND_SOC_IMX_PCM_FIQ select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI select SND_SOC_FSL_SSI -- cgit v0.10.2 From 57d4325a4fa67436b05f30c02a36e204c6cd1282 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Mar 2014 09:19:37 +0100 Subject: ASoC: ak4104: Remove superfluous codec->control_data initialization The driver uses automatic IO setup, which will also initialize the control_data field of the CODEC, no need to do it manually. Signed-off-by: Lars-Peter Clausen Acked-by: Daniel Mack Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index b4819dc..10adf25 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -174,8 +174,6 @@ static int ak4104_probe(struct snd_soc_codec *codec) struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = ak4104->regmap; - /* set power-up and non-reset bits */ ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, -- cgit v0.10.2 From a2a99cea5ec7c1e47825559f0e75a4efbcf8aee3 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 26 Feb 2014 03:09:41 -0800 Subject: iscsi-target: Fix iscsit_get_tpg_from_np tpg_state bug This patch fixes a bug in iscsit_get_tpg_from_np() where the tpg->tpg_state sanity check was looking for TPG_STATE_FREE, instead of != TPG_STATE_ACTIVE. The latter is expected during a normal TPG shutdown once the tpg_state goes into TPG_STATE_INACTIVE in order to reject any new incoming login attempts. Cc: #3.10+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 3976183..44a5471 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -137,7 +137,7 @@ struct iscsi_portal_group *iscsit_get_tpg_from_np( list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) { spin_lock(&tpg->tpg_state_lock); - if (tpg->tpg_state == TPG_STATE_FREE) { + if (tpg->tpg_state != TPG_STATE_ACTIVE) { spin_unlock(&tpg->tpg_state_lock); continue; } -- cgit v0.10.2 From 5159d763f60af693a3fcec45dce2021f66e528a4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 3 Feb 2014 12:53:51 -0800 Subject: iscsi/iser-target: Use list_del_init for ->i_conn_node There are a handful of uses of list_empty() for cmd->i_conn_node within iser-target code that expect to return false once a cmd has been removed from the per connect list. This patch changes all uses of list_del -> list_del_init in order to ensure that list_empty() returns false as expected. Acked-by: Sagi Grimberg Cc: Or Gerlitz Cc: #3.10+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index d18d08a..5eb2b88 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1464,7 +1464,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd) case ISCSI_OP_SCSI_CMD: spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node)) - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); if (cmd->data_direction == DMA_TO_DEVICE) @@ -1476,7 +1476,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd) case ISCSI_OP_SCSI_TMFUNC: spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node)) - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); transport_generic_free_cmd(&cmd->se_cmd, 0); @@ -1486,7 +1486,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd) case ISCSI_OP_TEXT: spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node)) - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); /* diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 7f1a7ce..ece82b0 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -785,7 +785,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn) spin_unlock_bh(&conn->cmd_lock); list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) { - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); iscsit_free_cmd(cmd, false); } } @@ -3708,7 +3708,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state break; case ISTATE_REMOVE: spin_lock_bh(&conn->cmd_lock); - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_cmd(cmd, false); @@ -4151,7 +4151,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) spin_lock_bh(&conn->cmd_lock); list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) { - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_increment_maxcmdsn(cmd, sess); diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 33be1fb..4ca8fd2 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c @@ -138,7 +138,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess) list_for_each_entry_safe(cmd, cmd_tmp, &cr->conn_recovery_cmd_list, i_conn_node) { - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); cmd->conn = NULL; spin_unlock(&cr->conn_recovery_cmd_lock); iscsit_free_cmd(cmd, true); @@ -160,7 +160,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess) list_for_each_entry_safe(cmd, cmd_tmp, &cr->conn_recovery_cmd_list, i_conn_node) { - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); cmd->conn = NULL; spin_unlock(&cr->conn_recovery_cmd_lock); iscsit_free_cmd(cmd, true); @@ -216,7 +216,7 @@ int iscsit_remove_cmd_from_connection_recovery( } cr = cmd->cr; - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); return --cr->cmd_count; } @@ -297,7 +297,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn) if (!(cmd->cmd_flags & ICF_OOO_CMDSN)) continue; - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_cmd(cmd, true); @@ -335,7 +335,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) /* * Only perform connection recovery on ISCSI_OP_SCSI_CMD or * ISCSI_OP_NOOP_OUT opcodes. For all other opcodes call - * list_del(&cmd->i_conn_node); to release the command to the + * list_del_init(&cmd->i_conn_node); to release the command to the * session pool and remove it from the connection's list. * * Also stop the DataOUT timer, which will be restarted after @@ -351,7 +351,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) " CID: %hu\n", cmd->iscsi_opcode, cmd->init_task_tag, cmd->cmd_sn, conn->cid); - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_cmd(cmd, true); spin_lock_bh(&conn->cmd_lock); @@ -371,7 +371,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) */ if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_cmd(cmd, true); spin_lock_bh(&conn->cmd_lock); @@ -393,7 +393,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) cmd->sess = conn->sess; - list_del(&cmd->i_conn_node); + list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_all_datain_reqs(cmd); -- cgit v0.10.2 From defd884845297fd5690594bfe89656b01f16d87e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 3 Feb 2014 12:54:39 -0800 Subject: iscsi/iser-target: Fix isert_conn->state hung shutdown issues This patch addresses a couple of different hug shutdown issues related to wait_event() + isert_conn->state. First, it changes isert_conn->conn_wait + isert_conn->conn_wait_comp_err from waitqueues to completions, and sets ISER_CONN_TERMINATING from within isert_disconnect_work(). Second, it splits isert_free_conn() into isert_wait_conn() that is called earlier in iscsit_close_connection() to ensure that all outstanding commands have completed before continuing. Finally, it breaks isert_cq_comp_err() into seperate TX / RX related code, and adds logic in isert_cq_rx_comp_err() to wait for outstanding commands to complete before setting ISER_CONN_DOWN and calling complete(&isert_conn->conn_wait_comp_err). Acked-by: Sagi Grimberg Cc: Or Gerlitz Cc: #3.10+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 5eb2b88..862d7b4 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -492,8 +492,8 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) isert_conn->state = ISER_CONN_INIT; INIT_LIST_HEAD(&isert_conn->conn_accept_node); init_completion(&isert_conn->conn_login_comp); - init_waitqueue_head(&isert_conn->conn_wait); - init_waitqueue_head(&isert_conn->conn_wait_comp_err); + init_completion(&isert_conn->conn_wait); + init_completion(&isert_conn->conn_wait_comp_err); kref_init(&isert_conn->conn_kref); kref_get(&isert_conn->conn_kref); mutex_init(&isert_conn->conn_mutex); @@ -688,11 +688,11 @@ isert_disconnect_work(struct work_struct *work) pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); mutex_lock(&isert_conn->conn_mutex); - isert_conn->state = ISER_CONN_DOWN; + if (isert_conn->state == ISER_CONN_UP) + isert_conn->state = ISER_CONN_TERMINATING; if (isert_conn->post_recv_buf_count == 0 && atomic_read(&isert_conn->post_send_buf_count) == 0) { - pr_debug("Calling wake_up(&isert_conn->conn_wait);\n"); mutex_unlock(&isert_conn->conn_mutex); goto wake_up; } @@ -712,7 +712,7 @@ isert_disconnect_work(struct work_struct *work) mutex_unlock(&isert_conn->conn_mutex); wake_up: - wake_up(&isert_conn->conn_wait); + complete(&isert_conn->conn_wait); isert_put_conn(isert_conn); } @@ -1589,7 +1589,7 @@ isert_do_control_comp(struct work_struct *work) pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); /* * Call atomic_dec(&isert_conn->post_send_buf_count) - * from isert_free_conn() + * from isert_wait_conn() */ isert_conn->logout_posted = true; iscsit_logout_post_handler(cmd, cmd->conn); @@ -1691,31 +1691,39 @@ isert_send_completion(struct iser_tx_desc *tx_desc, } static void -isert_cq_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) +isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) { struct ib_device *ib_dev = isert_conn->conn_cm_id->device; + struct isert_cmd *isert_cmd = tx_desc->isert_cmd; + + if (!isert_cmd) + isert_unmap_tx_desc(tx_desc, ib_dev); + else + isert_completion_put(tx_desc, isert_cmd, ib_dev); +} + +static void +isert_cq_rx_comp_err(struct isert_conn *isert_conn) +{ + struct ib_device *ib_dev = isert_conn->conn_cm_id->device; + struct iscsi_conn *conn = isert_conn->conn; - if (tx_desc) { - struct isert_cmd *isert_cmd = tx_desc->isert_cmd; + if (isert_conn->post_recv_buf_count) + return; - if (!isert_cmd) - isert_unmap_tx_desc(tx_desc, ib_dev); - else - isert_completion_put(tx_desc, isert_cmd, ib_dev); + if (conn->sess) { + target_sess_cmd_list_set_waiting(conn->sess->se_sess); + target_wait_for_sess_cmds(conn->sess->se_sess); } - if (isert_conn->post_recv_buf_count == 0 && - atomic_read(&isert_conn->post_send_buf_count) == 0) { - pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - pr_debug("Calling wake_up from isert_cq_comp_err\n"); + while (atomic_read(&isert_conn->post_send_buf_count)) + msleep(3000); - mutex_lock(&isert_conn->conn_mutex); - if (isert_conn->state != ISER_CONN_DOWN) - isert_conn->state = ISER_CONN_TERMINATING; - mutex_unlock(&isert_conn->conn_mutex); + mutex_lock(&isert_conn->conn_mutex); + isert_conn->state = ISER_CONN_DOWN; + mutex_unlock(&isert_conn->conn_mutex); - wake_up(&isert_conn->conn_wait_comp_err); - } + complete(&isert_conn->conn_wait_comp_err); } static void @@ -1740,8 +1748,9 @@ isert_cq_tx_work(struct work_struct *work) pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); pr_debug("TX wc.status: 0x%08x\n", wc.status); pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err); + atomic_dec(&isert_conn->post_send_buf_count); - isert_cq_comp_err(tx_desc, isert_conn); + isert_cq_tx_comp_err(tx_desc, isert_conn); } } @@ -1784,7 +1793,7 @@ isert_cq_rx_work(struct work_struct *work) wc.vendor_err); } isert_conn->post_recv_buf_count--; - isert_cq_comp_err(NULL, isert_conn); + isert_cq_rx_comp_err(isert_conn); } } @@ -2702,22 +2711,11 @@ isert_free_np(struct iscsi_np *np) kfree(isert_np); } -static int isert_check_state(struct isert_conn *isert_conn, int state) -{ - int ret; - - mutex_lock(&isert_conn->conn_mutex); - ret = (isert_conn->state == state); - mutex_unlock(&isert_conn->conn_mutex); - - return ret; -} - -static void isert_free_conn(struct iscsi_conn *conn) +static void isert_wait_conn(struct iscsi_conn *conn) { struct isert_conn *isert_conn = conn->context; - pr_debug("isert_free_conn: Starting \n"); + pr_debug("isert_wait_conn: Starting \n"); /* * Decrement post_send_buf_count for special case when called * from isert_do_control_comp() -> iscsit_logout_post_handler() @@ -2727,38 +2725,29 @@ static void isert_free_conn(struct iscsi_conn *conn) atomic_dec(&isert_conn->post_send_buf_count); if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) { - pr_debug("Calling rdma_disconnect from isert_free_conn\n"); + pr_debug("Calling rdma_disconnect from isert_wait_conn\n"); rdma_disconnect(isert_conn->conn_cm_id); } /* * Only wait for conn_wait_comp_err if the isert_conn made it * into full feature phase.. */ - if (isert_conn->state == ISER_CONN_UP) { - pr_debug("isert_free_conn: Before wait_event comp_err %d\n", - isert_conn->state); - mutex_unlock(&isert_conn->conn_mutex); - - wait_event(isert_conn->conn_wait_comp_err, - (isert_check_state(isert_conn, ISER_CONN_TERMINATING))); - - wait_event(isert_conn->conn_wait, - (isert_check_state(isert_conn, ISER_CONN_DOWN))); - - isert_put_conn(isert_conn); - return; - } if (isert_conn->state == ISER_CONN_INIT) { mutex_unlock(&isert_conn->conn_mutex); - isert_put_conn(isert_conn); return; } - pr_debug("isert_free_conn: wait_event conn_wait %d\n", - isert_conn->state); + if (isert_conn->state == ISER_CONN_UP) + isert_conn->state = ISER_CONN_TERMINATING; mutex_unlock(&isert_conn->conn_mutex); - wait_event(isert_conn->conn_wait, - (isert_check_state(isert_conn, ISER_CONN_DOWN))); + wait_for_completion(&isert_conn->conn_wait_comp_err); + + wait_for_completion(&isert_conn->conn_wait); +} + +static void isert_free_conn(struct iscsi_conn *conn) +{ + struct isert_conn *isert_conn = conn->context; isert_put_conn(isert_conn); } @@ -2771,6 +2760,7 @@ static struct iscsit_transport iser_target_transport = { .iscsit_setup_np = isert_setup_np, .iscsit_accept_np = isert_accept_np, .iscsit_free_np = isert_free_np, + .iscsit_wait_conn = isert_wait_conn, .iscsit_free_conn = isert_free_conn, .iscsit_get_login_rx = isert_get_login_rx, .iscsit_put_login_tx = isert_put_login_tx, diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 708a069..41e799f 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -116,8 +116,8 @@ struct isert_conn { struct isert_device *conn_device; struct work_struct conn_logout_work; struct mutex conn_mutex; - wait_queue_head_t conn_wait; - wait_queue_head_t conn_wait_comp_err; + struct completion conn_wait; + struct completion conn_wait_comp_err; struct kref conn_kref; struct list_head conn_fr_pool; int conn_fr_pool_size; diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index ece82b0..b83ec37 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -4196,6 +4196,10 @@ int iscsit_close_connection( iscsit_stop_timers_for_cmds(conn); iscsit_stop_nopin_response_timer(conn); iscsit_stop_nopin_timer(conn); + + if (conn->conn_transport->iscsit_wait_conn) + conn->conn_transport->iscsit_wait_conn(conn); + iscsit_free_queue_reqs_for_conn(conn); /* diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index ae5a171..4483fad 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -12,6 +12,7 @@ struct iscsit_transport { int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *); int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *); void (*iscsit_free_np)(struct iscsi_np *); + void (*iscsit_wait_conn)(struct iscsi_conn *); void (*iscsit_free_conn)(struct iscsi_conn *); int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *); int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32); -- cgit v0.10.2 From b6b87a1df604678ed1be40158080db012a99ccca Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Feb 2014 09:05:03 -0800 Subject: iser-target: Fix post_send_buf_count for RDMA READ/WRITE This patch fixes the incorrect setting of ->post_send_buf_count related to RDMA WRITEs + READs where isert_rdma_rw->send_wr_num was not being taken into account. This includes incrementing ->post_send_buf_count within isert_put_datain() + isert_get_dataout(), decrementing within __isert_send_completion() + isert_response_completion(), and clearing wr->send_wr_num within isert_completion_rdma_read() This is necessary because even though IB_SEND_SIGNALED is not set for RDMA WRITEs + READs, during a QP failure event the work requests will be returned with exception status from the TX completion queue. Acked-by: Sagi Grimberg Cc: Or Gerlitz Cc: #3.10+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 862d7b4..a70b0cf 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1549,6 +1549,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc, iscsit_stop_dataout_timer(cmd); device->unreg_rdma_mem(isert_cmd, isert_conn); cmd->write_data_done = wr->cur_rdma_length; + wr->send_wr_num = 0; pr_debug("Cmd: %p RDMA_READ comp calling execute_cmd\n", isert_cmd); spin_lock_bh(&cmd->istate_lock); @@ -1613,6 +1614,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc, struct ib_device *ib_dev) { struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; + struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || cmd->i_state == ISTATE_SEND_LOGOUTRSP || @@ -1624,7 +1626,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc, queue_work(isert_comp_wq, &isert_cmd->comp_work); return; } - atomic_dec(&isert_conn->post_send_buf_count); + atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); cmd->i_state = ISTATE_SENT_STATUS; isert_completion_put(tx_desc, isert_cmd, ib_dev); @@ -1662,7 +1664,7 @@ __isert_send_completion(struct iser_tx_desc *tx_desc, case ISER_IB_RDMA_READ: pr_debug("isert_send_completion: Got ISER_IB_RDMA_READ:\n"); - atomic_dec(&isert_conn->post_send_buf_count); + atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count); isert_completion_rdma_read(tx_desc, isert_cmd); break; default: @@ -2386,12 +2388,12 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd) isert_init_send_wr(isert_conn, isert_cmd, &isert_cmd->tx_desc.send_wr, true); - atomic_inc(&isert_conn->post_send_buf_count); + atomic_add(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed); if (rc) { pr_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n"); - atomic_dec(&isert_conn->post_send_buf_count); + atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); } pr_debug("Cmd: %p posted RDMA_WRITE + Response for iSER Data READ\n", isert_cmd); @@ -2419,12 +2421,12 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery) return rc; } - atomic_inc(&isert_conn->post_send_buf_count); + atomic_add(wr->send_wr_num, &isert_conn->post_send_buf_count); rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed); if (rc) { pr_warn("ib_post_send() failed for IB_WR_RDMA_READ\n"); - atomic_dec(&isert_conn->post_send_buf_count); + atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count); } pr_debug("Cmd: %p posted RDMA_READ memory for ISER Data WRITE\n", isert_cmd); -- cgit v0.10.2 From 9bb4ca68fc48eea618b1af1c1cde2a251ae32d1b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Feb 2014 07:02:48 -0800 Subject: iser-target: Ignore completions for FRWRs in isert_cq_tx_work This patch changes IB_WR_FAST_REG_MR + IB_WR_LOCAL_INV related work requests to include a ISER_FRWR_LI_WRID value in order to signal isert_cq_tx_work() that these requests should be ignored. This is necessary because even though IB_SEND_SIGNALED is not set for either work request, during a QP failure event the work requests will be returned with exception status from the TX completion queue. v2 changes: - Rename ISER_FRWR_LI_WRID -> ISER_FASTREG_LI_WRID (Sagi) Acked-by: Sagi Grimberg Cc: Or Gerlitz Cc: #3.12+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index a70b0cf..614a6ef 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1751,8 +1751,10 @@ isert_cq_tx_work(struct work_struct *work) pr_debug("TX wc.status: 0x%08x\n", wc.status); pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err); - atomic_dec(&isert_conn->post_send_buf_count); - isert_cq_tx_comp_err(tx_desc, isert_conn); + if (wc.wr_id != ISER_FASTREG_LI_WRID) { + atomic_dec(&isert_conn->post_send_buf_count); + isert_cq_tx_comp_err(tx_desc, isert_conn); + } } } @@ -2213,6 +2215,7 @@ isert_fast_reg_mr(struct fast_reg_descriptor *fr_desc, if (!fr_desc->valid) { memset(&inv_wr, 0, sizeof(inv_wr)); + inv_wr.wr_id = ISER_FASTREG_LI_WRID; inv_wr.opcode = IB_WR_LOCAL_INV; inv_wr.ex.invalidate_rkey = fr_desc->data_mr->rkey; wr = &inv_wr; @@ -2223,6 +2226,7 @@ isert_fast_reg_mr(struct fast_reg_descriptor *fr_desc, /* Prepare FASTREG WR */ memset(&fr_wr, 0, sizeof(fr_wr)); + fr_wr.wr_id = ISER_FASTREG_LI_WRID; fr_wr.opcode = IB_WR_FAST_REG_MR; fr_wr.wr.fast_reg.iova_start = fr_desc->data_frpl->page_list[0] + page_off; diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 41e799f..10be55a 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -6,6 +6,7 @@ #define ISERT_RDMA_LISTEN_BACKLOG 10 #define ISCSI_ISER_SG_TABLESIZE 256 +#define ISER_FASTREG_LI_WRID 0xffffffffffffffffULL enum isert_desc_type { ISCSI_TX_CONTROL, -- cgit v0.10.2 From ebbe442183b7b8192c963266f1c89048fefc63a5 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 2 Mar 2014 14:51:12 -0800 Subject: iser-target: Fix command leak for tx_desc->comp_llnode_batch This patch addresses a number of active I/O shutdown issues related to isert_cmd descriptors being leaked that are part of a completion interrupt coalescing batch. This includes adding logic in isert_cq_tx_comp_err() to drain any associated tx_desc->comp_llnode_batch, as well as isert_cq_drain_comp_llist() to drain any associated isert_conn->conn_comp_llist. Also, set tx_desc->llnode_active in isert_init_send_wr() in order to determine when work requests need to be skipped in isert_cq_tx_work() exception path code. Finally, update isert_init_send_wr() to only allow interrupt coalescing when ISER_CONN_UP. Acked-by: Sagi Grimberg Cc: Or Gerlitz Cc: #3.13+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 614a6ef..8ee228e 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -497,7 +497,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) kref_init(&isert_conn->conn_kref); kref_get(&isert_conn->conn_kref); mutex_init(&isert_conn->conn_mutex); - mutex_init(&isert_conn->conn_comp_mutex); spin_lock_init(&isert_conn->conn_lock); cma_id->context = isert_conn; @@ -888,16 +887,17 @@ isert_init_send_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, * Coalesce send completion interrupts by only setting IB_SEND_SIGNALED * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls. */ - mutex_lock(&isert_conn->conn_comp_mutex); - if (coalesce && + mutex_lock(&isert_conn->conn_mutex); + if (coalesce && isert_conn->state == ISER_CONN_UP && ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) { + tx_desc->llnode_active = true; llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist); - mutex_unlock(&isert_conn->conn_comp_mutex); + mutex_unlock(&isert_conn->conn_mutex); return; } isert_conn->conn_comp_batch = 0; tx_desc->comp_llnode_batch = llist_del_all(&isert_conn->conn_comp_llist); - mutex_unlock(&isert_conn->conn_comp_mutex); + mutex_unlock(&isert_conn->conn_mutex); send_wr->send_flags = IB_SEND_SIGNALED; } @@ -1693,10 +1693,45 @@ isert_send_completion(struct iser_tx_desc *tx_desc, } static void +isert_cq_drain_comp_llist(struct isert_conn *isert_conn, struct ib_device *ib_dev) +{ + struct llist_node *llnode; + struct isert_rdma_wr *wr; + struct iser_tx_desc *t; + + mutex_lock(&isert_conn->conn_mutex); + llnode = llist_del_all(&isert_conn->conn_comp_llist); + isert_conn->conn_comp_batch = 0; + mutex_unlock(&isert_conn->conn_mutex); + + while (llnode) { + t = llist_entry(llnode, struct iser_tx_desc, comp_llnode); + llnode = llist_next(llnode); + wr = &t->isert_cmd->rdma_wr; + + atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); + isert_completion_put(t, t->isert_cmd, ib_dev); + } +} + +static void isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) { struct ib_device *ib_dev = isert_conn->conn_cm_id->device; struct isert_cmd *isert_cmd = tx_desc->isert_cmd; + struct llist_node *llnode = tx_desc->comp_llnode_batch; + struct isert_rdma_wr *wr; + struct iser_tx_desc *t; + + while (llnode) { + t = llist_entry(llnode, struct iser_tx_desc, comp_llnode); + llnode = llist_next(llnode); + wr = &t->isert_cmd->rdma_wr; + + atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); + isert_completion_put(t, t->isert_cmd, ib_dev); + } + tx_desc->comp_llnode_batch = NULL; if (!isert_cmd) isert_unmap_tx_desc(tx_desc, ib_dev); @@ -1713,6 +1748,8 @@ isert_cq_rx_comp_err(struct isert_conn *isert_conn) if (isert_conn->post_recv_buf_count) return; + isert_cq_drain_comp_llist(isert_conn, ib_dev); + if (conn->sess) { target_sess_cmd_list_set_waiting(conn->sess->se_sess); target_wait_for_sess_cmds(conn->sess->se_sess); @@ -1752,6 +1789,9 @@ isert_cq_tx_work(struct work_struct *work) pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err); if (wc.wr_id != ISER_FASTREG_LI_WRID) { + if (tx_desc->llnode_active) + continue; + atomic_dec(&isert_conn->post_send_buf_count); isert_cq_tx_comp_err(tx_desc, isert_conn); } diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 10be55a..f6ae7f5 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -46,6 +46,7 @@ struct iser_tx_desc { struct isert_cmd *isert_cmd; struct llist_node *comp_llnode_batch; struct llist_node comp_llnode; + bool llnode_active; struct ib_send_wr send_wr; } __packed; @@ -127,7 +128,6 @@ struct isert_conn { #define ISERT_COMP_BATCH_COUNT 8 int conn_comp_batch; struct llist_head conn_comp_llist; - struct mutex conn_comp_mutex; }; #define ISERT_MAX_CQ 64 -- cgit v0.10.2 From 905a5117e79367b7e58ae046d12ca9961f048c89 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 11 Feb 2014 00:22:37 +0800 Subject: pinctrl: sunxi: use chained_irq_{enter, exit} for GIC compatibility On tha Allwinner A20 SoC, the external interrupts on the pin controller device are connected to the GIC. Without chained_irq_{enter, exit}, external GPIO interrupts, such as used by mmc core card detect, cause the system to hang. This issue was first encountered during my attempt to get out-of-band interrupts for WiFi on the Cubietruck working. With David's new series of sunci-mci using mmc slot-gpio for (GPIO interrupt based) card detection, removing the SD card also causes my Cubietruck to hang. This problem should extend to all Allwinner A20 based boards. With this fix, the system no longer hangs when I remove or insert the SD card. /proc/interrupts show that the interrupt has correctly fired. However the system still does not detect card removal/insertion. I believe this is another unrelated issue. Cc: stable@vger.kernel.org Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c index 9ccf681..787f352 100644 --- a/drivers/pinctrl/pinctrl-sunxi.c +++ b/drivers/pinctrl/pinctrl-sunxi.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -665,6 +666,7 @@ static struct irq_chip sunxi_pinctrl_irq_chip = { static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc) { + struct irq_chip *chip = irq_get_chip(irq); struct sunxi_pinctrl *pctl = irq_get_handler_data(irq); const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG); @@ -674,10 +676,12 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc) if (reg) { int irqoffset; + chained_irq_enter(chip, desc); for_each_set_bit(irqoffset, ®, SUNXI_IRQ_NUMBER) { int pin_irq = irq_find_mapping(pctl->domain, irqoffset); generic_handle_irq(pin_irq); } + chained_irq_exit(chip, desc); } } -- cgit v0.10.2 From d82f94013a9897e02a93400e4c16efe82b530eaa Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 22:19:43 +0100 Subject: pinctrl: sunxi: Fix masking when setting irq type Signed-off-by: Hans de Goede Acked-by: Maxime Ripard Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c index 787f352..f9fabe9 100644 --- a/drivers/pinctrl/pinctrl-sunxi.c +++ b/drivers/pinctrl/pinctrl-sunxi.c @@ -585,7 +585,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, spin_lock_irqsave(&pctl->lock, flags); regval = readl(pctl->membase + reg); - regval &= ~IRQ_CFG_IRQ_MASK; + regval &= ~(IRQ_CFG_IRQ_MASK << index); writel(regval | (mode << index), pctl->membase + reg); spin_unlock_irqrestore(&pctl->lock, flags); -- cgit v0.10.2 From ef5aff05f1e6ff172bab86097fbbfe26a44cc228 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 22:19:44 +0100 Subject: pinctrl: sunxi: Fix interrupt register offset calculation This fixing setting the interrupt type for eints >= 8. Signed-off-by: Hans de Goede Acked-by: Maxime Ripard Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h index 01c494f..552b0e9 100644 --- a/drivers/pinctrl/pinctrl-sunxi.h +++ b/drivers/pinctrl/pinctrl-sunxi.h @@ -511,7 +511,7 @@ static inline u32 sunxi_pull_offset(u16 pin) static inline u32 sunxi_irq_cfg_reg(u16 irq) { - u8 reg = irq / IRQ_CFG_IRQ_PER_REG; + u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04; return reg + IRQ_CFG_REG; } @@ -523,7 +523,7 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq) static inline u32 sunxi_irq_ctrl_reg(u16 irq) { - u8 reg = irq / IRQ_CTRL_IRQ_PER_REG; + u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04; return reg + IRQ_CTRL_REG; } @@ -535,7 +535,7 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq) static inline u32 sunxi_irq_status_reg(u16 irq) { - u8 reg = irq / IRQ_STATUS_IRQ_PER_REG; + u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04; return reg + IRQ_STATUS_REG; } -- cgit v0.10.2 From 5ba341604a054294aeb812603349bba024d716ee Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Mon, 24 Feb 2014 12:41:20 -0600 Subject: pinctrl: msm: make PINCTRL_MSM bool instead of tristate Modular builds of pinctrl-msm break due to handle_bad_irq being unexported for module use. For now, make PINCTRL_MSM 'bool'. Signed-off-by: Josh Cartwright Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index be361b7..1e4e693 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -217,7 +217,7 @@ config PINCTRL_IMX28 select PINCTRL_MXS config PINCTRL_MSM - tristate + bool select PINMUX select PINCONF select GENERIC_PINCONF -- cgit v0.10.2 From b5973fcd76ac5b3f2fabb0ab181d45ac16b8ce02 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 26 Feb 2014 19:10:26 +0900 Subject: pinctrl: sh-pfc: r8a7791: SD1_CLK fix Fix the SD1_CLK handling for r8a7791. Without this patch it is impossible to request all pins needed for SDHI1 on the Koelsch board. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index 77d103f..567d691 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -89,7 +89,8 @@ enum { /* GPSR6 */ FN_IP13_10, FN_IP13_11, FN_IP13_12, FN_IP13_13, FN_IP13_14, - FN_IP13_15, FN_IP13_18_16, FN_IP13_21_19, FN_IP13_22, FN_IP13_24_23, + FN_IP13_15, FN_IP13_18_16, FN_IP13_21_19, + FN_IP13_22, FN_IP13_24_23, FN_SD1_CLK, FN_IP13_25, FN_IP13_26, FN_IP13_27, FN_IP13_30_28, FN_IP14_1_0, FN_IP14_2, FN_IP14_3, FN_IP14_4, FN_IP14_5, FN_IP14_6, FN_IP14_7, FN_IP14_10_8, FN_IP14_13_11, FN_IP14_16_14, FN_IP14_19_17, @@ -788,6 +789,7 @@ static const u16 pinmux_data[] = { PINMUX_DATA(USB1_PWEN_MARK, FN_USB1_PWEN), PINMUX_DATA(USB1_OVC_MARK, FN_USB1_OVC), PINMUX_DATA(DU0_DOTCLKIN_MARK, FN_DU0_DOTCLKIN), + PINMUX_DATA(SD1_CLK_MARK, FN_SD1_CLK), /* IPSR0 */ PINMUX_IPSR_DATA(IP0_0, D0), @@ -3825,7 +3827,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_6_11_FN, FN_IP13_25, GP_6_10_FN, FN_IP13_24_23, GP_6_9_FN, FN_IP13_22, - 0, 0, + GP_6_8_FN, FN_SD1_CLK, GP_6_7_FN, FN_IP13_21_19, GP_6_6_FN, FN_IP13_18_16, GP_6_5_FN, FN_IP13_15, -- cgit v0.10.2 From e4ad1accb28d0ed8cea6f12395d58686ad344ca7 Mon Sep 17 00:00:00 2001 From: Patrick Lai Date: Sun, 2 Mar 2014 11:52:57 -0800 Subject: ASoC: pcm: free path list before exiting from error conditions dpcm_path_get() allocates dynamic memory to hold path list. Corresponding dpcm_path_put() must be called to free the memory. dpcm_path_put() is not called under several error conditions. This leads to memory leak. Signed-off-by: Patrick Lai Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 47e1ce7..28522bd 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1989,6 +1989,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); if (paths < 0) { + dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "playback"); mutex_unlock(&card->mutex); @@ -2018,6 +2019,7 @@ capture: paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); if (paths < 0) { + dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "capture"); mutex_unlock(&card->mutex); @@ -2082,6 +2084,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].runtime = fe_substream->runtime; if (dpcm_path_get(fe, stream, &list) <= 0) { + dpcm_path_put(&list); dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", fe->dai_link->name, stream ? "capture" : "playback"); } -- cgit v0.10.2 From 017145fef567430789e40f6a22a90ce2a766370b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 14 Feb 2014 12:49:12 +0800 Subject: spi: fsl-dspi: Fix getting correct address for master Current code set platform drvdata to dspi. However, the code in dspi_suspend() and dspi_resume() assumes the drvdata is the address of master. Fix it by setting platform drvdata to master. Signed-off-by: Axel Lin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index ec79f72..a253920 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -420,7 +420,6 @@ static int dspi_suspend(struct device *dev) static int dspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); struct fsl_dspi *dspi = spi_master_get_devdata(master); @@ -504,7 +503,7 @@ static int dspi_probe(struct platform_device *pdev) clk_prepare_enable(dspi->clk); init_waitqueue_head(&dspi->waitq); - platform_set_drvdata(pdev, dspi); + platform_set_drvdata(pdev, master); ret = spi_bitbang_start(&dspi->bitbang); if (ret != 0) { @@ -525,7 +524,8 @@ out_master_put: static int dspi_remove(struct platform_device *pdev) { - struct fsl_dspi *dspi = platform_get_drvdata(pdev); + struct spi_master *master = platform_get_drvdata(pdev); + struct fsl_dspi *dspi = spi_master_get_devdata(master); /* Disconnect from the SPI framework */ spi_bitbang_stop(&dspi->bitbang); -- cgit v0.10.2 From ee73b4c6e3fc0755a91752ab8eebc8e070038b53 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 14 Feb 2014 09:53:00 +0800 Subject: spi: coldfire-qspi: Fix getting correct address for *mcfqspi dev_get_drvdata() returns the address of master rather than mcfqspi. Fixes: af361079 (spi/coldfire-qspi: Drop extra calls to spi_master_get in suspend/resume functions) Signed-off-by: Axel Lin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index cabed8f..28ae470 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -514,7 +514,8 @@ static int mcfqspi_resume(struct device *dev) #ifdef CONFIG_PM_RUNTIME static int mcfqspi_runtime_suspend(struct device *dev) { - struct mcfqspi *mcfqspi = dev_get_drvdata(dev); + struct spi_master *master = dev_get_drvdata(dev); + struct mcfqspi *mcfqspi = spi_master_get_devdata(master); clk_disable(mcfqspi->clk); @@ -523,7 +524,8 @@ static int mcfqspi_runtime_suspend(struct device *dev) static int mcfqspi_runtime_resume(struct device *dev) { - struct mcfqspi *mcfqspi = dev_get_drvdata(dev); + struct spi_master *master = dev_get_drvdata(dev); + struct mcfqspi *mcfqspi = spi_master_get_devdata(master); clk_enable(mcfqspi->clk); -- cgit v0.10.2 From ba938f3a295686aa9ab5077b10d1049f8091cbd7 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Wed, 5 Mar 2014 11:29:01 +0800 Subject: spi: atmel: add missing spi_master_{resume,suspend} calls to PM callbacks The PM callbacks implemented by the spi-atmel driver don't call spi_master_{resume,suspend}, fix that. Signed-off-by: Wenyou Yang Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index b0842f7..5d7b07f 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1455,6 +1455,14 @@ static int atmel_spi_suspend(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct atmel_spi *as = spi_master_get_devdata(master); + int ret; + + /* Stop the queue running */ + ret = spi_master_suspend(master); + if (ret) { + dev_warn(dev, "cannot suspend master\n"); + return ret; + } clk_disable_unprepare(as->clk); return 0; @@ -1464,9 +1472,16 @@ static int atmel_spi_resume(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct atmel_spi *as = spi_master_get_devdata(master); + int ret; clk_prepare_enable(as->clk); - return 0; + + /* Start the queue running */ + ret = spi_master_resume(master); + if (ret) + dev_err(dev, "problem starting queue (%d)\n", ret); + + return ret; } static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume); -- cgit v0.10.2 From 78f13d0c5a2888564b2bed7f8433c8ec889997ff Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:49:50 -0800 Subject: ASoC: rsnd: add struct rsnd_dai_platform_info R-Car sound DAI consists from SSI/SCU/SSIU/SRU... Current R-Car sound DAI is decided from these settings, but it is intuitively unclear, and is not good design for DT support. This patch adds new rsnd_dai_platform_info to solve this issue. But now, many platform is using this driver without rsnd_dai_platform_info. So, this patch still supports DAI settings via SSI to keep compatible. It will be removed in next Linux version. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index e3d585c..698f7b5 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -36,13 +36,15 @@ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) #define RSND_SSI_PLAY (1 << 24) +#define RSND_SSI(_dma_id, _pio_irq, _flags) \ +{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \ { .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_UNUSED \ { .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 } struct rsnd_ssi_platform_info { - int dai_id; + int dai_id; /* will be removed */ int dma_id; int pio_irq; u32 flags; @@ -53,6 +55,8 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ +#define RSND_SCU(rate, _dma_id) \ +{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } #define RSND_SCU_SET(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } #define RSND_SCU_UNUSED \ @@ -64,6 +68,15 @@ struct rsnd_scu_platform_info { int dma_id; /* for Gen2 SCU */ }; +struct rsnd_dai_path_info { + struct rsnd_ssi_platform_info *ssi; +}; + +struct rsnd_dai_platform_info { + struct rsnd_dai_path_info playback; + struct rsnd_dai_path_info capture; +}; + /* * flags * @@ -81,6 +94,8 @@ struct rcar_snd_info { int ssi_info_nr; struct rsnd_scu_platform_info *scu_info; int scu_info_nr; + struct rsnd_dai_platform_info *dai_info; + int dai_info_nr; int (*start)(int id); int (*stop)(int id); }; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ea74761..4504726 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -639,19 +639,26 @@ static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_dai *rdai; struct rsnd_mod *pmod, *cmod; struct device *dev = rsnd_priv_to_dev(priv); - int dai_nr; + int dai_nr = info->dai_info_nr; int i; - /* get max dai nr */ - for (dai_nr = 0; dai_nr < 32; dai_nr++) { - pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); - cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); + /* + * dai_nr should be set via dai_info_nr, + * but allow it to keeping compatible + */ + if (!dai_nr) { + /* get max dai nr */ + for (dai_nr = 0; dai_nr < 32; dai_nr++) { + pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); + cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); - if (!pmod && !cmod) - break; + if (!pmod && !cmod) + break; + } } if (!dai_nr) { @@ -671,6 +678,8 @@ static int rsnd_dai_probe(struct platform_device *pdev, priv->rdai = rdai; for (i = 0; i < dai_nr; i++) { + if (info->dai_info) + rdai[i].info = &info->dai_info[i]; pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 25a7d44..3423481 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -451,12 +451,26 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = { struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play) { + struct rsnd_dai_platform_info *dai_info = NULL; + struct rsnd_dai_path_info *path_info = NULL; + struct rsnd_ssi_platform_info *target_info = NULL; struct rsnd_ssi *ssi; int i, has_play; + if (priv->rdai) + dai_info = priv->rdai[dai_id].info; + if (dai_info) + path_info = (is_play) ? &dai_info->playback : &dai_info->capture; + if (path_info) + target_info = path_info->ssi; + is_play = !!is_play; for_each_rsnd_ssi(ssi, priv, i) { + if (target_info == ssi->info) + return &ssi->mod; + + /* for compatible */ if (rsnd_ssi_dai_id(ssi) != dai_id) continue; -- cgit v0.10.2 From 389933d9f6e55a1ef3a71549c36f6283b9f8c145 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:00 -0800 Subject: ASoC: rsnd: Get correct SCU ID Current rsnd driver is assuming that SCU/SRU ID is same as SSIU/SSI ID, because Gen1 can't select it. But, Gen2 can select it. The SCU/SRU/SSIU/SSI pair depends on the platform. This patch get correct SCU ID from platform info. To keep compatible, it still assuming SCU ID = SSI ID if platform doesn't have info Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 698f7b5..1d8c683 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -70,6 +70,7 @@ struct rsnd_scu_platform_info { struct rsnd_dai_path_info { struct rsnd_ssi_platform_info *ssi; + struct rsnd_scu_platform_info *scu; }; struct rsnd_dai_platform_info { diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4504726..7316d10 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -107,6 +107,11 @@ (!(priv->info->func) ? 0 : \ priv->info->func(param)) +#define rsnd_is_enable_path(io, name) \ + ((io)->info ? (io)->info->name : NULL) +#define rsnd_info_id(priv, io, name) \ + ((io)->info->name - priv->info->name##_info) + /* * rsnd_mod functions */ @@ -572,8 +577,10 @@ static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai_stream *io) { struct rsnd_mod *mod; + struct rsnd_dai_platform_info *dai_info = rdai->info; int ret; - int id; + int ssi_id = -1; + int scu_id = -1; /* * Gen1 is created by SRU/SSI, and this SRU is base module of @@ -584,29 +591,35 @@ static int rsnd_path_init(struct rsnd_priv *priv, * * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is * using fixed path. - * - * Then, SSI id = SCU id here */ - /* get SSI's ID */ - mod = rsnd_ssi_mod_get_frm_dai(priv, - rsnd_dai_id(priv, rdai), - rsnd_dai_is_play(rdai, io)); - if (!mod) - return 0; - id = rsnd_mod_id(mod); + if (dai_info) { + if (rsnd_is_enable_path(io, ssi)) + ssi_id = rsnd_info_id(priv, io, ssi); + if (rsnd_is_enable_path(io, scu)) + scu_id = rsnd_info_id(priv, io, scu); + } else { + /* get SSI's ID */ + mod = rsnd_ssi_mod_get_frm_dai(priv, + rsnd_dai_id(priv, rdai), + rsnd_dai_is_play(rdai, io)); + if (!mod) + return 0; + ssi_id = scu_id = rsnd_mod_id(mod); + } + ret = 0; /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - if (mod) { + if (scu_id >= 0) { + mod = rsnd_scu_mod_get(priv, scu_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - if (mod) { + if (ssi_id >= 0) { + mod = rsnd_ssi_mod_get(priv, ssi_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; @@ -699,6 +712,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].playback.formats = RSND_FMTS; drv[i].playback.channels_min = 2; drv[i].playback.channels_max = 2; + + if (info->dai_info) + rdai[i].playback.info = &info->dai_info[i].playback; rsnd_path_init(priv, &rdai[i], &rdai[i].playback); } if (cmod) { @@ -706,6 +722,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].capture.formats = RSND_FMTS; drv[i].capture.channels_min = 2; drv[i].capture.channels_max = 2; + + if (info->dai_info) + rdai[i].capture.info = &info->dai_info[i].capture; rsnd_path_init(priv, &rdai[i], &rdai[i].capture); } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d5afdee..3472631 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -211,6 +211,7 @@ char *rsnd_mod_name(struct rsnd_mod *mod); struct rsnd_dai_stream { struct snd_pcm_substream *substream; struct rsnd_mod *mod[RSND_MOD_MAX]; + struct rsnd_dai_path_info *info; /* rcar_snd.h */ int byte_pos; int period_pos; int byte_per_period; @@ -328,6 +329,19 @@ struct rsnd_priv { #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) +#define rsnd_info_is_playback(priv, type) \ +({ \ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); \ + int i, is_play = 0; \ + for (i = 0; i < info->dai_info_nr; i++) { \ + if (info->dai_info[i].playback.type == (type)->info) { \ + is_play = 1; \ + break; \ + } \ + } \ + is_play; \ +}) + /* * R-Car SCU */ diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 1073d35..b517300 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -620,6 +620,9 @@ int rsnd_scu_probe(struct platform_device *pdev, * init SCU */ nr = info->scu_info_nr; + if (!nr) + return 0; + scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); if (!scu) { dev_err(dev, "SCU allocate failed\n"); @@ -644,11 +647,19 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; if (rsnd_is_gen2(priv)) { - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); - int ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(&scu->mod), - rsnd_ssi_is_play(ssi), - scu->info->dma_id); + int ret; + int is_play; + + if (info->dai_info) { + is_play = rsnd_info_is_playback(priv, scu); + } else { + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); + is_play = rsnd_ssi_is_play(ssi); + } + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(&scu->mod), + is_play, + scu->info->dma_id); if (ret < 0) return ret; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 3423481..9162c2b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -567,9 +567,16 @@ int rsnd_ssi_probe(struct platform_device *pdev, * SSI DMA case */ if (pinfo->dma_id > 0) { + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, ssi); + else + is_play = rsnd_ssi_is_play(&ssi->mod); + ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), - rsnd_ssi_is_play(&ssi->mod), + is_play, pinfo->dma_id); if (ret < 0) dev_info(dev, "SSI DMA failed. try PIO transter\n"); -- cgit v0.10.2 From b8cc41e9e8cc5beec9dcbe044cfc44aa0325d9e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:08 -0800 Subject: ASoC: rsnd: add rsnd_scu_enable_ssi_irq() Current R-Car sound driver is assuming that SCU mod is used even though it is not needed. Because scu.c is controlling SSIU too. (it is Gen1 compatibility) But, SCU mod will be really not used if new platform dai feature was used. Thus, SSIU irq setting is called from SSI directory by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3472631..3b71b77 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -353,6 +353,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); +int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); #define rsnd_scu_nr(priv) ((priv)->scu_nr) diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index b517300..8ce79e8 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -165,6 +165,19 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, return 0; } +int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + + /* enable PIO interrupt if Gen2 */ + if (rsnd_is_gen2(priv)) + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); + + return 0; +} + unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) @@ -579,22 +592,9 @@ static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .stop = rsnd_scu_stop_gen2, }; -static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); - - /* enable PIO interrupt */ - rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); - - return 0; -} - static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { .name = "non-scu (gen2)", .init = rsnd_scu_ssi_mode_init, - .start = rsnd_scu_start_non_gen2, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 9162c2b..a74c7a7 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -365,6 +365,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; + rsnd_scu_enable_ssi_irq(mod, rdai, io); + rsnd_ssi_hw_start(ssi, rdai, io); return 0; -- cgit v0.10.2 From 221bf523e31306c1095b28932e079950108e3887 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:24 -0800 Subject: ASoC: rsnd: call rsnd_scu_ssi_mode_init() from SSI Current R-Car sound driver is assuming that SCU mod is used even though it is not needed. Because scu.c is controlling SSIU too. (it is Gen1 compatibility) But, SCU mod will be really not used if new platform dai feature was added. Thus, rsnd_scu_ssi_mode_init() is called from SSI directory by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3b71b77..9205f96 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -353,6 +353,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); +int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 8ce79e8..63e6aeb 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -115,28 +115,28 @@ struct rsnd_scu { /* * Gen1/Gen2 common functions */ -static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_mod *scu_mod = rsnd_io_to_mod_scu(io); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); int ssi_id = rsnd_mod_id(ssi_mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - - if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { - struct device *dev = rsnd_priv_to_dev(priv); - - dev_err(dev, "rsnd should be clk master when you rate convert\n"); - return -EINVAL; - } + int has_scu = 0; /* * SSI_MODE0 */ - rsnd_mod_bset(mod, SSI_MODE0, (1 << ssi_id), - rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << ssi_id)); + if (info->dai_info) { + has_scu = !!scu_mod; + } else { + struct rsnd_scu *scu = rsnd_mod_to_scu(scu_mod); + has_scu = rsnd_scu_hpbif_is_enable(scu); + } + + rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), + has_scu ? 0 : (1 << ssi_id)); /* * SSI_MODE1 @@ -156,7 +156,7 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, } if (shift >= 0) - rsnd_mod_bset(mod, SSI_MODE1, + rsnd_mod_bset(ssi_mod, SSI_MODE1, 0x3 << shift, rsnd_dai_is_clk_master(rdai) ? 0x2 << shift : 0x1 << shift); @@ -253,14 +253,9 @@ static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int ret; clk_enable(scu->clk); - ret = rsnd_scu_ssi_mode_init(mod, rdai, io); - if (ret < 0) - return ret; - return 0; } @@ -487,11 +482,6 @@ static struct rsnd_mod_ops rsnd_scu_gen1_ops = { .stop = rsnd_scu_stop_gen1, }; -static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { - .name = "non-sru (gen1)", - .init = rsnd_scu_ssi_mode_init, -}; - /* * Gen2 functions */ @@ -592,11 +582,6 @@ static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .stop = rsnd_scu_stop_gen2, }; -static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { - .name = "non-scu (gen2)", - .init = rsnd_scu_ssi_mode_init, -}; - struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) { if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) @@ -665,11 +650,6 @@ int rsnd_scu_probe(struct platform_device *pdev, ops = &rsnd_scu_gen2_ops; } - } else { - if (rsnd_is_gen1(priv)) - ops = &rsnd_scu_non_gen1_ops; - if (rsnd_is_gen2(priv)) - ops = &rsnd_scu_non_gen2_ops; } rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index a74c7a7..a7df216 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -287,6 +287,8 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ + rsnd_scu_ssi_mode_init(mod, rdai, io); + return 0; } -- cgit v0.10.2 From 7681f6ac6b6338932621f842d68e54f6267b785f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:33 -0800 Subject: ASoC: rsnd: add probe/remove callback on rsnd_mod_ops Each rsnd mod needs specific probe method, and its best timing is DAI probe timing. But current code runs it mod probe timing. This patch adds new probe/remove callback to solve it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 7316d10..e8e585d 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -842,6 +842,7 @@ static int rsnd_probe(struct platform_device *pdev) struct rcar_snd_info *info; struct rsnd_priv *priv; struct device *dev = &pdev->dev; + struct rsnd_dai *rdai; int (*probe_func[])(struct platform_device *pdev, struct rsnd_priv *priv) = { rsnd_gen_probe, @@ -880,6 +881,16 @@ static int rsnd_probe(struct platform_device *pdev) return ret; } + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, probe); + if (ret) + return ret; + + ret = rsnd_dai_call(rdai, &rdai->capture, probe); + if (ret) + return ret; + } + /* * asoc register */ @@ -912,9 +923,21 @@ exit_snd_soc: static int rsnd_remove(struct platform_device *pdev) { struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); + struct rsnd_dai *rdai; + int ret, i; pm_runtime_disable(&pdev->dev); + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, remove); + if (ret) + return ret; + + ret = rsnd_dai_call(rdai, &rdai->capture, remove); + if (ret) + return ret; + } + /* * remove each module */ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9205f96..db20b37 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -167,6 +167,12 @@ enum rsnd_mod_type { struct rsnd_mod_ops { char *name; + int (*probe)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); + int (*remove)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); int (*init)(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -- cgit v0.10.2 From 76c6fb5c49790da44d553f655182b426ade2c599 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:41 -0800 Subject: ASoC: rsnd: use mod probe method on SCU Now, it can use .probe Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 63e6aeb..40250ac 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -525,6 +525,42 @@ static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, return ret; } +static int rsnd_scu_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); + struct device *dev = rsnd_priv_to_dev(priv); + int ret; + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, scu); + else + is_play = rsnd_ssi_is_play(ssi); + + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(mod), + is_play, + scu->info->dma_id); + if (ret < 0) + dev_err(dev, "SCU DMA failed\n"); + + return ret; +} + +static int rsnd_scu_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + static int rsnd_scu_init_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -576,6 +612,8 @@ static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .name = "scu (gen2)", + .probe = rsnd_scu_probe_gen2, + .remove = rsnd_scu_remove_gen2, .init = rsnd_scu_init_gen2, .quit = rsnd_scu_quit, .start = rsnd_scu_start_gen2, @@ -631,25 +669,8 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_scu_hpbif_is_enable(scu)) { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; - if (rsnd_is_gen2(priv)) { - int ret; - int is_play; - - if (info->dai_info) { - is_play = rsnd_info_is_playback(priv, scu); - } else { - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); - is_play = rsnd_ssi_is_play(ssi); - } - ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(&scu->mod), - is_play, - scu->info->dma_id); - if (ret < 0) - return ret; - + if (rsnd_is_gen2(priv)) ops = &rsnd_scu_gen2_ops; - } } rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); @@ -663,11 +684,4 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_scu *scu; - int i; - - for_each_rsnd_scu(scu, priv, i) { - if (rsnd_scu_dma_available(scu)) - rsnd_dma_quit(priv, rsnd_mod_to_dma(&scu->mod)); - } } -- cgit v0.10.2 From ff8f30e688477beead6d1e648fb11f321220a4d7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:49 -0800 Subject: ASoC: rsnd: use mod probe method on SSI Now, it can use .probe Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index a7df216..0f3eeac 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -358,6 +358,26 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) return ret; } +static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + int irq = ssi->info->pio_irq; + int ret; + + ret = devm_request_irq(dev, irq, + rsnd_ssi_pio_interrupt, + IRQF_SHARED, + dev_name(dev), ssi); + if (ret) + dev_err(dev, "SSI request interrupt failed\n"); + + return ret; +} + static int rsnd_ssi_pio_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -389,12 +409,50 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .name = "ssi (pio)", + .probe = rsnd_ssi_pio_probe, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_pio_start, .stop = rsnd_ssi_pio_stop, }; +static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int dma_id = ssi->info->dma_id; + int is_play; + int ret; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, ssi); + else + is_play = rsnd_ssi_is_play(&ssi->mod); + + ret = rsnd_dma_init( + priv, rsnd_mod_to_dma(mod), + is_play, + dma_id); + + if (ret < 0) + dev_err(dev, "SSI DMA failed\n"); + + return ret; +} + +static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + static int rsnd_ssi_dma_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -436,6 +494,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .name = "ssi (dma)", + .probe = rsnd_ssi_dma_probe, + .remove = rsnd_ssi_dma_remove, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_dma_start, @@ -538,7 +598,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct clk *clk; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; - int i, nr, ret; + int i, nr; /* * init SSI @@ -566,48 +626,10 @@ int rsnd_ssi_probe(struct platform_device *pdev, ssi->clk = clk; ops = &rsnd_ssi_non_ops; - - /* - * SSI DMA case - */ - if (pinfo->dma_id > 0) { - int is_play; - - if (info->dai_info) - is_play = rsnd_info_is_playback(priv, ssi); - else - is_play = rsnd_ssi_is_play(&ssi->mod); - - ret = rsnd_dma_init( - priv, rsnd_mod_to_dma(&ssi->mod), - is_play, - pinfo->dma_id); - if (ret < 0) - dev_info(dev, "SSI DMA failed. try PIO transter\n"); - else - ops = &rsnd_ssi_dma_ops; - - dev_dbg(dev, "SSI%d use DMA transfer\n", i); - } - - /* - * SSI PIO case - */ - if (!rsnd_ssi_dma_available(ssi) && - rsnd_ssi_pio_available(ssi)) { - ret = devm_request_irq(dev, pinfo->pio_irq, - &rsnd_ssi_pio_interrupt, - IRQF_SHARED, - dev_name(dev), ssi); - if (ret) { - dev_err(dev, "SSI request interrupt failed\n"); - return ret; - } - - ops = &rsnd_ssi_pio_ops; - - dev_dbg(dev, "SSI%d use PIO transfer\n", i); - } + if (pinfo->dma_id > 0) + ops = &rsnd_ssi_dma_ops; + else if (rsnd_ssi_pio_available(ssi)) + ops = &rsnd_ssi_pio_ops; rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); @@ -620,12 +642,4 @@ int rsnd_ssi_probe(struct platform_device *pdev, void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_ssi *ssi; - int i; - - for_each_rsnd_ssi(ssi, priv, i) { - if (rsnd_ssi_dma_available(ssi)) - rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); - } - } -- cgit v0.10.2 From 4076220767416b8b65009dd57eeb317c38d41baa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:03 -0800 Subject: ASoC: rsnd: nothing to do on rsnd_dai_remove() rsnd_dai_remove() called rsnd_path_exit(), but these memory will be cleaned automatically. Because it is created by devm_kzalloc(). nothing to do on rsnd_dai_remove() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index e8e585d..92e155b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -348,14 +348,6 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, return 0; } -static int rsnd_dai_disconnect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) -{ - io->mod[mod->type] = NULL; - mod->io = NULL; - - return 0; -} - int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) { int id = rdai - priv->rdai; @@ -628,26 +620,6 @@ static int rsnd_path_init(struct rsnd_priv *priv, return ret; } -static int rsnd_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod; - int ret = 0, i; - - /* - * remove all mod from rdai - */ - for (i = 0; i < RSND_MOD_MAX; i++) { - mod = io->mod[i]; - if (!mod) - continue; - ret |= rsnd_dai_disconnect(mod, io); - } - - return ret; -} - static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { @@ -739,14 +711,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, static void rsnd_dai_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_dai *rdai; - int i; - - for (i = 0; i < rsnd_rdai_nr(priv); i++) { - rdai = rsnd_dai_get(priv, i); - rsnd_path_exit(priv, rdai, &rdai->playback); - rsnd_path_exit(priv, rdai, &rdai->capture); - } } /* -- cgit v0.10.2 From 9524be0e761edd9f3c020344677d914ed249d010 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:11 -0800 Subject: ASoC: rsnd: remove all rsnd_xxx_remove() Now, rsnd_xxx_remove() do nothing. remove these Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 8df00ac..953f1cc 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -454,8 +454,3 @@ int rsnd_adg_probe(struct platform_device *pdev, return 0; } - -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 92e155b..ceb4e8b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -708,11 +708,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, return 0; } -static void rsnd_dai_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} - /* * pcm ops */ @@ -902,15 +897,6 @@ static int rsnd_remove(struct platform_device *pdev) return ret; } - /* - * remove each module - */ - rsnd_ssi_remove(pdev, priv); - rsnd_adg_remove(pdev, priv); - rsnd_scu_remove(pdev, priv); - rsnd_dai_remove(pdev, priv); - rsnd_gen_remove(pdev, priv); - return 0; } diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 92d1bc9..9094970 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -385,8 +385,3 @@ int rsnd_gen_probe(struct platform_device *pdev, return ret; } - -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index db20b37..878dc6e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -261,8 +261,6 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); */ int rsnd_gen_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); @@ -276,8 +274,6 @@ int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv); int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, @@ -353,8 +349,6 @@ struct rsnd_priv { */ int rsnd_scu_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, @@ -373,8 +367,6 @@ int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, */ int rsnd_ssi_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_ssi_remove(struct platform_device *pdev, - struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 40250ac..3526a5c 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -680,8 +680,3 @@ int rsnd_scu_probe(struct platform_device *pdev, return 0; } - -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0f3eeac..45f828d 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -638,8 +638,3 @@ int rsnd_ssi_probe(struct platform_device *pdev, return 0; } - -void rsnd_ssi_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} -- cgit v0.10.2 From ba9c949f797aa3af56303445812a452144c61c35 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:21 -0800 Subject: ASoC: rsnd: rename scu to src R-Car sound has SCU unit which has SRC/CTU/MIX/DVC, and current rsnd driver has scu.c and scu module. Current scu.c has SRC support only. My first concept was control these feature on scu.c but, it become difficult and un-understandable now. This patch rename scu to src Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 1d8c683..34a3c02 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -55,14 +55,18 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ -#define RSND_SCU(rate, _dma_id) \ +#define RSND_SRC(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } -#define RSND_SCU_SET(rate, _dma_id) \ +#define RSND_SRC_SET(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } -#define RSND_SCU_UNUSED \ +#define RSND_SRC_UNUSED \ { .flags = 0, .convert_rate = 0, .dma_id = 0, } -struct rsnd_scu_platform_info { +#define rsnd_scu_platform_info rsnd_src_platform_info +#define src_info scu_info +#define src_info_nr scu_info_nr + +struct rsnd_src_platform_info { u32 flags; u32 convert_rate; /* sampling rate convert */ int dma_id; /* for Gen2 SCU */ @@ -70,7 +74,7 @@ struct rsnd_scu_platform_info { struct rsnd_dai_path_info { struct rsnd_ssi_platform_info *ssi; - struct rsnd_scu_platform_info *scu; + struct rsnd_src_platform_info *src; }; struct rsnd_dai_platform_info { @@ -93,8 +97,8 @@ struct rcar_snd_info { u32 flags; struct rsnd_ssi_platform_info *ssi_info; int ssi_info_nr; - struct rsnd_scu_platform_info *scu_info; - int scu_info_nr; + struct rsnd_src_platform_info *src_info; + int src_info_nr; struct rsnd_dai_platform_info *dai_info; int dai_info_nr; int (*start)(int id); diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 0ff492d..7d0051c 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,2 +1,2 @@ -snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o +snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ceb4e8b..6a1b45d 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -73,13 +73,13 @@ * | +- ssi[2] * | ... * | - * | ** these control scu + * | ** these control src * | - * +- scu + * +- src * | - * +- scu[0] - * +- scu[1] - * +- scu[2] + * +- src[0] + * +- src[1] + * +- src[2] * ... * * @@ -572,7 +572,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai_platform_info *dai_info = rdai->info; int ret; int ssi_id = -1; - int scu_id = -1; + int src_id = -1; /* * Gen1 is created by SRU/SSI, and this SRU is base module of @@ -587,8 +587,8 @@ static int rsnd_path_init(struct rsnd_priv *priv, if (dai_info) { if (rsnd_is_enable_path(io, ssi)) ssi_id = rsnd_info_id(priv, io, ssi); - if (rsnd_is_enable_path(io, scu)) - scu_id = rsnd_info_id(priv, io, scu); + if (rsnd_is_enable_path(io, src)) + src_id = rsnd_info_id(priv, io, src); } else { /* get SSI's ID */ mod = rsnd_ssi_mod_get_frm_dai(priv, @@ -596,14 +596,14 @@ static int rsnd_path_init(struct rsnd_priv *priv, rsnd_dai_is_play(rdai, io)); if (!mod) return 0; - ssi_id = scu_id = rsnd_mod_id(mod); + ssi_id = src_id = rsnd_mod_id(mod); } ret = 0; - /* SCU */ - if (scu_id >= 0) { - mod = rsnd_scu_mod_get(priv, scu_id); + /* SRC */ + if (src_id >= 0) { + mod = rsnd_src_mod_get(priv, src_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; @@ -806,7 +806,7 @@ static int rsnd_probe(struct platform_device *pdev) struct rsnd_priv *priv) = { rsnd_gen_probe, rsnd_ssi_probe, - rsnd_scu_probe, + rsnd_src_probe, rsnd_adg_probe, rsnd_dai_probe, }; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 878dc6e..c46e0af 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -160,7 +160,7 @@ void rsnd_dma_quit(struct rsnd_priv *priv, * R-Car sound mod */ enum rsnd_mod_type { - RSND_MOD_SCU = 0, + RSND_MOD_SRC = 0, RSND_MOD_SSI, RSND_MOD_MAX, }; @@ -224,7 +224,7 @@ struct rsnd_dai_stream { int next_period_byte; }; #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) -#define rsnd_io_to_mod_scu(io) ((io)->mod[RSND_MOD_SCU]) +#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -302,10 +302,10 @@ struct rsnd_priv { void *gen; /* - * below value will be filled on rsnd_scu_probe() + * below value will be filled on rsnd_src_probe() */ - void *scu; - int scu_nr; + void *src; + int src_nr; /* * below value will be filled on rsnd_adg_probe() @@ -345,22 +345,22 @@ struct rsnd_priv { }) /* - * R-Car SCU + * R-Car SRC */ -int rsnd_scu_probe(struct platform_device *pdev, +int rsnd_src_probe(struct platform_device *pdev, struct rsnd_priv *priv); -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); -int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -#define rsnd_scu_nr(priv) ((priv)->scu_nr) +#define rsnd_src_nr(priv) ((priv)->src_nr) /* * R-Car SSI diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c deleted file mode 100644 index 3526a5c..0000000 --- a/sound/soc/sh/rcar/scu.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Renesas R-Car SCU support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Kuninori Morimoto - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include "rsnd.h" - -struct rsnd_scu { - struct rsnd_scu_platform_info *info; /* rcar_snd.h */ - struct rsnd_mod mod; - struct clk *clk; -}; - -#define RSND_SCU_NAME_SIZE 16 - -/* - * ADINR - */ -#define OTBL_24 (0 << 16) -#define OTBL_22 (2 << 16) -#define OTBL_20 (4 << 16) -#define OTBL_18 (6 << 16) -#define OTBL_16 (8 << 16) - -#define rsnd_scu_mode_flags(p) ((p)->info->flags) -#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) -#define rsnd_mod_to_scu(_mod) \ - container_of((_mod), struct rsnd_scu, mod) -#define rsnd_scu_hpbif_is_enable(scu) \ - (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) -#define rsnd_scu_dma_available(scu) \ - rsnd_dma_available(rsnd_mod_to_dma(&(scu)->mod)) - -#define for_each_rsnd_scu(pos, priv, i) \ - for ((i) = 0; \ - ((i) < rsnd_scu_nr(priv)) && \ - ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ - i++) - - -/* - * image of SRC (Sampling Rate Converter) - * - * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ - * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | - * 44.1kHz <-> +-----+ +-----+ +-------+ - * ... - * - */ - -/* - * scu.c is caring... - * - * Gen1 - * - * [mem] -> [SRU] -> [SSI] - * |--------| - * - * Gen2 - * - * [mem] -> [SCU] -> [SSIU] -> [SSI] - * |-----------------| - */ - -/* - * How to use SRC bypass mode for debugging - * - * SRC has bypass mode, and it is useful for debugging. - * In Gen2 case, - * SRCm_MODE controls whether SRC is used or not - * SSI_MODE0 controls whether SSIU which receives SRC data - * is used or not. - * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, - * but SRC bypass mode needs SSI_MODE0 only. - * - * This driver request - * struct rsnd_scu_platform_info { - * u32 flags; - * u32 convert_rate; - * } - * - * rsnd_scu_hpbif_is_enable() will be true - * if flags had RSND_SCU_USE_HPBIF, - * and it controls whether SSIU is used or not. - * - * rsnd_scu_convert_rate() indicates - * above convert_rate, and it controls - * whether SRC is used or not. - * - * ex) doesn't use SRC - * struct rsnd_scu_platform_info info = { - * .flags = 0, - * .convert_rate = 0, - * }; - * - * ex) uses SRC - * struct rsnd_scu_platform_info info = { - * .flags = RSND_SCU_USE_HPBIF, - * .convert_rate = 48000, - * }; - * - * ex) uses SRC bypass mode - * struct rsnd_scu_platform_info info = { - * .flags = RSND_SCU_USE_HPBIF, - * .convert_rate = 0, - * }; - * - */ - -/* - * Gen1/Gen2 common functions - */ -int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); - struct rsnd_mod *scu_mod = rsnd_io_to_mod_scu(io); - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - int ssi_id = rsnd_mod_id(ssi_mod); - int has_scu = 0; - - /* - * SSI_MODE0 - */ - if (info->dai_info) { - has_scu = !!scu_mod; - } else { - struct rsnd_scu *scu = rsnd_mod_to_scu(scu_mod); - has_scu = rsnd_scu_hpbif_is_enable(scu); - } - - rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), - has_scu ? 0 : (1 << ssi_id)); - - /* - * SSI_MODE1 - */ - if (rsnd_ssi_is_pin_sharing(ssi_mod)) { - int shift = -1; - switch (ssi_id) { - case 1: - shift = 0; - break; - case 2: - shift = 2; - break; - case 4: - shift = 16; - break; - } - - if (shift >= 0) - rsnd_mod_bset(ssi_mod, SSI_MODE1, - 0x3 << shift, - rsnd_dai_is_clk_master(rdai) ? - 0x2 << shift : 0x1 << shift); - } - - return 0; -} - -int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); - - /* enable PIO interrupt if Gen2 */ - if (rsnd_is_gen2(priv)) - rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); - - return 0; -} - -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_dai_stream *io, - struct snd_pcm_runtime *runtime) -{ - struct rsnd_scu *scu; - unsigned int rate; - - scu = rsnd_mod_to_scu(rsnd_io_to_mod_scu(io)); - - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_scu_convert_rate(scu); - if (!rate) - rate = runtime->rate; - - return rate; -} - -static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 adinr = runtime->channels; - u32 fsrate = 0; - - if (convert_rate) - fsrate = 0x0400000 / convert_rate * runtime->rate; - - /* set/clear soft reset */ - rsnd_mod_write(mod, SRC_SWRSR, 0); - rsnd_mod_write(mod, SRC_SWRSR, 1); - - /* - * Initialize the operation of the SRC internal circuits - * see rsnd_scu_start() - */ - rsnd_mod_write(mod, SRC_SRCIR, 1); - - /* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); - - /* Enable the initial value of IFS */ - if (fsrate) { - rsnd_mod_write(mod, SRC_IFSCR, 1); - - /* Set initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSVR, fsrate); - } - - /* use DMA transfer */ - rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); - - return 0; -} - -static int rsnd_scu_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - clk_enable(scu->clk); - - return 0; -} - -static int rsnd_scu_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - clk_disable(scu->clk); - - return 0; -} - -static int rsnd_scu_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - /* - * Cancel the initialization and operate the SRC function - * see rsnd_scu_set_convert_rate() - */ - rsnd_mod_write(mod, SRC_SRCIR, 0); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); - - return 0; -} - - -static int rsnd_scu_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); - - return 0; -} - -static struct rsnd_mod_ops rsnd_scu_non_ops = { - .name = "scu (non)", -}; - -/* - * Gen1 functions - */ -static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct scu_route_config { - u32 mask; - int shift; - } routes[] = { - { 0xF, 0, }, /* 0 */ - { 0xF, 4, }, /* 1 */ - { 0xF, 8, }, /* 2 */ - { 0x7, 12, }, /* 3 */ - { 0x7, 16, }, /* 4 */ - { 0x7, 20, }, /* 5 */ - { 0x7, 24, }, /* 6 */ - { 0x3, 28, }, /* 7 */ - { 0x3, 30, }, /* 8 */ - }; - u32 mask; - u32 val; - int id; - - id = rsnd_mod_id(mod); - if (id < 0 || id >= ARRAY_SIZE(routes)) - return -EIO; - - /* - * SRC_ROUTE_SELECT - */ - val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; - val = val << routes[id].shift; - mask = routes[id].mask << routes[id].shift; - - rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); - - return 0; -} - -static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 mask; - u32 val; - int shift; - int id = rsnd_mod_id(mod); - int ret; - - /* - * SRC_TIMING_SELECT - */ - shift = (id % 4) * 8; - mask = 0x1F << shift; - - /* - * ADG is used as source clock if SRC was used, - * then, SSI WS is used as destination clock. - * SSI WS is used as source clock if SRC is not used - * (when playback, source/destination become reverse when capture) - */ - ret = 0; - if (convert_rate) { - /* use ADG */ - val = 0; - ret = rsnd_adg_set_convert_clk_gen1(priv, mod, - runtime->rate, - convert_rate); - } else if (8 == id) { - /* use SSI WS, but SRU8 is special */ - val = id << shift; - } else { - /* use SSI WS */ - val = (id + 1) << shift; - } - - if (ret < 0) - return ret; - - switch (id / 4) { - case 0: - rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); - break; - case 1: - rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); - break; - case 2: - rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); - break; - } - - return 0; -} - -static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_set_convert_rate(mod, rdai, io); - if (ret < 0) - return ret; - - /* Select SRC mode (fixed value) */ - rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); - - /* Set the restriction value of the FS ratio (98%) */ - rsnd_mod_write(mod, SRC_MNFSR, - rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); - - /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ - - return 0; -} - -static int rsnd_scu_init_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_init(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_src_set_route_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_rate_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_timing_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - return 0; -} - -static int rsnd_scu_start_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int id = rsnd_mod_id(mod); - - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - - return rsnd_scu_start(mod, rdai, io); -} - -static int rsnd_scu_stop_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int id = rsnd_mod_id(mod); - - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - - return rsnd_scu_stop(mod, rdai, io); -} - -static struct rsnd_mod_ops rsnd_scu_gen1_ops = { - .name = "sru (gen1)", - .init = rsnd_scu_init_gen1, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start_gen1, - .stop = rsnd_scu_stop_gen1, -}; - -/* - * Gen2 functions - */ -static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_set_convert_rate(mod, rdai, io); - if (ret < 0) - return ret; - - rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); - rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); - - rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); - - rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); - rsnd_mod_write(mod, SRC_BSISR, 0x00100060); - - return 0; -} - -static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - int ret; - - if (convert_rate) - ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, - runtime->rate, - convert_rate); - else - ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); - - return ret; -} - -static int rsnd_scu_probe_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); - struct device *dev = rsnd_priv_to_dev(priv); - int ret; - int is_play; - - if (info->dai_info) - is_play = rsnd_info_is_playback(priv, scu); - else - is_play = rsnd_ssi_is_play(ssi); - - ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(mod), - is_play, - scu->info->dma_id); - if (ret < 0) - dev_err(dev, "SCU DMA failed\n"); - - return ret; -} - -static int rsnd_scu_remove_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); - - return 0; -} - -static int rsnd_scu_init_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_init(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_rate_gen2(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_timing_gen2(mod, rdai, io); - if (ret < 0) - return ret; - - return 0; -} - -static int rsnd_scu_start_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - rsnd_dma_start(rsnd_mod_to_dma(&scu->mod)); - - rsnd_mod_write(mod, SSI_CTRL, 0x1); - rsnd_mod_write(mod, SRC_CTRL, 0x11); - - return rsnd_scu_start(mod, rdai, io); -} - -static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - rsnd_mod_write(mod, SSI_CTRL, 0); - rsnd_mod_write(mod, SRC_CTRL, 0); - - rsnd_dma_stop(rsnd_mod_to_dma(&scu->mod)); - - return rsnd_scu_stop(mod, rdai, io); -} - -static struct rsnd_mod_ops rsnd_scu_gen2_ops = { - .name = "scu (gen2)", - .probe = rsnd_scu_probe_gen2, - .remove = rsnd_scu_remove_gen2, - .init = rsnd_scu_init_gen2, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start_gen2, - .stop = rsnd_scu_stop_gen2, -}; - -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) -{ - if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) - id = 0; - - return &((struct rsnd_scu *)(priv->scu) + id)->mod; -} - -int rsnd_scu_probe(struct platform_device *pdev, - struct rsnd_priv *priv) -{ - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_scu *scu; - struct rsnd_mod_ops *ops; - struct clk *clk; - char name[RSND_SCU_NAME_SIZE]; - int i, nr; - - /* - * init SCU - */ - nr = info->scu_info_nr; - if (!nr) - return 0; - - scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); - if (!scu) { - dev_err(dev, "SCU allocate failed\n"); - return -ENOMEM; - } - - priv->scu_nr = nr; - priv->scu = scu; - - for_each_rsnd_scu(scu, priv, i) { - snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i); - - clk = devm_clk_get(dev, name); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - scu->info = &info->scu_info[i]; - scu->clk = clk; - - ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(scu)) { - if (rsnd_is_gen1(priv)) - ops = &rsnd_scu_gen1_ops; - if (rsnd_is_gen2(priv)) - ops = &rsnd_scu_gen2_ops; - } - - rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); - - dev_dbg(dev, "SCU%d probed\n", i); - } - - return 0; -} diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c new file mode 100644 index 0000000..ea6a214 --- /dev/null +++ b/sound/soc/sh/rcar/src.c @@ -0,0 +1,687 @@ +/* + * Renesas R-Car SRC support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Kuninori Morimoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "rsnd.h" + +struct rsnd_src { + struct rsnd_src_platform_info *info; /* rcar_snd.h */ + struct rsnd_mod mod; + struct clk *clk; +}; + +#define RSND_SRC_NAME_SIZE 16 + +/* + * ADINR + */ +#define OTBL_24 (0 << 16) +#define OTBL_22 (2 << 16) +#define OTBL_20 (4 << 16) +#define OTBL_18 (6 << 16) +#define OTBL_16 (8 << 16) + +#define rsnd_src_mode_flags(p) ((p)->info->flags) +#define rsnd_src_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_mod_to_src(_mod) \ + container_of((_mod), struct rsnd_src, mod) +#define rsnd_src_hpbif_is_enable(src) \ + (rsnd_src_mode_flags(src) & RSND_SCU_USE_HPBIF) +#define rsnd_src_dma_available(src) \ + rsnd_dma_available(rsnd_mod_to_dma(&(src)->mod)) + +#define for_each_rsnd_src(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_src_nr(priv)) && \ + ((pos) = (struct rsnd_src *)(priv)->src + i); \ + i++) + + +/* + * image of SRC (Sampling Rate Converter) + * + * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ + * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | + * 44.1kHz <-> +-----+ +-----+ +-------+ + * ... + * + */ + +/* + * src.c is caring... + * + * Gen1 + * + * [mem] -> [SRU] -> [SSI] + * |--------| + * + * Gen2 + * + * [mem] -> [SRC] -> [SSIU] -> [SSI] + * |-----------------| + */ + +/* + * How to use SRC bypass mode for debugging + * + * SRC has bypass mode, and it is useful for debugging. + * In Gen2 case, + * SRCm_MODE controls whether SRC is used or not + * SSI_MODE0 controls whether SSIU which receives SRC data + * is used or not. + * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, + * but SRC bypass mode needs SSI_MODE0 only. + * + * This driver request + * struct rsnd_src_platform_info { + * u32 flags; + * u32 convert_rate; + * } + * + * rsnd_src_hpbif_is_enable() will be true + * if flags had RSND_SRC_USE_HPBIF, + * and it controls whether SSIU is used or not. + * + * rsnd_src_convert_rate() indicates + * above convert_rate, and it controls + * whether SRC is used or not. + * + * ex) doesn't use SRC + * struct rsnd_src_platform_info info = { + * .flags = 0, + * .convert_rate = 0, + * }; + * + * ex) uses SRC + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 48000, + * }; + * + * ex) uses SRC bypass mode + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 0, + * }; + * + */ + +/* + * Gen1/Gen2 common functions + */ +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + int ssi_id = rsnd_mod_id(ssi_mod); + int has_src = 0; + + /* + * SSI_MODE0 + */ + if (info->dai_info) { + has_src = !!src_mod; + } else { + struct rsnd_src *src = rsnd_mod_to_src(src_mod); + has_src = rsnd_src_hpbif_is_enable(src); + } + + rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), + has_src ? 0 : (1 << ssi_id)); + + /* + * SSI_MODE1 + */ + if (rsnd_ssi_is_pin_sharing(ssi_mod)) { + int shift = -1; + switch (ssi_id) { + case 1: + shift = 0; + break; + case 2: + shift = 2; + break; + case 4: + shift = 16; + break; + } + + if (shift >= 0) + rsnd_mod_bset(ssi_mod, SSI_MODE1, + 0x3 << shift, + rsnd_dai_is_clk_master(rdai) ? + 0x2 << shift : 0x1 << shift); + } + + return 0; +} + +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + + /* enable PIO interrupt if Gen2 */ + if (rsnd_is_gen2(priv)) + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); + + return 0; +} + +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_dai_stream *io, + struct snd_pcm_runtime *runtime) +{ + struct rsnd_src *src; + unsigned int rate; + + src = rsnd_mod_to_src(rsnd_io_to_mod_src(io)); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_src_convert_rate(src); + if (!rate) + rate = runtime->rate; + + return rate; +} + +static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 adinr = runtime->channels; + u32 fsrate = 0; + + if (convert_rate) + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* set/clear soft reset */ + rsnd_mod_write(mod, SRC_SWRSR, 0); + rsnd_mod_write(mod, SRC_SWRSR, 1); + + /* + * Initialize the operation of the SRC internal circuits + * see rsnd_src_start() + */ + rsnd_mod_write(mod, SRC_SRCIR, 1); + + /* Set channel number and output bit length */ + switch (runtime->sample_bits) { + case 16: + adinr |= OTBL_16; + break; + case 32: + adinr |= OTBL_24; + break; + default: + return -EIO; + } + rsnd_mod_write(mod, SRC_ADINR, adinr); + + /* Enable the initial value of IFS */ + if (fsrate) { + rsnd_mod_write(mod, SRC_IFSCR, 1); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + } + + /* use DMA transfer */ + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + + return 0; +} + +static int rsnd_src_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_enable(src->clk); + + return 0; +} + +static int rsnd_src_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_disable(src->clk); + + return 0; +} + +static int rsnd_src_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + /* + * Cancel the initialization and operate the SRC function + * see rsnd_src_set_convert_rate() + */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; +} + + +static int rsnd_src_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); + + return 0; +} + +static struct rsnd_mod_ops rsnd_src_non_ops = { + .name = "src (non)", +}; + +/* + * Gen1 functions + */ +static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct src_route_config { + u32 mask; + int shift; + } routes[] = { + { 0xF, 0, }, /* 0 */ + { 0xF, 4, }, /* 1 */ + { 0xF, 8, }, /* 2 */ + { 0x7, 12, }, /* 3 */ + { 0x7, 16, }, /* 4 */ + { 0x7, 20, }, /* 5 */ + { 0x7, 24, }, /* 6 */ + { 0x3, 28, }, /* 7 */ + { 0x3, 30, }, /* 8 */ + }; + u32 mask; + u32 val; + int id; + + id = rsnd_mod_id(mod); + if (id < 0 || id >= ARRAY_SIZE(routes)) + return -EIO; + + /* + * SRC_ROUTE_SELECT + */ + val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; + val = val << routes[id].shift; + mask = routes[id].mask << routes[id].shift; + + rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 mask; + u32 val; + int shift; + int id = rsnd_mod_id(mod); + int ret; + + /* + * SRC_TIMING_SELECT + */ + shift = (id % 4) * 8; + mask = 0x1F << shift; + + /* + * ADG is used as source clock if SRC was used, + * then, SSI WS is used as destination clock. + * SSI WS is used as source clock if SRC is not used + * (when playback, source/destination become reverse when capture) + */ + ret = 0; + if (convert_rate) { + /* use ADG */ + val = 0; + ret = rsnd_adg_set_convert_clk_gen1(priv, mod, + runtime->rate, + convert_rate); + } else if (8 == id) { + /* use SSI WS, but SRU8 is special */ + val = id << shift; + } else { + /* use SSI WS */ + val = (id + 1) << shift; + } + + if (ret < 0) + return ret; + + switch (id / 4) { + case 0: + rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); + break; + case 1: + rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); + break; + case 2: + rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); + break; + } + + return 0; +} + +static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + /* Select SRC mode (fixed value) */ + rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); + + /* Set the restriction value of the FS ratio (98%) */ + rsnd_mod_write(mod, SRC_MNFSR, + rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); + + /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ + + return 0; +} + +static int rsnd_src_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_route_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen1_ops = { + .name = "sru (gen1)", + .init = rsnd_src_init_gen1, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen1, + .stop = rsnd_src_stop_gen1, +}; + +/* + * Gen2 functions + */ +static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + + rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); + + rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); + rsnd_mod_write(mod, SRC_BSISR, 0x00100060); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + int ret; + + if (convert_rate) + ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, + runtime->rate, + convert_rate); + else + ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); + + return ret; +} + +static int rsnd_src_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); + struct device *dev = rsnd_priv_to_dev(priv); + int ret; + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, src); + else + is_play = rsnd_ssi_is_play(ssi); + + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(mod), + is_play, + src->info->dma_id); + if (ret < 0) + dev_err(dev, "SRC DMA failed\n"); + + return ret; +} + +static int rsnd_src_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + +static int rsnd_src_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); + + rsnd_mod_write(mod, SSI_CTRL, 0x1); + rsnd_mod_write(mod, SRC_CTRL, 0x11); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_mod_write(mod, SSI_CTRL, 0); + rsnd_mod_write(mod, SRC_CTRL, 0); + + rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen2_ops = { + .name = "src (gen2)", + .probe = rsnd_src_probe_gen2, + .remove = rsnd_src_remove_gen2, + .init = rsnd_src_init_gen2, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen2, + .stop = rsnd_src_stop_gen2, +}; + +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) +{ + if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) + id = 0; + + return &((struct rsnd_src *)(priv->src) + id)->mod; +} + +int rsnd_src_probe(struct platform_device *pdev, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_src *src; + struct rsnd_mod_ops *ops; + struct clk *clk; + char name[RSND_SRC_NAME_SIZE]; + int i, nr; + + /* + * init SRC + */ + nr = info->src_info_nr; + if (!nr) + return 0; + + src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); + if (!src) { + dev_err(dev, "SRC allocate failed\n"); + return -ENOMEM; + } + + priv->src_nr = nr; + priv->src = src; + + for_each_rsnd_src(src, priv, i) { + snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i); + + clk = devm_clk_get(dev, name); + if (IS_ERR(clk)) { + snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i); + clk = devm_clk_get(dev, name); + } + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + src->info = &info->src_info[i]; + src->clk = clk; + + ops = &rsnd_src_non_ops; + if (rsnd_src_hpbif_is_enable(src)) { + if (rsnd_is_gen1(priv)) + ops = &rsnd_src_gen1_ops; + if (rsnd_is_gen2(priv)) + ops = &rsnd_src_gen2_ops; + } + + rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); + + dev_dbg(dev, "SRC%d probed\n", i); + } + + return 0; +} diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 45f828d..633b23d 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -121,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; - unsigned int rate = rsnd_scu_get_ssi_rate(priv, io, runtime); + unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG @@ -287,7 +287,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ - rsnd_scu_ssi_mode_init(mod, rdai, io); + rsnd_src_ssi_mode_init(mod, rdai, io); return 0; } @@ -387,7 +387,7 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - rsnd_scu_enable_ssi_irq(mod, rdai, io); + rsnd_src_enable_ssi_irq(mod, rdai, io); rsnd_ssi_hw_start(ssi, rdai, io); -- cgit v0.10.2 From 81985bd63f6f1711035aa8d97caf2fb203250a95 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 20:32:43 -0800 Subject: ASoC: simple-card: tidyup cpu/codec dai_fmt settings for non-DT 30d0341e7da0c012f64fb290dd1153360fb49a8d (ASoC: simple-card: simplify the daifmt code) simplify cpu/codec dai_fmt which consists from dai specific format + common format. But, it didn't care about non-DT case. This patch fixes it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 034a2b7..7cabcc5 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -307,6 +307,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) sizeof(priv->cpu_dai)); memcpy(&priv->codec_dai, &cinfo->codec_dai, sizeof(priv->codec_dai)); + + priv->cpu_dai.fmt |= cinfo->daifmt; + priv->codec_dai.fmt |= cinfo->daifmt; } /* -- cgit v0.10.2 From e291fd20ef0870ed527470ca9c2402ba6f44d31c Mon Sep 17 00:00:00 2001 From: Barry Song Date: Wed, 5 Mar 2014 14:55:02 +0800 Subject: pinctrl: sirf: fix kernel panic in gpio_lock_as_irq commit 655dada6277991 causes kernel panic, this patch fixes it. [ 1.197816] [ffffffee] *pgd=0d7fd821, *pte=00000000, *ppte=00000000 [ 1.204070] Internal error: Oops: 17 [#1] PREEMPT SMP ARM [ 1.209447] Modules linked in: [ 1.212490] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.14.0-rc1 #3 [ 1.218737] task: cd03c000 ti: cd040000 task.ti: cd040000 [ 1.224127] PC is at gpiod_lock_as_irq+0xc/0x64 [ 1.228634] LR is at sirfsoc_gpio_irq_startup+0x18/0x44 [ 1.233842] pc : [] lr : [] psr: a0000193 [ 1.233842] sp : cd041d30 ip : 00000000 fp : 00000000 [ 1.245296] r10: 00000000 r9 : cd023db4 r8 : 60000113 [ 1.250505] r7 : 0000003e r6 : cd023dd4 r5 : c06bfa54 r4 : cd023d80 [ 1.257014] r3 : 00000020 r2 : 00000000 r1 : ffffffea r0 : ffffffea [ 1.263526] Flags: NzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel [ 1.270903] Control: 10c53c7d Table: 00004059 DAC: 00000015 [ 1.276631] Process swapper/0 (pid: 1, stack limit = 0xcd040240) [ 1.282620] Stack: (0xcd041d30 to 0xcd042000) [ 1.286963] 1d20: cd023d80 c01d1c38 c01d1c20 cd023d80 [ 1.295124] 1d40: 00000001 c0068438 cd023d80 ccb6d880 cd023dd4 c0067044 0000718e c006719c [ 1.286963] 1d20: cd023d80 c01d1c38 c01d1c20 cd023d80 [ 1.295124] 1d40: 00000001 c0068438 cd023d80 ccb6d880 cd023dd4 c0067044 0000718e c006719c [ 1.295124] 1d40: 00000001 c0068438 cd023d80 ccb6d880 cd023dd4 c0067044 0000718e c006719c [ 1.303283] 1d60: 00000800 00000083 ccb6d880 cd023d80 c02b41d8 00000083 0000003e ccb7c410 [ 1.311442] 1d80: 00000000 c00671dc 00000083 0000003e c02b41d8 cd3dd5c0 0000003e ccb7c634 [ 1.319601] 1da0: cd040030 c00672a8 cd3dd5c0 ccb7c410 ccb6d340 ccb7c410 ccb6d340 cd3dd400 [ 1.327760] 1dc0: cd3dd410 c02b4434 ccb7c410 c01265a8 00000001 cd3dd410 c0687108 00000000 [ 1.335919] 1de0: c0687108 00000000 00000000 c0240170 c0240158 cd3dd410 c06c30d0 c023e8bc [ 1.344079] 1e00: c023e9d4 00000000 cd3dd410 c023e9d4 c0682150 c023cf88 cd003e98 cd2d50c4 [ 1.352238] 1e20: cd3dd410 cd3dd444 c06822f0 c023e768 cd3dd418 cd3dd410 c06822f0 c023de14 [ 1.360397] 1e40: cd3dd418 00000000 cd3dd410 c023c398 cd041e78 cd041ea8 cd3dd400 cd3dd410 [ 1.368556] 1e60: 00000083 00000000 cd3dd400 cd3dd410 00000083 000000c8 c04e00c8 c023fee8 [ 1.376715] 1e80: 00000000 cd041ea8 cd3dd400 00000001 00000083 c024048c c0435ef8 c0434dec [ 1.384874] 1ea0: c068da58 c04c6d04 c0682150 c0435ef8 ffffffff 00000000 00000000 c068da58 [ 1.393033] 1ec0: 00000020 00000000 00000000 00000000 c05dabb8 00000007 c068d640 c068d640 [ 1.401193] 1ee0: c04c247c c04c249c 00000000 c00088e8 cd004c00 c043bbb8 cd029180 c03812a0 [ 1.409352] 1f00: 00000000 00000000 60000113 c0673728 60000113 c0673728 00000000 00000000 [ 1.417511] 1f20: cd7fce01 c0390a54 00000065 c003a81c c049e8bc 00000007 cd7fce0e 00000007 [ 1.425670] 1f40: 00000000 c05dabb8 00000007 c068d640 c068d640 c04c050c c04e00c8 00000065 [ 1.433829] 1f60: c04e00c0 c04c0c54 00000007 00000007 c04c050c c037d8fc cd03c000 c004322c [ 1.441988] 1f80: c0662b40 0000d640 c03737c0 00000000 00000000 00000000 00000000 00000000 [ 1.450147] 1fa0: 00000000 c03737cc 00000000 c000e478 00000000 00000000 00000000 00000000 [ 1.458307] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 1.466467] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000 0002d481 05014092 [ 1.474640] [] (gpiod_lock_as_irq) from [] (sirfsoc_gpio_irq_startup+0x18/0x44) [ 1.483661] [] (sirfsoc_gpio_irq_startup) from [] (irq_startup+0x34/0x6c) [ 1.492163] [] (irq_startup) from [] (__setup_irq+0x450/0x4b8) [ 1.499714] [] (__setup_irq) from [] (request_threaded_irq+0xa8/0x128) [ 1.507960] [] (request_threaded_irq) from [] (request_any_context_irq+0x4c/0x7c) [ 1.517164] [] (request_any_context_irq) from [] (gpio_extcon_probe+0x144/0x1d4) [ 1.526279] [] (gpio_extcon_probe) from [] (platform_drv_probe+0x18/0x48) [ 1.534783] [] (platform_drv_probe) from [] (driver_probe_device+0x120/0x238) [ 1.543641] [] (driver_probe_device) from [] (bus_for_each_drv+0x58/0x8c) [ 1.552143] [] (bus_for_each_drv) from [] (device_attach+0x74/0x88) [ 1.560126] [] (device_attach) from [] (bus_probe_device+0x84/0xa8) [ 1.568113] [] (bus_probe_device) from [] (device_add+0x440/0x520) [ 1.576012] [] (device_add) from [] (platform_device_add+0xb4/0x214) [ 1.584084] [] (platform_device_add) from [] (platform_device_register_full+0xb8/0xdc) [ 1.593719] [] (platform_device_register_full) from [] (sirfsoc_init_late+0xec/0xf4) [ 1.603185] [] (sirfsoc_init_late) from [] (init_machine_late+0x20/0x28) [ 1.611603] [] (init_machine_late) from [] (do_one_initcall+0xf8/0x144) [ 1.619934] [] (do_one_initcall) from [] (kernel_init_freeable+0x13c/0x1dc) [ 1.628620] [] (kernel_init_freeable) from [] (kernel_init+0xc/0x118) Signed-off-by: Barry Song Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c index a0d6152..617a491 100644 --- a/drivers/pinctrl/sirf/pinctrl-sirf.c +++ b/drivers/pinctrl/sirf/pinctrl-sirf.c @@ -598,7 +598,7 @@ static unsigned int sirfsoc_gpio_irq_startup(struct irq_data *d) { struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d); - if (gpio_lock_as_irq(&bank->chip.gc, d->hwirq)) + if (gpio_lock_as_irq(&bank->chip.gc, d->hwirq % SIRFSOC_GPIO_BANK_SIZE)) dev_err(bank->chip.gc.dev, "unable to lock HW IRQ %lu for IRQ\n", d->hwirq); @@ -611,7 +611,7 @@ static void sirfsoc_gpio_irq_shutdown(struct irq_data *d) struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d); sirfsoc_gpio_irq_mask(d); - gpio_unlock_as_irq(&bank->chip.gc, d->hwirq); + gpio_unlock_as_irq(&bank->chip.gc, d->hwirq % SIRFSOC_GPIO_BANK_SIZE); } static struct irq_chip sirfsoc_irq_chip = { -- cgit v0.10.2 From c5eda4c1bf6214332c46fb2f4e7c42a85e5e5643 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Mar 2014 11:52:24 +0100 Subject: ALSA: hda - Add missing loopback merge path for AD1884/1984 codecs The mixer widget (NID 0x20) of AD1884 and AD1984 codecs isn't connected directly to the actual I/O paths but only via another mixer widget (NID 0x21). We need a similar fix as we did for AD1882. Cc: Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index df3652a..4989710 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1092,6 +1092,7 @@ static int patch_ad1884(struct hda_codec *codec) spec = codec->spec; spec->gen.mixer_nid = 0x20; + spec->gen.mixer_merge_nid = 0x21; spec->gen.beep_nid = 0x10; set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); -- cgit v0.10.2 From f3e9b59cb948e2328bc06635ad39572d5b7b4791 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Mar 2014 12:00:29 +0100 Subject: ALSA: hda - Use analog beep for Thinkpads with AD1984 codecs For making the driver behavior compatible with the earlier kernels, use the analog beep in the loopback path instead of the digital beep. Cc: Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 4989710..8ed0bcc 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1026,6 +1026,9 @@ static void ad1884_fixup_thinkpad(struct hda_codec *codec, spec->gen.keep_eapd_on = 1; spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; spec->eapd_nid = 0x12; + /* Analog PC Beeper - allow firmware/ACPI beeps */ + spec->beep_amp = HDA_COMPOSE_AMP_VAL(0x20, 3, 3, HDA_INPUT); + spec->gen.beep_nid = 0; /* no digital beep */ } } -- cgit v0.10.2 From e805ca8b0a9b6c91099c0eaa4b160a1196a4ae25 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Mar 2014 12:34:39 +0100 Subject: ALSA: usb-audio: Add quirk for Logitech Webcam C500 Logitech C500 (046d:0807) needs the same workaround like other Logitech Webcams. Cc: Signed-off-by: Takashi Iwai diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 44b0ba4..1bed780 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -883,6 +883,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, } break; + case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */ case USB_ID(0x046d, 0x0808): case USB_ID(0x046d, 0x0809): case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ -- cgit v0.10.2 From e1253be0ece1a95a02c7f5843194877471af8179 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 5 Mar 2014 08:44:23 -0500 Subject: NFSv4: nfs4_stateid_is_current should return 'true' for an invalid stateid When nfs4_set_rw_stateid() can fails by returning EIO to indicate that the stateid is completely invalid, then it makes no sense to have it trigger a retry of the READ or WRITE operation. Instead, we should just have it fall through and attempt a recovery. This fixes an infinite loop in which the client keeps replaying the same bad stateid back to the server. Reported-by: Andy Adamson Link: http://lkml.kernel.org/r/1393954269-3974-1-git-send-email-andros@netapp.com Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 44e088d..4ae8141 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4011,8 +4011,9 @@ static bool nfs4_stateid_is_current(nfs4_stateid *stateid, { nfs4_stateid current_stateid; - if (nfs4_set_rw_stateid(¤t_stateid, ctx, l_ctx, fmode)) - return false; + /* If the current stateid represents a lost lock, then exit */ + if (nfs4_set_rw_stateid(¤t_stateid, ctx, l_ctx, fmode) == -EIO) + return true; return nfs4_stateid_match(stateid, ¤t_stateid); } -- cgit v0.10.2 From 927864cd92aaad1d6285e3bb16e503caf3d6e27e Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 4 Mar 2014 13:12:03 -0500 Subject: NFSv4: Fix the return value of nfs4_select_rw_stateid In commit 5521abfdcf4d6 (NFSv4: Resend the READ/WRITE RPC call if a stateid change causes an error), we overloaded the return value of nfs4_select_rw_stateid() to cause it to return -EWOULDBLOCK if an RPC call is outstanding that would cause the NFSv4 lock or open stateid to change. That is all redundant when we actually copy the stateid used in the read/write RPC call that failed, and check that against the current stateid. It is doubly so, when we consider that in the NFSv4.1 case, we also set the stateid's seqid to the special value '0', which means 'match the current valid stateid'. Reported-by: Andy Adamson Link: http://lkml.kernel.org/r/1393954269-3974-1-git-send-email-andros@netapp.com Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e1a4721..0deb321 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -974,9 +974,6 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst, else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { nfs4_stateid_copy(dst, &lsp->ls_stateid); ret = 0; - smp_rmb(); - if (!list_empty(&lsp->ls_seqid.list)) - ret = -EWOULDBLOCK; } spin_unlock(&state->state_lock); nfs4_put_lock_state(lsp); @@ -984,10 +981,9 @@ out: return ret; } -static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) +static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) { const nfs4_stateid *src; - int ret; int seq; do { @@ -996,12 +992,7 @@ static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) if (test_bit(NFS_OPEN_STATE, &state->flags)) src = &state->open_stateid; nfs4_stateid_copy(dst, src); - ret = 0; - smp_rmb(); - if (!list_empty(&state->owner->so_seqid.list)) - ret = -EWOULDBLOCK; } while (read_seqretry(&state->seqlock, seq)); - return ret; } /* @@ -1026,7 +1017,8 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, * choose to use. */ goto out; - ret = nfs4_copy_open_stateid(dst, state); + nfs4_copy_open_stateid(dst, state); + ret = 0; out: if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41)) dst->seqid = 0; -- cgit v0.10.2 From 869a9d375dca601dde1dee1344f3d1d665505f19 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Tue, 4 Mar 2014 12:31:09 -0500 Subject: NFSv4.1 Fail data server I/O if stateid represents a lost lock Signed-off-by: Andy Adamson Link: http://lkml.kernel.org/r/1393954269-3974-1-git-send-email-andros@netapp.com Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 12c8132..b9a35c0 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -324,8 +324,9 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) &rdata->res.seq_res, task)) return; - nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context, - rdata->args.lock_context, FMODE_READ); + if (nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context, + rdata->args.lock_context, FMODE_READ) == -EIO) + rpc_exit(task, -EIO); /* lost lock, terminate I/O */ } static void filelayout_read_call_done(struct rpc_task *task, void *data) @@ -435,8 +436,9 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data) &wdata->res.seq_res, task)) return; - nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, - wdata->args.lock_context, FMODE_WRITE); + if (nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, + wdata->args.lock_context, FMODE_WRITE) == -EIO) + rpc_exit(task, -EIO); /* lost lock, terminate I/O */ } static void filelayout_write_call_done(struct rpc_task *task, void *data) -- cgit v0.10.2 From 0418dae1056d6091e9527b7158a3763f7aa92353 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 4 Mar 2014 13:48:16 -0500 Subject: NFSv4: Fail the truncate() if the lock/open stateid is invalid If the open stateid could not be recovered, or the file locks were lost, then we should fail the truncate() operation altogether. Reported-by: Andy Adamson Link: http://lkml.kernel.org/r/1393954269-3974-1-git-send-email-andros@netapp.com Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4ae8141..450bfed 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2398,13 +2398,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) { /* Use that stateid */ - } else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) { + } else if (truncate && state != NULL) { struct nfs_lockowner lockowner = { .l_owner = current->files, .l_pid = current->tgid, }; - nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, - &lockowner); + if (!nfs4_valid_open_stateid(state)) + return -EBADF; + if (nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, + &lockowner) == -EIO) + return -EBADF; } else nfs4_stateid_copy(&arg.stateid, &zero_stateid); -- cgit v0.10.2 From 07f2b6e0382ec4c59887d5954683f1a0b265574e Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 14 Feb 2014 11:58:41 -0500 Subject: dm thin: ensure user takes action to validate data and metadata consistency If a thin metadata operation fails the current transaction will abort, whereby causing potential for IO layers up the stack (e.g. filesystems) to have data loss. As such, set THIN_METADATA_NEEDS_CHECK_FLAG in the thin metadata's superblock which: 1) requires the user verify the thin metadata is consistent (e.g. use thin_check, etc) 2) suggests the user verify the thin data is consistent (e.g. use fsck) The only way to clear the superblock's THIN_METADATA_NEEDS_CHECK_FLAG is to run thin_repair. On metadata operation failure: abort current metadata transaction, set pool in read-only mode, and now set the needs_check flag. As part of this change, constraints are introduced or relaxed: * don't allow a pool to transition to write mode if needs_check is set * don't allow data or metadata space to be resized if needs_check is set * if a thin pool's metadata space is exhausted: the kernel will now force the user to take the pool offline for repair before the kernel will allow the metadata space to be extended. Also, update Documentation to include information about when the thin provisioning target commits metadata, how it handles metadata failures and running out of space. Signed-off-by: Mike Snitzer Signed-off-by: Joe Thornber diff --git a/Documentation/device-mapper/cache.txt b/Documentation/device-mapper/cache.txt index e6b72d3..68c0f51 100644 --- a/Documentation/device-mapper/cache.txt +++ b/Documentation/device-mapper/cache.txt @@ -124,12 +124,11 @@ the default being 204800 sectors (or 100MB). Updating on-disk metadata ------------------------- -On-disk metadata is committed every time a REQ_SYNC or REQ_FUA bio is -written. If no such requests are made then commits will occur every -second. This means the cache behaves like a physical disk that has a -write cache (the same is true of the thin-provisioning target). If -power is lost you may lose some recent writes. The metadata should -always be consistent in spite of any crash. +On-disk metadata is committed every time a FLUSH or FUA bio is written. +If no such requests are made then commits will occur every second. This +means the cache behaves like a physical disk that has a volatile write +cache. If power is lost you may lose some recent writes. The metadata +should always be consistent in spite of any crash. The 'dirty' state for a cache block changes far too frequently for us to keep updating it on the fly. So we treat it as a hint. In normal diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt index 8a7a3d4..3b34b4f 100644 --- a/Documentation/device-mapper/thin-provisioning.txt +++ b/Documentation/device-mapper/thin-provisioning.txt @@ -116,6 +116,35 @@ Resuming a device with a new table itself triggers an event so the userspace daemon can use this to detect a situation where a new table already exceeds the threshold. +A low water mark for the metadata device is maintained in the kernel and +will trigger a dm event if free space on the metadata device drops below +it. + +Updating on-disk metadata +------------------------- + +On-disk metadata is committed every time a FLUSH or FUA bio is written. +If no such requests are made then commits will occur every second. This +means the thin-provisioning target behaves like a physical disk that has +a volatile write cache. If power is lost you may lose some recent +writes. The metadata should always be consistent in spite of any crash. + +If data space is exhausted the pool will either error or queue IO +according to the configuration (see: error_if_no_space). If metadata +space is exhausted or a metadata operation fails: the pool will error IO +until the pool is taken offline and repair is performed to 1) fix any +potential inconsistencies and 2) clear the flag that imposes repair. +Once the pool's metadata device is repaired it may be resized, which +will allow the pool to return to normal operation. Note that if a pool +is flagged as needing repair, the pool's data and metadata devices +cannot be resized until repair is performed. It should also be noted +that when the pool's metadata space is exhausted the current metadata +transaction is aborted. Given that the pool will cache IO whose +completion may have already been acknowledged to upper IO layers +(e.g. filesystem) it is strongly suggested that consistency checks +(e.g. fsck) be performed on those layers when repair of the pool is +required. + Thin provisioning ----------------- diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index baa87ff..fb9efc8 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -76,7 +76,7 @@ #define THIN_SUPERBLOCK_MAGIC 27022010 #define THIN_SUPERBLOCK_LOCATION 0 -#define THIN_VERSION 1 +#define THIN_VERSION 2 #define THIN_METADATA_CACHE_SIZE 64 #define SECTOR_TO_BLOCK_SHIFT 3 @@ -1755,3 +1755,38 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, return r; } + +int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd) +{ + int r; + struct dm_block *sblock; + struct thin_disk_superblock *disk_super; + + down_write(&pmd->root_lock); + pmd->flags |= THIN_METADATA_NEEDS_CHECK_FLAG; + + r = superblock_lock(pmd, &sblock); + if (r) { + DMERR("couldn't read superblock"); + goto out; + } + + disk_super = dm_block_data(sblock); + disk_super->flags = cpu_to_le32(pmd->flags); + + dm_bm_unlock(sblock); +out: + up_write(&pmd->root_lock); + return r; +} + +bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd) +{ + bool needs_check; + + down_read(&pmd->root_lock); + needs_check = pmd->flags & THIN_METADATA_NEEDS_CHECK_FLAG; + up_read(&pmd->root_lock); + + return needs_check; +} diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h index 82ea384..e3c857d 100644 --- a/drivers/md/dm-thin-metadata.h +++ b/drivers/md/dm-thin-metadata.h @@ -25,6 +25,11 @@ /*----------------------------------------------------------------*/ +/* + * Thin metadata superblock flags. + */ +#define THIN_METADATA_NEEDS_CHECK_FLAG (1 << 0) + struct dm_pool_metadata; struct dm_thin_device; @@ -202,6 +207,12 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, dm_sm_threshold_fn fn, void *context); +/* + * Updates the superblock immediately. + */ +int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd); +bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd); + /*----------------------------------------------------------------*/ #endif diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index dfa48ec..a04eba9 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1403,7 +1403,28 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) { int r; struct pool_c *pt = pool->ti->private; - enum pool_mode old_mode = pool->pf.mode; + bool needs_check = dm_pool_metadata_needs_check(pool->pmd); + enum pool_mode old_mode = get_pool_mode(pool); + + /* + * Never allow the pool to transition to PM_WRITE mode if user + * intervention is required to verify metadata and data consistency. + */ + if (new_mode == PM_WRITE && needs_check) { + DMERR("%s: unable to switch pool to write mode until repaired.", + dm_device_name(pool->pool_md)); + if (old_mode != new_mode) + new_mode = old_mode; + else + new_mode = PM_READ_ONLY; + } + /* + * If we were in PM_FAIL mode, rollback of metadata failed. We're + * not going to recover without a thin_repair. So we never let the + * pool move out of the old mode. + */ + if (old_mode == PM_FAIL) + new_mode = old_mode; switch (new_mode) { case PM_FAIL: @@ -1467,19 +1488,28 @@ static void out_of_data_space(struct pool *pool) set_pool_mode(pool, PM_READ_ONLY); } -static void metadata_operation_failed(struct pool *pool, const char *op, int r) +static void abort_transaction(struct pool *pool) { - dm_block_t free_blocks; + const char *dev_name = dm_device_name(pool->pool_md); + + DMERR_LIMIT("%s: aborting current metadata transaction", dev_name); + if (dm_pool_abort_metadata(pool->pmd)) { + DMERR("%s: failed to abort metadata transaction", dev_name); + set_pool_mode(pool, PM_FAIL); + } + + if (dm_pool_metadata_set_needs_check(pool->pmd)) { + DMERR("%s: failed to set 'needs_check' flag in metadata", dev_name); + set_pool_mode(pool, PM_FAIL); + } +} +static void metadata_operation_failed(struct pool *pool, const char *op, int r) +{ DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d", dm_device_name(pool->pool_md), op, r); - if (r == -ENOSPC && - !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) && - !free_blocks) - DMERR_LIMIT("%s: no free metadata space available.", - dm_device_name(pool->pool_md)); - + abort_transaction(pool); set_pool_mode(pool, PM_READ_ONLY); } @@ -1693,7 +1723,7 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti) /* * We want to make sure that a pool in PM_FAIL mode is never upgraded. */ - enum pool_mode old_mode = pool->pf.mode; + enum pool_mode old_mode = get_pool_mode(pool); enum pool_mode new_mode = pt->adjusted_pf.mode; /* @@ -1707,16 +1737,6 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti) pool->pf = pt->adjusted_pf; pool->low_water_blocks = pt->low_water_blocks; - /* - * If we were in PM_FAIL mode, rollback of metadata failed. We're - * not going to recover without a thin_repair. So we never let the - * pool move out of the old mode. On the other hand a PM_READ_ONLY - * may have been due to a lack of metadata or data space, and may - * now work (ie. if the underlying devices have been resized). - */ - if (old_mode == PM_FAIL) - new_mode = old_mode; - set_pool_mode(pool, new_mode); return 0; @@ -2259,6 +2279,12 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit) return -EINVAL; } else if (data_size > sb_data_size) { + if (dm_pool_metadata_needs_check(pool->pmd)) { + DMERR("%s: unable to grow the data device until repaired.", + dm_device_name(pool->pool_md)); + return 0; + } + if (sb_data_size) DMINFO("%s: growing the data device from %llu to %llu blocks", dm_device_name(pool->pool_md), @@ -2300,6 +2326,12 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit) return -EINVAL; } else if (metadata_dev_size > sb_metadata_dev_size) { + if (dm_pool_metadata_needs_check(pool->pmd)) { + DMERR("%s: unable to grow the metadata device until repaired.", + dm_device_name(pool->pool_md)); + return 0; + } + warn_if_metadata_device_too_big(pool->md_dev); DMINFO("%s: growing the metadata device from %llu to %llu blocks", dm_device_name(pool->pool_md), @@ -2801,7 +2833,7 @@ static struct target_type pool_target = { .name = "thin-pool", .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | DM_TARGET_IMMUTABLE, - .version = {1, 10, 0}, + .version = {1, 11, 0}, .module = THIS_MODULE, .ctr = pool_ctr, .dtr = pool_dtr, @@ -3091,7 +3123,7 @@ static int thin_iterate_devices(struct dm_target *ti, static struct target_type thin_target = { .name = "thin", - .version = {1, 10, 0}, + .version = {1, 11, 0}, .module = THIS_MODULE, .ctr = thin_ctr, .dtr = thin_dtr, -- cgit v0.10.2 From 3e1a0699095803e53072699a4a1485af7744601d Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Mon, 3 Mar 2014 16:03:26 +0000 Subject: dm thin: fix out of data space handling Ideally a thin pool would never run out of data space; the low water mark would trigger userland to extend the pool before we completely run out of space. However, many small random IOs to unprovisioned space can consume data space at an alarming rate. Adjust your low water mark if you're frequently seeing "out-of-data-space" mode. Before this fix, if data space ran out the pool would be put in PM_READ_ONLY mode which also aborted the pool's current metadata transaction (data loss for any changes in the transaction). This had a side-effect of needlessly compromising data consistency. And retry of queued unserviceable bios, once the data pool was resized, could initiate changes to potentially inconsistent pool metadata. Now when the pool's data space is exhausted transition to a new pool mode (PM_OUT_OF_DATA_SPACE) that allows metadata to be changed but data may not be allocated. This allows users to remove thin volumes or discard data to recover data space. The pool is no longer put in PM_READ_ONLY mode in response to the pool running out of data space. And PM_READ_ONLY mode no longer aborts the pool's current metadata transaction. Also, set_pool_mode() will now notify userspace when the pool mode is changed. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index a04eba9..38a063f 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -130,10 +130,11 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b, struct dm_thin_new_mapping; /* - * The pool runs in 3 modes. Ordered in degraded order for comparisons. + * The pool runs in 4 modes. Ordered in degraded order for comparisons. */ enum pool_mode { PM_WRITE, /* metadata may be changed */ + PM_OUT_OF_DATA_SPACE, /* metadata may be changed, though data may not be allocated */ PM_READ_ONLY, /* metadata may not be changed */ PM_FAIL, /* all I/O fails */ }; @@ -198,7 +199,6 @@ struct pool { }; static enum pool_mode get_pool_mode(struct pool *pool); -static void out_of_data_space(struct pool *pool); static void metadata_operation_failed(struct pool *pool, const char *op, int r); /* @@ -399,6 +399,23 @@ static void requeue_io(struct thin_c *tc) spin_unlock_irqrestore(&pool->lock, flags); } +static void error_retry_list(struct pool *pool) +{ + struct bio *bio; + unsigned long flags; + struct bio_list bios; + + bio_list_init(&bios); + + spin_lock_irqsave(&pool->lock, flags); + bio_list_merge(&bios, &pool->retry_on_resume_list); + bio_list_init(&pool->retry_on_resume_list); + spin_unlock_irqrestore(&pool->lock, flags); + + while ((bio = bio_list_pop(&bios))) + bio_io_error(bio); +} + /* * This section of code contains the logic for processing a thin device's IO. * Much of the code depends on pool object resources (lists, workqueues, etc) @@ -925,13 +942,15 @@ static void check_low_water_mark(struct pool *pool, dm_block_t free_blocks) } } +static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); + static int alloc_data_block(struct thin_c *tc, dm_block_t *result) { int r; dm_block_t free_blocks; struct pool *pool = tc->pool; - if (get_pool_mode(pool) != PM_WRITE) + if (WARN_ON(get_pool_mode(pool) != PM_WRITE)) return -EINVAL; r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); @@ -958,7 +977,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) } if (!free_blocks) { - out_of_data_space(pool); + set_pool_mode(pool, PM_OUT_OF_DATA_SPACE); return -ENOSPC; } } @@ -988,15 +1007,32 @@ static void retry_on_resume(struct bio *bio) spin_unlock_irqrestore(&pool->lock, flags); } -static void handle_unserviceable_bio(struct pool *pool, struct bio *bio) +static bool should_error_unserviceable_bio(struct pool *pool) { - /* - * When pool is read-only, no cell locking is needed because - * nothing is changing. - */ - WARN_ON_ONCE(get_pool_mode(pool) != PM_READ_ONLY); + enum pool_mode m = get_pool_mode(pool); + + switch (m) { + case PM_WRITE: + /* Shouldn't get here */ + DMERR_LIMIT("bio unserviceable, yet pool is in PM_WRITE mode"); + return true; + + case PM_OUT_OF_DATA_SPACE: + return pool->pf.error_if_no_space; + + case PM_READ_ONLY: + case PM_FAIL: + return true; + default: + /* Shouldn't get here */ + DMERR_LIMIT("bio unserviceable, yet pool has an unknown mode"); + return true; + } +} - if (pool->pf.error_if_no_space) +static void handle_unserviceable_bio(struct pool *pool, struct bio *bio) +{ + if (should_error_unserviceable_bio(pool)) bio_io_error(bio); else retry_on_resume(bio); @@ -1007,11 +1043,20 @@ static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *c struct bio *bio; struct bio_list bios; + if (should_error_unserviceable_bio(pool)) { + cell_error(pool, cell); + return; + } + bio_list_init(&bios); cell_release(pool, cell, &bios); - while ((bio = bio_list_pop(&bios))) - handle_unserviceable_bio(pool, bio); + if (should_error_unserviceable_bio(pool)) + while ((bio = bio_list_pop(&bios))) + bio_io_error(bio); + else + while ((bio = bio_list_pop(&bios))) + retry_on_resume(bio); } static void process_discard(struct thin_c *tc, struct bio *bio) @@ -1296,6 +1341,11 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio) } } +static void process_bio_success(struct thin_c *tc, struct bio *bio) +{ + bio_endio(bio, 0); +} + static void process_bio_fail(struct thin_c *tc, struct bio *bio) { bio_io_error(bio); @@ -1399,9 +1449,15 @@ static enum pool_mode get_pool_mode(struct pool *pool) return pool->pf.mode; } +static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode) +{ + dm_table_event(pool->ti->table); + DMINFO("%s: switching pool to %s mode", + dm_device_name(pool->pool_md), new_mode); +} + static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) { - int r; struct pool_c *pt = pool->ti->private; bool needs_check = dm_pool_metadata_needs_check(pool->pmd); enum pool_mode old_mode = get_pool_mode(pool); @@ -1429,38 +1485,48 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) switch (new_mode) { case PM_FAIL: if (old_mode != new_mode) - DMERR("%s: switching pool to failure mode", - dm_device_name(pool->pool_md)); + notify_of_pool_mode_change(pool, "failure"); dm_pool_metadata_read_only(pool->pmd); pool->process_bio = process_bio_fail; pool->process_discard = process_bio_fail; pool->process_prepared_mapping = process_prepared_mapping_fail; pool->process_prepared_discard = process_prepared_discard_fail; + + error_retry_list(pool); break; case PM_READ_ONLY: if (old_mode != new_mode) - DMERR("%s: switching pool to read-only mode", - dm_device_name(pool->pool_md)); - r = dm_pool_abort_metadata(pool->pmd); - if (r) { - DMERR("%s: aborting transaction failed", - dm_device_name(pool->pool_md)); - new_mode = PM_FAIL; - set_pool_mode(pool, new_mode); - } else { - dm_pool_metadata_read_only(pool->pmd); - pool->process_bio = process_bio_read_only; - pool->process_discard = process_discard; - pool->process_prepared_mapping = process_prepared_mapping_fail; - pool->process_prepared_discard = process_prepared_discard_passdown; - } + notify_of_pool_mode_change(pool, "read-only"); + dm_pool_metadata_read_only(pool->pmd); + pool->process_bio = process_bio_read_only; + pool->process_discard = process_bio_success; + pool->process_prepared_mapping = process_prepared_mapping_fail; + pool->process_prepared_discard = process_prepared_discard_passdown; + + error_retry_list(pool); + break; + + case PM_OUT_OF_DATA_SPACE: + /* + * Ideally we'd never hit this state; the low water mark + * would trigger userland to extend the pool before we + * completely run out of data space. However, many small + * IOs to unprovisioned space can consume data space at an + * alarming rate. Adjust your low water mark if you're + * frequently seeing this mode. + */ + if (old_mode != new_mode) + notify_of_pool_mode_change(pool, "out-of-data-space"); + pool->process_bio = process_bio_read_only; + pool->process_discard = process_discard; + pool->process_prepared_mapping = process_prepared_mapping; + pool->process_prepared_discard = process_prepared_discard_passdown; break; case PM_WRITE: if (old_mode != new_mode) - DMINFO("%s: switching pool to write mode", - dm_device_name(pool->pool_md)); + notify_of_pool_mode_change(pool, "write"); dm_pool_metadata_read_write(pool->pmd); pool->process_bio = process_bio; pool->process_discard = process_discard; @@ -1477,17 +1543,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) pt->adjusted_pf.mode = new_mode; } -/* - * Rather than calling set_pool_mode directly, use these which describe the - * reason for mode degradation. - */ -static void out_of_data_space(struct pool *pool) -{ - DMERR_LIMIT("%s: no free data space available.", - dm_device_name(pool->pool_md)); - set_pool_mode(pool, PM_READ_ONLY); -} - static void abort_transaction(struct pool *pool) { const char *dev_name = dm_device_name(pool->pool_md); @@ -2719,7 +2774,9 @@ static void pool_status(struct dm_target *ti, status_type_t type, else DMEMIT("- "); - if (pool->pf.mode == PM_READ_ONLY) + if (pool->pf.mode == PM_OUT_OF_DATA_SPACE) + DMEMIT("out_of_data_space "); + else if (pool->pf.mode == PM_READ_ONLY) DMEMIT("ro "); else DMEMIT("rw "); -- cgit v0.10.2 From 18adc57779866ba451237dccca2ebf019be2fa20 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Mon, 3 Mar 2014 15:46:42 +0000 Subject: dm thin: fix deadlock in __requeue_bio_list The spin lock in requeue_io() was held for too long, allowing deadlock. Don't worry, due to other issues addressed in the following "dm thin: fix noflush suspend IO queueing" commit, this code was never called. Fix this by taking the spin lock for a much shorter period of time. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 38a063f..f39876d 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -369,14 +369,18 @@ struct dm_thin_endio_hook { struct dm_thin_new_mapping *overwrite_mapping; }; -static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) +static void requeue_bio_list(struct thin_c *tc, struct bio_list *master) { struct bio *bio; struct bio_list bios; + unsigned long flags; bio_list_init(&bios); + + spin_lock_irqsave(&tc->pool->lock, flags); bio_list_merge(&bios, master); bio_list_init(master); + spin_unlock_irqrestore(&tc->pool->lock, flags); while ((bio = bio_list_pop(&bios))) { struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); @@ -391,12 +395,9 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) static void requeue_io(struct thin_c *tc) { struct pool *pool = tc->pool; - unsigned long flags; - spin_lock_irqsave(&pool->lock, flags); - __requeue_bio_list(tc, &pool->deferred_bios); - __requeue_bio_list(tc, &pool->retry_on_resume_list); - spin_unlock_irqrestore(&pool->lock, flags); + requeue_bio_list(tc, &pool->deferred_bios); + requeue_bio_list(tc, &pool->retry_on_resume_list); } static void error_retry_list(struct pool *pool) -- cgit v0.10.2 From 738211f70a1d0c7ff7dc965395f7b8a436365ebd Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Mon, 3 Mar 2014 15:52:28 +0000 Subject: dm thin: fix noflush suspend IO queueing i) by the time DM core calls the postsuspend hook the dm_noflush flag has been cleared. So the old thin_postsuspend did nothing. We need to use the presuspend hook instead. ii) There was a race between bios leaving DM core and arriving in the deferred queue. thin_presuspend now sets a 'requeue' flag causing all bios destined for that thin to be requeued back to DM core. Then it requeues all held IO, and all IO on the deferred queue (destined for that thin). Finally postsuspend clears the 'requeue' flag. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index f39876d..be70d38 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -226,6 +226,7 @@ struct thin_c { struct pool *pool; struct dm_thin_device *td; + bool requeue_mode:1; }; /*----------------------------------------------------------------*/ @@ -1379,6 +1380,11 @@ static void process_deferred_bios(struct pool *pool) struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); struct thin_c *tc = h->tc; + if (tc->requeue_mode) { + bio_endio(bio, DM_ENDIO_REQUEUE); + continue; + } + /* * If we've got no free new_mapping structs, and processing * this bio might require one, we pause until there are some @@ -1445,6 +1451,51 @@ static void do_waker(struct work_struct *ws) /*----------------------------------------------------------------*/ +struct noflush_work { + struct work_struct worker; + struct thin_c *tc; + + atomic_t complete; + wait_queue_head_t wait; +}; + +static void complete_noflush_work(struct noflush_work *w) +{ + atomic_set(&w->complete, 1); + wake_up(&w->wait); +} + +static void do_noflush_start(struct work_struct *ws) +{ + struct noflush_work *w = container_of(ws, struct noflush_work, worker); + w->tc->requeue_mode = true; + requeue_io(w->tc); + complete_noflush_work(w); +} + +static void do_noflush_stop(struct work_struct *ws) +{ + struct noflush_work *w = container_of(ws, struct noflush_work, worker); + w->tc->requeue_mode = false; + complete_noflush_work(w); +} + +static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *)) +{ + struct noflush_work w; + + INIT_WORK(&w.worker, fn); + w.tc = tc; + atomic_set(&w.complete, 0); + init_waitqueue_head(&w.wait); + + queue_work(tc->pool->wq, &w.worker); + + wait_event(w.wait, atomic_read(&w.complete)); +} + +/*----------------------------------------------------------------*/ + static enum pool_mode get_pool_mode(struct pool *pool) { return pool->pf.mode; @@ -1616,6 +1667,11 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) thin_hook_bio(tc, bio); + if (tc->requeue_mode) { + bio_endio(bio, DM_ENDIO_REQUEUE); + return DM_MAPIO_SUBMITTED; + } + if (get_pool_mode(tc->pool) == PM_FAIL) { bio_io_error(bio); return DM_MAPIO_SUBMITTED; @@ -3093,10 +3149,23 @@ static int thin_endio(struct dm_target *ti, struct bio *bio, int err) return 0; } -static void thin_postsuspend(struct dm_target *ti) +static void thin_presuspend(struct dm_target *ti) { + struct thin_c *tc = ti->private; + if (dm_noflush_suspending(ti)) - requeue_io((struct thin_c *)ti->private); + noflush_work(tc, do_noflush_start); +} + +static void thin_postsuspend(struct dm_target *ti) +{ + struct thin_c *tc = ti->private; + + /* + * The dm_noflush_suspending flag has been cleared by now, so + * unfortunately we must always run this. + */ + noflush_work(tc, do_noflush_stop); } /* @@ -3187,6 +3256,7 @@ static struct target_type thin_target = { .dtr = thin_dtr, .map = thin_map, .end_io = thin_endio, + .presuspend = thin_presuspend, .postsuspend = thin_postsuspend, .status = thin_status, .iterate_devices = thin_iterate_devices, -- cgit v0.10.2 From 9c369c6e885599818d98ff7130d6ef62ce6ae8d4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Mar 2014 17:53:31 +0100 Subject: ASoC: cs4271: Fix build error without CONFIG_SPI_MASTER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cs4271_common_probe() is called from cs4271_i2c_probe() but defined in CONFIG_SPI_MASTER block, thus it results in a build error when CONFIG_SPI_MASTER=n: sound/soc/codecs/cs4271.c:721:2: error: implicit declaration of function ‘cs4271_common_probe’ [-Werror=implicit-function-declaration] Move the function out of #if block. Fixes: d6cf89ee07cb ('ASoC: cs4271: claim reset GPIO in bus probe function') Signed-off-by: Takashi Iwai Acked-by: Daniel Mack Acked-by: Brian Austin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 96c3097..aef4965 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -612,22 +612,6 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), }; -#if defined(CONFIG_SPI_MASTER) - -static const struct regmap_config cs4271_spi_regmap = { - .reg_bits = 16, - .val_bits = 8, - .max_register = CS4271_LASTREG, - .read_flag_mask = 0x21, - .write_flag_mask = 0x20, - - .reg_defaults = cs4271_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), - .cache_type = REGCACHE_RBTREE, - - .volatile_reg = cs4271_volatile_reg, -}; - static int cs4271_common_probe(struct device *dev, struct cs4271_private **c) { @@ -658,6 +642,22 @@ static int cs4271_common_probe(struct device *dev, return 0; } +#if defined(CONFIG_SPI_MASTER) + +static const struct regmap_config cs4271_spi_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = CS4271_LASTREG, + .read_flag_mask = 0x21, + .write_flag_mask = 0x20, + + .reg_defaults = cs4271_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = cs4271_volatile_reg, +}; + static int cs4271_spi_probe(struct spi_device *spi) { struct cs4271_private *cs4271; -- cgit v0.10.2 From c1a7898d655fd265feefcf6fe82ab0096e6d078e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Mar 2014 14:28:16 +0000 Subject: ASoC: wm_adsp: Split firmware load into smaller chunks The firmware files can be quite large and allocating the whole firmware a single DMA safe buffer can be problematic if the system is under a high memory load. Ease the requirements slightly by writing the firmware out in page sized chunks. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f9fd564..937af6f 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -684,24 +684,38 @@ static int wm_adsp_load(struct wm_adsp *dsp) } if (reg) { - buf = wm_adsp_buf_alloc(region->data, - le32_to_cpu(region->len), - &buf_list); - if (!buf) { - adsp_err(dsp, "Out of memory\n"); - ret = -ENOMEM; - goto out_fw; - } + size_t to_write = PAGE_SIZE; + size_t remain = le32_to_cpu(region->len); + const u8 *data = region->data; + + while (remain > 0) { + if (remain < PAGE_SIZE) + to_write = remain; + + buf = wm_adsp_buf_alloc(data, + to_write, + &buf_list); + if (!buf) { + adsp_err(dsp, "Out of memory\n"); + ret = -ENOMEM; + goto out_fw; + } - ret = regmap_raw_write_async(regmap, reg, buf->buf, - le32_to_cpu(region->len)); - if (ret != 0) { - adsp_err(dsp, - "%s.%d: Failed to write %d bytes at %d in %s: %d\n", - file, regions, - le32_to_cpu(region->len), offset, - region_name, ret); - goto out_fw; + ret = regmap_raw_write_async(regmap, reg, + buf->buf, + to_write); + if (ret != 0) { + adsp_err(dsp, + "%s.%d: Failed to write %d bytes at %d in %s: %d\n", + file, regions, + to_write, offset, + region_name, ret); + goto out_fw; + } + + data += to_write; + reg += to_write / 2; + remain -= to_write; } } -- cgit v0.10.2 From d9120198ddef2c0b61ca6659ace41b7c1e7c8f08 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Fri, 28 Feb 2014 14:12:05 +0100 Subject: clk: shmobile: rcar-gen2: Use kick bit to allow Z clock frequency change The Z clock frequency change is effective only after setting the kick bit located in the FRQCRB register. Without that, the CA15 CPUs clock rate will never change. Fix that by checking if the kick bit is cleared and enable it to make the clock rate change effective. The bit is cleared automatically upon completion. Signed-off-by: Benoit Cousson Acked-by: Laurent Pinchart Signed-off-by: Mike Turquette diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index a59ec21..de680e6 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -26,6 +26,8 @@ struct rcar_gen2_cpg { void __iomem *reg; }; +#define CPG_FRQCRB 0x00000004 +#define CPG_FRQCRB_KICK BIT(31) #define CPG_SDCKCR 0x00000074 #define CPG_PLL0CR 0x000000d8 #define CPG_FRQCRC 0x000000e0 @@ -45,6 +47,7 @@ struct rcar_gen2_cpg { struct cpg_z_clk { struct clk_hw hw; void __iomem *reg; + void __iomem *kick_reg; }; #define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) @@ -83,17 +86,45 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, { struct cpg_z_clk *zclk = to_z_clk(hw); unsigned int mult; - u32 val; + u32 val, kick; + unsigned int i; mult = div_u64((u64)rate * 32, parent_rate); mult = clamp(mult, 1U, 32U); + if (clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK) + return -EBUSY; + val = clk_readl(zclk->reg); val &= ~CPG_FRQCRC_ZFC_MASK; val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT; clk_writel(val, zclk->reg); - return 0; + /* + * Set KICK bit in FRQCRB to update hardware setting and wait for + * clock change completion. + */ + kick = clk_readl(zclk->kick_reg); + kick |= CPG_FRQCRB_KICK; + clk_writel(kick, zclk->kick_reg); + + /* + * Note: There is no HW information about the worst case latency. + * + * Using experimental measurements, it seems that no more than + * ~10 iterations are needed, independently of the CPU rate. + * Since this value might be dependant of external xtal rate, pll1 + * rate or even the other emulation clocks rate, use 1000 as a + * "super" safe value. + */ + for (i = 1000; i; i--) { + if (!(clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) + return 0; + + cpu_relax(); + } + + return -ETIMEDOUT; } static const struct clk_ops cpg_z_clk_ops = { @@ -120,6 +151,7 @@ static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg) init.num_parents = 1; zclk->reg = cpg->reg + CPG_FRQCRC; + zclk->kick_reg = cpg->reg + CPG_FRQCRB; zclk->hw.init = &init; clk = clk_register(NULL, &zclk->hw); -- cgit v0.10.2 From f516e368dcb5eb5fbe23246c09bf69573d67cd18 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Wed, 5 Mar 2014 16:34:34 +0800 Subject: ASoC: sirf: Add SiRF internal audio codec driver SiRF internal audio codec is integrated in SiRF atlas6 and prima2 SoC. Features include: 1. Stereo DAC and ADC with 16-bit resolution amd 48KHz sample rate 2. Support headphone and/or speaker output 3. Integrate headphone and speaker output amp 4. Support LINE and MIC input 5. Support single ended and differential input mode Signed-off-by: Rongjun Ying --v5: 1. Drop all inlines. 2. Reordering the Kconfig and Makefile 3. Remove the sirf_audio_codec_reg_bits struct, use the new controls instead it. 4. Add some SND_SOC_DAPM_OUT_DRV instead of HP and SPK enable driver 5. Add audio codec clock supply instead of adc event callback 6. Fixed playback and capture can't concurrent work bug. -- .../devicetree/bindings/sound/sirf-audio-codec.txt | 17 + sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 1 + sound/soc/codecs/sirf-audio-codec.c | 533 ++++++++++++++++++++ sound/soc/codecs/sirf-audio-codec.h | 75 +++ 5 files changed, 631 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/sirf-audio-codec.txt create mode 100644 sound/soc/codecs/sirf-audio-codec.c create mode 100644 sound/soc/codecs/sirf-audio-codec.h Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt new file mode 100644 index 0000000..062f5ec --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt @@ -0,0 +1,17 @@ +SiRF internal audio CODEC + +Required properties: + + - compatible : "sirf,atlas6-audio-codec" or "sirf,prima2-audio-codec" + + - reg : the register address of the device. + + - clocks: the clock of SiRF internal audio codec + +Example: + +audiocodec: audiocodec@b0040000 { + compatible = "sirf,atlas6-audio-codec"; + reg = <0xb0040000 0x10000>; + clocks = <&clks 27>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087a..bf9b12c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -63,6 +63,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C select SND_SOC_SI476X if MFD_SI476X_CORE + select SND_SOC_SIRF_AUDIO_CODEC select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF select SND_SOC_SSM2518 if I2C @@ -330,6 +331,10 @@ config SND_SOC_SIGMADSP tristate select CRC32 +config SND_SOC_SIRF_AUDIO_CODEC + tristate "SiRF SoC internal audio codec" + select REGMAP_MMIO + config SND_SOC_SN95031 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc12676..de6d7f8 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -53,6 +53,7 @@ snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o snd-soc-sigmadsp-objs := sigmadsp.o snd-soc-si476x-objs := si476x.o +snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o snd-soc-sn95031-objs := sn95031.o snd-soc-spdif-tx-objs := spdif_transmitter.o snd-soc-spdif-rx-objs := spdif_receiver.o diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c new file mode 100644 index 0000000..90e3a22 --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.c @@ -0,0 +1,533 @@ +/* + * SiRF audio codec driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sirf-audio-codec.h" + +struct sirf_audio_codec { + struct clk *clk; + struct regmap *regmap; + u32 reg_ctrl0, reg_ctrl1; +}; + +static const char * const input_mode_mux[] = {"Single-ended", + "Differential"}; + +static const struct soc_enum input_mode_mux_enum = + SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux); + +static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control = + SOC_DAPM_ENUM("Route", input_mode_mux_enum); + +static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0); +static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0); +static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6, + 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0), + 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0), +); + +static struct snd_kcontrol_new volume_controls_atlas6[] = { + SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, + 0x7F, 0, playback_vol_tlv), + SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10, + 0x3F, 0, capture_vol_tlv_atlas6), +}; + +static struct snd_kcontrol_new volume_controls_prima2[] = { + SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, + 0x7F, 0, playback_vol_tlv), + SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10, + 0x1F, 0, capture_vol_tlv_prima2), +}; + +static struct snd_kcontrol_new left_input_path_controls[] = { + SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0), + SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0), +}; + +static struct snd_kcontrol_new right_input_path_controls[] = { + SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0), + SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0), +}; + +static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0); + +static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0); + +static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0); + +static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0); + +static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0); + +static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0); + +/* After enable adc, Delay 200ms to avoid pop noise */ +static int adc_enable_delay_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + msleep(200); + break; + default: + break; + } + + return 0; +} + +static void enable_and_reset_codec(struct regmap *regmap, + u32 codec_enable_bits, u32 codec_reset_bits) +{ + regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, + codec_enable_bits | codec_reset_bits, + codec_enable_bits | ~codec_reset_bits); + msleep(20); + regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, + codec_reset_bits, codec_reset_bits); +} + +static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ +#define ATLAS6_CODEC_ENABLE_BITS (1 << 29) +#define ATLAS6_CODEC_RESET_BITS (1 << 28) + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + enable_and_reset_codec(sirf_audio_codec->regmap, + ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, + ~ATLAS6_CODEC_ENABLE_BITS); + break; + default: + break; + } + + return 0; +} + +static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ +#define PRIMA2_CODEC_ENABLE_BITS (1 << 27) +#define PRIMA2_CODEC_RESET_BITS (1 << 26) + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + enable_and_reset_codec(sirf_audio_codec->regmap, + PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, + ~PRIMA2_CODEC_ENABLE_BITS); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, + 25, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, + 26, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, + 27, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, + 23, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, + 24, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, + 25, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget = + SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, + atlas6_codec_enable_and_reset_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); + +static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget = + SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, + prima2_codec_enable_and_reset_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); + +static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0), + SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0), + SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0, + &left_dac_to_hp_left_amp_switch_control), + SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0, + &left_dac_to_hp_right_amp_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0, + &right_dac_to_hp_left_amp_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0, + &right_dac_to_hp_right_amp_switch_control), + SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0, + NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0, + NULL, 0), + + SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0, + &left_dac_to_speaker_lineout_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0, + &right_dac_to_speaker_lineout_switch_control), + SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), + SND_SOC_DAPM_OUTPUT("SPKOUT"), + + SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0, + adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0, + adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0, + &left_input_path_controls[0], + ARRAY_SIZE(left_input_path_controls)), + SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0, + &right_input_path_controls[0], + ARRAY_SIZE(right_input_path_controls)), + + SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0, + &sirf_audio_codec_input_mode_control), + SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0), + SND_SOC_DAPM_INPUT("MICIN1"), + SND_SOC_DAPM_INPUT("MICIN2"), + SND_SOC_DAPM_INPUT("LINEIN1"), + SND_SOC_DAPM_INPUT("LINEIN2"), + + SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0, + 30, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { + {"SPKOUT", NULL, "Speaker Driver"}, + {"Speaker Driver", NULL, "Speaker amp driver"}, + {"Speaker amp driver", NULL, "Left dac to speaker lineout"}, + {"Speaker amp driver", NULL, "Right dac to speaker lineout"}, + {"Left dac to speaker lineout", "Switch", "DAC left"}, + {"Right dac to speaker lineout", "Switch", "DAC right"}, + {"HPOUTL", NULL, "HP Left Driver"}, + {"HPOUTR", NULL, "HP Right Driver"}, + {"HP Left Driver", NULL, "HP amp left driver"}, + {"HP Right Driver", NULL, "HP amp right driver"}, + {"HP amp left driver", NULL, "Right dac to hp left amp"}, + {"HP amp right driver", NULL , "Right dac to hp right amp"}, + {"HP amp left driver", NULL, "Left dac to hp left amp"}, + {"HP amp right driver", NULL , "Right dac to hp right amp"}, + {"Right dac to hp left amp", "Switch", "DAC left"}, + {"Right dac to hp right amp", "Switch", "DAC right"}, + {"Left dac to hp left amp", "Switch", "DAC left"}, + {"Left dac to hp right amp", "Switch", "DAC right"}, + {"DAC left", NULL, "codecclk"}, + {"DAC right", NULL, "codecclk"}, + {"DAC left", NULL, "Playback"}, + {"DAC right", NULL, "Playback"}, + {"DAC left", NULL, "HSL Phase Opposite"}, + {"DAC right", NULL, "HSL Phase Opposite"}, + + {"Capture", NULL, "ADC left"}, + {"Capture", NULL, "ADC right"}, + {"ADC left", NULL, "codecclk"}, + {"ADC right", NULL, "codecclk"}, + {"ADC left", NULL, "Left PGA mixer"}, + {"ADC right", NULL, "Right PGA mixer"}, + {"Left PGA mixer", "Line Left Switch", "LINEIN2"}, + {"Right PGA mixer", "Line Right Switch", "LINEIN1"}, + {"Left PGA mixer", "Mic Left Switch", "MICIN2"}, + {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"}, + {"Mic input mode mux", "Single-ended", "MICIN1"}, + {"Mic input mode mux", "Differential", "MICIN1"}, +}; + +static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *dai) +{ + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + struct snd_soc_codec *codec = dai->codec; + u32 val = 0; + + /* + * This is a workaround, When stop playback, + * need disable HP amp, avoid the current noise. + */ + switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (playback) + val = IC_HSLEN | IC_HSREN; + break; + default: + return -EINVAL; + } + + if (playback) + snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, + IC_HSLEN | IC_HSREN, val); + return 0; +} + +struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { + .trigger = sirf_audio_codec_trigger, +}; + +struct snd_soc_dai_driver sirf_audio_codec_dai = { + .name = "sirf-audio-codec", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &sirf_audio_codec_dai_ops, +}; + +static int sirf_audio_codec_probe(struct snd_soc_codec *codec) +{ + int ret; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); + + pm_runtime_enable(codec->dev); + codec->control_data = sirf_audio_codec->regmap; + + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { + snd_soc_dapm_new_controls(dapm, + prima2_output_driver_dapm_widgets, + ARRAY_SIZE(prima2_output_driver_dapm_widgets)); + snd_soc_dapm_new_controls(dapm, + &prima2_codec_clock_dapm_widget, 1); + return snd_soc_add_codec_controls(codec, + volume_controls_prima2, + ARRAY_SIZE(volume_controls_prima2)); + } + if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) { + snd_soc_dapm_new_controls(dapm, + atlas6_output_driver_dapm_widgets, + ARRAY_SIZE(atlas6_output_driver_dapm_widgets)); + snd_soc_dapm_new_controls(dapm, + &atlas6_codec_clock_dapm_widget, 1); + return snd_soc_add_codec_controls(codec, + volume_controls_atlas6, + ARRAY_SIZE(volume_controls_atlas6)); + } + + return -EINVAL; +} + +static int sirf_audio_codec_remove(struct snd_soc_codec *codec) +{ + pm_runtime_disable(codec->dev); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = { + .probe = sirf_audio_codec_probe, + .remove = sirf_audio_codec_remove, + .dapm_widgets = sirf_audio_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets), + .dapm_routes = sirf_audio_codec_map, + .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map), + .idle_bias_off = true, +}; + +static const struct of_device_id sirf_audio_codec_of_match[] = { + { .compatible = "sirf,prima2-audio-codec" }, + { .compatible = "sirf,atlas6-audio-codec" }, + {} +}; +MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match); + +static const struct regmap_config sirf_audio_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = AUDIO_IC_CODEC_CTRL3, + .cache_type = REGCACHE_NONE, +}; + +static int sirf_audio_codec_driver_probe(struct platform_device *pdev) +{ + int ret; + struct sirf_audio_codec *sirf_audio_codec; + void __iomem *base; + struct resource *mem_res; + const struct of_device_id *match; + + match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node); + + sirf_audio_codec = devm_kzalloc(&pdev->dev, + sizeof(struct sirf_audio_codec), GFP_KERNEL); + if (!sirf_audio_codec) + return -ENOMEM; + + platform_set_drvdata(pdev, sirf_audio_codec); + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, mem_res); + if (base == NULL) + return -ENOMEM; + + sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_audio_codec_regmap_config); + if (IS_ERR(sirf_audio_codec->regmap)) + return PTR_ERR(sirf_audio_codec->regmap); + + sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sirf_audio_codec->clk)) { + dev_err(&pdev->dev, "Get clock failed.\n"); + return PTR_ERR(sirf_audio_codec->clk); + } + + ret = clk_prepare_enable(sirf_audio_codec->clk); + if (ret) { + dev_err(&pdev->dev, "Enable clock failed.\n"); + return ret; + } + + ret = snd_soc_register_codec(&(pdev->dev), + &soc_codec_device_sirf_audio_codec, + &sirf_audio_codec_dai, 1); + if (ret) { + dev_err(&pdev->dev, "Register Audio Codec dai failed.\n"); + goto err_clk_put; + } + + /* + * Always open charge pump, if not, when the charge pump closed the + * adc will not stable + */ + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + IC_CPFREQ, IC_CPFREQ); + + if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec")) + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN); + return 0; + +err_clk_put: + clk_disable_unprepare(sirf_audio_codec->clk); + return ret; +} + +static int sirf_audio_codec_driver_remove(struct platform_device *pdev) +{ + struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev); + + clk_disable_unprepare(sirf_audio_codec->clk); + snd_soc_unregister_codec(&(pdev->dev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int sirf_audio_codec_suspend(struct device *dev) +{ + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); + + regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + &sirf_audio_codec->reg_ctrl0); + regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, + &sirf_audio_codec->reg_ctrl1); + clk_disable_unprepare(sirf_audio_codec->clk); + + return 0; +} + +static int sirf_audio_codec_resume(struct device *dev) +{ + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(sirf_audio_codec->clk); + if (ret) + return ret; + + regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + sirf_audio_codec->reg_ctrl0); + regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, + sirf_audio_codec->reg_ctrl1); + + return 0; +} +#endif + +static const struct dev_pm_ops sirf_audio_codec_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume) +}; + +static struct platform_driver sirf_audio_codec_driver = { + .driver = { + .name = "sirf-audio-codec", + .owner = THIS_MODULE, + .of_match_table = sirf_audio_codec_of_match, + .pm = &sirf_audio_codec_pm_ops, + }, + .probe = sirf_audio_codec_driver_probe, + .remove = sirf_audio_codec_driver_remove, +}; + +module_platform_driver(sirf_audio_codec_driver); + +MODULE_DESCRIPTION("SiRF audio codec driver"); +MODULE_AUTHOR("RongJun Ying "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h new file mode 100644 index 0000000..d4c187b --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.h @@ -0,0 +1,75 @@ +/* + * SiRF inner codec controllers define + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _SIRF_AUDIO_CODEC_H +#define _SIRF_AUDIO_CODEC_H + + +#define AUDIO_IC_CODEC_PWR (0x00E0) +#define AUDIO_IC_CODEC_CTRL0 (0x00E4) +#define AUDIO_IC_CODEC_CTRL1 (0x00E8) +#define AUDIO_IC_CODEC_CTRL2 (0x00EC) +#define AUDIO_IC_CODEC_CTRL3 (0x00F0) + +#define MICBIASEN (1 << 3) + +#define IC_RDACEN (1 << 0) +#define IC_LDACEN (1 << 1) +#define IC_HSREN (1 << 2) +#define IC_HSLEN (1 << 3) +#define IC_SPEN (1 << 4) +#define IC_CPEN (1 << 5) + +#define IC_HPRSELR (1 << 6) +#define IC_HPLSELR (1 << 7) +#define IC_HPRSELL (1 << 8) +#define IC_HPLSELL (1 << 9) +#define IC_SPSELR (1 << 10) +#define IC_SPSELL (1 << 11) + +#define IC_MONOR (1 << 12) +#define IC_MONOL (1 << 13) + +#define IC_RXOSRSEL (1 << 28) +#define IC_CPFREQ (1 << 29) +#define IC_HSINVEN (1 << 30) + +#define IC_MICINREN (1 << 0) +#define IC_MICINLEN (1 << 1) +#define IC_MICIN1SEL (1 << 2) +#define IC_MICIN2SEL (1 << 3) +#define IC_MICDIFSEL (1 << 4) +#define IC_LINEIN1SEL (1 << 5) +#define IC_LINEIN2SEL (1 << 6) +#define IC_RADCEN (1 << 7) +#define IC_LADCEN (1 << 8) +#define IC_ALM (1 << 9) + +#define IC_DIGMICEN (1 << 22) +#define IC_DIGMICFREQ (1 << 23) +#define IC_ADC14B_12 (1 << 24) +#define IC_FIRDAC_HSL_EN (1 << 25) +#define IC_FIRDAC_HSR_EN (1 << 26) +#define IC_FIRDAC_LOUT_EN (1 << 27) +#define IC_POR (1 << 28) +#define IC_CODEC_CLK_EN (1 << 29) +#define IC_HP_3DB_BOOST (1 << 30) + +#define IC_ADC_LEFT_GAIN_SHIFT 16 +#define IC_ADC_RIGHT_GAIN_SHIFT 10 +#define IC_ADC_GAIN_MASK 0x3F +#define IC_MIC_MAX_GAIN 0x39 + +#define IC_RXPGAR_MASK 0x3F +#define IC_RXPGAR_SHIFT 14 +#define IC_RXPGAL_MASK 0x3F +#define IC_RXPGAL_SHIFT 21 +#define IC_RXPGAR 0x7B +#define IC_RXPGAL 0x7B + +#endif /*__SIRF_AUDIO_CODEC_H*/ -- cgit v0.10.2 From 208a1589db3e30767223d97e39e13237328e8a6e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:42 +0100 Subject: ASoC: Handle ignore_pmdown_time for CODEC to CODEC links For CODEC to CODEC links we should only immediately power down if both CODECs are configured to ignore the power down delay. Factor the logic for this into a helper function that can be used for both compressed and normal PCMs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a00147..93c31c7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -413,6 +413,8 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, const char *dai_link); +bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); + /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 5e9690c..ef585af 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -235,8 +235,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) cpu_dai->runtime = NULL; if (cstream->direction == SND_COMPRESS_PLAYBACK) { - if (!rtd->pmdown_time || codec->ignore_pmdown_time || - rtd->dai_link->ignore_pmdown_time) { + if (snd_soc_runtime_ignore_pmdown_time(rtd)) { snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, SND_SOC_DAPM_STREAM_STOP); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 47e1ce7..f098c80 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -35,6 +35,30 @@ #define DPCM_MAX_BE_USERS 8 /** + * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay + * @rtd: The ASoC PCM runtime that should be checked. + * + * This function checks whether the power down delay should be ignored for a + * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has + * been configured to ignore the delay, or if none of the components benefits + * from having the delay. + */ +bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) +{ + bool ignore = true; + + if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) + return true; + + if (rtd->cpu_dai->codec) + ignore &= rtd->cpu_dai->codec->ignore_pmdown_time; + + ignore &= rtd->codec_dai->codec->ignore_pmdown_time; + + return ignore; +} + +/** * snd_soc_set_runtime_hwparams - set the runtime hardware parameters * @substream: the pcm substream * @hw: the hardware parameters @@ -496,8 +520,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) cpu_dai->runtime = NULL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (!rtd->pmdown_time || codec->ignore_pmdown_time || - rtd->dai_link->ignore_pmdown_time) { + if (snd_soc_runtime_ignore_pmdown_time(rtd)) { /* powered down playback stream now */ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, -- cgit v0.10.2 From 24894b76468ed250d03f9718ddfe77b902995cbd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:43 +0100 Subject: ASoC: Add helper functions for PCM runtime 'active' management We have the same code that increments and decrements the active field of the various PCM runtime components (all with the same bugs). Factor this out into common helper functions. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 93c31c7..53d15e0 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -414,6 +414,8 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, const char *dai_link); bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); +void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); +void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index ef585af..91083e6 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -30,8 +30,6 @@ static int soc_compr_open(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_platform *platform = rtd->platform; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); @@ -52,17 +50,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) } } - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - - cpu_dai->active++; - codec_dai->active++; - rtd->codec->active++; + snd_soc_runtime_activate(rtd, cstream->direction); mutex_unlock(&rtd->pcm_mutex); @@ -81,8 +69,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; struct snd_soc_platform *platform = fe->platform; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; - struct snd_soc_dai *codec_dai = fe->codec_dai; struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; int stream; @@ -140,17 +126,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - - cpu_dai->active++; - codec_dai->active++; - fe->codec->active++; + snd_soc_runtime_activate(fe, stream); mutex_unlock(&fe->card->mutex); @@ -202,23 +178,18 @@ static int soc_compr_free(struct snd_compr_stream *cstream) struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + int stream; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { - cpu_dai->capture_active--; - codec_dai->capture_active--; - } + if (cstream->direction == SND_COMPRESS_PLAYBACK) + stream = SNDRV_PCM_STREAM_PLAYBACK; + else + stream = SNDRV_PCM_STREAM_CAPTURE; - snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); + snd_soc_runtime_deactivate(rtd, stream); - cpu_dai->active--; - codec_dai->active--; - codec->active--; + snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); if (!cpu_dai->active) cpu_dai->rate = 0; @@ -260,26 +231,17 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_soc_platform *platform = fe->platform; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; - struct snd_soc_dai *codec_dai = fe->codec_dai; struct snd_soc_dpcm *dpcm; int stream, ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - if (cstream->direction == SND_COMPRESS_PLAYBACK) { + if (cstream->direction == SND_COMPRESS_PLAYBACK) stream = SNDRV_PCM_STREAM_PLAYBACK; - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { + else stream = SNDRV_PCM_STREAM_CAPTURE; - cpu_dai->capture_active--; - codec_dai->capture_active--; - } - cpu_dai->active--; - codec_dai->active--; - fe->codec->active--; + snd_soc_runtime_deactivate(fe, stream); fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index f098c80..1a98575 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -35,6 +35,66 @@ #define DPCM_MAX_BE_USERS 8 /** + * snd_soc_runtime_activate() - Increment active count for PCM runtime components + * @rtd: ASoC PCM runtime that is activated + * @stream: Direction of the PCM stream + * + * Increments the active count for all the DAIs and components attached to a PCM + * runtime. Should typically be called when a stream is opened. + * + * Must be called with the rtd->pcm_mutex being held + */ +void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + lockdep_assert_held(&rtd->pcm_mutex); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active++; + codec_dai->playback_active++; + } else { + cpu_dai->capture_active++; + codec_dai->capture_active++; + } + + cpu_dai->active++; + codec_dai->active++; + rtd->codec->active++; +} + +/** + * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components + * @rtd: ASoC PCM runtime that is deactivated + * @stream: Direction of the PCM stream + * + * Decrements the active count for all the DAIs and components attached to a PCM + * runtime. Should typically be called when a stream is closed. + * + * Must be called with the rtd->pcm_mutex being held + */ +void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + lockdep_assert_held(&rtd->pcm_mutex); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active--; + codec_dai->playback_active--; + } else { + cpu_dai->capture_active--; + codec_dai->capture_active--; + } + + cpu_dai->active--; + codec_dai->active--; + rtd->codec->active--; +} + +/** * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay * @rtd: The ASoC PCM runtime that should be checked. * @@ -402,16 +462,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rate_max); dynamic: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - cpu_dai->active++; - codec_dai->active++; - rtd->codec->active++; + + snd_soc_runtime_activate(rtd, substream->stream); + mutex_unlock(&rtd->pcm_mutex); return 0; @@ -483,21 +536,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { - cpu_dai->capture_active--; - codec_dai->capture_active--; - } - - cpu_dai->active--; - codec_dai->active--; - codec->active--; + snd_soc_runtime_deactivate(rtd, substream->stream); /* clear the corresponding DAIs rate when inactive */ if (!cpu_dai->active) -- cgit v0.10.2 From a1a0cc0646e38b41bfaac94f2b84422bb1df40e0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:44 +0100 Subject: ASoC: Fix active count tracking for CODEC to CODEC links For CODEC to CODEC links we need to make sure to also manage the 'active' field of the cpu_dai CODEC. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1a98575..71a01dd 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -61,7 +61,9 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active++; codec_dai->active++; - rtd->codec->active++; + if (cpu_dai->codec) + cpu_dai->codec->active++; + codec_dai->codec->active++; } /** @@ -91,7 +93,9 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active--; codec_dai->active--; - rtd->codec->active--; + if (cpu_dai->codec) + cpu_dai->codec->active--; + codec_dai->codec->active--; } /** -- cgit v0.10.2 From 5c898e74d135a23ce12e0263c1a3c78eeae1b52b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:45 +0100 Subject: ASoC: Add helper function to check whether a CODEC is active Instead of directly checking the 'active' field of the CODEC struct add a new helper function that will return either true or false depending on whether the CODEC is active. This will make the migration to the component level easier. The patch also updates all CODEC drivers that check the active attribute to use the new helper function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 53d15e0..5c2b4f4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1172,6 +1172,11 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec) +{ + return codec->active != 0; +} + int snd_soc_util_init(void); void snd_soc_util_exit(void); diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a..d50cf5b 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -722,7 +722,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - if (!codec->active || !adav80x->rate) + if (!snd_soc_codec_is_active(codec) || !adav80x->rate) return 0; return snd_pcm_hw_constraint_minmax(substream->runtime, @@ -735,7 +735,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - if (!codec->active) + if (!snd_soc_codec_is_active(codec)) adav80x->rate = 0; } diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc..458a6ae 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); /* deactivate */ - if (!codec->active) { + if (!snd_soc_codec_is_active(codec)) { udelay(50); snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); } diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4f35839..35b2d24 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -461,7 +461,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol, if (dac33->fifo_mode == ucontrol->value.integer.value[0]) return 0; /* Do not allow changes while stream is running*/ - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EPERM; if (ucontrol->value.integer.value[0] < 0 || diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 726df6d..8e3940d 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, /* the interpolator & decimator regs must only be written when the * codec DAI is active. */ - if (!codec->active && (reg >= UDA1380_MVOL)) + if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL)) return 0; pr_debug("uda1380: hw write %x val %x\n", reg, value); if (codec->hw_write(codec->control_data, data, 3) == 3) { diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index b7ab2ef..47e96ff 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -197,7 +197,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, return 0; /* Do not allow changes while stream is running */ - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EPERM; if (ucontrol->value.integer.value[0] < 0 || diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index d99f948..6efcc40 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; /* deactivate */ - if (!codec->active) { + if (!snd_soc_codec_is_active(codec)) { udelay(50); snd_soc_write(codec, WM8711_ACTIVE, 0x0); } diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index be85da9..5cf4beb 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -251,7 +251,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, if (wm8753->dai_func == ucontrol->value.integer.value[0]) return 0; - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EBUSY; ioctl = snd_soc_read(codec, WM8753_IOCTL); @@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) /* the digital mute covers the HiFi and Voice DAC's on the WM8753. * make sure we check if they are not both active when we mute */ if (mute && wm8753->dai_func == 1) { - if (!codec->active) + if (!snd_soc_codec_is_active(codec)) snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); } else { if (mute) -- cgit v0.10.2 From 6106d12947d1b05dc15ca3933eb514347d6ed726 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:46 +0100 Subject: ASoC: Add component pointer to the DAI struct Keep track of which component registered a DAI. We'll need this as componentization progresses. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71f27c4..8763e53 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -270,6 +270,7 @@ struct snd_soc_dai { /* parent platform/codec */ struct snd_soc_platform *platform; struct snd_soc_codec *codec; + struct snd_soc_component *component; struct snd_soc_card *card; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50..6401e97 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3884,11 +3884,13 @@ static inline char *fmt_multiple_name(struct device *dev, /** * snd_soc_register_dai - Register a DAI with the ASoC core * - * @dai: DAI to register + * @component: The component the DAIs are registered for + * @dai_drv: DAI driver to use for the DAIs */ -static int snd_soc_register_dai(struct device *dev, +static int snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv) { + struct device *dev = component->dev; struct snd_soc_codec *codec; struct snd_soc_dai *dai; @@ -3905,6 +3907,7 @@ static int snd_soc_register_dai(struct device *dev, return -ENOMEM; } + dai->component = component; dai->dev = dev; dai->driver = dai_drv; dai->dapm.dev = dev; @@ -3962,12 +3965,14 @@ found: /** * snd_soc_register_dais - Register multiple DAIs with the ASoC core * - * @dai: Array of DAIs to register + * @component: The component the DAIs are registered for + * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs */ -static int snd_soc_register_dais(struct device *dev, +static int snd_soc_register_dais(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, size_t count) { + struct device *dev = component->dev; struct snd_soc_codec *codec; struct snd_soc_dai *dai; int i, ret = 0; @@ -3990,6 +3995,7 @@ static int snd_soc_register_dais(struct device *dev, goto err; } + dai->component = component; dai->dev = dev; dai->driver = &dai_drv[i]; if (dai->driver->id) @@ -4086,9 +4092,9 @@ __snd_soc_register_component(struct device *dev, * since it had been used snd_soc_register_dais(), */ if ((1 == num_dai) && allow_single_dai) - ret = snd_soc_register_dai(dev, dai_drv); + ret = snd_soc_register_dai(cmpnt, dai_drv); else - ret = snd_soc_register_dais(dev, dai_drv, num_dai); + ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai); if (ret < 0) { dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto error_component_name; -- cgit v0.10.2 From cdde4ccb14b4959bd1c96a07367bf02b746328d3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:47 +0100 Subject: ASoC: Move active count from CODEC to component There is no reason why active count tracking should only be done for CODECs but not for other components. Moving the active count from the snd_soc_codec struct to the snd_soc_component struct reduces the differences between CODECs and other components and will eventually allow component to component DAI links (Which is a prerequisite for converting CODECs to components). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 5c2b4f4..0495b4a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -660,6 +660,9 @@ struct snd_soc_component { const char *name; int id; struct device *dev; + + unsigned int active; + struct list_head list; struct snd_soc_dai_driver *dai_drv; @@ -687,7 +690,6 @@ struct snd_soc_codec { /* runtime */ struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ - unsigned int active; unsigned int cache_bypass:1; /* Suppress access to the cache */ unsigned int suspended:1; /* Codec is in suspend PM state */ unsigned int probed:1; /* Codec has been probed */ @@ -1172,9 +1174,15 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline bool snd_soc_component_is_active( + struct snd_soc_component *component) +{ + return component->active != 0; +} + static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec) { - return codec->active != 0; + return snd_soc_component_is_active(&codec->component); } int snd_soc_util_init(void); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 71a01dd..98b4629 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -61,9 +61,8 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active++; codec_dai->active++; - if (cpu_dai->codec) - cpu_dai->codec->active++; - codec_dai->codec->active++; + cpu_dai->component->active++; + codec_dai->component->active++; } /** @@ -93,9 +92,8 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active--; codec_dai->active--; - if (cpu_dai->codec) - cpu_dai->codec->active--; - codec_dai->codec->active--; + cpu_dai->component->active--; + codec_dai->component->active--; } /** -- cgit v0.10.2 From 3d59400fe47e7e8bfb024cd1651433bef42e268e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:48 +0100 Subject: ASoC: Move ignore_pmdown_time from CODEC to component In preparation for componentization move the ignore_pmdown_time field from the snd_soc_codec struct to the snd_soc_component struct. Set it to true for non CODEC components for now. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 0495b4a..b14acd8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -663,6 +663,8 @@ struct snd_soc_component { unsigned int active; + unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ + struct list_head list; struct snd_soc_dai_driver *dai_drv; @@ -715,7 +717,6 @@ struct snd_soc_codec { /* dapm */ struct snd_soc_dapm_context dapm; - unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_codec_root; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6401e97..18aecd2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4127,6 +4127,8 @@ int snd_soc_register_component(struct device *dev, return -ENOMEM; } + cmpnt->ignore_pmdown_time = true; + return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, dai_drv, num_dai, true); } @@ -4325,7 +4327,7 @@ int snd_soc_register_codec(struct device *dev, codec->volatile_register = codec_drv->volatile_register; codec->readable_register = codec_drv->readable_register; codec->writable_register = codec_drv->writable_register; - codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time; + codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; codec->dapm.bias_level = SND_SOC_BIAS_OFF; codec->dapm.dev = dev; codec->dapm.codec = codec; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 98b4629..2cedf09 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -107,17 +107,11 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) */ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) { - bool ignore = true; - if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) return true; - if (rtd->cpu_dai->codec) - ignore &= rtd->cpu_dai->codec->ignore_pmdown_time; - - ignore &= rtd->codec_dai->codec->ignore_pmdown_time; - - return ignore; + return rtd->cpu_dai->component->ignore_pmdown_time && + rtd->codec_dai->component->ignore_pmdown_time; } /** -- cgit v0.10.2 From a731e217df3a2ee3ef9413153ed7b45e578d8687 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Wed, 5 Mar 2014 16:34:35 +0800 Subject: ASoC: sirf: Add SiRF audio port driver is used by SiRF internal audio codec This driver is used by SIRF internal audio codec. Use dedicated SiRF audio port TXFIFO and RXFIFO Supports two DMA channels for SiRF audio port TXFIFO and RXFIFO The audio port like as audio bus such as i2s. Signed-off-by: Rongjun Ying Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-port.txt b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt new file mode 100644 index 0000000..1f66de3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt @@ -0,0 +1,20 @@ +* SiRF SoC audio port + +Required properties: +- compatible: "sirf,audio-port" +- reg: Base address and size entries: +- dmas: List of DMA controller phandle and DMA request line ordered pairs. +- dma-names: Identifier string for each DMA request line in the dmas property. + These strings correspond 1:1 with the ordered pairs in dmas. + + One of the DMA channels will be responsible for transmission (should be + named "tx") and one for reception (should be named "rx"). + +Example: + +audioport: audioport@b0040000 { + compatible = "sirf,audio-port"; + reg = <0xb0040000 0x10000>; + dmas = <&dmac1 3>, <&dmac1 8>; + dma-names = "rx", "tx"; +}; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index d62ce48..0060b31 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -50,6 +50,7 @@ source "sound/soc/pxa/Kconfig" source "sound/soc/samsung/Kconfig" source "sound/soc/s6000/Kconfig" source "sound/soc/sh/Kconfig" +source "sound/soc/sirf/Kconfig" source "sound/soc/spear/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 62a1822e7..5f1df02 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += samsung/ obj-$(CONFIG_SND_SOC) += s6000/ obj-$(CONFIG_SND_SOC) += sh/ +obj-$(CONFIG_SND_SOC) += sirf/ obj-$(CONFIG_SND_SOC) += spear/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig new file mode 100644 index 0000000..75b0344 --- /dev/null +++ b/sound/soc/sirf/Kconfig @@ -0,0 +1,8 @@ +config SND_SOC_SIRF + tristate "SoC Audio for the SiRF SoC chips" + depends on ARCH_SIRF || COMPILE_TEST + select SND_SOC_GENERIC_DMAENGINE_PCM + +config SND_SOC_SIRF_AUDIO_PORT + select REGMAP_MMIO + tristate diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile new file mode 100644 index 0000000..fb012c8 --- /dev/null +++ b/sound/soc/sirf/Makefile @@ -0,0 +1,3 @@ +snd-soc-sirf-audio-port-objs := sirf-audio-port.o + +obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c new file mode 100644 index 0000000..b04a53f --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.c @@ -0,0 +1,194 @@ +/* + * SiRF Audio port driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ +#include +#include +#include +#include +#include + +#include "sirf-audio-port.h" + +struct sirf_audio_port { + struct regmap *regmap; + struct snd_dmaengine_dai_dma_data playback_dma_data; + struct snd_dmaengine_dai_dma_data capture_dma_data; +}; + +static void sirf_audio_port_tx_enable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, IC_TX_ENABLE); +} + +static void sirf_audio_port_tx_disable(struct sirf_audio_port *port) +{ + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, ~IC_TX_ENABLE); +} + +static void sirf_audio_port_rx_enable(struct sirf_audio_port *port, + int channels) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + if (channels == 1) + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); + else + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); +} + +static void sirf_audio_port_rx_disable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); +} + +static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, + &port->capture_dma_data); + return 0; +} + +static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (playback) + sirf_audio_port_tx_disable(port); + else + sirf_audio_port_rx_disable(port); + break; + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (playback) + sirf_audio_port_tx_enable(port); + else + sirf_audio_port_rx_enable(port, + substream->runtime->channels); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = { + .trigger = sirf_audio_port_trigger, +}; + +static struct snd_soc_dai_driver sirf_audio_port_dai = { + .probe = sirf_audio_port_dai_probe, + .name = "sirf-audio-port", + .id = 0, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &sirf_audio_port_dai_ops, +}; + +static const struct snd_soc_component_driver sirf_audio_port_component = { + .name = "sirf-audio-port", +}; + +static const struct regmap_config sirf_audio_port_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, + .cache_type = REGCACHE_NONE, +}; + +static int sirf_audio_port_probe(struct platform_device *pdev) +{ + int ret; + struct sirf_audio_port *port; + void __iomem *base; + struct resource *mem_res; + + port = devm_kzalloc(&pdev->dev, + sizeof(struct sirf_audio_port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + dev_err(&pdev->dev, "no mem resource?\n"); + return -ENODEV; + } + + base = devm_ioremap(&pdev->dev, mem_res->start, + resource_size(mem_res)); + if (base == NULL) + return -ENOMEM; + + port->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_audio_port_regmap_config); + if (IS_ERR(port->regmap)) + return PTR_ERR(port->regmap); + + ret = devm_snd_soc_register_component(&pdev->dev, + &sirf_audio_port_component, &sirf_audio_port_dai, 1); + if (ret) + return ret; + + platform_set_drvdata(pdev, port); + return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); +} + +static const struct of_device_id sirf_audio_port_of_match[] = { + { .compatible = "sirf,audio-port", }, + {} +}; +MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match); + +static struct platform_driver sirf_audio_port_driver = { + .driver = { + .name = "sirf-audio-port", + .owner = THIS_MODULE, + .of_match_table = sirf_audio_port_of_match, + }, + .probe = sirf_audio_port_probe, +}; + +module_platform_driver(sirf_audio_port_driver); + +MODULE_DESCRIPTION("SiRF Audio Port driver"); +MODULE_AUTHOR("RongJun Ying "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h new file mode 100644 index 0000000..f32dc54 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.h @@ -0,0 +1,62 @@ +/* + * SiRF Audio port controllers define + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _SIRF_AUDIO_PORT_H +#define _SIRF_AUDIO_PORT_H + +#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F +#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20 + +#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_SC_OFFSET) +#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_LC_OFFSET) +#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_HC_OFFSET) + +#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F +#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20 + +#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_SC_OFFSET) +#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_LC_OFFSET) +#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_HC_OFFSET) +#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4) +#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8) + +#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC) +#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100) +#define AUDIO_PORT_IC_TXFIFO_STS (0x0104) +#define AUDIO_PORT_IC_TXFIFO_INT (0x0108) +#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C) + +#define AUDIO_PORT_IC_RXFIFO_OP (0x0110) +#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114) +#define AUDIO_PORT_IC_RXFIFO_STS (0x0118) +#define AUDIO_PORT_IC_RXFIFO_INT (0x011C) +#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120) + +#define AUDIO_FIFO_START (1 << 0) +#define AUDIO_FIFO_RESET (1 << 1) + +#define AUDIO_FIFO_FULL (1 << 0) +#define AUDIO_FIFO_EMPTY (1 << 1) +#define AUDIO_FIFO_OFLOW (1 << 2) +#define AUDIO_FIFO_UFLOW (1 << 3) + +#define IC_TX_ENABLE (0x03) +#define IC_RX_ENABLE_MONO (0x01) +#define IC_RX_ENABLE_STEREO (0x03) + +#endif /*__SIRF_AUDIO_PORT_H*/ -- cgit v0.10.2 From af12a31f054f55b75c8cf4a459c7bd9d1c7726a9 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Wed, 5 Mar 2014 16:34:36 +0800 Subject: ASoC: sirf: Add SiRF audio card This connects platform DAI, SiRF internal audio codec DAI and SiRF auido port DAI together and works as a mach driver. Signed-off-by: Rongjun Ying Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/sirf-audio.txt b/Documentation/devicetree/bindings/sound/sirf-audio.txt new file mode 100644 index 0000000..c88882c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio.txt @@ -0,0 +1,41 @@ +* SiRF atlas6 and prima2 internal audio codec and port based audio setups + +Required properties: +- compatible: "sirf,sirf-audio-card" +- sirf,audio-platform: phandle for the platform node +- sirf,audio-codec: phandle for the SiRF internal codec node + +Optional properties: +- hp-pa-gpios: Need to be present if the board need control external + headphone amplifier. +- spk-pa-gpios: Need to be present if the board need control external + speaker amplifier. +- hp-switch-gpios: Need to be present if the board capable to detect jack + insertion, removal. + +Available audio endpoints for the audio-routing table: + +Board connectors: + * Headset Stereophone + * Ext Spk + * Line In + * Mic + +SiRF internal audio codec pins: + * HPOUTL + * HPOUTR + * SPKOUT + * Ext Mic + * Mic Bias + +Example: + +sound { + compatible = "sirf,sirf-audio-card"; + sirf,audio-codec = <&audiocodec>; + sirf,audio-platform = <&audioport>; + hp-pa-gpios = <&gpio 44 0>; + spk-pa-gpios = <&gpio 46 0>; + hp-switch-gpios = <&gpio 45 0>; +}; + diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig index 75b0344..89e8942 100644 --- a/sound/soc/sirf/Kconfig +++ b/sound/soc/sirf/Kconfig @@ -3,6 +3,12 @@ config SND_SOC_SIRF depends on ARCH_SIRF || COMPILE_TEST select SND_SOC_GENERIC_DMAENGINE_PCM +config SND_SOC_SIRF_AUDIO + tristate "SoC Audio support for SiRF internal audio codec" + depends on SND_SOC_SIRF + select SND_SOC_SIRF_AUDIO_CODEC + select SND_SOC_SIRF_AUDIO_PORT + config SND_SOC_SIRF_AUDIO_PORT select REGMAP_MMIO tristate diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile index fb012c8..913b932 100644 --- a/sound/soc/sirf/Makefile +++ b/sound/soc/sirf/Makefile @@ -1,3 +1,5 @@ +snd-soc-sirf-audio-objs := sirf-audio.o snd-soc-sirf-audio-port-objs := sirf-audio-port.o +obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c new file mode 100644 index 0000000..ecef510 --- /dev/null +++ b/sound/soc/sirf/sirf-audio.c @@ -0,0 +1,156 @@ +/* + * SiRF audio card driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sirf_audio_card { + unsigned int gpio_hp_pa; + unsigned int gpio_spk_pa; +}; + +static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *ctrl, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); + int on = !SND_SOC_DAPM_EVENT_OFF(event); + if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) + gpio_set_value(sirf_audio_card->gpio_hp_pa, on); + return 0; +} + +static int sirf_audio_spk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *ctrl, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); + int on = !SND_SOC_DAPM_EVENT_OFF(event); + + if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) + gpio_set_value(sirf_audio_card->gpio_spk_pa, on); + + return 0; +} +static const struct snd_soc_dapm_widget sirf_audio_dapm_widgets[] = { + SND_SOC_DAPM_HP("Hp", sirf_audio_hp_event), + SND_SOC_DAPM_SPK("Ext Spk", sirf_audio_spk_event), + SND_SOC_DAPM_MIC("Ext Mic", NULL), +}; + +static const struct snd_soc_dapm_route intercon[] = { + {"Hp", NULL, "HPOUTL"}, + {"Hp", NULL, "HPOUTR"}, + {"Ext Spk", NULL, "SPKOUT"}, + {"MICIN1", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Ext Mic"}, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link sirf_audio_dai_link[] = { + { + .name = "SiRF audio card", + .stream_name = "SiRF audio HiFi", + .codec_dai_name = "sirf-audio-codec", + }, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_sirf_audio_card = { + .name = "SiRF audio card", + .owner = THIS_MODULE, + .dai_link = sirf_audio_dai_link, + .num_links = ARRAY_SIZE(sirf_audio_dai_link), + .dapm_widgets = sirf_audio_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sirf_audio_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), +}; + +static int sirf_audio_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_sirf_audio_card; + struct sirf_audio_card *sirf_audio_card; + int ret; + + sirf_audio_card = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_card), + GFP_KERNEL); + if (sirf_audio_card == NULL) + return -ENOMEM; + + sirf_audio_dai_link[0].cpu_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); + sirf_audio_dai_link[0].platform_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); + sirf_audio_dai_link[0].codec_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); + sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, + "spk-pa-gpios", 0); + sirf_audio_card->gpio_hp_pa = of_get_named_gpio(pdev->dev.of_node, + "hp-pa-gpios", 0); + if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) { + ret = devm_gpio_request_one(&pdev->dev, + sirf_audio_card->gpio_spk_pa, + GPIOF_OUT_INIT_LOW, "SPA_PA_SD"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request GPIO_%d for reset: %d\n", + sirf_audio_card->gpio_spk_pa, ret); + return ret; + } + } + if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) { + ret = devm_gpio_request_one(&pdev->dev, + sirf_audio_card->gpio_hp_pa, + GPIOF_OUT_INIT_LOW, "HP_PA_SD"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request GPIO_%d for reset: %d\n", + sirf_audio_card->gpio_hp_pa, ret); + return ret; + } + } + + card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, sirf_audio_card); + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); + + return ret; +} + +static const struct of_device_id sirf_audio_of_match[] = { + {.compatible = "sirf,sirf-audio-card", }, + { }, +}; +MODULE_DEVICE_TABLE(of, sirf_audio_of_match); + +static struct platform_driver sirf_audio_driver = { + .driver = { + .name = "sirf-audio-card", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = sirf_audio_of_match, + }, + .probe = sirf_audio_probe, +}; +module_platform_driver(sirf_audio_driver); + +MODULE_AUTHOR("RongJun Ying "); +MODULE_DESCRIPTION("ALSA SoC SIRF audio card driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 13ff50c85846338bb9820abd3933227b678dc086 Mon Sep 17 00:00:00 2001 From: Nenghua Cao Date: Wed, 19 Feb 2014 18:44:13 +0800 Subject: regmap: add regmap_parse_val api In some cases, we need regmap's format parse_val function to do be/le translation according to the bus configuration. For example, snd_soc_bytes_put() uses regmap to write/read values, and use cpu_to_be() directly to covert MASK into big endian. This is a defect, and should use regmap's format function to do it according to bus configuration. Signed-off-by: Nenghua Cao Signed-off-by: Mark Brown diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 6a19515..4b2ed0c 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2240,6 +2240,18 @@ int regmap_get_val_bytes(struct regmap *map) } EXPORT_SYMBOL_GPL(regmap_get_val_bytes); +int regmap_parse_val(struct regmap *map, const void *buf, + unsigned int *val) +{ + if (!map->format.parse_val) + return -EINVAL; + + *val = map->format.parse_val(buf); + + return 0; +} +EXPORT_SYMBOL_GPL(regmap_parse_val); + static int __init regmap_initcall(void) { regmap_debugfs_initcall(); diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 4149f1a..3e1a2e4 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -423,6 +423,8 @@ bool regmap_check_range_table(struct regmap *map, unsigned int reg, int regmap_register_patch(struct regmap *map, const struct reg_default *regs, int num_regs); +int regmap_parse_val(struct regmap *map, const void *buf, + unsigned int *val); static inline bool regmap_reg_in_range(unsigned int reg, const struct regmap_range *range) @@ -695,6 +697,13 @@ static inline int regmap_register_patch(struct regmap *map, return -EINVAL; } +static inline int regmap_parse_val(struct regmap *map, const void *buf, + unsigned int *val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + static inline struct regmap *dev_get_regmap(struct device *dev, const char *name) { -- cgit v0.10.2 From a1a564ed6abf62e05fcffa9ed3f46a826400df3a Mon Sep 17 00:00:00 2001 From: Nenghua Cao Date: Wed, 19 Feb 2014 18:44:58 +0800 Subject: ASoC: core: use regmap's parse_val to do endian translation In snd_soc_bytes_put function, it forces cpu to do cpu_to_be translation, but for mmio bus which uses REGMAP_ENDIAN_NATIVE, it doesn't need to do endian translation. So it is better to use regmap's api which can decide if this translation is needed according to bus configuration. Signed-off-by: Nenghua Cao Signed-off-by: Mark Brown diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 45a1faf..9d25c2e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3234,7 +3234,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, struct soc_bytes *params = (void *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); int ret, len; - unsigned int val; + unsigned int val, mask; void *data; if (!codec->using_regmap) @@ -3264,12 +3264,36 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, ((u8 *)data)[0] |= val; break; case 2: - ((u16 *)data)[0] &= cpu_to_be16(~params->mask); - ((u16 *)data)[0] |= cpu_to_be16(val); + mask = ~params->mask; + ret = regmap_parse_val(codec->control_data, + &mask, &mask); + if (ret != 0) + goto out; + + ((u16 *)data)[0] &= mask; + + ret = regmap_parse_val(codec->control_data, + &val, &val); + if (ret != 0) + goto out; + + ((u16 *)data)[0] |= val; break; case 4: - ((u32 *)data)[0] &= cpu_to_be32(~params->mask); - ((u32 *)data)[0] |= cpu_to_be32(val); + mask = ~params->mask; + ret = regmap_parse_val(codec->control_data, + &mask, &mask); + if (ret != 0) + goto out; + + ((u32 *)data)[0] &= mask; + + ret = regmap_parse_val(codec->control_data, + &val, &val); + if (ret != 0) + goto out; + + ((u32 *)data)[0] |= val; break; default: ret = -EINVAL; -- cgit v0.10.2 From 999976e0f6233322a878b0b7148c810544d6c8a8 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Tue, 4 Mar 2014 12:42:15 -0800 Subject: cpufreq: use cpufreq_cpu_get() to avoid cpufreq_get() race conditions If a module calls cpufreq_get while cpufreq is initializing, it's possible for it to be called after cpufreq_driver is set but before cpufreq_cpu_data is written during subsys_interface_register. This happens because cpufreq_get doesn't take the cpufreq_driver_lock around its use of cpufreq_cpu_data. Fix this by using cpufreq_cpu_get(cpu) to look up the policy rather than reading it out of cpufreq_cpu_data directly. cpufreq_cpu_get() takes the appropriate locks to prevent this race from happening. Since it's possible for policy to be NULL if the caller passes in an invalid CPU number or calls the function before cpufreq is initialized, delete the BUG_ON(!policy) and simply return 0. Don't try to return -ENOENT because that's negative and the function returns an unsigned integer. References: https://bbs.archlinux.org/viewtopic.php?id=177934 Signed-off-by: Aaron Plattner Cc: 3.13+ # 3.13+ Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index cb003a6..c4cacab 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1546,23 +1546,16 @@ static unsigned int __cpufreq_get(unsigned int cpu) */ unsigned int cpufreq_get(unsigned int cpu) { - struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); unsigned int ret_freq = 0; - if (cpufreq_disabled() || !cpufreq_driver) - return -ENOENT; - - BUG_ON(!policy); - - if (!down_read_trylock(&cpufreq_rwsem)) - return 0; - - down_read(&policy->rwsem); - - ret_freq = __cpufreq_get(cpu); + if (policy) { + down_read(&policy->rwsem); + ret_freq = __cpufreq_get(cpu); + up_read(&policy->rwsem); - up_read(&policy->rwsem); - up_read(&cpufreq_rwsem); + cpufreq_cpu_put(policy); + } return ret_freq; } -- cgit v0.10.2 From 5a7e56a5d29071bcccd947dee6e3b9f8e4eb3309 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 4 Mar 2014 11:44:00 +0800 Subject: cpufreq: Initialize policy before making it available for others to use Policy must be fully initialized before it is being made available for use by others. Otherwise cpufreq_cpu_get() would be able to grab a half initialized policy structure that might not have affected_cpus (for example) populated. Then, anybody accessing those fields will get a wrong value and that will lead to unpredictable results. In order to fix this, do all the necessary initialization before we make the policy structure available via cpufreq_cpu_get(). That will guarantee that any code accessing fields of the policy will get correct data from them. Reported-by: Saravana Kannan Signed-off-by: Viresh Kumar [rjw: Changelog] Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c4cacab..d6622689 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1109,6 +1109,20 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, goto err_set_policy_cpu; } + /* related cpus should atleast have policy->cpus */ + cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); + + /* + * affected cpus must always be the one, which are online. We aren't + * managing offline cpus here. + */ + cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); + + if (!frozen) { + policy->user_policy.min = policy->min; + policy->user_policy.max = policy->max; + } + write_lock_irqsave(&cpufreq_driver_lock, flags); for_each_cpu(j, policy->cpus) per_cpu(cpufreq_cpu_data, j) = policy; @@ -1162,20 +1176,6 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, } } - /* related cpus should atleast have policy->cpus */ - cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); - - /* - * affected cpus must always be the one, which are online. We aren't - * managing offline cpus here. - */ - cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); - - if (!frozen) { - policy->user_policy.min = policy->min; - policy->user_policy.max = policy->max; - } - blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_START, policy); -- cgit v0.10.2 From 4e97b631f24c927b2302368f4f83efbba82076ee Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 4 Mar 2014 11:44:01 +0800 Subject: cpufreq: Initialize governor for a new policy under policy->rwsem policy->rwsem is used to lock access to all parts of code modifying struct cpufreq_policy, but it's not used on a new policy created by __cpufreq_add_dev(). Because of that, if cpufreq_update_policy() is called in a tight loop on one CPU in parallel with offline/online of another CPU, then the following crash can be triggered: Unable to handle kernel NULL pointer dereference at virtual address 00000020 pgd = c0003000 [00000020] *pgd=80000000004003, *pmd=00000000 Internal error: Oops: 206 [#1] PREEMPT SMP ARM PC is at __cpufreq_governor+0x10/0x1ac LR is at cpufreq_update_policy+0x114/0x150 ---[ end trace f23a8defea6cd706 ]--- Kernel panic - not syncing: Fatal exception CPU0: stopping CPU: 0 PID: 7136 Comm: mpdecision Tainted: G D W 3.10.0-gd727407-00074-g979ede8 #396 [] (notifier_call_chain+0x40/0x68) from [] (__blocking_notifier_call_chain+0x40/0x58) [] (__blocking_notifier_call_chain+0x40/0x58) from [] (blocking_notifier_call_chain+0x14/0x1c) [] (blocking_notifier_call_chain+0x14/0x1c) from [] (cpufreq_set_policy+0xd4/0x2b8) [] (cpufreq_set_policy+0xd4/0x2b8) from [] (cpufreq_init_policy+0x30/0x98) [] (cpufreq_init_policy+0x30/0x98) from [] (__cpufreq_add_dev.isra.17+0x4dc/0x7a4) [] (__cpufreq_add_dev.isra.17+0x4dc/0x7a4) from [] (cpufreq_cpu_callback+0x58/0x84) [] (cpufreq_cpu_callback+0x58/0x84) from [] (notifier_call_chain+0x40/0x68) [] (notifier_call_chain+0x40/0x68) from [] (__cpu_notify+0x28/0x44) [] (__cpu_notify+0x28/0x44) from [] (_cpu_up+0xf4/0x1dc) [] (_cpu_up+0xf4/0x1dc) from [] (cpu_up+0x5c/0x78) [] (cpu_up+0x5c/0x78) from [] (store_online+0x44/0x74) [] (store_online+0x44/0x74) from [] (sysfs_write_file+0x108/0x14c) [] (sysfs_write_file+0x108/0x14c) from [] (vfs_write+0xd0/0x180) [] (vfs_write+0xd0/0x180) from [] (SyS_write+0x38/0x68) [] (SyS_write+0x38/0x68) from [] (ret_fast_syscall+0x0/0x30) Fix that by taking locks at appropriate places in __cpufreq_add_dev() as well. Reported-by: Saravana Kannan Suggested-by: Srivatsa S. Bhat Signed-off-by: Viresh Kumar [rjw: Changelog] Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index d6622689..cf485d9 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1123,6 +1123,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, policy->user_policy.max = policy->max; } + down_write(&policy->rwsem); write_lock_irqsave(&cpufreq_driver_lock, flags); for_each_cpu(j, policy->cpus) per_cpu(cpufreq_cpu_data, j) = policy; @@ -1206,6 +1207,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, policy->user_policy.policy = policy->policy; policy->user_policy.governor = policy->governor; } + up_write(&policy->rwsem); kobject_uevent(&policy->kobj, KOBJ_ADD); up_read(&cpufreq_rwsem); -- cgit v0.10.2 From ad332c8a45330d170bb38b95209de449b31cd1b4 Mon Sep 17 00:00:00 2001 From: Kieran Clancy Date: Sat, 1 Mar 2014 00:42:28 +1030 Subject: ACPI / EC: Clear stale EC events on Samsung systems A number of Samsung notebooks (530Uxx/535Uxx/540Uxx/550Pxx/900Xxx/etc) continue to log events during sleep (lid open/close, AC plug/unplug, battery level change), which accumulate in the EC until a buffer fills. After the buffer is full (tests suggest it holds 8 events), GPEs stop being triggered for new events. This state persists on wake or even on power cycle, and prevents new events from being registered until the EC is manually polled. This is the root cause of a number of bugs, including AC not being detected properly, lid close not triggering suspend, and low ambient light not triggering the keyboard backlight. The bug also seemed to be responsible for performance issues on at least one user's machine. Juan Manuel Cabo found the cause of bug and the workaround of polling the EC manually on wake. The loop which clears the stale events is based on an earlier patch by Lan Tianyu (see referenced attachment). This patch: - Adds a function acpi_ec_clear() which polls the EC for stale _Q events at most ACPI_EC_CLEAR_MAX (currently 100) times. A warning is logged if this limit is reached. - Adds a flag EC_FLAGS_CLEAR_ON_RESUME which is set to 1 if the DMI system vendor is Samsung. This check could be replaced by several more specific DMI vendor/product pairs, but it's likely that the bug affects more Samsung products than just the five series mentioned above. Further, it should not be harmful to run acpi_ec_clear() on systems without the bug; it will return immediately after finding no data waiting. - Runs acpi_ec_clear() on initialisation (boot), from acpi_ec_add() - Runs acpi_ec_clear() on wake, from acpi_ec_unblock_transactions() References: https://bugzilla.kernel.org/show_bug.cgi?id=44161 References: https://bugzilla.kernel.org/show_bug.cgi?id=45461 References: https://bugzilla.kernel.org/show_bug.cgi?id=57271 References: https://bugzilla.kernel.org/attachment.cgi?id=126801 Suggested-by: Juan Manuel Cabo Signed-off-by: Kieran Clancy Reviewed-by: Lan Tianyu Reviewed-by: Dennis Jansen Tested-by: Kieran Clancy Tested-by: Juan Manuel Cabo Tested-by: Dennis Jansen Tested-by: Maurizio D'Addona Tested-by: San Zamoyski Cc: All applicable Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 959d41a..d7d32c2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -67,6 +67,8 @@ enum ec_command { #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ +#define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query + * when trying to clear the EC */ enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ @@ -116,6 +118,7 @@ EXPORT_SYMBOL(first_ec); static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ +static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ /* -------------------------------------------------------------------------- Transaction Management @@ -440,6 +443,29 @@ acpi_handle ec_get_handle(void) EXPORT_SYMBOL(ec_get_handle); +static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data); + +/* + * Clears stale _Q events that might have accumulated in the EC. + * Run with locked ec mutex. + */ +static void acpi_ec_clear(struct acpi_ec *ec) +{ + int i, status; + u8 value = 0; + + for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { + status = acpi_ec_query_unlocked(ec, &value); + if (status || !value) + break; + } + + if (unlikely(i == ACPI_EC_CLEAR_MAX)) + pr_warn("Warning: Maximum of %d stale EC events cleared\n", i); + else + pr_info("%d stale EC events cleared\n", i); +} + void acpi_ec_block_transactions(void) { struct acpi_ec *ec = first_ec; @@ -463,6 +489,10 @@ void acpi_ec_unblock_transactions(void) mutex_lock(&ec->mutex); /* Allow transactions to be carried out again */ clear_bit(EC_FLAGS_BLOCKED, &ec->flags); + + if (EC_FLAGS_CLEAR_ON_RESUME) + acpi_ec_clear(ec); + mutex_unlock(&ec->mutex); } @@ -821,6 +851,13 @@ static int acpi_ec_add(struct acpi_device *device) /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); + + /* Clear stale _Q events if hardware might require that */ + if (EC_FLAGS_CLEAR_ON_RESUME) { + mutex_lock(&ec->mutex); + acpi_ec_clear(ec); + mutex_unlock(&ec->mutex); + } return ret; } @@ -922,6 +959,30 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id) return 0; } +/* + * On some hardware it is necessary to clear events accumulated by the EC during + * sleep. These ECs stop reporting GPEs until they are manually polled, if too + * many events are accumulated. (e.g. Samsung Series 5/9 notebooks) + * + * https://bugzilla.kernel.org/show_bug.cgi?id=44161 + * + * Ideally, the EC should also be instructed NOT to accumulate events during + * sleep (which Windows seems to do somehow), but the interface to control this + * behaviour is not known at this time. + * + * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx, + * however it is very likely that other Samsung models are affected. + * + * On systems which don't accumulate _Q events during sleep, this extra check + * should be harmless. + */ +static int ec_clear_on_resume(const struct dmi_system_id *id) +{ + pr_debug("Detected system needing EC poll on resume.\n"); + EC_FLAGS_CLEAR_ON_RESUME = 1; + return 0; +} + static struct dmi_system_id ec_dmi_table[] __initdata = { { ec_skip_dsdt_scan, "Compal JFL92", { @@ -965,6 +1026,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL}, + { + ec_clear_on_resume, "Samsung hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, {}, }; -- cgit v0.10.2 From d4078e232267ff53f3b030b9698a3c001db4dbec Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 5 Mar 2014 14:07:49 +0100 Subject: x86, trace: Further robustify CR2 handling vs tracing Building on commit 0ac09f9f8cd1 ("x86, trace: Fix CR2 corruption when tracing page faults") this patch addresses another few issues: - Now that read_cr2() is lifted into trace_do_page_fault(), we should pass the address to trace_page_fault_entries() to avoid it re-reading a potentially changed cr2. - Put both trace_do_page_fault() and trace_page_fault_entries() under CONFIG_TRACING. - Mark both fault entry functions {,trace_}do_page_fault() as notrace to avoid getting __mcount or other function entry trace callbacks before we've observed CR2. - Mark __do_page_fault() as noinline to guarantee the function tracer does get to see the fault. Cc: Cc: Acked-by: Steven Rostedt Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140306145300.GO9987@twins.programming.kicks-ass.net Signed-off-by: H. Peter Anvin diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index e7fa28b..a10c8c7 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -1020,8 +1020,12 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. + * + * This function must have noinline because both callers + * {,trace_}do_page_fault() have notrace on. Having this an actual function + * guarantees there's a function trace entry. */ -static void __kprobes +static void __kprobes noinline __do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address) { @@ -1245,31 +1249,38 @@ good_area: up_read(&mm->mmap_sem); } -dotraplinkage void __kprobes +dotraplinkage void __kprobes notrace do_page_fault(struct pt_regs *regs, unsigned long error_code) { + unsigned long address = read_cr2(); /* Get the faulting address */ enum ctx_state prev_state; - /* Get the faulting address: */ - unsigned long address = read_cr2(); + + /* + * We must have this function tagged with __kprobes, notrace and call + * read_cr2() before calling anything else. To avoid calling any kind + * of tracing machinery before we've observed the CR2 value. + * + * exception_{enter,exit}() contain all sorts of tracepoints. + */ prev_state = exception_enter(); __do_page_fault(regs, error_code, address); exception_exit(prev_state); } -static void trace_page_fault_entries(struct pt_regs *regs, +#ifdef CONFIG_TRACING +static void trace_page_fault_entries(unsigned long address, struct pt_regs *regs, unsigned long error_code) { if (user_mode(regs)) - trace_page_fault_user(read_cr2(), regs, error_code); + trace_page_fault_user(address, regs, error_code); else - trace_page_fault_kernel(read_cr2(), regs, error_code); + trace_page_fault_kernel(address, regs, error_code); } -dotraplinkage void __kprobes +dotraplinkage void __kprobes notrace trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) { - enum ctx_state prev_state; /* * The exception_enter and tracepoint processing could * trigger another page faults (user space callchain @@ -1277,9 +1288,11 @@ trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) * the faulting address now. */ unsigned long address = read_cr2(); + enum ctx_state prev_state; prev_state = exception_enter(); - trace_page_fault_entries(regs, error_code); + trace_page_fault_entries(address, regs, error_code); __do_page_fault(regs, error_code, address); exception_exit(prev_state); } +#endif /* CONFIG_TRACING */ -- cgit v0.10.2 From f6d16d32797f665100b1507f6a77c4cd0acb30c5 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 6 Mar 2014 14:04:51 -0500 Subject: dm thin: fix Documentation for held metadata root feature The Documentation for the thin provisioning target's held metadata root feature was incorrect. It is now available and the value for the held metadata root is in block units (not 512b sectors). Signed-off-by: Mike Snitzer diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt index 3b34b4f..05a27e9 100644 --- a/Documentation/device-mapper/thin-provisioning.txt +++ b/Documentation/device-mapper/thin-provisioning.txt @@ -287,10 +287,9 @@ ii) Status should register for the event and then check the target's status. held metadata root: - The location, in sectors, of the metadata root that has been + The location, in blocks, of the metadata root that has been 'held' for userspace read access. '-' indicates there is no - held root. This feature is not yet implemented so '-' is - always returned. + held root. discard_passdown|no_discard_passdown Whether or not discards are actually being passed down to the -- cgit v0.10.2 From 0ca49345b6f489e95f8d6edeb0b092e257475b2a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 6 Mar 2014 20:39:04 +0100 Subject: firewire: ohci: fix probe failure with Agere/LSI controllers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit bd972688eb24 "firewire: ohci: Fix 'failed to read phy reg' on FW643 rev8", there is a high chance that firewire-ohci fails to initialize LSI née Agere controllers. https://bugzilla.kernel.org/show_bug.cgi?id=65151 Peter Hurley points out the reason: IEEE 1394a:2000 clause 5A.1 (or IEEE 1394:2008 clause 17.2.1) say: "The PHY shall insure that no more than 10 ms elapse from the reassertion of LPS until the interface is reset. The link shall not assert LReq until the reset is complete." In other words, the link needs to give the PHY at least 10 ms to get the interface operational. With just the msleep(1) in bd972688eb24, the first read_phy_reg() during ohci_enable() may happen before the phy-link interface reset was finished, and fail. Due to the high variability of msleep(n) with small n, this failure was not fully reproducible, and not apparent at all with low CONFIG_HZ setting. On the other hand, Peter can no longer reproduce the issue with FW643 rev8. The read phy reg failures that happened back then may have had an unrelated cause. So, just revert bd972688eb24, except for the valid comment on TSB82AA2 cards. Reported-by: Mikhail Gavrilov Reported-by: Jay Fenlason Reported-by: Clemens Ladisch Reported-by: Peter Hurley Cc: stable@vger.kernel.org # v3.10+ Signed-off-by: Stefan Richter diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 6f74d8d..8db6632 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -290,7 +290,6 @@ static char ohci_driver_name[] = KBUILD_MODNAME; #define QUIRK_NO_MSI 0x10 #define QUIRK_TI_SLLZ059 0x20 #define QUIRK_IR_WAKE 0x40 -#define QUIRK_PHY_LCTRL_TIMEOUT 0x80 /* In case of multiple matches in ohci_quirks[], only the first one is used. */ static const struct { @@ -303,10 +302,7 @@ static const struct { QUIRK_BE_HEADERS}, {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6, - QUIRK_PHY_LCTRL_TIMEOUT | QUIRK_NO_MSI}, - - {PCI_VENDOR_ID_ATT, PCI_ANY_ID, PCI_ANY_ID, - QUIRK_PHY_LCTRL_TIMEOUT}, + QUIRK_NO_MSI}, {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID, QUIRK_RESET_PACKET}, @@ -353,7 +349,6 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", disable MSI = " __stringify(QUIRK_NO_MSI) ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059) ", IR wake unreliable = " __stringify(QUIRK_IR_WAKE) - ", phy LCtrl timeout = " __stringify(QUIRK_PHY_LCTRL_TIMEOUT) ")"); #define OHCI_PARAM_DEBUG_AT_AR 1 @@ -2299,9 +2294,6 @@ static int ohci_enable(struct fw_card *card, * TI TSB82AA2 + TSB81BA3(A) cards signal LPS enabled early but * cannot actually use the phy at that time. These need tens of * millisecods pause between LPS write and first phy access too. - * - * But do not wait for 50msec on Agere/LSI cards. Their phy - * arbitration state machine may time out during such a long wait. */ reg_write(ohci, OHCI1394_HCControlSet, @@ -2309,11 +2301,8 @@ static int ohci_enable(struct fw_card *card, OHCI1394_HCControl_postedWriteEnable); flush_writes(ohci); - if (!(ohci->quirks & QUIRK_PHY_LCTRL_TIMEOUT)) + for (lps = 0, i = 0; !lps && i < 3; i++) { msleep(50); - - for (lps = 0, i = 0; !lps && i < 150; i++) { - msleep(1); lps = reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_LPS; } -- cgit v0.10.2 From 14eedc32a3c0ec9dd70448a73763ee21feae3111 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Fri, 28 Feb 2014 20:50:23 +0200 Subject: drm/radeon: TTM must be init with cpu-visible VRAM, v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this, a bo may get created in the cpu-inaccessible vram. Before the CP engines get setup, all copies are done via cpu memcpy. This means that the cpu tries to read from inaccessible memory, fails, and the radeon module proceeds to disable acceleration. Doing this has no downsides, as the real VRAM size gets set as soon as the CP engines get init. This is a candidate for 3.14 fixes. v2: Add comment on why the function is used Signed-off-by: Lauri Kasanen Signed-off-by: Alex Deucher Reviewed-by: Christian König Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 77f5b0c..5cdba9b 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -714,6 +714,9 @@ int radeon_ttm_init(struct radeon_device *rdev) DRM_ERROR("Failed initializing VRAM heap.\n"); return r; } + /* Change the size here instead of the init above so only lpfn is affected */ + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->stollen_vga_memory); -- cgit v0.10.2 From bc6a62955f6ea6aabe26292a21dbdd67f5b89b67 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Feb 2014 12:01:28 -0500 Subject: drm/radeon: resume old pm late Moving the pm resume up in the init order to fix dpm seems to have regressed somes cases with the old pm code. Move it back to late resume. Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index e6419ca..a6d1e6c 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7902,7 +7902,8 @@ int cik_resume(struct radeon_device *rdev) /* init golden registers */ cik_init_golden_registers(rdev); - radeon_pm_resume(rdev); + if (rdev->pm.pm_method == PM_METHOD_DPM) + radeon_pm_resume(rdev); rdev->accel_working = true; r = cik_startup(rdev); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 8a2c010..27b0ff1 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -5299,7 +5299,8 @@ int evergreen_resume(struct radeon_device *rdev) /* init golden registers */ evergreen_init_golden_registers(rdev); - radeon_pm_resume(rdev); + if (rdev->pm.pm_method == PM_METHOD_DPM) + radeon_pm_resume(rdev); rdev->accel_working = true; r = evergreen_startup(rdev); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index ea932ac..bf6300c 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -2105,7 +2105,8 @@ int cayman_resume(struct radeon_device *rdev) /* init golden registers */ ni_init_golden_registers(rdev); - radeon_pm_resume(rdev); + if (rdev->pm.pm_method == PM_METHOD_DPM) + radeon_pm_resume(rdev); rdev->accel_working = true; r = cayman_startup(rdev); diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index ef024ce..3cc78bb 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3942,8 +3942,6 @@ int r100_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = r100_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 7c63ef8..0b658b3 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1430,8 +1430,6 @@ int r300_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = r300_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 3768aab..802b192 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -325,8 +325,6 @@ int r420_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = r420_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index e209eb7..98d6053 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -240,8 +240,6 @@ int r520_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = r520_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index cdbc417..647ef40 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2968,7 +2968,8 @@ int r600_resume(struct radeon_device *rdev) /* post card */ atom_asic_init(rdev->mode_info.atom_context); - radeon_pm_resume(rdev); + if (rdev->pm.pm_method == PM_METHOD_DPM) + radeon_pm_resume(rdev); rdev->accel_working = true; r = r600_startup(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index b012cbb..044bc98 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1521,13 +1521,16 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) if (r) DRM_ERROR("ib ring test failed (%d).\n", r); - if (rdev->pm.dpm_enabled) { + if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { /* do dpm late init */ r = radeon_pm_late_init(rdev); if (r) { rdev->pm.dpm_enabled = false; DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); } + } else { + /* resume old pm late */ + radeon_pm_resume(rdev); } radeon_restore_bios_scratch_regs(rdev); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index b5c2369..130d5cc 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -474,8 +474,6 @@ int rs400_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = rs400_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index fdcde76..72d3616 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -1048,8 +1048,6 @@ int rs600_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = rs600_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 3595073..3462b64 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -756,8 +756,6 @@ int rs690_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = rs690_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 98e8138..237dd29 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -586,8 +586,6 @@ int rv515_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); - radeon_pm_resume(rdev); - rdev->accel_working = true; r = rv515_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 4e37a42..fef3107 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1811,7 +1811,8 @@ int rv770_resume(struct radeon_device *rdev) /* init golden registers */ rv770_init_golden_registers(rdev); - radeon_pm_resume(rdev); + if (rdev->pm.pm_method == PM_METHOD_DPM) + radeon_pm_resume(rdev); rdev->accel_working = true; r = rv770_startup(rdev); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 8357832..9a124d0 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6618,7 +6618,8 @@ int si_resume(struct radeon_device *rdev) /* init golden registers */ si_init_golden_registers(rdev); - radeon_pm_resume(rdev); + if (rdev->pm.pm_method == PM_METHOD_DPM) + radeon_pm_resume(rdev); rdev->accel_working = true; r = si_startup(rdev); -- cgit v0.10.2 From 0d997b68574217b41c1288ee4c6728c7003aac1f Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 4 Mar 2014 10:34:48 +0100 Subject: drm/radeon: silence GCC warning on 32 bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building radeon_ttm.o on 32 bit x86 triggers a warning: In file included from include/asm-generic/bug.h:13:0, from [...]/arch/x86/include/asm/bug.h:38, from include/linux/bug.h:4, from include/drm/drm_mm.h:39, from include/drm/drm_vma_manager.h:26, from include/drm/ttm/ttm_bo_api.h:35, from drivers/gpu/drm/radeon/radeon_ttm.c:32: drivers/gpu/drm/radeon/radeon_ttm.c: In function 'radeon_ttm_gtt_read': include/linux/kernel.h:712:17: warning: comparison of distinct pointer types lacks a cast [enabled by default] (void) (&_min1 == &_min2); \ ^ drivers/gpu/drm/radeon/radeon_ttm.c:938:22: note: in expansion of macro 'min' ssize_t cur_size = min(size, PAGE_SIZE - off); ^ Silence this warning by using min_t(). Since cur_size will never be negative and its upper bound is PAGE_SIZE, we can change its type to size_t and use min_t(size_t, [...]) here. Signed-off-by: Paul Bolle Signed-off-by: Alex Deucher Reviewed-by: Christian König diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 5cdba9b..040a2a1 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -938,7 +938,7 @@ static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf, while (size) { loff_t p = *pos / PAGE_SIZE; unsigned off = *pos & ~PAGE_MASK; - ssize_t cur_size = min(size, PAGE_SIZE - off); + size_t cur_size = min_t(size_t, size, PAGE_SIZE - off); struct page *page; void *ptr; -- cgit v0.10.2 From 972c5ddb177e14835212de63f8f16a690e4db9ff Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 4 Mar 2014 15:50:29 -0500 Subject: drm/radeon/cik: fix typo in documentation Copy-paste typo. Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index a6d1e6c..e22be84 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -3046,7 +3046,7 @@ static u32 cik_create_bitmask(u32 bit_width) } /** - * cik_select_se_sh - select which SE, SH to address + * cik_get_rb_disabled - computes the mask of disabled RBs * * @rdev: radeon_device pointer * @max_rb_num: max RBs (render backends) for the asic -- cgit v0.10.2 From 13714323f83ffa5a772fe0d8b74e0fa32ee08819 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 6 Mar 2014 13:16:55 -0500 Subject: drm/radeon/dpm: fix typo in EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters Should be at 0x8 rather than 0. fixes: https://bugzilla.kernel.org/show_bug.cgi?id=60523 Noticed by ArtForz on #radeon Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/evergreen_smc.h b/drivers/gpu/drm/radeon/evergreen_smc.h index 76ada8c..3a03ba3 100644 --- a/drivers/gpu/drm/radeon/evergreen_smc.h +++ b/drivers/gpu/drm/radeon/evergreen_smc.h @@ -57,7 +57,7 @@ typedef struct SMC_Evergreen_MCRegisters SMC_Evergreen_MCRegisters; #define EVERGREEN_SMC_FIRMWARE_HEADER_LOCATION 0x100 -#define EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters 0x0 +#define EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters 0x8 #define EVERGREEN_SMC_FIRMWARE_HEADER_stateTable 0xC #define EVERGREEN_SMC_FIRMWARE_HEADER_mcRegisterTable 0x20 -- cgit v0.10.2 From 77ac9a05d4a0be6b2ab22b61d7fb36d29c212d72 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 6 Mar 2014 13:26:36 +0100 Subject: drm: fix bochs kconfig dependencies Signed-off-by: Gerd Hoffmann Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/bochs/Kconfig b/drivers/gpu/drm/bochs/Kconfig index c8fcf12..5f8b0c2 100644 --- a/drivers/gpu/drm/bochs/Kconfig +++ b/drivers/gpu/drm/bochs/Kconfig @@ -2,6 +2,7 @@ config DRM_BOCHS tristate "DRM Support for bochs dispi vga interface (qemu stdvga)" depends on DRM && PCI select DRM_KMS_HELPER + select DRM_KMS_FB_HELPER select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT -- cgit v0.10.2 From f50d7146a298692daa730b40335e1466110727de Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 3 Mar 2014 12:18:14 +0000 Subject: MAINTAINERS: add maintainer entry for TDA998x driver Add a maintainers entry for the TDA998x driver. Rob Clark has handed this driver over to me to look after. Acked-by: Rob Clark Signed-off-by: Russell King Signed-off-by: Dave Airlie diff --git a/MAINTAINERS b/MAINTAINERS index e9d85f6..07d093e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6171,6 +6171,12 @@ S: Supported F: drivers/block/nvme* F: include/linux/nvme.h +NXP TDA998X DRM DRIVER +M: Russell King +S: Supported +F: drivers/gpu/drm/i2c/tda998x_drv.c +F: include/drm/i2c/tda998x.h + OMAP SUPPORT M: Tony Lindgren L: linux-omap@vger.kernel.org -- cgit v0.10.2 From d03874c881a049a50e12f285077ab1f9fc2686e1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 6 Mar 2014 18:09:52 -0500 Subject: drm/radeon/atom: select the proper number of lanes in transmitter setup We need to check for DVI vs. HDMI when setting up duallink since HDMI is single link only. Fixes 4k modes on newer asics. bug: https://bugs.freedesktop.org/show_bug.cgi?id=75223 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 2cec2ab..607dc14 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1314,7 +1314,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } if (is_dp) args.v5.ucLaneNum = dp_lane_count; - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v5.ucLaneNum = 8; else args.v5.ucLaneNum = 4; -- cgit v0.10.2 From fab800cc33e98378336faf75688ea0961eac21b6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 6 Mar 2014 10:00:18 +0000 Subject: ASoC: wm_adsp: Correct type specifier in printf Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 937af6f..bb5f7b4 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -706,7 +706,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) to_write); if (ret != 0) { adsp_err(dsp, - "%s.%d: Failed to write %d bytes at %d in %s: %d\n", + "%s.%d: Failed to write %zd bytes at %d in %s: %d\n", file, regions, to_write, offset, region_name, ret); -- cgit v0.10.2 From 621b5060e823301d0cba4cb52a7ee3491922d291 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 3 Mar 2014 14:21:40 +1100 Subject: powerpc/tm: Fix crash when forking inside a transaction When we fork/clone we currently don't copy any of the TM state to the new thread. This results in a TM bad thing (program check) when the new process is switched in as the kernel does a tmrechkpt with TEXASR FS not set. Also, since R1 is from userspace, we trigger the bad kernel stack pointer detection. So we end up with something like this: Bad kernel stack pointer 0 at c0000000000404fc cpu 0x2: Vector: 700 (Program Check) at [c00000003ffefd40] pc: c0000000000404fc: restore_gprs+0xc0/0x148 lr: 0000000000000000 sp: 0 msr: 9000000100201030 current = 0xc000001dd1417c30 paca = 0xc00000000fe00800 softe: 0 irq_happened: 0x01 pid = 0, comm = swapper/2 WARNING: exception is not recoverable, can't continue The below fixes this by flushing the TM state before we copy the task_struct to the clone. To do this we go through the tmreclaim patch, which removes the checkpointed registers from the CPU and transitions the CPU out of TM suspend mode. Hence we need to call tmrechkpt after to restore the checkpointed state and the TM mode for the current task. To make this fail from userspace is simply: tbegin li r0, 2 sc Kudos to Adhemerval Zanella Neto for finding this. Signed-off-by: Michael Neuling cc: Adhemerval Zanella Neto cc: stable@vger.kernel.org Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 8d4c247f1..af064d2 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1048,6 +1048,15 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) flush_altivec_to_thread(src); flush_vsx_to_thread(src); flush_spe_to_thread(src); + /* + * Flush TM state out so we can copy it. __switch_to_tm() does this + * flush but it removes the checkpointed state from the current CPU and + * transitions the CPU out of TM mode. Hence we need to call + * tm_recheckpoint_new_task() (on the same task) to restore the + * checkpointed state back and the TM mode. + */ + __switch_to_tm(src); + tm_recheckpoint_new_task(src); *dst = *src; -- cgit v0.10.2 From a5b2cf5b1af424ee3dd9e3ce6d5cea18cb927e67 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 4 Mar 2014 08:31:24 +1100 Subject: powerpc: Align p_dyn, p_rela and p_st symbols The 64bit relocation code places a few symbols in the text segment. These symbols are only 4 byte aligned where they need to be 8 byte aligned. Add an explicit alignment. Signed-off-by: Anton Blanchard Cc: stable@vger.kernel.org Tested-by: Laurent Dufour Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/reloc_64.S b/arch/powerpc/kernel/reloc_64.S index 1482327..d88736f 100644 --- a/arch/powerpc/kernel/reloc_64.S +++ b/arch/powerpc/kernel/reloc_64.S @@ -81,6 +81,7 @@ _GLOBAL(relocate) 6: blr +.balign 8 p_dyn: .llong __dynamic_start - 0b p_rela: .llong __rela_dyn_start - 0b p_st: .llong _stext - 0b -- cgit v0.10.2 From b3fc5725967cea8b661383742ccce21fdeb3ef72 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 6 Mar 2014 14:04:41 +0400 Subject: ASoC: tlv320aic23: add support for SPI control mode tlv320aic23 chip control interface may work in either I2C or SPI mode depending on the MODE pin state. Functionality and register layout are independent of the control mode. Implement bus-specific parts as separate modules. Signed-off-by: Max Filippov Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087a..5e4fc04 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -71,7 +71,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_STA529 if I2C select SND_SOC_STAC9766 if SND_SOC_AC97_BUS select SND_SOC_TAS5086 if I2C - select SND_SOC_TLV320AIC23 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC32X4 if I2C select SND_SOC_TLV320AIC3X if I2C @@ -357,6 +358,14 @@ config SND_SOC_TAS5086 config SND_SOC_TLV320AIC23 tristate +config SND_SOC_TLV320AIC23_I2C + tristate + select SND_SOC_TLV320AIC23 + +config SND_SOC_TLV320AIC23_SPI + tristate + select SND_SOC_TLV320AIC23 + config SND_SOC_TLV320AIC26 tristate depends on SPI diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc12676..ed1fd89 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -63,6 +63,8 @@ snd-soc-sta529-objs := sta529.o snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o +snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o +snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o @@ -193,6 +195,8 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c new file mode 100644 index 0000000..20fc460 --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-i2c.c @@ -0,0 +1,59 @@ +/* + * ALSA SoC TLV320AIC23 codec driver I2C interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "tlv320aic23.h" + +static int tlv320aic23_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *i2c_id) +{ + struct regmap *regmap; + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EINVAL; + + regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); + return tlv320aic23_probe(&i2c->dev, regmap); +} + +static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + return 0; +} + +static const struct i2c_device_id tlv320aic23_id[] = { + {"tlv320aic23", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); + +static struct i2c_driver tlv320aic23_i2c_driver = { + .driver = { + .name = "tlv320aic23-codec", + }, + .probe = tlv320aic23_i2c_probe, + .remove = __exit_p(tlv320aic23_i2c_remove), + .id_table = tlv320aic23_id, +}; + +module_i2c_driver(tlv320aic23_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c new file mode 100644 index 0000000..585aea4 --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-spi.c @@ -0,0 +1,57 @@ +/* + * ALSA SoC TLV320AIC23 codec driver SPI interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "tlv320aic23.h" + +static int aic23_spi_probe(struct spi_device *spi) +{ + int ret; + struct regmap *regmap; + + dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); + + spi->bits_per_word = 16; + spi->mode = SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0) + return ret; + + regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap); + return tlv320aic23_probe(&spi->dev, regmap); +} + +static int aic23_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver aic23_spi = { + .driver = { + .name = "tlv320aic23", + .owner = THIS_MODULE, + }, + .probe = aic23_spi_probe, + .remove = aic23_spi_remove, +}; + +module_spi_driver(aic23_spi); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 139f11f..ab369ae 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = { { 9, 0x0000 }, }; -static const struct regmap_config tlv320aic23_regmap = { +const struct regmap_config tlv320aic23_regmap = { .reg_bits = 7, .val_bits = 9, @@ -557,7 +556,7 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) return 0; } -static int tlv320aic23_probe(struct snd_soc_codec *codec) +static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) { int ret; @@ -604,7 +603,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { - .probe = tlv320aic23_probe, + .probe = tlv320aic23_codec_probe, .remove = tlv320aic23_remove, .suspend = tlv320aic23_suspend, .resume = tlv320aic23_resume, @@ -617,57 +616,25 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), }; -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int tlv320aic23_codec_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) +int tlv320aic23_probe(struct device *dev, struct regmap *regmap) { struct aic23 *aic23; - int ret; - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EINVAL; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); + aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); if (aic23 == NULL) return -ENOMEM; - aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); - if (IS_ERR(aic23->regmap)) - return PTR_ERR(aic23->regmap); + aic23->regmap = regmap; - i2c_set_clientdata(i2c, aic23); + dev_set_drvdata(dev, aic23); - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); - return ret; -} -static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; + return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, + &tlv320aic23_dai, 1); } -static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); - -static struct i2c_driver tlv320aic23_i2c_driver = { - .driver = { - .name = "tlv320aic23-codec", - }, - .probe = tlv320aic23_codec_probe, - .remove = __exit_p(tlv320aic23_i2c_remove), - .id_table = tlv320aic23_id, -}; - -module_i2c_driver(tlv320aic23_i2c_driver); - MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index e804120..3a7235a 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h @@ -12,6 +12,12 @@ #ifndef _TLV320AIC23_H #define _TLV320AIC23_H +struct device; +struct regmap_config; + +extern const struct regmap_config tlv320aic23_regmap; +int tlv320aic23_probe(struct device *dev, struct regmap *regmap); + /* Codec TLV320AIC23 */ #define TLV320AIC23_LINVOL 0x00 #define TLV320AIC23_RINVOL 0x01 -- cgit v0.10.2 From cc1bc54aa787c39125fe843e81bd693e8f507c32 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 6 Mar 2014 14:04:42 +0400 Subject: ASoC: update Kconfig of AIC23 users to select I2C variant Now that AIC23 supports two control interfaces all existing I2C users should select I2C variant. Signed-off-by: Max Filippov Signed-off-by: Mark Brown diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e634eb7..4789619 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260 depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC select SND_ATMEL_SOC_PDC select SND_ATMEL_SOC_SSC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y here to support sound on AFEB9260 board. diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938d..a0bf4a6 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 select SND_EP93XX_SOC_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for I2S audio on the Bluewater Systems Snapper CL15 module. diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f14..19a18a4 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -170,7 +170,7 @@ config SND_SOC_EUKREA_TLV320 || MACH_EUKREA_MBIMXSD35_BASEBOARD \ || MACH_EUKREA_MBIMXSD51_BASEBOARD depends on I2C - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C select SND_SOC_IMX_PCM_FIQ select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 22ad9c5..e006593 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -58,7 +58,7 @@ config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on osk5912. @@ -66,7 +66,7 @@ config SND_OMAP_SOC_AM3517EVM tristate "SoC Audio support for OMAP3517 / AM3517 EVM" depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 EVM. diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 454f41c..47a7a1b 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -117,7 +117,7 @@ config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" depends on SND_SOC_SAMSUNG && ARCH_S3C24XX select SND_S3C24XX_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_HERMES diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 9f9c185..31198cf7 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -105,7 +105,7 @@ config SND_SOC_TEGRA_TRIMSLICE tristate "SoC Audio support for TrimSlice board" depends on SND_SOC_TEGRA && I2C select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for SoC audio on the TrimSlice platform. -- cgit v0.10.2 From 16c0ae028989df40bdab46b7f241d331ddc97c59 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Wed, 5 Mar 2014 14:05:09 +0200 Subject: Target/sbc: Fix sbc_copy_prot for offset scatters When copying between device and command protection scatters we must take into account that device scatters might be offset and we might copy outside scatter range. Thus for each cmd prot scatter we must take the min between cmd prot scatter, dev prot scatter, and whats left (and loop in case we havn't copied enough from/to cmd prot scatter). Example (single t_prot_sg of len 2048): kernel: sbc_dif_copy_prot: se_cmd=ffff880380aaf970, left=2048, len=2048, dev_prot_sg_offset=3072, dev_prot_sg_len=4096 kernel: isert: se_cmd=ffff880380aaf970 PI error found type 0 at sector 0x2600 expected 0x0 vs actual 0x725f, lba=2580 Instead of copying 2048 from offset 3072 (copying junk outside sg limit 4096), we must to copy 1024 and continue to next sg until we complete cmd prot scatter. This issue was found using iSER T10-PI offload over rd_mcp (wasn't discovered with fileio since file_dev prot sglists are never offset). Changes from v1: - Fix sbc_copy_prot copy length miss-calculation Changes from v0: - Removed psg->offset consideration for psg_len computation - Removed sg->offset consideration for offset condition - Added copied consideraiton for len computation - Added copied offset to paddr when doing memcpy Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 42f18fc..77e6531 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -1079,25 +1079,31 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, left = sectors * dev->prot_length; for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) { - - len = min(psg->length, left); - if (offset >= sg->length) { - sg = sg_next(sg); - offset = 0; - } + unsigned int psg_len, copied = 0; paddr = kmap_atomic(sg_page(psg)) + psg->offset; - addr = kmap_atomic(sg_page(sg)) + sg->offset + offset; - - if (read) - memcpy(paddr, addr, len); - else - memcpy(addr, paddr, len); - - left -= len; - offset += len; + psg_len = min(left, psg->length); + while (psg_len) { + len = min(psg_len, sg->length - offset); + addr = kmap_atomic(sg_page(sg)) + sg->offset + offset; + + if (read) + memcpy(paddr + copied, addr, len); + else + memcpy(addr, paddr + copied, len); + + left -= len; + offset += len; + copied += len; + psg_len -= len; + + if (offset >= sg->length) { + sg = sg_next(sg); + offset = 0; + } + kunmap_atomic(addr); + } kunmap_atomic(paddr); - kunmap_atomic(addr); } } -- cgit v0.10.2 From 739c3eea711a255df5ed1246face0a4dce5e589f Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 19 Feb 2014 20:20:21 +0800 Subject: blk-mq: add REQ_SYNC early Add REQ_SYNC early, so rq_dispatched[] in blk_mq_rq_ctx_init is set correctly. Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index 1b8b50d..883f720 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -860,6 +860,8 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) ctx = blk_mq_get_ctx(q); hctx = q->mq_ops->map_queue(q, ctx->cpu); + if (is_sync) + rw |= REQ_SYNC; trace_block_getrq(q, bio, rw); rq = __blk_mq_alloc_request(hctx, GFP_ATOMIC, false); if (likely(rq)) -- cgit v0.10.2 From 70044d71d31d6973665ced5be04ef39ac1c09a48 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 7 Mar 2014 10:19:57 -0500 Subject: firewire: don't use PREPARE_DELAYED_WORK PREPARE_[DELAYED_]WORK() are being phased out. They have few users and a nasty surprise in terms of reentrancy guarantee as workqueue considers work items to be different if they don't have the same work function. firewire core-device and sbp2 have been been multiplexing work items with multiple work functions. Introduce fw_device_workfn() and sbp2_lu_workfn() which invoke fw_device->workfn and sbp2_logical_unit->workfn respectively and always use the two functions as the work functions and update the users to set the ->workfn fields instead of overriding work functions using PREPARE_DELAYED_WORK(). This fixes a variety of possible regressions since a2c1c57be8d9 "workqueue: consider work function when searching for busy work items" due to which fw_workqueue lost its required non-reentrancy property. Signed-off-by: Tejun Heo Acked-by: Stefan Richter Cc: linux1394-devel@lists.sourceforge.net Cc: stable@vger.kernel.org # v3.9+ Cc: stable@vger.kernel.org # v3.8.2+ Cc: stable@vger.kernel.org # v3.4.60+ Cc: stable@vger.kernel.org # v3.2.40+ diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index de4aa40..2c6d5e1 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -916,7 +916,7 @@ static int lookup_existing_device(struct device *dev, void *data) old->config_rom_retries = 0; fw_notice(card, "rediscovered device %s\n", dev_name(dev)); - PREPARE_DELAYED_WORK(&old->work, fw_device_update); + old->workfn = fw_device_update; fw_schedule_device_work(old, 0); if (current_node == card->root_node) @@ -1075,7 +1075,7 @@ static void fw_device_init(struct work_struct *work) if (atomic_cmpxchg(&device->state, FW_DEVICE_INITIALIZING, FW_DEVICE_RUNNING) == FW_DEVICE_GONE) { - PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); + device->workfn = fw_device_shutdown; fw_schedule_device_work(device, SHUTDOWN_DELAY); } else { fw_notice(card, "created device %s: GUID %08x%08x, S%d00\n", @@ -1196,13 +1196,20 @@ static void fw_device_refresh(struct work_struct *work) dev_name(&device->device), fw_rcode_string(ret)); gone: atomic_set(&device->state, FW_DEVICE_GONE); - PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); + device->workfn = fw_device_shutdown; fw_schedule_device_work(device, SHUTDOWN_DELAY); out: if (node_id == card->root_node->node_id) fw_schedule_bm_work(card, 0); } +static void fw_device_workfn(struct work_struct *work) +{ + struct fw_device *device = container_of(to_delayed_work(work), + struct fw_device, work); + device->workfn(work); +} + void fw_node_event(struct fw_card *card, struct fw_node *node, int event) { struct fw_device *device; @@ -1252,7 +1259,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) * power-up after getting plugged in. We schedule the * first config rom scan half a second after bus reset. */ - INIT_DELAYED_WORK(&device->work, fw_device_init); + device->workfn = fw_device_init; + INIT_DELAYED_WORK(&device->work, fw_device_workfn); fw_schedule_device_work(device, INITIAL_DELAY); break; @@ -1268,7 +1276,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) if (atomic_cmpxchg(&device->state, FW_DEVICE_RUNNING, FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) { - PREPARE_DELAYED_WORK(&device->work, fw_device_refresh); + device->workfn = fw_device_refresh; fw_schedule_device_work(device, device->is_local ? 0 : INITIAL_DELAY); } @@ -1283,7 +1291,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) smp_wmb(); /* update node_id before generation */ device->generation = card->generation; if (atomic_read(&device->state) == FW_DEVICE_RUNNING) { - PREPARE_DELAYED_WORK(&device->work, fw_device_update); + device->workfn = fw_device_update; fw_schedule_device_work(device, 0); } break; @@ -1308,7 +1316,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) device = node->data; if (atomic_xchg(&device->state, FW_DEVICE_GONE) == FW_DEVICE_RUNNING) { - PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); + device->workfn = fw_device_shutdown; fw_schedule_device_work(device, list_empty(&card->link) ? 0 : SHUTDOWN_DELAY); } diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 281029d..7aef911 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -146,6 +146,7 @@ struct sbp2_logical_unit { */ int generation; int retries; + work_func_t workfn; struct delayed_work work; bool has_sdev; bool blocked; @@ -864,7 +865,7 @@ static void sbp2_login(struct work_struct *work) /* set appropriate retry limit(s) in BUSY_TIMEOUT register */ sbp2_set_busy_timeout(lu); - PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect); + lu->workfn = sbp2_reconnect; sbp2_agent_reset(lu); /* This was a re-login. */ @@ -918,7 +919,7 @@ static void sbp2_login(struct work_struct *work) * If a bus reset happened, sbp2_update will have requeued * lu->work already. Reset the work from reconnect to login. */ - PREPARE_DELAYED_WORK(&lu->work, sbp2_login); + lu->workfn = sbp2_login; } static void sbp2_reconnect(struct work_struct *work) @@ -952,7 +953,7 @@ static void sbp2_reconnect(struct work_struct *work) lu->retries++ >= 5) { dev_err(tgt_dev(tgt), "failed to reconnect\n"); lu->retries = 0; - PREPARE_DELAYED_WORK(&lu->work, sbp2_login); + lu->workfn = sbp2_login; } sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); @@ -972,6 +973,13 @@ static void sbp2_reconnect(struct work_struct *work) sbp2_conditionally_unblock(lu); } +static void sbp2_lu_workfn(struct work_struct *work) +{ + struct sbp2_logical_unit *lu = container_of(to_delayed_work(work), + struct sbp2_logical_unit, work); + lu->workfn(work); +} + static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) { struct sbp2_logical_unit *lu; @@ -998,7 +1006,8 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) lu->blocked = false; ++tgt->dont_block; INIT_LIST_HEAD(&lu->orb_list); - INIT_DELAYED_WORK(&lu->work, sbp2_login); + lu->workfn = sbp2_login; + INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn); list_add_tail(&lu->link, &tgt->lu_list); return 0; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 5d7782e..c3683bd 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -200,6 +200,7 @@ struct fw_device { unsigned irmc:1; unsigned bc_implemented:2; + work_func_t workfn; struct delayed_work work; struct fw_attribute_group attribute_group; }; -- cgit v0.10.2 From cebc2de44d3bce53e46476e774126c298ca2c8a9 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Fri, 7 Mar 2014 14:57:19 +0000 Subject: dm space map metadata: fix refcount decrement below 0 which caused corruption This has been a relatively long-standing issue that wasn't nailed down until Teng-Feng Yang's meticulous bug report to dm-devel on 3/7/2014, see: http://www.redhat.com/archives/dm-devel/2014-March/msg00021.html From that report: "When decreasing the reference count of a metadata block with its reference count equals 3, we will call dm_btree_remove() to remove this enrty from the B+tree which keeps the reference count info in metadata device. The B+tree will try to rebalance the entry of the child nodes in each node it traversed, and the rebalance process contains the following steps. (1) Finding the corresponding children in current node (shadow_current(s)) (2) Shadow the children block (issue BOP_INC) (3) redistribute keys among children, and free children if necessary (issue BOP_DEC) Since the update of a metadata block's reference count could be recursive, we will stash these reference count update operations in smm->uncommitted and then process them in a FILO fashion. The problem is that step(3) could free the children which is created in step(2), so the BOP_DEC issued in step(3) will be carried out before the BOP_INC issued in step(2) since these BOPs will be processed in FILO fashion. Once the BOP_DEC from step(3) tries to decrease the reference count of newly shadow block, it will report failure for its reference equals 0 before decreasing. It looks like we can solve this issue by processing these BOPs in a FIFO fashion instead of FILO." Commit 5b564d80 ("dm space map: disallow decrementing a reference count below zero") changed the code to report an error for this temporary refcount decrement below zero. So what was previously a harmless invalid refcount became a hard failure due to the new error path: device-mapper: space map common: unable to decrement a reference count below 0 device-mapper: thin: 253:6: dm_thin_insert_block() failed: error = -22 device-mapper: thin: 253:6: switching pool to read-only mode This bug is in dm persistent-data code that is common to the DM thin and cache targets. So any users of those targets should apply this fix. Fix this by applying recursive space map operations in FIFO order rather than FILO. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=68801 Reported-by: Apollon Oikonomopoulos Reported-by: edwillam1007@gmail.com Reported-by: Teng-Feng Yang Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org # 3.13+ diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index e9bdd46..786b689 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -91,6 +91,69 @@ struct block_op { dm_block_t block; }; +struct bop_ring_buffer { + unsigned begin; + unsigned end; + struct block_op bops[MAX_RECURSIVE_ALLOCATIONS + 1]; +}; + +static void brb_init(struct bop_ring_buffer *brb) +{ + brb->begin = 0; + brb->end = 0; +} + +static bool brb_empty(struct bop_ring_buffer *brb) +{ + return brb->begin == brb->end; +} + +static unsigned brb_next(struct bop_ring_buffer *brb, unsigned old) +{ + unsigned r = old + 1; + return (r >= (sizeof(brb->bops) / sizeof(*brb->bops))) ? 0 : r; +} + +static int brb_push(struct bop_ring_buffer *brb, + enum block_op_type type, dm_block_t b) +{ + struct block_op *bop; + unsigned next = brb_next(brb, brb->end); + + /* + * We don't allow the last bop to be filled, this way we can + * differentiate between full and empty. + */ + if (next == brb->begin) + return -ENOMEM; + + bop = brb->bops + brb->end; + bop->type = type; + bop->block = b; + + brb->end = next; + + return 0; +} + +static int brb_pop(struct bop_ring_buffer *brb, struct block_op *result) +{ + struct block_op *bop; + + if (brb_empty(brb)) + return -ENODATA; + + bop = brb->bops + brb->begin; + result->type = bop->type; + result->block = bop->block; + + brb->begin = brb_next(brb, brb->begin); + + return 0; +} + +/*----------------------------------------------------------------*/ + struct sm_metadata { struct dm_space_map sm; @@ -101,25 +164,20 @@ struct sm_metadata { unsigned recursion_count; unsigned allocated_this_transaction; - unsigned nr_uncommitted; - struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS]; + struct bop_ring_buffer uncommitted; struct threshold threshold; }; static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b) { - struct block_op *op; + int r = brb_push(&smm->uncommitted, type, b); - if (smm->nr_uncommitted == MAX_RECURSIVE_ALLOCATIONS) { + if (r) { DMERR("too many recursive allocations"); return -ENOMEM; } - op = smm->uncommitted + smm->nr_uncommitted++; - op->type = type; - op->block = b; - return 0; } @@ -158,11 +216,17 @@ static int out(struct sm_metadata *smm) return -ENOMEM; } - if (smm->recursion_count == 1 && smm->nr_uncommitted) { - while (smm->nr_uncommitted && !r) { - smm->nr_uncommitted--; - r = commit_bop(smm, smm->uncommitted + - smm->nr_uncommitted); + if (smm->recursion_count == 1) { + while (!brb_empty(&smm->uncommitted)) { + struct block_op bop; + + r = brb_pop(&smm->uncommitted, &bop); + if (r) { + DMERR("bug in bop ring buffer"); + break; + } + + r = commit_bop(smm, &bop); if (r) break; } @@ -217,7 +281,8 @@ static int sm_metadata_get_nr_free(struct dm_space_map *sm, dm_block_t *count) static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b, uint32_t *result) { - int r, i; + int r; + unsigned i; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); unsigned adjustment = 0; @@ -225,8 +290,10 @@ static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b, * We may have some uncommitted adjustments to add. This list * should always be really short. */ - for (i = 0; i < smm->nr_uncommitted; i++) { - struct block_op *op = smm->uncommitted + i; + for (i = smm->uncommitted.begin; + i != smm->uncommitted.end; + i = brb_next(&smm->uncommitted, i)) { + struct block_op *op = smm->uncommitted.bops + i; if (op->block != b) continue; @@ -254,7 +321,8 @@ static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b, static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm, dm_block_t b, int *result) { - int r, i, adjustment = 0; + int r, adjustment = 0; + unsigned i; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); uint32_t rc; @@ -262,8 +330,11 @@ static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm, * We may have some uncommitted adjustments to add. This list * should always be really short. */ - for (i = 0; i < smm->nr_uncommitted; i++) { - struct block_op *op = smm->uncommitted + i; + for (i = smm->uncommitted.begin; + i != smm->uncommitted.end; + i = brb_next(&smm->uncommitted, i)) { + + struct block_op *op = smm->uncommitted.bops + i; if (op->block != b) continue; @@ -671,7 +742,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm, smm->begin = superblock + 1; smm->recursion_count = 0; smm->allocated_this_transaction = 0; - smm->nr_uncommitted = 0; + brb_init(&smm->uncommitted); threshold_init(&smm->threshold); memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); @@ -715,7 +786,7 @@ int dm_sm_metadata_open(struct dm_space_map *sm, smm->begin = 0; smm->recursion_count = 0; smm->allocated_this_transaction = 0; - smm->nr_uncommitted = 0; + brb_init(&smm->uncommitted); threshold_init(&smm->threshold); memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); -- cgit v0.10.2 From b053940df41808f0f27568eb36820d10a8a987f8 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 7 Mar 2014 13:22:22 +0530 Subject: ARC: Use correct PTAG register for icache flush This fixes a subtle issue with cache flush which could potentially cause random userspace crashes because of stale icache lines. This error crept in when consolidating the cache flush code Fixes: bd12976c3664 (ARC: cacheflush refactor #3: Unify the {d,i}cache) Signed-off-by: Vineet Gupta Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org # 3.13 Cc: arc-linux-dev@synopsys.com Signed-off-by: Linus Torvalds diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 6b58c1d..400c663 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -282,7 +282,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, #else /* if V-P const for loop, PTAG can be written once outside loop */ if (full_page_op) - write_aux_reg(ARC_REG_DC_PTAG, paddr); + write_aux_reg(aux_tag, paddr); #endif while (num_lines-- > 0) { @@ -296,7 +296,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, write_aux_reg(aux_cmd, vaddr); vaddr += L1_CACHE_BYTES; #else - write_aux_reg(aux, paddr); + write_aux_reg(aux_cmd, paddr); paddr += L1_CACHE_BYTES; #endif } -- cgit v0.10.2 From b28a613e9138e4b3a64649bd60b13436f4b4b49b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Mar 2014 16:34:29 +0000 Subject: libata: add ATA_HORKAGE_BROKEN_FPDMA_AA quirk for Seagate Momentus SpinPoint M8 (2BA30001) Via commit 87809942d3fa "libata: add ATA_HORKAGE_BROKEN_FPDMA_AA quirk for Seagate Momentus SpinPoint M8" we added a quirk for disks named "ST1000LM024 HN-M101MBB" with firmware revision "2AR10001". As reported on https://bugzilla.redhat.com/show_bug.cgi?id=1073901, we need to also add firmware revision 2BA30001 as it is broken as well. Reported-by: Nicholas Signed-off-by: Michele Baldessari Tested-by: Guilherme Amadio Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 191cdfb..65d3f1b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4175,6 +4175,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA }, /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ -- cgit v0.10.2 From e0429362ab15c46ea4d64c3f8c9e0933e48a143a Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 4 Mar 2014 10:52:39 -0800 Subject: usb: Add device quirk for Logitech HD Pro Webcams C920 and C930e We've encountered a rare issue when enumerating two Logitech webcams after a reboot that doesn't power cycle the USB ports. They are spewing random data (possibly some leftover UVC buffers) on the second (full-sized) Get Configuration request of the enumeration phase. Since the data is random this can potentially cause all kinds of odd behavior, and since it occasionally happens multiple times (after the kernel issues another reset due to the garbled configuration descriptor), it is not always recoverable. Set the USB_DELAY_INIT quirk that seems to work around the issue. Signed-off-by: Julius Werner Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 8f37063..739ee8e 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -47,6 +47,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Microsoft LifeCam-VX700 v2.0 */ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech HD Pro Webcams C920 and C930e */ + { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, + { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Logitech Quickcam Fusion */ { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, -- cgit v0.10.2 From d86db25e53fa69e3e97f3b55dd82a70689787c5d Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 4 Mar 2014 11:27:38 -0800 Subject: usb: Make DELAY_INIT quirk wait 100ms between Get Configuration requests The DELAY_INIT quirk only reduces the frequency of enumeration failures with the Logitech HD Pro C920 and C930e webcams, but does not quite eliminate them. We have found that adding a delay of 100ms between the first and second Get Configuration request makes the device enumerate perfectly reliable even after several weeks of extensive testing. The reasons for that are anyone's guess, but since the DELAY_INIT quirk already delays enumeration by a whole second, wating for another 10th of that isn't really a big deal for the one other device that uses it, and it will resolve the problems with these webcams. Signed-off-by: Julius Werner Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 8d72f0c..062967c 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -717,6 +717,10 @@ int usb_get_configuration(struct usb_device *dev) result = -ENOMEM; goto err; } + + if (dev->quirks & USB_QUIRK_DELAY_INIT) + msleep(100); + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { -- cgit v0.10.2 From e2ed511400d41e0d136089d5a55ceab57c6a2426 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 7 Mar 2014 17:06:57 +0200 Subject: Revert "xhci 1.0: Limit arbitrarily-aligned scatter gather." This reverts commit 247bf557273dd775505fb9240d2d152f4f20d304. This commit, together with commit 3804fad45411b48233b48003e33a78f290d227c8 "USBNET: ax88179_178a: enable tso if usb host supports sg dma" were origially added to get xHCI 1.0 hosts and usb ethernet ax88179_178a devices working together with scatter gather. xHCI 1.0 hosts pose some requirement on how transfer buffers are aligned, setting this requirement for 1.0 hosts caused USB 3.0 mass storage devices to fail more frequently. USB 3.0 mass storage devices used to work before 3.14-rc1. Theoretically, the TD fragment rules could have caused an occasional disk glitch. Now the devices *will* fail, instead of theoretically failing. >From a user perspective, this looks like a regression; the USB device obviously fails on 3.14-rc1, and may sometimes silently fail on prior kernels. The proper soluition is to implement the TD fragment rules required, but for now this patch needs to be reverted to get USB 3.0 mass storage devices working at the level they used to. Signed-off-by: Mathias Nyman Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6fe577d..924a6cc 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4733,6 +4733,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) /* Accept arbitrarily long scatter-gather lists */ hcd->self.sg_tablesize = ~0; + /* support to build packet from discontinuous buffers */ + hcd->self.no_sg_constraint = 1; + /* XHCI controllers don't stop the ep queue on short packets :| */ hcd->self.no_stop_on_short = 1; @@ -4757,14 +4760,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) /* xHCI private pointer was set in xhci_pci_probe for the second * registered roothub. */ - xhci = hcd_to_xhci(hcd); - /* - * Support arbitrarily aligned sg-list entries on hosts without - * TD fragment rules (which are currently unsupported). - */ - if (xhci->hci_version < 0x100) - hcd->self.no_sg_constraint = 1; - return 0; } @@ -4793,9 +4788,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) if (xhci->hci_version > 0x96) xhci->quirks |= XHCI_SPURIOUS_SUCCESS; - if (xhci->hci_version < 0x100) - hcd->self.no_sg_constraint = 1; - /* Make sure the HC is halted. */ retval = xhci_halt(xhci); if (retval) -- cgit v0.10.2 From 469d417b68958a064c09e7875646c97c6e783dfc Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 7 Mar 2014 17:06:58 +0200 Subject: Revert "USBNET: ax88179_178a: enable tso if usb host supports sg dma" This reverts commit 3804fad45411b48233b48003e33a78f290d227c8. This commit, together with commit 247bf557273dd775505fb9240d2d152f4f20d304 "xhci 1.0: Limit arbitrarily-aligned scatter gather." were origially added to get xHCI 1.0 hosts and usb ethernet ax88179_178a devices working together with scatter gather. xHCI 1.0 hosts pose some requirement on how transfer buffers are aligned, setting this requirement for 1.0 hosts caused USB 3.0 mass storage devices to fail more frequently. USB 3.0 mass storage devices used to work before 3.14-rc1. Theoretically, the TD fragment rules could have caused an occasional disk glitch. Now the devices *will* fail, instead of theoretically failing. >From a user perspective, this looks like a regression; the USB device obviously fails on 3.14-rc1, and may sometimes silently fail on prior kernels. The proper soluition is to implement the TD fragment rules for xHCI 1.0 hosts, but for now, revert this patch until scatter gather can be properly supported. Signed-off-by: Mathias Nyman Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 955df81..42085e6 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1029,20 +1029,12 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.phy_id = 0x03; dev->mii.supports_gmii = 1; - if (usb_device_no_sg_constraint(dev->udev)) - dev->can_dma_sg = 1; - dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; - if (dev->can_dma_sg) { - dev->net->features |= NETIF_F_SG | NETIF_F_TSO; - dev->net->hw_features |= NETIF_F_SG | NETIF_F_TSO; - } - /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; -- cgit v0.10.2 From 006fa2599bf0daf107cbb7a8a99fcfb9a998a169 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 26 Feb 2014 19:40:46 +0000 Subject: ARM: fix noMMU kallsyms symbol filtering With noMMU, CONFIG_PAGE_OFFSET was not being set correctly. As there's no MMU, PAGE_OFFSET should be equal to PHYS_OFFSET in all cases. This commit makes that explicit. Since we do this, we don't need to mess around in asm/memory.h with ifdefs to sort this out, so let's get rid of that, and there's no point offering the "Memory split" option for noMMU as that's meaningless there. Fixes: b9b32bf70f2f ("ARM: use linker magic for vectors and vector stubs") Cc: Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e254198..2a232ce 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1578,6 +1578,7 @@ config BL_SWITCHER_DUMMY_IF choice prompt "Memory split" + depends on MMU default VMSPLIT_3G help Select the desired split between kernel and user memory. @@ -1595,6 +1596,7 @@ endchoice config PAGE_OFFSET hex + default PHYS_OFFSET if !MMU default 0x40000000 if VMSPLIT_1G default 0x80000000 if VMSPLIT_2G default 0xC0000000 diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 8756e4b..4afb376 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -30,14 +30,15 @@ */ #define UL(x) _AC(x, UL) +/* PAGE_OFFSET - the virtual address of the start of the kernel image */ +#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET) + #ifdef CONFIG_MMU /* - * PAGE_OFFSET - the virtual address of the start of the kernel image * TASK_SIZE - the maximum size of a user space task. * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area */ -#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET) #define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M)) #define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) @@ -104,10 +105,6 @@ #define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE) #endif -#ifndef PAGE_OFFSET -#define PAGE_OFFSET PLAT_PHYS_OFFSET -#endif - /* * The module can be at any place in ram in nommu mode. */ -- cgit v0.10.2 From 052450fdc55894a39fbae93d9bbe43947956f663 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Feb 2014 22:41:41 +0100 Subject: ARM: 7991/1: sa1100: fix compile problem on Collie Due to a problem in the MFD Kconfig it was not possible to compile the UCB battery driver for the Collie SA1100 system, in turn making it impossible to compile in the battery driver. (See patch "mfd: include all drivers in subsystem menu".) After fixing the MFD Kconfig (separate patch) a compile error appears in the Collie battery driver due to the implicitly requiring through via prior to commit 40ca061b "ARM: 7841/1: sa1100: remove complex GPIO interface". Fix this up by including the required header into . Cc: stable@vger.kernel.org Cc: Andrea Adami Cc: Dmitry Eremin-Solenikov Signed-off-by: Linus Walleij Signed-off-by: Russell King diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h index f33679d..50e1d85 100644 --- a/arch/arm/mach-sa1100/include/mach/collie.h +++ b/arch/arm/mach-sa1100/include/mach/collie.h @@ -13,6 +13,8 @@ #ifndef __ASM_ARCH_COLLIE_H #define __ASM_ARCH_COLLIE_H +#include "hardware.h" /* Gives GPIO_MAX */ + extern void locomolcd_power(int on); #define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1) -- cgit v0.10.2 From 38e0b088d322e5762ac21fb4df433e83faf128eb Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 26 Feb 2014 17:21:26 +0100 Subject: ARM: 7992/1: boot: compressed: ignore bswapsdi2.S Commit 017f161a55b4 (ARM: 7877/1: use built-in byte swap function) added bswapsdi2.{o,S} to arch/arm/boot/compressed/Makefile, but didn't update the .gitignore. Thus after a a build git status shows bswapsdi2.S as a new file, which is a little annoying. This patch updates arch/arm/boot/compressed/.gitignore to ignore bswapsdi2.S, as we already do for ashldi3.S and others. Signed-off-by: Mark Rutland Acked-by: Nicolas Pitre Acked-by: Kim Phillips Cc: David Woodhouse Signed-off-by: Russell King diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index 47279aa..0714e03 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -1,4 +1,5 @@ ashldi3.S +bswapsdi2.S font.c lib1funcs.S hyp-stub.S -- cgit v0.10.2 From 5fa10196bdb5f190f595ebd048490ee52dddea0f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 7 Mar 2014 15:05:20 -0800 Subject: x86: Ignore NMIs that come in during early boot Don Zickus reports: A customer generated an external NMI using their iLO to test kdump worked. Unfortunately, the machine hung. Disabling the nmi_watchdog made things work. I speculated the external NMI fired, caused the machine to panic (as expected) and the perf NMI from the watchdog came in and was latched. My guess was this somehow caused the hang. ---- It appears that the latched NMI stays latched until the early page table generation on 64 bits, which causes exceptions to happen which end in IRET, which re-enable NMI. Therefore, ignore NMIs that come in during early execution, until we have proper exception handling. Reported-and-tested-by: Don Zickus Link: http://lkml.kernel.org/r/1394221143-29713-1-git-send-email-dzickus@redhat.com Signed-off-by: H. Peter Anvin Cc: # v3.5+, older with some backport effort diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 81ba276..d2a2159 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -544,6 +544,10 @@ ENDPROC(early_idt_handlers) /* This is global to keep gas from relaxing the jumps */ ENTRY(early_idt_handler) cld + + cmpl $X86_TRAP_NMI,(%esp) + je is_nmi # Ignore NMI + cmpl $2,%ss:early_recursion_flag je hlt_loop incl %ss:early_recursion_flag @@ -594,8 +598,9 @@ ex_entry: pop %edx pop %ecx pop %eax - addl $8,%esp /* drop vector number and error code */ decl %ss:early_recursion_flag +is_nmi: + addl $8,%esp /* drop vector number and error code */ iret ENDPROC(early_idt_handler) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index e1aabdb..33f36c7 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -343,6 +343,9 @@ early_idt_handlers: ENTRY(early_idt_handler) cld + cmpl $X86_TRAP_NMI,(%rsp) + je is_nmi # Ignore NMI + cmpl $2,early_recursion_flag(%rip) jz 1f incl early_recursion_flag(%rip) @@ -405,8 +408,9 @@ ENTRY(early_idt_handler) popq %rdx popq %rcx popq %rax - addq $16,%rsp # drop vector number and error code decl early_recursion_flag(%rip) +is_nmi: + addq $16,%rsp # drop vector number and error code INTERRUPT_RETURN ENDPROC(early_idt_handler) -- cgit v0.10.2 From 2ca310fc4160ed0420da65534a21ae77b24326a8 Mon Sep 17 00:00:00 2001 From: Ditang Chen Date: Fri, 7 Mar 2014 13:27:57 +0800 Subject: SUNRPC: Fix oops when trace sunrpc_task events in nfs client When tracking sunrpc_task events in nfs client, the clnt pointer may be NULL. [ 139.269266] BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 [ 139.269915] IP: [] ftrace_raw_event_rpc_task_running+0x86/0xf0 [sunrpc] [ 139.269915] PGD 1d293067 PUD 1d294067 PMD 0 [ 139.269915] Oops: 0000 [#1] SMP [ 139.269915] Modules linked in: nfsv4 dns_resolver nfs lockd sunrpc fscache sg ppdev e1000 serio_raw pcspkr parport_pc parport i2c_piix4 i2c_core microcode xfs libcrc32c sd_mod sr_mod cdrom ata_generic crc_t10dif crct10dif_common pata_acpi ahci libahci ata_piix libata dm_mirror dm_region_hash dm_log dm_mod [ 139.269915] CPU: 0 PID: 59 Comm: kworker/0:2 Not tainted 3.10.0-84.el7.x86_64 #1 [ 139.269915] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 139.269915] Workqueue: rpciod rpc_async_schedule [sunrpc] [ 139.269915] task: ffff88001b598000 ti: ffff88001b632000 task.ti: ffff88001b632000 [ 139.269915] RIP: 0010:[] [] ftrace_raw_event_rpc_task_running+0x86/0xf0 [sunrpc] [ 139.269915] RSP: 0018:ffff88001b633d70 EFLAGS: 00010206 [ 139.269915] RAX: ffff88001dfc5338 RBX: ffff88001cc37a00 RCX: ffff88001dfc5334 [ 139.269915] RDX: ffff88001dfc5338 RSI: 0000000000000000 RDI: ffff88001dfc533c [ 139.269915] RBP: ffff88001b633db0 R08: 000000000000002c R09: 000000000000000a [ 139.269915] R10: 0000000000062180 R11: 00000020759fb9dc R12: ffffffffa0292c20 [ 139.269915] R13: ffff88001dfc5334 R14: 0000000000000000 R15: 0000000000000000 [ 139.269915] FS: 0000000000000000(0000) GS:ffff88001fc00000(0000) knlGS:0000000000000000 [ 139.269915] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 139.269915] CR2: 0000000000000004 CR3: 000000001d290000 CR4: 00000000000006f0 [ 139.269915] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 139.269915] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 139.269915] Stack: [ 139.269915] 000000001b633d98 0000000000000246 ffff88001df1dc00 ffff88001cc37a00 [ 139.269915] ffff88001bc35e60 0000000000000000 ffff88001ffa0a48 ffff88001bc35ee0 [ 139.269915] ffff88001b633e08 ffffffffa02704b5 0000000000010000 ffff88001cc37a70 [ 139.269915] Call Trace: [ 139.269915] [] __rpc_execute+0x1d5/0x400 [sunrpc] [ 139.269915] [] rpc_async_schedule+0x26/0x30 [sunrpc] [ 139.269915] [] process_one_work+0x17b/0x460 [ 139.269915] [] worker_thread+0x11b/0x400 [ 139.269915] [] ? rescuer_thread+0x3e0/0x3e0 [ 139.269915] [] kthread+0xc0/0xd0 [ 139.269915] [] ? kthread_create_on_node+0x110/0x110 [ 139.269915] [] ret_from_fork+0x7c/0xb0 [ 139.269915] [] ? kthread_create_on_node+0x110/0x110 [ 139.269915] Code: 4c 8b 45 c8 48 8d 7d d0 89 4d c4 41 89 c9 b9 28 00 00 00 e8 9d b4 e9 e0 48 85 c0 49 89 c5 74 a2 48 89 c7 e8 9d 3f e9 e0 48 89 c2 <41> 8b 46 04 48 8b 7d d0 4c 89 e9 4c 89 e6 89 42 0c 0f b7 83 d4 [ 139.269915] RIP [] ftrace_raw_event_rpc_task_running+0x86/0xf0 [sunrpc] [ 139.269915] RSP [ 139.269915] CR2: 0000000000000004 [ 140.946406] ---[ end trace ba486328b98d7622 ]--- Signed-off-by: Ditang Chen Signed-off-by: Trond Myklebust diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index ddc179b..1fef3e6 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h @@ -83,7 +83,7 @@ DECLARE_EVENT_CLASS(rpc_task_running, ), TP_fast_assign( - __entry->client_id = clnt->cl_clid; + __entry->client_id = clnt ? clnt->cl_clid : -1; __entry->task_id = task->tk_pid; __entry->action = action; __entry->runstate = task->tk_runstate; @@ -91,7 +91,7 @@ DECLARE_EVENT_CLASS(rpc_task_running, __entry->flags = task->tk_flags; ), - TP_printk("task:%u@%u flags=%4.4x state=%4.4lx status=%d action=%pf", + TP_printk("task:%u@%d flags=%4.4x state=%4.4lx status=%d action=%pf", __entry->task_id, __entry->client_id, __entry->flags, __entry->runstate, -- cgit v0.10.2 From b01d4e68933ec23e43b1046fa35d593cefcf37d1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 7 Mar 2014 18:58:40 -0800 Subject: x86: fix compile error due to X86_TRAP_NMI use in asm files It's an enum, not a #define, you can't use it in asm files. Introduced in commit 5fa10196bdb5 ("x86: Ignore NMIs that come in during early boot"), and sadly I didn't compile-test things like I should have before pushing out. My weak excuse is that the x86 tree generally doesn't introduce stupid things like this (and the ARM pull afterwards doesn't cause me to do a compile-test either, since I don't cross-compile). Cc: Don Zickus Cc: H. Peter Anvin Signed-off-by: Linus Torvalds diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index d2a2159..f36bd42 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -545,7 +545,7 @@ ENDPROC(early_idt_handlers) ENTRY(early_idt_handler) cld - cmpl $X86_TRAP_NMI,(%esp) + cmpl $2,(%esp) # X86_TRAP_NMI je is_nmi # Ignore NMI cmpl $2,%ss:early_recursion_flag diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 33f36c7..a468c0a 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -343,7 +343,7 @@ early_idt_handlers: ENTRY(early_idt_handler) cld - cmpl $X86_TRAP_NMI,(%rsp) + cmpl $2,(%rsp) # X86_TRAP_NMI je is_nmi # Ignore NMI cmpl $2,early_recursion_flag(%rip) -- cgit v0.10.2 From 22066226b50e40591d67aef1d5525abce7515df2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Mar 2014 11:44:08 +0800 Subject: ASoC: pcm512x: Split out bus drivers Move to the new style of defining the bus interfaces in separate modules in order to simplify dependencies. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index fa47a83..cebe3ce 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -59,7 +59,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM1792A if SPI_MASTER select SND_SOC_PCM3008 - select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI + select SND_SOC_PCM512x_I2C if I2C + select SND_SOC_PCM512x_SPI if SPI_MASTER select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C @@ -315,8 +316,19 @@ config SND_SOC_PCM3008 tristate config SND_SOC_PCM512x - tristate "Texas Instruments PCM512x CODECs" - select REGMAP + tristate + +config SND_SOC_PCM512x_I2C + tristate "Texas Instruments PCM512x CODECs - I2C" + depends on I2C + select SND_SOC_PCM512x + select REGMAP_I2C + +config SND_SOC_PCM512x_SPI + tristate "Texas Instruments PCM512x CODECs - SPI" + depends on SPI_MASTER + select SND_SOC_PCM512x + select REGMAP_SPI config SND_SOC_RT5631 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d3b536f..c1191c0 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -47,6 +47,8 @@ snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm1792a-codec-objs := pcm1792a.o snd-soc-pcm3008-objs := pcm3008.o snd-soc-pcm512x-objs := pcm512x.o +snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o +snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o snd-soc-sgtl5000-objs := sgtl5000.o @@ -181,6 +183,8 @@ obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o +obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o +obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c new file mode 100644 index 0000000..4d62230 --- /dev/null +++ b/sound/soc/codecs/pcm512x-i2c.c @@ -0,0 +1,71 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include + +#include "pcm512x.h" + +static int pcm512x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return pcm512x_probe(&i2c->dev, regmap); +} + +static int pcm512x_i2c_remove(struct i2c_client *i2c) +{ + pcm512x_remove(&i2c->dev); + return 0; +} + +static const struct i2c_device_id pcm512x_i2c_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static struct i2c_driver pcm512x_i2c_driver = { + .probe = pcm512x_i2c_probe, + .remove = pcm512x_i2c_remove, + .id_table = pcm512x_i2c_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; + +module_i2c_driver(pcm512x_i2c_driver); + +MODULE_DESCRIPTION("ASoC PCM512x codec driver - I2C"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c new file mode 100644 index 0000000..f297058 --- /dev/null +++ b/sound/soc/codecs/pcm512x-spi.c @@ -0,0 +1,69 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include + +#include "pcm512x.h" + +static int pcm512x_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + return ret; + } + + return pcm512x_probe(&spi->dev, regmap); +} + +static int pcm512x_spi_remove(struct spi_device *spi) +{ + pcm512x_remove(&spi->dev); + return 0; +} + +static const struct spi_device_id pcm512x_spi_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { }, +}; +MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static struct spi_driver pcm512x_spi_driver = { + .probe = pcm512x_spi_probe, + .remove = pcm512x_spi_remove, + .id_table = pcm512x_spi_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; + +module_spi_driver(pcm512x_spi_driver); diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 3a0bbb6..0c90705 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -18,11 +18,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -375,7 +373,7 @@ static const struct regmap_range_cfg pcm512x_range = { .window_start = 0, .window_len = 0x100, }; -static const struct regmap_config pcm512x_regmap = { +const struct regmap_config pcm512x_regmap = { .reg_bits = 8, .val_bits = 8, @@ -390,15 +388,9 @@ static const struct regmap_config pcm512x_regmap = { .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL_GPL(pcm512x_regmap); -static const struct of_device_id pcm512x_of_match[] = { - { .compatible = "ti,pcm5121", }, - { .compatible = "ti,pcm5122", }, - { } -}; -MODULE_DEVICE_TABLE(of, pcm512x_of_match); - -static int pcm512x_probe(struct device *dev, struct regmap *regmap) +int pcm512x_probe(struct device *dev, struct regmap *regmap) { struct pcm512x_priv *pcm512x; int i, ret; @@ -510,8 +502,9 @@ err: pcm512x->supplies); return ret; } +EXPORT_SYMBOL_GPL(pcm512x_probe); -static void pcm512x_remove(struct device *dev) +void pcm512x_remove(struct device *dev) { struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); @@ -522,6 +515,7 @@ static void pcm512x_remove(struct device *dev) regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), pcm512x->supplies); } +EXPORT_SYMBOL_GPL(pcm512x_remove); static int pcm512x_suspend(struct device *dev) { @@ -585,122 +579,10 @@ static int pcm512x_resume(struct device *dev) return 0; } -static const struct dev_pm_ops pcm512x_pm_ops = { +const struct dev_pm_ops pcm512x_pm_ops = { SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) }; - -#if IS_ENABLED(CONFIG_I2C) -static int pcm512x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct regmap *regmap; - - regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - return pcm512x_probe(&i2c->dev, regmap); -} - -static int pcm512x_i2c_remove(struct i2c_client *i2c) -{ - pcm512x_remove(&i2c->dev); - return 0; -} - -static const struct i2c_device_id pcm512x_i2c_id[] = { - { "pcm5121", }, - { "pcm5122", }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); - -static struct i2c_driver pcm512x_i2c_driver = { - .probe = pcm512x_i2c_probe, - .remove = pcm512x_i2c_remove, - .id_table = pcm512x_i2c_id, - .driver = { - .name = "pcm512x", - .owner = THIS_MODULE, - .of_match_table = pcm512x_of_match, - .pm = &pcm512x_pm_ops, - }, -}; -#endif - -#if defined(CONFIG_SPI_MASTER) -static int pcm512x_spi_probe(struct spi_device *spi) -{ - struct regmap *regmap; - int ret; - - regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); - if (IS_ERR(regmap)) { - ret = PTR_ERR(regmap); - return ret; - } - - return pcm512x_probe(&spi->dev, regmap); -} - -static int pcm512x_spi_remove(struct spi_device *spi) -{ - pcm512x_remove(&spi->dev); - return 0; -} - -static const struct spi_device_id pcm512x_spi_id[] = { - { "pcm5121", }, - { "pcm5122", }, - { }, -}; -MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); - -static struct spi_driver pcm512x_spi_driver = { - .probe = pcm512x_spi_probe, - .remove = pcm512x_spi_remove, - .id_table = pcm512x_spi_id, - .driver = { - .name = "pcm512x", - .owner = THIS_MODULE, - .of_match_table = pcm512x_of_match, - .pm = &pcm512x_pm_ops, - }, -}; -#endif - -static int __init pcm512x_modinit(void) -{ - int ret = 0; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&pcm512x_i2c_driver); - if (ret) { - printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&pcm512x_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(pcm512x_modinit); - -static void __exit pcm512x_exit(void) -{ -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&pcm512x_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&pcm512x_spi_driver); -#endif -} -module_exit(pcm512x_exit); +EXPORT_SYMBOL_GPL(pcm512x_pm_ops); MODULE_DESCRIPTION("ASoC PCM512x codec driver"); MODULE_AUTHOR("Mark Brown "); diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index ac4a52c..6ee76aa 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h @@ -17,6 +17,9 @@ #ifndef _SND_SOC_PCM512X #define _SND_SOC_PCM512X +#include +#include + #define PCM512x_VIRT_BASE 0x100 #define PCM512x_PAGE_LEN 0x100 #define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n)) @@ -159,4 +162,10 @@ #define PCM512x_AGBR_SHIFT 0 #define PCM512x_AGBL_SHIFT 4 +extern const struct dev_pm_ops pcm512x_pm_ops; +extern const struct regmap_config pcm512x_regmap; + +int pcm512x_probe(struct device *dev, struct regmap *regmap); +void pcm512x_remove(struct device *dev); + #endif -- cgit v0.10.2 From e97db9abf99280e6ff7d9b339dd2ca4846ce2eea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Mar 2014 11:43:04 +0800 Subject: ASoC: pcm512x: Fix duplicate const warning Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 0c90705..4b4c0c7 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -201,10 +201,10 @@ static const unsigned int pcm512x_dsp_program_values[] = { 7, }; -static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, - PCM512x_DSP_PROGRAM, 0, 0x1f, - pcm512x_dsp_program_texts, - pcm512x_dsp_program_values); +static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, + PCM512x_DSP_PROGRAM, 0, 0x1f, + pcm512x_dsp_program_texts, + pcm512x_dsp_program_values); static const char * const pcm512x_clk_missing_text[] = { "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" -- cgit v0.10.2 From 40423285a10e317b8e89e430779633eaef0b4add Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 8 Mar 2014 13:31:06 +0400 Subject: ASoC: tlv320aic23: add missing EXPORT_SYMBOLs This fixes the following build errors when aic23 is configured as module: >> ERROR: "tlv320aic23_probe" >> [sound/soc/codecs/snd-soc-tlv320aic23-i2c.ko] undefined! >> ERROR: "tlv320aic23_regmap" >> [sound/soc/codecs/snd-soc-tlv320aic23-i2c.ko] undefined! Signed-off-by: Max Filippov Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index ab369ae..7b4cfef 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -59,6 +59,7 @@ const struct regmap_config tlv320aic23_regmap = { .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL(tlv320aic23_regmap); static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -634,6 +635,7 @@ int tlv320aic23_probe(struct device *dev, struct regmap *regmap) return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); } +EXPORT_SYMBOL(tlv320aic23_probe); MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS "); -- cgit v0.10.2 From da28ed585b26dc6eb0c8d897a9b842a86dd6a659 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:17 +0000 Subject: ASoC: arizona: An OUTDIV of 1 is not valid, avoid this One is not a valid value for the OUTDIV start searching at 2 instead. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e4295fe..d908046 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1406,7 +1406,7 @@ static int arizona_calc_fll(struct arizona_fll *fll, Fref /= div; /* Fvco should be over the targt; don't check the upper bound */ - div = 1; + div = 2; while (Fout * div < 90000000 * fll->vco_mult) { div++; if (div > 7) { -- cgit v0.10.2 From 87383ac5a73ff34c60d3ea483bf24cabb27fb522 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:18 +0000 Subject: ASoC: arizona: Add defines for FLL configuration constants Improve readability by adding defines for some of the constants associated with FLL configuration. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index d908046..3d4408d 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -53,6 +53,12 @@ #define ARIZONA_AIF_RX_ENABLES 0x1A #define ARIZONA_AIF_FORCE_WRITE 0x1B +#define ARIZONA_FLL_MAX_FREF 13500000 +#define ARIZONA_FLL_MIN_FVCO 90000000 +#define ARIZONA_FLL_MAX_REFDIV 8 +#define ARIZONA_FLL_MIN_OUTDIV 2 +#define ARIZONA_FLL_MAX_OUTDIV 7 + #define arizona_fll_err(_fll, fmt, ...) \ dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) #define arizona_fll_warn(_fll, fmt, ...) \ @@ -1390,11 +1396,11 @@ static int arizona_calc_fll(struct arizona_fll *fll, /* Fref must be <=13.5MHz */ div = 1; cfg->refdiv = 0; - while ((Fref / div) > 13500000) { + while ((Fref / div) > ARIZONA_FLL_MAX_FREF) { div *= 2; cfg->refdiv++; - if (div > 8) { + if (div > ARIZONA_FLL_MAX_REFDIV) { arizona_fll_err(fll, "Can't scale %dMHz in to <=13.5MHz\n", Fref); @@ -1406,10 +1412,10 @@ static int arizona_calc_fll(struct arizona_fll *fll, Fref /= div; /* Fvco should be over the targt; don't check the upper bound */ - div = 2; - while (Fout * div < 90000000 * fll->vco_mult) { + div = ARIZONA_FLL_MIN_OUTDIV; + while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { div++; - if (div > 7) { + if (div > ARIZONA_FLL_MAX_OUTDIV) { arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", Fout); return -EINVAL; -- cgit v0.10.2 From 61719db8141acde1a6293bbbddc733655defcc3c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:19 +0000 Subject: ASoC: arizona: Move set of OUTDIV in to arizona_apply_fll Since we know in arizona_apply_fll if we are setting the sync or ref path there is no need to set the outdiv seperately anymore. This patch moves this from arizona_enable_fll to arizona_apply_fll. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 3d4408d..9afd8c4 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1502,14 +1502,18 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); - if (sync) - regmap_update_bits_async(arizona->regmap, base + 0x7, - ARIZONA_FLL1_GAIN_MASK, - cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); - else - regmap_update_bits_async(arizona->regmap, base + 0x9, - ARIZONA_FLL1_GAIN_MASK, - cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + if (sync) { + regmap_update_bits(arizona->regmap, base + 0x7, + ARIZONA_FLL1_GAIN_MASK, + cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + } else { + regmap_update_bits(arizona->regmap, base + 0x5, + ARIZONA_FLL1_OUTDIV_MASK, + cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); + regmap_update_bits(arizona->regmap, base + 0x9, + ARIZONA_FLL1_GAIN_MASK, + cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + } regmap_update_bits_async(arizona->regmap, base + 2, ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, @@ -1546,10 +1550,6 @@ static void arizona_enable_fll(struct arizona_fll *fll, */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - regmap_update_bits_async(arizona->regmap, fll->base + 5, - ARIZONA_FLL1_OUTDIV_MASK, - ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); - arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, false); if (fll->sync_src >= 0) { @@ -1558,10 +1558,6 @@ static void arizona_enable_fll(struct arizona_fll *fll, use_sync = true; } } else if (fll->sync_src >= 0) { - regmap_update_bits_async(arizona->regmap, fll->base + 5, - ARIZONA_FLL1_OUTDIV_MASK, - sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); - arizona_apply_fll(arizona, fll->base, sync, fll->sync_src, false); -- cgit v0.10.2 From 23f785a8bc33a98c4c384a653b9bff9c0cc3591d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:20 +0000 Subject: ASoC: arizona: Move calculation of FLL configuration Currently the FLL configuration is calculated before it is known which FLL path the configuration will be applied to. Newer versions of the IP have differences in the configuration required for each FLL path, which makes it complicated to calculate the FLL configuration in advance. This patch simply checks the validity of a requested input and output frequency before we know which FLL path they will be applied to and saves the actual calculation of the configuration until we know where the settings will be applied. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9afd8c4..7398c69 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1383,6 +1383,29 @@ struct arizona_fll_cfg { int gain; }; +static int arizona_validate_fll(struct arizona_fll *fll, + unsigned int Fref, + unsigned int Fout) +{ + unsigned int Fvco_min; + + if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { + arizona_fll_err(fll, + "Can't scale %dMHz in to <=13.5MHz\n", + Fref); + return -EINVAL; + } + + Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult; + if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) { + arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", + Fout); + return -EINVAL; + } + + return 0; +} + static int arizona_calc_fll(struct arizona_fll *fll, struct arizona_fll_cfg *cfg, unsigned int Fref, @@ -1400,12 +1423,8 @@ static int arizona_calc_fll(struct arizona_fll *fll, div *= 2; cfg->refdiv++; - if (div > ARIZONA_FLL_MAX_REFDIV) { - arizona_fll_err(fll, - "Can't scale %dMHz in to <=13.5MHz\n", - Fref); + if (div > ARIZONA_FLL_MAX_REFDIV) return -EINVAL; - } } /* Apply the division for our remaining calculations */ @@ -1415,11 +1434,8 @@ static int arizona_calc_fll(struct arizona_fll *fll, div = ARIZONA_FLL_MIN_OUTDIV; while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { div++; - if (div > ARIZONA_FLL_MAX_OUTDIV) { - arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", - Fout); + if (div > ARIZONA_FLL_MAX_OUTDIV) return -EINVAL; - } } target = Fout * div / fll->vco_mult; cfg->outdiv = div; @@ -1536,13 +1552,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll) return reg & ARIZONA_FLL1_ENA; } -static void arizona_enable_fll(struct arizona_fll *fll, - struct arizona_fll_cfg *ref, - struct arizona_fll_cfg *sync) +static void arizona_enable_fll(struct arizona_fll *fll) { struct arizona *arizona = fll->arizona; int ret; bool use_sync = false; + struct arizona_fll_cfg cfg; /* * If we have both REFCLK and SYNCCLK then enable both, @@ -1550,15 +1565,21 @@ static void arizona_enable_fll(struct arizona_fll *fll, */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, + arizona_calc_fll(fll, &cfg, fll->ref_freq, fll->fout); + + arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { - arizona_apply_fll(arizona, fll->base + 0x10, sync, + arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + + arizona_apply_fll(arizona, fll->base + 0x10, &cfg, fll->sync_src, true); use_sync = true; } } else if (fll->sync_src >= 0) { - arizona_apply_fll(arizona, fll->base, sync, + arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + + arizona_apply_fll(arizona, fll->base, &cfg, fll->sync_src, false); regmap_update_bits_async(arizona->regmap, fll->base + 0x11, @@ -1620,32 +1641,22 @@ static void arizona_disable_fll(struct arizona_fll *fll) int arizona_set_fll_refclk(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { - struct arizona_fll_cfg ref, sync; int ret; if (fll->ref_src == source && fll->ref_freq == Fref) return 0; - if (fll->fout) { - if (Fref > 0) { - ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); - if (ret != 0) - return ret; - } - - if (fll->sync_src >= 0) { - ret = arizona_calc_fll(fll, &sync, fll->sync_freq, - fll->fout); - if (ret != 0) - return ret; - } + if (fll->fout && Fref > 0) { + ret = arizona_validate_fll(fll, Fref, fll->fout); + if (ret != 0) + return ret; } fll->ref_src = source; fll->ref_freq = Fref; if (fll->fout && Fref > 0) { - arizona_enable_fll(fll, &ref, &sync); + arizona_enable_fll(fll); } return 0; @@ -1655,7 +1666,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); int arizona_set_fll(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { - struct arizona_fll_cfg ref, sync; int ret; if (fll->sync_src == source && @@ -1664,13 +1674,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source, if (Fout) { if (fll->ref_src >= 0) { - ret = arizona_calc_fll(fll, &ref, fll->ref_freq, - Fout); + ret = arizona_validate_fll(fll, fll->ref_freq, Fout); if (ret != 0) return ret; } - ret = arizona_calc_fll(fll, &sync, Fref, Fout); + ret = arizona_validate_fll(fll, Fref, Fout); if (ret != 0) return ret; } @@ -1680,7 +1689,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source, fll->fout = Fout; if (Fout) { - arizona_enable_fll(fll, &ref, &sync); + arizona_enable_fll(fll); } else { arizona_disable_fll(fll); } -- cgit v0.10.2 From 8ccefcd265b486186c94ea70c77511e7c570347d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:21 +0000 Subject: ASoC: arizona: Don't pass Fout into arizona_calc_fll As we now calculate the FLL configuration at a later stage in the process the fout member of the FLL structure will contain the desired Fout frequency so no need to pass this in seperately. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 7398c69..7b1354a 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1408,13 +1408,12 @@ static int arizona_validate_fll(struct arizona_fll *fll, static int arizona_calc_fll(struct arizona_fll *fll, struct arizona_fll_cfg *cfg, - unsigned int Fref, - unsigned int Fout) + unsigned int Fref) { unsigned int target, div, gcd_fll; int i, ratio; - arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout); + arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout); /* Fref must be <=13.5MHz */ div = 1; @@ -1432,12 +1431,12 @@ static int arizona_calc_fll(struct arizona_fll *fll, /* Fvco should be over the targt; don't check the upper bound */ div = ARIZONA_FLL_MIN_OUTDIV; - while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { + while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { div++; if (div > ARIZONA_FLL_MAX_OUTDIV) return -EINVAL; } - target = Fout * div / fll->vco_mult; + target = fll->fout * div / fll->vco_mult; cfg->outdiv = div; arizona_fll_dbg(fll, "Fvco=%dHz\n", target); @@ -1565,19 +1564,19 @@ static void arizona_enable_fll(struct arizona_fll *fll) */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - arizona_calc_fll(fll, &cfg, fll->ref_freq, fll->fout); + arizona_calc_fll(fll, &cfg, fll->ref_freq); arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + arizona_calc_fll(fll, &cfg, fll->sync_freq); arizona_apply_fll(arizona, fll->base + 0x10, &cfg, fll->sync_src, true); use_sync = true; } } else if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + arizona_calc_fll(fll, &cfg, fll->sync_freq); arizona_apply_fll(arizona, fll->base, &cfg, fll->sync_src, false); -- cgit v0.10.2 From f641aec62c948c7754429136ad176824fbb97238 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:22 +0000 Subject: ASoC: arizona: Calculate OUTDIV first OUTDIV will remain unchanged whilst the rest of the FLL configuration is calculated so do this first. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 7b1354a..1f106ab 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1415,6 +1415,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout); + /* Fvco should be over the targt; don't check the upper bound */ + div = ARIZONA_FLL_MIN_OUTDIV; + while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { + div++; + if (div > ARIZONA_FLL_MAX_OUTDIV) + return -EINVAL; + } + target = fll->fout * div / fll->vco_mult; + cfg->outdiv = div; + + arizona_fll_dbg(fll, "Fvco=%dHz\n", target); + /* Fref must be <=13.5MHz */ div = 1; cfg->refdiv = 0; @@ -1429,18 +1441,6 @@ static int arizona_calc_fll(struct arizona_fll *fll, /* Apply the division for our remaining calculations */ Fref /= div; - /* Fvco should be over the targt; don't check the upper bound */ - div = ARIZONA_FLL_MIN_OUTDIV; - while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { - div++; - if (div > ARIZONA_FLL_MAX_OUTDIV) - return -EINVAL; - } - target = fll->fout * div / fll->vco_mult; - cfg->outdiv = div; - - arizona_fll_dbg(fll, "Fvco=%dHz\n", target); - /* Find an appropraite FLL_FRATIO and factor it out of the target */ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { -- cgit v0.10.2 From 5a3935c7643966e4172e7a704a48a35f9b4dc668 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:23 +0000 Subject: ASoC: arizona: Calculate FLL gain last No part of the FLL calculation depends on the value determined for the gain but the gain does depend on other values. In preparation for future updates this patch moves the gain to be the last thing calculated. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 1f106ab..219d1d5 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1455,18 +1455,6 @@ static int arizona_calc_fll(struct arizona_fll *fll, return -EINVAL; } - for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { - if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { - cfg->gain = fll_gains[i].gain; - break; - } - } - if (i == ARRAY_SIZE(fll_gains)) { - arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", - Fref); - return -EINVAL; - } - cfg->n = target / (ratio * Fref); if (target % (ratio * Fref)) { @@ -1490,6 +1478,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, cfg->lambda >>= 1; } + for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { + if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { + cfg->gain = fll_gains[i].gain; + break; + } + } + if (i == ARRAY_SIZE(fll_gains)) { + arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", + Fref); + return -EINVAL; + } + arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", cfg->n, cfg->theta, cfg->lambda); arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", -- cgit v0.10.2 From 9dd02e89cb920a727349f8852430fdc92cc729f4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:24 +0000 Subject: mfd: arizona: Add support for new fratio encoding Newer IP has an expanded encoding for the fratio bits. As the additional used bits are unused on older IP simply expand the field to the new size. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index fdf3aa3..3ddaa63 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -1702,9 +1702,9 @@ /* * R373 (0x175) - FLL1 Control 5 */ -#define ARIZONA_FLL1_FRATIO_MASK 0x0700 /* FLL1_FRATIO - [10:8] */ -#define ARIZONA_FLL1_FRATIO_SHIFT 8 /* FLL1_FRATIO - [10:8] */ -#define ARIZONA_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [10:8] */ +#define ARIZONA_FLL1_FRATIO_MASK 0x0F00 /* FLL1_FRATIO - [11:8] */ +#define ARIZONA_FLL1_FRATIO_SHIFT 8 /* FLL1_FRATIO - [11:8] */ +#define ARIZONA_FLL1_FRATIO_WIDTH 4 /* FLL1_FRATIO - [11:8] */ #define ARIZONA_FLL1_OUTDIV_MASK 0x000E /* FLL1_OUTDIV - [3:1] */ #define ARIZONA_FLL1_OUTDIV_SHIFT 1 /* FLL1_OUTDIV - [3:1] */ #define ARIZONA_FLL1_OUTDIV_WIDTH 3 /* FLL1_OUTDIV - [3:1] */ -- cgit v0.10.2 From d0800342bba71e7f11b2a67a29cf00c41ad1a3e4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:25 +0000 Subject: ASoC: arizona: Support new fratio encoding on the wm5110 rev D The reference clock path on newer IP FLLs requires a different configuration, and should avoid integer mode operation. This patch adds support for both the new encoding and updates the calculation. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 219d1d5..c388486 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -53,8 +53,10 @@ #define ARIZONA_AIF_RX_ENABLES 0x1A #define ARIZONA_AIF_FORCE_WRITE 0x1B +#define ARIZONA_FLL_VCO_CORNER 141900000 #define ARIZONA_FLL_MAX_FREF 13500000 #define ARIZONA_FLL_MIN_FVCO 90000000 +#define ARIZONA_FLL_MAX_FRATIO 16 #define ARIZONA_FLL_MAX_REFDIV 8 #define ARIZONA_FLL_MIN_OUTDIV 2 #define ARIZONA_FLL_MAX_OUTDIV 7 @@ -1406,9 +1408,99 @@ static int arizona_validate_fll(struct arizona_fll *fll, return 0; } +static int arizona_find_fratio(unsigned int Fref, int *fratio) +{ + int i; + + /* Find an appropriate FLL_FRATIO */ + for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { + if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { + if (fratio) + *fratio = fll_fratios[i].fratio; + return fll_fratios[i].ratio; + } + } + + return -EINVAL; +} + +static int arizona_calc_fratio(struct arizona_fll *fll, + struct arizona_fll_cfg *cfg, + unsigned int target, + unsigned int Fref, bool sync) +{ + int init_ratio, ratio; + int refdiv, div; + + /* Fref must be <=13.5MHz, find initial refdiv */ + div = 1; + cfg->refdiv = 0; + while (Fref > ARIZONA_FLL_MAX_FREF) { + div *= 2; + Fref /= 2; + cfg->refdiv++; + + if (div > ARIZONA_FLL_MAX_REFDIV) + return -EINVAL; + } + + /* Find an appropriate FLL_FRATIO */ + init_ratio = arizona_find_fratio(Fref, &cfg->fratio); + if (init_ratio < 0) { + arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", + Fref); + return init_ratio; + } + + switch (fll->arizona->type) { + case WM5110: + if (fll->arizona->rev < 3 || sync) + return init_ratio; + break; + default: + return init_ratio; + } + + cfg->fratio = init_ratio - 1; + + /* Adjust FRATIO/refdiv to avoid integer mode if possible */ + refdiv = cfg->refdiv; + + while (div <= ARIZONA_FLL_MAX_REFDIV) { + for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; + ratio++) { + if (target % (ratio * Fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } + } + + for (ratio = init_ratio - 1; ratio >= 0; ratio--) { + if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) < + Fref) + break; + + if (target % (ratio * Fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } + } + + div *= 2; + Fref /= 2; + refdiv++; + init_ratio = arizona_find_fratio(Fref, NULL); + } + + arizona_fll_warn(fll, "Falling back to integer mode operation\n"); + return cfg->fratio + 1; +} + static int arizona_calc_fll(struct arizona_fll *fll, struct arizona_fll_cfg *cfg, - unsigned int Fref) + unsigned int Fref, bool sync) { unsigned int target, div, gcd_fll; int i, ratio; @@ -1427,33 +1519,13 @@ static int arizona_calc_fll(struct arizona_fll *fll, arizona_fll_dbg(fll, "Fvco=%dHz\n", target); - /* Fref must be <=13.5MHz */ - div = 1; - cfg->refdiv = 0; - while ((Fref / div) > ARIZONA_FLL_MAX_FREF) { - div *= 2; - cfg->refdiv++; - - if (div > ARIZONA_FLL_MAX_REFDIV) - return -EINVAL; - } + /* Find an appropriate FLL_FRATIO and refdiv */ + ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync); + if (ratio < 0) + return ratio; /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - cfg->fratio = fll_fratios[i].fratio; - ratio = fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", - Fref); - return -EINVAL; - } + Fref = Fref / (1 << cfg->refdiv); cfg->n = target / (ratio * Fref); @@ -1564,19 +1636,19 @@ static void arizona_enable_fll(struct arizona_fll *fll) */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - arizona_calc_fll(fll, &cfg, fll->ref_freq); + arizona_calc_fll(fll, &cfg, fll->ref_freq, false); arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq); + arizona_calc_fll(fll, &cfg, fll->sync_freq, true); arizona_apply_fll(arizona, fll->base + 0x10, &cfg, fll->sync_src, true); use_sync = true; } } else if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq); + arizona_calc_fll(fll, &cfg, fll->sync_freq, false); arizona_apply_fll(arizona, fll->base, &cfg, fll->sync_src, false); -- cgit v0.10.2 From 64ebdec36a2a70dc9805c7172b50c43d868dedb6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2014 15:03:55 +0200 Subject: ASoC: davinci-mcasp: Rename the pointer to davinci dma_params as dma_params It is quite confusing to name the pointer to davinci_pcm_dma_params as dma_data. Rename the pointer to avoid confusion. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 35b9b55..b0ae067 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1025,7 +1025,7 @@ nodata: static int davinci_mcasp_probe(struct platform_device *pdev) { - struct davinci_pcm_dma_params *dma_data; + struct davinci_pcm_dma_params *dma_params; struct resource *mem, *ioarea, *res, *dat; struct davinci_mcasp_pdata *pdata; struct davinci_mcasp *mcasp; @@ -1094,41 +1094,41 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (dat) mcasp->dat_port = true; - dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_playback; + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; + dma_params->asp_chan_q = pdata->asp_chan_q; + dma_params->ram_chan_q = pdata->ram_chan_q; + dma_params->sram_pool = pdata->sram_pool; + dma_params->sram_size = pdata->sram_size_playback; if (dat) - dma_data->dma_addr = dat->start; + dma_params->dma_addr = dat->start; else - dma_data->dma_addr = mem->start + pdata->tx_dma_offset; + dma_params->dma_addr = mem->start + pdata->tx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr; + mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_params->dma_addr; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) - dma_data->channel = res->start; + dma_params->channel = res->start; else - dma_data->channel = pdata->tx_dma_channel; + dma_params->channel = pdata->tx_dma_channel; - dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_capture; + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; + dma_params->asp_chan_q = pdata->asp_chan_q; + dma_params->ram_chan_q = pdata->ram_chan_q; + dma_params->sram_pool = pdata->sram_pool; + dma_params->sram_size = pdata->sram_size_capture; if (dat) - dma_data->dma_addr = dat->start; + dma_params->dma_addr = dat->start; else - dma_data->dma_addr = mem->start + pdata->rx_dma_offset; + dma_params->dma_addr = mem->start + pdata->rx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr; + mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_params->dma_addr; if (mcasp->version < MCASP_VERSION_3) { mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; - /* dma_data->dma_addr is pointing to the data port address */ + /* dma_params->dma_addr is pointing to the data port address */ mcasp->dat_port = true; } else { mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; @@ -1136,9 +1136,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (res) - dma_data->channel = res->start; + dma_params->channel = res->start; else - dma_data->channel = pdata->rx_dma_channel; + dma_params->channel = pdata->rx_dma_channel; /* Unconditional dmaengine stuff */ mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx"; -- cgit v0.10.2 From b46f2c5c0054153a6e5f76b6a943df5d837879f6 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 7 Mar 2014 14:58:32 +0200 Subject: ASoC: tlv320aic32x4: Sort Makefile in alphabetic order The tlv320aic32x4 related lines were wrongly placed after tlv320aic3x lines. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc12676..1deeb20 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -64,8 +64,8 @@ snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o -snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o +snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o @@ -194,8 +194,8 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o -obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o +obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o -- cgit v0.10.2 From 4c7b70406e5aadc1c78db4d375d5744df65c5b58 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 9 Mar 2014 18:30:50 +0100 Subject: Revert "ACPI / sleep: pm_power_off needs more sanity checks to be installed" Revert commit 3130497f5bab ("ACPI / sleep: pm_power_off needs more sanity checks to be installed") that breaks power ACPI power off on a lot of systems, because it checks wrong registers. Fixes: 3130497f5bab ("ACPI / sleep: pm_power_off needs more sanity checks to be installed") Signed-off-by: Rafael J. Wysocki Signed-off-by: Linus Torvalds diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index b0f6c4a..b718806 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -807,12 +807,7 @@ int __init acpi_sleep_init(void) acpi_sleep_hibernate_setup(); status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); - /* - * Check both ACPI S5 object and ACPI sleep registers to - * install pm_power_off_prepare/pm_power_off hook - */ - if (ACPI_SUCCESS(status) && acpi_gbl_FADT.sleep_control.address - && acpi_gbl_FADT.sleep_status.address) { + if (ACPI_SUCCESS(status)) { sleep_states[ACPI_STATE_S5] = 1; pm_power_off_prepare = acpi_power_off_prepare; pm_power_off = acpi_power_off; -- cgit v0.10.2 From 979e0d74651ba5aa533277f2a6423d0f982fb6f6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Sun, 9 Mar 2014 08:21:58 +0000 Subject: KEYS: Make the keyring cycle detector ignore other keyrings of the same name This fixes CVE-2014-0102. The following command sequence produces an oops: keyctl new_session i=`keyctl newring _ses @s` keyctl link @s $i The problem is that search_nested_keyrings() sees two keyrings that have matching type and description, so keyring_compare_object() returns true. s_n_k() then passes the key to the iterator function - keyring_detect_cycle_iterator() - which *should* check to see whether this is the keyring of interest, not just one with the same name. Because assoc_array_find() will return one and only one match, I assumed that the iterator function would only see an exact match or never be called - but the iterator isn't only called from assoc_array_find()... The oops looks something like this: kernel BUG at /data/fs/linux-2.6-fscache/security/keys/keyring.c:1003! invalid opcode: 0000 [#1] SMP ... RIP: keyring_detect_cycle_iterator+0xe/0x1f ... Call Trace: search_nested_keyrings+0x76/0x2aa __key_link_check_live_key+0x50/0x5f key_link+0x4e/0x85 keyctl_keyring_link+0x60/0x81 SyS_keyctl+0x65/0xe4 tracesys+0xdd/0xe2 The fix is to make keyring_detect_cycle_iterator() check that the key it has is the key it was actually looking for rather than calling BUG_ON(). A testcase has been included in the keyutils testsuite for this: http://git.kernel.org/cgit/linux/kernel/git/dhowells/keyutils.git/commit/?id=891f3365d07f1996778ade0e3428f01878a1790b Reported-by: Tommi Rantala Signed-off-by: David Howells Acked-by: James Morris Signed-off-by: Linus Torvalds diff --git a/security/keys/keyring.c b/security/keys/keyring.c index d46cbc5..2fb2576 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -1000,7 +1000,11 @@ static int keyring_detect_cycle_iterator(const void *object, kenter("{%d}", key->serial); - BUG_ON(key != ctx->match_data); + /* We might get a keyring with matching index-key that is nonetheless a + * different keyring. */ + if (key != ctx->match_data) + return 0; + ctx->result = ERR_PTR(-EDEADLK); return 1; } -- cgit v0.10.2 From fa389e220254c69ffae0d403eac4146171062d08 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 9 Mar 2014 19:41:57 -0700 Subject: Linux 3.14-rc6 diff --git a/Makefile b/Makefile index 78209ee..1a2628e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v0.10.2 From 12ffa6fc1958879a81b6af1624c1a2edd83ec04a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 9 Mar 2014 19:37:56 -0700 Subject: ASoC: simple-card: card name can be option snd_card.name is now option on DT case. non-DT case can follow same style, and it is understandable from platform point of view. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7cabcc5..5dd4769 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -287,7 +287,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) } if (!cinfo->name || - !cinfo->card || !cinfo->codec_dai.name || !cinfo->codec || !cinfo->platform || @@ -296,7 +295,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return -EINVAL; } - priv->snd_card.name = cinfo->card; + priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name; dai_link->name = cinfo->name; dai_link->stream_name = cinfo->name; dai_link->platform_name = cinfo->platform; -- cgit v0.10.2 From b0ffe9b1ab8705eeffa72feacd791ab6fdd2a06c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 8 Mar 2014 15:47:22 +0100 Subject: ASoC: sam9g20_wm8731: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. While we are at it also remove the snd_soc_dapm_enable_pin() in the init callback. Pins are enabled by default. Signed-off-by: Lars-Peter Clausen Tested-by: Bo Shen Acked-by: Bo Shen Signed-off-by: Mark Brown diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index f15bff1..174bd54 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -155,25 +155,14 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) return ret; } - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets, - ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); - /* Set up specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - /* not connected */ snd_soc_dapm_nc_pin(dapm, "RLINEIN"); snd_soc_dapm_nc_pin(dapm, "LLINEIN"); -#ifdef ENABLE_MIC_INPUT - snd_soc_dapm_enable_pin(dapm, "Int Mic"); -#else - snd_soc_dapm_nc_pin(dapm, "Int Mic"); +#ifndef ENABLE_MIC_INPUT + snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic"); #endif - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - return 0; } @@ -194,6 +183,11 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = { .dai_link = &at91sam9g20ek_dai, .num_links = 1, .set_bias_level = at91sam9g20ek_set_bias_level, + + .dapm_widgets = at91sam9g20ek_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), }; static int at91sam9g20ek_audio_probe(struct platform_device *pdev) -- cgit v0.10.2 From 58d4d3c976b33784a1443c446a3d7203bf2153f0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Mar 2014 09:41:53 +0100 Subject: ASoC: si476x: Fix IO setup The si476x is a MFD device and the CODEC driver is using the regmap struct of the parent device, hence automatic IO setup will not work and we need to manually call snd_soc_codec_set_cache_io(). The issue was introduced commit d6173df35f ("ASoC: si476x: Remove custom register I/O implementation") Fixes: d6173df35f ("ASoC: si476x: Remove custom register I/O implementation") Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 52e7cb0..fa2b8e0 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -210,7 +210,7 @@ out: static int si476x_codec_probe(struct snd_soc_codec *codec) { codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - return 0; + return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); } static struct snd_soc_dai_ops si476x_dai_ops = { -- cgit v0.10.2 From 8eeb5c15131d7b5061c10423eda3ae4c68db4eaf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Mar 2014 09:39:24 +0100 Subject: ASoC: 88pm860: Fix IO setup The 88pm860 is a MFD device and the CODEC driver is using the regmap struct of the parent device, hence automatic IO setup will not work and we need to manually call snd_soc_codec_set_cache_io(). The issue was introduced in commit f9ded3b2e7 ("ASoC: 88pm860x: Use regmap for I/O"). Fixes: f9ded3b2e7 ("ASoC: 88pm860x: Use regmap for I/O"). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 75d0ad5..647a72c 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -1328,6 +1328,9 @@ static int pm860x_probe(struct snd_soc_codec *codec) pm860x->codec = codec; codec->control_data = pm860x->regmap; + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (ret) + return ret; for (i = 0; i < 4; i++) { ret = request_threaded_irq(pm860x->irq[i], NULL, -- cgit v0.10.2 From 32c9ba544b65991b14ede102928c552ed24d4827 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Mar 2014 17:41:45 +0100 Subject: ASoC: Consolidate snd_soc_register_dai() and snd_soc_register_dais() snd_soc_register_dais() has basically the same code as snd_soc_register_dai(), but running in a loop. The only difference is that snd_soc_register_dai() calls fmt_single_name() to generate the DAIs name and snd_soc_register_dais() calls fmt_multiple_name(). This patch pushes the check in __snd_soc_register_component() which decides whether to call snd_soc_register_dai() or snd_soc_register_dais() to snd_soc_register_dais() to decide which naming scheme to use. This allows us to remove snd_soc_register_dai(). The patch also updates snd_soc_register_dais() to unregister every DAI it finds for the component rather than trying to unregister one DAI for each DAI that was registered. Both have the same result since there won't be more DAIs than what have been registered, but the former is easier to implement. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 255eca9..c365be9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3906,100 +3906,47 @@ static inline char *fmt_multiple_name(struct device *dev, } /** - * snd_soc_register_dai - Register a DAI with the ASoC core + * snd_soc_unregister_dai - Unregister DAIs from the ASoC core * - * @component: The component the DAIs are registered for - * @dai_drv: DAI driver to use for the DAIs + * @component: The component for which the DAIs should be unregistered */ -static int snd_soc_register_dai(struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv) +static void snd_soc_unregister_dais(struct snd_soc_component *component) { - struct device *dev = component->dev; - struct snd_soc_codec *codec; - struct snd_soc_dai *dai; - - dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev)); - - dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); - if (dai == NULL) - return -ENOMEM; - - /* create DAI component name */ - dai->name = fmt_single_name(dev, &dai->id); - if (dai->name == NULL) { - kfree(dai); - return -ENOMEM; - } - - dai->component = component; - dai->dev = dev; - dai->driver = dai_drv; - dai->dapm.dev = dev; - if (!dai->driver->ops) - dai->driver->ops = &null_dai_ops; + struct snd_soc_dai *dai, *_dai; mutex_lock(&client_mutex); + list_for_each_entry_safe(dai, _dai, &dai_list, list) { + if (dai->dev != component->dev) + continue; - list_for_each_entry(codec, &codec_list, list) { - if (codec->dev == dev) { - dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", - dai->name, codec->name); - dai->codec = codec; - break; - } - } - - if (!dai->codec) - dai->dapm.idle_bias_off = 1; - - list_add(&dai->list, &dai_list); - - mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); - - return 0; -} - -/** - * snd_soc_unregister_dai - Unregister a DAI from the ASoC core - * - * @dai: DAI to unregister - */ -static void snd_soc_unregister_dai(struct device *dev) -{ - struct snd_soc_dai *dai; + list_del(&dai->list); - list_for_each_entry(dai, &dai_list, list) { - if (dev == dai->dev) - goto found; + dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", + dai->name); + kfree(dai->name); + kfree(dai); } - return; - -found: - mutex_lock(&client_mutex); - list_del(&dai->list); mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name); - kfree(dai->name); - kfree(dai); } /** - * snd_soc_register_dais - Register multiple DAIs with the ASoC core + * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs + * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the + * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, size_t count) + struct snd_soc_dai_driver *dai_drv, size_t count, + bool legacy_dai_naming) { struct device *dev = component->dev; struct snd_soc_codec *codec; struct snd_soc_dai *dai; - int i, ret = 0; + unsigned int i; + int ret; dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); @@ -4011,21 +3958,32 @@ static int snd_soc_register_dais(struct snd_soc_component *component, goto err; } - /* create DAI component name */ - dai->name = fmt_multiple_name(dev, &dai_drv[i]); + /* + * Back in the old days when we still had component-less DAIs, + * instead of having a static name, component-less DAIs would + * inherit the name of the parent device so it is possible to + * register multiple instances of the DAI. We still need to keep + * the same naming style even though those DAIs are not + * component-less anymore. + */ + if (count == 1 && legacy_dai_naming) { + dai->name = fmt_single_name(dev, &dai->id); + } else { + dai->name = fmt_multiple_name(dev, &dai_drv[i]); + if (dai_drv[i].id) + dai->id = dai_drv[i].id; + else + dai->id = i; + } if (dai->name == NULL) { kfree(dai); - ret = -EINVAL; + ret = -ENOMEM; goto err; } dai->component = component; dai->dev = dev; dai->driver = &dai_drv[i]; - if (dai->driver->id) - dai->id = dai->driver->id; - else - dai->id = i; dai->dapm.dev = dev; if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; @@ -4034,8 +3992,7 @@ static int snd_soc_register_dais(struct snd_soc_component *component, list_for_each_entry(codec, &codec_list, list) { if (codec->dev == dev) { - dev_dbg(dev, - "ASoC: Mapped DAI %s to CODEC %s\n", + dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", dai->name, codec->name); dai->codec = codec; break; @@ -4049,33 +4006,18 @@ static int snd_soc_register_dais(struct snd_soc_component *component, mutex_unlock(&client_mutex); - dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name); + dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); } return 0; err: - for (i--; i >= 0; i--) - snd_soc_unregister_dai(dev); + snd_soc_unregister_dais(component); return ret; } /** - * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core - * - * @dai: Array of DAIs to unregister - * @count: Number of DAIs - */ -static void snd_soc_unregister_dais(struct device *dev, size_t count) -{ - int i; - - for (i = 0; i < count; i++) - snd_soc_unregister_dai(dev); -} - -/** * snd_soc_register_component - Register a component with the ASoC core * */ @@ -4106,19 +4048,7 @@ __snd_soc_register_component(struct device *dev, cmpnt->dai_drv = dai_drv; cmpnt->num_dai = num_dai; - /* - * snd_soc_register_dai() uses fmt_single_name(), and - * snd_soc_register_dais() uses fmt_multiple_name() - * for dai->name which is used for name based matching - * - * this function is used from cpu/codec. - * allow_single_dai flag can ignore "codec" driver reworking - * since it had been used snd_soc_register_dais(), - */ - if ((1 == num_dai) && allow_single_dai) - ret = snd_soc_register_dai(cmpnt, dai_drv); - else - ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai); + ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, allow_single_dai); if (ret < 0) { dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto error_component_name; @@ -4173,7 +4103,7 @@ void snd_soc_unregister_component(struct device *dev) return; found: - snd_soc_unregister_dais(dev, cmpnt->num_dai); + snd_soc_unregister_dais(cmpnt); mutex_lock(&client_mutex); list_del(&cmpnt->list); -- cgit v0.10.2 From 6cc240f39d393c5878bc6cf053aa0fe8e3fe4260 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Mar 2014 17:41:46 +0100 Subject: ASoC: Pass CODEC to snd_soc_register_dais() snd_soc_register_dais() looks up the CODEC that is registering the DAIs by looping over all registered CODECs. This patch updates the code to simply pass the CODEC that registers the DAIs to snd_soc_register_dais() thus avoiding the lookup. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c365be9..cc52241 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3933,17 +3933,18 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component) * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for + * @codec: The CODEC that the DAIs are registered for, NULL if the component is + * not a CODEC. * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, size_t count, - bool legacy_dai_naming) + struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, + size_t count, bool legacy_dai_naming) { struct device *dev = component->dev; - struct snd_soc_codec *codec; struct snd_soc_dai *dai; unsigned int i; int ret; @@ -3982,28 +3983,19 @@ static int snd_soc_register_dais(struct snd_soc_component *component, } dai->component = component; + dai->codec = codec; dai->dev = dev; dai->driver = &dai_drv[i]; dai->dapm.dev = dev; if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; - mutex_lock(&client_mutex); - - list_for_each_entry(codec, &codec_list, list) { - if (codec->dev == dev) { - dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", - dai->name, codec->name); - dai->codec = codec; - break; - } - } if (!dai->codec) dai->dapm.idle_bias_off = 1; + mutex_lock(&client_mutex); list_add(&dai->list, &dai_list); - mutex_unlock(&client_mutex); dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); @@ -4025,6 +4017,7 @@ static int __snd_soc_register_component(struct device *dev, struct snd_soc_component *cmpnt, const struct snd_soc_component_driver *cmpnt_drv, + struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, int num_dai, bool allow_single_dai) { @@ -4048,7 +4041,8 @@ __snd_soc_register_component(struct device *dev, cmpnt->dai_drv = dai_drv; cmpnt->num_dai = num_dai; - ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, allow_single_dai); + ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, + allow_single_dai); if (ret < 0) { dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto error_component_name; @@ -4083,7 +4077,7 @@ int snd_soc_register_component(struct device *dev, cmpnt->ignore_pmdown_time = true; - return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, + return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, dai_drv, num_dai, true); } EXPORT_SYMBOL_GPL(snd_soc_register_component); @@ -4304,7 +4298,7 @@ int snd_soc_register_codec(struct device *dev, /* register component */ ret = __snd_soc_register_component(dev, &codec->component, &codec_drv->component_driver, - dai_drv, num_dai, false); + codec, dai_drv, num_dai, false); if (ret < 0) { dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); goto fail_codec_name; -- cgit v0.10.2 From 1438c2f60ba955114cff3717f1a334878c7886a9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Mar 2014 17:41:47 +0100 Subject: ASoC: Add a per component dai list Now that every DAI has a component we can track the DAIs on a per component basis. This simplifies the DAI lookup when we are only interested in DAIs of a specific component and also makes it possible to have multiple components with the same parent device and also register DAIs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index b14acd8..37b470c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -671,6 +671,8 @@ struct snd_soc_component { int num_dai; const struct snd_soc_component_driver *driver; + + struct list_head dai_list; }; /* SoC Audio Codec device */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cc52241..f34f1a0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -56,7 +56,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); #endif static DEFINE_MUTEX(client_mutex); -static LIST_HEAD(dai_list); static LIST_HEAD(platform_list); static LIST_HEAD(codec_list); static LIST_HEAD(component_list); @@ -370,18 +369,22 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf, { char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); ssize_t len, ret = 0; + struct snd_soc_component *component; struct snd_soc_dai *dai; if (!buf) return -ENOMEM; - list_for_each_entry(dai, &dai_list, list) { - len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name); - if (len >= 0) - ret += len; - if (ret > PAGE_SIZE) { - ret = PAGE_SIZE; - break; + list_for_each_entry(component, &component_list, list) { + list_for_each_entry(dai, &component->dai_list, list) { + len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", + dai->name); + if (len >= 0) + ret += len; + if (ret > PAGE_SIZE) { + ret = PAGE_SIZE; + break; + } } } @@ -855,6 +858,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) { struct snd_soc_dai_link *dai_link = &card->dai_link[num]; struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_component *component; struct snd_soc_codec *codec; struct snd_soc_platform *platform; struct snd_soc_dai *codec_dai, *cpu_dai; @@ -863,18 +867,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); /* Find CPU DAI from registered DAIs*/ - list_for_each_entry(cpu_dai, &dai_list, list) { + list_for_each_entry(component, &component_list, list) { if (dai_link->cpu_of_node && - (cpu_dai->dev->of_node != dai_link->cpu_of_node)) + component->dev->of_node != dai_link->cpu_of_node) continue; if (dai_link->cpu_name && - strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) - continue; - if (dai_link->cpu_dai_name && - strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + strcmp(dev_name(component->dev), dai_link->cpu_name)) continue; + list_for_each_entry(cpu_dai, &component->dai_list, list) { + if (dai_link->cpu_dai_name && + strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + continue; - rtd->cpu_dai = cpu_dai; + rtd->cpu_dai = cpu_dai; + } } if (!rtd->cpu_dai) { @@ -899,12 +905,10 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) * CODEC found, so find CODEC DAI from registered DAIs from * this CODEC */ - list_for_each_entry(codec_dai, &dai_list, list) { - if (codec->dev == codec_dai->dev && - !strcmp(codec_dai->name, - dai_link->codec_dai_name)) { - + list_for_each_entry(codec_dai, &codec->component.dai_list, list) { + if (!strcmp(codec_dai->name, dai_link->codec_dai_name)) { rtd->codec_dai = codec_dai; + break; } } @@ -1128,12 +1132,8 @@ static int soc_probe_codec(struct snd_soc_card *card, driver->num_dapm_widgets); /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &dai_list, list) { - if (dai->dev != codec->dev) - continue; - + list_for_each_entry(dai, &codec->component.dai_list, list) snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); - } codec->dapm.idle_bias_off = driver->idle_bias_off; @@ -1180,6 +1180,7 @@ static int soc_probe_platform(struct snd_soc_card *card, { int ret = 0; const struct snd_soc_platform_driver *driver = platform->driver; + struct snd_soc_component *component; struct snd_soc_dai *dai; platform->card = card; @@ -1195,11 +1196,11 @@ static int soc_probe_platform(struct snd_soc_card *card, driver->dapm_widgets, driver->num_dapm_widgets); /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &dai_list, list) { - if (dai->dev != platform->dev) + list_for_each_entry(component, &component_list, list) { + if (component->dev != platform->dev) continue; - - snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); + list_for_each_entry(dai, &component->dai_list, list) + snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); } platform->dapm.idle_bias_off = 1; @@ -3912,21 +3913,14 @@ static inline char *fmt_multiple_name(struct device *dev, */ static void snd_soc_unregister_dais(struct snd_soc_component *component) { - struct snd_soc_dai *dai, *_dai; - - mutex_lock(&client_mutex); - list_for_each_entry_safe(dai, _dai, &dai_list, list) { - if (dai->dev != component->dev) - continue; - - list_del(&dai->list); + struct snd_soc_dai *dai; + list_for_each_entry(dai, &component->dai_list, list) { dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", dai->name); kfree(dai->name); kfree(dai); } - mutex_unlock(&client_mutex); } /** @@ -3990,13 +3984,10 @@ static int snd_soc_register_dais(struct snd_soc_component *component, if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; - if (!dai->codec) dai->dapm.idle_bias_off = 1; - mutex_lock(&client_mutex); - list_add(&dai->list, &dai_list); - mutex_unlock(&client_mutex); + list_add(&dai->list, &component->dai_list); dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); } @@ -4040,6 +4031,7 @@ __snd_soc_register_component(struct device *dev, cmpnt->driver = cmpnt_drv; cmpnt->dai_drv = dai_drv; cmpnt->num_dai = num_dai; + INIT_LIST_HEAD(&cmpnt->dai_list); ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, allow_single_dai); -- cgit v0.10.2 From 492c0a18b7b4f171b5af382541e72541de69f545 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Mar 2014 16:15:48 +0800 Subject: ASoC: dapm: Staticise dapm_mark_dirty() The function is not called outside soc-dapm.c so there is no need for it to be exported. Signed-off-by: Mark Brown diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 3b99176..05aaaf6 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -471,7 +471,6 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); /* Mostly internal - should not normally be used */ -void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason); void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); /* dapm path query */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 77743e5..5a4376b4 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -146,7 +146,7 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) return !list_empty(&w->dirty); } -void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) +static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) { if (!dapm_dirty_widget(w)) { dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", @@ -154,7 +154,6 @@ void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty); } } -EXPORT_SYMBOL_GPL(dapm_mark_dirty); void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) { -- cgit v0.10.2 From f9fa2b1855a9ece2ec2a4f54b7f9131cd89257d6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Mar 2014 16:49:11 +0800 Subject: ASoC: dapm: Sprinkle lockdep asserts through the code Try to spot locking issues by asserting that the DAPM mutex is held when it should be. There's a bit of fun due to us not requiring the lock to be held prior to the card being instantiated which mean we need to wrap the assert in some paths and this isn't methodical by any stretch of the imagination. Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5a4376b4..5c01ac1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -115,6 +115,12 @@ static int dapm_down_seq[] = { [snd_soc_dapm_post] = 14, }; +static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) +{ + if (dapm->card && dapm->card->instantiated) + lockdep_assert_held(&dapm->card->dapm_mutex); +} + static void pop_wait(u32 pop_time) { if (pop_time) @@ -148,6 +154,8 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) { + dapm_assert_locked(w->dapm); + if (!dapm_dirty_widget(w)) { dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", w->name, reason); @@ -360,6 +368,8 @@ static void dapm_reset(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; + lockdep_assert_held(&card->dapm_mutex); + memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); list_for_each_entry(w, &card->widgets, list) { @@ -1823,6 +1833,8 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) ASYNC_DOMAIN_EXCLUSIVE(async_domain); enum snd_soc_bias_level bias; + lockdep_assert_held(&card->dapm_mutex); + trace_snd_soc_dapm_start(card); list_for_each_entry(d, &card->dapm_list, list) { @@ -2118,6 +2130,8 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; + lockdep_assert_held(&card->dapm_mutex); + /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { if (!path->name || !e->texts[mux]) @@ -2168,6 +2182,8 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; + lockdep_assert_held(&card->dapm_mutex); + /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { found = 1; @@ -2333,6 +2349,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, { struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); + dapm_assert_locked(dapm); + if (!w) { dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin); return -EINVAL; -- cgit v0.10.2 From 23a735cc0200609edeff7c148c83d5046169dee9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Mar 2014 08:14:14 +0100 Subject: ASoC: migor: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index 5014a88..c58c252 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -136,19 +136,6 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Mic Bias", NULL, "External Microphone" }, }; -static int migor_dai_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, migor_dapm_widgets, - ARRAY_SIZE(migor_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - /* migor digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link migor_dai = { .name = "wm8978", @@ -158,7 +145,6 @@ static struct snd_soc_dai_link migor_dai = { .platform_name = "siu-pcm-audio", .codec_name = "wm8978.0-001a", .ops = &migor_dai_ops, - .init = migor_dai_init, }; /* migor audio machine driver */ @@ -167,6 +153,11 @@ static struct snd_soc_card snd_soc_migor = { .owner = THIS_MODULE, .dai_link = &migor_dai, .num_links = 1, + + .dapm_widgets = migor_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(migor_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *migor_snd_device; -- cgit v0.10.2 From bde24030b5a2825ef198b2f092b7271e22fae142 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Mar 2014 08:57:49 +0100 Subject: ASoC: spear: spdif_out: Fix mute control For controls registers with snd_soc_add_dai_controls snd_kcontrol_chip() returns a pointer to the DAI, not to the CODEC. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index fe99f46..19cca04 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c @@ -213,10 +213,7 @@ static int spdif_digital_mute(struct snd_soc_dai *dai, int mute) static int spdif_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_card *card = codec->card; - struct snd_soc_pcm_runtime *rtd = card->rtd; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); ucontrol->value.integer.value[0] = host->saved_params.mute; @@ -226,10 +223,7 @@ static int spdif_mute_get(struct snd_kcontrol *kcontrol, static int spdif_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_card *card = codec->card; - struct snd_soc_pcm_runtime *rtd = card->rtd; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); if (host->saved_params.mute == ucontrol->value.integer.value[0]) -- cgit v0.10.2 From 5c1d5f091dc39eecf9a34a8be01492d14c23ad91 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 08:34:39 +0100 Subject: ASoC: Fix use after free Freeing the current list element while iterating over the list will cause a use after free since the iterator function will still use the current element to look up the next. Use list_for_each_safe() and remove the element from the list before freeing it to avoid this. Fixes: 1438c2f60b ("ASoC: Add a per component dai list") Reported-by: Dan Carpenter Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f34f1a0..a78bba4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3913,11 +3913,12 @@ static inline char *fmt_multiple_name(struct device *dev, */ static void snd_soc_unregister_dais(struct snd_soc_component *component) { - struct snd_soc_dai *dai; + struct snd_soc_dai *dai, *_dai; - list_for_each_entry(dai, &component->dai_list, list) { + list_for_each_entry_safe(dai, _dai, &component->dai_list, list) { dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", dai->name); + list_del(&dai->list); kfree(dai->name); kfree(dai); } -- cgit v0.10.2 From 051389e250d018f7c38c8043c54aa8979d4b2cab Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Mar 2014 13:32:34 +0000 Subject: ASoC: tlv320aic23: Remove spurious bits per word setting regmap should handle any byte ordering issues required, it is looking for a byte stream from the bus, so don't set 16 bits per word. This is likely to have tested out OK due to use of an unmerged SPI controller driver. Signed-off-by: Mark Brown Tested-by: Max Filippov diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c index 585aea4..3b387e4 100644 --- a/sound/soc/codecs/tlv320aic23-spi.c +++ b/sound/soc/codecs/tlv320aic23-spi.c @@ -25,7 +25,6 @@ static int aic23_spi_probe(struct spi_device *spi) dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); - spi->bits_per_word = 16; spi->mode = SPI_MODE_0; ret = spi_setup(spi); if (ret < 0) -- cgit v0.10.2