From bba3d8c3b3c0f2123be5bc687d1cddc13437c923 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 23 Jul 2012 12:16:19 +0100 Subject: [PATCH 001/665] [PARISC] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts The following build error occured during a parisc build with swap-over-NFS patches applied. net/core/sock.c:274:36: error: initializer element is not constant net/core/sock.c:274:36: error: (near initialization for 'memalloc_socks') net/core/sock.c:274:36: error: initializer element is not constant Dave Anglin says: > Here is the line in sock.i: > > struct static_key memalloc_socks = ((struct static_key) { .enabled = > ((atomic_t) { (0) }) }); The above line contains two compound literals. It also uses a designated initializer to initialize the field enabled. A compound literal is not a constant expression. The location of the above statement isn't fully clear, but if a compound literal occurs outside the body of a function, the initializer list must consist of constant expressions. Reported-by: Fengguang Wu Signed-off-by: Mel Gorman Cc: Signed-off-by: James Bottomley --- arch/parisc/include/asm/atomic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 6c6defc24619..af9cf30ed474 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -141,7 +141,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0) -#define ATOMIC_INIT(i) ((atomic_t) { (i) }) +#define ATOMIC_INIT(i) { (i) } #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() @@ -150,7 +150,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #ifdef CONFIG_64BIT -#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) +#define ATOMIC64_INIT(i) { (i) } static __inline__ s64 __atomic64_add_return(s64 i, atomic64_t *v) From 5b24c421621792fcc588af6f644d6acf2dd798cc Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 2 Aug 2012 15:33:59 +0200 Subject: [PATCH 002/665] [PARISC] fix personality flag check in copy_thread() Directly comparing task_struct->personality against PER_* is not fully correct, as it doesn't take flags potentially stored in top three bytes into account. Analogically, directly forcefully setting personality to PER_LINUX32 or PER_LINUX discards any flags stored in the top three bytes. Signed-off-by: Jiri Kosina Signed-off-by: James Bottomley --- arch/parisc/kernel/process.c | 2 +- arch/parisc/kernel/sys_parisc.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index d4b94b395c16..2c05a9292a81 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -309,7 +309,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, cregs->ksp = (unsigned long)stack + (pregs->gr[21] & (THREAD_SIZE - 1)); cregs->gr[30] = usp; - if (p->personality == PER_HPUX) { + if (personality(p->personality) == PER_HPUX) { #ifdef CONFIG_HPUX cregs->kpc = (unsigned long) &hpux_child_return; #else diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index c9b932260f47..7426e40699bd 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -225,12 +225,12 @@ long parisc_personality(unsigned long personality) long err; if (personality(current->personality) == PER_LINUX32 - && personality == PER_LINUX) - personality = PER_LINUX32; + && personality(personality) == PER_LINUX) + personality = (personality & ~PER_MASK) | PER_LINUX32; err = sys_personality(personality); - if (err == PER_LINUX32) - err = PER_LINUX; + if (personality(err) == PER_LINUX32) + err = (err & ~PER_MASK) | PER_LINUX; return err; } From d77ae3329292baebfc6eced97d2e12b66349f83c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 23 Jul 2012 12:39:51 +0300 Subject: [PATCH 003/665] ASoC: omap-mcpdm: Convert to use devm_* Switch to use devm_* te make the probe/remove code more cleaner. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 52 ++++++++++--------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 2c66e2498a45..f7babb374a37 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -445,9 +445,8 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) { struct omap_mcpdm *mcpdm; struct resource *res; - int ret = 0; - mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); + mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL); if (!mcpdm) return -ENOMEM; @@ -456,55 +455,30 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) mutex_init(&mcpdm->mutex); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no resource\n"); - goto err_res; - } + if (res == NULL) + return -ENOMEM; - if (!request_mem_region(res->start, resource_size(res), "McPDM")) { - ret = -EBUSY; - goto err_res; - } + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), "McPDM")) + return -EBUSY; - mcpdm->io_base = ioremap(res->start, resource_size(res)); - if (!mcpdm->io_base) { - ret = -ENOMEM; - goto err_iomap; - } + mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!mcpdm->io_base) + return -ENOMEM; mcpdm->irq = platform_get_irq(pdev, 0); - if (mcpdm->irq < 0) { - ret = mcpdm->irq; - goto err_irq; - } + if (mcpdm->irq < 0) + return mcpdm->irq; mcpdm->dev = &pdev->dev; - ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); - if (!ret) - return 0; - -err_irq: - iounmap(mcpdm->io_base); -err_iomap: - release_mem_region(res->start, resource_size(res)); -err_res: - kfree(mcpdm); - return ret; + return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); } static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) { - struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev); - struct resource *res; - snd_soc_unregister_dai(&pdev->dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(mcpdm->io_base); - release_mem_region(res->start, resource_size(res)); - - kfree(mcpdm); return 0; } From 0651322bfcf3ca51802c6d8d161d6d1c9f3013eb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 23 Jul 2012 17:25:15 +0530 Subject: [PATCH 004/665] ASoC: isabelle: Remove version.h header file inclusion version.h header file inclusion is no longer needed for this file. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/isabelle.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5d8f39e32978..1bf55602c9eb 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -13,7 +13,6 @@ */ #include #include -#include #include #include #include From fbfe69836c088bcc0c5a0f32e788d3aef5f66aca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Jul 2012 20:14:43 +0100 Subject: [PATCH 005/665] ASoC: wm8994: Implement support for self-oscillation mode in the FLL The FLLs in the WM8994 series devices can be started without any reference being supplied, mainly for use in analogue bypass cases. Implement support for this mode. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 21 +++++++++++++++------ sound/soc/codecs/wm8994.h | 9 +++++---- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 04ef03175c51..2c9b8b7fdf3d 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2102,6 +2102,10 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, case WM8994_FLL_SRC_LRCLK: case WM8994_FLL_SRC_BCLK: break; + case WM8994_FLL_SRC_INTERNAL: + freq_in = 12000000; + freq_out = 12000000; + break; default: return -EINVAL; } @@ -2164,9 +2168,11 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, fll.n << WM8994_FLL1_N_SHIFT); snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, - WM8958_FLL1_BYP | + WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | WM8994_FLL1_REFCLK_DIV_MASK | WM8994_FLL1_REFCLK_SRC_MASK, + ((src == WM8994_FLL_SRC_INTERNAL) + << WM8994_FLL1_FRC_NCO_SHIFT) | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | (src - 1)); @@ -2192,13 +2198,16 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, } } + reg = WM8994_FLL1_ENA; + if (fll.k) - reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; - else - reg = WM8994_FLL1_ENA; + reg |= WM8994_FLL1_FRAC; + if (src == WM8994_FLL_SRC_INTERNAL) + reg |= WM8994_FLL1_OSC_ENA; + snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, - WM8994_FLL1_ENA | WM8994_FLL1_FRAC, - reg); + WM8994_FLL1_ENA | WM8994_FLL1_OSC_ENA | + WM8994_FLL1_FRAC, reg); if (wm8994->fll_locked_irq) { timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index d77e06f0a675..19068d8fa301 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -28,10 +28,11 @@ #define WM8994_FLL1 1 #define WM8994_FLL2 2 -#define WM8994_FLL_SRC_MCLK1 1 -#define WM8994_FLL_SRC_MCLK2 2 -#define WM8994_FLL_SRC_LRCLK 3 -#define WM8994_FLL_SRC_BCLK 4 +#define WM8994_FLL_SRC_MCLK1 1 +#define WM8994_FLL_SRC_MCLK2 2 +#define WM8994_FLL_SRC_LRCLK 3 +#define WM8994_FLL_SRC_BCLK 4 +#define WM8994_FLL_SRC_INTERNAL 5 enum wm8994_vmid_mode { WM8994_VMID_NORMAL, From 0dcd47426abde223b2386165470ec45d9777478e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 26 Jul 2012 11:28:37 +0100 Subject: [PATCH 006/665] ASoC: ux500: Strengthen error checking after memory allocation Currently there is no out-of-memory error checking after attempting to allocate memory for the ux500_msp or ux500_msp_i2s_drvdata data structures. Instead we go about populating them regardless. This patch applies the necessary error checking to prevent a panic. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 3 +++ sound/soc/ux500/ux500_msp_i2s.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 057e28ef770e..772cb19d2fb3 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -760,6 +760,9 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp_i2s_drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + drvdata->fmt = 0; drvdata->slots = 1; drvdata->tx_mask = 0x01; diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 5c472f335a64..36be11e47ad6 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -673,6 +673,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); msp = *msp_p; + if (!msp) + return -ENOMEM; msp->id = platform_data->id; msp->dev = &pdev->dev; From 5ef75e710b4950439f953c4897e4a871c2f9dc8f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 25 Jul 2012 16:09:11 +0300 Subject: [PATCH 007/665] ASoC: omap-abe-twl6040: Add device tree support When the board boots with device tree the driver will receive the name of the card, DAPM routing map, phandle for the audio components described in the dts file, mclk speed, and the possibility of detecting the jack detection. The card will be set up based on this information. Since the routing is provided via DT we can mark the card fully routed so core can take care of disconnecting the unused pins. Signed-off-by: Peter Ujfalusi Reviwed-by: Mark Brown Signed-off-by: Mark Brown --- .../bindings/sound/omap-abe-twl6040.txt | 91 +++++++++++ sound/soc/omap/omap-abe-twl6040.c | 145 ++++++++++++++---- 2 files changed, 206 insertions(+), 30 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt diff --git a/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt new file mode 100644 index 000000000000..65dec876cb2d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt @@ -0,0 +1,91 @@ +* Texas Instruments OMAP4+ and twl6040 based audio setups + +Required properties: +- compatible: "ti,abe-twl6040" +- ti,model: Name of the sound card ( for example "SDP4430") +- ti,mclk-freq: MCLK frequency for HPPLL operation +- ti,mcpdm: phandle for the McPDM node +- ti,twl6040: phandle for the twl6040 core node +- ti,audio-routing: List of 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. + +Optional properties: +- ti,dmic: phandle for the OMAP dmic node if the machine have it connected +- ti,jack_detection: Need to be set to <1> if the board capable to detect jack + insertion, removal. + +Available audio endpoints for the audio-routing table: + +Board connectors: + * Headset Stereophone + * Earphone Spk + * Ext Spk + * Line Out + * Vibrator + * Headset Mic + * Main Handset Mic + * Sub Handset Mic + * Line In + * Digital Mic + +twl6040 pins: + * HSOL + * HSOR + * EP + * HFL + * HFR + * AUXL + * AUXR + * VIBRAL + * VIBRAR + * HSMIC + * MAINMIC + * SUBMIC + * AFML + * AFMR + + * Headset Mic Bias + * Main Mic Bias + * Digital Mic1 Bias + * Digital Mic2 Bias + +Digital mic pins: + * DMic + +Example: + +sound { + compatible = "ti,abe-twl6040"; + ti,model = "SDP4430"; + + ti,jack-detection = <1>; + ti,mclk-freq = <38400000>; + + ti,mcpdm = <&mcpdm>; + ti,dmic = <&dmic>; + + ti,twl6040 = <&twl6040>; + + /* Audio routing */ + ti,audio-routing = + "Headset Stereophone", "HSOL", + "Headset Stereophone", "HSOR", + "Earphone Spk", "EP", + "Ext Spk", "HFL", + "Ext Spk", "HFR", + "Line Out", "AUXL", + "Line Out", "AUXR", + "Vibrator", "VIBRAL", + "Vibrator", "VIBRAR", + "HSMIC", "Headset Mic", + "Headset Mic", "Headset Mic Bias", + "MAINMIC", "Main Handset Mic", + "Main Handset Mic", "Main Mic Bias", + "SUBMIC", "Sub Handset Mic", + "Sub Handset Mic", "Main Mic Bias", + "AFML", "Line In", + "AFMR", "Line In", + "DMic", "Digital Mic", + "Digital Mic", "Digital Mic1 Bias"; +}; diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 9d93793d3077..be525dfe9faa 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,8 @@ struct abe_twl6040 { int jack_detection; /* board can detect jack events */ int mclk_freq; /* MCLK frequency speed for twl6040 */ + + struct platform_device *dmic_codec_dev; }; static int omap_abe_hw_params(struct snd_pcm_substream *substream, @@ -185,17 +188,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) int hs_trim; int ret = 0; - /* Disable not connected paths if not used */ - twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); - twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); - twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); - twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); - twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); - /* * Configure McPDM offset cancellation based on the HSOTRIM value from * twl6040. @@ -216,6 +208,24 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); } + /* + * NULL pdata means we booted with DT. In this case the routing is + * provided and the card is fully routed, no need to mark pins. + */ + if (!pdata) + return ret; + + /* Disable not connected paths if not used */ + twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); + twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); + twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); + twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); + twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); + twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); + twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); + twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); + twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); + return ret; } @@ -270,52 +280,116 @@ static struct snd_soc_card omap_abe_card = { static __devinit int omap_abe_probe(struct platform_device *pdev) { struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); + struct device_node *node = pdev->dev.of_node; struct snd_soc_card *card = &omap_abe_card; struct abe_twl6040 *priv; int num_links = 0; - int ret; + int ret = 0; card->dev = &pdev->dev; - if (!pdata) { - dev_err(&pdev->dev, "Missing pdata\n"); - return -ENODEV; - } - priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - if (pdata->card_name) { - card->name = pdata->card_name; + priv->dmic_codec_dev = ERR_PTR(-EINVAL); + + if (node) { + struct device_node *dai_node; + + if (snd_soc_of_parse_card_name(card, "ti,model")) { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + ret = snd_soc_of_parse_audio_routing(card, + "ti,audio-routing"); + if (ret) { + dev_err(&pdev->dev, + "Error while parsing DAPM routing\n"); + return ret; + } + + dai_node = of_parse_phandle(node, "ti,mcpdm", 0); + if (!dai_node) { + dev_err(&pdev->dev, "McPDM node is not provided\n"); + return -EINVAL; + } + abe_twl6040_dai_links[0].cpu_dai_name = NULL; + abe_twl6040_dai_links[0].cpu_of_node = dai_node; + + dai_node = of_parse_phandle(node, "ti,dmic", 0); + if (dai_node) { + num_links = 2; + abe_twl6040_dai_links[1].cpu_dai_name = NULL; + abe_twl6040_dai_links[1].cpu_of_node = dai_node; + + priv->dmic_codec_dev = platform_device_register_simple( + "dmic-codec", -1, NULL, 0); + if (IS_ERR(priv->dmic_codec_dev)) { + dev_err(&pdev->dev, + "Can't instantiate dmic-codec\n"); + return PTR_ERR(priv->dmic_codec_dev); + } + } else { + num_links = 1; + } + + of_property_read_u32(node, "ti,jack-detection", + &priv->jack_detection); + of_property_read_u32(node, "ti,mclk-freq", + &priv->mclk_freq); + if (!priv->mclk_freq) { + dev_err(&pdev->dev, "MCLK frequency not provided\n"); + ret = -EINVAL; + goto err_unregister; + } + + omap_abe_card.fully_routed = 1; + } else if (pdata) { + if (pdata->card_name) { + card->name = pdata->card_name; + } else { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + if (pdata->has_dmic) + num_links = 2; + else + num_links = 1; + + priv->jack_detection = pdata->jack_detection; + priv->mclk_freq = pdata->mclk_freq; } else { - dev_err(&pdev->dev, "Card name is not provided\n"); + dev_err(&pdev->dev, "Missing pdata\n"); return -ENODEV; } - priv->jack_detection = pdata->jack_detection; - priv->mclk_freq = pdata->mclk_freq; - if (!priv->mclk_freq) { dev_err(&pdev->dev, "MCLK frequency missing\n"); - return -ENODEV; + ret = -ENODEV; + goto err_unregister; } - if (pdata->has_dmic) - num_links = 2; - else - num_links = 1; - card->dai_link = abe_twl6040_dai_links; card->num_links = num_links; snd_soc_card_set_drvdata(card, priv); ret = snd_soc_register_card(card); - if (ret) + if (ret) { dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + goto err_unregister; + } + + return 0; + +err_unregister: + if (!IS_ERR(priv->dmic_codec_dev)) + platform_device_unregister(priv->dmic_codec_dev); return ret; } @@ -323,17 +397,28 @@ static __devinit int omap_abe_probe(struct platform_device *pdev) static int __devexit omap_abe_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); + struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); + if (!IS_ERR(priv->dmic_codec_dev)) + platform_device_unregister(priv->dmic_codec_dev); + return 0; } +static const struct of_device_id omap_abe_of_match[] = { + {.compatible = "ti,abe-twl6040", }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_abe_of_match); + static struct platform_driver omap_abe_driver = { .driver = { .name = "omap-abe-twl6040", .owner = THIS_MODULE, .pm = &snd_soc_pm_ops, + .of_match_table = omap_abe_of_match, }, .probe = omap_abe_probe, .remove = __devexit_p(omap_abe_remove), From acaf24f015b2bdd34032188d26c3092d6ca749b3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jul 2012 22:57:35 +0100 Subject: [PATCH 008/665] ASoC: jack: Always update jack state even for noop changes Now that DAPM is very cheap for most updates we've no need to avoid trying to run it so always notify even if we don't think there are any changes. This avoids potential issues with bootstrapping state like the pin state or other notifiers when there's nothing in the jack. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-jack.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 7f8b3b7428bb..2ca3c734a288 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -83,11 +83,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) jack->status &= ~mask; jack->status |= status & mask; - /* The DAPM sync is expensive enough to be worth skipping. - * However, empty mask means pin synchronization is desired. */ - if (mask && (jack->status == oldstatus)) - goto out; - trace_snd_soc_jack_notify(jack, status); list_for_each_entry(pin, &jack->pins, list) { @@ -109,7 +104,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) snd_jack_report(jack->jack, jack->status); -out: mutex_unlock(&jack->mutex); } EXPORT_SYMBOL_GPL(snd_soc_jack_report); From 8cb8e83bfa7cb63ad4b3c3b79410766da397124b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jul 2012 18:10:03 +0100 Subject: [PATCH 009/665] ASoC: wm_hubs: Move CODEC stored in private data into wm_hubs Further wm_hubs code will use this. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8958-dsp2.c | 28 ++++++++++++++++------------ sound/soc/codecs/wm8994.c | 28 +++++++++++++--------------- sound/soc/codecs/wm8994.h | 1 - sound/soc/codecs/wm_hubs.c | 2 ++ sound/soc/codecs/wm_hubs.h | 2 ++ 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 1332692ef81b..00121ba36597 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -946,7 +946,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->mbc_texts = kmalloc(sizeof(char *) * pdata->num_mbc_cfgs, GFP_KERNEL); if (!wm8994->mbc_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d MBC config texts\n", pdata->num_mbc_cfgs); return; @@ -958,9 +958,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->mbc_enum.max = pdata->num_mbc_cfgs; wm8994->mbc_enum.texts = wm8994->mbc_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add MBC mode controls: %d\n", ret); } @@ -974,7 +975,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_texts = kmalloc(sizeof(char *) * pdata->num_vss_cfgs, GFP_KERNEL); if (!wm8994->vss_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d VSS config texts\n", pdata->num_vss_cfgs); return; @@ -986,9 +987,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_enum.max = pdata->num_vss_cfgs; wm8994->vss_enum.texts = wm8994->vss_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add VSS mode controls: %d\n", ret); } @@ -1003,7 +1005,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_hpf_texts = kmalloc(sizeof(char *) * pdata->num_vss_hpf_cfgs, GFP_KERNEL); if (!wm8994->vss_hpf_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d VSS HPF config texts\n", pdata->num_vss_hpf_cfgs); return; @@ -1015,9 +1017,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add VSS HPFmode controls: %d\n", ret); } @@ -1033,7 +1036,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->enh_eq_texts = kmalloc(sizeof(char *) * pdata->num_enh_eq_cfgs, GFP_KERNEL); if (!wm8994->enh_eq_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d enhanced EQ config texts\n", pdata->num_enh_eq_cfgs); return; @@ -1045,9 +1048,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add enhanced EQ controls: %d\n", ret); } diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 2c9b8b7fdf3d..1237c11c8c35 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3036,7 +3036,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) { - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; struct wm8994_pdata *pdata = wm8994->pdata; struct snd_kcontrol_new controls[] = { SOC_ENUM_EXT("AIF1.1 EQ Mode", @@ -3094,16 +3094,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, controls, + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, ARRAY_SIZE(controls)); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add ReTune Mobile controls: %d\n", ret); } static void wm8994_handle_pdata(struct wm8994_priv *wm8994) { - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; struct wm8994_pdata *pdata = wm8994->pdata; int ret, i; @@ -3132,10 +3132,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) }; /* We need an array of texts for the enum API */ - wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev, + wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); if (!wm8994->drc_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d DRC config texts\n", pdata->num_drc_cfgs); return; @@ -3147,10 +3147,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) wm8994->drc_enum.max = pdata->num_drc_cfgs; wm8994->drc_enum.texts = wm8994->drc_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, controls, + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, ARRAY_SIZE(controls)); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add DRC mode controls: %d\n", ret); for (i = 0; i < WM8994_NUM_DRC; i++) @@ -3163,7 +3163,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) if (pdata->num_retune_mobile_cfgs) wm8994_handle_retune_mobile_pdata(wm8994); else - snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls, + snd_soc_add_codec_controls(wm8994->hubs.codec, wm8994_eq_controls, ARRAY_SIZE(wm8994_eq_controls)); for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { @@ -3318,7 +3318,7 @@ static void wm8994_mic_work(struct work_struct *work) static irqreturn_t wm8994_mic_irq(int irq, void *data) { struct wm8994_priv *priv = data; - struct snd_soc_codec *codec = priv->codec; + struct snd_soc_codec *codec = priv->hubs.codec; #ifndef CONFIG_SND_SOC_WM8994_MODULE trace_snd_soc_jack_irq(dev_name(codec->dev)); @@ -3431,7 +3431,7 @@ static void wm8958_default_micdet(u16 status, void *data) static irqreturn_t wm1811_jackdet_irq(int irq, void *data) { struct wm8994_priv *wm8994 = data; - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; int reg; bool present; @@ -3609,7 +3609,7 @@ EXPORT_SYMBOL_GPL(wm8958_mic_detect); static irqreturn_t wm8958_mic_irq(int irq, void *data) { struct wm8994_priv *wm8994 = data; - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; int reg, count; /* @@ -3699,13 +3699,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) unsigned int reg; int ret, i; - wm8994->codec = codec; + wm8994->hubs.codec = codec; codec->control_data = control->regmap; snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - wm8994->codec = codec; - mutex_init(&wm8994->accdet_lock); INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 19068d8fa301..e6d8209b8f29 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -73,7 +73,6 @@ struct wm8994; struct wm8994_priv { struct wm_hubs_data hubs; struct wm8994 *wm8994; - struct snd_soc_codec *codec; int sysclk[2]; int sysclk_rate[2]; int mclk[2]; diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 61baa48823cb..728a18010a49 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -1112,6 +1112,8 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; + hubs->codec = codec; + INIT_LIST_HEAD(&hubs->dcs_cache); init_completion(&hubs->dcs_done); diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index da2dc899ce6d..a5a09e6f87d5 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h @@ -46,6 +46,8 @@ struct wm_hubs_data { bool dcs_done_irq; struct completion dcs_done; + + struct snd_soc_codec *codec; }; extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); From 99af79dff5a609fe886d271bbc91e1a95eca3066 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jul 2012 23:03:36 +0100 Subject: [PATCH 010/665] ASoC: wm8994: Ensure we get a notification on startup for jackdet Since jackdet only reports deltas it won't generate an interrupt on startup when a jack is not present. This doesn't make a difference to userspace but does mean we don't generate a notification via the internal notifier chains. Fix that by scheduling a work to poll the chip after the clock is enabled. Use an extremely large timeout since there's no urgency and we don't want to report a false negative. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 37 ++++++++++++++++++++++++++++++++++++- sound/soc/codecs/wm8994.h | 2 ++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1237c11c8c35..7bb0c2c824cc 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -789,11 +789,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: return configure_clock(codec); + case SND_SOC_DAPM_POST_PMU: + /* + * JACKDET won't run until we start the clock and it + * only reports deltas, make sure we notify the state + * up the stack on startup. Use a *very* generous + * timeout for paranoia, there's no urgency and we + * don't want false reports. + */ + if (wm8994->jackdet && !wm8994->clk_has_run) { + schedule_delayed_work(&wm8994->jackdet_bootstrap, + msecs_to_jiffies(1000)); + wm8994->clk_has_run = true; + } + break; + case SND_SOC_DAPM_POST_PMD: configure_clock(codec); break; @@ -1632,7 +1648,8 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), @@ -3508,10 +3525,22 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) SND_JACK_MECHANICAL | SND_JACK_HEADSET | wm8994->btn_mask); + /* Since we only report deltas force an update, ensures we + * avoid bootstrapping issues with the core. */ + snd_soc_jack_report(wm8994->micdet[0].jack, 0, 0); + pm_runtime_put(codec->dev); return IRQ_HANDLED; } +static void wm1811_jackdet_bootstrap(struct work_struct *work) +{ + struct wm8994_priv *wm8994 = container_of(work, + struct wm8994_priv, + jackdet_bootstrap.work); + wm1811_jackdet_irq(0, wm8994); +} + /** * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ * @@ -3582,6 +3611,10 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, * otherwise jump straight to microphone detection. */ if (wm8994->jackdet) { + /* Disable debounce for the initial detect */ + snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, + WM1811_JACKDET_DB, 0); + snd_soc_update_bits(codec, WM8958_MICBIAS2, WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); @@ -3706,6 +3739,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) mutex_init(&wm8994->accdet_lock); INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); + INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, + wm1811_jackdet_bootstrap); for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) init_completion(&wm8994->fll_locked[i]); diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index e6d8209b8f29..f142ec198db3 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -81,6 +81,7 @@ struct wm8994_priv { struct completion fll_locked[2]; bool fll_locked_irq; bool fll_byp; + bool clk_has_run; int vmid_refcount; int active_refcount; @@ -134,6 +135,7 @@ struct wm8994_priv { int btn_mask; bool jackdet; int jackdet_mode; + struct delayed_work jackdet_bootstrap; wm8958_micdet_cb jack_cb; void *jack_cb_data; From fae4efa23ac012a57d45682bc22d540271c54532 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Jul 2012 19:49:06 +0100 Subject: [PATCH 011/665] ASoC: wm_hubs: Factor out DC servo readback code It's currently only used in one place but another user will be added shortly and there's an argument it's clearer anyway. Also add support for readback in mode 1, though it's not currently used. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 65 +++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 728a18010a49..6ab69f32f249 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -199,6 +199,47 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) list_add_tail(&cache->list, &hubs->dcs_cache); } +static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, + u16 *reg_l, u16 *reg_r) +{ + struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); + u16 dcs_reg, reg; + + switch (hubs->dcs_readback_mode) { + case 2: + dcs_reg = WM8994_DC_SERVO_4E; + break; + case 1: + dcs_reg = WM8994_DC_SERVO_READBACK; + break; + default: + dcs_reg = WM8993_DC_SERVO_3; + break; + } + + /* Different chips in the family support different readback + * methods. + */ + switch (hubs->dcs_readback_mode) { + case 0: + *reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) + & WM8993_DCS_INTEG_CHAN_0_MASK; + *reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) + & WM8993_DCS_INTEG_CHAN_1_MASK; + break; + case 2: + case 1: + reg = snd_soc_read(codec, dcs_reg); + *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) + >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; + *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; + break; + default: + WARN(1, "Unknown DCS readback method\n"); + return; + } +} + /* * Startup calibration of the DC servo */ @@ -207,7 +248,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); struct wm_hubs_dcs_cache *cache; s8 offset; - u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; + u16 reg_l, reg_r, dcs_cfg, dcs_reg; switch (hubs->dcs_readback_mode) { case 2: @@ -245,27 +286,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) WM8993_DCS_TRIG_STARTUP_1); } - /* Different chips in the family support different readback - * methods. - */ - switch (hubs->dcs_readback_mode) { - case 0: - reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) - & WM8993_DCS_INTEG_CHAN_0_MASK; - reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) - & WM8993_DCS_INTEG_CHAN_1_MASK; - break; - case 2: - case 1: - reg = snd_soc_read(codec, dcs_reg); - reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) - >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; - reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; - break; - default: - WARN(1, "Unknown DCS readback method\n"); - return; - } + wm_hubs_read_dc_servo(codec, ®_l, ®_r); dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); From a7892c35cfad4d6c6ccf1242b55c1004b0d5d1d1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Jul 2012 19:50:45 +0100 Subject: [PATCH 012/665] ASoC: wm_hubs: Rename calibrate_dc_servo() Really we're enabling it here and the name will become very confusing shortly. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 6ab69f32f249..05a02e1b7e92 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -243,7 +243,7 @@ static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, /* * Startup calibration of the DC servo */ -static void calibrate_dc_servo(struct snd_soc_codec *codec) +static void enable_dc_servo(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); struct wm_hubs_dcs_cache *cache; @@ -556,7 +556,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WM8993_DC_SERVO_1, WM8993_DCS_TIMER_PERIOD_01_MASK, 0); - calibrate_dc_servo(codec); + enable_dc_servo(codec); reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; From 7435d4eec76ee9debffb070f3e0d67615a828673 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 26 Jul 2012 14:49:11 +0100 Subject: [PATCH 013/665] ASoC: wm8994: Fix some indentation issues Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 7bb0c2c824cc..5fc31797994a 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2182,7 +2182,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, WM8994_FLL1_N_MASK, - fll.n << WM8994_FLL1_N_SHIFT); + fll.n << WM8994_FLL1_N_SHIFT); snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | @@ -3371,7 +3371,7 @@ static void wm8958_default_micdet(u16 status, void *data) snd_soc_jack_report(wm8994->micdet[0].jack, 0, wm8994->btn_mask | - SND_JACK_HEADSET); + SND_JACK_HEADSET); } return; } From d95e933730b3eb7b06bd778dc1d8f0ab3702b607 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 26 Jul 2012 15:25:48 +0100 Subject: [PATCH 014/665] ASoC: ab8500: Remove pointless cast There's never any need to cast away from void. Signed-off-by: Mark Brown Acked-by: Lee Jones --- sound/soc/codecs/ab8500-codec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 23b40186f9b8..b7836503dc69 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2404,12 +2404,12 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) dev_dbg(dev, "%s: Enter.\n", __func__); - /* Setup AB8500 according to board-settings */ - pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); - /* Inform SoC Core that we have our own I/O arrangements. */ codec->control_data = (void *)true; + /* Setup AB8500 according to board-settings */ + pdata = dev_get_platdata(dev->parent); + status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); if (status < 0) { pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); From d9f34df782b2aa7d233cb08850c8b12fdb37d18a Mon Sep 17 00:00:00 2001 From: Chris Rattray Date: Tue, 31 Jul 2012 14:51:34 +0100 Subject: [PATCH 015/665] ASoC: wm8994: enable mic and short detect debounce. Signed-off-by: Chris Rattray Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 5fc31797994a..02080da8b451 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3262,6 +3262,12 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); + /* enable MICDET and MICSHRT deboune */ + snd_soc_update_bits(codec, WM8994_IRQ_DEBOUNCE, + WM8994_MIC1_DET_DB_MASK | WM8994_MIC1_SHRT_DB_MASK | + WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, + WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); + snd_soc_dapm_sync(&codec->dapm); return 0; From 85d07e4d625d6511934799f7df93e9111ac2c88b Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 25 Jul 2012 15:28:34 +0200 Subject: [PATCH 016/665] ASoC: add DT bindings for cs4270 Signed-off-by: Daniel Mack Acked-by: Timur Tabi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/cs4270.txt | 16 ++++++++++++++++ sound/soc/codecs/cs4270.c | 11 +++++++++++ 2 files changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cs4270.txt diff --git a/Documentation/devicetree/bindings/sound/cs4270.txt b/Documentation/devicetree/bindings/sound/cs4270.txt new file mode 100644 index 000000000000..7f0bfd84d3fc --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs4270.txt @@ -0,0 +1,16 @@ +CS4270 audio CODEC + +The driver for this device currently only supports I2C. + +Required properties: + + - compatible : "cirrus,cs4270" + + - reg : the I2C address of the device for I2C + +Example: + +codec: cs4270@48 { + compatible = "cirrus,cs4270"; + reg = <0x48>; +}; diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 047917f0b8ae..4b71b01ecbcd 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -29,6 +29,7 @@ #include #include #include +#include /* * The codec isn't really big-endian or little-endian, since the I2S @@ -639,6 +640,15 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .reg_cache_default = cs4270_default_reg_cache, }; +/* + * cs4270_of_match - the device tree bindings + */ +static const struct of_device_id cs4270_of_match[] = { + { .compatible = "cirrus,cs4270", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs4270_of_match); + /** * cs4270_i2c_probe - initialize the I2C interface of the CS4270 * @i2c_client: the I2C client object @@ -718,6 +728,7 @@ static struct i2c_driver cs4270_i2c_driver = { .driver = { .name = "cs4270", .owner = THIS_MODULE, + .of_match_table = cs4270_of_match, }, .id_table = cs4270_id, .probe = cs4270_i2c_probe, From 02286190f3ec86f03025a60c4d3f747ff1047248 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 25 Jul 2012 15:28:35 +0200 Subject: [PATCH 017/665] ASoC: Add reset-gpio DT property to cs4270 driver In the process of moving over from static board files to the device tree, reset pins of peripheral reset pins should be handled by their corresponding drivers. Add a reset-gpio DT property to the cs4270 driver, and de-assert it before probing the chip. The logic could be augmented some day to re-assert it when codec is put to suspend. Signed-off-by: Daniel Mack Acked-by: Timur Tabi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/cs4270.txt | 5 +++++ sound/soc/codecs/cs4270.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/cs4270.txt b/Documentation/devicetree/bindings/sound/cs4270.txt index 7f0bfd84d3fc..6b222f9b8ef5 100644 --- a/Documentation/devicetree/bindings/sound/cs4270.txt +++ b/Documentation/devicetree/bindings/sound/cs4270.txt @@ -8,6 +8,11 @@ Required properties: - reg : the I2C address of the device for I2C +Optional properties: + + - reset-gpio : a GPIO spec for the reset pin. If specified, it will be + deasserted before communication to the codec starts. + Example: codec: cs4270@48 { diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 4b71b01ecbcd..fd11bb646d40 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -30,6 +30,7 @@ #include #include #include +#include /* * The codec isn't really big-endian or little-endian, since the I2S @@ -660,9 +661,25 @@ MODULE_DEVICE_TABLE(of, cs4270_of_match); static int cs4270_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { + struct device_node *np = i2c_client->dev.of_node; struct cs4270_private *cs4270; int ret; + /* See if we have a way to bring the codec out of reset */ + if (np) { + enum of_gpio_flags flags; + int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags); + + if (gpio_is_valid(gpio)) { + ret = devm_gpio_request_one(&i2c_client->dev, gpio, + flags & OF_GPIO_ACTIVE_LOW ? + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, + "cs4270 reset"); + if (ret < 0) + return ret; + } + } + /* Verify that we have a CS4270 */ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); From ad3ab1bba9bf3fcd13a4e3f868a438013174dcc1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 27 Jul 2012 14:32:10 -0300 Subject: [PATCH 018/665] ASoC: imx-ssi: Use devm functions Using devm_ functions can make the code simpler and smaller. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/fsl/imx-ssi.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 28dd76c7cb1c..e174c1767c2d 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -523,7 +523,7 @@ static int imx_ssi_probe(struct platform_device *pdev) int ret = 0; struct snd_soc_dai_driver *dai; - ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); + ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); if (!ssi) return -ENOMEM; dev_set_drvdata(&pdev->dev, ssi); @@ -536,7 +536,7 @@ static int imx_ssi_probe(struct platform_device *pdev) ssi->irq = platform_get_irq(pdev, 0); - ssi->clk = clk_get(&pdev->dev, NULL); + ssi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ssi->clk)) { ret = PTR_ERR(ssi->clk); dev_err(&pdev->dev, "Cannot get the clock: %d\n", @@ -551,23 +551,17 @@ static int imx_ssi_probe(struct platform_device *pdev) goto failed_get_resource; } - if (!request_mem_region(res->start, resource_size(res), DRV_NAME)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - ret = -EBUSY; - goto failed_get_resource; - } - - ssi->base = ioremap(res->start, resource_size(res)); + ssi->base = devm_request_and_ioremap(&pdev->dev, res); if (!ssi->base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENODEV; - goto failed_ioremap; + goto failed_register; } if (ssi->flags & IMX_SSI_USE_AC97) { if (ac97_ssi) { ret = -EBUSY; - goto failed_ac97; + goto failed_register; } ac97_ssi = ssi; setup_channel_to_ac97(ssi); @@ -636,15 +630,10 @@ failed_pdev_fiq_add: failed_pdev_fiq_alloc: snd_soc_unregister_dai(&pdev->dev); failed_register: -failed_ac97: - iounmap(ssi->base); -failed_ioremap: release_mem_region(res->start, resource_size(res)); failed_get_resource: clk_disable_unprepare(ssi->clk); - clk_put(ssi->clk); failed_clk: - kfree(ssi); return ret; } @@ -662,11 +651,8 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) if (ssi->flags & IMX_SSI_USE_AC97) ac97_ssi = NULL; - iounmap(ssi->base); release_mem_region(res->start, resource_size(res)); clk_disable_unprepare(ssi->clk); - clk_put(ssi->clk); - kfree(ssi); return 0; } From 9a37eae230e7350ba803801404a022e098016e56 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:37:30 +0100 Subject: [PATCH 019/665] ASoC: wm9712: Fix funky indentation Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index f16fb361a4eb..3fefa6e8e451 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -684,8 +684,8 @@ static int __devexit wm9712_remove(struct platform_device *pdev) static struct platform_driver wm9712_codec_driver = { .driver = { - .name = "wm9712-codec", - .owner = THIS_MODULE, + .name = "wm9712-codec", + .owner = THIS_MODULE, }, .probe = wm9712_probe, From 689185b78ba6fbe0042f662a468b5565909dff7a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:37:29 +0100 Subject: [PATCH 020/665] ASoC: wm9712: Fix name of Capture Switch Help UIs associate it with the matching gain control. Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 3fefa6e8e451..c9c696ca76f7 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -146,7 +146,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), -SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), +SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), From 1427cc37b6c073e83309565bfebad25fb6cd9182 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Aug 2012 19:25:50 +0100 Subject: [PATCH 021/665] ASoC: sta529: Staticise non-exported codec driver struct Signed-off-by: Mark Brown --- sound/soc/codecs/sta529.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 0c225cd569d2..9e3144862386 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -358,7 +358,7 @@ static int sta529_resume(struct snd_soc_codec *codec) return 0; } -struct snd_soc_codec_driver sta529_codec_driver = { +static const struct snd_soc_codec_driver sta529_codec_driver = { .probe = sta529_probe, .remove = sta529_remove, .set_bias_level = sta529_set_bias_level, From a0f1e98b34f22bb4055aebfc528bc9080b259f8f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:34:07 +0100 Subject: [PATCH 022/665] ASoC: imx-ssi: Say if we fail to register a second AC'97 bus Saves anyone wondering what happened if they run into this error. Signed-off-by: Mark Brown --- sound/soc/fsl/imx-ssi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index e174c1767c2d..3c520c46fa4a 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -560,6 +560,7 @@ static int imx_ssi_probe(struct platform_device *pdev) if (ssi->flags & IMX_SSI_USE_AC97) { if (ac97_ssi) { + dev_err(&pdev->dev, "AC'97 SSI already registered\n"); ret = -EBUSY; goto failed_register; } From 3b09efd1decb2b36ba2c7eb88ae4893f0581e470 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:34 +0530 Subject: [PATCH 023/665] ASoC: tlv320aic32x4: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index b0a73d37ed52..f230292ba96b 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -746,24 +746,7 @@ static struct i2c_driver aic32x4_i2c_driver = { .id_table = aic32x4_i2c_id, }; -static int __init aic32x4_modinit(void) -{ - int ret = 0; - - ret = i2c_add_driver(&aic32x4_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(aic32x4_modinit); - -static void __exit aic32x4_exit(void) -{ - i2c_del_driver(&aic32x4_i2c_driver); -} -module_exit(aic32x4_exit); +module_i2c_driver(aic32x4_i2c_driver); MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); MODULE_AUTHOR("Javier Martin "); From a3627e9c0a22283cb1f73fa1170f70fe604315d9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:35 +0530 Subject: [PATCH 024/665] ASoC: max9877: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max9877.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 3a2ba3d8fd6d..d15e5943c85e 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c @@ -291,17 +291,7 @@ static struct i2c_driver max9877_i2c_driver = { .id_table = max9877_i2c_id, }; -static int __init max9877_init(void) -{ - return i2c_add_driver(&max9877_i2c_driver); -} -module_init(max9877_init); - -static void __exit max9877_exit(void) -{ - i2c_del_driver(&max9877_i2c_driver); -} -module_exit(max9877_exit); +module_i2c_driver(max9877_i2c_driver); MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); MODULE_AUTHOR("Joonyoung Shim "); From 96124c2910a5317b5ea9fbfd9e07b135fdc1dd28 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:39 +0530 Subject: [PATCH 025/665] ASoC: wm9090: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm9090.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 2c2346fdd637..c7ddc56175d1 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -695,17 +695,7 @@ static struct i2c_driver wm9090_i2c_driver = { .id_table = wm9090_id, }; -static int __init wm9090_init(void) -{ - return i2c_add_driver(&wm9090_i2c_driver); -} -module_init(wm9090_init); - -static void __exit wm9090_exit(void) -{ - i2c_del_driver(&wm9090_i2c_driver); -} -module_exit(wm9090_exit); +module_i2c_driver(wm9090_i2c_driver); MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("WM9090 ASoC driver"); From 38ece8db99e1c7954608a6452bbe8b331d269ad6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:40 +0530 Subject: [PATCH 026/665] ASoC: wm8991: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 9ac31ba9b82e..b9dbfebbda13 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1400,23 +1400,7 @@ static struct i2c_driver wm8991_i2c_driver = { .id_table = wm8991_i2c_id, }; -static int __init wm8991_modinit(void) -{ - int ret; - ret = i2c_add_driver(&wm8991_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n", - ret); - } - return 0; -} -module_init(wm8991_modinit); - -static void __exit wm8991_exit(void) -{ - i2c_del_driver(&wm8991_i2c_driver); -} -module_exit(wm8991_exit); +module_i2c_driver(wm8991_i2c_driver); MODULE_DESCRIPTION("ASoC WM8991 driver"); MODULE_AUTHOR("Graeme Gregory"); From 5e383f53e80f4c644bc49a17b5590b110bad5832 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:41 +0530 Subject: [PATCH 027/665] ASoC: cs4270: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index fd11bb646d40..44a176f74170 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -752,17 +752,7 @@ static struct i2c_driver cs4270_i2c_driver = { .remove = cs4270_i2c_remove, }; -static int __init cs4270_init(void) -{ - return i2c_add_driver(&cs4270_i2c_driver); -} -module_init(cs4270_init); - -static void __exit cs4270_exit(void) -{ - i2c_del_driver(&cs4270_i2c_driver); -} -module_exit(cs4270_exit); +module_i2c_driver(cs4270_i2c_driver); MODULE_AUTHOR("Timur Tabi "); MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); From fd39d14b9676cfd3dbd5b7bfdefe3ec6149b9e1a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:42 +0530 Subject: [PATCH 028/665] ASoC: tlv320aic3x: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index dc78f5a4bcbf..01485bd51404 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1499,23 +1499,7 @@ static struct i2c_driver aic3x_i2c_driver = { .id_table = aic3x_i2c_id, }; -static int __init aic3x_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&aic3x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", - ret); - } - return ret; -} -module_init(aic3x_modinit); - -static void __exit aic3x_exit(void) -{ - i2c_del_driver(&aic3x_i2c_driver); -} -module_exit(aic3x_exit); +module_i2c_driver(aic3x_i2c_driver); MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); MODULE_AUTHOR("Vladimir Barinov"); From 0ead1136bda75d04cc134960bd265eebe210f74b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:43 +0530 Subject: [PATCH 029/665] ASoC: sta32x: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/sta32x.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8d717f4b5a87..51b7313a4c14 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -1006,17 +1006,7 @@ static struct i2c_driver sta32x_i2c_driver = { .id_table = sta32x_i2c_id, }; -static int __init sta32x_init(void) -{ - return i2c_add_driver(&sta32x_i2c_driver); -} -module_init(sta32x_init); - -static void __exit sta32x_exit(void) -{ - i2c_del_driver(&sta32x_i2c_driver); -} -module_exit(sta32x_exit); +module_i2c_driver(sta32x_i2c_driver); MODULE_DESCRIPTION("ASoC STA32X driver"); MODULE_AUTHOR("Johannes Stezenbach "); From 63a47a7544c65f0d4ca28f3ffa54468bc5f6cc6c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:44 +0530 Subject: [PATCH 030/665] ASoC: tlv320dac33: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 0dd41077ab79..d2e16c5d7d1f 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1621,24 +1621,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = { .id_table = tlv320dac33_i2c_id, }; -static int __init dac33_module_init(void) -{ - int r; - r = i2c_add_driver(&tlv320dac33_i2c_driver); - if (r < 0) { - printk(KERN_ERR "DAC33: driver registration failed\n"); - return r; - } - return 0; -} -module_init(dac33_module_init); - -static void __exit dac33_module_exit(void) -{ - i2c_del_driver(&tlv320dac33_i2c_driver); -} -module_exit(dac33_module_exit); - +module_i2c_driver(tlv320dac33_i2c_driver); MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); MODULE_AUTHOR("Peter Ujfalusi "); From beb22de07e87a2f6802cc0e916b2f5c6aeb3f59f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:45 +0530 Subject: [PATCH 031/665] ASoC: adau1701: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/adau1701.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 3d50fc8646b6..51f2f3cd8136 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -527,17 +527,7 @@ static struct i2c_driver adau1701_i2c_driver = { .id_table = adau1701_i2c_id, }; -static int __init adau1701_init(void) -{ - return i2c_add_driver(&adau1701_i2c_driver); -} -module_init(adau1701_init); - -static void __exit adau1701_exit(void) -{ - i2c_del_driver(&adau1701_i2c_driver); -} -module_exit(adau1701_exit); +module_i2c_driver(adau1701_i2c_driver); MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); MODULE_AUTHOR("Cliff Cai "); From 4abdc8c8fd25fa2f85d86babcbdb4fbbf759c86a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:46 +0530 Subject: [PATCH 032/665] ASoC: max9850: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max9850.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index a1913091f56c..efe535c37b39 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -369,17 +369,7 @@ static struct i2c_driver max9850_i2c_driver = { .id_table = max9850_i2c_id, }; -static int __init max9850_init(void) -{ - return i2c_add_driver(&max9850_i2c_driver); -} -module_init(max9850_init); - -static void __exit max9850_exit(void) -{ - i2c_del_driver(&max9850_i2c_driver); -} -module_exit(max9850_exit); +module_i2c_driver(max9850_i2c_driver); MODULE_AUTHOR("Christian Glindkamp "); MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); From 28285b96c9e75a79b7698bc4286aa1cb94e5c9cb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:47 +0530 Subject: [PATCH 033/665] ASoC: wm8971: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8971.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index eef783f6b6d6..5ce647758443 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -721,23 +721,7 @@ static struct i2c_driver wm8971_i2c_driver = { .id_table = wm8971_i2c_id, }; -static int __init wm8971_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8971_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8971_modinit); - -static void __exit wm8971_exit(void) -{ - i2c_del_driver(&wm8971_i2c_driver); -} -module_exit(wm8971_exit); +module_i2c_driver(wm8971_i2c_driver); MODULE_DESCRIPTION("ASoC WM8971 driver"); MODULE_AUTHOR("Lab126"); From 0ecbbb4fe5f0aae4cd70ec02383fd6b96aedb052 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:48 +0530 Subject: [PATCH 034/665] ASoC: ak4671: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/ak4671.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 5fb7c2a80e6d..2b457976a7bf 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -696,17 +696,7 @@ static struct i2c_driver ak4671_i2c_driver = { .id_table = ak4671_i2c_id, }; -static int __init ak4671_modinit(void) -{ - return i2c_add_driver(&ak4671_i2c_driver); -} -module_init(ak4671_modinit); - -static void __exit ak4671_exit(void) -{ - i2c_del_driver(&ak4671_i2c_driver); -} -module_exit(ak4671_exit); +module_i2c_driver(ak4671_i2c_driver); MODULE_DESCRIPTION("ASoC AK4671 codec driver"); MODULE_AUTHOR("Joonyoung Shim "); From f6ec139f2dc5380c542fa3100dbe1c73324be432 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:49 +0530 Subject: [PATCH 035/665] ASoC: lm4857: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/lm4857.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index ba4fafb93e56..81a328c78838 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -250,17 +250,7 @@ static struct i2c_driver lm4857_i2c_driver = { .id_table = lm4857_i2c_id, }; -static int __init lm4857_init(void) -{ - return i2c_add_driver(&lm4857_i2c_driver); -} -module_init(lm4857_init); - -static void __exit lm4857_exit(void) -{ - i2c_del_driver(&lm4857_i2c_driver); -} -module_exit(lm4857_exit); +module_i2c_driver(lm4857_i2c_driver); MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_DESCRIPTION("LM4857 amplifier driver"); From 0b34ac810ac079735f9e7e2c58d467f849a67ede Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:50 +0530 Subject: [PATCH 036/665] ASoC: wm8978: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8978.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a5be3adecf75..5421fd9fbcb5 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -1105,23 +1105,7 @@ static struct i2c_driver wm8978_i2c_driver = { .id_table = wm8978_i2c_id, }; -static int __init wm8978_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8978_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8978_modinit); - -static void __exit wm8978_exit(void) -{ - i2c_del_driver(&wm8978_i2c_driver); -} -module_exit(wm8978_exit); +module_i2c_driver(wm8978_i2c_driver); MODULE_DESCRIPTION("ASoC WM8978 codec driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); From 2342a07f2ca81c8e076ed6d5c6d19ac36794c848 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:51 +0530 Subject: [PATCH 037/665] ASoC: max98088: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max98088.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index af7324b79dd0..3264a5169306 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -2107,23 +2107,7 @@ static struct i2c_driver max98088_i2c_driver = { .id_table = max98088_i2c_id, }; -static int __init max98088_init(void) -{ - int ret; - - ret = i2c_add_driver(&max98088_i2c_driver); - if (ret) - pr_err("Failed to register max98088 I2C driver: %d\n", ret); - - return ret; -} -module_init(max98088_init); - -static void __exit max98088_exit(void) -{ - i2c_del_driver(&max98088_i2c_driver); -} -module_exit(max98088_exit); +module_i2c_driver(max98088_i2c_driver); MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); From 07c9c32be01db1705db2655922ee66173594b230 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:52 +0530 Subject: [PATCH 038/665] ASoC: wm8955: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8955.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 61fe97433e73..2f1c075755b1 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -1071,23 +1071,7 @@ static struct i2c_driver wm8955_i2c_driver = { .id_table = wm8955_i2c_id, }; -static int __init wm8955_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8955_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8955_modinit); - -static void __exit wm8955_exit(void) -{ - i2c_del_driver(&wm8955_i2c_driver); -} -module_exit(wm8955_exit); +module_i2c_driver(wm8955_i2c_driver); MODULE_DESCRIPTION("ASoC WM8955 driver"); MODULE_AUTHOR("Mark Brown "); From a9418ddca69db1c4b5d2d7b5f091e50893387be3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:53 +0530 Subject: [PATCH 039/665] ASoC: wm2200: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm2200.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cde..71debd0a3822 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2270,17 +2270,7 @@ static struct i2c_driver wm2200_i2c_driver = { .id_table = wm2200_i2c_id, }; -static int __init wm2200_modinit(void) -{ - return i2c_add_driver(&wm2200_i2c_driver); -} -module_init(wm2200_modinit); - -static void __exit wm2200_exit(void) -{ - i2c_del_driver(&wm2200_i2c_driver); -} -module_exit(wm2200_exit); +module_i2c_driver(wm2200_i2c_driver); MODULE_DESCRIPTION("ASoC WM2200 driver"); MODULE_AUTHOR("Mark Brown "); From 3a4bfd88af87b065e8a650211a7730b3f1e58e3e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:54 +0530 Subject: [PATCH 040/665] ASoC: wm2000: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm2000.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 3fd5b29dc933..89cd6fcad015 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -858,17 +858,7 @@ static struct i2c_driver wm2000_i2c_driver = { .id_table = wm2000_i2c_id, }; -static int __init wm2000_init(void) -{ - return i2c_add_driver(&wm2000_i2c_driver); -} -module_init(wm2000_init); - -static void __exit wm2000_exit(void) -{ - i2c_del_driver(&wm2000_i2c_driver); -} -module_exit(wm2000_exit); +module_i2c_driver(wm2000_i2c_driver); MODULE_DESCRIPTION("ASoC WM2000 driver"); MODULE_AUTHOR("Mark Brown "); From 794836b959e95b4e4705e11e7bdf2a688c72e2f7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:55 +0530 Subject: [PATCH 041/665] ASoC: wm8940: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8940.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 481a3d9cfe48..b20aa4e7c3f9 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -785,23 +785,7 @@ static struct i2c_driver wm8940_i2c_driver = { .id_table = wm8940_i2c_id, }; -static int __init wm8940_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8940_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8940_modinit); - -static void __exit wm8940_exit(void) -{ - i2c_del_driver(&wm8940_i2c_driver); -} -module_exit(wm8940_exit); +module_i2c_driver(wm8940_i2c_driver); MODULE_DESCRIPTION("ASoC WM8940 driver"); MODULE_AUTHOR("Jonathan Cameron"); From 8b08eb28c761aea8434e0228a0f080e31e16d791 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:56 +0530 Subject: [PATCH 042/665] ASoC: wm8961: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 01edbcc754d2..719fb69a17c8 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -1114,23 +1114,7 @@ static struct i2c_driver wm8961_i2c_driver = { .id_table = wm8961_i2c_id, }; -static int __init wm8961_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8961_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8961_modinit); - -static void __exit wm8961_exit(void) -{ - i2c_del_driver(&wm8961_i2c_driver); -} -module_exit(wm8961_exit); +module_i2c_driver(wm8961_i2c_driver); MODULE_DESCRIPTION("ASoC WM8961 driver"); MODULE_AUTHOR("Mark Brown "); From 5c86ea44bba82641b6173419c88c0de7cf09b60a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:57 +0530 Subject: [PATCH 043/665] ASoC: wm8903: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 73f1c8d7bafb..839414f9e2ed 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2241,23 +2241,7 @@ static struct i2c_driver wm8903_i2c_driver = { .id_table = wm8903_i2c_id, }; -static int __init wm8903_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8903_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8903_modinit); - -static void __exit wm8903_exit(void) -{ - i2c_del_driver(&wm8903_i2c_driver); -} -module_exit(wm8903_exit); +module_i2c_driver(wm8903_i2c_driver); MODULE_DESCRIPTION("ASoC WM8903 driver"); MODULE_AUTHOR("Mark Brown "); From d0b2d4fabb262dd7200382ee834d4292f6d76b1e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:58 +0530 Subject: [PATCH 044/665] ASoC: adau1373: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/adau1373.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 44f59064d8de..704544bfc90d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1392,17 +1392,7 @@ static struct i2c_driver adau1373_i2c_driver = { .id_table = adau1373_i2c_id, }; -static int __init adau1373_init(void) -{ - return i2c_add_driver(&adau1373_i2c_driver); -} -module_init(adau1373_init); - -static void __exit adau1373_exit(void) -{ - i2c_del_driver(&adau1373_i2c_driver); -} -module_exit(adau1373_exit); +module_i2c_driver(adau1373_i2c_driver); MODULE_DESCRIPTION("ASoC ADAU1373 driver"); MODULE_AUTHOR("Lars-Peter Clausen "); From 3c010e60ee54ee19dc2f39b4efa43dea03d65aaa Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:36 +0530 Subject: [PATCH 045/665] ASoC: wm8960: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 96518ac8e24c..804f4116912f 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1010,23 +1010,7 @@ static struct i2c_driver wm8960_i2c_driver = { .id_table = wm8960_i2c_id, }; -static int __init wm8960_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8960_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8960_modinit); - -static void __exit wm8960_exit(void) -{ - i2c_del_driver(&wm8960_i2c_driver); -} -module_exit(wm8960_exit); +module_i2c_driver(wm8960_i2c_driver); MODULE_DESCRIPTION("ASoC WM8960 driver"); MODULE_AUTHOR("Liam Girdwood"); From 2be59418f76dac590b98027586ac1714be17fcae Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:59 +0530 Subject: [PATCH 046/665] ASoC: wm8974: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8974.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index d93c03f820c9..9a39511af52a 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -659,23 +659,7 @@ static struct i2c_driver wm8974_i2c_driver = { .id_table = wm8974_i2c_id, }; -static int __init wm8974_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8974_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8974_modinit); - -static void __exit wm8974_exit(void) -{ - i2c_del_driver(&wm8974_i2c_driver); -} -module_exit(wm8974_exit); +module_i2c_driver(wm8974_i2c_driver); MODULE_DESCRIPTION("ASoC WM8974 driver"); MODULE_AUTHOR("Liam Girdwood"); From a8af02cf62e32644c02566adc462bba9ae148154 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:26:00 +0530 Subject: [PATCH 047/665] ASoC: max98095: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max98095.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 7cd508e16a5c..38d43c59d3f4 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2533,23 +2533,7 @@ static struct i2c_driver max98095_i2c_driver = { .id_table = max98095_i2c_id, }; -static int __init max98095_init(void) -{ - int ret; - - ret = i2c_add_driver(&max98095_i2c_driver); - if (ret) - pr_err("Failed to register max98095 I2C driver: %d\n", ret); - - return ret; -} -module_init(max98095_init); - -static void __exit max98095_exit(void) -{ - i2c_del_driver(&max98095_i2c_driver); -} -module_exit(max98095_exit); +module_i2c_driver(max98095_i2c_driver); MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); MODULE_AUTHOR("Peter Hsiang"); From cee4fcfa9dba7f13b0b45810832208df48ff4ca4 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:37 +0530 Subject: [PATCH 048/665] ASoC: cs42l51: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 091d0193f507..1e0fa3b5f79a 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -614,24 +614,7 @@ static struct i2c_driver cs42l51_i2c_driver = { .remove = cs42l51_i2c_remove, }; -static int __init cs42l51_init(void) -{ - int ret; - - ret = i2c_add_driver(&cs42l51_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "%s: can't add i2c driver\n", __func__); - return ret; - } - return 0; -} -module_init(cs42l51_init); - -static void __exit cs42l51_exit(void) -{ - i2c_del_driver(&cs42l51_i2c_driver); -} -module_exit(cs42l51_exit); +module_i2c_driver(cs42l51_i2c_driver); MODULE_AUTHOR("Arnaud Patard "); MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); From f062e2b64153e9769adf5370103f787971c9cd95 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:38 +0530 Subject: [PATCH 049/665] ASoC: tpa6130a2: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tpa6130a2.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 6fe4aa3ac544..565ff39ad3a3 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -487,19 +487,8 @@ static struct i2c_driver tpa6130a2_i2c_driver = { .id_table = tpa6130a2_id, }; -static int __init tpa6130a2_init(void) -{ - return i2c_add_driver(&tpa6130a2_i2c_driver); -} - -static void __exit tpa6130a2_exit(void) -{ - i2c_del_driver(&tpa6130a2_i2c_driver); -} +module_i2c_driver(tpa6130a2_i2c_driver); MODULE_AUTHOR("Peter Ujfalusi "); MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); MODULE_LICENSE("GPL"); - -module_init(tpa6130a2_init); -module_exit(tpa6130a2_exit); From 4185392da4b4b494e51934c51b999b4df424afba Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Mon, 6 Aug 2012 15:49:47 -0700 Subject: [PATCH 050/665] openvswitch: Relax set header validation. When installing a flow with an action to set a particular field we need to validate that the packets that are part of the flow actually contain that header. With IP we use zeroed addresses and with TCP/UDP the check is for zeroed ports. This check is overly broad and can catch packets like DHCP requests that have a zero source address in a legitimate header. This changes the check to look for a zeroed protocol number for IP or for both ports be zero for TCP/UDP before considering the header to not exist. Reported-by: Ethan Jackson Signed-off-by: Jesse Gross --- net/openvswitch/datapath.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index d8277d29e710..cf58cedad083 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -425,10 +425,10 @@ static int validate_sample(const struct nlattr *attr, static int validate_tp_port(const struct sw_flow_key *flow_key) { if (flow_key->eth.type == htons(ETH_P_IP)) { - if (flow_key->ipv4.tp.src && flow_key->ipv4.tp.dst) + if (flow_key->ipv4.tp.src || flow_key->ipv4.tp.dst) return 0; } else if (flow_key->eth.type == htons(ETH_P_IPV6)) { - if (flow_key->ipv6.tp.src && flow_key->ipv6.tp.dst) + if (flow_key->ipv6.tp.src || flow_key->ipv6.tp.dst) return 0; } @@ -460,7 +460,7 @@ static int validate_set(const struct nlattr *a, if (flow_key->eth.type != htons(ETH_P_IP)) return -EINVAL; - if (!flow_key->ipv4.addr.src || !flow_key->ipv4.addr.dst) + if (!flow_key->ip.proto) return -EINVAL; ipv4_key = nla_data(ovs_key); From 209ffe19ff98f5c0133bd98a689fc4fb42202de3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 7 Aug 2012 12:07:27 +0530 Subject: [PATCH 051/665] ASoC: cs42l52: Remove duplicate inclusion of slab.h header file slab.h header file was included twice. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 628daf6a1d97..61599298fb26 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include From 5f800080ca6840326b3048202fb63fc4a71a4c49 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Aug 2012 10:24:13 +0300 Subject: [PATCH 052/665] ASoC: core: Set dapm->idle_bias_off for DAIs not mapped with a codec The idle_bias_off flag is not configured for DAIs not mapped with a codec. This causes the pm counter to be increased at probe time for the CPU dai which unbalances the pm counter handling. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f81c5976b961..f10f00b5d29f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3715,6 +3715,9 @@ int snd_soc_register_dai(struct device *dev, } } + if (!dai->codec) + dai->dapm.idle_bias_off = 1; + list_add(&dai->list, &dai_list); mutex_unlock(&client_mutex); @@ -3803,6 +3806,9 @@ int snd_soc_register_dais(struct device *dev, } } + if (!dai->codec) + dai->dapm.idle_bias_off = 1; + list_add(&dai->list, &dai_list); mutex_unlock(&client_mutex); From 730963f8190b7650b0445a76e701fdef20c31cfb Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 7 Aug 2012 01:29:43 -0300 Subject: [PATCH 053/665] ASoC: mxs-saif: Use devm_clk_get() Using devm_clk_get can make the code simpler and smaller. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index b3030718c228..aa037b292f3d 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -704,7 +704,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) return ret; } - saif->clk = clk_get(&pdev->dev, NULL); + saif->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(saif->clk)) { ret = PTR_ERR(saif->clk); dev_err(&pdev->dev, "Cannot get the clock: %d\n", @@ -717,8 +717,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) saif->base = devm_request_and_ioremap(&pdev->dev, iores); if (!saif->base) { dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENODEV; - goto failed_get_resource; + return -ENODEV; } dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -731,7 +730,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) &saif->dma_param.chan_num); if (ret) { dev_err(&pdev->dev, "failed to get dma channel\n"); - goto failed_get_resource; + return ret; } } else { saif->dma_param.chan_num = dmares->start; @@ -742,7 +741,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) ret = saif->irq; dev_err(&pdev->dev, "failed to get irq resource: %d\n", ret); - goto failed_get_resource; + return ret; } saif->dev = &pdev->dev; @@ -750,7 +749,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) "mxs-saif", saif); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); - goto failed_get_resource; + return ret; } saif->dma_param.chan_irq = platform_get_irq(pdev, 1); @@ -758,7 +757,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) ret = saif->dma_param.chan_irq; dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", ret); - goto failed_get_resource; + return ret; } platform_set_drvdata(pdev, saif); @@ -766,7 +765,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); if (ret) { dev_err(&pdev->dev, "register DAI failed\n"); - goto failed_get_resource; + return ret; } ret = mxs_pcm_platform_register(&pdev->dev); @@ -779,19 +778,14 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) failed_pdev_alloc: snd_soc_unregister_dai(&pdev->dev); -failed_get_resource: - clk_put(saif->clk); return ret; } static int __devexit mxs_saif_remove(struct platform_device *pdev) { - struct mxs_saif *saif = platform_get_drvdata(pdev); - mxs_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); - clk_put(saif->clk); return 0; } From 8f245499791a4701bfe1ce9b0df90cea9d2f13e5 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Wed, 8 Aug 2012 20:40:30 +0530 Subject: [PATCH 054/665] ASoC: Davinci: McASP: remove unused header include Defines or parameters from isn't used anywhere. Hence remove the header include. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 10a2d8c788b7..c80c20a89b11 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -24,7 +24,6 @@ #include #include -#include #include "davinci-pcm.h" #include "davinci-i2s.h" From 10884347f18842aa9b8ae18ebb16272d9b7fafa2 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Wed, 8 Aug 2012 20:40:32 +0530 Subject: [PATCH 055/665] ASoC: McASP: Convert driver to use Runtime PM API * Add Runtime PM support to McASP host controller. * Use Runtime PM API to enable/disable McASP clock. This was tested on AM18x Board using suspend/resume Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 40 +++++++++++++++---------------- sound/soc/davinci/davinci-mcasp.h | 3 +-- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 95441bfc8190..d919fb8de7a3 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include @@ -776,20 +776,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!dev->clk_active) { - clk_enable(dev->clk); - dev->clk_active = 1; - } + ret = pm_runtime_get_sync(dev->dev); + if (IS_ERR_VALUE(ret)) + dev_err(dev->dev, "pm_runtime_get_sync() failed\n"); davinci_mcasp_start(dev, substream->stream); break; case SNDRV_PCM_TRIGGER_SUSPEND: davinci_mcasp_stop(dev, substream->stream); - if (dev->clk_active) { - clk_disable(dev->clk); - dev->clk_active = 0; - } - + ret = pm_runtime_put_sync(dev->dev); + if (IS_ERR_VALUE(ret)) + dev_err(dev->dev, "pm_runtime_put_sync() failed\n"); break; case SNDRV_PCM_TRIGGER_STOP: @@ -886,12 +883,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev) } pdata = pdev->dev.platform_data; - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) - return -ENODEV; + pm_runtime_enable(&pdev->dev); - clk_enable(dev->clk); - dev->clk_active = 1; + ret = pm_runtime_get_sync(&pdev->dev); + if (IS_ERR_VALUE(ret)) { + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); + return ret; + } dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); if (!dev->base) { @@ -908,6 +906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dev->version = pdata->version; dev->txnumevt = pdata->txnumevt; dev->rxnumevt = pdata->rxnumevt; + dev->dev = &pdev->dev; dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; dma_data->asp_chan_q = pdata->asp_chan_q; @@ -949,19 +948,18 @@ static int davinci_mcasp_probe(struct platform_device *pdev) return 0; err_release_clk: - clk_disable(dev->clk); - clk_put(dev->clk); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); return ret; } static int davinci_mcasp_remove(struct platform_device *pdev) { - struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); return 0; } diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 4681acc63606..51479f9ee909 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -40,9 +40,8 @@ struct davinci_audio_dev { struct davinci_pcm_dma_params dma_params[2]; void __iomem *base; int sample_rate; - struct clk *clk; + struct device *dev; unsigned int codec_fmt; - u8 clk_active; /* McASP specific data */ int tdm_slots; From 28d528c8dbab5c6b3cf2fc4f0e91470a9a63dbc0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 9 Aug 2012 18:45:23 +0100 Subject: [PATCH 056/665] ASoC: core: Remove pointless error on card registration failure If we fail to register the card we should say why somewhere else so there's no point in repeating the same thing with less information. Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f10f00b5d29f..3a43fa6ba2ee 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1830,13 +1830,7 @@ static int soc_probe(struct platform_device *pdev) /* Bodge while we unpick instantiation */ card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to register card\n"); - return ret; - } - - return 0; + return snd_soc_register_card(card); } static int soc_cleanup_card_resources(struct snd_soc_card *card) From cbd840dadeb03826b6cc074e38f380bbd4faaea5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Aug 2012 17:52:44 +0100 Subject: [PATCH 057/665] ASoC: arizona: Implement OPCLK support Arizona devices support two output system clocks. Provide support for configuring these via set_sysclk(). Once the clock API is more useful we should migrate over to that. Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 66 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/arizona.h | 6 ++-- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5c9cacaf2d52..5e96a0a1669c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -229,6 +229,69 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, } EXPORT_SYMBOL_GPL(arizona_out_ev); +static unsigned int arizona_sysclk_48k_rates[] = { + 6144000, + 12288000, + 22579200, + 49152000, +}; + +static unsigned int arizona_sysclk_44k1_rates[] = { + 5644800, + 11289600, + 24576000, + 45158400, +}; + +static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, + unsigned int freq) +{ + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); + unsigned int reg; + unsigned int *rates; + int ref, div, refclk; + + switch (clk) { + case ARIZONA_CLK_OPCLK: + reg = ARIZONA_OUTPUT_SYSTEM_CLOCK; + refclk = priv->sysclk; + break; + case ARIZONA_CLK_ASYNC_OPCLK: + reg = ARIZONA_OUTPUT_ASYNC_CLOCK; + refclk = priv->asyncclk; + break; + default: + return -EINVAL; + } + + if (refclk % 8000) + rates = arizona_sysclk_44k1_rates; + else + rates = arizona_sysclk_48k_rates; + + for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) && + rates[ref] <= refclk; ref++) { + div = 1; + while (rates[ref] / div >= freq && div < 32) { + if (rates[ref] / div == freq) { + dev_dbg(codec->dev, "Configured %dHz OPCLK\n", + freq); + snd_soc_update_bits(codec, reg, + ARIZONA_OPCLK_DIV_MASK | + ARIZONA_OPCLK_SEL_MASK, + (div << + ARIZONA_OPCLK_DIV_SHIFT) | + ref); + return 0; + } + div++; + } + } + + dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq); + return -EINVAL; +} + int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, int source, unsigned int freq, int dir) { @@ -252,6 +315,9 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, reg = ARIZONA_ASYNC_CLOCK_1; clk = &priv->asyncclk; break; + case ARIZONA_CLK_OPCLK: + case ARIZONA_CLK_ASYNC_OPCLK: + return arizona_set_opclk(codec, clk_id, freq); default: return -EINVAL; } diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 59caca8865e8..eb66b52777c9 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -17,8 +17,10 @@ #include -#define ARIZONA_CLK_SYSCLK 1 -#define ARIZONA_CLK_ASYNCCLK 2 +#define ARIZONA_CLK_SYSCLK 1 +#define ARIZONA_CLK_ASYNCCLK 2 +#define ARIZONA_CLK_OPCLK 3 +#define ARIZONA_CLK_ASYNC_OPCLK 4 #define ARIZONA_CLK_SRC_MCLK1 0x0 #define ARIZONA_CLK_SRC_MCLK2 0x1 From c665d1a8c4c391a7918f53c8a02d909626266773 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Aug 2012 17:53:01 +0100 Subject: [PATCH 058/665] ASoC: wm5102: Enable output clocks Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 6537f16d383e..4c2fc361051c 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -285,6 +285,10 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, + ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, + ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), From 94237f8e8ed5c2bfc5d8a28cdda241170eda6994 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 9 Aug 2012 19:14:43 +0100 Subject: [PATCH 059/665] ASoC: wm5110: Enable output clocks Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 8033f7065189..3db6e6e7a591 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -305,6 +305,10 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, + ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, + ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), From b545dd924b4ffaf1e4fdd73fe7e9b6eb01e45aea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Aug 2012 20:03:02 +0100 Subject: [PATCH 060/665] ASoC: bells: Add machine driver for Wolfson Bells boards The Wolfson Bells board takes submodules for various audio functions but since the system integrations are virtually identical for most of them we can support the overwhemling majority from the same machine driver. Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 8 + sound/soc/samsung/Makefile | 2 + sound/soc/samsung/bells.c | 346 +++++++++++++++++++++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 sound/soc/samsung/bells.c diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fe3995ce9b38..fb5600083612 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -199,6 +199,14 @@ config SND_SOC_TOBERMORY select SND_SAMSUNG_I2S select SND_SOC_WM8962 +config SND_SOC_BELLS + tristate "Audio support for Wolfson Bells" + depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 + select SND_SAMSUNG_I2S + select SND_SOC_WM5102 + select SND_SOC_WM5110 + select SND_SOC_WM9081 + config SND_SOC_LOWLAND tristate "Audio support for Wolfson Lowland" depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 9d03beb40c86..709f6059ad67 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -42,6 +42,7 @@ snd-soc-speyside-objs := speyside.o snd-soc-tobermory-objs := tobermory.o snd-soc-lowland-objs := lowland.o snd-soc-littlemill-objs := littlemill.o +snd-soc-bells-objs := bells.o obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -65,3 +66,4 @@ obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o +obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c new file mode 100644 index 000000000000..5dc10dfc0d42 --- /dev/null +++ b/sound/soc/samsung/bells.c @@ -0,0 +1,346 @@ +/* + * Bells audio support + * + * Copyright 2012 Wolfson Microelectronics + * + * 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 "../codecs/wm5102.h" +#include "../codecs/wm9081.h" + +/* + * 44.1kHz based clocks for the SYSCLK domain, use a very high clock + * to allow all the DSP functionality to be enabled if desired. + */ +#define SYSCLK_RATE (44100 * 1024) + +/* 48kHz based clocks for the ASYNC domain */ +#define ASYNCCLK_RATE (48000 * 512) + +/* BCLK2 is fixed at this currently */ +#define BCLK2_RATE (64 * 8000) + +/* + * Expect a 24.576MHz crystal if one is fitted (the driver will function + * if this is not fitted). + */ +#define MCLK_RATE 24576000 + +#define WM9081_AUDIO_RATE 44100 +#define WM9081_MCLK_RATE (WM9081_AUDIO_RATE * 256) + +static int bells_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; + int ret; + + if (dapm->dev != codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_PREPARE: + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { + ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, + ARIZONA_FLL_SRC_MCLK1, + MCLK_RATE, + SYSCLK_RATE); + if (ret < 0) + pr_err("Failed to start FLL: %d\n", ret); + + ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, + ARIZONA_FLL_SRC_AIF2BCLK, + BCLK2_RATE, + ASYNCCLK_RATE); + if (ret < 0) + pr_err("Failed to start FLL: %d\n", ret); + } + break; + + default: + break; + } + + return 0; +} + +static int bells_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; + int ret; + + if (dapm->dev != codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 0, 0, 0); + if (ret < 0) { + pr_err("Failed to stop FLL: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0); + if (ret < 0) { + pr_err("Failed to stop FLL: %d\n", ret); + return ret; + } + break; + + default: + break; + } + + dapm->bias_level = level; + + return 0; +} + +static int bells_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_codec *codec = card->rtd[0].codec; + struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; + struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai; + struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); + if (ret != 0) { + dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); + if (ret != 0) { + dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); + if (ret != 0) { + dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, + ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE, + SND_SOC_CLOCK_IN); + if (ret != 0) { + dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0, + WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT); + if (ret != 0) { + dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, + ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE, + SND_SOC_CLOCK_IN); + if (ret != 0) { + dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK, + 0, WM9081_MCLK_RATE, 0); + if (ret != 0) { + dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct snd_soc_pcm_stream baseband_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 2, + .channels_max = 2, +}; + +static const struct snd_soc_pcm_stream sub_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = WM9081_AUDIO_RATE, + .rate_max = WM9081_AUDIO_RATE, + .channels_min = 2, + .channels_max = 2, +}; + +static struct snd_soc_dai_link bells_dai_wm5102[] = { + { + .name = "CPU", + .stream_name = "CPU", + .cpu_dai_name = "samsung-i2s.0", + .codec_dai_name = "wm5102-aif1", + .platform_name = "samsung-audio", + .codec_name = "wm5102-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "Baseband", + .stream_name = "Baseband", + .cpu_dai_name = "wm5102-aif2", + .codec_dai_name = "wm1250-ev1", + .codec_name = "wm1250-ev1.1-0027", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + .params = &baseband_params, + }, + { + .name = "Sub", + .stream_name = "Sub", + .cpu_dai_name = "wm5102-aif3", + .codec_dai_name = "wm9081-hifi", + .codec_name = "wm9081.1-006c", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .params = &sub_params, + }, +}; + +static struct snd_soc_dai_link bells_dai_wm5110[] = { + { + .name = "CPU", + .stream_name = "CPU", + .cpu_dai_name = "samsung-i2s.0", + .codec_dai_name = "wm5110-aif1", + .platform_name = "samsung-audio", + .codec_name = "wm5110-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "Baseband", + .stream_name = "Baseband", + .cpu_dai_name = "wm5110-aif2", + .codec_dai_name = "wm1250-ev1", + .codec_name = "wm1250-ev1.1-0027", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + .params = &baseband_params, + }, + { + .name = "Sub", + .stream_name = "Sub", + .cpu_dai_name = "wm5102-aif3", + .codec_dai_name = "wm9081-hifi", + .codec_name = "wm9081.1-006c", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .params = &sub_params, + }, +}; + +static struct snd_soc_codec_conf bells_codec_conf[] = { + { + .dev_name = "wm9081.1-006c", + .name_prefix = "Sub", + }, +}; + +static struct snd_soc_dapm_route bells_routes[] = { + { "Sub CLK_SYS", NULL, "OPCLK" }, +}; + +static struct snd_soc_card bells_cards[] = { + { + .name = "Bells WM5102", + .owner = THIS_MODULE, + .dai_link = bells_dai_wm5102, + .num_links = ARRAY_SIZE(bells_dai_wm5102), + .codec_conf = bells_codec_conf, + .num_configs = ARRAY_SIZE(bells_codec_conf), + + .late_probe = bells_late_probe, + + .dapm_routes = bells_routes, + .num_dapm_routes = ARRAY_SIZE(bells_routes), + + .set_bias_level = bells_set_bias_level, + .set_bias_level_post = bells_set_bias_level_post, + }, + { + .name = "Bells WM5110", + .owner = THIS_MODULE, + .dai_link = bells_dai_wm5110, + .num_links = ARRAY_SIZE(bells_dai_wm5110), + .codec_conf = bells_codec_conf, + .num_configs = ARRAY_SIZE(bells_codec_conf), + + .late_probe = bells_late_probe, + + .dapm_routes = bells_routes, + .num_dapm_routes = ARRAY_SIZE(bells_routes), + + .set_bias_level = bells_set_bias_level, + .set_bias_level_post = bells_set_bias_level_post, + }, +}; + + +static __devinit int bells_probe(struct platform_device *pdev) +{ + int ret; + + bells_cards[pdev->id].dev = &pdev->dev; + + ret = snd_soc_register_card(&bells_cards[pdev->id]); + if (ret) { + dev_err(&pdev->dev, + "snd_soc_register_card(%s) failed: %d\n", + bells_cards[pdev->id].name, ret); + return ret; + } + + return 0; +} + +static int __devexit bells_remove(struct platform_device *pdev) +{ + snd_soc_unregister_card(&bells_cards[pdev->id]); + + return 0; +} + +static struct platform_driver bells_driver = { + .driver = { + .name = "bells", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = bells_probe, + .remove = __devexit_p(bells_remove), +}; + +module_platform_driver(bells_driver); + +MODULE_DESCRIPTION("Bells audio support"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bells"); From 367e43c50d7f7c3b0cec17f4d855a96f47f5e17b Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Fri, 10 Aug 2012 11:55:11 +0200 Subject: [PATCH 061/665] link-vmlinux.sh: Fix stray "echo" in error message Reported-by: Jan Engelhardt Signed-off-by: Michal Marek --- scripts/link-vmlinux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 4629038c9e5a..4235a6361fec 100644 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -211,7 +211,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then if ! cmp -s System.map .tmp_System.map; then echo >&2 Inconsistent kallsyms data - echo >&2 echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround + echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround cleanup exit 1 fi From 3876566a368b30908ec4195d58f04a411f22f736 Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Thu, 9 Aug 2012 23:16:26 -0700 Subject: [PATCH 062/665] ASoC: core: remove unused variable in soc_probe() in linux-next With commit 28d528c8 "ASoC: core: Remove pointless error on card registration failure", the variable ret is no longer used in soc_probe() and generates an unused variable warning during a build. Signed-off-by: Jerry Snitselaar Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3a43fa6ba2ee..f585d0239551 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1814,7 +1814,6 @@ base_error: static int soc_probe(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - int ret = 0; /* * no card, so machine driver should be registering card From 61a0cfb008f57ecf7eb28ee762952fb42dc15d15 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Wed, 1 Aug 2012 20:34:15 -0300 Subject: [PATCH 063/665] Bluetooth: Fix use-after-free bug in SMP If SMP fails, we should always cancel security_timer delayed work. Otherwise, security_timer function may run after l2cap_conn object has been freed. This patch fixes the following warning reported by ODEBUG: WARNING: at lib/debugobjects.c:261 debug_print_object+0x7c/0x8d() Hardware name: Bochs ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x27 Modules linked in: btusb bluetooth Pid: 440, comm: kworker/u:2 Not tainted 3.5.0-rc1+ #4 Call Trace: [] ? free_obj_work+0x4a/0x7f [] warn_slowpath_common+0x7e/0x97 [] warn_slowpath_fmt+0x41/0x43 [] debug_print_object+0x7c/0x8d [] ? __queue_work+0x241/0x241 [] debug_check_no_obj_freed+0x92/0x159 [] slab_free_hook+0x6f/0x77 [] ? l2cap_conn_del+0x148/0x157 [bluetooth] [] kfree+0x59/0xac [] l2cap_conn_del+0x148/0x157 [bluetooth] [] l2cap_recv_frame+0xa77/0xfa4 [bluetooth] [] ? trace_hardirqs_on_caller+0x112/0x1ad [] l2cap_recv_acldata+0xe2/0x264 [bluetooth] [] hci_rx_work+0x235/0x33c [bluetooth] [] ? process_one_work+0x126/0x2fe [] process_one_work+0x185/0x2fe [] ? process_one_work+0x126/0x2fe [] ? lock_acquired+0x1b5/0x1cf [] ? le_scan_work+0x11d/0x11d [bluetooth] [] ? spin_lock_irq+0x9/0xb [] worker_thread+0xcf/0x175 [] ? rescuer_thread+0x175/0x175 [] kthread+0x95/0x9d [] kernel_threadi_helper+0x4/0x10 [] ? retint_restore_args+0x13/0x13 [] ? flush_kthread_worker+0xdb/0xdb [] ? gs_change+0x13/0x13 This bug can be reproduced using hctool lecc or l2test tools and bluetoothd not running. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/smp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 901a616c8083..98ffc1b6a6fa 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -267,10 +267,10 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, hcon->dst_type, reason); - if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { - cancel_delayed_work_sync(&conn->security_timer); + cancel_delayed_work_sync(&conn->security_timer); + + if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) smp_chan_destroy(conn); - } } #define JUST_WORKS 0x00 From bc21fde2d549d1cb1ebef04016eb7affa43bb5c1 Mon Sep 17 00:00:00 2001 From: Yevgeniy Melnichuk Date: Tue, 7 Aug 2012 19:48:10 +0530 Subject: [PATCH 064/665] Bluetooth: Add support for Sony Vaio T-Series Add Sony Vaio T-Series Bluetooth Module( 0x489:0xE036) to the blacklist of btusb module and add it to the ath3k module. output of cat /sys/kernel/debug/usb/devices T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 5 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e036 Rev= 0.02 S: Manufacturer=Atheros Communications S: Product=Bluetooth USB Host Controller S: SerialNumber=Alaska Day 2006 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Yevgeniy Melnichuk Signed-off-by: Mohammed Shafi Shajakhan Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 11f36e502136..fc2de5528dcc 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -86,6 +86,7 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C) }, + { USB_DEVICE(0x0489, 0xE036) }, { } /* Terminating entry */ }; @@ -109,6 +110,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index cef3bac1a543..2fe7776dc49c 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -141,6 +141,7 @@ static struct usb_device_id blacklist_table[] = { /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, From fff8491c8b8cce5fc9190e025d1a665f2ee71a4f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 14 Aug 2012 12:07:56 +0300 Subject: [PATCH 065/665] ASoC: omap-twl4030: Simple machine driver for TI SoC with twl4030 codec Machine driver to handle simple devices using twl4030 as audio codec. The driver supports the following boards: - Beagleboard or Devkit8000 - Gumstix Overo or CompuLab CM-T35/CM-T3730 - IGEP v2 - OMAP3EVM All of these boards can be switched to use this driver since their setup is identical. Devicetree support for the omap-twl4030 machine driver also implemented. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../bindings/sound/omap-twl4030.txt | 17 ++ include/linux/platform_data/omap-twl4030.h | 32 +++ sound/soc/omap/Kconfig | 13 ++ sound/soc/omap/Makefile | 2 + sound/soc/omap/omap-twl4030.c | 188 ++++++++++++++++++ 5 files changed, 252 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/omap-twl4030.txt create mode 100644 include/linux/platform_data/omap-twl4030.h create mode 100644 sound/soc/omap/omap-twl4030.c diff --git a/Documentation/devicetree/bindings/sound/omap-twl4030.txt b/Documentation/devicetree/bindings/sound/omap-twl4030.txt new file mode 100644 index 000000000000..6fae51c7f766 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-twl4030.txt @@ -0,0 +1,17 @@ +* Texas Instruments SoC with twl4030 based audio setups + +Required properties: +- compatible: "ti,omap-twl4030" +- ti,model: Name of the sound card (for example "omap3beagle") +- ti,mcbsp: phandle for the McBSP node +- ti,codec: phandle for the twl4030 audio node + +Example: + +sound { + compatible = "ti,omap-twl4030"; + ti,model = "omap3beagle"; + + ti,mcbsp = <&mcbsp2>; + ti,codec = <&twl_audio>; +}; diff --git a/include/linux/platform_data/omap-twl4030.h b/include/linux/platform_data/omap-twl4030.h new file mode 100644 index 000000000000..c7bef788daab --- /dev/null +++ b/include/linux/platform_data/omap-twl4030.h @@ -0,0 +1,32 @@ +/** + * omap-twl4030.h - ASoC machine driver for TI SoC based boards with twl4030 + * codec, header. + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * All rights reserved. + * + * Author: Peter Ujfalusi + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef _OMAP_TWL4030_H_ +#define _OMAP_TWL4030_H_ + +struct omap_tw4030_pdata { + const char *card_name; +}; + +#endif /* _OMAP_TWL4030_H_ */ diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 57a2fa751085..fc83d748625f 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -95,6 +95,19 @@ config SND_OMAP_SOC_SDP3430 Say Y if you want to add support for SoC audio on Texas Instruments SDP3430. +config SND_OMAP_SOC_OMAP_TWL4030 + tristate "SoC Audio support for TI SoC based boards with twl4030 codec" + depends on TWL4030_CORE && SND_OMAP_SOC + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on TI SoC based boards + using twl4030 as c codec. This driver currently supports: + - Beagleboard or Devkit8000 + - Gumstix Overo or CompuLab CM-T35/CM-T3730 + - IGEP v2 + - OMAP3EVM + config SND_OMAP_SOC_OMAP_ABE_TWL6040 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 0e14dd322565..861e640e2be9 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -21,6 +21,7 @@ snd-soc-omap3evm-objs := omap3evm.o snd-soc-am3517evm-objs := am3517evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o +snd-soc-omap-twl4030-objs := omap-twl4030.o snd-soc-omap3pandora-objs := omap3pandora.o snd-soc-omap3beagle-objs := omap3beagle.o snd-soc-zoom2-objs := zoom2.o @@ -37,6 +38,7 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c new file mode 100644 index 000000000000..3b97b87971f5 --- /dev/null +++ b/sound/soc/omap/omap-twl4030.c @@ -0,0 +1,188 @@ +/* + * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * All rights reserved. + * + * Author: Peter Ujfalusi + * + * This driver replaces the following machine drivers: + * omap3beagle (Author: Steve Sakoman ) + * omap3evm (Author: Anuj Aggarwal ) + * overo (Author: Steve Sakoman ) + * igep0020 (Author: Enric Balletbo i Serra ) + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "omap-mcbsp.h" +#include "omap-pcm.h" + +static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *card = codec->card; + unsigned int fmt; + int ret; + + switch (params_channels(params)) { + case 2: /* Stereo I2S mode */ + fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM; + break; + case 4: /* Four channel TDM mode */ + fmt = SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM; + break; + default: + return -EINVAL; + } + + /* Set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(card->dev, "can't set codec DAI configuration\n"); + return ret; + } + + /* Set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) { + dev_err(card->dev, "can't set cpu DAI configuration\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops omap_twl4030_ops = { + .hw_params = omap_twl4030_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link omap_twl4030_dai_links[] = { + { + .name = "TWL4030", + .stream_name = "TWL4030", + .cpu_dai_name = "omap-mcbsp.2", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", + .ops = &omap_twl4030_ops, + }, +}; + +/* Audio machine driver */ +static struct snd_soc_card omap_twl4030_card = { + .owner = THIS_MODULE, + .dai_link = omap_twl4030_dai_links, + .num_links = ARRAY_SIZE(omap_twl4030_dai_links), +}; + +static __devinit int omap_twl4030_probe(struct platform_device *pdev) +{ + struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev); + struct device_node *node = pdev->dev.of_node; + struct snd_soc_card *card = &omap_twl4030_card; + int ret = 0; + + card->dev = &pdev->dev; + + if (node) { + struct device_node *dai_node; + + if (snd_soc_of_parse_card_name(card, "ti,model")) { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + dai_node = of_parse_phandle(node, "ti,mcbsp", 0); + if (!dai_node) { + dev_err(&pdev->dev, "McBSP node is not provided\n"); + return -EINVAL; + } + omap_twl4030_dai_links[0].cpu_dai_name = NULL; + omap_twl4030_dai_links[0].cpu_of_node = dai_node; + + } else if (pdata) { + if (pdata->card_name) { + card->name = pdata->card_name; + } else { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + } else { + dev_err(&pdev->dev, "Missing pdata\n"); + return -ENODEV; + } + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + return ret; + } + + return 0; +} + +static int __devexit omap_twl4030_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static const struct of_device_id omap_twl4030_of_match[] = { + {.compatible = "ti,omap-twl4030", }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_twl4030_of_match); + +static struct platform_driver omap_twl4030_driver = { + .driver = { + .name = "omap-twl4030", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = omap_twl4030_of_match, + }, + .probe = omap_twl4030_probe, + .remove = __devexit_p(omap_twl4030_remove), +}; + +module_platform_driver(omap_twl4030_driver); + +MODULE_AUTHOR("Peter Ujfalusi "); +MODULE_DESCRIPTION("ALSA SoC for TI SoC based boards with twl4030 codec"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:omap-twl4030"); From 552d9dc316cfedd134ee882cd1ae24ca6934ffc0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 14 Aug 2012 12:07:57 +0300 Subject: [PATCH 066/665] ARM: OMAP: twl-common: Add helper function to register the omap-twl4030 audio driver Since several OMAP3 based boards will be using the unified simple audio driver it is better to not have duplicated code in the board files for this purpose. Board files can call omap_twl4030_audio_init(); to set up the needed device for the audio support. For example: omap_twl4030_audio_init("omap3beagle", 26000000); Signed-off-by: Peter Ujfalusi Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/twl-common.c | 27 +++++++++++++++++++++++++++ arch/arm/mach-omap2/twl-common.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index de47f170ba50..0606f238a247 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -537,3 +537,30 @@ void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data, pmic_data->v2v1 = &omap4_v2v1_idata; } #endif /* CONFIG_ARCH_OMAP4 */ + +#if defined(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) || \ + defined(CONFIG_SND_OMAP_SOC_OMAP_TWL4030_MODULE) +#include + +static struct omap_tw4030_pdata omap_twl4030_audio_data; + +static struct platform_device audio_device = { + .name = "omap-twl4030", + .id = -1, + .dev = { + .platform_data = &omap_twl4030_audio_data, + }, +}; + +void __init omap_twl4030_audio_init(char *card_name) +{ + omap_twl4030_audio_data.card_name = card_name; + platform_device_register(&audio_device); +} + +#else /* SOC_OMAP_TWL4030 */ +void __init omap_twl4030_audio_init(char *card_name, int codec_sysclk) +{ + return; +} +#endif /* SOC_OMAP_TWL4030 */ diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h index 8fe71cfd002c..cb25b43317a7 100644 --- a/arch/arm/mach-omap2/twl-common.h +++ b/arch/arm/mach-omap2/twl-common.h @@ -59,4 +59,6 @@ void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data, void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data, u32 pdata_flags, u32 regulators_flags); +void omap_twl4030_audio_init(char *card_name); + #endif /* __OMAP_PMIC_COMMON__ */ From ac51c90f10be1d1e360f50ca521e3a2133919d23 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 14 Aug 2012 12:07:58 +0300 Subject: [PATCH 067/665] ARM: OMAP3: Switch to use the unified audio driver (omap-twl4030) for selected boards These boards have similar audio setup and they can all use the same driver for audio support if it is enabled in the kernel config. Signed-off-by: Peter Ujfalusi Cc: Igor Grinberg Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/board-cm-t35.c | 1 + arch/arm/mach-omap2/board-devkit8000.c | 1 + arch/arm/mach-omap2/board-igep0020.c | 1 + arch/arm/mach-omap2/board-omap3beagle.c | 1 + arch/arm/mach-omap2/board-omap3evm.c | 1 + arch/arm/mach-omap2/board-overo.c | 1 + 6 files changed, 6 insertions(+) diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 97d719047af3..188cc4eb0a79 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -731,6 +731,7 @@ static void __init cm_t3x_common_init(void) cm_t35_init_ethernet(); cm_t35_init_led(); cm_t35_init_display(); + omap_twl4030_audio_init("cm-t3x"); usb_musb_init(NULL); cm_t35_init_usbh(); diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6567c1cd5572..4cd804f615a5 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -630,6 +630,7 @@ static void __init devkit8000_init(void) usbhs_init(&usbhs_bdata); omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, ARRAY_SIZE(devkit8000_nand_partitions)); + omap_twl4030_audio_init("omap3beagle"); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 74915295482e..293fc9c2bea9 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -626,6 +626,7 @@ static void __init igep_init(void) igep_flash_init(); igep_leds_init(); + omap_twl4030_audio_init("igep2"); /* * WLAN-BT combo module from MuRata which has a Marvell WLAN diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 6202fc76e490..3ccfa5b23a24 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -519,6 +519,7 @@ static void __init omap3_beagle_init(void) usbhs_init(&usbhs_bdata); omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, ARRAY_SIZE(omap3beagle_nand_partitions)); + omap_twl4030_audio_init("omap3beagle"); /* Ensure msecure is mux'd to be able to set the RTC. */ omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH); diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index ef230a0eb5eb..46e6ecad5696 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -736,6 +736,7 @@ static void __init omap3_evm_init(void) omap3evm_init_smsc911x(); omap3_evm_display_init(); omap3_evm_wl12xx_init(); + omap_twl4030_audio_init("omap3evm"); } MACHINE_START(OMAP3EVM, "OMAP3 EVM") diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 779734d8ba37..fe674d0c6c04 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -509,6 +509,7 @@ static void __init overo_init(void) overo_display_init(); overo_init_led(); overo_init_keys(); + omap_twl4030_audio_init("overo"); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); From 152c6e56f6a8577bd291f6f4ca897e5758332a1b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 14 Aug 2012 12:07:59 +0300 Subject: [PATCH 068/665] ASoC: Remove obsolete OMAP3 machine drivers The new omap-twl4030 handles the boards used the following drivers: igep0020, omap3beagle, omap3evm and overo. Remove these drivers since they are mostly identical and we already have drop in replacement for all of them. Note: Earlier patch added the needed code for the board files to retain the audio support for boards I can identify that used one of the removed drivers. If I missed something please take a look at for example: arch/arm/mach-omap2/board-omap3beagle.c on how add support for omap-twl4030 audio. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/Kconfig | 35 -------- sound/soc/omap/Makefile | 8 -- sound/soc/omap/igep0020.c | 120 ---------------------------- sound/soc/omap/omap3beagle.c | 150 ----------------------------------- sound/soc/omap/omap3evm.c | 118 --------------------------- sound/soc/omap/overo.c | 122 ---------------------------- 6 files changed, 553 deletions(-) delete mode 100644 sound/soc/omap/igep0020.c delete mode 100644 sound/soc/omap/omap3beagle.c delete mode 100644 sound/soc/omap/omap3evm.c delete mode 100644 sound/soc/omap/overo.c diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index fc83d748625f..2c484a52ef92 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -60,23 +60,6 @@ config SND_OMAP_SOC_OSK5912 help Say Y if you want to add support for SoC audio on osk5912. -config SND_OMAP_SOC_OVERO - tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35" - depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35) - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the - Gumstix Overo or CompuLab CM-T35 - -config SND_OMAP_SOC_OMAP3EVM - tristate "SoC Audio support for OMAP3EVM board" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the omap3evm board. - config SND_OMAP_SOC_AM3517EVM tristate "SoC Audio support for OMAP3517 / AM3517 EVM" depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C @@ -140,16 +123,6 @@ config SND_OMAP_SOC_OMAP3_PANDORA help Say Y if you want to add support for SoC audio on the OMAP3 Pandora. -config SND_OMAP_SOC_OMAP3_BEAGLE - tristate "SoC Audio support for OMAP3 Beagle and Devkit8000" - depends on TWL4030_CORE && SND_OMAP_SOC - depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000) - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the Beagleboard or - the clone Devkit8000. - config SND_OMAP_SOC_ZOOM2 tristate "SoC Audio support for Zoom2" depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 @@ -157,11 +130,3 @@ config SND_OMAP_SOC_ZOOM2 select SND_SOC_TWL4030 help Say Y if you want to add support for Soc audio on Zoom2 board. - -config SND_OMAP_SOC_IGEP0020 - tristate "SoC Audio support for IGEP v2" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for Soc audio on IGEP v2 board. diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 861e640e2be9..19637e55ea48 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -16,31 +16,23 @@ snd-soc-n810-objs := n810.o snd-soc-rx51-objs := rx51.o snd-soc-ams-delta-objs := ams-delta.o snd-soc-osk5912-objs := osk5912.o -snd-soc-overo-objs := overo.o -snd-soc-omap3evm-objs := omap3evm.o snd-soc-am3517evm-objs := am3517evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o snd-soc-omap-twl4030-objs := omap-twl4030.o snd-soc-omap3pandora-objs := omap3pandora.o -snd-soc-omap3beagle-objs := omap3beagle.o snd-soc-zoom2-objs := zoom2.o -snd-soc-igep0020-objs := igep0020.o snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o -obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o -obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c deleted file mode 100644 index e8357819175b..000000000000 --- a/sound/soc/omap/igep0020.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * igep0020.c -- SoC audio for IGEP v2 - * - * Based on sound/soc/omap/overo.c by Steve Sakoman - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int igep2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops igep2_ops = { - .hw_params = igep2_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link igep2_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &igep2_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_card_igep2 = { - .name = "igep2", - .owner = THIS_MODULE, - .dai_link = &igep2_dai, - .num_links = 1, -}; - -static struct platform_device *igep2_snd_device; - -static int __init igep2_soc_init(void) -{ - int ret; - - if (!machine_is_igep0020()) - return -ENODEV; - printk(KERN_INFO "IGEP v2 SoC init\n"); - - igep2_snd_device = platform_device_alloc("soc-audio", -1); - if (!igep2_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2); - - ret = platform_device_add(igep2_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(igep2_snd_device); - - return ret; -} -module_init(igep2_soc_init); - -static void __exit igep2_soc_exit(void) -{ - platform_device_unregister(igep2_snd_device); -} -module_exit(igep2_soc_exit); - -MODULE_AUTHOR("Enric Balletbo i Serra "); -MODULE_DESCRIPTION("ALSA SoC IGEP v2"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c deleted file mode 100644 index 2830dfd05661..000000000000 --- a/sound/soc/omap/omap3beagle.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * omap3beagle.c -- SoC audio for OMAP3 Beagle - * - * Author: Steve Sakoman - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int omap3beagle_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int fmt; - int ret; - - switch (params_channels(params)) { - case 2: /* Stereo I2S mode */ - fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; - break; - case 4: /* Four channel TDM mode */ - fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM; - break; - default: - return -EINVAL; - } - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, fmt); - if (ret < 0) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - return ret; - } - - /* Set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); - if (ret < 0) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return ret; - } - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops omap3beagle_ops = { - .hw_params = omap3beagle_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3beagle_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .platform_name = "omap-pcm-audio", - .codec_dai_name = "twl4030-hifi", - .codec_name = "twl4030-codec", - .ops = &omap3beagle_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_omap3beagle = { - .name = "omap3beagle", - .owner = THIS_MODULE, - .dai_link = &omap3beagle_dai, - .num_links = 1, -}; - -static struct platform_device *omap3beagle_snd_device; - -static int __init omap3beagle_soc_init(void) -{ - int ret; - - if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) - return -ENODEV; - pr_info("OMAP3 Beagle/Devkit8000 SoC init\n"); - - omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); - if (!omap3beagle_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle); - - ret = platform_device_add(omap3beagle_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(omap3beagle_snd_device); - - return ret; -} - -static void __exit omap3beagle_soc_exit(void) -{ - platform_device_unregister(omap3beagle_snd_device); -} - -module_init(omap3beagle_soc_init); -module_exit(omap3beagle_soc_exit); - -MODULE_AUTHOR("Steve Sakoman "); -MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c deleted file mode 100644 index 3d468c9179d7..000000000000 --- a/sound/soc/omap/omap3evm.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * omap3evm.c -- ALSA SoC support for OMAP3 EVM - * - * Author: Anuj Aggarwal - * - * Based on sound/soc/omap/beagle.c by Steve Sakoman - * - * Copyright (C) 2008 Texas Instruments, Incorporated - * - * 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; 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 "omap-mcbsp.h" -#include "omap-pcm.h" - -static int omap3evm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops omap3evm_ops = { - .hw_params = omap3evm_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3evm_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &omap3evm_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_omap3evm = { - .name = "omap3evm", - .owner = THIS_MODULE, - .dai_link = &omap3evm_dai, - .num_links = 1, -}; - -static struct platform_device *omap3evm_snd_device; - -static int __init omap3evm_soc_init(void) -{ - int ret; - - if (!machine_is_omap3evm()) - return -ENODEV; - pr_info("OMAP3 EVM SoC init\n"); - - omap3evm_snd_device = platform_device_alloc("soc-audio", -1); - if (!omap3evm_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm); - ret = platform_device_add(omap3evm_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(omap3evm_snd_device); - - return ret; -} - -static void __exit omap3evm_soc_exit(void) -{ - platform_device_unregister(omap3evm_snd_device); -} - -module_init(omap3evm_soc_init); -module_exit(omap3evm_soc_exit); - -MODULE_AUTHOR("Anuj Aggarwal "); -MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c deleted file mode 100644 index 6ac3e0c3c282..000000000000 --- a/sound/soc/omap/overo.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * overo.c -- SoC audio for Gumstix Overo - * - * Author: Steve Sakoman - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int overo_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops overo_ops = { - .hw_params = overo_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link overo_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &overo_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_card_overo = { - .name = "overo", - .owner = THIS_MODULE, - .dai_link = &overo_dai, - .num_links = 1, -}; - -static struct platform_device *overo_snd_device; - -static int __init overo_soc_init(void) -{ - int ret; - - if (!(machine_is_overo() || machine_is_cm_t35())) { - pr_debug("Incomatible machine!\n"); - return -ENODEV; - } - printk(KERN_INFO "overo SoC init\n"); - - overo_snd_device = platform_device_alloc("soc-audio", -1); - if (!overo_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(overo_snd_device, &snd_soc_card_overo); - - ret = platform_device_add(overo_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(overo_snd_device); - - return ret; -} -module_init(overo_soc_init); - -static void __exit overo_soc_exit(void) -{ - platform_device_unregister(overo_snd_device); -} -module_exit(overo_soc_exit); - -MODULE_AUTHOR("Steve Sakoman "); -MODULE_DESCRIPTION("ALSA SoC overo"); -MODULE_LICENSE("GPL"); From c61307a7cc1be87b6785dad0885492b6ca7998db Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 9 Aug 2012 08:38:43 +0200 Subject: [PATCH 069/665] gpio: Fix debug message in of_get_named_gpio_flags() This was probably missed in the conversion done in commit 3d0f7cf ("gpio: Adjust of_xlate API to support multiple GPIO chips"). Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a18c4aa68b1e..f1a45997aea8 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -82,7 +82,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); of_node_put(gg_data.gpiospec.np); - pr_debug("%s exited with status %d\n", __func__, ret); + pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio); return gg_data.out_gpio; } EXPORT_SYMBOL(of_get_named_gpio_flags); From a3150f09174ace7878bf4bbbf23d3ba25cc01261 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 16 Aug 2012 20:28:18 +0100 Subject: [PATCH 070/665] ASoC: wm5102: Add AEC routing control Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 4c2fc361051c..2e6f1ffc9fd4 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -280,6 +280,27 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); + +static const char *wm5102_aec_loopback_texts[] = { + "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", + "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", +}; + +static const unsigned int wm5102_aec_loopback_values[] = { + 0, 1, 2, 3, 4, 6, 7, 8, 9, +}; + +static const struct soc_enum wm5102_aec_loopback = + SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, + ARIZONA_AEC_LOOPBACK_SRC_MASK, + ARRAY_SIZE(wm5102_aec_loopback_texts), + wm5102_aec_loopback_texts, + wm5102_aec_loopback_values); + +static const struct snd_kcontrol_new wm5102_aec_loopback_mux = + SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5102_aec_loopback); + static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0), @@ -435,6 +456,9 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, + ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), + SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), @@ -532,6 +556,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), { name, "Noise Generator", "Noise Generator" }, \ { name, "Tone Generator 1", "Tone Generator 1" }, \ { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "AEC", "AEC Loopback" }, \ { name, "IN1L", "IN1L PGA" }, \ { name, "IN1R", "IN1R PGA" }, \ { name, "IN2L", "IN2L PGA" }, \ @@ -692,21 +717,30 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), + { "AEC Loopback", "HPOUT1L", "OUT1L" }, + { "AEC Loopback", "HPOUT1R", "OUT1R" }, { "HPOUT1L", NULL, "OUT1L" }, { "HPOUT1R", NULL, "OUT1R" }, + { "AEC Loopback", "HPOUT2L", "OUT2L" }, + { "AEC Loopback", "HPOUT2R", "OUT2R" }, { "HPOUT2L", NULL, "OUT2L" }, { "HPOUT2R", NULL, "OUT2R" }, + { "AEC Loopback", "EPOUT", "OUT3L" }, { "EPOUTN", NULL, "OUT3L" }, { "EPOUTP", NULL, "OUT3L" }, + { "AEC Loopback", "SPKOUTL", "OUT4L" }, { "SPKOUTLN", NULL, "OUT4L" }, { "SPKOUTLP", NULL, "OUT4L" }, + { "AEC Loopback", "SPKOUTR", "OUT4R" }, { "SPKOUTRN", NULL, "OUT4R" }, { "SPKOUTRP", NULL, "OUT4R" }, + { "AEC Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC Loopback", "SPKDAT1R", "OUT5R" }, { "SPKDAT1L", NULL, "OUT5L" }, { "SPKDAT1R", NULL, "OUT5R" }, }; From 45a690f6bcd5506d9988d0d069811ac9380750ad Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 15 Aug 2012 19:20:54 +0100 Subject: [PATCH 071/665] ASoC: wm8994: Add bytes controls for DRC If DRC coefficients are not configured via platform data then add bytes controls for them instead so they can be configured by applications. This is the normal means of controlling things like this for newer systems, we maintain compatibility with platform data to avoid disruption to existing systems. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 02080da8b451..353612eec8bf 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -671,6 +671,18 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, eq_tlv), }; +static const struct snd_kcontrol_new wm8994_drc_controls[] = { +SND_SOC_BYTES_MASK("AIF1.1 DRC", WM8994_AIF1_DRC1_1, 5, + WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | + WM8994_AIF1ADC1R_DRC_ENA), +SND_SOC_BYTES_MASK("AIF1.2 DRC", WM8994_AIF1_DRC2_1, 5, + WM8994_AIF1DAC2_DRC_ENA | WM8994_AIF1ADC2L_DRC_ENA | + WM8994_AIF1ADC2R_DRC_ENA), +SND_SOC_BYTES_MASK("AIF2 DRC", WM8994_AIF2_DRC_1, 5, + WM8994_AIF2DAC_DRC_ENA | WM8994_AIF2ADCL_DRC_ENA | + WM8994_AIF2ADCR_DRC_ENA), +}; + static const char *wm8958_ng_text[] = { "30ms", "125ms", "250ms", "500ms", }; @@ -3166,14 +3178,19 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(wm8994->hubs.codec->dev, - "Failed to add DRC mode controls: %d\n", ret); - for (i = 0; i < WM8994_NUM_DRC; i++) wm8994_set_drc(codec, i); + } else { + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + wm8994_drc_controls, + ARRAY_SIZE(wm8994_drc_controls)); } + if (ret != 0) + dev_err(wm8994->hubs.codec->dev, + "Failed to add DRC mode controls: %d\n", ret); + + dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", pdata->num_retune_mobile_cfgs); From d14a13d3d94bae80c3f44ff35a3c76192fb3408c Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Fri, 10 Aug 2012 18:06:08 -0400 Subject: [PATCH 072/665] ASoC: bf5xx-ad1836: convert to use snd_soc_register_card Cpu dai and codec name are passed in through platform data. Signed-off-by: Scott Jiang Signed-off-by: Mark Brown --- sound/soc/blackfin/bf5xx-ad1836.c | 73 ++++++++++++++++--------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index d542d4063771..16b9c9efd19a 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c @@ -59,62 +59,63 @@ static struct snd_soc_ops bf5xx_ad1836_ops = { #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ SND_SOC_DAIFMT_CBM_CFM) -static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { - { - .name = "ad1836", - .stream_name = "AD1836", - .cpu_dai_name = "bfin-tdm.0", - .codec_dai_name = "ad1836-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.4", - .ops = &bf5xx_ad1836_ops, - .dai_fmt = BF5XX_AD1836_DAIFMT, - }, - { - .name = "ad1836", - .stream_name = "AD1836", - .cpu_dai_name = "bfin-tdm.1", - .codec_dai_name = "ad1836-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.4", - .ops = &bf5xx_ad1836_ops, - .dai_fmt = BF5XX_AD1836_DAIFMT, - }, +static struct snd_soc_dai_link bf5xx_ad1836_dai = { + .name = "ad1836", + .stream_name = "AD1836", + .codec_dai_name = "ad1836-hifi", + .platform_name = "bfin-tdm-pcm-audio", + .ops = &bf5xx_ad1836_ops, + .dai_fmt = BF5XX_AD1836_DAIFMT, }; static struct snd_soc_card bf5xx_ad1836 = { .name = "bfin-ad1836", .owner = THIS_MODULE, - .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], + .dai_link = &bf5xx_ad1836_dai, .num_links = 1, }; -static struct platform_device *bfxx_ad1836_snd_device; - -static int __init bf5xx_ad1836_init(void) +static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev) { + struct snd_soc_card *card = &bf5xx_ad1836; + const char **link_name; int ret; - bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1); - if (!bfxx_ad1836_snd_device) - return -ENOMEM; + link_name = pdev->dev.platform_data; + if (!link_name) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + bf5xx_ad1836_dai.cpu_dai_name = link_name[0]; + bf5xx_ad1836_dai.codec_name = link_name[1]; - platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); - ret = platform_device_add(bfxx_ad1836_snd_device); + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + ret = snd_soc_register_card(card); if (ret) - platform_device_put(bfxx_ad1836_snd_device); - + dev_err(&pdev->dev, "Failed to register card\n"); return ret; } -static void __exit bf5xx_ad1836_exit(void) +static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev) { - platform_device_unregister(bfxx_ad1836_snd_device); + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + return 0; } -module_init(bf5xx_ad1836_init); -module_exit(bf5xx_ad1836_exit); +static struct platform_driver bf5xx_ad1836_driver = { + .driver = { + .name = "bfin-snd-ad1836", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = bf5xx_ad1836_driver_probe, + .remove = __devexit_p(bf5xx_ad1836_driver_remove), +}; +module_platform_driver(bf5xx_ad1836_driver); /* Module information */ MODULE_AUTHOR("Barry Song"); From 63f49dce39e5d6a19e5f1f9004eb48e73ba259e8 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Fri, 10 Aug 2012 18:06:09 -0400 Subject: [PATCH 073/665] blackfin: add platform device for ad1836 machine driver Signed-off-by: Mark Brown --- arch/blackfin/mach-bf527/boards/ezkit.c | 20 ++++++++++++++++++++ arch/blackfin/mach-bf533/boards/stamp.c | 20 ++++++++++++++++++++ arch/blackfin/mach-bf537/boards/stamp.c | 20 ++++++++++++++++++++ arch/blackfin/mach-bf561/boards/ezkit.c | 20 ++++++++++++++++++++ arch/blackfin/mach-bf609/boards/ezkit.c | 19 +++++++++++++++++++ 5 files changed, 99 insertions(+) diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index fc179ca07799..29f16e5c37b9 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -587,6 +587,21 @@ static struct platform_device bfin_tdm = { }; #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ + || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) +static const char * const ad1836_link[] = { + "bfin-tdm.0", + "spi0.4", +}; +static struct platform_device bfin_ad1836_machine = { + .name = "bfin-snd-ad1836", + .id = -1, + .dev = { + .platform_data = (void *)ad1836_link, + }, +}; +#endif + static struct spi_board_info bfin_spi_board_info[] __initdata = { #if defined(CONFIG_MTD_M25P80) \ || defined(CONFIG_MTD_M25P80_MODULE) @@ -1269,6 +1284,11 @@ static struct platform_device *stamp_devices[] __initdata = { #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) &bfin_tdm, #endif + +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ + defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) + &bfin_ad1836_machine, +#endif }; static int __init ezkit_init(void) diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index ce88a7165b62..6fca8698bf3b 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -617,6 +617,21 @@ static struct platform_device bfin_ac97_pcm = { }; #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ + || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) +static const char * const ad1836_link[] = { + "bfin-tdm.0", + "spi0.4", +}; +static struct platform_device bfin_ad1836_machine = { + .name = "bfin-snd-ad1836", + .id = -1, + .dev = { + .platform_data = (void *)ad1836_link, + }, +}; +#endif + #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) static const unsigned ad73311_gpio[] = { @@ -754,6 +769,11 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_ac97_pcm, #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ + defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) + &bfin_ad1836_machine, +#endif + #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) &bfin_ad73311_machine, diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 5ed654ae66e1..307bd7e62f43 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -2641,6 +2641,21 @@ static struct platform_device bfin_ac97_pcm = { }; #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ + || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) +static const char * const ad1836_link[] = { + "bfin-tdm.0", + "spi0.4", +}; +static struct platform_device bfin_ad1836_machine = { + .name = "bfin-snd-ad1836", + .id = -1, + .dev = { + .platform_data = (void *)ad1836_link, + }, +}; +#endif + #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) static const unsigned ad73311_gpio[] = { @@ -2927,6 +2942,11 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_ac97_pcm, #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ + defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) + &bfin_ad1836_machine, +#endif + #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) &bfin_ad73311_machine, diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 7c36777c6455..551f866172cf 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c @@ -539,6 +539,21 @@ static struct platform_device bfin_ac97 = { }; #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ + || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) +static const char * const ad1836_link[] = { + "bfin-tdm.0", + "spi0.4", +}; +static struct platform_device bfin_ad1836_machine = { + .name = "bfin-snd-ad1836", + .id = -1, + .dev = { + .platform_data = (void *)ad1836_link, + }, +}; +#endif + static struct platform_device *ezkit_devices[] __initdata = { &bfin_dpmc, @@ -603,6 +618,11 @@ static struct platform_device *ezkit_devices[] __initdata = { #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) &bfin_ac97, #endif + +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ + defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) + &bfin_ad1836_machine, +#endif }; static int __init net2272_init(void) diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c index c2cf1ae31189..61c1f47a4bf2 100644 --- a/arch/blackfin/mach-bf609/boards/ezkit.c +++ b/arch/blackfin/mach-bf609/boards/ezkit.c @@ -818,6 +818,21 @@ static struct platform_device bfin_i2s = { }; #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ + || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) +static const char * const ad1836_link[] = { + "bfin-tdm.0", + "spi0.76", +}; +static struct platform_device bfin_ad1836_machine = { + .name = "bfin-snd-ad1836", + .id = -1, + .dev = { + .platform_data = (void *)ad1836_link, + }, +}; +#endif + #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE) static struct platform_device adau1761_device = { @@ -1557,6 +1572,10 @@ static struct platform_device *ezkit_devices[] __initdata = { defined(CONFIG_SND_BF6XX_SOC_I2S_MODULE) &bfin_i2s, #endif +#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ + defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) + &bfin_ad1836_machine, +#endif #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE) &adau1761_device, From b7ca69289680cf631fb20b7d436467c4ec1153cd Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 3 Aug 2012 08:43:01 -0500 Subject: [PATCH 074/665] CIFS: Protect i_nlink from being negative that can cause warning messages. Pavel had initially suggested a smaller patch around drop_nlink, after a similar problem was discovered NFS. Protecting additional places where nlink is touched was suggested by Jeff Layton and is included in this. Reviewed-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Steve French --- fs/cifs/inode.c | 24 ++++++++++++++++-------- fs/cifs/link.c | 2 ++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 7354877fa3bd..cb79c7edecb0 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -124,10 +124,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) { struct cifsInodeInfo *cifs_i = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - unsigned long oldtime = cifs_i->time; cifs_revalidate_cache(inode, fattr); + spin_lock(&inode->i_lock); inode->i_atime = fattr->cf_atime; inode->i_mtime = fattr->cf_mtime; inode->i_ctime = fattr->cf_ctime; @@ -148,9 +148,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) else cifs_i->time = jiffies; - cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode, - oldtime, cifs_i->time); - cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; cifs_i->server_eof = fattr->cf_eof; @@ -158,7 +155,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) * Can't safely change the file size here if the client is writing to * it due to potential races. */ - spin_lock(&inode->i_lock); if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { i_size_write(inode, fattr->cf_eof); @@ -859,12 +855,14 @@ struct inode *cifs_root_iget(struct super_block *sb) if (rc && tcon->ipc) { cFYI(1, "ipc connection - fake read inode"); + spin_lock(&inode->i_lock); inode->i_mode |= S_IFDIR; set_nlink(inode, 2); inode->i_op = &cifs_ipc_inode_ops; inode->i_fop = &simple_dir_operations; inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; + spin_unlock(&inode->i_lock); } else if (rc) { iget_failed(inode); inode = ERR_PTR(rc); @@ -1110,6 +1108,15 @@ undo_setattr: goto out_close; } +/* copied from fs/nfs/dir.c with small changes */ +static void +cifs_drop_nlink(struct inode *inode) +{ + spin_lock(&inode->i_lock); + if (inode->i_nlink > 0) + drop_nlink(inode); + spin_unlock(&inode->i_lock); +} /* * If dentry->d_inode is null (usually meaning the cached dentry @@ -1166,13 +1173,13 @@ retry_std_delete: psx_del_no_retry: if (!rc) { if (inode) - drop_nlink(inode); + cifs_drop_nlink(inode); } else if (rc == -ENOENT) { d_drop(dentry); } else if (rc == -ETXTBSY) { rc = cifs_rename_pending_delete(full_path, dentry, xid); if (rc == 0) - drop_nlink(inode); + cifs_drop_nlink(inode); } else if ((rc == -EACCES) && (dosattr == 0) && inode) { attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) { @@ -1241,9 +1248,10 @@ cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode, * setting nlink not necessary except in cases where we failed to get it * from the server or was set bogus */ + spin_lock(&dentry->d_inode->i_lock); if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2)) set_nlink(dentry->d_inode, 2); - + spin_unlock(&dentry->d_inode->i_lock); mode &= ~current_umask(); /* must turn on setgid bit if parent dir has it */ if (inode->i_mode & S_ISGID) diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 09e4b3ae4564..e6ce3b112875 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -433,7 +433,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, if (old_file->d_inode) { cifsInode = CIFS_I(old_file->d_inode); if (rc == 0) { + spin_lock(&old_file->d_inode->i_lock); inc_nlink(old_file->d_inode); + spin_unlock(&old_file->d_inode->i_lock); /* BB should we make this contingent on superblock flag NOATIME? */ /* old_file->d_inode->i_ctime = CURRENT_TIME;*/ /* parent dir timestamps will update from srv From 7411286088d5ba879e9ffcaaa296f657642ef2c4 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Fri, 27 Jul 2012 01:20:41 +0400 Subject: [PATCH 075/665] CIFS: Fix log messages in packet checking for SMB2 Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/smb2misc.c | 16 +++++++++------- fs/cifs/smb2pdu.h | 10 ++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index a4ff5d547554..e4d3b9964167 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -52,7 +52,8 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) cERROR(1, "Bad protocol string signature header %x", *(unsigned int *) hdr->ProtocolId); if (mid != hdr->MessageId) - cERROR(1, "Mids do not match"); + cERROR(1, "Mids do not match: %llu and %llu", mid, + hdr->MessageId); } cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId); return 1; @@ -107,7 +108,7 @@ smb2_check_message(char *buf, unsigned int length) * ie Validate the wct via smb2_struct_sizes table above */ - if (length < 2 + sizeof(struct smb2_hdr)) { + if (length < sizeof(struct smb2_pdu)) { if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { pdu->StructureSize2 = 0; /* @@ -121,15 +122,15 @@ smb2_check_message(char *buf, unsigned int length) return 1; } if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) { - cERROR(1, "SMB length greater than maximum, mid=%lld", mid); + cERROR(1, "SMB length greater than maximum, mid=%llu", mid); return 1; } if (check_smb2_hdr(hdr, mid)) return 1; - if (hdr->StructureSize != SMB2_HEADER_SIZE) { - cERROR(1, "Illegal structure size %d", + if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { + cERROR(1, "Illegal structure size %u", le16_to_cpu(hdr->StructureSize)); return 1; } @@ -161,8 +162,9 @@ smb2_check_message(char *buf, unsigned int length) if (4 + len != clc_len) { cFYI(1, "Calculated size %u length %u mismatch mid %llu", clc_len, 4 + len, mid); - if (clc_len == 4 + len + 1) /* BB FIXME (fix samba) */ - return 0; /* BB workaround Samba 3 bug SessSetup rsp */ + /* server can return one byte more */ + if (clc_len == 4 + len + 1) + return 0; return 1; } return 0; diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index f37a1b41b402..c5fbfac5d576 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -87,10 +87,6 @@ #define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe) -#define SMB2_HEADER_SIZE __constant_le16_to_cpu(64) - -#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9) - /* * SMB2 Header Definition * @@ -99,6 +95,9 @@ * "PDU" : "Protocol Data Unit" (ie a network "frame") * */ + +#define SMB2_HEADER_STRUCTURE_SIZE __constant_le16_to_cpu(64) + struct smb2_hdr { __be32 smb2_buf_length; /* big endian on wire */ /* length is only two or three bytes - with @@ -140,6 +139,9 @@ struct smb2_pdu { * command code name for the struct. Note that structures must be packed. * */ + +#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9) + struct smb2_err_rsp { struct smb2_hdr hdr; __le16 StructureSize; From 985e4ff016b5f3d95c12fe8073d1df89300dab3d Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 3 Aug 2012 09:42:45 -0500 Subject: [PATCH 076/665] cifs: print error code if smb signature verification fails While trying to debug a SMB signature related issue with Windows Servers figured out it might be easier to debug if we print the error code from cifs_verify_signature(). Also, fix indendation while at it. Signed-off-by: Suresh Jayaraman Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 11 ++++++++--- fs/cifs/transport.c | 9 ++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 074923ce593d..f0cf934ba877 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1576,9 +1576,14 @@ cifs_readv_callback(struct mid_q_entry *mid) /* result already set, check signature */ if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - if (cifs_verify_signature(rdata->iov, rdata->nr_iov, - server, mid->sequence_number + 1)) - cERROR(1, "Unexpected SMB signature"); + int rc = 0; + + rc = cifs_verify_signature(rdata->iov, rdata->nr_iov, + server, + mid->sequence_number + 1); + if (rc) + cERROR(1, "SMB signature verification returned " + "error = %d", rc); } /* FIXME: should this be counted toward the initiating task? */ task_io_account_read(rdata->bytes); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 83867ef348df..d9b639b95fa8 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -503,13 +503,16 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, /* convert the length into a more usable form */ if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { struct kvec iov; + int rc = 0; iov.iov_base = mid->resp_buf; iov.iov_len = len; /* FIXME: add code to kill session */ - if (cifs_verify_signature(&iov, 1, server, - mid->sequence_number + 1) != 0) - cERROR(1, "Unexpected SMB signature"); + rc = cifs_verify_signature(&iov, 1, server, + mid->sequence_number + 1); + if (rc) + cERROR(1, "SMB signature verification returned error = " + "%d", rc); } /* BB special case reconnect tid and uid here? */ From ea7b4887e7266b93fa0c203cc452a926a0fef4f0 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Fri, 17 Aug 2012 18:02:19 +0400 Subject: [PATCH 077/665] CIFS: Fix cifs_do_create error hadnling Commit d2c127197dfc0b2bae62a52e1e0d3e3ff493919e caused a regression in cifs_do_create error handling. Fix this by closing a file handle in the case of a get_inode_info(_unix) error. Also remove unnecessary checks for newinode being NULL. Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/dir.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index cbe709ad6663..781025be48bc 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -356,19 +356,12 @@ cifs_create_get_file_info: cifs_create_set_dentry: if (rc != 0) { cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); + CIFSSMBClose(xid, tcon, *fileHandle); goto out; } d_drop(direntry); d_add(direntry, newinode); - /* ENOENT for create? How weird... */ - rc = -ENOENT; - if (!newinode) { - CIFSSMBClose(xid, tcon, *fileHandle); - goto out; - } - rc = 0; - out: kfree(buf); kfree(full_path); From 2dba62c30ec3040ef1b647a8976fd7e6854cc7a7 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 19 Aug 2012 10:16:08 +0000 Subject: [PATCH 078/665] netfilter: nfnetlink_log: fix NLA_PUT macro removal bug Commit 1db20a52 (nfnetlink_log: Stop using NLA_PUT*().) incorrectly converted a NLA_PUT_BE16 macro to nla_put_be32() in nfnetlink_log: - NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)); + if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 169ab59ed9d4..592091c1260b 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -480,7 +480,7 @@ __build_packet_message(struct nfulnl_instance *inst, } if (indev && skb_mac_header_was_set(skb)) { - if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || + if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || nla_put_be16(inst->skb, NFULA_HWLEN, htons(skb->dev->hard_header_len)) || nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, From db8b624d55e65ad5d8211a9fef66fa7f16bd13a0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:52 +0200 Subject: [PATCH 079/665] ASoC: imx-sgtl5000: fix error return code Initialize ret on the second call to imx_audmux_v2_configure_port so that the subsequent test checks that result and not the previous one. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Mark Brown --- sound/soc/fsl/imx-sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index fb21b17f17f5..199408ec4261 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -94,7 +94,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) dev_err(&pdev->dev, "audmux internal port setup failed\n"); return ret; } - imx_audmux_v2_configure_port(ext_port, + ret = imx_audmux_v2_configure_port(ext_port, IMX_AUDMUX_V2_PTCR_SYN, IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); if (ret) { From b18e93a493626c1446f9788ebd5844d008bbf71c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:02:53 +0200 Subject: [PATCH 080/665] ASoC: ux500_msp_i2s: better use devm functions and fix error return code Remove unnecessary calls to devm_kfree and replace iounmap by devm_iounmap (and use resource_size for the third argument). These changes make it possible to remove the error-handling code at the end of ux500_msp_i2s_init_msp, and all of the gotos become direct returns. In the case of the second call to devm_kzalloc, the return variable ret was not initialized. Here it is changed to a direct return of -ENOMEM. A simplified version of the semantic match that finds the second problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_i2s.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 5c472f335a64..eb85113d472a 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -663,7 +663,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, struct ux500_msp **msp_p, struct msp_i2s_platform_data *platform_data) { - int ret = 0; struct resource *res = NULL; struct i2s_controller *i2s_cont; struct ux500_msp *msp; @@ -685,15 +684,14 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, if (res == NULL) { dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n", __func__); - ret = -ENOMEM; - goto err_res; + return -ENOMEM; } - msp->registers = ioremap(res->start, (res->end - res->start + 1)); + msp->registers = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); if (msp->registers == NULL) { dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__); - ret = -ENOMEM; - goto err_res; + return -ENOMEM; } msp->msp_state = MSP_STATE_IDLE; @@ -705,7 +703,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, dev_err(&pdev->dev, "%s: ERROR: Failed to allocate I2S-controller!\n", __func__); - goto err_i2s_cont; + return -ENOMEM; } i2s_cont->dev.parent = &pdev->dev; i2s_cont->data = (void *)msp; @@ -716,14 +714,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, msp->i2s_cont = i2s_cont; return 0; - -err_i2s_cont: - iounmap(msp->registers); - -err_res: - devm_kfree(&pdev->dev, msp); - - return ret; } void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, @@ -732,11 +722,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id); device_unregister(&msp->i2s_cont->dev); - devm_kfree(&pdev->dev, msp->i2s_cont); - - iounmap(msp->registers); - - devm_kfree(&pdev->dev, msp); } MODULE_LICENSE("GPL v2"); From bc72d26bdb23c908ad52ec2d321a137d27762f08 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 09:03:00 +0200 Subject: [PATCH 081/665] ASoC: am3517evm: fix error return code It was forgotten to initialize ret to the result of calling snd_soc_dai_set_sysclk, unlike at the other calls in the same function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/am3517evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 009533ab8d18..df65f98211ec 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -59,7 +59,7 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, return ret; } - snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, + ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); From 4968107786e75f5aaba3c1c8e959ccbae929457f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 16 Aug 2012 17:10:40 +0530 Subject: [PATCH 082/665] ASoC: add definations for compressed operations Here we update the asoc structures to add compress stream definations First the struct snd_soc_dai_driver adds a new member to indicate if the dai is compressed or pcm. Next we add a new structre the struct snd_soc_compr_ops in the struct snd_soc_dai_link. This is to be used for machine driver to perform any opertaions required for setting up compressed audio streams next is the compressed data operations, they are added using struct snd_compr_ops in the struct snd_soc_platform_driver. Signed-off-by: Namarta Kohli Signed-off-by: Ramesh Babu K V Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- include/sound/compress_driver.h | 1 + include/sound/soc-dai.h | 3 +++ include/sound/soc.h | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 48f2a1ff2bbc..f2912abacdf3 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -61,6 +61,7 @@ struct snd_compr_runtime { u64 total_bytes_available; u64 total_bytes_transferred; wait_queue_head_t sleep; + void *private_data; }; /** diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1f69e0af2941..628db7bca4fd 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -18,6 +18,7 @@ struct snd_pcm_substream; struct snd_soc_dapm_widget; +struct snd_compr_stream; /* * DAI hardware audio formats. @@ -205,6 +206,8 @@ struct snd_soc_dai_driver { int (*remove)(struct snd_soc_dai *dai); int (*suspend)(struct snd_soc_dai *dai); int (*resume)(struct snd_soc_dai *dai); + /* compress dai */ + bool compress_dai; /* ops */ const struct snd_soc_dai_ops *ops; diff --git a/include/sound/soc.h b/include/sound/soc.h index e063380f63a2..313b7660562c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -399,6 +400,7 @@ int snd_soc_platform_read(struct snd_soc_platform *platform, int snd_soc_platform_write(struct snd_soc_platform *platform, unsigned int reg, unsigned int val); int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); +int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num); struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, const char *dai_link, int stream); @@ -632,6 +634,13 @@ struct snd_soc_ops { int (*trigger)(struct snd_pcm_substream *, int); }; +struct snd_soc_compr_ops { + int (*startup)(struct snd_compr_stream *); + void (*shutdown)(struct snd_compr_stream *); + int (*set_params)(struct snd_compr_stream *); + int (*trigger)(struct snd_compr_stream *); +}; + /* SoC cache ops */ struct snd_soc_cache_ops { const char *name; @@ -787,9 +796,12 @@ struct snd_soc_platform_driver { snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, struct snd_soc_dai *); - /* platform stream ops */ + /* platform stream pcm ops */ struct snd_pcm_ops *ops; + /* platform stream compress ops */ + struct snd_compr_ops *compr_ops; + /* platform stream completion event */ int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); @@ -891,6 +903,7 @@ struct snd_soc_dai_link { /* machine stream operations */ struct snd_soc_ops *ops; + struct snd_soc_compr_ops *compr_ops; }; struct snd_soc_codec_conf { @@ -1027,6 +1040,7 @@ struct snd_soc_pcm_runtime { /* runtime devices */ struct snd_pcm *pcm; + struct snd_compr *compr; struct snd_soc_codec *codec; struct snd_soc_platform *platform; struct snd_soc_dai *codec_dai; From 1245b7005de02d5bfa0c321df925f5b6c83c99e1 Mon Sep 17 00:00:00 2001 From: Namarta Kohli Date: Thu, 16 Aug 2012 17:10:41 +0530 Subject: [PATCH 083/665] ASoC: add compress stream support This patch adds the support to parse the compress dai's and then also adds the soc-compress.c file while handles the compress stream operations, mostly analogus to what is done in the soc-pcm.c and aditional handling of the compress opertaions Signed-off-by: Namarta Kohli Signed-off-by: Ramesh Babu K V Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 2 +- sound/soc/soc-compress.c | 295 +++++++++++++++++++++++++++++++++++++++ sound/soc/soc-core.c | 59 ++++---- 4 files changed, 332 insertions(+), 25 deletions(-) create mode 100644 sound/soc/soc-compress.c diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index c5de0a84566f..c24de902f5f5 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -9,6 +9,7 @@ menuconfig SND_SOC select SND_JACK if INPUT=y || INPUT=SND select REGMAP_I2C if I2C select REGMAP_SPI if SPI_MASTER + select SND_COMPRESS_OFFLOAD ---help--- If you want ASoC support, you should say Y here and also to the diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 00a555a743b6..c1264007b4ee 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,5 +1,5 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o -snd-soc-core-objs += soc-pcm.o soc-io.o +snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c new file mode 100644 index 000000000000..88d85badd932 --- /dev/null +++ b/sound/soc/soc-compress.c @@ -0,0 +1,295 @@ +/* + * soc-compress.c -- ALSA SoC Compress + * + * Copyright (C) 2012 Intel Corp. + * + * Authors: Namarta Kohli + * Ramesh Babu K V + * Vinod Koul + * + * 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 + +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; + + if (platform->driver->compr_ops && platform->driver->compr_ops->open) { + ret = platform->driver->compr_ops->open(cstream); + if (ret < 0) { + pr_err("compress asoc: can't open platform %s\n", platform->name); + goto out; + } + } + + if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { + ret = rtd->dai_link->compr_ops->startup(cstream); + if (ret < 0) { + pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name); + goto machine_err; + } + } + + 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++; + + return 0; + +machine_err: + if (platform->driver->compr_ops && platform->driver->compr_ops->free) + platform->driver->compr_ops->free(cstream); +out: + return ret; +} + +static int soc_compr_free(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; + struct snd_soc_codec *codec = rtd->codec; + + if (cstream->direction == SND_COMPRESS_PLAYBACK) { + cpu_dai->playback_active--; + codec_dai->playback_active--; + } else { + cpu_dai->capture_active--; + codec_dai->capture_active--; + } + + snd_soc_dai_digital_mute(codec_dai, 1); + + cpu_dai->active--; + codec_dai->active--; + codec->active--; + + if (!cpu_dai->active) + cpu_dai->rate = 0; + + if (!codec_dai->active) + codec_dai->rate = 0; + + + if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) + rtd->dai_link->compr_ops->shutdown(cstream); + + if (platform->driver->compr_ops && platform->driver->compr_ops->free) + platform->driver->compr_ops->free(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) { + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_DAPM_STREAM_STOP); + } else + codec_dai->pop_wait = 1; + schedule_delayed_work(&rtd->delayed_work, + msecs_to_jiffies(rtd->pmdown_time)); + } else { + /* capture streams can be powered down now */ + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_CAPTURE, + SND_SOC_DAPM_STREAM_STOP); + } + + return 0; +} + +static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) +{ + + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { + ret = platform->driver->compr_ops->trigger(cstream, cmd); + if (ret < 0) + return ret; + } + + if (cmd == SNDRV_PCM_TRIGGER_START) + snd_soc_dai_digital_mute(codec_dai, 0); + else if (cmd == SNDRV_PCM_TRIGGER_STOP) + snd_soc_dai_digital_mute(codec_dai, 1); + + return ret; +} + +static int soc_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret = 0; + + /* first we call set_params for the platform driver + * this should configure the soc side + * if the machine has compressed ops then we call that as well + * expectation is that platform and machine will configure everything + * for this compress path, like configuring pcm port for codec + */ + if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { + ret = platform->driver->compr_ops->set_params(cstream, params); + if (ret < 0) + return ret; + } + + if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { + ret = rtd->dai_link->compr_ops->set_params(cstream); + if (ret < 0) + return ret; + } + + snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_DAPM_STREAM_START); + + return ret; +} + +static int soc_compr_get_params(struct snd_compr_stream *cstream, + struct snd_codec *params) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->get_params) + ret = platform->driver->compr_ops->get_params(cstream, params); + + return ret; +} + +static int soc_compr_get_caps(struct snd_compr_stream *cstream, + struct snd_compr_caps *caps) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps) + ret = platform->driver->compr_ops->get_caps(cstream, caps); + + return ret; +} + +static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, + struct snd_compr_codec_caps *codec) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) + ret = platform->driver->compr_ops->get_codec_caps(cstream, codec); + + return ret; +} + +static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->ack) + ret = platform->driver->compr_ops->ack(cstream, bytes); + + return ret; +} + +static int soc_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + + if (platform->driver->compr_ops && platform->driver->compr_ops->pointer) + platform->driver->compr_ops->pointer(cstream, tstamp); + + return 0; +} + +/* ASoC Compress operations */ +static struct snd_compr_ops soc_compr_ops = { + .open = soc_compr_open, + .free = soc_compr_free, + .set_params = soc_compr_set_params, + .get_params = soc_compr_get_params, + .trigger = soc_compr_trigger, + .pointer = soc_compr_pointer, + .ack = soc_compr_ack, + .get_caps = soc_compr_get_caps, + .get_codec_caps = soc_compr_get_codec_caps +}; + +/* create a new compress */ +int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_compr *compr; + char new_name[64]; + int ret = 0, direction = 0; + + /* check client and interface hw capabilities */ + snprintf(new_name, sizeof(new_name), "%s %s-%d", + rtd->dai_link->stream_name, codec_dai->name, num); + direction = SND_COMPRESS_PLAYBACK; + compr = kzalloc(sizeof(*compr), GFP_KERNEL); + if (compr == NULL) { + snd_printk(KERN_ERR "Cannot allocate compr\n"); + return -ENOMEM; + } + + compr->ops = &soc_compr_ops; + mutex_init(&compr->lock); + ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); + if (ret < 0) { + pr_err("compress asoc: can't create compress for codec %s\n", + codec->name); + kfree(compr); + return ret; + } + + rtd->compr = compr; + compr->private_data = rtd; + + printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, + cpu_dai->name); + return ret; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f585d0239551..c7a00fd8cc66 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1388,37 +1388,48 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) if (ret < 0) pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); - if (!dai_link->params) { - /* create the pcm */ - ret = soc_new_pcm(rtd, num); + if (cpu_dai->driver->compress_dai) { + /*create compress_device"*/ + ret = soc_new_compress(rtd, num); if (ret < 0) { - pr_err("asoc: can't create pcm %s :%d\n", - dai_link->stream_name, ret); + pr_err("asoc: can't create compress %s\n", + dai_link->stream_name); return ret; } } else { - /* link the DAI widgets */ - play_w = codec_dai->playback_widget; - capture_w = cpu_dai->capture_widget; - if (play_w && capture_w) { - ret = snd_soc_dapm_new_pcm(card, dai_link->params, - capture_w, play_w); - if (ret != 0) { - dev_err(card->dev, "Can't link %s to %s: %d\n", - play_w->name, capture_w->name, ret); + + if (!dai_link->params) { + /* create the pcm */ + ret = soc_new_pcm(rtd, num); + if (ret < 0) { + pr_err("asoc: can't create pcm %s :%d\n", + dai_link->stream_name, ret); return ret; } - } - - play_w = cpu_dai->playback_widget; - capture_w = codec_dai->capture_widget; - if (play_w && capture_w) { - ret = snd_soc_dapm_new_pcm(card, dai_link->params, + } else { + /* link the DAI widgets */ + play_w = codec_dai->playback_widget; + capture_w = cpu_dai->capture_widget; + if (play_w && capture_w) { + ret = snd_soc_dapm_new_pcm(card, dai_link->params, capture_w, play_w); - if (ret != 0) { - dev_err(card->dev, "Can't link %s to %s: %d\n", - play_w->name, capture_w->name, ret); - return ret; + if (ret != 0) { + dev_err(card->dev, "Can't link %s to %s: %d\n", + play_w->name, capture_w->name, ret); + return ret; + } + } + + play_w = cpu_dai->playback_widget; + capture_w = codec_dai->capture_widget; + if (play_w && capture_w) { + ret = snd_soc_dapm_new_pcm(card, dai_link->params, + capture_w, play_w); + if (ret != 0) { + dev_err(card->dev, "Can't link %s to %s: %d\n", + play_w->name, capture_w->name, ret); + return ret; + } } } } From c514a9119a982a6c7a9fd29ee62c0ba8a8e4c7d1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 16 Aug 2012 17:10:42 +0530 Subject: [PATCH 084/665] ASoC: mid-x86 - add support for compressed streams Signed-off-by: Namarta Kohli Signed-off-by: Ramesh Babu K V Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/mid-x86/mfld_machine.c | 9 ++ sound/soc/mid-x86/sst_dsp.h | 134 ++++++++++++++++++++ sound/soc/mid-x86/sst_platform.c | 204 ++++++++++++++++++++++++++++++- sound/soc/mid-x86/sst_platform.h | 26 +++- 4 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 sound/soc/mid-x86/sst_dsp.h diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 2937e54da49e..2cc7782714b5 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c @@ -318,6 +318,15 @@ static struct snd_soc_dai_link mfld_msic_dailink[] = { .platform_name = "sst-platform", .init = NULL, }, + { + .name = "Medfield Compress", + .stream_name = "Speaker", + .cpu_dai_name = "Compress-cpu-dai", + .codec_dai_name = "SN95031 Speaker", + .codec_name = "sn95031", + .platform_name = "sst-platform", + .init = NULL, + }, }; /* SoC card */ diff --git a/sound/soc/mid-x86/sst_dsp.h b/sound/soc/mid-x86/sst_dsp.h new file mode 100644 index 000000000000..0fce1de284ff --- /dev/null +++ b/sound/soc/mid-x86/sst_dsp.h @@ -0,0 +1,134 @@ +#ifndef __SST_DSP_H__ +#define __SST_DSP_H__ +/* + * sst_dsp.h - Intel SST Driver for audio engine + * + * Copyright (C) 2008-12 Intel Corporation + * Authors: Vinod Koul + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +enum sst_codec_types { + /* AUDIO/MUSIC CODEC Type Definitions */ + SST_CODEC_TYPE_UNKNOWN = 0, + SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ + SST_CODEC_TYPE_MP3, + SST_CODEC_TYPE_MP24, + SST_CODEC_TYPE_AAC, + SST_CODEC_TYPE_AACP, + SST_CODEC_TYPE_eAACP, +}; + +enum stream_type { + SST_STREAM_TYPE_NONE = 0, + SST_STREAM_TYPE_MUSIC = 1, +}; + +struct snd_pcm_params { + u16 codec; /* codec type */ + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u32 reserved; /* Bitrate in bits per second */ + u32 sfreq; /* Sampling rate in Hz */ + u8 use_offload_path; + u8 reserved2; + u16 reserved3; + u8 channel_map[8]; +} __packed; + +/* MP3 Music Parameters Message */ +struct snd_mp3_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u8 crc_check; /* crc_check - disable (0) or enable (1) */ + u8 reserved1; /* unused*/ + u16 reserved2; /* Unused */ +} __packed; + +#define AAC_BIT_STREAM_ADTS 0 +#define AAC_BIT_STREAM_ADIF 1 +#define AAC_BIT_STREAM_RAW 2 + +/* AAC Music Parameters Message */ +struct snd_aac_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo*/ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */ + u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ + u16 reser2; + u32 externalsr; /*sampling rate of basic AAC raw bit stream*/ + u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/ + u8 reser1; + u16 reser3; +} __packed; + +/* WMA Music Parameters Message */ +struct snd_wma_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u32 brate; /* Use the hard coded value. */ + u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ + u32 channel_mask; /* Channel Mask */ + u16 format_tag; /* Format Tag */ + u16 block_align; /* packet size */ + u16 wma_encode_opt;/* Encoder option */ + u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ + u8 reserved; /* reserved */ +} __packed; + +/* Codec params struture */ +union snd_sst_codec_params { + struct snd_pcm_params pcm_params; + struct snd_mp3_params mp3_params; + struct snd_aac_params aac_params; + struct snd_wma_params wma_params; +} __packed; + +/* Address and size info of a frame buffer */ +struct sst_address_info { + u32 addr; /* Address at IA */ + u32 size; /* Size of the buffer */ +}; + +struct snd_sst_alloc_params_ext { + struct sst_address_info ring_buf_info[8]; + u8 sg_count; + u8 reserved; + u16 reserved2; + u32 frag_size; /*Number of samples after which period elapsed + message is sent valid only if path = 0*/ +} __packed; + +struct snd_sst_stream_params { + union snd_sst_codec_params uc; +} __packed; + +struct snd_sst_params { + u32 stream_id; + u8 codec; + u8 ops; + u8 stream_type; + u8 device_type; + struct snd_sst_stream_params sparams; + struct snd_sst_alloc_params_ext aparams; +}; + +#endif /* __SST_DSP_H__ */ diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index d34563b12c3b..a263cbed8624 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c @@ -1,7 +1,7 @@ /* * sst_platform.c - Intel MID Platform driver * - * Copyright (C) 2010 Intel Corp + * Copyright (C) 2010-2012 Intel Corp * Author: Vinod Koul * Author: Harsha Priya * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -32,6 +32,7 @@ #include #include #include +#include #include "sst_platform.h" static struct sst_device *sst; @@ -152,6 +153,16 @@ static struct snd_soc_dai_driver sst_platform_dai[] = { .formats = SNDRV_PCM_FMTBIT_S24_LE, }, }, +{ + .name = "Compress-cpu-dai", + .compress_dai = 1, + .playback = { + .channels_min = SST_STEREO, + .channels_max = SST_STEREO, + .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, +}, }; /* helper functions */ @@ -463,8 +474,199 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) } return retval; } + +/* compress stream operations */ +static void sst_compr_fragment_elapsed(void *arg) +{ + struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg; + + pr_debug("fragment elapsed by driver\n"); + if (cstream) + snd_compr_fragment_elapsed(cstream); +} + +static int sst_platform_compr_open(struct snd_compr_stream *cstream) +{ + + int ret_val = 0; + struct snd_compr_runtime *runtime = cstream->runtime; + struct sst_runtime_stream *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + spin_lock_init(&stream->status_lock); + + /* get the sst ops */ + if (!sst || !try_module_get(sst->dev->driver->owner)) { + pr_err("no device available to run\n"); + ret_val = -ENODEV; + goto out_ops; + } + stream->compr_ops = sst->compr_ops; + + stream->id = 0; + sst_set_stream_status(stream, SST_PLATFORM_INIT); + runtime->private_data = stream; + return 0; +out_ops: + kfree(stream); + return ret_val; +} + +static int sst_platform_compr_free(struct snd_compr_stream *cstream) +{ + struct sst_runtime_stream *stream; + int ret_val = 0, str_id; + + stream = cstream->runtime->private_data; + /*need to check*/ + str_id = stream->id; + if (str_id) + ret_val = stream->compr_ops->close(str_id); + module_put(sst->dev->driver->owner); + kfree(stream); + pr_debug("%s: %d\n", __func__, ret_val); + return 0; +} + +static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params) +{ + struct sst_runtime_stream *stream; + int retval; + struct snd_sst_params str_params; + struct sst_compress_cb cb; + + stream = cstream->runtime->private_data; + /* construct fw structure for this*/ + memset(&str_params, 0, sizeof(str_params)); + + str_params.ops = STREAM_OPS_PLAYBACK; + str_params.stream_type = SST_STREAM_TYPE_MUSIC; + str_params.device_type = SND_SST_DEVICE_COMPRESS; + + switch (params->codec.id) { + case SND_AUDIOCODEC_MP3: { + str_params.codec = SST_CODEC_TYPE_MP3; + str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3; + str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in; + str_params.sparams.uc.mp3_params.pcm_wd_sz = 16; + break; + } + + case SND_AUDIOCODEC_AAC: { + str_params.codec = SST_CODEC_TYPE_AAC; + str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC; + str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in; + str_params.sparams.uc.aac_params.pcm_wd_sz = 16; + if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS) + str_params.sparams.uc.aac_params.bs_format = + AAC_BIT_STREAM_ADTS; + else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW) + str_params.sparams.uc.aac_params.bs_format = + AAC_BIT_STREAM_RAW; + else { + pr_err("Undefined format%d\n", params->codec.format); + return -EINVAL; + } + str_params.sparams.uc.aac_params.externalsr = + params->codec.sample_rate; + break; + } + + default: + pr_err("codec not supported, id =%d\n", params->codec.id); + return -EINVAL; + } + + str_params.aparams.ring_buf_info[0].addr = + virt_to_phys(cstream->runtime->buffer); + str_params.aparams.ring_buf_info[0].size = + cstream->runtime->buffer_size; + str_params.aparams.sg_count = 1; + str_params.aparams.frag_size = cstream->runtime->fragment_size; + + cb.param = cstream; + cb.compr_cb = sst_compr_fragment_elapsed; + + retval = stream->compr_ops->open(&str_params, &cb); + if (retval < 0) { + pr_err("stream allocation failed %d\n", retval); + return retval; + } + + stream->id = retval; + return 0; +} + +static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->control(cmd, stream->id); +} + +static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + struct sst_runtime_stream *stream; + + stream = cstream->runtime->private_data; + stream->compr_ops->tstamp(stream->id, tstamp); + tstamp->byte_offset = tstamp->copied_total % + (u32)cstream->runtime->buffer_size; + pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); + return 0; +} + +static int sst_platform_compr_ack(struct snd_compr_stream *cstream, + size_t bytes) +{ + struct sst_runtime_stream *stream; + + stream = cstream->runtime->private_data; + stream->compr_ops->ack(stream->id, (unsigned long)bytes); + stream->bytes_written += bytes; + + return 0; +} + +static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, + struct snd_compr_caps *caps) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->get_caps(caps); +} + +static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, + struct snd_compr_codec_caps *codec) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->get_codec_caps(codec); +} + +static struct snd_compr_ops sst_platform_compr_ops = { + + .open = sst_platform_compr_open, + .free = sst_platform_compr_free, + .set_params = sst_platform_compr_set_params, + .trigger = sst_platform_compr_trigger, + .pointer = sst_platform_compr_pointer, + .ack = sst_platform_compr_ack, + .get_caps = sst_platform_compr_get_caps, + .get_codec_caps = sst_platform_compr_get_codec_caps, +}; + static struct snd_soc_platform_driver sst_soc_platform_drv = { .ops = &sst_platform_ops, + .compr_ops = &sst_platform_compr_ops, .pcm_new = sst_pcm_new, .pcm_free = sst_pcm_free, }; diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h index f04f4f72daa0..d61c5d514ffa 100644 --- a/sound/soc/mid-x86/sst_platform.h +++ b/sound/soc/mid-x86/sst_platform.h @@ -27,6 +27,8 @@ #ifndef __SST_PLATFORMDRV_H__ #define __SST_PLATFORMDRV_H__ +#include "sst_dsp.h" + #define SST_MONO 1 #define SST_STEREO 2 #define SST_MAX_CAP 5 @@ -42,7 +44,6 @@ #define SST_MIN_PERIODS 2 #define SST_MAX_PERIODS (1024*2) #define SST_FIFO_SIZE 0 -#define SST_CODEC_TYPE_PCM 1 struct pcm_stream_info { int str_id; @@ -83,6 +84,7 @@ enum sst_audio_device_type { SND_SST_DEVICE_VIBRA, SND_SST_DEVICE_HAPTIC, SND_SST_DEVICE_CAPTURE, + SND_SST_DEVICE_COMPRESS, }; /* PCM Parameters */ @@ -107,6 +109,24 @@ struct sst_stream_params { struct sst_pcm_params sparams; }; +struct sst_compress_cb { + void *param; + void (*compr_cb)(void *param); +}; + +struct compress_sst_ops { + const char *name; + int (*open) (struct snd_sst_params *str_params, + struct sst_compress_cb *cb); + int (*control) (unsigned int cmd, unsigned int str_id); + int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); + int (*ack) (unsigned int str_id, unsigned long bytes); + int (*close) (unsigned int str_id); + int (*get_caps) (struct snd_compr_caps *caps); + int (*get_codec_caps) (struct snd_compr_codec_caps *codec); + +}; + struct sst_ops { int (*open) (struct sst_stream_params *str_param); int (*device_control) (int cmd, void *arg); @@ -115,8 +135,11 @@ struct sst_ops { struct sst_runtime_stream { int stream_status; + unsigned int id; + size_t bytes_written; struct pcm_stream_info stream_info; struct sst_ops *ops; + struct compress_sst_ops *compr_ops; spinlock_t status_lock; }; @@ -124,6 +147,7 @@ struct sst_device { char *name; struct device *dev; struct sst_ops *ops; + struct compress_sst_ops *compr_ops; }; int sst_register_dsp(struct sst_device *sst); From cbe05685c1859e655c663b6ff2d0f71093ee834d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 12 Aug 2012 12:01:34 +0200 Subject: [PATCH 085/665] s390: Always use "long" for ssize_t to match size_t On s390x-linux-gcc, __SIZE_TYPE__ expands to "long unsigned int" for both 32-bit s390 and 64-bit s390x, as gcc-4.6.3-nolibc/s390x-linux/lib/gcc/s390x-linux/4.6.3/plugin/include/config/s390/linux.h has #define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "long unsigned int") To match this, __kernel_size_t is always set to "long unsigned int". But while __kernel_ssize_t is "long" on 64-bit s390x, it is "int" on 32-bit s390, causing compiler warnings like: fs/quota/quota_tree.c:372:4: warning: format '%zd' expects argument of type 'signed size_t', but argument 4 has type 'ssize_t' [-Wformat] To fix this, __kernel_ssize_t should be "long", irrespective of word size. Signed-off-by: Geert Uytterhoeven Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/posix_types.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/s390/include/asm/posix_types.h b/arch/s390/include/asm/posix_types.h index 7bcc14e395f0..bf2a2ad2f800 100644 --- a/arch/s390/include/asm/posix_types.h +++ b/arch/s390/include/asm/posix_types.h @@ -13,6 +13,7 @@ */ typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; #define __kernel_size_t __kernel_size_t typedef unsigned short __kernel_old_dev_t; @@ -25,7 +26,6 @@ typedef unsigned short __kernel_mode_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; typedef unsigned short __kernel_gid_t; -typedef int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; #else /* __s390x__ */ @@ -35,7 +35,6 @@ typedef unsigned int __kernel_mode_t; typedef int __kernel_ipc_pid_t; typedef unsigned int __kernel_uid_t; typedef unsigned int __kernel_gid_t; -typedef long __kernel_ssize_t; typedef long __kernel_ptrdiff_t; typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ From 9d2667a910b8d889a8307bd2534032eb6ed0ea36 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 21 Aug 2012 12:15:02 +0530 Subject: [PATCH 086/665] ASoC: compress - fix code alignment Reported-by: Fengguang Wu Signed-off-by: Namarta Kohli Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 88d85badd932..cc0562d28df2 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -104,7 +104,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) if (platform->driver->compr_ops && platform->driver->compr_ops->free) platform->driver->compr_ops->free(cstream); - cpu_dai->runtime = NULL; + cpu_dai->runtime = NULL; if (cstream->direction == SND_COMPRESS_PLAYBACK) { if (!rtd->pmdown_time || codec->ignore_pmdown_time || From 1be437fa53609da9a796a4d213d3fc0a17fc03e0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 21 Aug 2012 12:20:22 +0530 Subject: [PATCH 087/665] ASoC: soc-compress: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit codec_dai is not used in the function. sound/soc/soc-compress.c: In function ‘soc_compr_set_params’: sound/soc/soc-compress.c:156:22: warning: unused variable ‘codec_dai’ [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index cc0562d28df2..967d0e173e1b 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -153,7 +153,6 @@ static int soc_compr_set_params(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 *codec_dai = rtd->codec_dai; int ret = 0; /* first we call set_params for the platform driver From 92c385f46b30f4954e9dd2d2005c12d233b479ea Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 6 Aug 2012 15:36:49 -0300 Subject: [PATCH 088/665] Bluetooth: Use USB_VENDOR_AND_INTERFACE() for Broadcom devices Many Broadcom devices has a vendor specific devices class, with this rule we match all existent and future controllers with this behavior. We also remove old rules to that matches product id for Broadcom devices. Tested-by: John Hommel Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btusb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2fe7776dc49c..e791b20beaf5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -94,16 +94,14 @@ static struct usb_device_id btusb_table[] = { /* Broadcom BCM20702A0 */ { USB_DEVICE(0x0489, 0xe042) }, - { USB_DEVICE(0x0a5c, 0x21e3) }, - { USB_DEVICE(0x0a5c, 0x21e6) }, - { USB_DEVICE(0x0a5c, 0x21e8) }, - { USB_DEVICE(0x0a5c, 0x21f3) }, - { USB_DEVICE(0x0a5c, 0x21f4) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ { USB_DEVICE(0x0489, 0xe033) }, + /*Broadcom devices with vendor specific id */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, + { } /* Terminating entry */ }; From 3a245cbef6a9e4398456bd733b0b4b7cb3f11994 Mon Sep 17 00:00:00 2001 From: Thomas Huehn Date: Wed, 15 Aug 2012 22:48:35 +0200 Subject: [PATCH 089/665] ath5k: fix wrong max power per rate eeprom reads for 802.11a This patch reduces the per rate target power eeprom reads for AR5K_EEPROM_MODE_11A from 10 to 8, as there are only 8 valid power curve entries on the eeprom. The former 10 reads lead to equal max power limits per rate and this causes an increasing distortion for all rates above 24 MBit and leads to a needless poor performance in 802.11a mode. Signed-off-by: Thomas Huehn Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 2 +- drivers/net/wireless/ath/ath5k/eeprom.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 4026c906cc7b..b7e0258887e7 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1482,7 +1482,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) case AR5K_EEPROM_MODE_11A: offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); rate_pcal_info = ee->ee_rate_tpwr_a; - ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; + ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_RATE_CHAN; break; case AR5K_EEPROM_MODE_11B: offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index dc2bcfeadeb4..94a9bbea6874 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -182,6 +182,7 @@ #define AR5K_EEPROM_EEP_DELTA 10 #define AR5K_EEPROM_N_MODES 3 #define AR5K_EEPROM_N_5GHZ_CHAN 10 +#define AR5K_EEPROM_N_5GHZ_RATE_CHAN 8 #define AR5K_EEPROM_N_2GHZ_CHAN 3 #define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 #define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4 From 7b4e6cfbae304177b8edc0c12341b4896cab3f2d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 11:49:58 +0200 Subject: [PATCH 090/665] drivers/net/wireless/ipw2x00/ipw2100.c: introduce missing initialization The result of one call to a function is tested, and then at the second call to the same function, the previous result, and not the current result, is tested again. Also changed &bssid to bssid, at the suggestion of Stanislav Yakovlev. The semantic match that finds the first problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression ret; identifier f; statement S1,S2; @@ *ret = f(...); if (\(ret != 0\|ret < 0\|ret == NULL\)) S1 ... when any *f(...); if (\(ret != 0\|ret < 0\|ret == NULL\)) S2 // Signed-off-by: Julia Lawall Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 95aa8e1683ec..83324b321652 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2042,7 +2042,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) return; } len = ETH_ALEN; - ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len); + ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, bssid, + &len); if (ret) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", __LINE__); From 94543a8d4fb302817014981489f15cb3b92ec3c2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Aug 2012 18:57:10 +0200 Subject: [PATCH 091/665] iwlwifi: fix flow handler debug code iwl_dbgfs_fh_reg_read() can cause crashes and/or BUG_ON in slub because the ifdefs are wrong, the code in iwl_dump_fh() should use DEBUGFS, not DEBUG to protect the buffer writing code. Also, while at it, clean up the arguments to the function, some code and make it generally safer. Cc: stable@vger.kernel.org Reported-by: Benjamin Herrenschmidt Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/pcie/internal.h | 2 +- drivers/net/wireless/iwlwifi/pcie/rx.c | 2 +- drivers/net/wireless/iwlwifi/pcie/trans.c | 30 +++++++++++--------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index d9694c58208c..4ffc18dc3a57 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -350,7 +350,7 @@ int iwl_queue_space(const struct iwl_queue *q); /***************************************************** * Error handling ******************************************************/ -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); +int iwl_dump_fh(struct iwl_trans *trans, char **buf); void iwl_dump_csr(struct iwl_trans *trans); /***************************************************** diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 39a6ca1f009c..d1a61ba6247a 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -555,7 +555,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) } iwl_dump_csr(trans); - iwl_dump_fh(trans, NULL, false); + iwl_dump_fh(trans, NULL); iwl_op_mode_nic_error(trans->op_mode); } diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 939c2f78df58..1e86ea2266d4 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1649,13 +1649,9 @@ static const char *get_fh_string(int cmd) #undef IWL_CMD } -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) +int iwl_dump_fh(struct iwl_trans *trans, char **buf) { int i; -#ifdef CONFIG_IWLWIFI_DEBUG - int pos = 0; - size_t bufsz = 0; -#endif static const u32 fh_tbl[] = { FH_RSCSR_CHNL0_STTS_WPTR_REG, FH_RSCSR_CHNL0_RBDCB_BASE_REG, @@ -1667,29 +1663,35 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_ERROR_REG }; -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (buf) { + int pos = 0; + size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); if (!*buf) return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) pos += scnprintf(*buf + pos, bufsz - pos, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), iwl_read_direct32(trans, fh_tbl[i])); - } + return pos; } #endif + IWL_ERR(trans, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) IWL_ERR(trans, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), iwl_read_direct32(trans, fh_tbl[i])); - } + return 0; } @@ -1982,11 +1984,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_trans *trans = file->private_data; - char *buf; + char *buf = NULL; int pos = 0; ssize_t ret = -EFAULT; - ret = pos = iwl_dump_fh(trans, &buf, true); + ret = pos = iwl_dump_fh(trans, &buf); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); From 4fc79db178f0a0ede479b4713e00df2d106028b3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Aug 2012 18:57:11 +0200 Subject: [PATCH 092/665] iwlwifi: protect SRAM debugfs If the device is not started, we can't read its SRAM and attempting to do so will cause issues. Protect the debugfs read. Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/dvm/debugfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 46782f1102ac..a47b306b522c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c @@ -124,6 +124,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, const struct fw_img *img; size_t bufsz; + if (!iwl_is_ready_rf(priv)) + return -EAGAIN; + /* default is to dump the entire data segment */ if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { priv->dbgfs_sram_offset = 0x800000; From 4f9c1397e2e80e52b17ec4e39760caa807bd15c7 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 8 Aug 2012 09:07:38 +0800 Subject: [PATCH 093/665] PCI/PM: Enable D3/D3cold by default for most devices This patch fixes the following bug: http://marc.info/?l=linux-usb&m=134318961120825&w=2 Originally, device lower power states include D1, D2, D3. After that, D3 is further divided into D3hot and D3cold. To support both scenario safely, original D3 is mapped to D3cold. When adding D3cold support, because worry about some device may have broken D3cold support, D3cold is disabled by default. This disable D3 on original platform too. But some original platform may only have working D3, but no working D1, D2. The root cause of the above bug is it too. To deal with this, this patch enables D3/D3cold by default for most devices. This restores the original behavior. For some devices that suspected to have broken D3cold support, such as PCIe port, D3cold is disabled by default. Reported-by: Bjorn Mork Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- drivers/pci/pci.c | 1 + drivers/pci/pcie/portdrv_pci.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f3ea977a5b1b..ab4bf5a4c2f1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1941,6 +1941,7 @@ void pci_pm_init(struct pci_dev *dev) dev->pm_cap = pm; dev->d3_delay = PCI_PM_D3_WAIT; dev->d3cold_delay = PCI_PM_D3COLD_WAIT; + dev->d3cold_allowed = true; dev->d1_support = false; dev->d2_support = false; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3a7eefcb270a..62f5a76c8f80 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -200,6 +200,11 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, return status; pci_save_state(dev); + /* + * D3cold may not work properly on some PCIe port, so disable + * it by default. + */ + dev->d3cold_allowed = false; if (!pci_match_id(port_runtime_pm_black_list, dev)) pm_runtime_put_noidle(&dev->dev); From ea8c88f13d9fb1d6b39a05bfa07ae076ca1c6803 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 8 Aug 2012 09:07:39 +0800 Subject: [PATCH 094/665] PCI/PM: Keep parent bridge active when probing device This patch fixes the following bug: http://marc.info/?l=linux-pci&m=134329923124234&w=2 The root cause of the bug is as follow. If a device is not bound with the corresponding driver, the device runtime PM will be disabled and the device will be put into suspended state. So that, the bridge/PCIe port connected to it may be put into suspended and low power state. When do probing for the device later, because the bridge/PCIe port connected to it is in low power state, the IO access to device may fail. To solve the issue, the bridge/PCIe port connected to the device is put into active state before probing. Reported-by: Bjorn Mork Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- drivers/pci/pci-driver.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 5270f1a99328..d6fd6b6d9d4b 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi) { struct drv_dev_and_id *ddi = _ddi; struct device *dev = &ddi->dev->dev; + struct device *parent = dev->parent; int rc; + /* The parent bridge must be in active state when probing */ + if (parent) + pm_runtime_get_sync(parent); /* Unbound PCI devices are always set to disabled and suspended. * During probe, the device is set to enabled and active and the * usage count is incremented. If the driver supports runtime PM, @@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi) pm_runtime_set_suspended(dev); pm_runtime_put_noidle(dev); } + if (parent) + pm_runtime_put(parent); return rc; } From 3d8387efe1ad9eb5bfe8a2e58cdbd1b88b247eef Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 15 Aug 2012 09:43:03 +0800 Subject: [PATCH 095/665] PCI/PM: Fix config reg access for D3cold and bridge suspending This patch fixes the following bug: http://marc.info/?l=linux-pci&m=134338059022620&w=2 Where lspci does not work properly if a device and the corresponding parent bridge (such as PCIe port) is suspended. This is because the device configuration space registers will be not accessible if the corresponding parent bridge is suspended or the device is put into D3cold state. To solve the issue, the bridge/PCIe port connected to the device is put into active state before read/write configuration space registers. If the device is in D3cold state, it will be put into active state too. To avoid resume/suspend PCIe port for each configuration register read/write, a small delay is added before the PCIe port to go suspended. Reported-by: Bjorn Mork Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- drivers/pci/pci-sysfs.c | 42 ++++++++++++++++++++++++++++++++++ drivers/pci/pcie/portdrv_pci.c | 9 ++++++++ 2 files changed, 51 insertions(+) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 6869009c7393..02d107b15281 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -458,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) } struct device_attribute vga_attr = __ATTR_RO(boot_vga); +static void +pci_config_pm_runtime_get(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + if (parent) + pm_runtime_get_sync(parent); + pm_runtime_get_noresume(dev); + /* + * pdev->current_state is set to PCI_D3cold during suspending, + * so wait until suspending completes + */ + pm_runtime_barrier(dev); + /* + * Only need to resume devices in D3cold, because config + * registers are still accessible for devices suspended but + * not in D3cold. + */ + if (pdev->current_state == PCI_D3cold) + pm_runtime_resume(dev); +} + +static void +pci_config_pm_runtime_put(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + pm_runtime_put(dev); + if (parent) + pm_runtime_put_sync(parent); +} + static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, @@ -484,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj, size = count; } + pci_config_pm_runtime_get(dev); + if ((off & 1) && size) { u8 val; pci_user_read_config_byte(dev, off, &val); @@ -529,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj, --size; } + pci_config_pm_runtime_put(dev); + return count; } @@ -549,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj, count = size; } + pci_config_pm_runtime_get(dev); + if ((off & 1) && size) { pci_user_write_config_byte(dev, off, data[off - init_off]); off++; @@ -587,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj, --size; } + pci_config_pm_runtime_put(dev); + return count; } diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 62f5a76c8f80..e76b44777dbf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(struct device *dev) { return 0; } + +static int pcie_port_runtime_idle(struct device *dev) +{ + /* Delay for a short while to prevent too frequent suspend/resume */ + pm_schedule_suspend(dev, 10); + return -EBUSY; +} #else #define pcie_port_runtime_suspend NULL #define pcie_port_runtime_resume NULL +#define pcie_port_runtime_idle NULL #endif static const struct dev_pm_ops pcie_portdrv_pm_ops = { @@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { .resume_noirq = pcie_port_resume_noirq, .runtime_suspend = pcie_port_runtime_suspend, .runtime_resume = pcie_port_runtime_resume, + .runtime_idle = pcie_port_runtime_idle, }; #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) From 046c6531b60e8b9eabf47820a06161338a612167 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 8 Aug 2012 09:07:41 +0800 Subject: [PATCH 096/665] PCI/PM: Add ABI document for sysfs file d3cold_allowed This patch adds ABI document for the following sysfs file: /sys/bus/pci/devices/.../d3cold_allowed Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-bus-pci | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index 34f51100f029..dff1f48d252d 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci @@ -210,3 +210,15 @@ Users: firmware assigned instance number of the PCI device that can help in understanding the firmware intended order of the PCI device. + +What: /sys/bus/pci/devices/.../d3cold_allowed +Date: July 2012 +Contact: Huang Ying +Description: + d3cold_allowed is bit to control whether the corresponding PCI + device can be put into D3Cold state. If it is cleared, the + device will never be put into D3Cold state. If it is set, the + device may be put into D3Cold state if other requirements are + satisfied too. Reading this attribute will show the current + value of d3cold_allowed bit. Writing this attribute will set + the value of d3cold_allowed bit. From a1d0fa776870aeda5eb91b131d0f1aede6d94ef1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 21 Aug 2012 22:01:45 -0700 Subject: [PATCH 097/665] Input: edt-ft5x06 - fix build error when compiling wthout CONFIG_DEBUG_FS This fixes the following breakage: edt-ft5x06.c: In function edt_ft5x06_ts_remove: edt-ft5x06.c:846:14: error: struct edt_ft5x06_ts_data has no member named raw_buffer Signed-off-by: Guenter Roeck Acked-by: Simon Budig Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 9afc777a40a7..b06a5e3a665e 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -602,6 +602,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) { if (tsdata->debug_dir) debugfs_remove_recursive(tsdata->debug_dir); + kfree(tsdata->raw_buffer); } #else @@ -843,7 +844,6 @@ static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client) if (gpio_is_valid(pdata->reset_pin)) gpio_free(pdata->reset_pin); - kfree(tsdata->raw_buffer); kfree(tsdata); return 0; From f35dd69ba341bda3790713b9e964483934b995e1 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 21 Aug 2012 21:57:15 -0700 Subject: [PATCH 098/665] Input: imx_keypad - reset the hardware before enabling Ensure the hardware is correctly initialized before requesting the interrupt, otherwise if a key was already touched since power-on the kernel enters an interrupt loop. To fix this issue we clear pending interrupt sources. We also have to make sure clk is enabled while changing the keypad registers. Signed-off-by: Michael Grzeschik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/imx_keypad.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index ff4c0a87a25f..ce68e361558c 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -358,6 +358,7 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad) /* Inhibit KDI and KRI interrupts. */ reg_val = readw(keypad->mmio_base + KPSR); reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE); + reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD; writew(reg_val, keypad->mmio_base + KPSR); /* Colums as open drain and disable all rows */ @@ -515,7 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) input_set_drvdata(input_dev, keypad); /* Ensure that the keypad will stay dormant until opened */ + clk_enable(keypad->clk); imx_keypad_inhibit(keypad); + clk_disable(keypad->clk); error = request_irq(irq, imx_keypad_irq_handler, 0, pdev->name, keypad); From 7b125b94ca16b7e618c6241cb02c4c8060cea5e3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 21 Aug 2012 21:57:15 -0700 Subject: [PATCH 099/665] Input: i8042 - add Gigabyte T1005 series netbooks to noloop table They all define their chassis type as "Other" and therefore are not categorized as "laptops" by the driver, which tries to perform AUX IRQ delivery test which fails and causes touchpad not working. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42620 Cc: stable@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5ec774d6c82b..6918773ce024 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -176,6 +176,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"), }, }, + { + /* Gigabyte T1005 - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005"), + }, + }, + { + /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"), + }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), From 6f4d0382e2a6d27045e223d8c452659477826650 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 21 Aug 2012 22:11:59 -0700 Subject: [PATCH 100/665] Input: wacom - add support for EMR on Cintiq 24HD touch Adds support for the EMR digitizer on the Cintiq 24HD touch. The EMR digitizer should work identically to that found on the Cintiq 24HD. The touch digitizer is a separate USB device similar to how we split apart some other devices. Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 002041975de9..532d067a9e07 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1848,7 +1848,10 @@ static const struct wacom_features wacom_features_0x2A = { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xF4 = - { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, + { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, + 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0xF8 = + { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, @@ -2091,6 +2094,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xEF) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, + { USB_DEVICE_WACOM(0xF8) }, { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } From 338b131a3269881c7431234855c93c219b0979b6 Mon Sep 17 00:00:00 2001 From: "sreekanth.reddy@lsi.com" Date: Tue, 17 Jul 2012 15:57:05 +0530 Subject: [PATCH 101/665] [SCSI] mpt2sas: Fix for Driver oops, when loading driver with max_queue_depth command line option to a very small value If the specified max_queue_depth setting is less than the expected number of internal commands, then driver will calculate the queue depth size to a negitive number. This negitive number is actually a very large number because variable is unsigned 16bit integer. So, the driver will ask for a very large amount of memory for message frames and resulting into oops as memory allocation routines will not able to handle such a large request. So, in order to limit this kind of oops, The driver need to set the max_queue_depth to a scsi mid layer's can_queue value. Then the overall message frames required for IO is minimum of either (max_queue_depth plus internal commands) or the IOC global credits. Signed-off-by: Sreekanth Reddy Cc: Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 9d46fcbe7755..b25757d1e91b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -2424,10 +2424,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1) - max_request_credit = (max_queue_depth < facts->RequestCredit) - ? max_queue_depth : facts->RequestCredit; - else + if (max_queue_depth != -1 && max_queue_depth != 0) { + max_request_credit = min_t(u16, max_queue_depth + + ioc->hi_priority_depth + ioc->internal_depth, + facts->RequestCredit); + if (max_request_credit > MAX_HBA_QUEUE_DEPTH) + max_request_credit = MAX_HBA_QUEUE_DEPTH; + } else max_request_credit = min_t(u16, facts->RequestCredit, MAX_HBA_QUEUE_DEPTH); @@ -2502,7 +2505,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* set the scsi host can_queue depth * with some internal commands that could be outstanding */ - ioc->shost->can_queue = ioc->scsiio_depth - (2); + ioc->shost->can_queue = ioc->scsiio_depth; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); From bd8d6dd43a77bfd2b8fef5b094b9d6095e169dee Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Tue, 17 Jul 2012 18:20:44 -0700 Subject: [PATCH 102/665] [SCSI] megaraid_sas: Move poll_aen_lock initializer The following patch moves the poll_aen_lock initializer from megasas_probe_one() to megasas_init(). This prevents a crash when a user loads the driver and tries to issue a poll() system call on the ioctl interface with no adapters present. Signed-off-by: Kashyap Desai Signed-off-by: Adam Radford Cc: Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index dc27598785e5..ed38454228c6 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4066,7 +4066,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&instance->cmd_pool_lock); spin_lock_init(&instance->hba_lock); spin_lock_init(&instance->completion_lock); - spin_lock_init(&poll_aen_lock); mutex_init(&instance->aen_mutex); mutex_init(&instance->reset_mutex); @@ -5392,6 +5391,8 @@ static int __init megasas_init(void) printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, MEGASAS_EXT_VERSION); + spin_lock_init(&poll_aen_lock); + support_poll_for_event = 2; support_device_change = 1; From 27c419739b67decced4650440829b8d51bef954b Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 31 May 2012 15:05:33 -0400 Subject: [PATCH 103/665] [SCSI] scsi_lib: fix scsi_io_completion's SG_IO error propagation The following v3.4-rc1 commit unmasked an existing bug in scsi_io_completion's SG_IO error handling: 47ac56d [SCSI] scsi_error: classify some ILLEGAL_REQUEST sense as a permanent TARGET_ERROR Given that certain ILLEGAL_REQUEST are now properly categorized as TARGET_ERROR the host_byte is being set (before host_byte wasn't ever set for these ILLEGAL_REQUEST). In scsi_io_completion, initialize req->errors with cmd->result _after_ the SG_IO block that calls __scsi_error_from_host_byte (which may modify the host_byte). Before this fix: cdb to send: 12 01 01 00 00 00 ioctl(3, SG_IO, {'S', SG_DXFER_NONE, cmd[6]=[12, 01, 01, 00, 00, 00], mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=20000, flags=0, status=02, masked_status=01, sb[19]=[70, 00, 05, 00, 00, 00, 00, 0b, 00, 00, 00, 00, 24, 00, 00, 00, 00, 00, 00], host_status=0x10, driver_status=0x8, resid=0, duration=0, info=0x1}) = 0 SCSI Status: Check Condition Sense Information: sense buffer empty After: cdb to send: 12 01 01 00 00 00 ioctl(3, SG_IO, {'S', SG_DXFER_NONE, cmd[6]=[12, 01, 01, 00, 00, 00], mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=20000, flags=0, status=02, masked_status=01, sb[19]=[70, 00, 05, 00, 00, 00, 00, 0b, 00, 00, 00, 00, 24, 00, 00, 00, 00, 00, 00], host_status=0, driver_status=0x8, resid=0, duration=0, info=0x1}) = 0 SCSI Status: Check Condition Sense Information: Fixed format, current; Sense key: Illegal Request Additional sense: Invalid field in cdb Raw sense data (in hex): 70 00 05 00 00 00 00 0b 00 00 00 00 24 00 00 00 00 00 00 Reported-by: Paolo Bonzini Tested-by: Paolo Bonzini Signed-off-by: Mike Snitzer Reviewed-by: Babu Moger Cc: stable@vger.kernel.org # 3.4 Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ffd77739ae3e..faa790fba134 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -776,7 +776,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ - req->errors = result; if (result) { if (sense_valid && req->sense) { /* @@ -792,6 +791,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) if (!sense_deferred) error = __scsi_error_from_host_byte(cmd, result); } + /* + * __scsi_error_from_host_byte may have reset the host_byte + */ + req->errors = cmd->result; req->resid_len = scsi_get_resid(cmd); From 14216561e164671ce147458653b1fea06a4ada1e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 25 Jul 2012 23:55:55 +0400 Subject: [PATCH 104/665] [SCSI] Fix 'Device not ready' issue on mpt2sas This is a particularly nasty SCSI ATA Translation Layer (SATL) problem. SAT-2 says (section 8.12.2) if the device is in the stopped state as the result of processing a START STOP UNIT command (see 9.11), then the SATL shall terminate the TEST UNIT READY command with CHECK CONDITION status with the sense key set to NOT READY and the additional sense code of LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED; mpt2sas internal SATL seems to implement this. The result is very confusing standby behaviour (using hdparm -y). If you suspend a drive and then send another command, usually it wakes up. However, if the next command is a TEST UNIT READY, the SATL sees that the drive is suspended and proceeds to follow the SATL rules for this, returning NOT READY to all subsequent commands. This means that the ordering of TEST UNIT READY is crucial: if you send TUR and then a command, you get a NOT READY to both back. If you send a command and then a TUR, you get GOOD status because the preceeding command woke the drive. This bit us badly because commit 85ef06d1d252f6a2e73b678591ab71caad4667bb Author: Tejun Heo Date: Fri Jul 1 16:17:47 2011 +0200 block: flush MEDIA_CHANGE from drivers on close(2) Changed our ordering on TEST UNIT READY commands meaning that SATA drives connected to an mpt2sas now suspend and refuse to wake (because the mpt2sas SATL sees the suspend *before* the drives get awoken by the next ATA command) resulting in lots of failed commands. The standard is completely nuts forcing this inconsistent behaviour, but we have to work around it. The fix for this is twofold: 1. Set the allow_restart flag so we wake the drive when we see it has been suspended 2. Return all TEST UNIT READY status directly to the mid layer without any further error handling which prevents us causing error handling which may offline the device just because of a media check TUR. Reported-by: Matthias Prager Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 10 ++++++++++ drivers/scsi/scsi_scan.c | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4a6381c87253..de2337f255a7 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -42,6 +42,8 @@ #include +static void scsi_eh_done(struct scsi_cmnd *scmd); + #define SENSE_TIMEOUT (10*HZ) /* @@ -241,6 +243,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) if (! scsi_command_normalize_sense(scmd, &sshdr)) return FAILED; /* no valid sense data */ + if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) + /* + * nasty: for mid-layer issued TURs, we need to return the + * actual sense data without any recovery attempt. For eh + * issued ones, we need to try to recover and interpret + */ + return SUCCESS; + if (scsi_sense_is_deferred(&sshdr)) return NEEDS_RETRY; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 56a93794c470..d947ffc20ceb 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -764,6 +764,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->model = (char *) (sdev->inquiry + 16); sdev->rev = (char *) (sdev->inquiry + 32); + if (strncmp(sdev->vendor, "ATA ", 8) == 0) { + /* + * sata emulation layer device. This is a hack to work around + * the SATL power management specifications which state that + * when the SATL detects the device has gone into standby + * mode, it shall respond with NOT READY. + */ + sdev->allow_restart = 1; + } + if (*bflags & BLIST_ISROM) { sdev->type = TYPE_ROM; sdev->removable = 1; From 27f011243a6e4e8b81078df1d83608dae31e3d38 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Mon, 20 Aug 2012 11:28:25 -0700 Subject: [PATCH 105/665] mac80211: fix DS to MBSS address translation The destination address of unicast frames forwarded through a mesh gate was being replaced with the broadcast address. Instead leave the original destination address as the mesh DA. If the nexthop address is not in the mpath table it will be resolved. If that fails, the frame will be forwarded to known mesh gates. Reported-by: Cedric Voncken Signed-off-by: Thomas Pedersen Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index acf712ffb5e6..c5e8c9c31f76 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1811,37 +1811,31 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata, NULL, NULL); } else { - int is_mesh_mcast = 1; - const u8 *mesh_da; + /* DS -> MBSS (802.11-2012 13.11.3.3). + * For unicast with unknown forwarding information, + * destination might be in the MBSS or if that fails + * forwarded to another mesh gate. In either case + * resolution will be handled in ieee80211_xmit(), so + * leave the original DA. This also works for mcast */ + const u8 *mesh_da = skb->data; + + if (mppath) + mesh_da = mppath->mpp; + else if (mpath) + mesh_da = mpath->dst; + rcu_read_unlock(); - if (is_multicast_ether_addr(skb->data)) - /* DA TA mSA AE:SA */ - mesh_da = skb->data; - else { - static const u8 bcast[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - if (mppath) { - /* RA TA mDA mSA AE:DA SA */ - mesh_da = mppath->mpp; - is_mesh_mcast = 0; - } else if (mpath) { - mesh_da = mpath->dst; - is_mesh_mcast = 0; - } else { - /* DA TA mSA AE:SA */ - mesh_da = bcast; - } - } hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, mesh_da, sdata->vif.addr); - rcu_read_unlock(); - if (is_mesh_mcast) + if (is_multicast_ether_addr(mesh_da)) + /* DA TA mSA AE:SA */ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata, skb->data + ETH_ALEN, NULL); else + /* RA TA mDA mSA AE:DA SA */ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata, From 1922b0f2758badc0b971d1ebbd300bc6635a6aef Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Mon, 13 Aug 2012 20:36:05 +0530 Subject: [PATCH 106/665] mfd: Move tps65217 regulator plat data handling to regulator Regulator platform data handling was mistakenly added to MFD driver. So we will see build errors if we compile MFD drivers without CONFIG_REGULATOR. This patch moves regulator platform data handling from TPS65217 MFD driver to regulator driver. This makes MFD driver independent of REGULATOR framework so build error is fixed if CONFIG_REGULATOR is not set. drivers/built-in.o: In function `tps65217_probe': tps65217.c:(.devinit.text+0x13e37): undefined reference to `of_regulator_match' This patch also fix allocation size of tps65217 platform data. Current implementation allocates a struct tps65217_board for each regulator specified in the device tree. But the structure itself provides array of regulators so one instance of it is sufficient. Signed-off-by: AnilKumar Ch --- drivers/mfd/tps65217.c | 130 ++++++++----------------- drivers/regulator/tps65217-regulator.c | 124 ++++++++++++++++++++--- include/linux/mfd/tps65217.h | 12 ++- 3 files changed, 161 insertions(+), 105 deletions(-) diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 61c097a98f5d..3bc274409b58 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -24,11 +24,18 @@ #include #include #include -#include +#include +#include #include #include +static struct mfd_cell tps65217s[] = { + { + .name = "tps65217-pmic", + }, +}; + /** * tps65217_reg_read: Read a single tps65217 register. * @@ -133,83 +140,48 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, } EXPORT_SYMBOL_GPL(tps65217_clear_bits); -#ifdef CONFIG_OF -static struct of_regulator_match reg_matches[] = { - { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, - { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, - { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, - { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, - { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, - { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, - { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, -}; - -static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) -{ - struct device_node *node = client->dev.of_node; - struct tps65217_board *pdata; - struct device_node *regs; - int count = ARRAY_SIZE(reg_matches); - int ret, i; - - regs = of_find_node_by_name(node, "regulators"); - if (!regs) - return NULL; - - ret = of_regulator_match(&client->dev, regs, reg_matches, count); - of_node_put(regs); - if ((ret < 0) || (ret > count)) - return NULL; - - count = ret; - pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - for (i = 0; i < count; i++) { - if (!reg_matches[i].init_data || !reg_matches[i].of_node) - continue; - - pdata->tps65217_init_data[i] = reg_matches[i].init_data; - pdata->of_node[i] = reg_matches[i].of_node; - } - - return pdata; -} - -static struct of_device_id tps65217_of_match[] = { - { .compatible = "ti,tps65217", }, - { }, -}; -#else -static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) -{ - return NULL; -} -#endif - static struct regmap_config tps65217_regmap_config = { .reg_bits = 8, .val_bits = 8, }; +static const struct of_device_id tps65217_of_match[] = { + { .compatible = "ti,tps65217", .data = (void *)TPS65217 }, + { /* sentinel */ }, +}; + static int __devinit tps65217_probe(struct i2c_client *client, const struct i2c_device_id *ids) { struct tps65217 *tps; - struct regulator_init_data *reg_data; - struct tps65217_board *pdata = client->dev.platform_data; - int i, ret; unsigned int version; + unsigned int chip_id = ids->driver_data; + const struct of_device_id *match; + int ret; - if (!pdata && client->dev.of_node) - pdata = tps65217_parse_dt(client); + if (client->dev.of_node) { + match = of_match_device(tps65217_of_match, &client->dev); + if (!match) { + dev_err(&client->dev, + "Failed to find matching dt id\n"); + return -EINVAL; + } + chip_id = (unsigned int)match->data; + } + + if (!chip_id) { + dev_err(&client->dev, "id is null.\n"); + return -ENODEV; + } tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; - tps->pdata = pdata; + i2c_set_clientdata(client, tps); + tps->dev = &client->dev; + tps->id = chip_id; + tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); @@ -218,8 +190,12 @@ static int __devinit tps65217_probe(struct i2c_client *client, return ret; } - i2c_set_clientdata(client, tps); - tps->dev = &client->dev; + ret = mfd_add_devices(tps->dev, -1, tps65217s, + ARRAY_SIZE(tps65217s), NULL, 0); + if (ret < 0) { + dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); + return ret; + } ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); if (ret < 0) { @@ -232,41 +208,21 @@ static int __devinit tps65217_probe(struct i2c_client *client, (version & TPS65217_CHIPID_CHIP_MASK) >> 4, version & TPS65217_CHIPID_REV_MASK); - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { - struct platform_device *pdev; - - pdev = platform_device_alloc("tps65217-pmic", i); - if (!pdev) { - dev_err(tps->dev, "Cannot create regulator %d\n", i); - continue; - } - - pdev->dev.parent = tps->dev; - pdev->dev.of_node = pdata->of_node[i]; - reg_data = pdata->tps65217_init_data[i]; - platform_device_add_data(pdev, reg_data, sizeof(*reg_data)); - tps->regulator_pdev[i] = pdev; - - platform_device_add(pdev); - } - return 0; } static int __devexit tps65217_remove(struct i2c_client *client) { struct tps65217 *tps = i2c_get_clientdata(client); - int i; - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) - platform_device_unregister(tps->regulator_pdev[i]); + mfd_remove_devices(tps->dev); return 0; } static const struct i2c_device_id tps65217_id_table[] = { - {"tps65217", 0xF0}, - {/* end of list */} + {"tps65217", TPS65217}, + { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, tps65217_id_table); diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 6caa222af77a..ab00cab905b7 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -281,37 +282,130 @@ static const struct regulator_desc regulators[] = { NULL), }; +#ifdef CONFIG_OF +static struct of_regulator_match reg_matches[] = { + { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, + { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, + { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, + { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, + { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, + { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, + { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, +}; + +static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) +{ + struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); + struct device_node *node = tps->dev->of_node; + struct tps65217_board *pdata; + struct device_node *regs; + int i, count; + + regs = of_find_node_by_name(node, "regulators"); + if (!regs) + return NULL; + + count = of_regulator_match(pdev->dev.parent, regs, + reg_matches, TPS65217_NUM_REGULATOR); + of_node_put(regs); + if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) + return NULL; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + for (i = 0; i < count; i++) { + if (!reg_matches[i].init_data || !reg_matches[i].of_node) + continue; + + pdata->tps65217_init_data[i] = reg_matches[i].init_data; + pdata->of_node[i] = reg_matches[i].of_node; + } + + return pdata; +} +#else +static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) +{ + return NULL; +} +#endif + static int __devinit tps65217_regulator_probe(struct platform_device *pdev) { + struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); + struct tps65217_board *pdata = dev_get_platdata(tps->dev); + struct regulator_init_data *reg_data; struct regulator_dev *rdev; - struct tps65217 *tps; - struct tps_info *info = &tps65217_pmic_regs[pdev->id]; struct regulator_config config = { }; + int i, ret; - /* Already set by core driver */ - tps = dev_to_tps65217(pdev->dev.parent); - tps->info[pdev->id] = info; + if (tps->dev->of_node) + pdata = tps65217_parse_dt(pdev); - config.dev = &pdev->dev; - config.of_node = pdev->dev.of_node; - config.init_data = pdev->dev.platform_data; - config.driver_data = tps; + if (!pdata) { + dev_err(&pdev->dev, "Platform data not found\n"); + return -EINVAL; + } - rdev = regulator_register(®ulators[pdev->id], &config); - if (IS_ERR(rdev)) - return PTR_ERR(rdev); + if (tps65217_chip_id(tps) != TPS65217) { + dev_err(&pdev->dev, "Invalid tps chip version\n"); + return -ENODEV; + } - platform_set_drvdata(pdev, rdev); + platform_set_drvdata(pdev, tps); + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { + + reg_data = pdata->tps65217_init_data[i]; + + /* + * Regulator API handles empty constraints but not NULL + * constraints + */ + if (!reg_data) + continue; + + /* Register the regulators */ + tps->info[i] = &tps65217_pmic_regs[i]; + + config.dev = tps->dev; + config.init_data = reg_data; + config.driver_data = tps; + config.regmap = tps->regmap; + if (tps->dev->of_node) + config.of_node = pdata->of_node[i]; + + rdev = regulator_register(®ulators[i], &config); + if (IS_ERR(rdev)) { + dev_err(tps->dev, "failed to register %s regulator\n", + pdev->name); + ret = PTR_ERR(rdev); + goto err_unregister_regulator; + } + + /* Save regulator for cleanup */ + tps->rdev[i] = rdev; + } return 0; + +err_unregister_regulator: + while (--i >= 0) + regulator_unregister(tps->rdev[i]); + + return ret; } static int __devexit tps65217_regulator_remove(struct platform_device *pdev) { - struct regulator_dev *rdev = platform_get_drvdata(pdev); + struct tps65217 *tps = platform_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) + regulator_unregister(tps->rdev[i]); platform_set_drvdata(pdev, NULL); - regulator_unregister(rdev); return 0; } diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 12c06870829a..7cd83d826ed8 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -22,6 +22,9 @@ #include #include +/* TPS chip id list */ +#define TPS65217 0xF0 + /* I2C ID for TPS65217 part */ #define TPS65217_I2C_ID 0x24 @@ -248,13 +251,11 @@ struct tps_info { struct tps65217 { struct device *dev; struct tps65217_board *pdata; + unsigned int id; struct regulator_desc desc[TPS65217_NUM_REGULATOR]; struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; struct tps_info *info[TPS65217_NUM_REGULATOR]; struct regmap *regmap; - - /* Client devices */ - struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR]; }; static inline struct tps65217 *dev_to_tps65217(struct device *dev) @@ -262,6 +263,11 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev) return dev_get_drvdata(dev); } +static inline int tps65217_chip_id(struct tps65217 *tps65217) +{ + return tps65217->id; +} + int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, unsigned int *val); int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, From 6c0274cbe63ec265f842537825684a619e6cce93 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2012 12:13:48 +0200 Subject: [PATCH 107/665] ARM: shmobile: sh73a0: fixup RELOC_BASE of intca_irq_pins_desc sh73a0 :: intca_irq_pins_desc irq table had conflict from irq 552 to irq 557 before. But the second controller was simply trampling the first one by way of the -EEXIST case from irq_alloc_desc_at(). But now, we have irqdomain support from 1d6a21b0a672fb29b01ccf397d478e0541e17716 (sh: intc: initial irqdomain support) The irqdomain code has simply tightened down the sanity checks and error path. So, sh73a0 CPU board got some WARNING when booting now. This patch fixup RELOC_BASE to solve this issue. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/intc-sh73a0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index ee447404c857..588555a67d9c 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -259,9 +259,9 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on) return 0; /* always allow wakeup */ } -#define RELOC_BASE 0x1000 +#define RELOC_BASE 0x1200 -/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */ +/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */ #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE) INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000, From 3eadd88a37c330a83bfdee35b3e5837b7c2f7214 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Aug 2012 17:30:13 +0100 Subject: [PATCH 108/665] ASoC: wm9712: Provide TLV information for capture boost controls Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c9c696ca76f7..6aa1bf8c6897 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -132,8 +132,9 @@ SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1), SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), -SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0), -SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1), +SOC_SINGLE_TLV("Capture Boost Switch", AC97_REC_SEL, 14, 1, 0, boost_tlv), +SOC_SINGLE_TLV("Capture to Phone Boost Switch", AC97_REC_SEL, 11, 1, 1, + boost_tlv), SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), From 363947d7d999f74dfd710fb7b7ccad965590f098 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 20 Aug 2012 19:54:24 +0100 Subject: [PATCH 109/665] ASoC: wm_hubs: Use explicit casts for converting to signed Should be no behaviour change. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 05a02e1b7e92..b340552efe4e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -297,12 +297,12 @@ static void enable_dc_servo(struct snd_soc_codec *codec) hubs->dcs_codes_l, hubs->dcs_codes_r); /* HPOUT1R */ - offset = reg_r; + offset = (s8)reg_r; offset += hubs->dcs_codes_r; dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1L */ - offset = reg_l; + offset = (s8)reg_l; offset += hubs->dcs_codes_l; dcs_cfg |= (u8)offset; From 20bac1f3f470e2d5c87af7b41b10e088e47989bb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 20 Aug 2012 20:01:51 +0100 Subject: [PATCH 110/665] ASoC: wm_hubs: Add trace showing semantics of the DCS update Aids diagnostics. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b340552efe4e..b2e939a8970e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -298,11 +298,15 @@ static void enable_dc_servo(struct snd_soc_codec *codec) /* HPOUT1R */ offset = (s8)reg_r; + dev_dbg(codec->dev, "DCS right %d->%d\n", offset, + offset + hubs->dcs_codes_r); offset += hubs->dcs_codes_r; dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1L */ offset = (s8)reg_l; + dev_dbg(codec->dev, "DCS left %d->%d\n", offset, + offset + hubs->dcs_codes_l); offset += hubs->dcs_codes_l; dcs_cfg |= (u8)offset; From 02e79476998ba7e62842d20dca898c403ad55c7e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 21 Aug 2012 17:54:52 +0100 Subject: [PATCH 111/665] ASoC: wm_hubs: Allow configuration of MICBIAS power up delay via pdata Sometimes the analogue circuitry connected to the microphone needs some time to settle after power up. Allow systems to configure this delay in the platform data, the driver will then insert the required delay during power up of paths that involve the microphone. Signed-off-by: Mark Brown --- include/linux/mfd/wm8994/pdata.h | 4 ++++ include/sound/wm8993.h | 4 ++++ sound/soc/codecs/wm8993.c | 2 ++ sound/soc/codecs/wm8994.c | 2 ++ sound/soc/codecs/wm_hubs.c | 35 ++++++++++++++++++++++++++++---- sound/soc/codecs/wm_hubs.h | 4 ++++ 6 files changed, 47 insertions(+), 4 deletions(-) diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index f0361c031927..fc87be4fdc25 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h @@ -164,6 +164,10 @@ struct wm8994_pdata { int num_micd_rates; struct wm8958_micd_rate *micd_rates; + /* Power up delays to add after microphone bias power up (ms) */ + int micb1_delay; + int micb2_delay; + /* LINEOUT can be differential or single ended */ unsigned int lineout1_diff:1; unsigned int lineout2_diff:1; diff --git a/include/sound/wm8993.h b/include/sound/wm8993.h index eee19f63c0d8..8016fd826f5a 100644 --- a/include/sound/wm8993.h +++ b/include/sound/wm8993.h @@ -32,6 +32,10 @@ struct wm8993_platform_data { unsigned int lineout1fb:1; unsigned int lineout2fb:1; + /* Delay to add for microphones to stabalise after power up */ + int micbias1_delay; + int micbias2_delay; + /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ unsigned int micbias1_lvl:1; unsigned int micbias2_lvl:1; diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9fd80d688979..94737a30716b 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1520,6 +1520,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) wm8993->pdata.lineout2fb, wm8993->pdata.jd_scthr, wm8993->pdata.jd_thr, + wm8993->pdata.micbias1_delay, + wm8993->pdata.micbias2_delay, wm8993->pdata.micbias1_lvl, wm8993->pdata.micbias2_lvl); diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 353612eec8bf..b74df52d2820 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3145,6 +3145,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) pdata->lineout2fb, pdata->jd_scthr, pdata->jd_thr, + pdata->micb1_delay, + pdata->micb2_delay, pdata->micbias1_lvl, pdata->micbias2_lvl); diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b2e939a8970e..7a773a835b8e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -644,6 +644,28 @@ static int lineout_event(struct snd_soc_dapm_widget *w, return 0; } +static int micbias_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); + + switch (w->shift) { + case WM8993_MICB1_ENA_SHIFT: + if (hubs->micb1_delay) + msleep(hubs->micb1_delay); + break; + case WM8993_MICB2_ENA_SHIFT: + if (hubs->micb2_delay) + msleep(hubs->micb2_delay); + break; + default: + return -EINVAL; + } + + return 0; +} + void wm_hubs_update_class_w(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); @@ -834,8 +856,10 @@ SND_SOC_DAPM_INPUT("IN1RP"), SND_SOC_DAPM_INPUT("IN2RN"), SND_SOC_DAPM_INPUT("IN2RP:VXRP"), -SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, + micbias_event, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, + micbias_event, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, in1l_pga, ARRAY_SIZE(in1l_pga)), @@ -1170,13 +1194,16 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, int lineout1_diff, int lineout2_diff, int lineout1fb, int lineout2fb, - int jd_scthr, int jd_thr, int micbias1_lvl, - int micbias2_lvl) + int jd_scthr, int jd_thr, + int micbias1_delay, int micbias2_delay, + int micbias1_lvl, int micbias2_lvl) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); hubs->lineout1_se = !lineout1_diff; hubs->lineout2_se = !lineout2_diff; + hubs->micb1_delay = micbias1_delay; + hubs->micb2_delay = micbias2_delay; if (!lineout1_diff) snd_soc_update_bits(codec, WM8993_LINE_MIXER1, diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index a5a09e6f87d5..24c763df21f9 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h @@ -36,6 +36,9 @@ struct wm_hubs_data { struct list_head dcs_cache; bool (*check_class_w_digital)(struct snd_soc_codec *); + int micb1_delay; + int micb2_delay; + bool lineout1_se; bool lineout1n_ena; bool lineout1p_ena; @@ -56,6 +59,7 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, int lineout1_diff, int lineout2_diff, int lineout1fb, int lineout2fb, int jd_scthr, int jd_thr, + int micbias1_dly, int micbias2_dly, int micbias1_lvl, int micbias2_lvl); extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); From ea2d218308e5710c70d76eb3c2876988c88119cc Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sun, 5 Aug 2012 00:29:07 +0300 Subject: [PATCH 112/665] brcm80211: smac: set interface down on reset This change marks interface as down on reset, otherwise the driver can't reinitialize itself properly. Without the change a transient problem turns out to be critical and leads to inavailability to reset the driver without brcmsmac module unload/load cycle: ieee80211 phy0: wl0: PSM microcode watchdog fired at 5993 (seconds). Resetting. brcms_c_dpc : PSM Watchdog, chipid 0xa8d9, chiprev 0x1 ieee80211 phy0: wl0: fatal error, reinitializing ieee80211 phy0: Hardware restart was requested ieee80211 phy0: brcms_ops_start: brcms_up() returned -19 Signed-off-by: Vladimir Zapolskiy Cc: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 192ad5c1fcc8..a5edebeb0b4f 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1233,6 +1233,9 @@ uint brcms_reset(struct brcms_info *wl) /* dpc will not be rescheduled */ wl->resched = false; + /* inform publicly that interface is down */ + wl->pub->up = false; + return 0; } From f199131a8f1dde3309c8520b663aa7a3daf5995e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:00 +0300 Subject: [PATCH 113/665] ARM/ASoC: omap-mcbsp: Move OMAP2+ clock parenting code to ASoC driver Move the McBSP CLKS re-parenting code to ASoC driver from arch/arm/mach-omap2. The call fort the re-parenting has been already limited to OMAP2+ SoC in the ASoC driver. There is no longer need to have callback function for it. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/mcbsp.c | 40 ------------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 1 - sound/soc/omap/mcbsp.c | 31 +++++++++++++++---- 3 files changed, 26 insertions(+), 46 deletions(-) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 577cb77db26c..ebc801ea5be9 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -101,45 +101,6 @@ static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, return 0; } -/* McBSP CLKS source switching function */ -static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk, - const char *src) -{ - struct clk *fck_src; - char *fck_src_name; - int r; - - if (!strcmp(src, "clks_ext")) - fck_src_name = "pad_fck"; - else if (!strcmp(src, "clks_fclk")) - fck_src_name = "prcm_fck"; - else - return -EINVAL; - - fck_src = clk_get(dev, fck_src_name); - if (IS_ERR_OR_NULL(fck_src)) { - pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks", - fck_src_name); - return -EINVAL; - } - - pm_runtime_put_sync(dev); - - r = clk_set_parent(clk, fck_src); - if (IS_ERR_VALUE(r)) { - pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n", - "clks", fck_src_name); - clk_put(fck_src); - return -EINVAL; - } - - pm_runtime_get_sync(dev); - - clk_put(fck_src); - - return 0; -} - static int omap3_enable_st_clock(unsigned int id, bool enable) { unsigned int w; @@ -181,7 +142,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->reg_size = 4; pdata->has_ccr = true; } - pdata->set_clk_src = omap2_mcbsp_set_clk_src; /* On OMAP2/3 the McBSP1 port has 6 pin configuration */ if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index 18814127809a..0a7d5ca471e0 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -47,7 +47,6 @@ struct omap_mcbsp_platform_data { bool has_wakeup; /* Wakeup capability */ bool has_ccr; /* Transceiver has configuration control registers */ int (*enable_st_clock)(unsigned int, bool); - int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src); int (*mux_signal)(struct device *dev, const char *signal, const char *src); }; diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 34835e8a9160..6afbc26cef70 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -726,19 +727,39 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx) int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) { + struct clk *fck_src; const char *src; + int r; if (fck_src_id == MCBSP_CLKS_PAD_SRC) - src = "clks_ext"; + src = "pad_fck"; else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) - src = "clks_fclk"; + src = "prcm_fck"; else return -EINVAL; - if (mcbsp->pdata->set_clk_src) - return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); - else + fck_src = clk_get(mcbsp->dev, src); + if (IS_ERR(fck_src)) { + dev_err(mcbsp->dev, "CLKS: could not clk_get() %s\n", src); return -EINVAL; + } + + pm_runtime_put_sync(mcbsp->dev); + + r = clk_set_parent(mcbsp->fclk, fck_src); + if (r) { + dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n", + src); + clk_put(fck_src); + return r; + } + + pm_runtime_get_sync(mcbsp->dev); + + clk_put(fck_src); + + return 0; + } int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) From cafebc4a66b7ebd4c7990757f7f578488d865ee9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:01 +0300 Subject: [PATCH 114/665] ARM: OMAP: mcbsp: Enable FIFO use for OMAP2430 On OMAP2430 all McBSP ports have 128 word long buffer, enable the use of the FIFO for the audio stack. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- arch/arm/mach-omap2/mcbsp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index ebc801ea5be9..6e046e1111b1 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -151,7 +151,10 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4) pdata->mux_signal = omap4_mcbsp4_mux_rx_clk; - if (oh->class->rev == MCBSP_CONFIG_TYPE3) { + if (oh->class->rev == MCBSP_CONFIG_TYPE2) { + /* The FIFO has 128 locations */ + pdata->buffer_size = 0x80; + } else if (oh->class->rev == MCBSP_CONFIG_TYPE3) { if (id == 2) /* The FIFO has 1024 + 256 locations */ pdata->buffer_size = 0x500; From 6253bac804507c3e15fd6600e0dbd962bba34aae Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:02 +0300 Subject: [PATCH 115/665] ARM: OMAP: board-am3517evm: Configure McBSP1 CLKR/FSR signal source am3517evm board uses McBSP1 for audio with 4pin configuration. The CLKR/FSR signals need to be connected to CLKX/FSX pin of the SoC in this case. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/board-am3517evm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 18f601096ce1..592812af84da 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -264,6 +264,16 @@ static __init void am3517_evm_musb_init(void) usb_musb_init(&musb_board_data); } +static __init void am3517_evm_mcbsp1_init(void) +{ + u32 devconf0; + + /* McBSP1 CLKR/FSR signal to be connected to CLKX/FSX pin */ + devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + devconf0 |= OMAP2_MCBSP1_CLKR_MASK | OMAP2_MCBSP1_FSR_MASK; + omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0); +} + static const struct usbhs_omap_board_data usbhs_bdata __initconst = { .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ @@ -373,6 +383,9 @@ static void __init am3517_evm_init(void) /* MUSB */ am3517_evm_musb_init(); + /* McBSP1 */ + am3517_evm_mcbsp1_init(); + /* MMC init function */ omap_hsmmc_init(mmc); } From fca04aea36a82bc451ddc33dee6f9a48bb0f8a2a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:03 +0300 Subject: [PATCH 116/665] ASoC: am3517evm: Do not configure McBSP1 CLKR/FSR signal muxing The muxing is done at board level, no need to do it in the ASoC machine driver. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/am3517evm.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 009533ab8d18..a997988af147 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -47,26 +47,10 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, /* Set the codec system clock for DAC and ADC */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN); - if (ret < 0) { + if (ret < 0) printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n"); - return ret; - } - - snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); - return ret; - } - - return 0; + return ret; } static struct snd_soc_ops am3517evm_ops = { From 8fef6263ea68f6160637f370a5864d0a455c620d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:04 +0300 Subject: [PATCH 117/665] ARM/ASoC: omap-mcbsp: Remove CLKR/FSR mux configuration code Remove the feature to configure the CLKR/FSR mux on McBSP port with 6pin configuration. When moving to devicetree these callback can no longer be used in a clean way anymore. If a board require to change the 6pin port to work in 4pin setup it needs to set up the mux in the board file. For OMAP2/3: u32 devconf0; /* McBSP1 CLKR/FSR signal to be connected to CLKX/FSX pin */ devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); devconf0 |= OMAP2_MCBSP1_CLKR_MASK | OMAP2_MCBSP1_FSR_MASK; omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0); For OMAP4: u32 mcbsp_pad; /* McBSP4 CLKR/FSR signal to be connected to CLKX/FSX pin */ mcbsp_pad = omap4_ctrl_pad_readl(OMAP2_CONTROL_DEVCONF0); mcbsp_pad |= ((1 << 31) | (1 << 30)); omap4_ctrl_pad_writel(mcbsp_pad, OMAP2_CONTROL_DEVCONF0); In case when the kernel is booted with DT blob the pinctrl-single will be provided as soon as it is enabled on the platform. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/mcbsp.c | 77 ------------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 1 - sound/soc/omap/mcbsp.h | 3 - sound/soc/omap/omap-mcbsp.c | 32 +--------- sound/soc/omap/omap-mcbsp.h | 4 -- 5 files changed, 3 insertions(+), 114 deletions(-) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 6e046e1111b1..660e00b3ef82 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -25,8 +25,6 @@ #include #include -#include "control.h" - /* * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle. * Sidetone needs non-gated ICLK and sidetone autoidle is broken. @@ -34,73 +32,6 @@ #include "cm2xxx_3xxx.h" #include "cm-regbits-34xx.h" -/* McBSP1 internal signal muxing function for OMAP2/3 */ -static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal, - const char *src) -{ - u32 v; - - v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - - if (!strcmp(signal, "clkr")) { - if (!strcmp(src, "clkr")) - v &= ~OMAP2_MCBSP1_CLKR_MASK; - else if (!strcmp(src, "clkx")) - v |= OMAP2_MCBSP1_CLKR_MASK; - else - return -EINVAL; - } else if (!strcmp(signal, "fsr")) { - if (!strcmp(src, "fsr")) - v &= ~OMAP2_MCBSP1_FSR_MASK; - else if (!strcmp(src, "fsx")) - v |= OMAP2_MCBSP1_FSR_MASK; - else - return -EINVAL; - } else { - return -EINVAL; - } - - omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); - - return 0; -} - -/* McBSP4 internal signal muxing function for OMAP4 */ -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX (1 << 31) -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX (1 << 30) -static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, - const char *src) -{ - u32 v; - - /* - * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR - * mux) is used */ - v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - if (!strcmp(signal, "clkr")) { - if (!strcmp(src, "clkr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else if (!strcmp(src, "clkx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else - return -EINVAL; - } else if (!strcmp(signal, "fsr")) { - if (!strcmp(src, "fsr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else if (!strcmp(src, "fsx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else - return -EINVAL; - } else { - return -EINVAL; - } - - omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - return 0; -} - static int omap3_enable_st_clock(unsigned int id, bool enable) { unsigned int w; @@ -143,14 +74,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->has_ccr = true; } - /* On OMAP2/3 the McBSP1 port has 6 pin configuration */ - if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) - pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; - - /* On OMAP4 the McBSP4 port has 6 pin configuration */ - if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4) - pdata->mux_signal = omap4_mcbsp4_mux_rx_clk; - if (oh->class->rev == MCBSP_CONFIG_TYPE2) { /* The FIFO has 128 locations */ pdata->buffer_size = 0x80; diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index 0a7d5ca471e0..c78d90b28b19 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -47,7 +47,6 @@ struct omap_mcbsp_platform_data { bool has_wakeup; /* Wakeup capability */ bool has_ccr; /* Transceiver has configuration control registers */ int (*enable_st_clock)(unsigned int, bool); - int (*mux_signal)(struct device *dev, const char *signal, const char *src); }; /** diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 262a6152111f..49a67259ce5a 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h @@ -334,9 +334,6 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx); /* McBSP functional clock source changing function */ int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); -/* McBSP signal muxing API */ -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux); - /* Sidetone specific API */ int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 1046083e90a0..506159493a9d 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -516,21 +516,9 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, return -EBUSY; } - if (clk_id == OMAP_MCBSP_SYSCLK_CLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { - mcbsp->in_freq = freq; - regs->srgr2 &= ~CLKSM; - regs->pcr0 &= ~SCLKME; - } else if (cpu_class_is_omap1()) { - /* - * McBSP CLKR/FSR signal muxing functions are only available on - * OMAP2 or newer versions - */ - return -EINVAL; - } + mcbsp->in_freq = freq; + regs->srgr2 &= ~CLKSM; + regs->pcr0 &= ~SCLKME; switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: @@ -558,20 +546,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; break; - - - case OMAP_MCBSP_CLKR_SRC_CLKR: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); - break; - case OMAP_MCBSP_CLKR_SRC_CLKX: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); - break; - case OMAP_MCBSP_FSR_SRC_FSR: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); - break; - case OMAP_MCBSP_FSR_SRC_FSX: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); - break; default: err = -ENODEV; } diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index f877b16f19c9..baebcee30e30 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -32,10 +32,6 @@ enum omap_mcbsp_clksrg_clk { OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */ - OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */ - OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */ }; /* McBSP dividers */ From 8d3c09096500aa20702395b87c81a62ac9cbe3be Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:05 +0300 Subject: [PATCH 118/665] ASoC: omap-mcbsp: Remove unused defines NUM_LINKS is no longer in use by the code. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index baebcee30e30..ba8386a0d8dc 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -39,22 +39,6 @@ enum omap_mcbsp_div { OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ }; -#if defined(CONFIG_SOC_OMAP2420) -#define NUM_LINKS 2 -#endif -#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -#undef NUM_LINKS -#define NUM_LINKS 3 -#endif -#if defined(CONFIG_ARCH_OMAP4) -#undef NUM_LINKS -#define NUM_LINKS 4 -#endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430) -#undef NUM_LINKS -#define NUM_LINKS 5 -#endif - int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); #endif From dc26df52455348e06e4c34a2af2910d291369fe8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:06 +0300 Subject: [PATCH 119/665] ASoC: omap-mcbsp: Remove cpu_is_omap* checks from the code We can use the has_ccr flag to replace the cpu_is_omap* checks. This provides future proof implementation and we do not need to update the code if new OMAP revision starts to use the McBSP driver. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 506159493a9d..b9770eea28a0 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -398,12 +398,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; regs->spcr1 |= RINTM(3); - /* RFIG and XFIG are not defined in 34xx */ - if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { + /* RFIG and XFIG are not defined in 2430 and on OMAP3+ */ + if (!mcbsp->pdata->has_ccr) { regs->rcr2 |= RFIG; regs->xcr2 |= XFIG; } - if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { + + /* Configure XCCR/RCCR only for revisions which have ccr registers */ + if (mcbsp->pdata->has_ccr) { regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; } From e586e955aa47f9b4afe6e665798fd2cb074a90f4 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:07 +0300 Subject: [PATCH 120/665] ARM: OMAP2+: McBSP: Do not create legacy devices when booting with DT data Only create the devices in a legacy way if we do not have the DT data. Signed-off-by: Peter Ujfalusi Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/mcbsp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 660e00b3ef82..d57a3578bf03 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -113,7 +114,8 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) static int __init omap2_mcbsp_init(void) { - omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL); + if (!of_have_populated_dt()) + omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL); return 0; } From 11dd586421b3091007e6f084a9211f3baa66f9fc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:08 +0300 Subject: [PATCH 121/665] ASoC: omap-mcbsp: Add device tree bindings Device tree support for McBSP modules on OMAP2+ SoC. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/omap-mcbsp.txt | 45 +++++++++++++ sound/soc/omap/omap-mcbsp.c | 66 ++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/sound/omap-mcbsp.txt diff --git a/Documentation/devicetree/bindings/sound/omap-mcbsp.txt b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt new file mode 100644 index 000000000000..447cb131e909 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt @@ -0,0 +1,45 @@ +* Texas Instruments OMAP2+ McBSP module + +Required properties: +- compatible: "ti,omap2420-mcbsp" for McBSP on OMAP2420 + "ti,omap2430-mcbsp" for McBSP on OMAP2430 + "ti,omap3-mcbsp" for McBSP on OMAP3 + "ti,omap4-mcbsp" for McBSP on OMAP4 and newer SoC +- reg: Register location and size, for OMAP4+ as an array: + , + ; +- interrupts: Interrupt numbers for the McBSP port, as an array in case the + McBSP IP have more interrupt lines: + , + , + ; +- interrupt-parent: The parent interrupt controller +- ti,buffer-size: Size of the FIFO on the port (OMAP2430 and newer SoC) +- ti,hwmods: Name of the hwmod associated to the McBSP port + +Sidetone support for OMAP3 McBSP2 and 3 ports: +- sidetone { }: Within this section the following parameters are required: +- reg: Register location and size for the ST block +- interrupts: The interrupt number for the ST block +- interrupt-parent: The parent interrupt controller for the ST block + +Example: + +mcbsp2: mcbsp@49022000 { + compatible = "ti,omap3-mcbsp"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x49022000 0xff>; + interrupts = <0 17 0x4>, /* OCP compliant interrup */ + <0 62 0x4>, /* TX interrup */ + <0 63 0x4>; /* RX interrup */ + interrupt-parent = <&intc>; + ti,buffer-size = <1280>; + ti,hwmods = "mcbsp2"; + + sidetone { + reg = <0x49028000 0xff>; + interrupts = <0 4 0x4>; + interrupt-parent = <&intc>; + }; +}; diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index b9770eea28a0..2e1750e2ab31 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -737,13 +739,74 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); +static struct omap_mcbsp_platform_data omap2420_pdata = { + .reg_step = 4, + .reg_size = 2, +}; + +static struct omap_mcbsp_platform_data omap2430_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, +}; + +static struct omap_mcbsp_platform_data omap3_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, + .has_wakeup = true, +}; + +static struct omap_mcbsp_platform_data omap4_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, + .has_wakeup = true, +}; + +static const struct of_device_id omap_mcbsp_of_match[] = { + { + .compatible = "ti,omap2420-mcbsp", + .data = &omap2420_pdata, + }, + { + .compatible = "ti,omap2430-mcbsp", + .data = &omap2430_pdata, + }, + { + .compatible = "ti,omap3-mcbsp", + .data = &omap3_pdata, + }, + { + .compatible = "ti,omap4-mcbsp", + .data = &omap4_pdata, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match); + static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) { struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); struct omap_mcbsp *mcbsp; + const struct of_device_id *match; int ret; - if (!pdata) { + match = of_match_device(omap_mcbsp_of_match, &pdev->dev); + if (match) { + struct device_node *node = pdev->dev.of_node; + int buffer_size; + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct omap_mcbsp_platform_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + memcpy(pdata, match->data, sizeof(*pdata)); + if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size)) + pdata->buffer_size = buffer_size; + } else if (!pdata) { dev_err(&pdev->dev, "missing platform data.\n"); return -EINVAL; } @@ -785,6 +848,7 @@ static struct platform_driver asoc_mcbsp_driver = { .driver = { .name = "omap-mcbsp", .owner = THIS_MODULE, + .of_match_table = omap_mcbsp_of_match, }, .probe = asoc_mcbsp_probe, From b8101048f0f3cd281ed4c4901e38ae2bcfb32030 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 21 Aug 2012 17:33:56 +0300 Subject: [PATCH 122/665] ASoC: omap-mcbsp: Device tree binding documentation update To reflect the final devicetree node structure of McBSPs. The initial OMAP McBSP DT structure was not able to describe the IP (and it's versions) correctly. The main issue was the sidetone block of McBSP2/3 on OMAP3. With this change in the DT description the OS can get the needed information about the IP. The sidetone is still not supported when the Linux kernel is booted with DT since we still depend on hwmod to fill the resources. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/omap-mcbsp.txt | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/omap-mcbsp.txt b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt index 447cb131e909..17cce4490456 100644 --- a/Documentation/devicetree/bindings/sound/omap-mcbsp.txt +++ b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt @@ -8,38 +8,30 @@ Required properties: - reg: Register location and size, for OMAP4+ as an array: , ; +- reg-names: Array of strings associated with the address space - interrupts: Interrupt numbers for the McBSP port, as an array in case the McBSP IP have more interrupt lines: , , ; +- interrupt-names: Array of strings associated with the interrupt numbers - interrupt-parent: The parent interrupt controller - ti,buffer-size: Size of the FIFO on the port (OMAP2430 and newer SoC) - ti,hwmods: Name of the hwmod associated to the McBSP port -Sidetone support for OMAP3 McBSP2 and 3 ports: -- sidetone { }: Within this section the following parameters are required: -- reg: Register location and size for the ST block -- interrupts: The interrupt number for the ST block -- interrupt-parent: The parent interrupt controller for the ST block - Example: mcbsp2: mcbsp@49022000 { compatible = "ti,omap3-mcbsp"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x49022000 0xff>; - interrupts = <0 17 0x4>, /* OCP compliant interrup */ - <0 62 0x4>, /* TX interrup */ - <0 63 0x4>; /* RX interrup */ + reg = <0x49022000 0xff>, + <0x49028000 0xff>; + reg-names = "mpu", "sidetone"; + interrupts = <0 17 0x4>, /* OCP compliant interrupt */ + <0 62 0x4>, /* TX interrupt */ + <0 63 0x4>, /* RX interrupt */ + <0 4 0x4>; /* Sidetone */ + interrupt-names = "common", "tx", "rx", "sidetone"; interrupt-parent = <&intc>; ti,buffer-size = <1280>; ti,hwmods = "mcbsp2"; - - sidetone { - reg = <0x49028000 0xff>; - interrupts = <0 4 0x4>; - interrupt-parent = <&intc>; - }; }; From 9b04f350057863d1fad1ba071e09362a1da3503e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Aug 2012 20:48:29 +0000 Subject: [PATCH 123/665] ipv4: properly update pmtu Sylvain Munault reported following info : - TCP connection get "stuck" with data in send queue when doing "large" transfers ( like typing 'ps ax' on a ssh connection ) - Only happens on path where the PMTU is lower than the MTU of the interface - Is not present right after boot, it only appears 10-20min after boot or so. (and that's inside the _same_ TCP connection, it works fine at first and then in the same ssh session, it'll get stuck) - Definitely seems related to fragments somehow since I see a router sending ICMP message saying fragmentation is needed. - Exact same setup works fine with kernel 3.5.1 Problem happens when the 10 minutes (ip_rt_mtu_expires) expiration period is over. ip_rt_update_pmtu() calls dst_set_expires() to rearm a new expiration, but dst_set_expires() does nothing because dst.expires is already set. It seems we want to set the expires field to a new value, regardless of prior one. With help from Julian Anastasov. Reported-by: Sylvain Munaut Signed-off-by: Eric Dumazet CC: Julian Anastasov Tested-by: Sylvain Munaut Signed-off-by: David S. Miller --- net/ipv4/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index fd9ecb52c66b..8c8c748ebb28 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -956,7 +956,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, dst->obsolete = DST_OBSOLETE_KILL; } else { rt->rt_pmtu = mtu; - dst_set_expires(&rt->dst, ip_rt_mtu_expires); + rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires); } } From 5f42f7bc9638a0bc69dcb8b8b6da542b72113fc2 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 22 Aug 2012 00:26:15 +0000 Subject: [PATCH 124/665] stmmac: fix GMAC syn ID Erroneously the DWMAC_CORE_3_40 was set to 34 instead of 0x34. This can generate problems when run on old chips because the driver assumes that there are the extra 16 regs available for perfect filtering. Signed-off-by: Giuseppe Cavallaro Cc: Gianni Antoniazzi Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index f90fcb5f9573..b4c44a587f02 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -229,6 +229,6 @@ enum rtc_control { #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 /* Synopsys Core versions */ -#define DWMAC_CORE_3_40 34 +#define DWMAC_CORE_3_40 0x34 extern const struct stmmac_dma_ops dwmac1000_dma_ops; From a6b9650108003e994770209fb8efedf6e214dcf7 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 22 Aug 2012 00:26:16 +0000 Subject: [PATCH 125/665] stmmac: fix a typo in the macro used to mask the mmc irq This patch fixes the name of the macro used to mask the mmc interrupt: erroneously it was used: MMC_DEFAUL_MASK. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index c07cfe989f6e..0c74a702d461 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -33,7 +33,7 @@ #define MMC_TX_INTR 0x00000108 /* MMC TX Interrupt */ #define MMC_RX_INTR_MASK 0x0000010c /* MMC Interrupt Mask */ #define MMC_TX_INTR_MASK 0x00000110 /* MMC Interrupt Mask */ -#define MMC_DEFAUL_MASK 0xffffffff +#define MMC_DEFAULT_MASK 0xffffffff /* MMC TX counter registers */ @@ -147,8 +147,8 @@ void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode) /* To mask all all interrupts.*/ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr) { - writel(MMC_DEFAUL_MASK, ioaddr + MMC_RX_INTR_MASK); - writel(MMC_DEFAUL_MASK, ioaddr + MMC_TX_INTR_MASK); + writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK); + writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK); } /* This reads the MAC core counters (if actaully supported). From b70ad586162609141f0aa9eb34790f31a8954f89 Mon Sep 17 00:00:00 2001 From: "Xu, Anhua" Date: Mon, 13 Aug 2012 03:08:33 +0000 Subject: [PATCH 126/665] drm/i915: fix wrong order of parameters in port checking functions Wrong order of parameters passed-in when calling hdmi/adpa /lvds_pipe_enabled(), 2nd and 3rd parameters are reversed. This bug was indroduced by commit 1519b9956eb4b4180fa3f47c73341463cdcfaa37 Author: Keith Packard Date: Sat Aug 6 10:35:34 2011 -0700 drm/i915: Fix PCH port pipe select in CPT disable paths The reachable tag for this commit is v3.1-rc1-3-g1519b99 Signed-off-by: Anhua Xu Reviewed-by: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44876 Tested-by: Daniel Schroeder Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a69a3d0d3acf..2dfa6cf4886b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1384,7 +1384,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - WARN(hdmi_pipe_enabled(dev_priv, val, pipe), + WARN(hdmi_pipe_enabled(dev_priv, pipe, val), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); @@ -1404,13 +1404,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - WARN(adpa_pipe_enabled(dev_priv, val, pipe), + WARN(adpa_pipe_enabled(dev_priv, pipe, val), "PCH VGA enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); reg = PCH_LVDS; val = I915_READ(reg); - WARN(lvds_pipe_enabled(dev_priv, val, pipe), + WARN(lvds_pipe_enabled(dev_priv, pipe, val), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); @@ -1872,7 +1872,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - if (hdmi_pipe_enabled(dev_priv, val, pipe)) { + if (hdmi_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n", reg, pipe); I915_WRITE(reg, val & ~PORT_ENABLE); @@ -1894,12 +1894,12 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - if (adpa_pipe_enabled(dev_priv, val, pipe)) + if (adpa_pipe_enabled(dev_priv, pipe, val)) I915_WRITE(reg, val & ~ADPA_DAC_ENABLE); reg = PCH_LVDS; val = I915_READ(reg); - if (lvds_pipe_enabled(dev_priv, val, pipe)) { + if (lvds_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val); I915_WRITE(reg, val & ~LVDS_PORT_EN); POSTING_READ(reg); From 5ee369138d28c17305e1cdc662a62a2fc83d80d7 Mon Sep 17 00:00:00 2001 From: Vijay Purushothaman Date: Thu, 23 Aug 2012 12:08:57 +0530 Subject: [PATCH 127/665] drm/i915: fix color order for BGR formats on IVB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is already fixed for ILK and SNB in the below commit but somehow IVB is missed. commit ab2f9df10dd955f1fc0a8650e377588c98f1c029 Author: Jesse Barnes Date: Mon Feb 27 12:40:10 2012 -0800 drm/i915: fix color order for BGR formats on SNB Had the wrong bits and field definitions. Signed-off-by: Vijay Purushothaman Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index cc8df4de2d92..7644f31a3778 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -60,11 +60,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, switch (fb->pixel_format) { case DRM_FORMAT_XBGR8888: - sprctl |= SPRITE_FORMAT_RGBX888; + sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; pixel_size = 4; break; case DRM_FORMAT_XRGB8888: - sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; + sprctl |= SPRITE_FORMAT_RGBX888; pixel_size = 4; break; case DRM_FORMAT_YUYV: From e432964a3c5ce517fd93101ae3875172ee958b65 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 24 Jul 2012 03:00:24 +0200 Subject: [PATCH 128/665] fbcon: prevent possible buffer overflow. Signed-off-by: Paul Cercueil Signed-off-by: Florian Tobias Schandinat --- drivers/video/console/fbcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 88e92041d8f0..fdefa8fd72c4 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -449,7 +449,7 @@ static int __init fb_console_setup(char *this_opt) while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) - strcpy(fontname, options + 5); + strlcpy(fontname, options + 5, sizeof(fontname)); if (!strncmp(options, "scrollback:", 11)) { options += 11; From 72caa5fb948ef818fe1332848e9c61b10687ce7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= Date: Mon, 30 Jul 2012 21:09:49 +0200 Subject: [PATCH 129/665] fbcon: Fix bit_putcs() call to kmalloc(s, GFP_KERNEL) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to kmalloc(,GFP_ATOMIC) in bit_putcs to fix below trace: [ 9.771812] BUG: sleeping function called from invalid context at /usr/src/linux-git/mm/slub.c:943 [ 9.771814] in_atomic(): 1, irqs_disabled(): 1, pid: 1063, name: mount [ 9.771818] Pid: 1063, comm: mount Not tainted 3.5.0-jupiter-00003-g8d858b1-dirty #2 [ 9.771819] Call Trace: [ 9.771838] [] __might_sleep+0xcb/0xe0 [ 9.771844] [] __kmalloc+0xb4/0x1c0 [ 9.771851] [] ? queue_work+0x1a/0x30 [ 9.771854] [] ? queue_delayed_work+0xf/0x30 [ 9.771862] [] ? bit_putcs+0xf2/0x3e0 [ 9.771865] [] ? schedule_delayed_work+0x11/0x20 [ 9.771868] [] bit_putcs+0xf2/0x3e0 [ 9.771875] [] ? get_color.clone.14+0x28/0x100 [ 9.771878] [] fbcon_putcs+0x11f/0x130 [ 9.771882] [] ? bit_clear+0xe0/0xe0 [ 9.771885] [] fbcon_redraw.clone.21+0x11d/0x160 [ 9.771889] [] fbcon_scroll+0x79d/0xe10 [ 9.771892] [] ? get_color.clone.14+0x28/0x100 [ 9.771897] [] scrup+0x64/0xd0 [ 9.771900] [] lf+0x2b/0x60 [ 9.771903] [] vt_console_print+0x1d5/0x2f0 [ 9.771907] [] ? register_vt_notifier+0x20/0x20 [ 9.771913] [] call_console_drivers.clone.5+0xa5/0xc0 [ 9.771916] [] console_unlock+0x2fe/0x3c0 [ 9.771920] [] vprintk_emit+0x2e6/0x300 [ 9.771924] [] printk+0x38/0x3a [ 9.771931] [] reiserfs_remount+0x2ae/0x3e0 [ 9.771934] [] ? reiserfs_fill_super+0xb00/0xb00 [ 9.771939] [] do_remount_sb+0xab/0x150 [ 9.771943] [] ? ns_capable+0x46/0x70 [ 9.771948] [] do_mount+0x20c/0x6b0 [ 9.771955] [] ? strndup_user+0x34/0x50 [ 9.771958] [] sys_mount+0x6c/0xa0 [ 9.771964] [] sysenter_do_call+0x12/0x26 According to comment in bit_putcs() that kammloc() call only happens when fbcon is drawing to a monochrome framebuffer (which is my case with hid-picolcd). Signed-off-by: Bruno Prémont Signed-off-by: Florian Tobias Schandinat --- drivers/video/console/bitblit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 28b1a834906b..61b182bf32a2 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -162,7 +162,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, image.depth = 1; if (attribute) { - buf = kmalloc(cellsize, GFP_KERNEL); + buf = kmalloc(cellsize, GFP_ATOMIC); if (!buf) return; } From 01817d194a5c078696ac4a31b5d8b99a6a9e40c7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 4 Aug 2012 14:00:30 +0200 Subject: [PATCH 130/665] drivers/video/auo_k190x.c: drop kfree of devm_kzalloc's data Using kfree to free data allocated with devm_kzalloc causes double frees. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x; @@ x = devm_kzalloc(...) ... ?-kfree(x); // Signed-off-by: Julia Lawall Signed-off-by: Florian Tobias Schandinat --- drivers/video/auo_k190x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c index 77da6a2f43dc..c03ecdd31e4c 100644 --- a/drivers/video/auo_k190x.c +++ b/drivers/video/auo_k190x.c @@ -987,7 +987,6 @@ err_regfb: fb_dealloc_cmap(&info->cmap); err_cmap: fb_deferred_io_cleanup(info); - kfree(info->fbdefio); err_defio: vfree((void *)info->screen_base); err_irq: @@ -1022,7 +1021,6 @@ int __devexit auok190x_common_remove(struct platform_device *pdev) fb_dealloc_cmap(&info->cmap); fb_deferred_io_cleanup(info); - kfree(info->fbdefio); vfree((void *)info->screen_base); From 25682362564fa0c950d9afe798def2ec9c3676a2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 18 Aug 2012 18:55:41 +0300 Subject: [PATCH 131/665] video: mb862xxfb: prevent divide by zero bug Do a sanity check on these before using them as divisors. Signed-off-by: Dan Carpenter Acked-by: Anatolij Gustschin Signed-off-by: Florian Tobias Schandinat --- drivers/video/mb862xx/mb862xxfbdrv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index 00ce1f34b496..57d940be5f3d 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c @@ -328,6 +328,8 @@ static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd, case MB862XX_L1_SET_CFG: if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg))) return -EFAULT; + if (l1_cfg->dh == 0 || l1_cfg->dw == 0) + return -EINVAL; if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) { /* downscaling */ outreg(cap, GC_CAP_CSC, From 35d678664873041026171b4b5e1cec49299e33a0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 21 Aug 2012 09:09:47 +0300 Subject: [PATCH 132/665] OMAPDSS: Fix SDI PLL locking Commit f476ae9dab3234532d41d36beb4ba7be838fa786 (OMAPDSS: APPLY: Remove DISPC writes to manager's lcd parameters in interface) broke the SDI output, as it causes the SDI PLL locking to fail. LCLK and PCLK divisors are located in shadow registers, and we normally write them to DISPC registers when enabling the output. However, SDI uses pck-free as source clock for its PLL, and pck-free is affected by the divisors. And as we need the PLL before enabling the output, we need to write the divisors early. It seems just writing to the DISPC register is enough, and we don't need to care about the shadow register mechanism for pck-free. The exact reason for this is unknown. Signed-off-by: Tomi Valkeinen Reported-by: Aaro Koskinen Signed-off-by: Florian Tobias Schandinat --- drivers/video/omap2/dss/sdi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 5d31699fbd3c..f43bfe17b3b6 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -105,6 +105,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) sdi_config_lcd_manager(dssdev); + /* + * LCLK and PCLK divisors are located in shadow registers, and we + * normally write them to DISPC registers when enabling the output. + * However, SDI uses pck-free as source clock for its PLL, and pck-free + * is affected by the divisors. And as we need the PLL before enabling + * the output, we need to write the divisors early. + * + * It seems just writing to the DISPC register is enough, and we don't + * need to care about the shadow register mechanism for pck-free. The + * exact reason for this is unknown. + */ + dispc_mgr_set_clock_div(dssdev->manager->id, + &sdi.mgr_config.clock_info); + dss_sdi_init(dssdev->phy.sdi.datapairs); r = dss_sdi_enable(); if (r) From c1c52848cef52e157468b8879fc3cae23b6f3a99 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 21 Aug 2012 09:09:48 +0300 Subject: [PATCH 133/665] OMAPFB: fix framebuffer console colors omapfb does not currently set pseudo palette correctly for color depths above 16bpp, making red text invisible, command like echo -e '\e[0;31mRED' > /dev/tty1 will display nothing on framebuffer console in 24bpp mode. This is because temporary variable is declared incorrectly, fix it. Signed-off-by: Grazvydas Ignotas Cc: stable@vger.kernel.org # v3.x Signed-off-by: Tomi Valkeinen Signed-off-by: Florian Tobias Schandinat --- drivers/video/omap2/omapfb/omapfb-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 08ec1a7103f2..fc671d3d8004 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1192,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, break; if (regno < 16) { - u16 pal; + u32 pal; pal = ((red >> (16 - var->red.length)) << var->red.offset) | ((green >> (16 - var->green.length)) << From 85ebea12f59e3341049a9c17edcb73fcf21043db Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 14 Aug 2012 11:19:21 +0200 Subject: [PATCH 134/665] ARM: at91: fix system timer irq issue due to sparse irq support AT91_ID_SYS as virq is incorrect because of spare irq support which introduces NR_IRQS_LEGACY offset. Signed-off-by: Ludovic Desroches Tested-by: Joachim Eastwood Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91rm9200_time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index 104ca40d8d18..aaa443b48c91 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -197,7 +197,7 @@ void __init at91rm9200_timer_init(void) at91_st_read(AT91_ST_SR); /* Make IRQs happen for the system timer */ - setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); + setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq); /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used * directly for the clocksource and all clockevents, after adjusting From e402af6caa02f12ad213af2e22aa8a32970f99b0 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 14 Aug 2012 11:19:22 +0200 Subject: [PATCH 135/665] ARM: at91: fix rtc-at91sam9 irq issue due to sparse irq support AT91_ID_SYS as virq is incorrect because of spare irq support which introduces NR_IRQS_LEGACY offset. It modifies rtc-at91sam9 driver in order to get irq from resources. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91sam9260_devices.c | 6 +++++- arch/arm/mach-at91/at91sam9261_devices.c | 6 +++++- arch/arm/mach-at91/at91sam9263_devices.c | 10 ++++++++-- arch/arm/mach-at91/at91sam9g45_devices.c | 6 +++++- arch/arm/mach-at91/at91sam9rl_devices.c | 6 +++++- drivers/rtc/rtc-at91sam9.c | 22 +++++++++++++++------- 6 files changed, 43 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 7b9c2ba396ed..bce572a530ef 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -726,6 +726,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, }, }; @@ -744,10 +746,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9260_rtt_device.num_resources = 2; + at91sam9260_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9260_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 8df5c1bdff92..bc2590d712d0 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -609,6 +609,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -626,10 +628,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9261_rtt_device.num_resources = 2; + at91sam9261_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9261_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index eb6bbf86fb9f..9b6ca734f1a9 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -990,6 +990,8 @@ static struct resource rtt0_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -1006,6 +1008,8 @@ static struct resource rtt1_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -1027,14 +1031,14 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed only for the chosen RTT: * GPBR will serve as the storage for RTC time offset */ - at91sam9263_rtt0_device.num_resources = 2; + at91sam9263_rtt0_device.num_resources = 3; at91sam9263_rtt1_device.num_resources = 1; pdev = &at91sam9263_rtt0_device; r = rtt0_resources; break; case 1: at91sam9263_rtt0_device.num_resources = 1; - at91sam9263_rtt1_device.num_resources = 2; + at91sam9263_rtt1_device.num_resources = 3; pdev = &at91sam9263_rtt1_device; r = rtt1_resources; break; @@ -1047,6 +1051,8 @@ static void __init at91_add_device_rtt_rtc(void) pdev->name = "rtc-at91sam9"; r[1].start = AT91SAM9263_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; r[1].end = r[1].start + 3; + r[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + r[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 06073996a382..1b47319ca00b 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -1293,6 +1293,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -1310,10 +1312,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9g45_rtt_device.num_resources = 2; + at91sam9g45_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9G45_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index f09fff932172..b3d365dadef5 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -688,6 +688,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -705,10 +707,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9rl_rtt_device.num_resources = 2; + at91sam9rl_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9RL_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 831868904e02..1dd61f402b04 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -58,6 +58,7 @@ struct sam9_rtc { struct rtc_device *rtcdev; u32 imr; void __iomem *gpbr; + int irq; }; #define rtt_readl(rtc, field) \ @@ -292,7 +293,7 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) { struct resource *r, *r_gpbr; struct sam9_rtc *rtc; - int ret; + int ret, irq; u32 mr; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -302,10 +303,18 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) return -ENODEV; } + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get interrupt resource\n"); + return irq; + } + rtc = kzalloc(sizeof *rtc, GFP_KERNEL); if (!rtc) return -ENOMEM; + rtc->irq = irq; + /* platform setup code should have handled this; sigh */ if (!device_can_wakeup(&pdev->dev)) device_init_wakeup(&pdev->dev, 1); @@ -345,11 +354,10 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) } /* register irq handler after we know what name we'll use */ - ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, - IRQF_SHARED, + ret = request_irq(rtc->irq, at91_rtc_interrupt, IRQF_SHARED, dev_name(&rtc->rtcdev->dev), rtc); if (ret) { - dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); + dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq); rtc_device_unregister(rtc->rtcdev); goto fail_register; } @@ -386,7 +394,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev) /* disable all interrupts */ rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); - free_irq(AT91_ID_SYS, rtc); + free_irq(rtc->irq, rtc); rtc_device_unregister(rtc->rtcdev); @@ -423,7 +431,7 @@ static int at91_rtc_suspend(struct platform_device *pdev, rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); if (rtc->imr) { if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) { - enable_irq_wake(AT91_ID_SYS); + enable_irq_wake(rtc->irq); /* don't let RTTINC cause wakeups */ if (mr & AT91_RTT_RTTINCIEN) rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); @@ -441,7 +449,7 @@ static int at91_rtc_resume(struct platform_device *pdev) if (rtc->imr) { if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(AT91_ID_SYS); + disable_irq_wake(rtc->irq); mr = rtt_readl(rtc, MR); rtt_writel(rtc, MR, mr | rtc->imr); } From 2ed1f58900280f79485bbc15f781687bd9584675 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 9 Jul 2012 21:06:25 +0200 Subject: [PATCH 136/665] ARM: at91/clock: fix PLLA overclock warning Fix PLLA overclock warning in relation with datasheet numbers. Add new > 240 MHz and > 210 MHz SoC categories. Reported-by: Jiri Prchal Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/clock.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index de2ec6b8fea7..188c82971ebd 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -63,6 +63,12 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); #define cpu_has_300M_plla() (cpu_is_at91sam9g10()) +#define cpu_has_240M_plla() (cpu_is_at91sam9261() \ + || cpu_is_at91sam9263() \ + || cpu_is_at91sam9rl()) + +#define cpu_has_210M_plla() (cpu_is_at91sam9260()) + #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ @@ -706,6 +712,12 @@ static int __init at91_pmc_init(unsigned long main_clock) } else if (cpu_has_800M_plla()) { if (plla.rate_hz > 800000000) pll_overclock = true; + } else if (cpu_has_240M_plla()) { + if (plla.rate_hz > 240000000) + pll_overclock = true; + } else if (cpu_has_210M_plla()) { + if (plla.rate_hz > 210000000) + pll_overclock = true; } else { if (plla.rate_hz > 209000000) pll_overclock = true; From 9e0255dd035348953e23161b7158b2ce0ddc182e Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Fri, 17 Aug 2012 16:23:56 +0800 Subject: [PATCH 137/665] ARM: at91/dts: remove partial parameter in at91sam9g25ek.dts Remove the malformed "mem=" bootargs parameter in at91sam9g25ek.dts Signed-off-by: Bo Shen Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91sam9g25ek.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts index 7829a4d0cb22..96514c134e54 100644 --- a/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/arch/arm/boot/dts/at91sam9g25ek.dts @@ -15,7 +15,7 @@ compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; chosen { - bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; + bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; }; ahb { From eda21d37eb1e7d065d0427679d0947da805ad35d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 23 Aug 2012 09:35:01 +0300 Subject: [PATCH 138/665] ARM: OMAP2+: twl-common: Fix compile time error when omap-twl4030 audio is not enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: CC arch/arm/mach-omap2/twl-common.o arch/arm/mach-omap2/twl-common.c:562: error: conflicting types for ‘omap_twl4030_audio_init’ arch/arm/mach-omap2/twl-common.h:62: error: previous declaration of ‘omap_twl4030_audio_init’ was here make[1]: *** [arch/arm/mach-omap2/twl-common.o] Error 1 make: *** [arch/arm/mach-omap2] Error 2 When building the kernel with !SND_OMAP_SOC_OMAP_TWL4030 Reported-by: Brian Austin Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- arch/arm/mach-omap2/twl-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 0606f238a247..5d142facb0e6 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -559,7 +559,7 @@ void __init omap_twl4030_audio_init(char *card_name) } #else /* SOC_OMAP_TWL4030 */ -void __init omap_twl4030_audio_init(char *card_name, int codec_sysclk) +void __init omap_twl4030_audio_init(char *card_name) { return; } From a0e35322910555e20e9eced3f050a76c7b3a1f92 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 16 Aug 2012 15:50:10 +0800 Subject: [PATCH 139/665] mfd: lpc_ich: Fix a 3.5 kernel regression for iTCO_wdt driver There are many reports (including 2 of my machines) that iTCO_wdt watchdog driver fails to be initialized in 3.5 kernel with error message like: [ 5.265175] ACPI Warning: 0x00001060-0x0000107f SystemIO conflicts with Region \_SB_.PCI0.LPCB.TCOI 1 (20120320/utaddress-251) [ 5.265192] ACPI: If an ACPI driver is available for this device, you should use it instead of the native driver [ 5.265206] lpc_ich: Resource conflict(s) found affecting iTCO_wdt The root cause the iTCO_wdt driver in 3.4 probes the HW IO resource from LPC's PCI config space, while in 3.5 kernel it relies on lpc_ich driver for the probe, which adds a new acpi_check_resource_conflict() check, and give up the probe if there is any conflict with ACPI. Fix it by removing all the checks for iTCO_wdt to keep the same behavior as 3.4 kernel. https://bugzilla.kernel.org/show_bug.cgi?id=44991 Actually the same check could be removed for the gpio-ich in lpc_ich.c, but I'm not sure if it will cause problems. Signed-off-by: Feng Tang Cc: Aaron Sierra Cc: Wim Van Sebroeck Cc: Len Brown Cc: Bob Moore Signed-off-by: Samuel Ortiz --- drivers/mfd/lpc_ich.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 027cc8f86132..a05fdfc2ebcf 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -765,7 +765,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, u32 base_addr_cfg; u32 base_addr; int ret; - bool acpi_conflict = false; struct resource *res; /* Setup power management base register */ @@ -780,20 +779,11 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_io_res(ICH_RES_IO_TCO); res->start = base_addr + ACPIBASE_TCO_OFF; res->end = base_addr + ACPIBASE_TCO_END; - ret = acpi_check_resource_conflict(res); - if (ret) { - acpi_conflict = true; - goto wdt_done; - } res = wdt_io_res(ICH_RES_IO_SMI); res->start = base_addr + ACPIBASE_SMI_OFF; res->end = base_addr + ACPIBASE_SMI_END; - ret = acpi_check_resource_conflict(res); - if (ret) { - acpi_conflict = true; - goto wdt_done; - } + lpc_ich_enable_acpi_space(dev); /* @@ -813,11 +803,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_mem_res(ICH_RES_MEM_GCS); res->start = base_addr + ACPIBASE_GCS_OFF; res->end = base_addr + ACPIBASE_GCS_END; - ret = acpi_check_resource_conflict(res); - if (ret) { - acpi_conflict = true; - goto wdt_done; - } } lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); @@ -825,9 +810,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, 1, NULL, 0); wdt_done: - if (acpi_conflict) - pr_warn("Resource conflict(s) found affecting %s\n", - lpc_ich_cells[LPC_WDT].name); return ret; } From 52ca1138fa55bf6f46a5e02a2c1088756a5c8f2e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 15:50:45 +0100 Subject: [PATCH 140/665] ASoC: wm8994: Update for new WM1811 variants There are some new WM1811 variants distinguished by both revision and cust_id which need slightly different handling. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b74df52d2820..890b582b40f3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3823,14 +3823,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8994->hubs.no_cache_dac_hp_direct = true; wm8994->fll_byp = true; - switch (wm8994->revision) { + switch (control->cust_id) { case 0: - case 1: case 2: - case 3: wm8994->hubs.dcs_codes_l = -9; wm8994->hubs.dcs_codes_r = -7; break; + case 1: + case 3: + wm8994->hubs.dcs_codes_l = -8; + wm8994->hubs.dcs_codes_r = -7; + break; default: break; } @@ -3919,7 +3922,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) switch (control->type) { case WM1811: - if (wm8994->revision > 1) { + if (control->cust_id > 1 || wm8994->revision > 1) { ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm1811_jackdet_irq, "JACKDET", From e3523e01869da20fdd12ffd19ae1df7bf492650e Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Thu, 23 Aug 2012 15:59:56 +0100 Subject: [PATCH 141/665] ASoC: wm0010: Add initial wm0010 DSP driver The WM0010 is a compact digital signal processor that has been highly optimised for low-power audio applications. Extensive memory resources and core optimisation allow the device to manage all audio processing algorithms efficiently and autonomously, while the host processor sleeps or performs other tasks. Signed-off-by: Dimitris Papastamos Signed-off-by: Mark Brown --- include/sound/wm0010.h | 27 ++ sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm0010.c | 930 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 963 insertions(+) create mode 100644 include/sound/wm0010.h create mode 100644 sound/soc/codecs/wm0010.c diff --git a/include/sound/wm0010.h b/include/sound/wm0010.h new file mode 100644 index 000000000000..3261e90815af --- /dev/null +++ b/include/sound/wm0010.h @@ -0,0 +1,27 @@ +/* + * wm0010.h -- Platform data for WM0010 DSP Driver + * + * Copyright 2012 Wolfson Microelectronics PLC. + * + * Author: Dimitris Papastamos + * + * 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. + */ + +#ifndef WM0010_PDATA_H +#define WM0010_PDATA_H + +struct wm0010_pdata { + int gpio_reset; + + /* Set if there is an inverter between the GPIO controlling + * the reset signal and the device. + */ + int reset_active_high; + int irq_flags; +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e8594aeb9..3684255e5fba 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WL1273 if MFD_WL1273_CORE + select SND_SOC_WM0010 if SPI_MASTER select SND_SOC_WM1250_EV1 if I2C select SND_SOC_WM2000 if I2C select SND_SOC_WM2200 if I2C @@ -326,6 +327,9 @@ config SND_SOC_UDA1380 config SND_SOC_WL1273 tristate +config SND_SOC_WM0010 + tristate + config SND_SOC_WM1250_EV1 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb59c68..ca508b251df7 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -61,6 +61,7 @@ snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wl1273-objs := wl1273.o +snd-soc-wm0010-objs := wm0010.o snd-soc-wm1250-ev1-objs := wm1250-ev1.o snd-soc-wm2000-objs := wm2000.o snd-soc-wm2200-objs := wm2200.o @@ -177,6 +178,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o +obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c new file mode 100644 index 000000000000..8e0b6d6bffaf --- /dev/null +++ b/sound/soc/codecs/wm0010.c @@ -0,0 +1,930 @@ +/* + * wm0010.c -- WM0010 DSP Driver + * + * Copyright 2012 Wolfson Microelectronics PLC. + * + * Authors: Mark Brown + * Dimitris Papastamos + * Scott Ling + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DEVICE_ID_WM0010 10 + +enum dfw_cmd { + DFW_CMD_FUSE = 0x01, + DFW_CMD_CODE_HDR, + DFW_CMD_CODE_DATA, + DFW_CMD_PLL, + DFW_CMD_INFO = 0xff +}; + +struct dfw_binrec { + u8 command; + u32 length:24; + u32 address; + uint8_t data[0]; +} __packed; + +struct dfw_pllrec { + u8 command; + u32 length:24; + u32 address; + u32 clkctrl1; + u32 clkctrl2; + u32 clkctrl3; + u32 ldetctrl; + u32 uart_div; + u32 spi_div; +} __packed; + +static struct pll_clock_map { + int max_sysclk; + int max_pll_spi_speed; + u32 pll_clkctrl1; +} pll_clock_map[] = { /* Dividers */ + { 22000000, 26000000, 0x00201f11 }, /* 2,32,2 */ + { 18000000, 26000000, 0x00203f21 }, /* 2,64,4 */ + { 14000000, 26000000, 0x00202620 }, /* 1,39,4 */ + { 10000000, 22000000, 0x00203120 }, /* 1,50,4 */ + { 6500000, 22000000, 0x00204520 }, /* 1,70,4 */ + { 5500000, 22000000, 0x00103f10 }, /* 1,64,2 */ +}; + +enum wm0010_state { + WM0010_POWER_OFF, + WM0010_OUT_OF_RESET, + WM0010_BOOTROM, + WM0010_STAGE2, + WM0010_FIRMWARE, +}; + +struct wm0010_priv { + struct snd_soc_codec *codec; + + struct mutex lock; + struct device *dev; + + struct wm0010_pdata pdata; + + int gpio_reset; + int gpio_reset_value; + + struct regulator_bulk_data core_supplies[2]; + struct regulator *dbvdd; + + int sysclk; + + enum wm0010_state state; + bool boot_failed; + int boot_done; + bool ready; + bool pll_running; + int max_spi_freq; + int board_max_spi_speed; + u32 pll_clkctrl1; + + spinlock_t irq_lock; + int irq; + + struct completion boot_completion; +}; + +struct wm0010_spi_msg { + struct spi_message m; + struct spi_transfer t; + u8 *tx_buf; + u8 *rx_buf; + size_t len; +}; + +static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { + { "SDI2 Playback", NULL, "SDI1 Playback" }, +}; + +static const char *wm0010_state_to_str(enum wm0010_state state) +{ + const char *state_to_str[] = { + "Power off", + "Out of reset", + "Bootrom", + "Stage2", + "Firmware" + }; + + if (state < 0 || state >= ARRAY_SIZE(state_to_str)) + return "null"; + return state_to_str[state]; +} + +/* Called with wm0010->lock held */ +static void wm0010_halt(struct snd_soc_codec *codec) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + unsigned long flags; + enum wm0010_state state; + + /* Fetch the wm0010 state */ + spin_lock_irqsave(&wm0010->irq_lock, flags); + state = wm0010->state; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + switch (state) { + case WM0010_POWER_OFF: + /* If there's nothing to do, bail out */ + return; + case WM0010_OUT_OF_RESET: + case WM0010_BOOTROM: + case WM0010_STAGE2: + case WM0010_FIRMWARE: + /* Remember to put chip back into reset */ + gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); + /* Disable the regulators */ + regulator_disable(wm0010->dbvdd); + regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); + break; + } + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_POWER_OFF; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); +} + +struct wm0010_boot_xfer { + struct list_head list; + struct snd_soc_codec *codec; + struct completion *done; + struct spi_message m; + struct spi_transfer t; +}; + +/* Called with wm0010->lock held */ +static void wm0010_mark_boot_failure(struct wm0010_priv *wm0010) +{ + enum wm0010_state state; + unsigned long flags; + + spin_lock_irqsave(&wm0010->irq_lock, flags); + state = wm0010->state; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + dev_err(wm0010->dev, "Failed to transition from `%s' state to `%s' state\n", + wm0010_state_to_str(state), wm0010_state_to_str(state + 1)); + + wm0010->boot_failed = true; +} + +static void wm0010_boot_xfer_complete(void *data) +{ + struct wm0010_boot_xfer *xfer = data; + struct snd_soc_codec *codec = xfer->codec; + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + u32 *out32 = xfer->t.rx_buf; + int i; + + if (xfer->m.status != 0) { + dev_err(codec->dev, "SPI transfer failed: %d\n", + xfer->m.status); + wm0010_mark_boot_failure(wm0010); + if (xfer->done) + complete(xfer->done); + return; + } + + for (i = 0; i < xfer->t.len / 4; i++) { + dev_dbg(codec->dev, "%d: %04x\n", i, out32[i]); + + switch (be32_to_cpu(out32[i])) { + case 0xe0e0e0e0: + dev_err(codec->dev, + "%d: ROM error reported in stage 2\n", i); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x55555555: + if (wm0010->boot_done == 0) + break; + dev_err(codec->dev, + "%d: ROM bootloader running in stage 2\n", i); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0000: + dev_dbg(codec->dev, "Stage2 loader running\n"); + break; + + case 0x0fed0007: + dev_dbg(codec->dev, "CODE_HDR packet received\n"); + break; + + case 0x0fed0008: + dev_dbg(codec->dev, "CODE_DATA packet received\n"); + break; + + case 0x0fed0009: + dev_dbg(codec->dev, "Download complete\n"); + break; + + case 0x0fed000c: + dev_dbg(codec->dev, "Application start\n"); + break; + + case 0x0fed000e: + dev_dbg(codec->dev, "PLL packet received\n"); + wm0010->pll_running = true; + break; + + case 0x0fed0025: + dev_err(codec->dev, "Device reports image too long\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed002c: + dev_err(codec->dev, "Device reports bad SPI packet\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0031: + dev_err(codec->dev, "Device reports SPI read overflow\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0032: + dev_err(codec->dev, "Device reports SPI underclock\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0033: + dev_err(codec->dev, "Device reports bad header packet\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0034: + dev_err(codec->dev, "Device reports invalid packet type\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0035: + dev_err(codec->dev, "Device reports data before header error\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0038: + dev_err(codec->dev, "Device reports invalid PLL packet\n"); + break; + + case 0x0fed003a: + dev_err(codec->dev, "Device reports packet alignment error\n"); + wm0010_mark_boot_failure(wm0010); + break; + + default: + dev_err(codec->dev, "Unrecognised return 0x%x\n", + be32_to_cpu(out32[i])); + wm0010_mark_boot_failure(wm0010); + break; + } + + if (wm0010->boot_failed) + break; + } + + wm0010->boot_done++; + if (xfer->done) + complete(xfer->done); +} + +static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len) +{ + int i; + + for (i = 0; i < len / 8; i++) + data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); +} + +static int wm0010_boot(struct snd_soc_codec *codec) +{ + struct spi_device *spi = to_spi_device(codec->dev); + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + unsigned long flags; + struct list_head xfer_list; + struct wm0010_boot_xfer *xfer; + int ret; + struct completion done; + const struct firmware *fw; + const struct dfw_binrec *rec; + struct spi_message m; + struct spi_transfer t; + struct dfw_pllrec pll_rec; + u32 *img, *p; + u64 *img_swap; + u8 *out; + u32 len, offset; + int i; + + spin_lock_irqsave(&wm0010->irq_lock, flags); + if (wm0010->state != WM0010_POWER_OFF) + dev_warn(wm0010->dev, "DSP already powered up!\n"); + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + if (wm0010->sysclk > 26000000) { + dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); + ret = -ECANCELED; + goto err; + } + + INIT_LIST_HEAD(&xfer_list); + + mutex_lock(&wm0010->lock); + wm0010->pll_running = false; + + dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); + + ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); + if (ret != 0) { + dev_err(&spi->dev, "Failed to enable core supplies: %d\n", + ret); + mutex_unlock(&wm0010->lock); + goto err; + } + + ret = regulator_enable(wm0010->dbvdd); + if (ret != 0) { + dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); + goto err_core; + } + + /* Release reset */ + gpio_set_value(wm0010->gpio_reset, !wm0010->gpio_reset_value); + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_OUT_OF_RESET; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + /* First the bootloader */ + ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); + if (ret != 0) { + dev_err(codec->dev, "Failed to request stage2 loader: %d\n", + ret); + goto abort; + } + + if (!wait_for_completion_timeout(&wm0010->boot_completion, + msecs_to_jiffies(10))) + dev_err(codec->dev, "Failed to get interrupt from DSP\n"); + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_BOOTROM; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + dev_dbg(codec->dev, "Downloading %d byte stage 2 loader\n", fw->size); + + /* Copy to local buffer first as vmalloc causes problems for dma */ + img = kzalloc(fw->size, GFP_KERNEL); + if (!img) { + dev_err(codec->dev, "Failed to allocate image buffer\n"); + goto abort; + } + + out = kzalloc(fw->size, GFP_KERNEL); + if (!out) { + dev_err(codec->dev, "Failed to allocate output buffer\n"); + goto abort; + } + + memcpy(img, &fw->data[0], fw->size); + + spi_message_init(&m); + memset(&t, 0, sizeof(t)); + t.rx_buf = out; + t.tx_buf = img; + t.len = fw->size; + t.bits_per_word = 8; + t.speed_hz = wm0010->sysclk / 10; + spi_message_add_tail(&t, &m); + + dev_dbg(codec->dev, "Starting initial download at %dHz\n", + t.speed_hz); + + ret = spi_sync(spi, &m); + if (ret != 0) { + dev_err(codec->dev, "Initial download failed: %d\n", ret); + goto abort; + } + + /* Look for errors from the boot ROM */ + for (i = 0; i < fw->size; i++) { + if (out[i] != 0x55) { + ret = -EBUSY; + dev_err(codec->dev, "Boot ROM error: %x in %d\n", + out[i], i); + wm0010_mark_boot_failure(wm0010); + goto abort; + } + } + + release_firmware(fw); + kfree(img); + kfree(out); + + if (!wait_for_completion_timeout(&wm0010->boot_completion, + msecs_to_jiffies(10))) + dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_STAGE2; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + /* Only initialise PLL if max_spi_freq initialised */ + if (wm0010->max_spi_freq) { + + /* Initialise a PLL record */ + memset(&pll_rec, 0, sizeof(pll_rec)); + pll_rec.command = DFW_CMD_PLL; + pll_rec.length = (sizeof(pll_rec) - 8); + + /* On wm0010 only the CLKCTRL1 value is used */ + pll_rec.clkctrl1 = wm0010->pll_clkctrl1; + + len = pll_rec.length + 8; + out = kzalloc(len, GFP_KERNEL); + if (!out) { + dev_err(codec->dev, + "Failed to allocate RX buffer\n"); + goto abort; + } + + img_swap = kzalloc(len, GFP_KERNEL); + if (!img_swap) { + dev_err(codec->dev, + "Failed to allocate image buffer\n"); + goto abort; + } + + /* We need to re-order for 0010 */ + byte_swap_64((u64 *)&pll_rec, img_swap, len); + + spi_message_init(&m); + memset(&t, 0, sizeof(t)); + t.rx_buf = out; + t.tx_buf = img_swap; + t.len = len; + t.bits_per_word = 8; + t.speed_hz = wm0010->sysclk / 6; + spi_message_add_tail(&t, &m); + + ret = spi_sync(spi, &m); + if (ret != 0) { + dev_err(codec->dev, "First PLL write failed: %d\n", ret); + goto abort; + } + + /* Use a second send of the message to get the return status */ + ret = spi_sync(spi, &m); + if (ret != 0) { + dev_err(codec->dev, "Second PLL write failed: %d\n", ret); + goto abort; + } + + p = (u32 *)out; + + /* Look for PLL active code from the DSP */ + for (i = 0; i < len / 4; i++) { + if (*p == 0x0e00ed0f) { + dev_dbg(codec->dev, "PLL packet received\n"); + wm0010->pll_running = true; + break; + } + p++; + } + + kfree(img_swap); + kfree(out); + } else + dev_dbg(codec->dev, "Not enabling DSP PLL."); + + ret = request_firmware(&fw, "wm0010.dfw", codec->dev); + if (ret != 0) { + dev_err(codec->dev, "Failed to request application: %d\n", + ret); + goto abort; + } + + rec = (const struct dfw_binrec *)fw->data; + offset = 0; + wm0010->boot_done = 0; + wm0010->boot_failed = false; + BUG_ON(!list_empty(&xfer_list)); + init_completion(&done); + + /* First record should be INFO */ + if (rec->command != DFW_CMD_INFO) { + dev_err(codec->dev, "First record not INFO\r\n"); + goto abort; + } + + /* Check it's a 0010 file */ + if (rec->data[0] != DEVICE_ID_WM0010) { + dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); + goto abort; + } + + /* Skip the info record as we don't need to send it */ + offset += ((rec->length) + 8); + rec = (void *)&rec->data[rec->length]; + + while (offset < fw->size) { + dev_dbg(codec->dev, + "Packet: command %d, data length = 0x%x\r\n", + rec->command, rec->length); + len = rec->length + 8; + + out = kzalloc(len, GFP_KERNEL); + if (!out) { + dev_err(codec->dev, + "Failed to allocate RX buffer\n"); + goto abort; + } + + img_swap = kzalloc(len, GFP_KERNEL); + if (!img_swap) { + dev_err(codec->dev, + "Failed to allocate image buffer\n"); + goto abort; + } + + /* We need to re-order for 0010 */ + byte_swap_64((u64 *)&rec->command, img_swap, len); + + xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); + if (!xfer) { + dev_err(codec->dev, "Failed to allocate xfer\n"); + goto abort; + } + + xfer->codec = codec; + list_add_tail(&xfer->list, &xfer_list); + + spi_message_init(&xfer->m); + xfer->m.complete = wm0010_boot_xfer_complete; + xfer->m.context = xfer; + xfer->t.tx_buf = img_swap; + xfer->t.rx_buf = out; + xfer->t.len = len; + xfer->t.bits_per_word = 8; + + if (!wm0010->pll_running) { + xfer->t.speed_hz = wm0010->sysclk / 6; + } else { + xfer->t.speed_hz = wm0010->max_spi_freq; + + if (wm0010->board_max_spi_speed && + (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) + xfer->t.speed_hz = wm0010->board_max_spi_speed; + } + + /* Store max usable spi frequency for later use */ + wm0010->max_spi_freq = xfer->t.speed_hz; + + spi_message_add_tail(&xfer->t, &xfer->m); + + offset += ((rec->length) + 8); + rec = (void *)&rec->data[rec->length]; + + if (offset >= fw->size) { + dev_dbg(codec->dev, "All transfers scheduled\n"); + xfer->done = &done; + } + + ret = spi_async(spi, &xfer->m); + if (ret != 0) { + dev_err(codec->dev, "Write failed: %d\n", ret); + goto abort; + } + + if (wm0010->boot_failed) + goto abort; + } + + wait_for_completion(&done); + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_FIRMWARE; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + mutex_unlock(&wm0010->lock); + + release_firmware(fw); + + while (!list_empty(&xfer_list)) { + xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, + list); + kfree(xfer->t.rx_buf); + kfree(xfer->t.tx_buf); + list_del(&xfer->list); + kfree(xfer); + } + + return 0; + +abort: + /* Put the chip back into reset */ + wm0010_halt(codec); + mutex_unlock(&wm0010->lock); + return ret; +err_core: + regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); +err: + return ret; +} + +static int wm0010_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) + wm0010_boot(codec); + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { + mutex_lock(&wm0010->lock); + wm0010_halt(codec); + mutex_unlock(&wm0010->lock); + } + break; + case SND_SOC_BIAS_OFF: + break; + } + + codec->dapm.bias_level = level; + + return 0; +} + +static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source, + int clk_id, unsigned int freq, int dir) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + unsigned int i; + + wm0010->sysclk = freq; + + if (freq < pll_clock_map[ARRAY_SIZE(pll_clock_map)-1].max_sysclk) { + wm0010->max_spi_freq = 0; + } else { + for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++) + if (freq >= pll_clock_map[i].max_sysclk) + break; + + wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed; + wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1; + } + + return 0; +} + +static int wm0010_probe(struct snd_soc_codec *codec); + +static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { + .probe = wm0010_probe, + .set_bias_level = wm0010_set_bias_level, + .set_sysclk = wm0010_set_sysclk, + + .dapm_routes = wm0010_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), +}; + +#define WM0010_RATES (SNDRV_PCM_RATE_48000) +#define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver wm0010_dai[] = { + { + .name = "wm0010-sdi1", + .playback = { + .stream_name = "SDI1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + .capture = { + .stream_name = "SDI1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + }, + { + .name = "wm0010-sdi2", + .playback = { + .stream_name = "SDI2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + .capture = { + .stream_name = "SDI2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + }, +}; + +static irqreturn_t wm0010_irq(int irq, void *data) +{ + struct wm0010_priv *wm0010 = data; + + switch (wm0010->state) { + case WM0010_POWER_OFF: + case WM0010_OUT_OF_RESET: + case WM0010_BOOTROM: + case WM0010_STAGE2: + spin_lock(&wm0010->irq_lock); + complete(&wm0010->boot_completion); + spin_unlock(&wm0010->irq_lock); + return IRQ_HANDLED; + default: + return IRQ_NONE; + } + + return IRQ_NONE; +} + +static int wm0010_probe(struct snd_soc_codec *codec) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + struct spi_device *spi = to_spi_device(wm0010->dev); + unsigned long flags; + unsigned long gpio_flags; + int ret; + int trigger; + int irq; + + wm0010->codec = codec; + + init_completion(&wm0010->boot_completion); + + wm0010->core_supplies[0].supply = "AVDD"; + wm0010->core_supplies[1].supply = "DCVDD"; + ret = devm_regulator_bulk_get(wm0010->dev, ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); + if (ret != 0) { + dev_err(wm0010->dev, "Failed to obtain core supplies: %d\n", + ret); + return ret; + } + + wm0010->dbvdd = devm_regulator_get(wm0010->dev, "DBVDD"); + if (IS_ERR(wm0010->dbvdd)) { + ret = PTR_ERR(wm0010->dbvdd); + dev_err(wm0010->dev, "Failed to obtain DBVDD: %d\n", ret); + return ret; + } + + if (wm0010->pdata.gpio_reset) { + wm0010->gpio_reset = wm0010->pdata.gpio_reset; + + if (wm0010->pdata.reset_active_high) + wm0010->gpio_reset_value = 1; + else + wm0010->gpio_reset_value = 0; + + if (wm0010->gpio_reset_value) + gpio_flags = GPIOF_OUT_INIT_HIGH; + else + gpio_flags = GPIOF_OUT_INIT_LOW; + + ret = devm_gpio_request_one(wm0010->dev, wm0010->gpio_reset, + gpio_flags, "wm0010 reset"); + if (ret < 0) { + dev_err(wm0010->dev, + "Failed to request GPIO for DSP reset: %d\n", + ret); + return ret; + } + } else { + dev_err(wm0010->dev, "No reset GPIO configured\n"); + return ret; + } + + irq = spi->irq; + if (wm0010->pdata.irq_flags) + trigger = wm0010->pdata.irq_flags; + else + trigger = IRQF_TRIGGER_FALLING; + trigger |= IRQF_ONESHOT; + + ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, + "wm0010", wm0010); + if (ret) + dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", + irq, ret); + wm0010->irq = irq; + + if (spi->max_speed_hz) + wm0010->board_max_spi_speed = spi->max_speed_hz; + else + wm0010->board_max_spi_speed = 0; + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_POWER_OFF; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + return 0; +} + +static int __devinit wm0010_spi_probe(struct spi_device *spi) +{ + struct wm0010_priv *wm0010; + int ret; + + wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), + GFP_KERNEL); + if (!wm0010) + return -ENOMEM; + + mutex_init(&wm0010->lock); + spin_lock_init(&wm0010->irq_lock); + + spi_set_drvdata(spi, wm0010); + wm0010->dev = &spi->dev; + + if (dev_get_platdata(&spi->dev)) + memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), + sizeof(wm0010->pdata)); + + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm0010, wm0010_dai, + ARRAY_SIZE(wm0010_dai)); + if (ret < 0) + return ret; + + return 0; +} + +static int __devexit wm0010_spi_remove(struct spi_device *spi) +{ + struct wm0010_priv *wm0010 = spi_get_drvdata(spi); + + snd_soc_unregister_codec(&spi->dev); + + if (wm0010->gpio_reset) { + /* Remember to put chip back into reset */ + gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); + gpio_free(wm0010->gpio_reset); + } + + if (wm0010->irq) + free_irq(wm0010->irq, wm0010); + + return 0; +} + +static struct spi_driver wm0010_spi_driver = { + .driver = { + .name = "wm0010", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = wm0010_spi_probe, + .remove = __devexit_p(wm0010_spi_remove), +}; + +module_spi_driver(wm0010_spi_driver); + +MODULE_DESCRIPTION("ASoC WM0010 driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); From a0dfb2634e5671770f598cda08002d8cda66ac77 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Thu, 23 Aug 2012 19:51:21 +0800 Subject: [PATCH 142/665] af_packet: match_fanout_group() can be static cc: Eric Leblond Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller --- net/packet/af_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index aee7196aac36..c5c9e2a54218 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1273,7 +1273,7 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) spin_unlock(&f->lock); } -bool match_fanout_group(struct packet_type *ptype, struct sock * sk) +static bool match_fanout_group(struct packet_type *ptype, struct sock * sk) { if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout) return true; From 0ff9514b579b4f2f3e6038cd961ce64c224c3c73 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 23 Aug 2012 10:53:08 -0600 Subject: [PATCH 143/665] PCI: Don't print anything while decoding is disabled If we try to print to the console device while its decoding is disabled, the system will hang. Reported-and-tested-by: Olof Johansson Signed-off-by: Bjorn Helgaas Acked-by: Olof Johansson --- drivers/pci/probe.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6c143b4497ca..9f8a6b79a8ec 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) case PCI_BASE_ADDRESS_MEM_TYPE_32: break; case PCI_BASE_ADDRESS_MEM_TYPE_1M: - dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); + /* 1M mem BAR treated as 32-bit BAR */ break; case PCI_BASE_ADDRESS_MEM_TYPE_64: flags |= IORESOURCE_MEM_64; break; default: - dev_warn(&dev->dev, - "mem unknown type %x treated as 32-bit BAR\n", - mem_type); + /* mem unknown type treated as 32-bit BAR */ break; } return flags; @@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, u32 l, sz, mask; u16 orig_cmd; struct pci_bus_region region; + bool bar_too_big = false, bar_disabled = false; mask = type ? PCI_ROM_ADDRESS_MASK : ~0; + /* No printks while decoding is disabled! */ if (!dev->mmio_always_on) { pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); pci_write_config_word(dev, PCI_COMMAND, @@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, goto fail; if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { - dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", - pos); + bar_too_big = true; goto fail; } @@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, region.start = 0; region.end = sz64; pcibios_bus_to_resource(dev, res, ®ion); + bar_disabled = true; } else { region.start = l64; region.end = l64 + sz64; pcibios_bus_to_resource(dev, res, ®ion); - dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", - pos, res); } } else { sz = pci_size(l, sz, mask); @@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, region.start = l; region.end = l + sz; pcibios_bus_to_resource(dev, res, ®ion); - - dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); } - out: + goto out; + + +fail: + res->flags = 0; +out: if (!dev->mmio_always_on) pci_write_config_word(dev, PCI_COMMAND, orig_cmd); + if (bar_too_big) + dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos); + if (res->flags && !bar_disabled) + dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); + return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; - fail: - res->flags = 0; - goto out; } static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) From 4c054ba63ad47ef244cfcfa1cea38134620a5bae Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 16 Aug 2012 15:33:10 -0700 Subject: [PATCH 144/665] target: Fix ->data_length re-assignment bug with SCSI overflow This patch fixes a long-standing bug with SCSI overflow handling where se_cmd->data_length was incorrectly being re-assigned to the larger CDB extracted allocation length, resulting in a number of fabric level errors that would end up causing a session reset in most cases. So instead now: - Only re-assign se_cmd->data_length durining UNDERFLOW (to use the smaller value) - Use existing se_cmd->data_length for OVERFLOW (to use the smaller value) This fix has been tested with the following CDB to generate an SCSI overflow: sg_raw -r512 /dev/sdc 28 0 0 0 0 0 0 0 9 0 Tested using iscsi-target, tcm_qla2xxx, loopback and tcm_vhost fabric ports. Here is a bit more detail on each case: - iscsi-target: Bug with open-iscsi with overflow, sg_raw returns -3584 bytes of data. - tcm_qla2xxx: Working as expected, returnins 512 bytes of data - loopback: sg_raw returns CHECK_CONDITION, from overflow rejection in transport_generic_map_mem_to_cmd() - tcm_vhost: Same as loopback Reported-by: Roland Dreier Cc: Roland Dreier Cc: Christoph Hellwig Cc: Boaz Harrosh Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4de3186dc44e..3425098ef728 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1181,15 +1181,20 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ goto out_invalid_cdb_field; } - + /* + * For the overflow case keep the existing fabric provided + * ->data_length. Otherwise for the underflow case, reset + * ->data_length to the smaller SCSI expected data transfer + * length. + */ if (size > cmd->data_length) { cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; cmd->residual_count = (size - cmd->data_length); } else { cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; cmd->residual_count = (cmd->data_length - size); + cmd->data_length = size; } - cmd->data_length = size; } return 0; From 22f5d115a2b087c977128f84ee557ad71530330e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 14 Aug 2012 10:53:38 +0000 Subject: [PATCH 145/665] drm: Initialize object type when using DRM_MODE() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRM_MODE() macro doesn't initialize the type of the base drm object. When a copy is made of the mode, the object type is overwritten with zero, and the the object can no longer be found by drm_mode_object_find() due to the type check failing. Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- include/drm/drm_crtc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index ced362533e3c..bfacf0d5a225 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -118,7 +118,8 @@ enum drm_mode_status { .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \ .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ - .vscan = (vs), .flags = (f), .vrefresh = 0 + .vscan = (vs), .flags = (f), .vrefresh = 0, \ + .base.type = DRM_MODE_OBJECT_MODE #define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */ From 7c4eaca4162d0b5ad4fb39f974d7ffd71b9daa09 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 16 Aug 2012 08:29:03 +0000 Subject: [PATCH 146/665] drm: Check for invalid cursor flags Signed-off-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 2 +- include/drm/drm_mode.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 08a7aa722d6b..6fbfc244748f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1981,7 +1981,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if (!req->flags) + if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) return -EINVAL; mutex_lock(&dev->mode_config.mutex); diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 5581980b14f6..3d6301b6ec16 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -359,8 +359,9 @@ struct drm_mode_mode_cmd { struct drm_mode_modeinfo mode; }; -#define DRM_MODE_CURSOR_BO (1<<0) -#define DRM_MODE_CURSOR_MOVE (1<<1) +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 +#define DRM_MODE_CURSOR_FLAGS 0x03 /* * depending on the value in flags different members are used. From ac70b2e9a13423b5efa0178e081936ce6979aea5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 15 Aug 2012 18:09:15 +0100 Subject: [PATCH 147/665] sfc: Fix reporting of IPv4 full filters through ethtool ETHTOOL_GRXCLSRULE returns filters for a TCP/IPv4 or UDP/IPv4 4-tuple with source and destination swapped. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 8cba2df82b18..5faedd855b77 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -863,8 +863,8 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, &ip_entry->ip4dst, &ip_entry->pdst); if (rc != 0) { rc = efx_filter_get_ipv4_full( - &spec, &proto, &ip_entry->ip4src, &ip_entry->psrc, - &ip_entry->ip4dst, &ip_entry->pdst); + &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst, + &ip_entry->ip4src, &ip_entry->psrc); EFX_WARN_ON_PARANOID(rc); ip_mask->ip4src = ~0; ip_mask->psrc = ~0; From ef813c412c0cf254ddce7d922289e2d6a69960f0 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 19:15:01 +0400 Subject: [PATCH 148/665] can: softing: Fix potential memory leak in softing_load_fw() Do not leak memory by updating pointer with potentially NULL realloc return value. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Marc Kleine-Budde --- drivers/net/can/softing/softing_fw.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c index 310596175676..b595d3422b9f 100644 --- a/drivers/net/can/softing/softing_fw.c +++ b/drivers/net/can/softing/softing_fw.c @@ -150,7 +150,7 @@ int softing_load_fw(const char *file, struct softing *card, const uint8_t *mem, *end, *dat; uint16_t type, len; uint32_t addr; - uint8_t *buf = NULL; + uint8_t *buf = NULL, *new_buf; int buflen = 0; int8_t type_end = 0; @@ -199,11 +199,12 @@ int softing_load_fw(const char *file, struct softing *card, if (len > buflen) { /* align buflen */ buflen = (len + (1024-1)) & ~(1024-1); - buf = krealloc(buf, buflen, GFP_KERNEL); - if (!buf) { + new_buf = krealloc(buf, buflen, GFP_KERNEL); + if (!new_buf) { ret = -ENOMEM; goto failed; } + buf = new_buf; } /* verify record data */ memcpy_fromio(buf, &dpram[addr + offset], len); From da3d50ef308d53f216f1f92f4971f245c13e9f65 Mon Sep 17 00:00:00 2001 From: Sven Schmitt Date: Thu, 9 Aug 2012 14:46:34 +0200 Subject: [PATCH 149/665] can: sja1000_platform: fix wrong flag IRQF_SHARED for interrupt sharing The sja1000 platform driver wrongly assumes that a shared IRQ is indicated with the IRQF_SHARED flag in irq resource flags. This patch changes the driver to handle the correct flag IORESOURCE_IRQ_SHAREABLE instead. There are no mainline users of the platform driver which wrongly make use of IRQF_SHARED. Signed-off-by: Sven Schmitt Acked-by: Yegor Yefremov Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/sja1000_platform.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 4f50145f6483..662c5f7eb0c5 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -109,7 +109,9 @@ static int sp_probe(struct platform_device *pdev) priv = netdev_priv(dev); dev->irq = res_irq->start; - priv->irq_flags = res_irq->flags & (IRQF_TRIGGER_MASK | IRQF_SHARED); + priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK; + if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE) + priv->irq_flags |= IRQF_SHARED; priv->reg_base = addr; /* The CAN clock frequency is half the oscillator clock frequency */ priv->can.clock.freq = pdata->osc_freq / 2; From 9a0f938bde74bf9e50bd75c8de9e38c1787398cd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 24 Aug 2012 09:12:22 +0100 Subject: [PATCH 150/665] drm/i915: Use the correct size of the GTT for placing the per-process entries The current layout is to place the per-process tables at the end of the GTT. However, this is currently using a hardcoded maximum size for the GTT and not taking in account limitations imposed by the BIOS. Use the value for the total number of entries allocated in the table as provided by the configuration registers. Reported-by: Matthew Garrett Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Ben Widawsky Cc: Matthew Garret Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index d9a5372ec56f..60815b861ec2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -72,7 +72,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 * entries. For aliasing ppgtt support we just steal them at the end for * now. */ - first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES; + first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES; ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); if (!ppgtt) From a51d4ed01e5bb39d2cf36a12f9976ab08872c192 Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Fri, 24 Aug 2012 07:56:31 -0400 Subject: [PATCH 151/665] i915: Quirk no_lvds on Gigabyte GA-D525TUD ITX motherboard This board is incorrectly detected as having an LVDS connector, resulting in the VGA output (the only available output on the board) showing the console only in the top-left 1024x768 pixels, and an extra LVDS connector appearing in X. It's a desktop Mini-ITX board using an Atom D525 CPU with an NM10 chipset. I've had this board for about a year, but this is the first time I noticed the issue because I've been running it headless for most of its life. Signed-off-by: Calvin Walton --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e05c0d3e3440..e9a6f6aaed85 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -780,6 +780,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Gigabyte GA-D525TUD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), + }, + }, { } /* terminating entry */ }; From 78df76a065ae3b5dbcb9a29912adc02f697de498 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 24 Aug 2012 05:40:47 +0000 Subject: [PATCH 152/665] ipv4: take rt_uncached_lock only if needed Multicast traffic allocates dst with DST_NOCACHE, but dst is not inserted into rt_uncached_list. This slowdown multicast workloads on SMP because rt_uncached_lock is contended. Change the test before taking the lock to actually check the dst was inserted into rt_uncached_list. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 8c8c748ebb28..24fd4c596643 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1263,7 +1263,7 @@ static void ipv4_dst_destroy(struct dst_entry *dst) { struct rtable *rt = (struct rtable *) dst; - if (dst->flags & DST_NOCACHE) { + if (!list_empty(&rt->rt_uncached)) { spin_lock_bh(&rt_uncached_lock); list_del(&rt->rt_uncached); spin_unlock_bh(&rt_uncached_lock); From bd4242dfe85470b9caecbd049310518f9b9e3f14 Mon Sep 17 00:00:00 2001 From: Rayagond Kokatanur Date: Wed, 22 Aug 2012 21:28:18 +0000 Subject: [PATCH 153/665] stmmac: add header inclusion protection This patch adds "#ifndef __
_H" for protecting header from double inclusion. Signed-off-by: Rayagond Kokatanur Hacked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/descs.h | 6 ++++++ drivers/net/ethernet/stmicro/stmmac/descs_com.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/dwmac100.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 3 +++ drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/mmc.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h | 4 ++++ 9 files changed, 43 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index e2d083228f3a..719be3912aa9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __COMMON_H__ +#define __COMMON_H__ + #include #include #include @@ -366,3 +369,5 @@ extern void stmmac_set_mac(void __iomem *ioaddr, bool enable); extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); extern const struct stmmac_ring_mode_ops ring_mode_ops; + +#endif /* __COMMON_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h index 9820ec842cc0..223adf95fd03 100644 --- a/drivers/net/ethernet/stmicro/stmmac/descs.h +++ b/drivers/net/ethernet/stmicro/stmmac/descs.h @@ -20,6 +20,10 @@ Author: Giuseppe Cavallaro *******************************************************************************/ + +#ifndef __DESCS_H__ +#define __DESCS_H__ + struct dma_desc { /* Receive descriptor */ union { @@ -166,3 +170,5 @@ enum tdes_csum_insertion { * is not calculated */ cic_full = 3, /* IP header and pseudoheader */ }; + +#endif /* __DESCS_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h index dd8d6e19dff6..7ee9499a6e38 100644 --- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h +++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h @@ -27,6 +27,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DESC_COM_H__ +#define __DESC_COM_H__ + #if defined(CONFIG_STMMAC_RING) static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end) { @@ -124,3 +127,5 @@ static inline void norm_set_tx_desc_len(struct dma_desc *p, int len) p->des01.tx.buffer1_size = len; } #endif + +#endif /* __DESC_COM_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h index 7c6d857a9cc7..2ec6aeae349e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DWMAC100_H__ +#define __DWMAC100_H__ + #include #include "common.h" @@ -119,3 +122,5 @@ enum ttc_control { #define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ extern const struct stmmac_dma_ops dwmac100_dma_ops; + +#endif /* __DWMAC100_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index b4c44a587f02..0e4cacedc1f0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -19,6 +19,8 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DWMAC1000_H__ +#define __DWMAC1000_H__ #include #include "common.h" @@ -232,3 +234,4 @@ enum rtc_control { #define DWMAC_CORE_3_40 0x34 extern const struct stmmac_dma_ops dwmac1000_dma_ops; +#endif /* __DWMAC1000_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index e678ce39d014..e49c9a0fd6ff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DWMAC_DMA_H__ +#define __DWMAC_DMA_H__ + /* DMA CRS Control and Status Register Mapping */ #define DMA_BUS_MODE 0x00001000 /* Bus Mode */ #define DMA_XMT_POLL_DEMAND 0x00001004 /* Transmit Poll Demand */ @@ -109,3 +112,5 @@ extern void dwmac_dma_start_rx(void __iomem *ioaddr); extern void dwmac_dma_stop_rx(void __iomem *ioaddr); extern int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); + +#endif /* __DWMAC_DMA_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h index a38352024cb8..67995ef25251 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc.h +++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __MMC_H__ +#define __MMC_H__ + /* MMC control register */ /* When set, all counter are reset */ #define MMC_CNTRL_COUNTER_RESET 0x1 @@ -129,3 +132,5 @@ struct stmmac_counters { extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode); extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr); extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc); + +#endif /* __MMC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index f2d3665430ad..e872e1da3137 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -20,6 +20,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __STMMAC_H__ +#define __STMMAC_H__ + #define STMMAC_RESOURCE_NAME "stmmaceth" #define DRV_MODULE_VERSION "March_2012" @@ -166,3 +169,5 @@ static inline void stmmac_unregister_pci(void) { } #endif /* CONFIG_STMMAC_PCI */ + +#endif /* __STMMAC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h index 6863590d184b..aea9b14cdfbe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h @@ -21,6 +21,8 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __STMMAC_TIMER_H__ +#define __STMMAC_TIMER_H__ struct stmmac_timer { void (*timer_start) (unsigned int new_freq); @@ -40,3 +42,5 @@ void stmmac_schedule(struct net_device *dev); extern int tmu2_register_user(void *fnt, void *data); extern void tmu2_unregister_user(void); #endif + +#endif /* __STMMAC_TIMER_H__ */ From 20e1db19db5d6b9e4e83021595eab0dc8f107bef Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 23 Aug 2012 02:09:11 +0000 Subject: [PATCH 154/665] netlink: fix possible spoofing from non-root processes Non-root user-space processes can send Netlink messages to other processes that are well-known for being subscribed to Netlink asynchronous notifications. This allows ilegitimate non-root process to send forged messages to Netlink subscribers. The userspace process usually verifies the legitimate origin in two ways: a) Socket credentials. If UID != 0, then the message comes from some ilegitimate process and the message needs to be dropped. b) Netlink portID. In general, portID == 0 means that the origin of the messages comes from the kernel. Thus, discarding any message not coming from the kernel. However, ctnetlink sets the portID in event messages that has been triggered by some user-space process, eg. conntrack utility. So other processes subscribed to ctnetlink events, eg. conntrackd, know that the event was triggered by some user-space action. Neither of the two ways to discard ilegitimate messages coming from non-root processes can help for ctnetlink. This patch adds capability validation in case that dst_pid is set in netlink_sendmsg(). This approach is aggressive since existing applications using any Netlink bus to deliver messages between two user-space processes will break. Note that the exception is NETLINK_USERSOCK, since it is reserved for netlink-to-netlink userspace communication. Still, if anyone wants that his Netlink bus allows netlink-to-netlink userspace, then they can set NL_NONROOT_SEND. However, by default, I don't think it makes sense to allow to use NETLINK_ROUTE to communicate two processes that are sending no matter what information that is not related to link/neighbouring/routing. They should be using NETLINK_USERSOCK instead for that. Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 1445d73533ed..527023823b5c 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1373,7 +1373,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, dst_pid = addr->nl_pid; dst_group = ffs(addr->nl_groups); err = -EPERM; - if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) + if ((dst_group || dst_pid) && + !netlink_capable(sock, NL_NONROOT_SEND)) goto out; } else { dst_pid = nlk->dst_pid; @@ -2147,6 +2148,7 @@ static void __init netlink_add_usersock_entry(void) rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners); nl_table[NETLINK_USERSOCK].module = THIS_MODULE; nl_table[NETLINK_USERSOCK].registered = 1; + nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND; netlink_table_ungrab(); } From 7c4a56fec379ac0d7754e0d4da6a7361f1a4fe64 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Thu, 23 Aug 2012 07:05:17 +0000 Subject: [PATCH 155/665] tcp: fix cwnd reduction for non-sack recovery The cwnd reduction in fast recovery is based on the number of packets newly delivered per ACK. For non-sack connections every DUPACK signifies a packet has been delivered, but the sender mistakenly skips counting them for cwnd reduction. The fix is to compute newly_acked_sacked after DUPACKs are accounted in sacked_out for non-sack connections. Signed-off-by: Yuchung Cheng Acked-by: Nandita Dukkipati Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 85308b90df80..6e38c6c23caa 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2926,13 +2926,14 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) * tcp_xmit_retransmit_queue(). */ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, - int newly_acked_sacked, bool is_dupack, + int prior_sacked, bool is_dupack, int flag) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); + int newly_acked_sacked = 0; int fast_rexmit = 0; if (WARN_ON(!tp->packets_out && tp->sacked_out)) @@ -2992,6 +2993,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, tcp_add_reno_sack(sk); } else do_lost = tcp_try_undo_partial(sk, pkts_acked); + newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; break; case TCP_CA_Loss: if (flag & FLAG_DATA_ACKED) @@ -3013,6 +3015,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (is_dupack) tcp_add_reno_sack(sk); } + newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; if (icsk->icsk_ca_state <= TCP_CA_Disorder) tcp_try_undo_dsack(sk); @@ -3590,7 +3593,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) int prior_packets; int prior_sacked = tp->sacked_out; int pkts_acked = 0; - int newly_acked_sacked = 0; bool frto_cwnd = false; /* If the ack is older than previous acks @@ -3666,8 +3668,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); pkts_acked = prior_packets - tp->packets_out; - newly_acked_sacked = (prior_packets - prior_sacked) - - (tp->packets_out - tp->sacked_out); if (tp->frto_counter) frto_cwnd = tcp_process_frto(sk, flag); @@ -3681,7 +3681,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_may_raise_cwnd(sk, flag)) tcp_cong_avoid(sk, ack, prior_in_flight); is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); } else { if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) @@ -3698,7 +3698,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) no_queue: /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than @@ -3718,8 +3718,7 @@ old_ack: */ if (TCP_SKB_CB(skb)->sacked) { flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); - newly_acked_sacked = tp->sacked_out - prior_sacked; - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); } From 2d85b9494d10501f20ebf043f8d599e45736d78f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 24 Jul 2012 15:26:08 +0200 Subject: [PATCH 156/665] ARM: mach-shmobile: armadillo800eva: Fix GPIO buttons descriptions The GPIO buttons are named SW3, SW4, SW5 and SW6 on the board silkscreen. Update the buttons descriptions accordingly. Signed-off-by: Laurent Pinchart Acked-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-armadillo800eva.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index cf10f92856dc..a002504e3236 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -523,10 +523,10 @@ static struct platform_device hdmi_lcdc_device = { #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } static struct gpio_keys_button gpio_buttons[] = { - GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"), - GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"), - GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"), - GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"), + GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3"), + GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"), + GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"), + GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"), }; static struct gpio_keys_platform_data gpio_key_info = { From 5c1d2d16772e2d7d4e2e8da99a92d6f50b9102f0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 24 Jul 2012 15:26:09 +0200 Subject: [PATCH 157/665] ARM: mach-shmobile: armadillo800eva: Enable power button as wakeup source Signed-off-by: Laurent Pinchart Acked-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index a002504e3236..65cb7936ed9e 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -520,10 +520,11 @@ static struct platform_device hdmi_lcdc_device = { }; /* GPIO KEY */ -#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } +#define GPIO_KEY(c, g, d, ...) \ + { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ } static struct gpio_keys_button gpio_buttons[] = { - GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3"), + GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3", .wakeup = 1), GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"), GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"), GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"), From a849088aa1552b1a28eea3daff599ee22a734ae3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 25 Aug 2012 09:03:15 +0100 Subject: [PATCH 158/665] ARM: Fix ioremap() of address zero Murali Nalajala reports a regression that ioremapping address zero results in an oops dump: Unable to handle kernel paging request at virtual address fa200000 pgd = d4f80000 [fa200000] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT SMP ARM Modules linked in: CPU: 0 Tainted: G W (3.4.0-g3b5f728-00009-g638207a #13) PC is at msm_pm_config_rst_vector_before_pc+0x8/0x30 LR is at msm_pm_boot_config_before_pc+0x18/0x20 pc : [] lr : [] psr: a0000093 sp : c0837ef0 ip : cfe00000 fp : 0000000d r10: da7efc17 r9 : 225c4278 r8 : 00000006 r7 : 0003c000 r6 : c085c824 r5 : 00000001 r4 : fa101000 r3 : fa200000 r2 : c095080c r1 : 002250fc r0 : 00000000 Flags: NzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5387d Table: 25180059 DAC: 00000015 [] (msm_pm_config_rst_vector_before_pc+0x8/0x30) from [] (msm_pm_boot_config_before_pc+0x18/0x20) [] (msm_pm_boot_config_before_pc+0x18/0x20) from [] (msm_pm_power_collapse+0x410/0xb04) [] (msm_pm_power_collapse+0x410/0xb04) from [] (arch_idle+0x294/0x3e0) [] (arch_idle+0x294/0x3e0) from [] (default_idle+0x18/0x2c) [] (default_idle+0x18/0x2c) from [] (cpu_idle+0x90/0xe4) [] (cpu_idle+0x90/0xe4) from [] (rest_init+0x88/0xa0) [] (rest_init+0x88/0xa0) from [] (start_kernel+0x3a8/0x40c) Code: c0704256 e12fff1e e59f2020 e5923000 (e5930000) This is caused by the 'reserved' entries which we insert (see 19b52abe3c5d7 - ARM: 7438/1: fill possible PMD empty section gaps) which get matched for physical address zero. Resolve this by marking these reserved entries with a different flag. Cc: Tested-by: Murali Nalajala Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/mm.h | 3 +++ arch/arm/mm/mmu.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 6776160618ef..a8ee92da3544 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -55,6 +55,9 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page /* permanent static mappings from iotable_init() */ #define VM_ARM_STATIC_MAPPING 0x40000000 +/* empty mapping */ +#define VM_ARM_EMPTY_MAPPING 0x20000000 + /* mapping type (attributes) for permanent static mappings */ #define VM_ARM_MTYPE(mt) ((mt) << 20) #define VM_ARM_MTYPE_MASK (0x1f << 20) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4c2d0451e84a..eab94bc6f805 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -807,7 +807,7 @@ static void __init pmd_empty_section_gap(unsigned long addr) vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); vm->addr = (void *)addr; vm->size = SECTION_SIZE; - vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; + vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING; vm->caller = pmd_empty_section_gap; vm_area_add_early(vm); } @@ -820,7 +820,7 @@ static void __init fill_pmd_gaps(void) /* we're still single threaded hence no lock needed here */ for (vm = vmlist; vm; vm = vm->next) { - if (!(vm->flags & VM_ARM_STATIC_MAPPING)) + if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING))) continue; addr = (unsigned long)vm->addr; if (addr < next) From bf8801145c01ab600f8df66e8c879ac642fa5846 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 16 Aug 2012 18:55:44 +0100 Subject: [PATCH 159/665] ARM: 7496/1: hw_breakpoint: don't rely on dfsr to show watchpoint access type From ARM debug architecture v7.1 onwards, a watchpoint exception causes the DFAR to be updated with the faulting data address. However, DFSR.WnR takes an UNKNOWN value and therefore cannot be used in general to determine the access type that triggered the watchpoint. This patch forbids watchpoints without an overflow handler from specifying a specific access type (load/store). Those with overflow handlers must be able to handle false positives potentially triggered by a watchpoint of a different access type on the same address. For SIGTRAP-based handlers (i.e. ptrace), this should have no impact. Cc: Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/hw_breakpoint.c | 55 ++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index ba386bd94107..18d39ea4c02f 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -159,6 +159,12 @@ static int debug_arch_supported(void) arch >= ARM_DEBUG_ARCH_V7_1; } +/* Can we determine the watchpoint access type from the fsr? */ +static int debug_exception_updates_fsr(void) +{ + return 0; +} + /* Determine number of WRP registers available. */ static int get_num_wrp_resources(void) { @@ -619,18 +625,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) info->address &= ~alignment_mask; info->ctrl.len <<= offset; - /* - * Currently we rely on an overflow handler to take - * care of single-stepping the breakpoint when it fires. - * In the case of userspace breakpoints on a core with V7 debug, - * we can use the mismatch feature as a poor-man's hardware - * single-step, but this only works for per-task breakpoints. - */ - if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || - !core_has_mismatch_brps() || !bp->hw.bp_target)) { - pr_warning("overflow handler required but none found\n"); - ret = -EINVAL; + if (!bp->overflow_handler) { + /* + * Mismatch breakpoints are required for single-stepping + * breakpoints. + */ + if (!core_has_mismatch_brps()) + return -EINVAL; + + /* We don't allow mismatch breakpoints in kernel space. */ + if (arch_check_bp_in_kernelspace(bp)) + return -EPERM; + + /* + * Per-cpu breakpoints are not supported by our stepping + * mechanism. + */ + if (!bp->hw.bp_target) + return -EINVAL; + + /* + * We only support specific access types if the fsr + * reports them. + */ + if (!debug_exception_updates_fsr() && + (info->ctrl.type == ARM_BREAKPOINT_LOAD || + info->ctrl.type == ARM_BREAKPOINT_STORE)) + return -EINVAL; } + out: return ret; } @@ -706,10 +729,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, goto unlock; /* Check that the access type matches. */ - access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : - HW_BREAKPOINT_R; - if (!(access & hw_breakpoint_type(wp))) - goto unlock; + if (debug_exception_updates_fsr()) { + access = (fsr & ARM_FSR_ACCESS_MASK) ? + HW_BREAKPOINT_W : HW_BREAKPOINT_R; + if (!(access & hw_breakpoint_type(wp))) + goto unlock; + } /* We have a winner. */ info->trigger = addr; From d968d2b801d877601d54e35e6dd0f52d9c797c99 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 16 Aug 2012 19:02:12 +0100 Subject: [PATCH 160/665] ARM: 7497/1: hw_breakpoint: allow single-byte watchpoints on all addresses Breakpoint validation currently fails for single-byte watchpoints on addresses ending in 11b. There is no reason to forbid such a watchpoint, so extend the validation code to allow it. Cc: Ulrich Weigand Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/hw_breakpoint.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 18d39ea4c02f..281bf3301241 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -610,13 +610,14 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) /* Aligned */ break; case 1: - /* Allow single byte watchpoint. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) - break; case 2: /* Allow halfword watchpoints and breakpoints. */ if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) break; + case 3: + /* Allow single byte watchpoint. */ + if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) + break; default: ret = -EINVAL; goto out; From dbece45894d3ab1baac15a96dc4e1e8e23f64a93 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 24 Aug 2012 15:20:59 +0100 Subject: [PATCH 161/665] ARM: 7501/1: decompressor: reset ttbcr for VMSA ARMv7 cores When enabling the MMU for ARMv7 CPUs, the decompressor does not touch the ttbcr register, assuming that it will be zeroed (N == 0, EAE == 0). Given that only EAE is defined as 0 for non-secure copies of the register (and a bootloader such as kexec may leave it set to 1 anyway), we should ensure that we reset the register ourselves before turning on the MMU. This patch zeroes TTBCR.EAE and TTBCR.N prior to enabling the MMU for ARMv7 cores in the decompressor, configuring us exclusively for 32-bit translation tables via TTBR0. Cc: Acked-by: Nicolas Pitre Signed-off-by: Matthew Leach Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/boot/compressed/head.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index b8c64b80bafc..81769c1341fa 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -659,10 +659,14 @@ __armv7_mmu_cache_on: #ifdef CONFIG_CPU_ENDIAN_BE8 orr r0, r0, #1 << 25 @ big-endian page tables #endif + mrcne p15, 0, r6, c2, c0, 2 @ read ttb control reg orrne r0, r0, #1 @ MMU enabled movne r1, #0xfffffffd @ domain 0 = client + bic r6, r6, #1 << 31 @ 32-bit translation system + bic r6, r6, #3 << 0 @ use only ttbr0 mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer mcrne p15, 0, r1, c3, c0, 0 @ load domain access control + mcrne p15, 0, r6, c2, c0, 2 @ load ttb control #endif mcr p15, 0, r0, c7, c5, 4 @ ISB mcr p15, 0, r0, c1, c0, 0 @ load control register From ae3790b8a916429be5fa61da95992929e6b34d64 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 24 Aug 2012 15:21:52 +0100 Subject: [PATCH 162/665] ARM: 7502/1: contextidr: avoid using bfi instruction during notifier The bfi instruction is not available on ARMv6, so instead use an and/orr sequence in the contextidr_notifier. This gets rid of the assembler error: Assembler messages: Error: selected processor does not support ARM mode `bfi r3,r2,#0,#8' Reported-by: Arnd Bergmann Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/context.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 119bc52ab93e..4e07eec1270d 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -63,10 +63,11 @@ static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd, pid = task_pid_nr(thread->task) << ASID_BITS; asm volatile( " mrc p15, 0, %0, c13, c0, 1\n" - " bfi %1, %0, #0, %2\n" - " mcr p15, 0, %1, c13, c0, 1\n" + " and %0, %0, %2\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c13, c0, 1\n" : "=r" (contextidr), "+r" (pid) - : "I" (ASID_BITS)); + : "I" (~ASID_MASK)); isb(); return NOTIFY_OK; From df547e08e800275a431e560a7f0a6b6f24ab2904 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 24 Aug 2012 15:23:06 +0100 Subject: [PATCH 163/665] ARM: 7503/1: mm: only flush both pmd entries for classic MMU LPAE does not use two pmd entries for a pte, so the additional tlb flushing is not required. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/tlb.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 314d4664eae7..99a19512ee26 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -199,6 +199,9 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, { pgtable_page_dtor(pte); +#ifdef CONFIG_ARM_LPAE + tlb_add_flush(tlb, addr); +#else /* * With the classic ARM MMU, a pte page has two corresponding pmd * entries, each covering 1MB. @@ -206,6 +209,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, addr &= PMD_MASK; tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); tlb_add_flush(tlb, addr + SZ_1M); +#endif tlb_remove_page(tlb, pte); } From 36418c516b31bff4ff949c7c618430a1a514debe Mon Sep 17 00:00:00 2001 From: Jonathan Austin Date: Thu, 23 Aug 2012 14:02:59 +0100 Subject: [PATCH 164/665] ARM: 7499/1: mm: Fix vmalloc overlap check for !HIGHMEM With !HIGHMEM, sanity_check_meminfo checks for banks that completely or partially overlap the vmalloc region. The test for partial overlap checks __va(bank->start + bank->size) > vmalloc_min. This is not appropriate if there is a non-linear translation between virtual and physical addresses, as bank->start + bank->size is actually in the bank following the one being interrogated. In most cases, even when using SPARSEMEM, this is not problematic as the subsequent bank will start at a higher va than the one in question. However if the physical to virtual address conversion is not monotonic increasing, the incorrect test could result in a bank not being truncated when it should be. This patch ensures we perform the va-pa conversion on memory from the bank we are interested in, not the following one. Reported-by: ??? (Steve) Signed-off-by: Jonathan Austin Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index eab94bc6f805..c2fa21d0103e 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -961,8 +961,8 @@ void __init sanity_check_meminfo(void) * Check whether this memory bank would partially overlap * the vmalloc area. */ - if (__va(bank->start + bank->size) > vmalloc_min || - __va(bank->start + bank->size) < __va(bank->start)) { + if (__va(bank->start + bank->size - 1) >= vmalloc_min || + __va(bank->start + bank->size - 1) <= __va(bank->start)) { unsigned long newsize = vmalloc_min - __va(bank->start); printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " "to -%.8llx (vmalloc region overlap).\n", From d8c3bb911f5afc32f7276c2e2e89eb58af4306ae Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 18:10:42 +0100 Subject: [PATCH 165/665] ASoC: dapm: Make sure we update the bias level for CODECs with no op Commit 412312 (ASoC: dapm: Make sure all dapm contexts are updated) ensures that we update non-CODEC DAPM contexts but means that if a CODEC has no set_bias_level() operation it'll not be updated. Fix that. Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dd7c49fafd75..145ec4b56ca9 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -291,6 +291,8 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, if (dapm->codec->driver->set_bias_level) ret = dapm->codec->driver->set_bias_level(dapm->codec, level); + else + dapm->bias_level = level; } else dapm->bias_level = level; From 4e872a46823c64e655d997e1e04a4b32e326aa1b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 18:20:49 +0100 Subject: [PATCH 166/665] ASoC: dapm: Don't force card bias level to be updated Commit 412312 (ASoC: dapm: Make sure all dapm contexts are updated) means that any DAPM context being updated will have the bias level automatically set, including the card. We can't safely do this as the card callbacks are called for each device context and so the management of the card bias is more complex. Several multi-component cards rely on this behaviour. Skip updates during the asynchronous run entirely. We should really do them in the synchronous section but it's not 100% clear which values to pick as the different DAPM contexts may have different bias levels. Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 145ec4b56ca9..f90139b5f50d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -293,8 +293,9 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, level); else dapm->bias_level = level; - } else + } else if (!card || dapm != &card->dapm) { dapm->bias_level = level; + } if (ret != 0) goto out; From 1549c34bfdf3dc29b769c803f6cfdc53dfc67f93 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 17:50:52 +0100 Subject: [PATCH 167/665] ASoC: wm0010: Fix passthrough routing Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 8e0b6d6bffaf..e1315e0e7856 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -119,7 +119,8 @@ struct wm0010_spi_msg { }; static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { - { "SDI2 Playback", NULL, "SDI1 Playback" }, + { "SDI2 Capture", NULL, "SDI1 Playback" }, + { "SDI1 Capture", NULL, "SDI2 Playback" }, }; static const char *wm0010_state_to_str(enum wm0010_state state) From f9372c9c06166dc24a17cf25d325d83a9a06a02d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 17:05:48 +0100 Subject: [PATCH 168/665] ASoC: samsung: Add hookup of WM0010 on Speyside The Speyside platform by default has a WM0010 fitted. Now that we have a public driver hook it up in the machine integration. Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 1 + sound/soc/samsung/speyside.c | 42 +++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fb5600083612..f17dd25e0f4a 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -191,6 +191,7 @@ config SND_SOC_SPEYSIDE select SND_SAMSUNG_I2S select SND_SOC_WM8996 select SND_SOC_WM9081 + select SND_SOC_WM0010 select SND_SOC_WM1250_EV1 config SND_SOC_TOBERMORY diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index a4a9fc7e8c76..c7e1c28528a4 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -25,7 +25,7 @@ static int speyside_set_bias_level(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { - struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; int ret; if (dapm->dev != codec_dai->dev) @@ -57,7 +57,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { - struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; int ret; if (dapm->dev != codec_dai->dev) @@ -126,6 +126,18 @@ static void speyside_set_polarity(struct snd_soc_codec *codec, snd_soc_dapm_sync(&codec->dapm); } +static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *dai = rtd->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(dai, 0, MCLK_AUDIO_RATE, 0); + if (ret < 0) + return ret; + + return 0; +} + static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai = rtd->codec_dai; @@ -172,17 +184,37 @@ static int speyside_late_probe(struct snd_soc_card *card) return 0; } +static const struct snd_soc_pcm_stream dsp_codec_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, +}; + static struct snd_soc_dai_link speyside_dai[] = { { - .name = "CPU", - .stream_name = "CPU", + .name = "CPU-DSP", + .stream_name = "CPU-DSP", .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm8996-aif1", + .codec_dai_name = "wm0010-sdi1", .platform_name = "samsung-audio", + .codec_name = "spi0.0", + .init = speyside_wm0010_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "DSP-CODEC", + .stream_name = "DSP-CODEC", + .cpu_dai_name = "wm0010-sdi2", + .codec_dai_name = "wm8996-aif1", .codec_name = "wm8996.1-001a", .init = speyside_wm8996_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + .params = &dsp_codec_params, + .ignore_suspend = 1, }, { .name = "Baseband", From 6df3198635e2ad961952566a05994bc592abe774 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 14:05:35 +0100 Subject: [PATCH 169/665] ASoC: wm0010: Enable 44.1kHz support With appropriate clocking configuration the WM0010 driver supports 44.1kHz audio; enable that. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index e1315e0e7856..f820b5725163 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -722,7 +722,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), }; -#define WM0010_RATES (SNDRV_PCM_RATE_48000) +#define WM0010_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) #define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S32_LE) From 1470bfacb675ab0e25c30c97772a764ca16e0e52 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 09:17:42 -0700 Subject: [PATCH 170/665] ASoC: wm0010: Add dummy widget for CLKIN Make it easier to integrate the management of the clock supplying the WM0010 with DAPM by providing a dummy supply widget which supplies the interface widgets, this can be connected to clock outputs by the machines. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index f820b5725163..b6f7097d7953 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -118,9 +118,18 @@ struct wm0010_spi_msg { size_t len; }; +static const struct snd_soc_dapm_widget wm0010_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("CLKIN", SND_SOC_NOPM, 0, 0, NULL, 0), +}; + static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { { "SDI2 Capture", NULL, "SDI1 Playback" }, { "SDI1 Capture", NULL, "SDI2 Playback" }, + + { "SDI1 Capture", NULL, "CLKIN" }, + { "SDI2 Capture", NULL, "CLKIN" }, + { "SDI1 Playback", NULL, "CLKIN" }, + { "SDI2 Playback", NULL, "CLKIN" }, }; static const char *wm0010_state_to_str(enum wm0010_state state) @@ -718,6 +727,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .set_bias_level = wm0010_set_bias_level, .set_sysclk = wm0010_set_sysclk, + .dapm_widgets = wm0010_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), .dapm_routes = wm0010_dapm_routes, .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), }; From d3fd716e82ed643d804c49ca9ca554079c429a5c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 09:23:40 -0700 Subject: [PATCH 171/665] ASoC: wm0010: Set idle_bias_off Doesn't make any practical difference given that _SUSPEND and _OFF are equivalent for the driver but it's what we're really doing. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index b6f7097d7953..61ec7633fe5a 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -726,6 +726,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .probe = wm0010_probe, .set_bias_level = wm0010_set_bias_level, .set_sysclk = wm0010_set_sysclk, + .idle_bias_off = true, .dapm_widgets = wm0010_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), From 4f3c3c1b32bb8fddcd7f626c2fb09d55f469f976 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 09:24:16 -0700 Subject: [PATCH 172/665] ASoC: wm0010: Don't double free reset GPIO We are using devm_ to allocate the GPIO so it will be freed automatically. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 61ec7633fe5a..6c4a2fa90fbe 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -917,7 +917,6 @@ static int __devexit wm0010_spi_remove(struct spi_device *spi) if (wm0010->gpio_reset) { /* Remember to put chip back into reset */ gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); - gpio_free(wm0010->gpio_reset); } if (wm0010->irq) From bf9d323722845c8643287dca436e04e34cb21bb8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 13:01:15 -0700 Subject: [PATCH 173/665] ASoC: wm0010: Tweak diagnostic output Make it scan better by writing ROM with capitals. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 6c4a2fa90fbe..30ec0bd85307 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -137,7 +137,7 @@ static const char *wm0010_state_to_str(enum wm0010_state state) const char *state_to_str[] = { "Power off", "Out of reset", - "Bootrom", + "Boot ROM", "Stage2", "Firmware" }; From 32c50a31aad77e8faf2718d149da13f2136c1b46 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 13:04:04 -0700 Subject: [PATCH 174/665] ASoC: wm0010: Move resource acquisition to device probe This is more idimatic for modern drivers. Also fix a couple of return codes while we're at it. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 54 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 30ec0bd85307..5f99148447e1 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -799,14 +799,35 @@ static irqreturn_t wm0010_irq(int irq, void *data) static int wm0010_probe(struct snd_soc_codec *codec) { struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); - struct spi_device *spi = to_spi_device(wm0010->dev); + + wm0010->codec = codec; + + return 0; +} + +static int __devinit wm0010_spi_probe(struct spi_device *spi) +{ unsigned long flags; unsigned long gpio_flags; int ret; int trigger; int irq; + struct wm0010_priv *wm0010; - wm0010->codec = codec; + wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), + GFP_KERNEL); + if (!wm0010) + return -ENOMEM; + + mutex_init(&wm0010->lock); + spin_lock_init(&wm0010->irq_lock); + + spi_set_drvdata(spi, wm0010); + wm0010->dev = &spi->dev; + + if (dev_get_platdata(&spi->dev)) + memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), + sizeof(wm0010->pdata)); init_completion(&wm0010->boot_completion); @@ -850,7 +871,7 @@ static int wm0010_probe(struct snd_soc_codec *codec) } } else { dev_err(wm0010->dev, "No reset GPIO configured\n"); - return ret; + return -EINVAL; } irq = spi->irq; @@ -862,9 +883,11 @@ static int wm0010_probe(struct snd_soc_codec *codec) ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, "wm0010", wm0010); - if (ret) + if (ret) { dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", irq, ret); + return ret; + } wm0010->irq = irq; if (spi->max_speed_hz) @@ -876,29 +899,6 @@ static int wm0010_probe(struct snd_soc_codec *codec) wm0010->state = WM0010_POWER_OFF; spin_unlock_irqrestore(&wm0010->irq_lock, flags); - return 0; -} - -static int __devinit wm0010_spi_probe(struct spi_device *spi) -{ - struct wm0010_priv *wm0010; - int ret; - - wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), - GFP_KERNEL); - if (!wm0010) - return -ENOMEM; - - mutex_init(&wm0010->lock); - spin_lock_init(&wm0010->irq_lock); - - spi_set_drvdata(spi, wm0010); - wm0010->dev = &spi->dev; - - if (dev_get_platdata(&spi->dev)) - memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), - sizeof(wm0010->pdata)); - ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm0010, wm0010_dai, ARRAY_SIZE(wm0010_dai)); From 28739dfcffaad629b28cbab947193b259f745ea9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:40 +0300 Subject: [PATCH 175/665] ASoC: omap-mcbsp: Check mcbsp->id instead of cpu_dai->id when adding ST controls In ddevice tree booted kernel all device have unique name and their device id is set to 0. Use the mcbsp->id for checking to decide which control set we should add for McBSP sidetone handling. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 2e1750e2ab31..20d30c9ae573 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -722,7 +722,7 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) if (!mcbsp->st_data) return -ENODEV; - switch (cpu_dai->id) { + switch (mcbsp->id) { case 2: /* McBSP 2 */ return snd_soc_add_dai_controls(cpu_dai, omap_mcbsp2_st_controls, From 8a88df4cda5eaed97e027f9c9e76012a7113bf9a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:41 +0300 Subject: [PATCH 176/665] ASoC: omap-mcbsp: Only print warning if the st_data is missing for the port When asked to add the ST controls warn only if the st_data is missing. In this way we do not block the otherwise functional card to probe. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 20d30c9ae573..c1f466e1b8b6 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -719,8 +719,10 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - if (!mcbsp->st_data) - return -ENODEV; + if (!mcbsp->st_data) { + dev_warn(mcbsp->dev, "No sidetone data for port\n"); + return 0; + } switch (mcbsp->id) { case 2: /* McBSP 2 */ From 8996a31c58374742dfb555675a8569617572d82c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:42 +0300 Subject: [PATCH 177/665] ASoC: omap-mcbsp: Use macro to create the McBSP2/3 ST controls To remove duplicated code from the driver. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 39 ++++++++++++++----------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index c1f466e1b8b6..1b9f5ebba44f 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -688,31 +688,22 @@ static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { - SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, - omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), -}; +#define OMAP_MCBSP_ST_CONTROLS(port) \ +static const struct snd_kcontrol_new omap_mcbsp##port##_st_controls[] = { \ +SOC_SINGLE_EXT("McBSP" #port " Sidetone Switch", 1, 0, 1, 0, \ + omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), \ +OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 0 Volume", \ + -32768, 32767, \ + omap_mcbsp_get_st_ch0_volume, \ + omap_mcbsp_set_st_ch0_volume), \ +OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \ + -32768, 32767, \ + omap_mcbsp_get_st_ch1_volume, \ + omap_mcbsp_set_st_ch1_volume), \ +} -static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { - SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, - omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), -}; +OMAP_MCBSP_ST_CONTROLS(2); +OMAP_MCBSP_ST_CONTROLS(3); int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) { From db61550931957ee6c7dba751662919424b4344f3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:43 +0300 Subject: [PATCH 178/665] ASoC: omap-mcbsp: Single macro for st channel volume set/get Since we always need to have set and get callbacks for McBSP sidetone it makes sense to combine the two macro to create the two callbacks. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 1b9f5ebba44f..9dff177cd4e2 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -619,9 +619,9 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, return 0; } -#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \ +#define OMAP_MCBSP_ST_CHANNEL_VOLUME(channel) \ static int \ -omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ +omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ struct snd_ctl_elem_value *uc) \ { \ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ @@ -637,11 +637,10 @@ omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ \ /* OMAP McBSP implementation uses index values 0..4 */ \ return omap_st_set_chgain(mcbsp, channel, val); \ -} - -#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \ +} \ + \ static int \ -omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ +omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ struct snd_ctl_elem_value *uc) \ { \ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ @@ -655,10 +654,8 @@ omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ return 0; \ } -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1) +OMAP_MCBSP_ST_CHANNEL_VOLUME(0) +OMAP_MCBSP_ST_CHANNEL_VOLUME(1) static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) From 760a9a30adc558a75916a13902f38c6792fa8c4b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 22 Aug 2012 14:34:11 +0100 Subject: [PATCH 179/665] kvm: Fix nonsense handling of compat ioctl KVM_SET_SIGNAL_MASK passed a NULL argument leaves the on stack signal sets uninitialized. It then passes them through to kvm_vcpu_ioctl_set_sigmask. We should be passing a NULL in this case not translated garbage. Signed-off-by: Alan Cox Signed-off-by: Marcelo Tosatti --- virt/kvm/kvm_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 246852397e30..d617f69131d7 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1976,9 +1976,10 @@ static long kvm_vcpu_compat_ioctl(struct file *filp, if (copy_from_user(&csigset, sigmask_arg->sigset, sizeof csigset)) goto out; - } - sigset_from_compat(&sigset, &csigset); - r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); + sigset_from_compat(&sigset, &csigset); + r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); + } else + r = kvm_vcpu_ioctl_set_sigmask(vcpu, NULL); break; } default: From 13b5533a38b1eec9d61a07711dc075f03ae47a36 Mon Sep 17 00:00:00 2001 From: Benjamin Wang Date: Sun, 26 Aug 2012 18:04:10 +0800 Subject: [PATCH 180/665] target: Check idr_get_new return value in iscsi_login_zero_tsih_s1 This patch updates iscsi_login_zero_tsih_s1() usage for generating iscsi_session->session_index to properly check the return value from idr_get_new(), and reject the iSCSI login attempt with exception status ISCSI_LOGIN_STATUS_NO_RESOURCES in the event of a failure. Signed-off-by: Benjamin Wang Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 0694d9b1bce6..6aba4395e8d8 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -221,6 +221,7 @@ static int iscsi_login_zero_tsih_s1( { struct iscsi_session *sess = NULL; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; + int ret; sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); if (!sess) { @@ -257,9 +258,17 @@ static int iscsi_login_zero_tsih_s1( return -ENOMEM; } spin_lock(&sess_idr_lock); - idr_get_new(&sess_idr, NULL, &sess->session_index); + ret = idr_get_new(&sess_idr, NULL, &sess->session_index); spin_unlock(&sess_idr_lock); + if (ret < 0) { + pr_err("idr_get_new() for sess_idr failed\n"); + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_NO_RESOURCES); + kfree(sess); + return -ENOMEM; + } + sess->creation_time = get_jiffies_64(); spin_lock_init(&sess->session_stats_lock); /* From e3e45c01ae690e65f2650e5288b9af802e95a136 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Fri, 24 Aug 2012 15:34:34 +0200 Subject: [PATCH 181/665] perf/x86: Fix microcode revision check for SNB-PEBS The following patch makes the microcode update code path actually invoke the perf_check_microcode() function and thus potentially renabling SNB PEBS. By default, CONFIG_MICROCODE_OLD_INTERFACE is forced to Y in arch/x86/Kconfig. There is no way to disable this. That means that the code path used in arch/x86/kernel/microcode_core.c did not include the call to perf_check_microcode(). Thus, even though the microcode was updated to a version that fixes the SNB PEBS problem, perf_event would still return EOPNOTSUPP when enabling precise sampling. This patch simply adds a call to perf_check_microcode() in the call path used when OLD_INTERFACE=y. Signed-off-by: Stephane Eranian Acked-by: Borislav Petkov Cc: peterz@infradead.org Cc: andi@firstfloor.org Link: http://lkml.kernel.org/r/20120824133434.GA8014@quad Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 4873e62db6a1..9e5bcf1e2376 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -225,6 +225,9 @@ static ssize_t microcode_write(struct file *file, const char __user *buf, if (do_microcode_update(buf, len) == 0) ret = (ssize_t)len; + if (ret > 0) + perf_check_microcode(); + mutex_unlock(µcode_mutex); put_online_cpus(); From 51a6149b89b822cacf572b2ca2a15cb6f2232b11 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 23 Aug 2012 15:05:07 +0200 Subject: [PATCH 182/665] ARM: at91/feature-removal-schedule: delay at91_mci removal Delay sd/mmc driver at91_mci.c removal because of tight schedule to move platform data to new driver atmel-mci. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre --- Documentation/feature-removal-schedule.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index afaff312bf41..f4d8c7105fcd 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -579,7 +579,7 @@ Why: KVM tracepoints provide mostly equivalent information in a much more ---------------------------- What: at91-mci driver ("CONFIG_MMC_AT91") -When: 3.7 +When: 3.8 Why: There are two mci drivers: at91-mci and atmel-mci. The PDC support was added to atmel-mci as a first step to support more chips. Then at91-mci was kept only for old IP versions (on at91rm9200 and From 81ff3478d9ba7f0b48b0abef740e542fd83adf79 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 19 Jul 2012 18:28:26 +0200 Subject: [PATCH 183/665] oprofile, s390: Fix uninitialized memory access when writing to oprofilefs If oprofilefs_ulong_from_user() is called with count equals zero, *val remains unchanged. Depending on the implementation it might be uninitialized. Fixing users of oprofilefs_ulong_ from_user(). We missed these s390 changes with: 913050b oprofile: Fix uninitialized memory access when writing to writing to oprofilefs Cc: stable@vger.kernel.org # 3.3+ Signed-off-by: Robert Richter --- arch/s390/oprofile/init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index a1e9d69a9c90..584b93674ea4 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -169,7 +169,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf, if (*offset) return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val < oprofile_min_interval) oprofile_hw_interval = oprofile_min_interval; @@ -212,7 +212,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0) return -EINVAL; @@ -243,7 +243,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) @@ -278,7 +278,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) @@ -317,7 +317,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) From 1fa6535faf055cd71311ab887e94fc234f04ee18 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 25 Aug 2012 19:28:06 +0200 Subject: [PATCH 184/665] Bluetooth: Add support for Apple vendor-specific devices As pointed out by Gustavo and Marcel, all Apple-specific Broadcom devices seen so far have the same interface class, subclass and protocol numbers. This patch adds an entry which matches all of them, using the new USB_VENDOR_AND_INTERFACE_INFO() macro. In particular, this patch adds support for the MacBook Pro Retina (05ac:8286), which is not in the present list. Signed-off-by: Henrik Rydberg Tested-by: Shea Levy Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e791b20beaf5..654e248763ef 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -52,6 +52,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple-specific (Broadcom) devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + /* Broadcom SoftSailing reporting vendor specific */ { USB_DEVICE(0x0a5c, 0x21e1) }, From 67ddbb3e6568fb1820b2cc45b00c50702b114801 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Aug 2012 10:51:55 -0400 Subject: [PATCH 185/665] HID: add NOGET quirk for Eaton Ellipse MAX UPS This patch (as1603) adds a NOGET quirk for the Eaton Ellipse MAX UPS device. (The USB IDs were already present in hid-ids.h, apparently under a different name.) Signed-off-by: Alan Stern Reported-by: Laurent Bigonville CC: Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 903eef3d3e10..991e85c7325c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -70,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { 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 }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, From cc110922da7e902b62d18641a370fec01a9fa794 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 23 Aug 2012 21:32:43 -0300 Subject: [PATCH 186/665] Bluetooth: Change signature of smp_conn_security() To make it clear that it may be called from contexts that may not have any knowledge of L2CAP, we change the connection parameter, to receive a hci_conn. This also makes it clear that it is checking the security of the link. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- include/net/bluetooth/smp.h | 2 +- net/bluetooth/l2cap_core.c | 11 ++++++----- net/bluetooth/l2cap_sock.c | 2 +- net/bluetooth/smp.c | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index ca356a734920..8b27927b2a55 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h @@ -136,7 +136,7 @@ struct smp_chan { }; /* SMP Commands */ -int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level); +int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index daa149b7003c..4ea1710a4783 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1199,14 +1199,15 @@ clean: static void l2cap_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan *chan; + struct hci_conn *hcon = conn->hcon; BT_DBG("conn %p", conn); - if (!conn->hcon->out && conn->hcon->type == LE_LINK) + if (!hcon->out && hcon->type == LE_LINK) l2cap_le_conn_ready(conn); - if (conn->hcon->out && conn->hcon->type == LE_LINK) - smp_conn_security(conn, conn->hcon->pending_sec_level); + if (hcon->out && hcon->type == LE_LINK) + smp_conn_security(hcon, hcon->pending_sec_level); mutex_lock(&conn->chan_lock); @@ -1219,8 +1220,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) continue; } - if (conn->hcon->type == LE_LINK) { - if (smp_conn_security(conn, chan->sec_level)) + if (hcon->type == LE_LINK) { + if (smp_conn_security(hcon, chan->sec_level)) l2cap_chan_ready(chan); } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b94abd30e6f9..45cb0b0dd2c7 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -615,7 +615,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch break; } - if (smp_conn_security(conn, sec.level)) + if (smp_conn_security(conn->hcon, sec.level)) break; sk->sk_state = BT_CONFIG; chan->state = BT_CONFIG; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 98ffc1b6a6fa..8c225ef349cd 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -760,9 +760,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) return 0; } -int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) +int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) { - struct hci_conn *hcon = conn->hcon; + struct l2cap_conn *conn = hcon->l2cap_data; struct smp_chan *smp = conn->smp_chan; __u8 authreq; From d8343f125710fb596f7a88cd756679f14f4e77b9 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 23 Aug 2012 21:32:44 -0300 Subject: [PATCH 187/665] Bluetooth: Fix sending a HCI Authorization Request over LE links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case that the link is already in the connected state and a Pairing request arrives from the mgmt interface, hci_conn_security() would be called but it was not considering LE links. Reported-by: João Paulo Rechi Vita Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5ad7da217474..3c094e78dde9 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -29,6 +29,7 @@ #include #include #include +#include static void hci_le_connect(struct hci_conn *conn) { @@ -619,6 +620,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) { BT_DBG("hcon %p", conn); + if (conn->type == LE_LINK) + return smp_conn_security(conn, sec_level); + /* For sdp we don't need the link key. */ if (sec_level == BT_SECURITY_SDP) return 1; From 9bb280a2eb9f4bc951549dceb1d4e0b0a316eb95 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 27 Aug 2012 17:00:26 +0530 Subject: [PATCH 188/665] ASoC: tlv320aic26: Use module_spi_driver module_spi_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic26.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 85944e953578..b1f6982c7c9c 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -444,14 +444,4 @@ static struct spi_driver aic26_spi = { .remove = aic26_spi_remove, }; -static int __init aic26_init(void) -{ - return spi_register_driver(&aic26_spi); -} -module_init(aic26_init); - -static void __exit aic26_exit(void) -{ - spi_unregister_driver(&aic26_spi); -} -module_exit(aic26_exit); +module_spi_driver(aic26_spi); From a5c8878017dd3b51f6f97a36d90c405f8061fe83 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 27 Aug 2012 17:00:27 +0530 Subject: [PATCH 189/665] ASoC: wm8770: Use module_spi_driver module_spi_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8770.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index a5127b4ff9e1..c7c0034d3966 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -724,24 +724,7 @@ static struct spi_driver wm8770_spi_driver = { .remove = __devexit_p(wm8770_spi_remove) }; -static int __init wm8770_modinit(void) -{ - int ret = 0; - - ret = spi_register_driver(&wm8770_spi_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n", - ret); - } - return ret; -} -module_init(wm8770_modinit); - -static void __exit wm8770_exit(void) -{ - spi_unregister_driver(&wm8770_spi_driver); -} -module_exit(wm8770_exit); +module_spi_driver(wm8770_spi_driver); MODULE_DESCRIPTION("ASoC WM8770 driver"); MODULE_AUTHOR("Dimitris Papastamos "); From 2a9a9c876fd6486978a24cd8bc72bd1aeb228b7b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 27 Aug 2012 17:00:28 +0530 Subject: [PATCH 190/665] ASoC: ad1836: Use module_spi_driver module_spi_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/ad1836.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index c67b50d8b317..ae1eb51bc9da 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -379,17 +379,7 @@ static struct spi_driver ad1836_spi_driver = { .id_table = ad1836_ids, }; -static int __init ad1836_init(void) -{ - return spi_register_driver(&ad1836_spi_driver); -} -module_init(ad1836_init); - -static void __exit ad1836_exit(void) -{ - spi_unregister_driver(&ad1836_spi_driver); -} -module_exit(ad1836_exit); +module_spi_driver(ad1836_spi_driver); MODULE_DESCRIPTION("ASoC ad1836 driver"); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); From c24fdc886fde9ce7bda8115b9c2b338818796c65 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:44 +0530 Subject: [PATCH 191/665] ASoC: tlv320aic3x: Add device tree bindings Device tree support for tlv320aic3x CODEC driver. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic3x.txt | 20 ++++++++++++ sound/soc/codecs/tlv320aic3x.c | 31 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic3x.txt diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt new file mode 100644 index 000000000000..e7b98f41fa5f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt @@ -0,0 +1,20 @@ +Texas Instruments - tlv320aic3x Codec module + +The tlv320aic3x serial control bus communicates through I2C protocols + +Required properties: +- compatible - "string" - "ti,tlv320aic3x" +- reg - - I2C slave address + + +Optional properties: + +- gpio-reset - gpio pin number used for codec reset +- ai3x-gpio-func - - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality + +Example: + +tlv320aic3x: tlv320aic3x@1b { + compatible = "ti,tlv320aic3x"; + reg = <0x1b>; +}; diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 01485bd51404..5708a973a776 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -1457,6 +1458,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, { struct aic3x_pdata *pdata = i2c->dev.platform_data; struct aic3x_priv *aic3x; + struct aic3x_setup_data *ai3x_setup; + struct device_node *np = i2c->dev.of_node; int ret; aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); @@ -1471,6 +1474,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, if (pdata) { aic3x->gpio_reset = pdata->gpio_reset; aic3x->setup = pdata->setup; + } else if (np) { + ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), + GFP_KERNEL); + if (ai3x_setup == NULL) { + dev_err(&i2c->dev, "failed to create private data\n"); + return -ENOMEM; + } + + ret = of_get_named_gpio(np, "gpio-reset", 0); + if (ret >= 0) + aic3x->gpio_reset = ret; + else + aic3x->gpio_reset = -1; + + if (of_property_read_u32_array(np, "ai3x-gpio-func", + ai3x_setup->gpio_func, 2) >= 0) { + aic3x->setup = ai3x_setup; + } + } else { aic3x->gpio_reset = -1; } @@ -1488,11 +1510,20 @@ static int aic3x_i2c_remove(struct i2c_client *client) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id tlv320aic3x_of_match[] = { + { .compatible = "ti,tlv320aic3x", }, + {}, +}; +MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); +#endif + /* machine i2c codec control layer */ static struct i2c_driver aic3x_i2c_driver = { .driver = { .name = "tlv320aic3x-codec", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tlv320aic3x_of_match), }, .probe = aic3x_i2c_probe, .remove = aic3x_i2c_remove, From 50d4b3062d6d4f165c76854a7644b1502836f9b9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 18 Aug 2012 09:48:00 +0100 Subject: [PATCH 192/665] staging:iio: prevent divide by zero bugs "val" is used as a divisor later, so we should check for zero here to avoid a division by zero. Signed-off-by: Dan Carpenter Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 ++ drivers/staging/iio/gyro/adis16260_core.c | 2 ++ drivers/staging/iio/imu/adis16400_core.c | 2 ++ drivers/staging/iio/meter/ade7753.c | 2 ++ drivers/staging/iio/meter/ade7754.c | 2 ++ drivers/staging/iio/meter/ade7759.c | 2 ++ 6 files changed, 12 insertions(+) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 095837285f4f..19a064d649e3 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -647,6 +647,8 @@ static ssize_t ad7192_write_frequency(struct device *dev, ret = strict_strtoul(buf, 10, &lval); if (ret) return ret; + if (lval == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) { diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 93aa431287ac..eb8e9d69efd3 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -195,6 +195,8 @@ static ssize_t adis16260_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); if (spi_get_device_id(st->us)) { diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 1f4c17779b5a..a618327e06ed 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -234,6 +234,8 @@ static ssize_t adis16400_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index f04ece7fbc2f..3ccff189f258 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -425,6 +425,8 @@ static ssize_t ade7753_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 6cee28a5e877..abb1e9c8d094 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -445,6 +445,8 @@ static ssize_t ade7754_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index b3f7e0fa9612..eb0a2a98f388 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -385,6 +385,8 @@ static ssize_t ade7759_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); From d1dc9c1276a4d988b29372fe67796430d5cbc756 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 22 Aug 2012 20:37:00 +0100 Subject: [PATCH 193/665] staging iio: fix potential memory leak in lis3l02dq_ring.c Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/lis3l02dq_ring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 18d108fd967a..f3da59063ed2 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -121,8 +121,10 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev, if (rx_array == NULL) return -ENOMEM; ret = lis3l02dq_read_all(indio_dev, rx_array); - if (ret < 0) + if (ret < 0) { + kfree(rx_array); return ret; + } for (i = 0; i < scan_count; i++) data[i] = combine_8_to_16(rx_array[i*4+1], rx_array[i*4+3]); From f08095a408bf6489b4a710d794ae6d5475a007ef Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:39 +0530 Subject: [PATCH 194/665] ASoC: davinci: davinci-pcm does not need to be a plaform_driver Same as the commit 518de86 (ASoC: tegra: register 'platform' from DAIs, get rid of pdev). It makes davinci-pcm not a platform_driver but helper to register "platform", so that the platform_device for davinci-pcm can be saved completely. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 15 ++++++++------- sound/soc/davinci/davinci-i2s.c | 10 ++++++++++ sound/soc/davinci/davinci-mcasp.c | 10 ++++++++++ sound/soc/davinci/davinci-pcm.c | 23 ++++++----------------- sound/soc/davinci/davinci-pcm.h | 3 +++ sound/soc/davinci/davinci-sffsdr.c | 2 +- sound/soc/davinci/davinci-vcif.c | 8 ++++++++ 7 files changed, 46 insertions(+), 25 deletions(-) diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index c80c20a89b11..4b37e2ac4685 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -159,7 +159,7 @@ static struct snd_soc_dai_link dm6446_evm_dai = { .cpu_dai_name = "davinci-mcbsp", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcbsp", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -170,7 +170,7 @@ static struct snd_soc_dai_link dm355_evm_dai = { .cpu_dai_name = "davinci-mcbsp.1", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcbsp.1", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -184,14 +184,15 @@ static struct snd_soc_dai_link dm365_evm_dai = { .init = evm_aic3x_init, .codec_name = "tlv320aic3x-codec.1-0018", .ops = &evm_ops, + .platform_name = "davinci-mcbsp", #elif defined(CONFIG_SND_DM365_VOICE_CODEC) .name = "Voice Codec - CQ93VC", .stream_name = "CQ93", .cpu_dai_name = "davinci-vcif", .codec_dai_name = "cq93vc-hifi", .codec_name = "cq93vc-codec", + .platform_name = "avinci-vcif", #endif - .platform_name = "davinci-pcm-audio", }; static struct snd_soc_dai_link dm6467_evm_dai[] = { @@ -200,7 +201,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { .stream_name = "AIC3X", .cpu_dai_name= "davinci-mcasp.0", .codec_dai_name = "tlv320aic3x-hifi", - .platform_name ="davinci-pcm-audio", + .platform_name = "davinci-mcasp.0", .codec_name = "tlv320aic3x-codec.0-001a", .init = evm_aic3x_init, .ops = &evm_ops, @@ -211,7 +212,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { .cpu_dai_name= "davinci-mcasp.1", .codec_dai_name = "dit-hifi", .codec_name = "spdif_dit", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcasp.1", .ops = &evm_spdif_ops, }, }; @@ -222,7 +223,7 @@ static struct snd_soc_dai_link da830_evm_dai = { .cpu_dai_name = "davinci-mcasp.1", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcasp.1", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -233,7 +234,7 @@ static struct snd_soc_dai_link da850_evm_dai = { .cpu_dai_name= "davinci-mcasp.0", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcasp.0", .init = evm_aic3x_init, .ops = &evm_ops, }; diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 0a74b9587a2c..407df7233d6d 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -732,8 +732,16 @@ static int davinci_i2s_probe(struct platform_device *pdev) if (ret != 0) goto err_release_clk; + ret = davinci_soc_platform_register(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + goto err_unregister_dai; + } + return 0; +err_unregister_dai: + snd_soc_unregister_dai(&pdev->dev); err_release_clk: clk_disable(dev->clk); clk_put(dev->clk); @@ -745,6 +753,8 @@ static int davinci_i2s_remove(struct platform_device *pdev) struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); + davinci_soc_platform_unregister(&pdev->dev); + clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index d919fb8de7a3..8f3c5a4cf537 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -945,8 +945,17 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (ret != 0) goto err_release_clk; + + ret = davinci_soc_platform_register(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + goto err_unregister_dai; + } + return 0; +err_unregister_dai: + snd_soc_unregister_dai(&pdev->dev); err_release_clk: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -957,6 +966,7 @@ static int davinci_mcasp_remove(struct platform_device *pdev) { snd_soc_unregister_dai(&pdev->dev); + davinci_soc_platform_unregister(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 97d77b298968..4b70828beedb 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -864,28 +864,17 @@ static struct snd_soc_platform_driver davinci_soc_platform = { .pcm_free = davinci_pcm_free, }; -static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) +int davinci_soc_platform_register(struct device *dev) { - return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); + return snd_soc_register_platform(dev, &davinci_soc_platform); } +EXPORT_SYMBOL_GPL(davinci_soc_platform_register); -static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) +void davinci_soc_platform_unregister(struct device *dev) { - snd_soc_unregister_platform(&pdev->dev); - return 0; + snd_soc_unregister_platform(dev); } - -static struct platform_driver davinci_pcm_driver = { - .driver = { - .name = "davinci-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = davinci_soc_platform_probe, - .remove = __devexit_p(davinci_soc_platform_remove), -}; - -module_platform_driver(davinci_pcm_driver); +EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister); MODULE_AUTHOR("Vladimir Barinov"); MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index c0d6c9be4b4d..5e5516460461 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -28,4 +28,7 @@ struct davinci_pcm_dma_params { unsigned int fifo_level; }; +int davinci_soc_platform_register(struct device *dev); +void davinci_soc_platform_unregister(struct device *dev); + #endif diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index f71175b29e38..5be65aae7e0e 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -86,7 +86,7 @@ static struct snd_soc_dai_link sffsdr_dai = { .cpu_dai_name = "davinci-mcbsp", .codec_dai_name = "pcm3008-hifi", .codec_name = "pcm3008-codec", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcbsp", .ops = &sffsdr_ops, }; diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index da030ff883d5..07bde2e6f84e 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c @@ -240,12 +240,20 @@ static int davinci_vcif_probe(struct platform_device *pdev) return ret; } + ret = davinci_soc_platform_register(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + snd_soc_unregister_dai(&pdev->dev); + return ret; + } + return 0; } static int davinci_vcif_remove(struct platform_device *pdev) { snd_soc_unregister_dai(&pdev->dev); + davinci_soc_platform_unregister(&pdev->dev); return 0; } From bdd732786dc776ba3e4ccb6f5d6461a92a978582 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:40 +0530 Subject: [PATCH 195/665] ARM: Davinci: Remove references to davinci pcm Since davinci-pcm is no more a platform_driver but helper to register "platform" pcm driver, remove davinci-pcm device registration Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- arch/arm/mach-davinci/devices-da8xx.c | 7 ------- arch/arm/mach-davinci/devices.c | 11 ----------- 2 files changed, 18 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 783eab6845c4..4735d64fd6f2 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -505,15 +505,8 @@ static struct platform_device da850_mcasp_device = { .resource = da850_mcasp_resources, }; -static struct platform_device davinci_pcm_device = { - .name = "davinci-pcm-audio", - .id = -1, -}; - void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata) { - platform_device_register(&davinci_pcm_device); - /* DA830/OMAP-L137 has 3 instances of McASP */ if (cpu_is_davinci_da830() && id == 1) { da830_mcasp1_device.dev.platform_data = pdata; diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index d2f9666284a7..70056fb8cc06 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -313,16 +313,6 @@ static void davinci_init_wdt(void) /*-------------------------------------------------------------------------*/ -static struct platform_device davinci_pcm_device = { - .name = "davinci-pcm-audio", - .id = -1, -}; - -static void davinci_init_pcm(void) -{ - platform_device_register(&davinci_pcm_device); -} - /*-------------------------------------------------------------------------*/ struct davinci_timer_instance davinci_timer_instance[2] = { @@ -345,7 +335,6 @@ static int __init davinci_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - davinci_init_pcm(); davinci_init_wdt(); return 0; From 896f66b7de293644e65cf62600e4933af954dcf2 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:41 +0530 Subject: [PATCH 196/665] ASoC/ARM: Davinci: McASP: split asp header into platform and audio specific Davinci McASP header & driver are shared by few OMAP platforms (like TI81xx, AM335x). Splitting asp header into Davinci platform specific header and Audio specific header helps to share them across platforms. Audio specific defines is moved to to common so that the header can be accessed by all related platforms. While here, correct the header usage (remove multiple header re-definitions and unused headers) and remove platform names from structures comments and enum. Also some some coding style errors. Signed-off-by: Hebbar, Gururaja Acked-by: Vaibhav Bedia Signed-off-by: Mark Brown --- arch/arm/mach-davinci/asp.h | 49 +++++++++++++ arch/arm/mach-davinci/davinci.h | 3 +- arch/arm/mach-davinci/devices-da8xx.c | 1 + arch/arm/mach-davinci/dm355.c | 2 +- arch/arm/mach-davinci/dm365.c | 2 +- arch/arm/mach-davinci/dm644x.c | 2 +- arch/arm/mach-davinci/dm646x.c | 2 +- arch/arm/mach-davinci/include/mach/da8xx.h | 2 +- .../linux/platform_data/davinci_asp.h | 73 +++++-------------- sound/soc/davinci/davinci-evm.c | 3 - sound/soc/davinci/davinci-i2s.c | 3 +- sound/soc/davinci/davinci-mcasp.h | 3 +- sound/soc/davinci/davinci-pcm.c | 1 - sound/soc/davinci/davinci-pcm.h | 3 +- 14 files changed, 81 insertions(+), 68 deletions(-) create mode 100644 arch/arm/mach-davinci/asp.h rename arch/arm/mach-davinci/include/mach/asp.h => include/linux/platform_data/davinci_asp.h (56%) diff --git a/arch/arm/mach-davinci/asp.h b/arch/arm/mach-davinci/asp.h new file mode 100644 index 000000000000..d9b2acd12393 --- /dev/null +++ b/arch/arm/mach-davinci/asp.h @@ -0,0 +1,49 @@ +/* + * TI DaVinci Audio definitions + */ +#ifndef __ASM_ARCH_DAVINCI_ASP_H +#define __ASM_ARCH_DAVINCI_ASP_H + +/* Bases of dm644x and dm355 register banks */ +#define DAVINCI_ASP0_BASE 0x01E02000 +#define DAVINCI_ASP1_BASE 0x01E04000 + +/* Bases of dm365 register banks */ +#define DAVINCI_DM365_ASP0_BASE 0x01D02000 + +/* Bases of dm646x register banks */ +#define DAVINCI_DM646X_MCASP0_REG_BASE 0x01D01000 +#define DAVINCI_DM646X_MCASP1_REG_BASE 0x01D01800 + +/* Bases of da850/da830 McASP0 register banks */ +#define DAVINCI_DA8XX_MCASP0_REG_BASE 0x01D00000 + +/* Bases of da830 McASP1 register banks */ +#define DAVINCI_DA830_MCASP1_REG_BASE 0x01D04000 + +/* EDMA channels of dm644x and dm355 */ +#define DAVINCI_DMA_ASP0_TX 2 +#define DAVINCI_DMA_ASP0_RX 3 +#define DAVINCI_DMA_ASP1_TX 8 +#define DAVINCI_DMA_ASP1_RX 9 + +/* EDMA channels of dm646x */ +#define DAVINCI_DM646X_DMA_MCASP0_AXEVT0 6 +#define DAVINCI_DM646X_DMA_MCASP0_AREVT0 9 +#define DAVINCI_DM646X_DMA_MCASP1_AXEVT1 12 + +/* EDMA channels of da850/da830 McASP0 */ +#define DAVINCI_DA8XX_DMA_MCASP0_AREVT 0 +#define DAVINCI_DA8XX_DMA_MCASP0_AXEVT 1 + +/* EDMA channels of da830 McASP1 */ +#define DAVINCI_DA830_DMA_MCASP1_AREVT 2 +#define DAVINCI_DA830_DMA_MCASP1_AXEVT 3 + +/* Interrupts */ +#define DAVINCI_ASP0_RX_INT IRQ_MBRINT +#define DAVINCI_ASP0_TX_INT IRQ_MBXINT +#define DAVINCI_ASP1_RX_INT IRQ_MBRINT +#define DAVINCI_ASP1_TX_INT IRQ_MBXINT + +#endif /* __ASM_ARCH_DAVINCI_ASP_H */ diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h index 8db0fc6809dd..8661b2013527 100644 --- a/arch/arm/mach-davinci/davinci.h +++ b/arch/arm/mach-davinci/davinci.h @@ -22,10 +22,11 @@ #include #include #include +#include -#include #include #include +#include #include #include diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 4735d64fd6f2..bd2f72b414bc 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -24,6 +24,7 @@ #include #include "clock.h" +#include "asp.h" #define DA8XX_TPCC_BASE 0x01c00000 #define DA8XX_TPTC0_BASE 0x01c08000 diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 678cd99b7336..e47a3f0e8ac4 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -26,13 +26,13 @@ #include #include #include -#include #include #include #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" #define DM355_UART2_BASE (IO_PHYS + 0x206000) diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index a50d49de1883..f473745d6e3c 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" #define DM365_REF_FREQ 24000000 /* 24 MHz on the DM365 EVM */ diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index c8b866657fcb..0755d466221a 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -23,12 +23,12 @@ #include #include #include -#include #include #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" /* * Device specific clocks diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 9eb87c1d1edd..97c0f8e555bd 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -24,12 +24,12 @@ #include #include #include -#include #include #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" #define DAVINCI_VPIF_BASE (0x01C12000) diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index a2f1f274f189..c74a6abef187 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -16,11 +16,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/include/linux/platform_data/davinci_asp.h similarity index 56% rename from arch/arm/mach-davinci/include/mach/asp.h rename to include/linux/platform_data/davinci_asp.h index 9aa240909a2c..79c26aa11db6 100644 --- a/arch/arm/mach-davinci/include/mach/asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -1,59 +1,26 @@ /* - * - DaVinci Audio Serial Port support + * TI DaVinci Audio Serial Port support + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ -#ifndef __ASM_ARCH_DAVINCI_ASP_H -#define __ASM_ARCH_DAVINCI_ASP_H -#include -#include - -/* Bases of dm644x and dm355 register banks */ -#define DAVINCI_ASP0_BASE 0x01E02000 -#define DAVINCI_ASP1_BASE 0x01E04000 - -/* Bases of dm365 register banks */ -#define DAVINCI_DM365_ASP0_BASE 0x01D02000 - -/* Bases of dm646x register banks */ -#define DAVINCI_DM646X_MCASP0_REG_BASE 0x01D01000 -#define DAVINCI_DM646X_MCASP1_REG_BASE 0x01D01800 - -/* Bases of da850/da830 McASP0 register banks */ -#define DAVINCI_DA8XX_MCASP0_REG_BASE 0x01D00000 - -/* Bases of da830 McASP1 register banks */ -#define DAVINCI_DA830_MCASP1_REG_BASE 0x01D04000 - -/* EDMA channels of dm644x and dm355 */ -#define DAVINCI_DMA_ASP0_TX 2 -#define DAVINCI_DMA_ASP0_RX 3 -#define DAVINCI_DMA_ASP1_TX 8 -#define DAVINCI_DMA_ASP1_RX 9 - -/* EDMA channels of dm646x */ -#define DAVINCI_DM646X_DMA_MCASP0_AXEVT0 6 -#define DAVINCI_DM646X_DMA_MCASP0_AREVT0 9 -#define DAVINCI_DM646X_DMA_MCASP1_AXEVT1 12 - -/* EDMA channels of da850/da830 McASP0 */ -#define DAVINCI_DA8XX_DMA_MCASP0_AREVT 0 -#define DAVINCI_DA8XX_DMA_MCASP0_AXEVT 1 - -/* EDMA channels of da830 McASP1 */ -#define DAVINCI_DA830_DMA_MCASP1_AREVT 2 -#define DAVINCI_DA830_DMA_MCASP1_AXEVT 3 - -/* Interrupts */ -#define DAVINCI_ASP0_RX_INT IRQ_MBRINT -#define DAVINCI_ASP0_TX_INT IRQ_MBXINT -#define DAVINCI_ASP1_RX_INT IRQ_MBRINT -#define DAVINCI_ASP1_TX_INT IRQ_MBXINT +#ifndef __DAVINCI_ASP_H +#define __DAVINCI_ASP_H struct snd_platform_data { u32 tx_dma_offset; u32 rx_dma_offset; - enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ - enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ + int asp_chan_q; /* event queue number for ASP channel */ + int ram_chan_q; /* event queue number for RAM channel */ unsigned int codec_fmt; /* * Allowing this is more efficient and eliminates left and right swaps @@ -70,7 +37,7 @@ struct snd_platform_data { * and MCBSP_CLKS. * Depending on different hardware connections it is possible * to use this setting to change the behaviour of McBSP - * driver. The dm365_clk_input_pin enum is available for dm365 + * driver. */ int clk_input_pin; @@ -122,8 +89,8 @@ enum { MCASP_VERSION_2, /* DA8xx/OMAPL1x */ }; -enum dm365_clk_input_pin { - MCBSP_CLKR = 0, /* DM365 */ +enum mcbsp_clk_input_pin { + MCBSP_CLKR = 0, /* as in DM365 */ MCBSP_CLKS, }; @@ -134,4 +101,4 @@ enum dm365_clk_input_pin { #define DAVINCI_MCASP_IIS_MODE 0 #define DAVINCI_MCASP_DIT_MODE 1 -#endif /* __ASM_ARCH_DAVINCI_ASP_H */ +#endif diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 4b37e2ac4685..ab0ad4591b08 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -22,9 +22,6 @@ #include #include -#include -#include - #include "davinci-pcm.h" #include "davinci-i2s.h" #include "davinci-mcasp.h" diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 407df7233d6d..821831207180 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -23,8 +24,6 @@ #include #include -#include - #include "davinci-pcm.h" #include "davinci-i2s.h" diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 51479f9ee909..0de9ed6ce038 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -19,7 +19,8 @@ #define DAVINCI_MCASP_H #include -#include +#include + #include "davinci-pcm.h" #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 4b70828beedb..93ea3bf567e1 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "davinci-pcm.h" diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index 5e5516460461..fc4d01cdd8c9 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -12,9 +12,8 @@ #ifndef _DAVINCI_PCM_H #define _DAVINCI_PCM_H +#include #include -#include - struct davinci_pcm_dma_params { int channel; /* sync dma channel ID */ From 3e3b8c3415b15adb5a7ffcbfbeb360e7c9f5f4f7 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:42 +0530 Subject: [PATCH 197/665] ASoC: Davinci: McASP: add device tree support for McASP Add device tree probe for McASP driver. Note: DMA parameters are not populated from DT and will be done later. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- .../bindings/sound/davinci-mcasp-audio.txt | 44 +++++++ sound/soc/davinci/davinci-mcasp.c | 124 +++++++++++++++++- 2 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt new file mode 100644 index 000000000000..e6148eca2942 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -0,0 +1,44 @@ +Texas Instruments McASP controller + +Required properties: +- compatible : + "ti,dm646x-mcasp-audio" : for DM646x platforms + "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms + +- reg : Should contain McASP registers offset and length +- interrupts : Interrupt number for McASP +- op-mode : I2S/DIT ops mode. +- tdm-slots : Slots for TDM operation. +- num-serializer : Serializers used by McASP. +- serial-dir : A list of serializer pin mode. The list number should be equal + to "num-serializer" parameter. Each entry is a number indication + serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX) + + +Optional properties: + +- ti,hwmods : Must be "mcasp", n is controller instance starting 0 +- tx-num-evt : FIFO levels. +- rx-num-evt : FIFO levels. +- sram-size-playback : size of sram to be allocated during playback +- sram-size-capture : size of sram to be allocated during capture + +Example: + +mcasp0: mcasp0@1d00000 { + compatible = "ti,da830-mcasp-audio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x100000 0x3000>; + interrupts = <82 83>; + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + num-serializer = <16>; + serial-dir = < + 0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 0 0 + 0 0 0 1 + 2 0 0 0 >; + tx-num-evt = <1>; + rx-num-evt = <1>; +}; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 8f3c5a4cf537..7ecf19dfb07c 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include #include @@ -856,6 +859,114 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }; +static const struct of_device_id mcasp_dt_ids[] = { + { + .compatible = "ti,dm646x-mcasp-audio", + .data = (void *)MCASP_VERSION_1, + }, + { + .compatible = "ti,da830-mcasp-audio", + .data = (void *)MCASP_VERSION_2, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mcasp_dt_ids); + +static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct snd_platform_data *pdata = NULL; + const struct of_device_id *match = + of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); + + const u32 *of_serial_dir32; + u8 *of_serial_dir; + u32 val; + int i, ret = 0; + + if (pdev->dev.platform_data) { + pdata = pdev->dev.platform_data; + return pdata; + } else if (match) { + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + goto nodata; + } + } else { + /* control shouldn't reach here. something is wrong */ + ret = -EINVAL; + goto nodata; + } + + if (match->data) + pdata->version = (u8)((int)match->data); + + ret = of_property_read_u32(np, "op-mode", &val); + if (ret >= 0) + pdata->op_mode = val; + + ret = of_property_read_u32(np, "tdm-slots", &val); + if (ret >= 0) + pdata->tdm_slots = val; + + ret = of_property_read_u32(np, "num-serializer", &val); + if (ret >= 0) + pdata->num_serializer = val; + + of_serial_dir32 = of_get_property(np, "serial-dir", &val); + val /= sizeof(u32); + if (val != pdata->num_serializer) { + dev_err(&pdev->dev, + "num-serializer(%d) != serial-dir size(%d)\n", + pdata->num_serializer, val); + ret = -EINVAL; + goto nodata; + } + + if (of_serial_dir32) { + of_serial_dir = devm_kzalloc(&pdev->dev, + (sizeof(*of_serial_dir) * val), + GFP_KERNEL); + if (!of_serial_dir) { + ret = -ENOMEM; + goto nodata; + } + + for (i = 0; i < pdata->num_serializer; i++) + of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); + + pdata->serial_dir = of_serial_dir; + } + + ret = of_property_read_u32(np, "tx-num-evt", &val); + if (ret >= 0) + pdata->txnumevt = val; + + ret = of_property_read_u32(np, "rx-num-evt", &val); + if (ret >= 0) + pdata->rxnumevt = val; + + ret = of_property_read_u32(np, "sram-size-playback", &val); + if (ret >= 0) + pdata->sram_size_playback = val; + + ret = of_property_read_u32(np, "sram-size-capture", &val); + if (ret >= 0) + pdata->sram_size_capture = val; + + return pdata; + +nodata: + if (ret < 0) { + dev_err(&pdev->dev, "Error populating platform data, err %d\n", + ret); + pdata = NULL; + } + return pdata; +} + static int davinci_mcasp_probe(struct platform_device *pdev) { struct davinci_pcm_dma_params *dma_data; @@ -864,11 +975,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev) struct davinci_audio_dev *dev; int ret; + if (!pdev->dev.platform_data && !pdev->dev.of_node) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), GFP_KERNEL); if (!dev) return -ENOMEM; + pdata = davinci_mcasp_set_pdata_from_of(pdev); + if (!pdata) { + dev_err(&pdev->dev, "no platform data\n"); + return -EINVAL; + } + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "no mem resource?\n"); @@ -882,7 +1004,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) return -EBUSY; } - pdata = pdev->dev.platform_data; pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); @@ -980,6 +1101,7 @@ static struct platform_driver davinci_mcasp_driver = { .driver = { .name = "davinci-mcasp", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(mcasp_dt_ids), }, }; From f755bbbf1f9f180aa61eb730d638b62e225bfc10 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 25 Aug 2012 21:57:09 +0200 Subject: [PATCH 198/665] drivers/iio/adc/at91_adc.c: adjust inconsistent IS_ERR and PTR_ERR Change the call to PTR_ERR to access the value just tested by IS_ERR. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e,e1; @@ ( if (IS_ERR(e)) { ... PTR_ERR(e) ... } | if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... } | *if (IS_ERR(e)) { ... * PTR_ERR(e1) ... } ) // Signed-off-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index f61780a02374..3bd5540238a7 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -617,7 +617,7 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) st->adc_clk = clk_get(&pdev->dev, "adc_op_clk"); if (IS_ERR(st->adc_clk)) { dev_err(&pdev->dev, "Failed to get the ADC clock.\n"); - ret = PTR_ERR(st->clk); + ret = PTR_ERR(st->adc_clk); goto error_disable_clk; } From 1d92128fe9e30c2340283361957a840f108e4abf Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 26 Aug 2012 18:00:29 +0300 Subject: [PATCH 199/665] KVM: x86: fix KVM_GET_MSR for PV EOI KVM_GET_MSR was missing support for PV EOI, which is needed for migration. Signed-off-by: Michael S. Tsirkin Signed-off-by: Marcelo Tosatti --- arch/x86/kvm/x86.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index dce75b760312..148ed666e311 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2000,6 +2000,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_KVM_STEAL_TIME: data = vcpu->arch.st.msr_val; break; + case MSR_KVM_PV_EOI_EN: + data = vcpu->arch.pv_eoi.msr_val; + break; case MSR_IA32_P5_MC_ADDR: case MSR_IA32_P5_MC_TYPE: case MSR_IA32_MCG_CAP: From 6b79d14e7a9f5d31b78bcd01a122f0c692e94a19 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 27 Aug 2012 10:59:42 +0200 Subject: [PATCH 200/665] s390/dasd: fix ioctl return value For unimplemented ioctls the dasd driver should return -ENOTTY. Reported-by: Wanlong Gao Acked-by: Stefan Weinhuber Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 2 +- drivers/s390/block/dasd_ioctl.c | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 40a826a7295f..2fb2b9ea97ec 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -3804,7 +3804,7 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) case BIODASDSYMMIO: return dasd_symm_io(device, argp); default: - return -ENOIOCTLCMD; + return -ENOTTY; } } diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index cceae70279f6..654c6921a6d4 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -498,12 +498,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, break; default: /* if the discipline has an ioctl method try it. */ - if (base->discipline->ioctl) { + rc = -ENOTTY; + if (base->discipline->ioctl) rc = base->discipline->ioctl(block, cmd, argp); - if (rc == -ENOIOCTLCMD) - rc = -EINVAL; - } else - rc = -EINVAL; } dasd_put_device(base); return rc; From 29a877fa1f402ce2c1a0c52957c4e29b9bb34216 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 27 Aug 2012 15:18:45 +0200 Subject: [PATCH 201/665] s390/smp: add missing smp_store_status() for !SMP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this compile error: arch/s390/kernel/machine_kexec.c: In function ‘setup_regs’: arch/s390/kernel/machine_kexec.c:63:3: error: implicit declaration of function ‘smp_store_status’ [-Werror=implicit-function-declaration] Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/smp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index a0a8340daafa..ce26ac3cb162 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -44,6 +44,7 @@ static inline void smp_call_online_cpu(void (*func)(void *), void *data) } static inline int smp_find_processor_id(int address) { return 0; } +static inline int smp_store_status(int cpu) { return 0; } static inline int smp_vcpu_scheduled(int cpu) { return 1; } static inline void smp_yield_cpu(int cpu) { } static inline void smp_yield(void) { } From b969afc8b719bbe3f0842a694e6bf5e87f08868f Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Thu, 23 Aug 2012 18:14:54 +0200 Subject: [PATCH 202/665] ASoC: atmel-ssc: include linux/io.h for raw io Include linux/io.h for raw io operations in atmel-scc header. This fixes the following build error: CC [M] sound/soc/atmel/atmel_ssc_dai.o sound/soc/atmel/atmel_ssc_dai.c: In function 'atmel_ssc_interrupt': sound/soc/atmel/atmel_ssc_dai.c:171: error: implicit declaration of function '__raw_readl' sound/soc/atmel/atmel_ssc_dai.c: In function 'atmel_ssc_shutdown': sound/soc/atmel/atmel_ssc_dai.c:249: error: implicit declaration of function '__raw_writel' Signed-off-by: Joachim Eastwood Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Mark Brown --- include/linux/atmel-ssc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h index 06023393fba9..4eb31752e2b7 100644 --- a/include/linux/atmel-ssc.h +++ b/include/linux/atmel-ssc.h @@ -3,6 +3,7 @@ #include #include +#include struct ssc_device { struct list_head list; From c921928661eda599d73a6a86e58bdd5aecfa18cb Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 24 Aug 2012 21:20:15 -0600 Subject: [PATCH 203/665] sound: tegra_alc5632: remove HP detect GPIO inversion Both the schematics and practical testing show that the HP detect GPIO is high when the headphones are plugged in. Hence, the snd_soc_jack_gpio should not specify to invert the signal. Signed-off-by: Stephen Warren Acked-by: Andrey Danin Signed-off-by: Mark Brown Cc: # v3.4 v3.5 --- sound/soc/tegra/tegra_alc5632.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index e463529b38bb..76cb1b363b71 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -89,7 +89,6 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = { .name = "Headset detection", .report = SND_JACK_HEADSET, .debounce_time = 150, - .invert = 1, }; static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = { From 3d721a34e66e8133404bda6852897b818df69b4c Mon Sep 17 00:00:00 2001 From: Sangsu Park Date: Tue, 28 Aug 2012 17:55:49 +0900 Subject: [PATCH 204/665] ASoC: SAMSUNG: Change Kconfig to support all SAMSUNG ASoC All SAMSUNG ASoC needs SND_SOC_SAMSUNG configuration. This patch change Kconfig to support all SAMSUNG ASoC. Signed-off-by: Sangsu Park Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index f17dd25e0f4a..e7b83179aca2 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -1,6 +1,6 @@ config SND_SOC_SAMSUNG tristate "ASoC support for Samsung" - depends on ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_EXYNOS4 + depends on PLAT_SAMSUNG select S3C64XX_DMA if ARCH_S3C64XX select S3C2410_DMA if ARCH_S3C24XX help From 0ed275eff31029c39355828cb48c46c0a006e2f8 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 21 Aug 2012 19:21:51 +0400 Subject: [PATCH 205/665] ASoC: Rename ep93xx soc directory to cirrus This patch is to rename the directory "ep93xx" in "cirrus". Name more accurately reflects the manufacturer and allows to add drivers not only for architecture ep93xx in this directory. Patch not contain any functional changes. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown --- sound/soc/Kconfig | 2 +- sound/soc/Makefile | 2 +- sound/soc/{ep93xx => cirrus}/Kconfig | 0 sound/soc/{ep93xx => cirrus}/Makefile | 0 sound/soc/{ep93xx => cirrus}/edb93xx.c | 0 sound/soc/{ep93xx => cirrus}/ep93xx-ac97.c | 0 sound/soc/{ep93xx => cirrus}/ep93xx-i2s.c | 0 sound/soc/{ep93xx => cirrus}/ep93xx-pcm.c | 0 sound/soc/{ep93xx => cirrus}/ep93xx-pcm.h | 0 sound/soc/{ep93xx => cirrus}/simone.c | 0 sound/soc/{ep93xx => cirrus}/snappercl15.c | 0 11 files changed, 2 insertions(+), 2 deletions(-) rename sound/soc/{ep93xx => cirrus}/Kconfig (100%) rename sound/soc/{ep93xx => cirrus}/Makefile (100%) rename sound/soc/{ep93xx => cirrus}/edb93xx.c (100%) rename sound/soc/{ep93xx => cirrus}/ep93xx-ac97.c (100%) rename sound/soc/{ep93xx => cirrus}/ep93xx-i2s.c (100%) rename sound/soc/{ep93xx => cirrus}/ep93xx-pcm.c (100%) rename sound/soc/{ep93xx => cirrus}/ep93xx-pcm.h (100%) rename sound/soc/{ep93xx => cirrus}/simone.c (100%) rename sound/soc/{ep93xx => cirrus}/snappercl15.c (100%) diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index c24de902f5f5..5da8ca7aee05 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -33,9 +33,9 @@ config SND_SOC_DMAENGINE_PCM source "sound/soc/atmel/Kconfig" source "sound/soc/au1x/Kconfig" source "sound/soc/blackfin/Kconfig" +source "sound/soc/cirrus/Kconfig" source "sound/soc/davinci/Kconfig" source "sound/soc/dwc/Kconfig" -source "sound/soc/ep93xx/Kconfig" source "sound/soc/fsl/Kconfig" source "sound/soc/jz4740/Kconfig" source "sound/soc/nuc900/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index c1264007b4ee..bcbf1d00aa85 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -10,9 +10,9 @@ obj-$(CONFIG_SND_SOC) += generic/ obj-$(CONFIG_SND_SOC) += atmel/ obj-$(CONFIG_SND_SOC) += au1x/ obj-$(CONFIG_SND_SOC) += blackfin/ +obj-$(CONFIG_SND_SOC) += cirrus/ obj-$(CONFIG_SND_SOC) += davinci/ obj-$(CONFIG_SND_SOC) += dwc/ -obj-$(CONFIG_SND_SOC) += ep93xx/ obj-$(CONFIG_SND_SOC) += fsl/ obj-$(CONFIG_SND_SOC) += jz4740/ obj-$(CONFIG_SND_SOC) += mid-x86/ diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/cirrus/Kconfig similarity index 100% rename from sound/soc/ep93xx/Kconfig rename to sound/soc/cirrus/Kconfig diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/cirrus/Makefile similarity index 100% rename from sound/soc/ep93xx/Makefile rename to sound/soc/cirrus/Makefile diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/cirrus/edb93xx.c similarity index 100% rename from sound/soc/ep93xx/edb93xx.c rename to sound/soc/cirrus/edb93xx.c diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c similarity index 100% rename from sound/soc/ep93xx/ep93xx-ac97.c rename to sound/soc/cirrus/ep93xx-ac97.c diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c similarity index 100% rename from sound/soc/ep93xx/ep93xx-i2s.c rename to sound/soc/cirrus/ep93xx-i2s.c diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c similarity index 100% rename from sound/soc/ep93xx/ep93xx-pcm.c rename to sound/soc/cirrus/ep93xx-pcm.c diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h similarity index 100% rename from sound/soc/ep93xx/ep93xx-pcm.h rename to sound/soc/cirrus/ep93xx-pcm.h diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/cirrus/simone.c similarity index 100% rename from sound/soc/ep93xx/simone.c rename to sound/soc/cirrus/simone.c diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/cirrus/snappercl15.c similarity index 100% rename from sound/soc/ep93xx/snappercl15.c rename to sound/soc/cirrus/snappercl15.c From 7ce9bf1f4785dab0598a19a7fcb0733a18193e4e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 27 Aug 2012 20:27:19 +0200 Subject: [PATCH 206/665] mm: cma: fix alignment requirements for contiguous regions Contiguous Memory Allocator requires each of its regions to be aligned in such a way that it is possible to change migration type for all pageblocks holding it and then isolate page of largest possible order from the buddy allocator (which is MAX_ORDER-1). This patch relaxes alignment requirements by one order, because MAX_ORDER alignment is not really needed. Signed-off-by: Marek Szyprowski CC: Michal Nazarewicz Acked-by: Michal Nazarewicz --- drivers/base/dma-contiguous.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 78efb0306a44..34d94c762a1e 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size, return -EINVAL; /* Sanitise input arguments */ - alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order); + alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); base = ALIGN(base, alignment); size = ALIGN(size, alignment); limit &= ~(alignment - 1); From e092705bcd53de3bafc3053b0b55bf83e5d6711f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Aug 2012 14:39:39 +0200 Subject: [PATCH 207/665] ARM: relax conditions required for enabling Contiguous Memory Allocator Contiguous Memory Allocator requires only paging and MMU enabled not particular CPU architectures, so there is no need for strict dependency on CPU type. This enables to use CMA on some older ARM v5 systems which also might need large contiguous blocks for the multimedia processing hw modules. Reported-by: Prabhakar Lad Signed-off-by: Marek Szyprowski Tested-by: Prabhakar Lad --- arch/arm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6d6e18fee9fe..0824a91ebc26 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -6,7 +6,7 @@ config ARM select HAVE_DMA_API_DEBUG select HAVE_IDE if PCI || ISA || PCMCIA select HAVE_DMA_ATTRS - select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7) + select HAVE_DMA_CONTIGUOUS if MMU select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION From 6e5267aa543817015edb4a65c66e15f9809f92bd Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Aug 2012 11:19:25 +0200 Subject: [PATCH 208/665] ARM: DMA-Mapping: add function for setting coherent pool size from platform code Some platforms might require to increase atomic coherent pool to make sure that their device will be able to allocate all their buffers from atomic context. This function can be also used to decrease atomic coherent pool size if coherent allocations are not used for the given sub-platform. Suggested-by: Josh Coombs Signed-off-by: Marek Szyprowski --- arch/arm/include/asm/dma-mapping.h | 7 +++++++ arch/arm/mm/dma-mapping.c | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 2ae842df4551..5c44dcb0987b 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -202,6 +202,13 @@ static inline void dma_free_writecombine(struct device *dev, size_t size, return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs); } +/* + * This can be called during early boot to increase the size of the atomic + * coherent DMA pool above the default value of 256KiB. It must be called + * before postcore_initcall. + */ +extern void __init init_dma_coherent_pool_size(unsigned long size); + /* * This can be called during boot to increase the size of the consistent * DMA region above it's default value of 2MB. It must be called before the diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 4e7d1182e8a3..d1cc9c1d3566 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -267,6 +267,8 @@ static void __dma_free_remap(void *cpu_addr, size_t size) vunmap(cpu_addr); } +#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K + struct dma_pool { size_t size; spinlock_t lock; @@ -277,7 +279,7 @@ struct dma_pool { }; static struct dma_pool atomic_pool = { - .size = SZ_256K, + .size = DEFAULT_DMA_COHERENT_POOL_SIZE, }; static int __init early_coherent_pool(char *p) @@ -287,6 +289,21 @@ static int __init early_coherent_pool(char *p) } early_param("coherent_pool", early_coherent_pool); +void __init init_dma_coherent_pool_size(unsigned long size) +{ + /* + * Catch any attempt to set the pool size too late. + */ + BUG_ON(atomic_pool.vaddr); + + /* + * Set architecture specific coherent pool size only if + * it has not been changed by kernel command line parameter. + */ + if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE) + atomic_pool.size = size; +} + /* * Initialise the coherent pool for atomic allocations. */ From fb71285f0c1633a85544784aae7577502274b77a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 22 Aug 2012 14:50:42 +0200 Subject: [PATCH 209/665] ARM: DMA-Mapping: print warning when atomic coherent allocation fails Print a loud warning when system runs out of memory from atomic DMA coherent pool to let users notice the potential problem. Reported-by: Aaro Koskinen Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index d1cc9c1d3566..acced9332109 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -461,6 +461,10 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page) bitmap_set(pool->bitmap, pageno, count); ptr = pool->vaddr + PAGE_SIZE * pageno; *ret_page = pool->page + pageno; + } else { + pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n" + "Please increase it with coherent_pool= kernel parameter!\n", + (unsigned)pool->size / 1024); } spin_unlock_irqrestore(&pool->lock, flags); From cb01b633eeb77ae7128cab0a3b5d3de56da6e913 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 28 Aug 2012 20:57:41 +0200 Subject: [PATCH 210/665] ARM: Kirkwood: increase atomic coherent pool size The default 256 KiB coherent pool may be too small for some of the Kirkwood devices, so increase it to make sure that devices will be able to allocate their buffers with GFP_ATOMIC flag. Suggested-by: Josh Coombs Signed-off-by: Marek Szyprowski Acked-by: Jason Cooper --- arch/arm/mach-kirkwood/common.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index c4b64adcbfce..d748f5033861 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -517,6 +517,13 @@ void __init kirkwood_wdt_init(void) void __init kirkwood_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); + + /* + * Some Kirkwood devices allocate their coherent buffers from atomic + * context. Increase size of atomic coherent pool to make sure such + * the allocations won't fail. + */ + init_dma_coherent_pool_size(SZ_1M); } int kirkwood_tclk; From 6b3fe47264262fa082897ebe8ae01041eae65e14 Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Tue, 28 Aug 2012 08:13:01 +0300 Subject: [PATCH 211/665] ARM: dma-mapping: atomic_pool with struct page **pages struct page **pages is necessary to align with non atomic path in __iommu_get_pages(). atomic_pool() has the intialized **pages instead of just *page. Signed-off-by: Hiroshi Doyu Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index acced9332109..9a21284a6ac4 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -275,7 +275,7 @@ struct dma_pool { unsigned long *bitmap; unsigned long nr_pages; void *vaddr; - struct page *page; + struct page **pages; }; static struct dma_pool atomic_pool = { @@ -314,6 +314,7 @@ static int __init atomic_pool_init(void) unsigned long nr_pages = pool->size >> PAGE_SHIFT; unsigned long *bitmap; struct page *page; + struct page **pages; void *ptr; int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long); @@ -321,21 +322,31 @@ static int __init atomic_pool_init(void) if (!bitmap) goto no_bitmap; + pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL); + if (!pages) + goto no_pages; + if (IS_ENABLED(CONFIG_CMA)) ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page); else ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot, &page, NULL); if (ptr) { + int i; + + for (i = 0; i < nr_pages; i++) + pages[i] = page + i; + spin_lock_init(&pool->lock); pool->vaddr = ptr; - pool->page = page; + pool->pages = pages; pool->bitmap = bitmap; pool->nr_pages = nr_pages; pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n", (unsigned)pool->size / 1024); return 0; } +no_pages: kfree(bitmap); no_bitmap: pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n", @@ -460,7 +471,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page) if (pageno < pool->nr_pages) { bitmap_set(pool->bitmap, pageno, count); ptr = pool->vaddr + PAGE_SIZE * pageno; - *ret_page = pool->page + pageno; + *ret_page = pool->pages[pageno]; } else { pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n" "Please increase it with coherent_pool= kernel parameter!\n", From 21d0a75951ccf71f671eb24b61a8ad2b497be4b4 Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Tue, 28 Aug 2012 08:13:02 +0300 Subject: [PATCH 212/665] ARM: dma-mapping: Refactor out to introduce __in_atomic_pool Check the given range("start", "size") is included in "atomic_pool" or not. Signed-off-by: Hiroshi Doyu Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 9a21284a6ac4..882eacc6ebc1 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -482,20 +482,34 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page) return ptr; } +static bool __in_atomic_pool(void *start, size_t size) +{ + struct dma_pool *pool = &atomic_pool; + void *end = start + size; + void *pool_start = pool->vaddr; + void *pool_end = pool->vaddr + pool->size; + + if (start < pool_start || start > pool_end) + return false; + + if (end <= pool_end) + return true; + + WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n", + start, end - 1, pool_start, pool_end - 1); + + return false; +} + static int __free_from_pool(void *start, size_t size) { struct dma_pool *pool = &atomic_pool; unsigned long pageno, count; unsigned long flags; - if (start < pool->vaddr || start > pool->vaddr + pool->size) + if (!__in_atomic_pool(start, size)) return 0; - if (start + size > pool->vaddr + pool->size) { - WARN(1, "freeing wrong coherent size from pool\n"); - return 0; - } - pageno = (start - pool->vaddr) >> PAGE_SHIFT; count = size >> PAGE_SHIFT; From 665bad7bb911d392000fa69bc6b599c0df992504 Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Tue, 28 Aug 2012 08:13:03 +0300 Subject: [PATCH 213/665] ARM: dma-mapping: Introduce __atomic_get_pages() for __iommu_get_pages() Support atomic allocation in __iommu_get_pages(). Signed-off-by: Hiroshi Doyu [moved __atomic_get_pages() under #ifdef CONFIG_ARM_DMA_USE_IOMMU to avoid unused fuction warning for no-IOMMU case] Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 882eacc6ebc1..54b158df5afa 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1136,10 +1136,22 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si return 0; } +static struct page **__atomic_get_pages(void *addr) +{ + struct dma_pool *pool = &atomic_pool; + struct page **pages = pool->pages; + int offs = (addr - pool->vaddr) >> PAGE_SHIFT; + + return pages + offs; +} + static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs) { struct vm_struct *area; + if (__in_atomic_pool(cpu_addr, PAGE_SIZE)) + return __atomic_get_pages(cpu_addr); + if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) return cpu_addr; From 479ed93a4b98eef03fd8260f7ddc00019221c450 Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Tue, 28 Aug 2012 08:13:04 +0300 Subject: [PATCH 214/665] ARM: dma-mapping: IOMMU allocates pages from atomic_pool with GFP_ATOMIC Make use of the same atomic pool as DMA does, and skip a kernel page mapping which can involve sleep'able operations at allocating a kernel page table. Signed-off-by: Hiroshi Doyu Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 54b158df5afa..051204fc4617 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1161,6 +1161,34 @@ static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs) return NULL; } +static void *__iommu_alloc_atomic(struct device *dev, size_t size, + dma_addr_t *handle) +{ + struct page *page; + void *addr; + + addr = __alloc_from_pool(size, &page); + if (!addr) + return NULL; + + *handle = __iommu_create_mapping(dev, &page, size); + if (*handle == DMA_ERROR_CODE) + goto err_mapping; + + return addr; + +err_mapping: + __free_from_pool(addr, size); + return NULL; +} + +static void __iommu_free_atomic(struct device *dev, struct page **pages, + dma_addr_t handle, size_t size) +{ + __iommu_remove_mapping(dev, handle, size); + __free_from_pool(page_address(pages[0]), size); +} + static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) { @@ -1171,6 +1199,9 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, *handle = DMA_ERROR_CODE; size = PAGE_ALIGN(size); + if (gfp & GFP_ATOMIC) + return __iommu_alloc_atomic(dev, size, handle); + pages = __iommu_alloc_buffer(dev, size, gfp); if (!pages) return NULL; @@ -1237,6 +1268,11 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, return; } + if (__in_atomic_pool(cpu_addr, size)) { + __iommu_free_atomic(dev, pages, handle, size); + return; + } + if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) { unmap_kernel_range((unsigned long)cpu_addr, size); vunmap(cpu_addr); From 14f0458a41e033dee31ba605137419385c03fc78 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 27 Aug 2012 16:22:49 +1000 Subject: [PATCH 215/665] drm/nvc0/copy: check PUNITS to determine which copy engines are disabled On some Fermi chipsets (NVCE particularly) PCOPY1 doesn't exist. And if what I've seen on Kepler is true of Fermi too, chipsets of the same type can have different PCOPY units available. This should fix a v3.5 regression reported by a number of people effecting suspend/resume on NVC8/NVCE chipsets. Cc: stable@vger.kernel.org [3.5] Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 1866dbb49979..c61014442aa9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -736,9 +736,11 @@ nouveau_card_init(struct drm_device *dev) } break; case NV_C0: - nvc0_copy_create(dev, 1); + if (!(nv_rd32(dev, 0x022500) & 0x00000200)) + nvc0_copy_create(dev, 1); case NV_D0: - nvc0_copy_create(dev, 0); + if (!(nv_rd32(dev, 0x022500) & 0x00000100)) + nvc0_copy_create(dev, 0); break; default: break; From 305a3d204aae15eddf1988e50e33aee4119b710d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 22 Aug 2012 17:02:42 +0200 Subject: [PATCH 216/665] drm/radeon: fix reading CB_COLORn_MASK from the CS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index ab74e6b149e7..7799e283811f 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -1416,7 +1416,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028118_CB_COLOR6_MASK: case R_02811C_CB_COLOR7_MASK: tmp = (reg - R_028100_CB_COLOR0_MASK) / 4; - track->cb_color_mask[tmp] = ib[idx]; + track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx); if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { track->cb_dirty = true; } From 3b5ef597ec40603c368f65d3eb6d9818ed6a7bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 22 Aug 2012 17:02:43 +0200 Subject: [PATCH 217/665] drm/radeon: initialize tracked CS state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should help catch uninitialized registers and reject commands because of that. Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 7799e283811f..8866937bd0b4 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -315,7 +315,14 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->cb_color_bo[i] = NULL; track->cb_color_bo_offset[i] = 0xFFFFFFFF; track->cb_color_bo_mc[i] = 0xFFFFFFFF; + track->cb_color_frag_bo[i] = NULL; + track->cb_color_frag_offset[i] = 0xFFFFFFFF; + track->cb_color_tile_bo[i] = NULL; + track->cb_color_tile_offset[i] = 0xFFFFFFFF; + track->cb_color_mask[i] = 0xFFFFFFFF; } + track->nsamples = 16; + track->log_nsamples = 4; track->cb_target_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF; track->cb_dirty = true; From 523885dec109188b6bed53ec67362072f13b0d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 24 Aug 2012 14:27:36 +0200 Subject: [PATCH 218/665] drm/radeon: add proper checking of RESOLVE_BOX command for r600-r700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checking of the second colorbuffer was skipped on r700, because CB_TARGET_MASK was 0xf. With r600, CB_TARGET_MASK is changed to 0xff, so we must set the number of samples of the second colorbuffer to 1 in order to pass the CS checker. The DRM version is bumped, because RESOLVE_BOX is always rejected without this fix on r600. Signed-off-by: Marek Olšák Reviewed-by: Jerome Glisse Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 19 +++++++++++++++++-- drivers/gpu/drm/radeon/r600d.h | 8 ++++++++ drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- drivers/gpu/drm/radeon/reg_srcs/r600 | 1 - 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 8866937bd0b4..f37676d7f217 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -63,6 +63,7 @@ struct r600_cs_track { u32 cb_color_size_idx[8]; /* unused */ u32 cb_target_mask; u32 cb_shader_mask; /* unused */ + bool is_resolve; u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; @@ -321,6 +322,7 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->cb_color_tile_offset[i] = 0xFFFFFFFF; track->cb_color_mask[i] = 0xFFFFFFFF; } + track->is_resolve = false; track->nsamples = 16; track->log_nsamples = 4; track->cb_target_mask = 0xFFFFFFFF; @@ -359,6 +361,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) volatile u32 *ib = p->ib.ptr; unsigned array_mode; u32 format; + /* When resolve is used, the second colorbuffer has always 1 sample. */ + unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples; size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; format = G_0280A0_FORMAT(track->cb_color_info[i]); @@ -382,7 +386,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) array_check.group_size = track->group_size; array_check.nbanks = track->nbanks; array_check.npipes = track->npipes; - array_check.nsamples = track->nsamples; + array_check.nsamples = nsamples; array_check.blocksize = r600_fmt_get_blocksize(format); if (r600_get_array_mode_alignment(&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { @@ -428,7 +432,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) /* check offset */ tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * - r600_fmt_get_blocksize(format) * track->nsamples; + r600_fmt_get_blocksize(format) * nsamples; switch (array_mode) { default: case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -799,6 +803,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) */ if (track->cb_dirty) { tmp = track->cb_target_mask; + + /* We must check both colorbuffers for RESOLVE. */ + if (track->is_resolve) { + tmp |= 0xff; + } + for (i = 0; i < 8; i++) { if ((tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ @@ -1288,6 +1298,11 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) track->nsamples = 1 << tmp; track->cb_dirty = true; break; + case R_028808_CB_COLOR_CONTROL: + tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx)); + track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX; + track->cb_dirty = true; + break; case R_0280A0_CB_COLOR0_INFO: case R_0280A4_CB_COLOR1_INFO: case R_0280A8_CB_COLOR2_INFO: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index bdb69a63062f..fa6f37099ba9 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -66,6 +66,14 @@ #define CC_RB_BACKEND_DISABLE 0x98F4 #define BACKEND_DISABLE(x) ((x) << 16) +#define R_028808_CB_COLOR_CONTROL 0x28808 +#define S_028808_SPECIAL_OP(x) (((x) & 0x7) << 4) +#define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7) +#define C_028808_SPECIAL_OP 0xFFFFFF8F +#define V_028808_SPECIAL_NORMAL 0x00 +#define V_028808_SPECIAL_DISABLE 0x01 +#define V_028808_SPECIAL_RESOLVE_BOX 0x07 + #define CB_COLOR0_BASE 0x28040 #define CB_COLOR1_BASE 0x28044 #define CB_COLOR2_BASE 0x28048 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 27d22d709c90..8c593ea82c41 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -63,9 +63,10 @@ * 2.19.0 - r600-eg: MSAA textures * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query * 2.21.0 - r600-r700: FMASK and CMASK + * 2.22.0 - r600 only: RESOLVE_BOX allowed */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 21 +#define KMS_DRIVER_MINOR 22 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index f93e45d869f4..20bfbda7b3f1 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -744,7 +744,6 @@ r600 0x9400 0x00028C38 CB_CLRCMP_DST 0x00028C3C CB_CLRCMP_MSK 0x00028C34 CB_CLRCMP_SRC -0x00028808 CB_COLOR_CONTROL 0x0002842C CB_FOG_BLUE 0x00028428 CB_FOG_GREEN 0x00028424 CB_FOG_RED From 4e58591c8961b3e31709313f75819f2eec06e322 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 21 Aug 2012 19:06:21 -0400 Subject: [PATCH 219/665] drm/radeon: don't disable plls that are in use by other crtcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some plls are shared for DP. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Reviewed-by: Michel Dänzer --- drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index f4d4505fe831..961d366f00eb 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1682,9 +1682,22 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_atom_ss ss; + int i; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != radeon_crtc->crtc_id && + radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off the pll + */ + goto done; + } + } + switch (radeon_crtc->pll_id) { case ATOM_PPLL1: case ATOM_PPLL2: @@ -1701,6 +1714,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) default: break; } +done: radeon_crtc->pll_id = -1; } From 8d1af57ae3c4458ed0de93ef97f388dd1b3239c7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Aug 2012 09:54:56 -0400 Subject: [PATCH 220/665] drm/radeon/atom: rework DIG modesetting on DCE3+ The ordering is important and the current drm code wasn't cutting it for modern DIG encoders. We need to have information about crtc before setting up the encoders so I've shifted the ordering a bit. Probably we'll need a full rework akin to danvet's recent intel patchs. This patch fixes numerous issues with DP bridge chips and makes link training much more reliable. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_encoders.c | 109 +++++++++------------ 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index f9bc27fe269a..4a7f95e5550d 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1379,6 +1379,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_connector *radeon_connector = NULL; struct radeon_connector_atom_dig *radeon_dig_connector = NULL; @@ -1390,19 +1392,37 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || - ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - if (ASIC_IS_DCE6(rdev)) { - /* It seems we need to call ATOM_ENCODER_CMD_SETUP again - * before reenabling encoder on DPMS ON, otherwise we never - * get picture - */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + if (!connector) + dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + else + dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + if (ext_encoder) { + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); } atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { + } else if (ASIC_IS_DCE4(rdev)) { + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + /* enable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } else { + /* setup and enable the encoder and transmitter */ + atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + /* some early dce3.2 boards have a bug in their transmitter control table */ + if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { @@ -1420,10 +1440,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else + } else if (ASIC_IS_DCE4(rdev)) { + /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + } else { + /* disable the encoder and transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); + } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1848,10 +1877,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); radeon_encoder->pixel_clock = adjusted_mode->clock; + /* need to call this here rather than in prepare() since we need some crtc info */ + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) atombios_yuv_setup(encoder, true); @@ -1870,38 +1901,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - - if (!connector) - dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; - else - dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); - - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - atombios_dig_encoder_setup(encoder, - ATOM_ENCODER_CMD_SETUP_PANEL_MODE, - dig->panel_mode); - } else if (ASIC_IS_DCE4(rdev)) { - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - - /* enable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - - /* setup and enable the encoder and transmitter */ - atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: @@ -1922,14 +1922,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, break; } - if (ext_encoder) { - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) - atombios_external_encoder_setup(encoder, ext_encoder, - EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); - else - atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); - } - atombios_apply_encoder_quirks(encoder, adjusted_mode); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { @@ -2116,7 +2108,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) } radeon_atom_output_lock(encoder, true); - radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -2137,6 +2128,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) static void radeon_atom_encoder_commit(struct drm_encoder *encoder) { + /* need to call this here as we need the crtc set up */ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); radeon_atom_output_lock(encoder, false); } @@ -2177,14 +2169,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE4(rdev)) - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: From c205b232a64fed6d26edd7e40985b396de99a27f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 24 Aug 2012 18:21:21 -0400 Subject: [PATCH 221/665] drm/radeon/atom: powergating fixes for DCE6 Power gating is per crtc pair, but the powergating registers should be called individually. The hw handles power up/down properly. The pair is powered up if either crtc in the pair is powered up and the pair is not powered down until both crtcs in the pair are powered down. This simplifies programming and should save additional power as the previous code never actually power gated the crtc pair. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 961d366f00eb..2817101fb167 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,7 +258,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); - /* disable crtc pair power gating before programming */ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); @@ -278,25 +277,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; - /* power gating is per-pair */ - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { - struct drm_crtc *other_crtc; - struct radeon_crtc *other_radeon_crtc; - list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { - other_radeon_crtc = to_radeon_crtc(other_crtc); - if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || - ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || - ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || - ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || - ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || - ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { - /* if both crtcs in the pair are off, enable power gating */ - if (other_radeon_crtc->enabled == false) - atombios_powergate_crtc(crtc, ATOM_ENABLE); - break; - } - } - } + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + atombios_powergate_crtc(crtc, ATOM_ENABLE); /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; From 0ceb996c9e729b056977a0f07692b38bbd57bc77 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Aug 2012 17:48:18 -0400 Subject: [PATCH 222/665] drm/radeon: rework panel mode setup Adjust the panel mode setup to match the behavior of the vbios. Rather than checking for specific bridge chip ids, just check the eDP configuration register. This saves extra aux transactions and works across DP bridge chips without requiring additional per chip id checking. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_dp.c | 29 ++++++++++++---------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 7712cf5ab33b..3623b98ed3fe 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -577,30 +577,25 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); + u8 tmp; if (!ASIC_IS_DCE4(rdev)) return panel_mode; - if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_NUTMEG) - panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; - else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_TRAVIS) { - u8 id[6]; - int i; - for (i = 0; i < 6; i++) - id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); - if (id[0] == 0x73 && - id[1] == 0x69 && - id[2] == 0x76 && - id[3] == 0x61 && - id[4] == 0x72 && - id[5] == 0x54) + if (dp_bridge != ENCODER_OBJECT_ID_NONE) { + /* DP bridge chips */ + tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || + (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; else - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); + /* eDP */ + tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; } From 4a2b6662c3632176b4fdf012243dd3751367bf1f Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 28 Aug 2012 16:50:22 -0400 Subject: [PATCH 223/665] drm/radeon: force dma32 to fix regression rs4xx,rs6xx,rs740 It seems some of those IGP dislike non dma32 page despite what documentation says. Fix regression since we allowed non dma32 pages. It seems it only affect some revision of those IGP chips as we don't know which one just force dma32 for all of them. https://bugzilla.redhat.com/show_bug.cgi?id=785375 Signed-off-by: Jerome Glisse Cc: Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index d2e243867ac6..33da8bff8942 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1051,7 +1051,7 @@ int radeon_device_init(struct radeon_device *rdev, if (rdev->flags & RADEON_IS_AGP) rdev->need_dma32 = true; if ((rdev->flags & RADEON_IS_PCI) && - (rdev->family < CHIP_RS400)) + (rdev->family <= CHIP_RS740)) rdev->need_dma32 = true; dma_bits = rdev->need_dma32 ? 32 : 40; From f54b350d89bf16d31593b935bafccf510ff4a708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 29 Aug 2012 13:24:15 +0200 Subject: [PATCH 224/665] drm/radeon: fix double free in radeon_gpu_reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit radeon_ring_restore is freeing the memory for the saved ring data. We need to remember that, otherwise we try to restore the ring data again on the next try. Additional to that it shouldn't try the reset infinitely if we have saved ring data. Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 33da8bff8942..7a3daebd732d 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1346,12 +1346,15 @@ retry: for (i = 0; i < RADEON_NUM_RINGS; ++i) { radeon_ring_restore(rdev, &rdev->ring[i], ring_sizes[i], ring_data[i]); + ring_sizes[i] = 0; + ring_data[i] = NULL; } r = radeon_ib_ring_tests(rdev); if (r) { dev_err(rdev->dev, "ib ring test failed (%d).\n", r); if (saved) { + saved = false; radeon_suspend(rdev); goto retry; } From 072a9c48600409d72aeb0d5b29fbb75861a06631 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 24 Aug 2012 21:41:11 +0000 Subject: [PATCH 225/665] netpoll: revert 6bdb7fe3104 and fix be_poll() instead Against -net. In the patch "netpoll: re-enable irq in poll_napi()", I tried to fix the following warning: [100718.051041] ------------[ cut here ]------------ [100718.051048] WARNING: at kernel/softirq.c:159 local_bh_enable_ip+0x7d/0xb0() (Not tainted) [100718.051049] Hardware name: ProLiant BL460c G7 ... [100718.051068] Call Trace: [100718.051073] [] ? warn_slowpath_common+0x87/0xc0 [100718.051075] [] ? warn_slowpath_null+0x1a/0x20 [100718.051077] [] ? local_bh_enable_ip+0x7d/0xb0 [100718.051080] [] ? _spin_unlock_bh+0x1b/0x20 [100718.051085] [] ? be_process_mcc+0x74/0x230 [be2net] [100718.051088] [] ? be_poll_tx_mcc+0x16c/0x290 [be2net] [100718.051090] [] ? netpoll_poll_dev+0xd6/0x490 [100718.051095] [] ? bond_poll_controller+0x75/0x80 [bonding] [100718.051097] [] ? netpoll_poll_dev+0x45/0x490 [100718.051100] [] ? ksize+0x19/0x80 [100718.051102] [] ? netpoll_send_skb_on_dev+0x157/0x240 by reenabling IRQ before calling ->poll, but it seems more problems are introduced after that patch: http://ozlabs.org/~akpm/stuff/IMG_20120824_122054.jpg http://marc.info/?l=linux-netdev&m=134563282530588&w=2 So it is safe to fix be2net driver code directly. This patch reverts the offending commit and fixes be_poll() by avoid disabling BH there, this is okay because be_poll() can be called either by poll_napi() which already disables IRQ, or by net_rx_action() which already disables BH. Reported-by: Andrew Morton Reported-by: Sylvain Munaut Cc: Sylvain Munaut Cc: Andrew Morton Cc: David Miller Cc: Sathya Perla Cc: Subbu Seetharaman Cc: Ajit Khaparde Signed-off-by: Cong Wang Tested-by: Sylvain Munaut Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 6 ++++-- drivers/net/ethernet/emulex/benet/be_main.c | 2 ++ net/core/netpoll.c | 10 +--------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 7fac97b4bb59..8c63d06ab12b 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -259,7 +259,7 @@ int be_process_mcc(struct be_adapter *adapter) int num = 0, status = 0; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; - spin_lock_bh(&adapter->mcc_cq_lock); + spin_lock(&adapter->mcc_cq_lock); while ((compl = be_mcc_compl_get(adapter))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { /* Interpret flags as an async trailer */ @@ -280,7 +280,7 @@ int be_process_mcc(struct be_adapter *adapter) if (num) be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); - spin_unlock_bh(&adapter->mcc_cq_lock); + spin_unlock(&adapter->mcc_cq_lock); return status; } @@ -295,7 +295,9 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) if (be_error(adapter)) return -EIO; + local_bh_disable(); status = be_process_mcc(adapter); + local_bh_enable(); if (atomic_read(&mcc_obj->q.used) == 0) break; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 90a903d83d87..78b8aa8069f0 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3763,7 +3763,9 @@ static void be_worker(struct work_struct *work) /* when interrupts are not yet enabled, just reap any pending * mcc completions */ if (!netif_running(adapter->netdev)) { + local_bh_disable(); be_process_mcc(adapter); + local_bh_enable(); goto reschedule; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 346b1eb83a1f..e4ba3e70c174 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -168,24 +168,16 @@ static void poll_napi(struct net_device *dev) struct napi_struct *napi; int budget = 16; - WARN_ON_ONCE(!irqs_disabled()); - list_for_each_entry(napi, &dev->napi_list, dev_list) { - local_irq_enable(); if (napi->poll_owner != smp_processor_id() && spin_trylock(&napi->poll_lock)) { - rcu_read_lock_bh(); budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), napi, budget); - rcu_read_unlock_bh(); spin_unlock(&napi->poll_lock); - if (!budget) { - local_irq_disable(); + if (!budget) break; - } } - local_irq_disable(); } } From 41fa54377057ab38bc3e08ebb46168a7daf2e63b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 29 Aug 2012 19:48:26 -0400 Subject: [PATCH 226/665] drm/radeon: fix dig encoder selection on DCE61 Was using the DCE41 code which was wrong. Fixes blank displays on a number of Trinity systems. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_encoders.c | 31 ++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 4a7f95e5550d..6e8803a1170c 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1769,13 +1769,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_encoder *test_encoder; - struct radeon_encoder_atom_dig *dig; + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; uint32_t dig_enc_in_use = 0; - /* DCE4/5 */ - if (ASIC_IS_DCE4(rdev)) { - dig = radeon_encoder->enc_priv; - if (ASIC_IS_DCE41(rdev)) { + if (ASIC_IS_DCE6(rdev)) { + /* DCE6 */ + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + return 1; + else + return 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + return 3; + else + return 2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + return 5; + else + return 4; + break; + } + } else if (ASIC_IS_DCE4(rdev)) { + /* DCE4/5 */ + if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { /* ontario follows DCE4 */ if (rdev->family == CHIP_PALM) { if (dig->linkb) From 4a68a74ba04e7ccf798d45988f4f2d2131fb5063 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 13 Aug 2012 16:31:24 +0000 Subject: [PATCH 227/665] gma500: Consider CRTC initially active. [this one ideally should make 3.6 - it fixes the very annoying mode setting bug] This causes the pipe to be forced off prior to initial mode set, which roughly mirrors the behavior of the i915 driver. It fixes initial mode setting on my Intel DN2800MT (Cedarview) board. Without it, mode setting triggers an out-of-range error from the monitor for most modes, but only on initial configuration (i.e. they can be configured successfully from userspace after that). Signed-off-by: Forest Bond Signed-off-by: Alan Cox Cc: stable Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_intel_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 30dc22a7156c..8033526bb53b 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -1362,6 +1362,9 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, (struct drm_connector **) (psb_intel_crtc + 1); psb_intel_crtc->mode_set.num_connectors = 0; psb_intel_cursor_init(dev, psb_intel_crtc); + + /* Set to true so that the pipe is forced off on initial config. */ + psb_intel_crtc->active = true; } int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, From 0a54e939d8c2647c711ef2369c3e73c3b7f3028c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 29 Aug 2012 06:49:11 +0000 Subject: [PATCH 228/665] ipvs: fix error return code Initialize return variable before exiting on an error path. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Acked-by: Simon Horman Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_ctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 72bf32a84874..f51013c07b9f 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1171,8 +1171,10 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, goto out_err; } svc->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); - if (!svc->stats.cpustats) + if (!svc->stats.cpustats) { + ret = -ENOMEM; goto out_err; + } /* I'm the first user of the service */ atomic_set(&svc->usecnt, 0); From ef6acf68c259d907517dcc0ffefcd4e30276ae29 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 29 Aug 2012 06:49:16 +0000 Subject: [PATCH 229/665] netfilter: ctnetlink: fix error return code in init path Initialize return variable before exiting on an error path. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index da4fc37a8578..9807f3278fcb 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -2790,7 +2790,8 @@ static int __init ctnetlink_init(void) goto err_unreg_subsys; } - if (register_pernet_subsys(&ctnetlink_net_ops)) { + ret = register_pernet_subsys(&ctnetlink_net_ops); + if (ret < 0) { pr_err("ctnetlink_init: cannot register pernet operations\n"); goto err_unreg_exp_subsys; } From 6fc09f10f12477bdaa54e94f9cb428bef6d81315 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 29 Aug 2012 06:49:17 +0000 Subject: [PATCH 230/665] netfilter: nfnetlink_log: fix error return code in init path Initialize return variable before exiting on an error path. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_log.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 592091c1260b..14e2f3903142 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -996,8 +996,10 @@ static int __init nfnetlink_log_init(void) #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) + proc_net_netfilter, &nful_file_ops)) { + status = -ENOMEM; goto cleanup_logger; + } #endif return status; From 6f33814bd4d9cfe76033a31b1c0c76c960cd8e4b Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Wed, 8 Aug 2012 23:12:19 +0200 Subject: [PATCH 231/665] drm: Add EDID_QUIRK_FORCE_REDUCED_BLANKING for ASUS VW222S Connecting an ASUS VW222S [1] over VGA a garbled screen is shown with vertical stripes in the top half. In commit bc42aabc [2] commit bc42aabc6a01b92b0f961d65671564e0e1cd7592 Author: Adam Jackson Date: Wed May 23 16:26:54 2012 -0400 drm/edid/quirks: ViewSonic VA2026w Adam Jackson added the quirk `EDID_QUIRK_FORCE_REDUCED_BLANKING` which is also needed for this ASUS monitor. All log files and output from `xrandr` is included in the referenced Bugzilla report #17629. Please note that this monitor only has a VGA (D-Sub) connector [1]. [1] http://www.asus.com/Display/LCD_Monitors/VW222S/ [2] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=bc42aabc6a01b92b0f961d65671564e0e1cd7592 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=17629 Signed-off-by: Paul Menzel Cc: Cc: Adam Jackson Cc: Ian Pilcher Cc: Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a8743c399e83..b7ee230572b7 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -87,6 +87,9 @@ static struct edid_quirk { int product_id; u32 quirks; } edid_quirk_list[] = { + /* ASUS VW222S */ + { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING }, + /* Acer AL1706 */ { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, /* Acer F51 */ From 497dcf6fc355f0734faf851662b6957386715d24 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 29 Aug 2012 18:58:01 -0700 Subject: [PATCH 232/665] ARM: shmobile: marzen: fixup smsc911x id for regulator dummy_supplies for smsc911x are registered as "smsc911x". smsc911x driver needs id = -1 Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-marzen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index 3a528cf4366c..fcf5a47f4772 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c @@ -67,7 +67,7 @@ static struct smsc911x_platform_config smsc911x_platdata = { static struct platform_device eth_device = { .name = "smsc911x", - .id = 0, + .id = -1, .dev = { .platform_data = &smsc911x_platdata, }, From 6c7080a61fc7b46b3ac8573952b5a3e9d5f68bc4 Mon Sep 17 00:00:00 2001 From: Mark Asselstine Date: Wed, 8 Aug 2012 13:14:36 -0400 Subject: [PATCH 233/665] firmware: fix directory creation rule matching with make 3.82 Attempting to run 'firmware_install' with CONFIG_USB_SERIAL_TI=y when using make 3.82 results in an error make[2]: *** No rule to make target `/lib/firmware/./', needed by `/lib/firmware/ti_3410.fw'. Stop. It turns out make 3.82 is picky when matching directory names with trailing slashes as a result, where make 3.81 would handle this correctly make 3.82 does not find the rule needed to create the directory. The './' seen in the error is added by $(dir) for firmware which resides in the base firmware src directory, such as ti_3410.fw.ihex. By performing $(dir) after we prepend the $(INSTALL_FW_PATH) we can ensure we don't end up with a './' in the middle of the path and the directory will be properly created. This change works with make 3.81 and should work with previous versions as well. Signed-off-by: Mark Asselstine Signed-off-by: Michal Marek --- scripts/Makefile.fwinst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index 6bf8e87f1dcf..c3f69ae275d1 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst @@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@) $(installed-fw-dirs): $(call cmd,mkdir) -$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %) +$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%) $(call cmd,install) PHONY += __fw_install __fw_modinst FORCE From 768fd0737f4533635ea351566dff98fd4912b0d8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 28 Aug 2012 10:02:08 +0200 Subject: [PATCH 234/665] s390/32: Don't clobber personality flags on exec In native 32 bit mode the personality flags were not correctly inherited. This is the s390 version of 59e4c3a2 "powerpc/32: Don't clobber personality flags on exec". Reported-by: Mike Frysinger Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/elf.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 32e8449640fa..9b94a160fe7f 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -180,7 +180,8 @@ extern char elf_platform[]; #define ELF_PLATFORM (elf_platform) #ifndef CONFIG_64BIT -#define SET_PERSONALITY(ex) set_personality(PER_LINUX) +#define SET_PERSONALITY(ex) \ + set_personality(PER_LINUX | (current->personality & (~PER_MASK))) #else /* CONFIG_64BIT */ #define SET_PERSONALITY(ex) \ do { \ From 3683243b2c551e58082b179fd153c7d43ddc503b Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 22 Aug 2012 00:26:47 +0000 Subject: [PATCH 235/665] xen-netfront: use __pskb_pull_tail to ensure linear area is big enough on RX I'm slightly concerned by the "only in exceptional circumstances" comment on __pskb_pull_tail but the structure of an skb just created by netfront shouldn't hit any of the especially slow cases. This approach still does slightly more work than the old way, since if we pull up the entire first frag we now have to shuffle everything down where before we just received into the right place in the first place. Signed-off-by: Ian Campbell Cc: Konrad Rzeszutek Wilk Cc: Jeremy Fitzhardinge Cc: Mel Gorman Cc: xen-devel@lists.xensource.com Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Tested-by: Konrad Rzeszutek Wilk Acked-by: Konrad Rzeszutek Wilk Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 39 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 30899901aef5..650f79a1f2bd 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -57,8 +57,7 @@ static const struct ethtool_ops xennet_ethtool_ops; struct netfront_cb { - struct page *page; - unsigned offset; + int pull_to; }; #define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb)) @@ -867,15 +866,9 @@ static int handle_incoming_queue(struct net_device *dev, struct sk_buff *skb; while ((skb = __skb_dequeue(rxq)) != NULL) { - struct page *page = NETFRONT_SKB_CB(skb)->page; - void *vaddr = page_address(page); - unsigned offset = NETFRONT_SKB_CB(skb)->offset; + int pull_to = NETFRONT_SKB_CB(skb)->pull_to; - memcpy(skb->data, vaddr + offset, - skb_headlen(skb)); - - if (page != skb_frag_page(&skb_shinfo(skb)->frags[0])) - __free_page(page); + __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); /* Ethernet work: Delayed to here as it peeks the header. */ skb->protocol = eth_type_trans(skb, dev); @@ -913,7 +906,6 @@ static int xennet_poll(struct napi_struct *napi, int budget) struct sk_buff_head errq; struct sk_buff_head tmpq; unsigned long flags; - unsigned int len; int err; spin_lock(&np->rx_lock); @@ -955,24 +947,13 @@ err: } } - NETFRONT_SKB_CB(skb)->page = - skb_frag_page(&skb_shinfo(skb)->frags[0]); - NETFRONT_SKB_CB(skb)->offset = rx->offset; + NETFRONT_SKB_CB(skb)->pull_to = rx->status; + if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD) + NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD; - len = rx->status; - if (len > RX_COPY_THRESHOLD) - len = RX_COPY_THRESHOLD; - skb_put(skb, len); - - if (rx->status > len) { - skb_shinfo(skb)->frags[0].page_offset = - rx->offset + len; - skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len); - skb->data_len = rx->status - len; - } else { - __skb_fill_page_desc(skb, 0, NULL, 0, 0); - skb_shinfo(skb)->nr_frags = 0; - } + skb_shinfo(skb)->frags[0].page_offset = rx->offset; + skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status); + skb->data_len = rx->status; i = xennet_fill_frags(np, skb, &tmpq); @@ -999,7 +980,7 @@ err: * receive throughout using the standard receive * buffer size was cut by 25%(!!!). */ - skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len); + skb->truesize += skb->data_len - RX_COPY_THRESHOLD; skb->len += skb->data_len; if (rx->flags & XEN_NETRXF_csum_blank) From 3f509c689a07a4aa989b426893d8491a7ffcc410 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Aug 2012 15:24:09 +0000 Subject: [PATCH 236/665] netfilter: nf_nat_sip: fix incorrect handling of EBUSY for RTCP expectation We're hitting bug while trying to reinsert an already existing expectation: kernel BUG at kernel/timer.c:895! invalid opcode: 0000 [#1] SMP [...] Call Trace: [] nf_ct_expect_related_report+0x4a0/0x57a [nf_conntrack] [] ? in4_pton+0x72/0x131 [] ip_nat_sdp_media+0xeb/0x185 [nf_nat_sip] [] set_expected_rtp_rtcp+0x32d/0x39b [nf_conntrack_sip] [] process_sdp+0x30c/0x3ec [nf_conntrack_sip] [] ? irq_exit+0x9a/0x9c [] ? ip_nat_sdp_media+0x185/0x185 [nf_nat_sip] We have to remove the RTP expectation if the RTCP expectation hits EBUSY since we keep trying with other ports until we succeed. Reported-by: Rafal Fitt Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/nf_nat_sip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 4ad9cf173992..9c87cde28ff8 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -502,7 +502,10 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, ret = nf_ct_expect_related(rtcp_exp); if (ret == 0) break; - else if (ret != -EBUSY) { + else if (ret == -EBUSY) { + nf_ct_unexpect_related(rtp_exp); + continue; + } else if (ret < 0) { nf_ct_unexpect_related(rtp_exp); port = 0; break; From e2c53be223aca36cf93eb6a0f6bafa079e78f52b Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 23 Aug 2012 21:46:25 +0000 Subject: [PATCH 237/665] gianfar: fix default tx vlan offload feature flag Commit - "b852b72 gianfar: fix bug caused by 87c288c6e9aa31720b72e2bc2d665e24e1653c3e" disables by default (on mac init) the hw vlan tag insertion. The "features" flags were not updated to reflect this, and "ethtool -K" shows tx-vlan-offload to be "on" by default. Cc: Sebastian Poehn Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 4605f7246687..d3233f59a82e 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1041,7 +1041,7 @@ static int gfar_probe(struct platform_device *ofdev) if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->features |= NETIF_F_HW_VLAN_RX; } if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { From 99469c32f79a32d8481f87be0d3c66dad286f4ec Mon Sep 17 00:00:00 2001 From: "xeb@mail.ru" Date: Fri, 24 Aug 2012 01:07:38 +0000 Subject: [PATCH 238/665] l2tp: avoid to use synchronize_rcu in tunnel free function Avoid to use synchronize_rcu in l2tp_tunnel_free because context may be atomic. Signed-off-by: Dmitry Kozlov Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 3 +-- net/l2tp/l2tp_core.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 393355d37b47..513cab08a986 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1347,11 +1347,10 @@ static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) /* Remove from tunnel list */ spin_lock_bh(&pn->l2tp_tunnel_list_lock); list_del_rcu(&tunnel->list); + kfree_rcu(tunnel, rcu); spin_unlock_bh(&pn->l2tp_tunnel_list_lock); - synchronize_rcu(); atomic_dec(&l2tp_tunnel_count); - kfree(tunnel); } /* Create a socket for the tunnel, if one isn't set up by diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index a38ec6cdeee1..56d583e083a7 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -163,6 +163,7 @@ struct l2tp_tunnel_cfg { struct l2tp_tunnel { int magic; /* Should be L2TP_TUNNEL_MAGIC */ + struct rcu_head rcu; rwlock_t hlist_lock; /* protect session_hlist */ struct hlist_head session_hlist[L2TP_HASH_SIZE]; /* hashed list of sessions, From d821a4c4d11ad160925dab2bb009b8444beff484 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 24 Aug 2012 20:38:11 +0000 Subject: [PATCH 239/665] e1000e: DoS while TSO enabled caused by link partner with small MSS With a low enough MSS on the link partner and TSO enabled locally, the networking stack can periodically send a very large (e.g. 64KB) TCP message for which the driver will attempt to use more Tx descriptors than are available by default in the Tx ring. This is due to a workaround in the code that imposes a limit of only 4 MSS-sized segments per descriptor which appears to be a carry-over from the older e1000 driver and may be applicable only to some older PCI or PCIx parts which are not supported in e1000e. When the driver gets a message that is too large to fit across the configured number of Tx descriptors, it stops the upper stack from queueing any more and gets stuck in this state. After a timeout, the upper stack assumes the adapter is hung and calls the driver to reset it. Remove the unnecessary limitation of using up to only 4 MSS-sized segments per Tx descriptor, and put in a hard failure test to catch when attempting to check for message sizes larger than would fit in the whole Tx ring. Refactor the remaining logic that limits the size of data per Tx descriptor from a seemingly arbitrary 8KB to a limit based on the dynamic size of the Tx packet buffer as described in the hardware specification. Also, fix the logic in the check for space in the Tx ring for the next largest possible packet after the current one has been successfully queued for transmit, and use the appropriate defines for default ring sizes in e1000_probe instead of magic values. This issue goes back to the introduction of e1000e in 2.6.24 when it was split off from e1000. Reported-by: Ben Hutchings Signed-off-by: Bruce Allan Cc: Stable [2.6.24+] Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/e1000e/e1000.h | 1 + drivers/net/ethernet/intel/e1000e/netdev.c | 48 +++++++++++----------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index cd153326c3cf..cb3356c9af80 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -310,6 +310,7 @@ struct e1000_adapter { */ struct e1000_ring *tx_ring /* One per active queue */ ____cacheline_aligned_in_smp; + u32 tx_fifo_limit; struct napi_struct napi; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 46c3b1f9ff89..d01a099475a1 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3516,6 +3516,15 @@ void e1000e_reset(struct e1000_adapter *adapter) break; } + /* + * Alignment of Tx data is on an arbitrary byte boundary with the + * maximum size per Tx descriptor limited only to the transmit + * allocation of the packet buffer minus 96 bytes with an upper + * limit of 24KB due to receive synchronization limitations. + */ + adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96, + 24 << 10); + /* * Disable Adaptive Interrupt Moderation if 2 full packets cannot * fit in receive buffer. @@ -4785,12 +4794,9 @@ static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb) return 1; } -#define E1000_MAX_PER_TXD 8192 -#define E1000_MAX_TXD_PWR 12 - static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, unsigned int first, unsigned int max_per_txd, - unsigned int nr_frags, unsigned int mss) + unsigned int nr_frags) { struct e1000_adapter *adapter = tx_ring->adapter; struct pci_dev *pdev = adapter->pdev; @@ -5023,20 +5029,19 @@ static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) { + BUG_ON(size > tx_ring->count); + if (e1000_desc_unused(tx_ring) >= size) return 0; return __e1000_maybe_stop_tx(tx_ring, size); } -#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1) static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_ring *tx_ring = adapter->tx_ring; unsigned int first; - unsigned int max_per_txd = E1000_MAX_PER_TXD; - unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; unsigned int len = skb_headlen(skb); unsigned int nr_frags; @@ -5056,18 +5061,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, } mss = skb_shinfo(skb)->gso_size; - /* - * The controller does a simple calculation to - * make sure there is enough room in the FIFO before - * initiating the DMA for each buffer. The calc is: - * 4 = ceil(buffer len/mss). To make sure we don't - * overrun the FIFO, adjust the max buffer len if mss - * drops. - */ if (mss) { u8 hdr_len; - max_per_txd = min(mss << 2, max_per_txd); - max_txd_pwr = fls(max_per_txd) - 1; /* * TSO Workaround for 82571/2/3 Controllers -- if skb->data @@ -5097,12 +5092,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, count++; count++; - count += TXD_USE_COUNT(len, max_txd_pwr); + count += DIV_ROUND_UP(len, adapter->tx_fifo_limit); nr_frags = skb_shinfo(skb)->nr_frags; for (f = 0; f < nr_frags; f++) - count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]), - max_txd_pwr); + count += DIV_ROUND_UP(skb_frag_size(&skb_shinfo(skb)->frags[f]), + adapter->tx_fifo_limit); if (adapter->hw.mac.tx_pkt_filtering) e1000_transfer_dhcp_info(adapter, skb); @@ -5144,15 +5139,18 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, tx_flags |= E1000_TX_FLAGS_NO_FCS; /* if count is 0 then mapping error has occurred */ - count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss); + count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit, + nr_frags); if (count) { skb_tx_timestamp(skb); netdev_sent_queue(netdev, skb->len); e1000_tx_queue(tx_ring, tx_flags, count); /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 2); - + e1000_maybe_stop_tx(tx_ring, + (MAX_SKB_FRAGS * + DIV_ROUND_UP(PAGE_SIZE, + adapter->tx_fifo_limit) + 2)); } else { dev_kfree_skb_any(skb); tx_ring->buffer_info[first].time_stamp = 0; @@ -6327,8 +6325,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->hw.phy.autoneg_advertised = 0x2f; /* ring size defaults */ - adapter->rx_ring->count = 256; - adapter->tx_ring->count = 256; + adapter->rx_ring->count = E1000_DEFAULT_RXD; + adapter->tx_ring->count = E1000_DEFAULT_TXD; /* * Initial Wake on LAN setting - If APM wake is enabled in From acbb219d5f53821b2d0080d047800410c0420ea1 Mon Sep 17 00:00:00 2001 From: Francesco Ruggeri Date: Fri, 24 Aug 2012 07:38:35 +0000 Subject: [PATCH 240/665] net: ipv4: ipmr_expire_timer causes crash when removing net namespace When tearing down a net namespace, ipv4 mr_table structures are freed without first deactivating their timers. This can result in a crash in run_timer_softirq. This patch mimics the corresponding behaviour in ipv6. Locking and synchronization seem to be adequate. We are about to kfree mrt, so existing code should already make sure that no other references to mrt are pending or can be created by incoming traffic. The functions invoked here do not cause new references to mrt or other race conditions to be created. Invoking del_timer_sync guarantees that ipmr_expire_timer is inactive. Both ipmr_expire_process (whose completion we may have to wait in del_timer_sync) and mroute_clean_tables internally use mfc_unres_lock or other synchronizations when needed, and they both only modify mrt. Tested in Linux 3.4.8. Signed-off-by: Francesco Ruggeri Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8eec8f4a0536..ebdf06f938bf 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -124,6 +124,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock); static struct kmem_cache *mrt_cachep __read_mostly; static struct mr_table *ipmr_new_table(struct net *net, u32 id); +static void ipmr_free_table(struct mr_table *mrt); + static int ip_mr_forward(struct net *net, struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *cache, int local); @@ -131,6 +133,7 @@ static int ipmr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, vifi_t vifi, int assert); static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); +static void mroute_clean_tables(struct mr_table *mrt); static void ipmr_expire_process(unsigned long arg); #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES @@ -271,7 +274,7 @@ static void __net_exit ipmr_rules_exit(struct net *net) list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { list_del(&mrt->list); - kfree(mrt); + ipmr_free_table(mrt); } fib_rules_unregister(net->ipv4.mr_rules_ops); } @@ -299,7 +302,7 @@ static int __net_init ipmr_rules_init(struct net *net) static void __net_exit ipmr_rules_exit(struct net *net) { - kfree(net->ipv4.mrt); + ipmr_free_table(net->ipv4.mrt); } #endif @@ -336,6 +339,13 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) return mrt; } +static void ipmr_free_table(struct mr_table *mrt) +{ + del_timer_sync(&mrt->ipmr_expire_timer); + mroute_clean_tables(mrt); + kfree(mrt); +} + /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) From 5c879d2094946081af934739850c7260e8b25d3c Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 26 Aug 2012 00:35:45 +0000 Subject: [PATCH 241/665] bnx2x: fix 57840_MF pci id Commit c3def943c7117d42caaed3478731ea7c3c87190e have added support for new pci ids of the 57840 board, while failing to change the obsolete value in 'pci_ids.h'. This patch does so, allowing the probe of such devices. Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- include/linux/pci_ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index fc3526077348..6b4565c440c8 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2149,7 +2149,7 @@ #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 #define PCI_DEVICE_ID_NX2_5706S 0x16aa -#define PCI_DEVICE_ID_NX2_57840_MF 0x16ab +#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 #define PCI_DEVICE_ID_NX2_5708S 0x16ac #define PCI_DEVICE_ID_NX2_57840_VF 0x16ad #define PCI_DEVICE_ID_NX2_57810_MF 0x16ae From bbd99797973f2cebd905bf6469ce08b531ab258f Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 30 Aug 2012 19:24:34 +0200 Subject: [PATCH 242/665] cuse: fix fuse_conn_kill() fuse_conn_kill() removed fc->entry, called fuse_ctl_remove_conn() and fuse_bdi_destroy(). None of which is appropriate for cuse cleanup. The fuse_ctl_remove_conn() decrements the nlink on the control filesystem, which is totally bogus. The others are harmless but unnecessary. So move these out from fuse_conn_kill() to fuse_put_super() where they belong. Signed-off-by: Miklos Szeredi --- fs/fuse/inode.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index ce0a2838ccd0..fca222dabe3c 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -367,11 +367,6 @@ void fuse_conn_kill(struct fuse_conn *fc) wake_up_all(&fc->waitq); wake_up_all(&fc->blocked_waitq); wake_up_all(&fc->reserved_req_waitq); - mutex_lock(&fuse_mutex); - list_del(&fc->entry); - fuse_ctl_remove_conn(fc); - mutex_unlock(&fuse_mutex); - fuse_bdi_destroy(fc); } EXPORT_SYMBOL_GPL(fuse_conn_kill); @@ -380,7 +375,14 @@ static void fuse_put_super(struct super_block *sb) struct fuse_conn *fc = get_fuse_conn_super(sb); fuse_send_destroy(fc); + fuse_conn_kill(fc); + mutex_lock(&fuse_mutex); + list_del(&fc->entry); + fuse_ctl_remove_conn(fc); + mutex_unlock(&fuse_mutex); + fuse_bdi_destroy(fc); + fuse_conn_put(fc); } From 8d39d801d64658d7d69e4754f287a71e9f9bbcb8 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 30 Aug 2012 19:24:35 +0200 Subject: [PATCH 243/665] cuse: kill connection on initialization error Luca Risolia reported that a CUSE daemon will continue to run even if initialization of the emulated device failes for some reason (e.g. the device number is already registered by another driver). This patch disconnects the fuse device on error, which will make the userspace CUSE daemon exit, albeit without indication about what the problem was. Reported-by: Luca Risolia Signed-off-by: Miklos Szeredi --- fs/fuse/cuse.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 3426521f3205..ee8d55042298 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -396,7 +396,7 @@ err_device: err_region: unregister_chrdev_region(devt, 1); err: - fc->conn_error = 1; + fuse_conn_kill(fc); goto out; } @@ -532,8 +532,6 @@ static int cuse_channel_release(struct inode *inode, struct file *file) cdev_del(cc->cdev); } - /* kill connection and shutdown channel */ - fuse_conn_kill(&cc->fc); rc = fuse_dev_release(inode, file); /* puts the base reference */ return rc; From c5ae7d41927dbd208c885d4794e30617ad6cdf12 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 28 Aug 2012 12:33:07 +0000 Subject: [PATCH 244/665] ipv4: must use rcu protection while calling fib_lookup Following lockdep splat was reported by Pavel Roskin : [ 1570.586223] =============================== [ 1570.586225] [ INFO: suspicious RCU usage. ] [ 1570.586228] 3.6.0-rc3-wl-main #98 Not tainted [ 1570.586229] ------------------------------- [ 1570.586231] /home/proski/src/linux/net/ipv4/route.c:645 suspicious rcu_dereference_check() usage! [ 1570.586233] [ 1570.586233] other info that might help us debug this: [ 1570.586233] [ 1570.586236] [ 1570.586236] rcu_scheduler_active = 1, debug_locks = 0 [ 1570.586238] 2 locks held by Chrome_IOThread/4467: [ 1570.586240] #0: (slock-AF_INET){+.-...}, at: [] release_sock+0x2c/0xa0 [ 1570.586253] #1: (fnhe_lock){+.-...}, at: [] update_or_create_fnhe+0x2c/0x270 [ 1570.586260] [ 1570.586260] stack backtrace: [ 1570.586263] Pid: 4467, comm: Chrome_IOThread Not tainted 3.6.0-rc3-wl-main #98 [ 1570.586265] Call Trace: [ 1570.586271] [] lockdep_rcu_suspicious+0xfd/0x130 [ 1570.586275] [] update_or_create_fnhe+0x15c/0x270 [ 1570.586278] [] __ip_rt_update_pmtu+0x73/0xb0 [ 1570.586282] [] ip_rt_update_pmtu+0x29/0x90 [ 1570.586285] [] inet_csk_update_pmtu+0x2c/0x80 [ 1570.586290] [] tcp_v4_mtu_reduced+0x2e/0xc0 [ 1570.586293] [] tcp_release_cb+0xa4/0xb0 [ 1570.586296] [] release_sock+0x55/0xa0 [ 1570.586300] [] tcp_sendmsg+0x4af/0xf50 [ 1570.586305] [] inet_sendmsg+0x120/0x230 [ 1570.586308] [] ? inet_sk_rebuild_header+0x40/0x40 [ 1570.586312] [] ? sock_update_classid+0xbd/0x3b0 [ 1570.586315] [] ? sock_update_classid+0x130/0x3b0 [ 1570.586320] [] do_sock_write+0xc5/0xe0 [ 1570.586323] [] sock_aio_write+0x53/0x80 [ 1570.586328] [] do_sync_write+0xa3/0xe0 [ 1570.586332] [] vfs_write+0x165/0x180 [ 1570.586335] [] sys_write+0x45/0x90 [ 1570.586340] [] system_call_fastpath+0x16/0x1b Signed-off-by: Eric Dumazet Reported-by: Pavel Roskin Signed-off-by: David S. Miller --- net/ipv4/route.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 24fd4c596643..82cf2a722b23 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -934,12 +934,14 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; + rcu_read_lock(); if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { struct fib_nh *nh = &FIB_RES_NH(res); update_or_create_fnhe(nh, fl4->daddr, 0, mtu, jiffies + ip_rt_mtu_expires); } + rcu_read_unlock(); return mtu; } From 26614ba5445fe31a69068a5e94266fa08b4ee345 Mon Sep 17 00:00:00 2001 From: Merav Sicron Date: Mon, 27 Aug 2012 03:26:19 +0000 Subject: [PATCH 245/665] bnx2x: Move netif_napi_add to the open call Move netif_napi_add for all queues from the probe call to the open call, to avoid the case that napi objects are added for queues that may eventually not be initialized and activated. With the former behavior, the driver could crash when netpoll was calling ndo_poll_controller. Signed-off-by: Merav Sicron Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 3 --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 4 ++++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 4 ++-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 -- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 10 ++++------ 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 463b9ec57d80..6d1a24acb77e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1708,9 +1708,6 @@ struct bnx2x_func_init_params { continue; \ else -#define for_each_napi_rx_queue(bp, var) \ - for ((var) = 0; (var) < bp->num_napi_queues; (var)++) - /* Skip OOO FP */ #define for_each_tx_queue(bp, var) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index e879e19eb0d6..af20c6ee2cd9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2046,6 +2046,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) */ bnx2x_setup_tc(bp->dev, bp->max_cos); + /* Add all NAPI objects */ + bnx2x_add_all_napi(bp); bnx2x_napi_enable(bp); /* set pf load just before approaching the MCP */ @@ -2408,6 +2410,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) /* Disable HW interrupts, NAPI */ bnx2x_netif_stop(bp, 1); + /* Delete all NAPI objects */ + bnx2x_del_all_napi(bp); /* Release IRQs */ bnx2x_free_irq(bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index dfa757e74296..21b553229ea4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -792,7 +792,7 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp) bp->num_napi_queues = bp->num_queues; /* Add NAPI objects */ - for_each_napi_rx_queue(bp, i) + for_each_rx_queue(bp, i) netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), bnx2x_poll, BNX2X_NAPI_WEIGHT); } @@ -801,7 +801,7 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp) { int i; - for_each_napi_rx_queue(bp, i) + for_each_rx_queue(bp, i) netif_napi_del(&bnx2x_fp(bp, i, napi)); } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index fc4e0e3885b0..c37a68d68090 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -2888,11 +2888,9 @@ static void bnx2x_get_channels(struct net_device *dev, */ static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss) { - bnx2x_del_all_napi(bp); bnx2x_disable_msi(bp); BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE; bnx2x_set_int_mode(bp); - bnx2x_add_all_napi(bp); } /** diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 02b5a343b195..5b42275ed033 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -8427,6 +8427,8 @@ unload_error: /* Disable HW interrupts, NAPI */ bnx2x_netif_stop(bp, 1); + /* Delete all NAPI objects */ + bnx2x_del_all_napi(bp); /* Release IRQs */ bnx2x_free_irq(bp); @@ -11899,9 +11901,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, */ bnx2x_set_int_mode(bp); - /* Add all NAPI objects */ - bnx2x_add_all_napi(bp); - rc = register_netdev(dev); if (rc) { dev_err(&pdev->dev, "Cannot register net device\n"); @@ -11976,9 +11975,6 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) unregister_netdev(dev); - /* Delete all NAPI objects */ - bnx2x_del_all_napi(bp); - /* Power on: we can't let PCI layer write to us while we are in D3 */ bnx2x_set_power_state(bp, PCI_D0); @@ -12025,6 +12021,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bnx2x_tx_disable(bp); bnx2x_netif_stop(bp, 0); + /* Delete all NAPI objects */ + bnx2x_del_all_napi(bp); del_timer_sync(&bp->timer); From 14a15d618743ebc4936fe03073bf0c75024d3a07 Mon Sep 17 00:00:00 2001 From: Merav Sicron Date: Mon, 27 Aug 2012 03:26:20 +0000 Subject: [PATCH 246/665] bnx2x: Correct the ndo_poll_controller call This patch correct poll_bnx2x (ndo_poll_controller call) which was not functioning well with MSI-X. Signed-off-by: Merav Sicron Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 5b42275ed033..21054987257a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11231,10 +11231,12 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static void poll_bnx2x(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); + int i; - disable_irq(bp->pdev->irq); - bnx2x_interrupt(bp->pdev->irq, dev); - enable_irq(bp->pdev->irq); + for_each_eth_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + } } #endif From 45caae74d238ef6583e9402cb8c550cc0b0f7dbd Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 28 Aug 2012 01:26:14 +0300 Subject: [PATCH 247/665] ARM: OMAP: timer: obey the !CONFIG_OMAP_32K_TIMER Currently, omap2_sync32k_clocksource_init() function initializes the 32K timer as the system clock source regardless of the CONFIG_OMAP_32K_TIMER setting. Fix this by providing a default implementation for !CONFIG_OMAP_32K_TIMER case. Signed-off-by: Igor Grinberg Reviewed-by: Paul Walmsley Acked-by: Santosh Shilimkar Cc: stable@vger.kernel.org Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 2ff6d41ec6c6..2ba4f57dda86 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -260,6 +260,7 @@ static u32 notrace dmtimer_read_sched_clock(void) return 0; } +#ifdef CONFIG_OMAP_32K_TIMER /* Setup free-running counter for clocksource */ static int __init omap2_sync32k_clocksource_init(void) { @@ -299,6 +300,12 @@ static int __init omap2_sync32k_clocksource_init(void) return ret; } +#else +static inline int omap2_sync32k_clocksource_init(void) +{ + return -ENODEV; +} +#endif static void __init omap2_gptimer_clocksource_init(int gptimer_id, const char *fck_source) From 528c28f5c1cd435c45515b323919205c95342331 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 29 Aug 2012 18:24:30 +0300 Subject: [PATCH 248/665] ARM: OMAP: sram: fix OMAP4 errata handling OMAP4-specific code should be executed only if we are running on OMAP4. Otherwise it may break multi-OMAP kernels. Found by reading the code. Signed-off-by: Aaro Koskinen Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/sram.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 766181cb5c95..85c23db25034 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -175,8 +175,10 @@ static void __init omap_map_sram(void) return; #ifdef CONFIG_OMAP4_ERRATA_I688 + if (cpu_is_omap44xx()) { omap_sram_start += PAGE_SIZE; omap_sram_size -= SZ_16K; + } #endif if (cpu_is_omap34xx()) { /* From b285673489e39252a2c3f0c7a7d77fd28a6cda38 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 29 Aug 2012 18:24:31 +0300 Subject: [PATCH 249/665] ARM: OMAP: sram: skip the first 16K on OMAP3 HS In some OMAP3 HS devices (at least Nokia N9 and N950), the public SRAM seems to conflict with secure portition of SRAM. When booting the 3.6-rc3 kernel (and also earlier) on these devices, the kernel gets tainted with tons of the following warnings: [ 6.894348] In-band Error seen by MPU at address 0 [...] [ 6.894378] WARNING: at arch/arm/mach-omap2/omap_l3_smx.c:162 Fix this by skipping the first 16K of the public SRAM. (Note that the mapping could not be changed, as it resulted in secure monitor call failure in save_secure_sram().) This will leave 12K SRAM available that should be still sufficient. The patch has been boot tested with vanilla 3.6-rc3 on N900, N950 and N9. Signed-off-by: Aaro Koskinen Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/sram.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 85c23db25034..024f3b08db29 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -68,6 +68,7 @@ static unsigned long omap_sram_start; static void __iomem *omap_sram_base; +static unsigned long omap_sram_skip; static unsigned long omap_sram_size; static void __iomem *omap_sram_ceil; @@ -106,6 +107,7 @@ static int is_sram_locked(void) */ static void __init omap_detect_sram(void) { + omap_sram_skip = SRAM_BOOTLOADER_SZ; if (cpu_class_is_omap2()) { if (is_sram_locked()) { if (cpu_is_omap34xx()) { @@ -113,6 +115,7 @@ static void __init omap_detect_sram(void) if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) || (omap_type() == OMAP2_DEVICE_TYPE_SEC)) { omap_sram_size = 0x7000; /* 28K */ + omap_sram_skip += SZ_16K; } else { omap_sram_size = 0x8000; /* 32K */ } @@ -205,8 +208,8 @@ static void __init omap_map_sram(void) * Looks like we need to preserve some bootloader code at the * beginning of SRAM for jumping to flash for reboot to work... */ - memset_io(omap_sram_base + SRAM_BOOTLOADER_SZ, 0, - omap_sram_size - SRAM_BOOTLOADER_SZ); + memset_io(omap_sram_base + omap_sram_skip, 0, + omap_sram_size - omap_sram_skip); } /* @@ -220,7 +223,7 @@ void *omap_sram_push_address(unsigned long size) { unsigned long available, new_ceil = (unsigned long)omap_sram_ceil; - available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ); + available = omap_sram_ceil - (omap_sram_base + omap_sram_skip); if (size > available) { pr_err("Not enough space in SRAM\n"); From a17fb8f520c3c662686aa54a86773f354002c7d3 Mon Sep 17 00:00:00 2001 From: Radek Pilar Date: Fri, 17 Aug 2012 18:03:43 +0200 Subject: [PATCH 250/665] ARM: OMAP: Config fix for omap3-touchbook board Fix inconsistency between mach-types and CONFIG_ name that prevents touchbook board from booting. Signed-off-by: Radek Pilar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 3 ++- arch/arm/mach-omap2/Makefile | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index dd2db025f778..0a3e1b9f1fbc 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -231,10 +231,11 @@ config MACH_OMAP3_PANDORA select OMAP_PACKAGE_CBB select REGULATOR_FIXED_VOLTAGE if REGULATOR -config MACH_OMAP3_TOUCHBOOK +config MACH_TOUCHBOOK bool "OMAP3 Touch Book" depends on ARCH_OMAP3 default y + select OMAP_PACKAGE_CBB config MACH_OMAP_3430SDP bool "OMAP 3430 SDP board" diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index f6a24b3f9c4f..34c2c7f59f0a 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -255,7 +255,7 @@ obj-$(CONFIG_MACH_OMAP_3630SDP) += board-zoom-display.o obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o obj-$(CONFIG_MACH_CM_T3517) += board-cm-t3517.o obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o -obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o +obj-$(CONFIG_MACH_TOUCHBOOK) += board-omap3touchbook.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o From a348cd5fd85dbca7260ef865c5def85929932861 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 31 Aug 2012 09:56:25 +1000 Subject: [PATCH 251/665] drm/nvd0/disp: hopefully fix selection of 6/8bpc mode on DP outputs I have a very limited number of traces available for DP on NVD9+, but, these values produce the same as the binary driver on a confirmed 18-bit eDP panel and a confirmed 24-bit eDP panel (Retina MBP). It's interesting that the bitfield values also match the MODE_CTRL values that control the same thing on nv50:nvd9. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvd0_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index dac525b2994e..8a2fc89b7763 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1510,10 +1510,10 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, case OUTPUT_DP: if (nv_connector->base.display_info.bpc == 6) { nv_encoder->dp.datarate = mode->clock * 18 / 8; - syncs |= 0x00000140; + syncs |= 0x00000002 << 6; } else { nv_encoder->dp.datarate = mode->clock * 24 / 8; - syncs |= 0x00000180; + syncs |= 0x00000005 << 6; } if (nv_encoder->dcb->sorconf.link & 1) From 991083ba60f89e717e3a4175be96d48a810e9eae Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 31 Aug 2012 10:51:20 +1000 Subject: [PATCH 252/665] drm/nv50-/gpio: initialise to vbios defaults during init This is required to fix an issue on the Retina MBP where the eDP panel's AUX channel isn't wired up to the HPD pin for the panel, causing our aux code to bail out early. From looking at various traces of the binary driver, it appears NVIDIA do something very similar on at least all nv50+ chipsets during their initialisation sequence. So, hopefully this is safe. Issue and fix initially tracked down by Ryan Bourgeois on fdo#51971. Backported fix from reworked nouveau kernel module. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_gpio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index f429e6a8ca7a..f03490534893 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -115,6 +115,9 @@ nv50_gpio_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + /* initialise gpios and routing to vbios defaults */ + nouveau_gpio_reset(dev); + /* disable, and ack any pending gpio interrupts */ nv_wr32(dev, 0xe050, 0x00000000); nv_wr32(dev, 0xe054, 0xffffffff); From ee3c843d0fc21c68ced93b982b5731178a24df68 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 8 Aug 2012 23:03:07 -0700 Subject: [PATCH 253/665] ARM: shmobile: armadillo800eva: fixup: sound card detection order Since armadillo800eva has 2 sound cards, and had reversed deferred probe order issue, it was purposely registered in reverse order. But it was solved by 1d29cfa57471a5e4b8a7c2a7433eeba170d3ad92 (driver core: fixup reversed deferred probe order) armadillo800eva board is expecting that FSI-WM8978 is the 1st, and FSI-HDMI is the 2nd sound card. This patch fixes it up Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-armadillo800eva.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index cf10f92856dc..ecd8136c5909 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -901,8 +901,8 @@ static struct platform_device *eva_devices[] __initdata = { &camera_device, &ceu0_device, &fsi_device, - &fsi_hdmi_device, &fsi_wm8978_device, + &fsi_hdmi_device, }; static void __init eva_clock_init(void) From e26a6038d3a902cd0bc784fc55571a83d7f9cb79 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 5 Aug 2012 22:47:00 -0700 Subject: [PATCH 254/665] ARM: shmobile: mackerel: fixup usb module order renesas_usbhs driver can play role as both Host and Gadget. In case of Gadget, it requires not only renesas_usbhs but also usb gadget module (like g_ether). So, renesas_usbhs driver calls usb_add_gadget_udc() on probe time. Because of this behavior, Host port plays also Gadget role if kernel has both Host/Gadget support. In mackerel case, from 0ada2da51800a4914887a9bcf22d563be80e50be (ARM: mach-shmobile: mackerel: use renesas_usbhs instead of r8a66597_hcd) usb0 plays Gadget role, and usb1 plays Host role, and current mackerel board probes as usb1 -> usb0. Thus, 1st installed usb gadget module (like g_ether) will be assigned to usb1 (= usb Host port), and 2nd module to usb0 (= usb Gadget port). It is very confusable for user. This patch fixup usb modes probing order as usb0 -> usb1. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-mackerel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 7ea2b31e3199..c129542f6aed 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -695,6 +695,7 @@ static struct platform_device usbhs0_device = { * - J30 "open" * - modify usbhs1_get_id() USBHS_HOST -> USBHS_GADGET * - add .get_vbus = usbhs_get_vbus in usbhs1_private + * - check usbhs0_device(pio)/usbhs1_device(irq) order in mackerel_devices. */ #define IRQ8 evt2irq(0x0300) #define USB_PHY_MODE (1 << 4) @@ -1325,8 +1326,8 @@ static struct platform_device *mackerel_devices[] __initdata = { &nor_flash_device, &smc911x_device, &lcdc_device, - &usbhs1_device, &usbhs0_device, + &usbhs1_device, &leds_device, &fsi_device, &fsi_ak4643_device, From 5b423f6a40a0327f9d40bc8b97ce9be266f74368 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Aug 2012 16:25:49 +0000 Subject: [PATCH 255/665] netfilter: nf_conntrack: fix racy timer handling with reliable events Existing code assumes that del_timer returns true for alive conntrack entries. However, this is not true if reliable events are enabled. In that case, del_timer may return true for entries that were just inserted in the dying list. Note that packets / ctnetlink may hold references to conntrack entries that were just inserted to such list. This patch fixes the issue by adding an independent timer for event delivery. This increases the size of the ecache extension. Still we can revisit this later and use variable size extensions to allocate this area on demand. Tested-by: Oliver Smith Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_ecache.h | 1 + net/netfilter/nf_conntrack_core.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index e1ce1048fe5f..4a045cda9c60 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -18,6 +18,7 @@ struct nf_conntrack_ecache { u16 ctmask; /* bitmask of ct events to be delivered */ u16 expmask; /* bitmask of expect events to be delivered */ u32 pid; /* netlink pid of destroyer */ + struct timer_list timeout; }; static inline struct nf_conntrack_ecache * diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index cf4875565d67..2ceec64b19f9 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -249,12 +249,15 @@ static void death_by_event(unsigned long ul_conntrack) { struct nf_conn *ct = (void *)ul_conntrack; struct net *net = nf_ct_net(ct); + struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); + + BUG_ON(ecache == NULL); if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { /* bad luck, let's retry again */ - ct->timeout.expires = jiffies + + ecache->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ct->timeout); + add_timer(&ecache->timeout); return; } /* we've got the event delivered, now it's dying */ @@ -268,6 +271,9 @@ static void death_by_event(unsigned long ul_conntrack) void nf_ct_insert_dying_list(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); + struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); + + BUG_ON(ecache == NULL); /* add this conntrack to the dying list */ spin_lock_bh(&nf_conntrack_lock); @@ -275,10 +281,10 @@ void nf_ct_insert_dying_list(struct nf_conn *ct) &net->ct.dying); spin_unlock_bh(&nf_conntrack_lock); /* set a new timer to retry event delivery */ - setup_timer(&ct->timeout, death_by_event, (unsigned long)ct); - ct->timeout.expires = jiffies + + setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct); + ecache->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ct->timeout); + add_timer(&ecache->timeout); } EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); From 4fd20570995c46b08711b062c69ab903319d6041 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Thu, 30 Aug 2012 07:39:12 +0200 Subject: [PATCH 256/665] ARM: Kirkwood: Fix 'SZ_1M' undeclared here for db88f6281-bp-setup.c Linux-next has failed to compile for kirkwood since 23 August with: arch/arm/mach-kirkwood/db88f6281-bp-setup.c:29: error: 'SZ_1M' undeclared here (not in a function) arch/arm/mach-kirkwood/db88f6281-bp-setup.c:33: error: 'SZ_4M' undeclared here (not in a function) Add missing Signed-off-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/mach-kirkwood/db88f6281-bp-setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c index d93359379598..be90b7d0e10b 100644 --- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include From b72c200975a4ed579dbf3353019e19528745a29a Mon Sep 17 00:00:00 2001 From: Jaccon Bastiaansen Date: Mon, 27 Aug 2012 11:53:51 +0000 Subject: [PATCH 257/665] cs89x0 : packet reception not working The RxCFG register of the CS89x0 could be configured incorrectly (because of misplaced parentheses), resulting in the disabling of packet reception. Signed-off-by: Jaccon Bastiaansen Signed-off-by: David S. Miller --- drivers/net/ethernet/cirrus/cs89x0.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index 845b2020f291..138446957786 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -1243,6 +1243,7 @@ static void set_multicast_list(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); unsigned long flags; + u16 cfg; spin_lock_irqsave(&lp->lock, flags); if (dev->flags & IFF_PROMISC) @@ -1260,11 +1261,10 @@ static void set_multicast_list(struct net_device *dev) /* in promiscuous mode, we accept errored packets, * so we have to enable interrupts on them also */ - writereg(dev, PP_RxCFG, - (lp->curr_rx_cfg | - (lp->rx_mode == RX_ALL_ACCEPT) - ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL) - : 0)); + cfg = lp->curr_rx_cfg; + if (lp->rx_mode == RX_ALL_ACCEPT) + cfg |= RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL; + writereg(dev, PP_RxCFG, cfg); spin_unlock_irqrestore(&lp->lock, flags); } From ab6f148de28261682d300662e87b9477f7efc95b Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sun, 26 Aug 2012 20:41:38 +0000 Subject: [PATCH 258/665] usbnet: fix deadlock in resume A usbnet device can share a multifunction device with a storage device. If the storage device is autoresumed the usbnet devices also needs to be autoresumed. Allocating memory with GFP_KERNEL can deadlock in this case. This should go back into all kernels that have commit 65841fd5132c3941cdf5df09e70df3ed28323212 That is 3.5 Signed-off-by: Oliver Neukum CC: stable@kernel.org Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8531c1caac28..fd4b26d46fd5 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1573,7 +1573,7 @@ int usbnet_resume (struct usb_interface *intf) netif_device_present(dev->net) && !timer_pending(&dev->delay) && !test_bit(EVENT_RX_HALT, &dev->flags)) - rx_alloc_submit(dev, GFP_KERNEL); + rx_alloc_submit(dev, GFP_NOIO); if (!(dev->txq.qlen >= TX_QLEN(dev))) netif_tx_wake_all_queues(dev->net); From fa026e223df2514b271b20f839ab05d7f21181b9 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Tue, 28 Aug 2012 02:30:32 +0000 Subject: [PATCH 259/665] net: qmi_wwan: new device: Foxconn/Novatel E396 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Foxconn-branded Novatel E396, Gobi3k modem. Cc: Dan Williams Cc: Bjørn Mork Cc: Ben Chan Signed-off-by: Aleksander Morgado Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 328397c66730..189e52d2eee6 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -441,6 +441,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + {QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */ { } /* END */ }; From 48f125ce1cc3ff275f9587b5bf56bf0f90766c7d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 29 Aug 2012 06:49:12 +0000 Subject: [PATCH 260/665] net: ipv6: fix error return code Initialize return variable before exiting on an error path. The initial initialization of the return variable is also dropped, because that value is never used. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- net/ipv6/esp6.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 6dc7fd353ef5..282f3723ee19 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -167,8 +167,6 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) struct esp_data *esp = x->data; /* skb is pure payload to encrypt */ - err = -ENOMEM; - aead = esp->aead; alen = crypto_aead_authsize(aead); @@ -203,8 +201,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) } tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); - if (!tmp) + if (!tmp) { + err = -ENOMEM; goto error; + } seqhi = esp_tmp_seqhi(tmp); iv = esp_tmp_iv(aead, tmp, seqhilen); From 599901c3e4204e9d9c5a24df5402cd91617a2a26 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 29 Aug 2012 06:49:15 +0000 Subject: [PATCH 261/665] net/xfrm/xfrm_state.c: fix error return code Initialize return variable before exiting on an error path. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- net/xfrm/xfrm_state.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 87cd0e4d4282..210be48d8ae3 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1994,8 +1994,10 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay) goto error; x->outer_mode = xfrm_get_mode(x->props.mode, family); - if (x->outer_mode == NULL) + if (x->outer_mode == NULL) { + err = -EPROTONOSUPPORT; goto error; + } if (init_replay) { err = xfrm_init_replay(x); From b27393aecf66199f5ddad37c302d3e0cfadbe6c0 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Thu, 30 Aug 2012 06:37:32 +0000 Subject: [PATCH 262/665] net: ethernet: fix kernel OOPS when remove davinci_mdio module davinci mdio device is not unregistered from mdiobus when removing the module, which causes BUG_ON() when free the device from mdiobus. Calling mdiobus_unregister() before mdiobus_free() fixes the issue. Signed-off-by: Bin Liu Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_mdio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index cd7ee204e94a..a9ca4a03d31b 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -394,8 +394,10 @@ static int __devexit davinci_mdio_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct davinci_mdio_data *data = dev_get_drvdata(dev); - if (data->bus) + if (data->bus) { + mdiobus_unregister(data->bus); mdiobus_free(data->bus); + } if (data->clk) clk_put(data->clk); From fd4fb262b31ecb06bf93defb036e72b33ddf0200 Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Fri, 31 Aug 2012 08:55:21 +0530 Subject: [PATCH 263/665] ASoC: spear: correct the check for NULL dma_buffer pointer The if condition if (!buf && !buf->area) checks if the buf pointer is NULL and then dereferences it again to check if the buffer area is NULL, resulting in possible NULL dereference. Signed-off-by: Prasad Joshi Signed-off-by: Mark Brown --- sound/soc/spear/spear_pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c index 97c2cac8e92c..8c7f23729446 100644 --- a/sound/soc/spear/spear_pcm.c +++ b/sound/soc/spear/spear_pcm.c @@ -138,7 +138,7 @@ static void spear_pcm_free(struct snd_pcm *pcm) continue; buf = &substream->dma_buffer; - if (!buf && !buf->area) + if (!buf || !buf->area) continue; dma_free_writecombine(pcm->card->dev, buf->bytes, From 4c30aa33d4b4ce9a0ee5b32d058a40f4eca2ab63 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 29 Aug 2012 09:35:24 +0800 Subject: [PATCH 264/665] gpio: mc9s08dz60: Fix build error if I2C=m Make GPIO_MC9S08DZ60 depend on I2C=y, this fixes below build error: LD init/built-in.o drivers/built-in.o: In function `mc9s08dz60_get_value': clk-fixed-factor.c:(.text+0x7214): undefined reference to `i2c_smbus_read_byte_data' drivers/built-in.o: In function `mc9s08dz60_set': clk-fixed-factor.c:(.text+0x727c): undefined reference to `i2c_smbus_read_byte_data' clk-fixed-factor.c:(.text+0x72bc): undefined reference to `i2c_smbus_write_byte_data' drivers/built-in.o: In function `mc9s08dz60_i2c_driver_init': clk-fixed-factor.c:(.init.text+0x290): undefined reference to `i2c_register_driver' drivers/built-in.o: In function `mc9s08dz60_i2c_driver_exit': clk-fixed-factor.c:(.exit.text+0x2c): undefined reference to `i2c_del_driver' make: *** [vmlinux] Error 1 Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b16c8a72a2e2..ba7926f5c099 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -294,7 +294,7 @@ config GPIO_MAX732X_IRQ config GPIO_MC9S08DZ60 bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions" - depends on I2C && MACH_MX35_3DS + depends on I2C=y && MACH_MX35_3DS help Select this to enable the MC9S08DZ60 GPIO driver From dd2914972e5f6d9c1a687158c0f65b81d239fe37 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 28 Aug 2012 19:30:44 +0800 Subject: [PATCH 265/665] gpio: em: Fix checking return value of irq_alloc_descs irq_alloc_descs() returns negative error code on failure. Signed-off-by: Axel Lin Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index ae37181798b3..ec48ed512628 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -247,9 +247,9 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) p->irq_base = irq_alloc_descs(pdata->irq_base, 0, pdata->number_of_pins, numa_node_id()); - if (IS_ERR_VALUE(p->irq_base)) { + if (p->irq_base < 0) { dev_err(&pdev->dev, "cannot get irq_desc\n"); - return -ENXIO; + return p->irq_base; } pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n", pdata->gpio_base, pdata->number_of_pins, p->irq_base); From ffb690d5aa36d38d7bed7579e3f07b84ff6b3a08 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Fri, 31 Aug 2012 18:20:59 +0530 Subject: [PATCH 266/665] ASoC: Davinci: evm: Fix typo in cpu dai name Fix typo caused by recent commit (cf53756 - ASoC: davinci: davinci-pcm does not need to be a plaform_driver) Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index ab0ad4591b08..6fac5af13298 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -188,7 +188,7 @@ static struct snd_soc_dai_link dm365_evm_dai = { .cpu_dai_name = "davinci-vcif", .codec_dai_name = "cq93vc-hifi", .codec_name = "cq93vc-codec", - .platform_name = "avinci-vcif", + .platform_name = "davinci-vcif", #endif }; From 1146f8822ae6601e24f9072d6cd74f76506142cd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 1 Sep 2012 14:11:22 +0800 Subject: [PATCH 267/665] gpio: rdc321x: Prevent removal of modules exporting active GPIOs This driver can be built as a module, set the missing owner field of struct gpio_chip to prevent removal of modules exporting active GPIOs. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rdc321x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index e97016af6443..b62d443e9a59 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c @@ -170,6 +170,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) rdc321x_gpio_dev->reg2_data_base = r->start + 0x4; rdc321x_gpio_dev->chip.label = "rdc321x-gpio"; + rdc321x_gpio_dev->chip.owner = THIS_MODULE; rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input; rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config; rdc321x_gpio_dev->chip.get = rdc_gpio_get_value; From cee58483cf56e0ba355fdd97ff5e8925329aa936 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 31 Aug 2012 13:30:06 -0400 Subject: [PATCH 268/665] time: Move ktime_t overflow checking into timespec_valid_strict Andreas Bombe reported that the added ktime_t overflow checking added to timespec_valid in commit 4e8b14526ca7 ("time: Improve sanity checking of timekeeping inputs") was causing problems with X.org because it caused timeouts larger then KTIME_T to be invalid. Previously, these large timeouts would be clamped to KTIME_MAX and would never expire, which is valid. This patch splits the ktime_t overflow checking into a new timespec_valid_strict function, and converts the timekeeping codes internal checking to use this more strict function. Reported-and-tested-by: Andreas Bombe Cc: Zhouping Liu Cc: Ingo Molnar Cc: Prarit Bhargava Cc: Thomas Gleixner Cc: stable@vger.kernel.org Signed-off-by: John Stultz Signed-off-by: Linus Torvalds --- include/linux/time.h | 7 +++++++ kernel/time/timekeeping.c | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/linux/time.h b/include/linux/time.h index b0bbd8f0130d..b51e664c83e7 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -125,6 +125,13 @@ static inline bool timespec_valid(const struct timespec *ts) /* Can't have more nanoseconds then a second */ if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) return false; + return true; +} + +static inline bool timespec_valid_strict(const struct timespec *ts) +{ + if (!timespec_valid(ts)) + return false; /* Disallow values that could overflow ktime_t */ if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX) return false; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 0c1485e42be6..34e5eac81424 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -428,7 +428,7 @@ int do_settimeofday(const struct timespec *tv) struct timespec ts_delta, xt; unsigned long flags; - if (!timespec_valid(tv)) + if (!timespec_valid_strict(tv)) return -EINVAL; write_seqlock_irqsave(&tk->lock, flags); @@ -476,7 +476,7 @@ int timekeeping_inject_offset(struct timespec *ts) /* Make sure the proposed value is valid */ tmp = timespec_add(tk_xtime(tk), *ts); - if (!timespec_valid(&tmp)) { + if (!timespec_valid_strict(&tmp)) { ret = -EINVAL; goto error; } @@ -659,7 +659,7 @@ void __init timekeeping_init(void) struct timespec now, boot, tmp; read_persistent_clock(&now); - if (!timespec_valid(&now)) { + if (!timespec_valid_strict(&now)) { pr_warn("WARNING: Persistent clock returned invalid value!\n" " Check your CMOS/BIOS settings.\n"); now.tv_sec = 0; @@ -667,7 +667,7 @@ void __init timekeeping_init(void) } read_boot_clock(&boot); - if (!timespec_valid(&boot)) { + if (!timespec_valid_strict(&boot)) { pr_warn("WARNING: Boot clock returned invalid value!\n" " Check your CMOS/BIOS settings.\n"); boot.tv_sec = 0; @@ -713,7 +713,7 @@ static struct timespec timekeeping_suspend_time; static void __timekeeping_inject_sleeptime(struct timekeeper *tk, struct timespec *delta) { - if (!timespec_valid(delta)) { + if (!timespec_valid_strict(delta)) { printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid " "sleep delta value!\n"); return; From 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 1 Sep 2012 10:39:58 -0700 Subject: [PATCH 269/665] Linux 3.6-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 354026873b13..371ce8899f5c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Saber-toothed Squirrel # *DOCUMENTATION* From b6d86d3d6d6e4c9b588d81615c81b5a8292b62ed Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 24 Aug 2012 17:25:01 -0700 Subject: [PATCH 270/665] linux/kernel.h: Fix DIV_ROUND_CLOSEST to support negative dividends DIV_ROUND_CLOSEST returns a bad result for negative dividends: DIV_ROUND_CLOSEST(-2, 2) = 0 Most of the time this does not matter. However, in the hardware monitoring subsystem, DIV_ROUND_CLOSEST is sometimes used on integers which can be negative (such as temperatures). Signed-off-by: Guenter Roeck Acked-by: Jean Delvare --- include/linux/kernel.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 604382143bcf..594b419b7d20 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -82,10 +82,18 @@ __x - (__x % (y)); \ } \ ) + +/* + * Divide positive or negative dividend by positive divisor and round + * to closest integer. Result is undefined for negative divisors. + */ #define DIV_ROUND_CLOSEST(x, divisor)( \ { \ - typeof(divisor) __divisor = divisor; \ - (((x) + ((__divisor) / 2)) / (__divisor)); \ + typeof(x) __x = x; \ + typeof(divisor) __d = divisor; \ + (((typeof(x))-1) >= 0 || (__x) >= 0) ? \ + (((__x) + ((__d) / 2)) / (__d)) : \ + (((__x) - ((__d) / 2)) / (__d)); \ } \ ) From e1b2aa7f3051e268973b6126fdca602ac4af6bc4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 1 Sep 2012 09:57:40 +0000 Subject: [PATCH 271/665] fddi: 64 bit bug in smt_add_para() The intent was to set 4 bytes of data so that's why the sp_len is set to 4 on the next line. The cast to u_long pointer clears 8 bytes on 64 bit arches. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/fddi/skfp/pmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fddi/skfp/pmf.c b/drivers/net/fddi/skfp/pmf.c index 24d8566cfd8b..441b4dc79450 100644 --- a/drivers/net/fddi/skfp/pmf.c +++ b/drivers/net/fddi/skfp/pmf.c @@ -673,7 +673,7 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, sm_pm_get_ls(smc,port_to_mib(smc,port))) ; break ; case SMT_P_REASON : - * (u_long *) to = 0 ; + *(u32 *)to = 0 ; sp_len = 4 ; goto sp_done ; case SMT_P1033 : /* time stamp */ From 5002200599429e83fc13e0d9a2d4788b79515b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sat, 1 Sep 2012 03:47:26 +0000 Subject: [PATCH 272/665] net: qmi_wwan: add several new Gobi devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gobi devices are composite, needing both the qcserial and qmi_wwan drivers to support all functions. Re-syncing the list of supported devices with qcserial. Cc: Aleksander Morgado Cc: Thomas Tuttle Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 189e52d2eee6..adfab3fc5478 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -413,7 +413,9 @@ static const struct usb_device_id products[] = { /* 5. Gobi 2000 and 3000 devices */ {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ + {QMI_GOBI_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */ {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */ @@ -441,6 +443,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + {QMI_GOBI_DEVICE(0x12d1, 0x14f1)}, /* Sony Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */ { } /* END */ From 9bfc8da00b1e74f55a52cc06a0d364f1f7f61ed8 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 1 Sep 2012 21:47:11 +0200 Subject: [PATCH 273/665] HID: Only dump input if someone is listening Going through the motions of printing the debug message information takes a long time; using the keyboard can lead to a 160 us irqsoff latency. This patch skips hid_dump_input() when there are no open handles, which brings latency down to 100 us. Signed-off-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8bf8a64e5115..b8485a0106c9 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -996,7 +996,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_driver *hdrv = hid->driver; int ret; - hid_dump_input(hid, usage, value); + if (!list_empty(&hid->debug_list)) + hid_dump_input(hid, usage, value); if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { ret = hdrv->event(hid, field, usage, value); From 39855b5ba9a72a80de96009011b7f8b2fb01612b Mon Sep 17 00:00:00 2001 From: Joe Stringer Date: Fri, 31 Aug 2012 15:28:28 -0700 Subject: [PATCH 274/665] openvswitch: Fix typo Signed-off-by: Joe Stringer Signed-off-by: Jesse Gross --- net/openvswitch/actions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index f3f96badf5aa..954405ceae9e 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -45,7 +45,7 @@ static int make_writable(struct sk_buff *skb, int write_len) return pskb_expand_head(skb, 0, 0, GFP_ATOMIC); } -/* remove VLAN header from packet and update csum accrodingly. */ +/* remove VLAN header from packet and update csum accordingly. */ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) { struct vlan_hdr *vhdr; From 0273de08c455031335dbea2630208f66106b0c14 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Sep 2012 07:22:16 +1000 Subject: [PATCH 275/665] drm/ast: drop debug level on error printk This was never an error, drop to a debug print. Reported-by: Keven Lachance Signed-off-by: Dave Airlie --- drivers/gpu/drm/ast/ast_mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 7282c081fb53..a712cafcfa1d 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -841,7 +841,7 @@ int ast_cursor_init(struct drm_device *dev) ast->cursor_cache = obj; ast->cursor_cache_gpu_addr = gpu_addr; - DRM_ERROR("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); + DRM_DEBUG_KMS("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); return 0; fail: return ret; From c1f05264d834e9fb9a4ebfd36dbd86172ac7107a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 30 Aug 2012 11:06:18 +1000 Subject: [PATCH 276/665] drm/i915/edp: get the panel delay before powering up In order to setup the i2c channel, we power up the panel via ironlake_edp_panel_vdd_on, however it requires intel_dp->panel_power_up_delay to be initialised, which hasn't been setup yet. So move things around so we set the panel power up values first then init the i2c stuff. This is one step to fixing the eDP panel in the MBP from uninitialised state. Signed-off-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a6c426afaa7a..ace757af9133 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2533,14 +2533,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) break; } - intel_dp_i2c_init(intel_dp, intel_connector, name); - /* Cache some DPCD data in the eDP case */ if (is_edp(intel_dp)) { - bool ret; struct edp_power_seq cur, vbt; u32 pp_on, pp_off, pp_div; - struct edid *edid; pp_on = I915_READ(PCH_PP_ON_DELAYS); pp_off = I915_READ(PCH_PP_OFF_DELAYS); @@ -2591,6 +2587,13 @@ intel_dp_init(struct drm_device *dev, int output_reg) DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); + } + + intel_dp_i2c_init(intel_dp, intel_connector, name); + + if (is_edp(intel_dp)) { + bool ret; + struct edid *edid; ironlake_edp_panel_vdd_on(intel_dp); ret = intel_dp_get_dpcd(intel_dp); From fcbc50da7753b210b4442ca9abc4efbd4e481f6e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Aug 2012 14:08:42 +0300 Subject: [PATCH 277/665] drm/i915: only enable sdvo hotplug irq if needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid constant wakeups caused by noisy irq lines when we don't even care about the irq. This should be particularly useful for i945g/gm where the hotplug has been disabled: commit 768b107e4b3be0acf6f58e914afe4f337c00932b Author: Daniel Vetter Date: Fri May 4 11:29:56 2012 +0200 drm/i915: disable sdvo hotplug on i945g/gm v2: While at it, remove the bogus hotplug_active read, and do not mask hotplug_active[0] before checking whether the irq is needed, per discussion with Daniel on IRC. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=38442 Tested-by: Dominik Köppl Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d81bb0bf2885..123afd357611 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2573,7 +2573,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) hotplug_mask = intel_sdvo->is_sdvob ? SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; } - dev_priv->hotplug_supported_mask |= hotplug_mask; drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); @@ -2581,14 +2580,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) goto err; - /* Set up hotplug command - note paranoia about contents of reply. - * We assume that the hardware is in a sane state, and only touch - * the bits we think we understand. - */ - intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, - &intel_sdvo->hotplug_active, 2); - intel_sdvo->hotplug_active[0] &= ~0x3; - if (intel_sdvo_output_setup(intel_sdvo, intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", @@ -2596,6 +2587,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) goto err; } + /* Only enable the hotplug irq if we need it, to work around noisy + * hotplug lines. + */ + if (intel_sdvo->hotplug_active[0]) + dev_priv->hotplug_supported_mask |= hotplug_mask; + intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); /* Set the input timing to the screen. Assume always input 0. */ From 28e515878f8896b33c325ff9767cb0237210fb4c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Sep 2012 23:06:52 -0700 Subject: [PATCH 278/665] ARM: shmobile: armadillo800eva: enable rw rootfs mount armadillo800eva default boot loader is "hermit", and it's tag->u.core.flags has flag when kernel boots. Because of this, ${LINUX}/arch/arm/kernel/setup.c :: parse_tag_core() didn't remove MS_RDONLY flag from root_mountflags. Thus, the rootfs is mounted as "readonly". This patch adds "rw" kernel parameter, and enable read/write mounts for rootfs Cc: Masahiro Nakai Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/configs/armadillo800eva_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig index 7d8718468e0d..90610c7030f7 100644 --- a/arch/arm/configs/armadillo800eva_defconfig +++ b/arch/arm/configs/armadillo800eva_defconfig @@ -33,7 +33,7 @@ CONFIG_AEABI=y CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" +CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw" CONFIG_CMDLINE_FORCE=y CONFIG_KEXEC=y CONFIG_VFP=y From 381bf7cad9dbce701c618f8942fd35954952ef39 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 28 Aug 2012 10:38:03 +0200 Subject: [PATCH 279/665] fuse: mark variables uninitialized gcc 4.6.3 complains about uninitialized variables in fs/fuse/control.c: CC fs/fuse/control.o fs/fuse/control.c: In function 'fuse_conn_congestion_threshold_write': fs/fuse/control.c:165:29: warning: 'val' may be used uninitialized in this function [-Wuninitialized] fs/fuse/control.c: In function 'fuse_conn_max_background_write': fs/fuse/control.c:128:23: warning: 'val' may be used uninitialized in this function [-Wuninitialized] fuse_conn_limit_write() will always return non-zero unless the &val is modified, so the warning is misleading. Let the compiler know about it by marking 'val' with 'uninitialized_var'. Signed-off-by: Daniel Mack Cc: Brian Foster Signed-off-by: Miklos Szeredi --- fs/fuse/control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 03ff5b1eba93..75a20c092dd4 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -117,7 +117,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned val; + unsigned uninitialized_var(val); ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, @@ -154,7 +154,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned val; + unsigned uninitialized_var(val); ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, From e812347ccf9e8ce073b0ba0c49d03b124707b2b4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 2 Sep 2012 23:57:18 +0000 Subject: [PATCH 280/665] net: sock_edemux() should take care of timewait sockets sock_edemux() can handle either a regular socket or a timewait socket Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/sock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 8f67ced8d6a8..7f64467535d1 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1523,7 +1523,12 @@ EXPORT_SYMBOL(sock_rfree); void sock_edemux(struct sk_buff *skb) { - sock_put(skb->sk); + struct sock *sk = skb->sk; + + if (sk->sk_state == TCP_TIME_WAIT) + inet_twsk_put(inet_twsk(sk)); + else + sock_put(sk); } EXPORT_SYMBOL(sock_edemux); From 4c3a5bdae293f75cdf729c6c00124e8489af2276 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 3 Sep 2012 04:27:42 +0000 Subject: [PATCH 281/665] sctp: Don't charge for data in sndbuf again when transmitting packet SCTP charges wmem_alloc via sctp_set_owner_w() in sctp_sendmsg() and via skb_set_owner_w() in sctp_packet_transmit(). If a sender runs out of sndbuf it will sleep in sctp_wait_for_sndbuf() and expects to be waken up by __sctp_write_space(). Buffer space charged via sctp_set_owner_w() is released in sctp_wfree() which calls __sctp_write_space() directly. Buffer space charged via skb_set_owner_w() is released via sock_wfree() which calls sk->sk_write_space() _if_ SOCK_USE_WRITE_QUEUE is not set. sctp_endpoint_init() sets SOCK_USE_WRITE_QUEUE on all sockets. Therefore if sctp_packet_transmit() manages to queue up more than sndbuf bytes, sctp_wait_for_sndbuf() will never be woken up again unless it is interrupted by a signal. This could be fixed by clearing the SOCK_USE_WRITE_QUEUE flag but ... Charging for the data twice does not make sense in the first place, it leads to overcharging sndbuf by a factor 2. Therefore this patch only charges a single byte in wmem_alloc when transmitting an SCTP packet to ensure that the socket stays alive until the packet has been released. This means that control chunks are no longer accounted for in wmem_alloc which I believe is not a problem as skb->truesize will typically lead to overcharging anyway and thus compensates for any control overhead. Signed-off-by: Thomas Graf CC: Vlad Yasevich CC: Neil Horman CC: David Miller Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/output.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index 838e18b4d7ea..be50aa234dcd 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -364,6 +364,25 @@ finish: return retval; } +static void sctp_packet_release_owner(struct sk_buff *skb) +{ + sk_free(skb->sk); +} + +static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk) +{ + skb_orphan(skb); + skb->sk = sk; + skb->destructor = sctp_packet_release_owner; + + /* + * The data chunks have already been accounted for in sctp_sendmsg(), + * therefore only reserve a single byte to keep socket around until + * the packet has been transmitted. + */ + atomic_inc(&sk->sk_wmem_alloc); +} + /* All packets are sent to the network through this function from * sctp_outq_tail(). * @@ -405,7 +424,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) /* Set the owning socket so that we know where to get the * destination IP address. */ - skb_set_owner_w(nskb, sk); + sctp_packet_set_owner_w(nskb, sk); if (!sctp_transport_dst_check(tp)) { sctp_transport_route(tp, NULL, sctp_sk(sk)); From 85e87870fa18ec9f5df98e2d3b48f3699560a570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 2 Sep 2012 22:26:18 +0000 Subject: [PATCH 282/665] net: usbnet: fix softirq storm on suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suspending an open usbnet device results in constant rescheduling of usbnet_bh. commit 65841fd5 "usbnet: handle remote wakeup asap" refactored the usbnet_bh code to allow sharing the urb allocate and submit code with usbnet_resume. In this process, a test for, and immediate return on, ENOLINK from rx_submit was unintentionally dropped. The rx queue will not grow if rx_submit fails, making usbnet_bh reschedule itself. This results in a softirq storm if the error is persistent. rx_submit translates the usb_submit_urb error EHOSTUNREACH into ENOLINK, so this is an expected and persistent error for a suspended device. The old code tested for this condition and avoided rescheduling. Putting this test back. Cc: # v3.5 Cc: Ming Lei Cc: Oliver Neukum Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index fd4b26d46fd5..fc9f578a1e25 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1201,19 +1201,26 @@ deferred: } EXPORT_SYMBOL_GPL(usbnet_start_xmit); -static void rx_alloc_submit(struct usbnet *dev, gfp_t flags) +static int rx_alloc_submit(struct usbnet *dev, gfp_t flags) { struct urb *urb; int i; + int ret = 0; /* don't refill the queue all at once */ for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) { urb = usb_alloc_urb(0, flags); if (urb != NULL) { - if (rx_submit(dev, urb, flags) == -ENOLINK) - return; + ret = rx_submit(dev, urb, flags); + if (ret) + goto err; + } else { + ret = -ENOMEM; + goto err; } } +err: + return ret; } /*-------------------------------------------------------------------------*/ @@ -1257,7 +1264,8 @@ static void usbnet_bh (unsigned long param) int temp = dev->rxq.qlen; if (temp < RX_QLEN(dev)) { - rx_alloc_submit(dev, GFP_ATOMIC); + if (rx_alloc_submit(dev, GFP_ATOMIC) == -ENOLINK) + return; if (temp != dev->rxq.qlen) netif_dbg(dev, link, dev->net, "rxqlen %d --> %d\n", From 577650139062dcc20246da3f61e0bdafc65edf8f Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 3 Sep 2012 11:50:36 -0600 Subject: [PATCH 283/665] ARM: OMAP2+: am33xx: Fix the timer fck clock naming convention With commit ae6df418a21f3a361c5f9b878e32a8aba4e17692 Sub: ARM: OMAP2+: dmtimer: cleanup fclk usage) The Timer functional clock naming convention has changed from gptX_fck => timerXfck, and so as the timer init function in mach-omap2/timer.c. OMAP4 clocktree also has changed accordingly. AM33xx Clock Tree has been merged during rc3-4 timeframe, before above commit got merged, so similar change is required for AM33xx as well (Change the gptX_fck => timerX_fck). Signed-off-by: Vaibhav Hiremath Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock33xx_data.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c index 25bbcc7ca4dc..ae27de8899a6 100644 --- a/arch/arm/mach-omap2/clock33xx_data.c +++ b/arch/arm/mach-omap2/clock33xx_data.c @@ -1036,13 +1036,13 @@ static struct omap_clk am33xx_clks[] = { CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX), CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX), CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX), - CLK(NULL, "gpt1_fck", &timer1_fck, CK_AM33XX), - CLK(NULL, "gpt2_fck", &timer2_fck, CK_AM33XX), - CLK(NULL, "gpt3_fck", &timer3_fck, CK_AM33XX), - CLK(NULL, "gpt4_fck", &timer4_fck, CK_AM33XX), - CLK(NULL, "gpt5_fck", &timer5_fck, CK_AM33XX), - CLK(NULL, "gpt6_fck", &timer6_fck, CK_AM33XX), - CLK(NULL, "gpt7_fck", &timer7_fck, CK_AM33XX), + CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX), + CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX), + CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX), + CLK(NULL, "timer4_fck", &timer4_fck, CK_AM33XX), + CLK(NULL, "timer5_fck", &timer5_fck, CK_AM33XX), + CLK(NULL, "timer6_fck", &timer6_fck, CK_AM33XX), + CLK(NULL, "timer7_fck", &timer7_fck, CK_AM33XX), CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX), CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX), CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX), From bfb7dd25fcde96d08591258bc7e97500337a57ee Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 3 Sep 2012 11:50:43 -0600 Subject: [PATCH 284/665] ARM: OMAP3xxx: clockdomain: fix software supervised wakeup/sleep Commit 4da71ae6 ("OMAP: clockdomain: Arch specific funcs for clkdm_clk_enable/disable") called the OMAP2xxx-specific functions for clockdomain wakeup and sleep. This would probably have broken software-supervised clockdomain wakeup and sleep on OMAP3. Signed-off-by: Paul Walmsley Cc: Rajendra Nayak Cc: Jon Hunter Acked-by: Rajendra Nayak --- arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 50 +++++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index a0d68dbecfa3..f99e65cfb862 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -241,6 +241,52 @@ static void omap3_clkdm_deny_idle(struct clockdomain *clkdm) _clkdm_del_autodeps(clkdm); } +static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm) +{ + bool hwsup = false; + + if (!clkdm->clktrctrl_mask) + return 0; + + hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + + if (hwsup) { + /* Disable HW transitions when we are changing deps */ + _disable_hwsup(clkdm); + _clkdm_add_autodeps(clkdm); + _enable_hwsup(clkdm); + } else { + if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) + omap3_clkdm_wakeup(clkdm); + } + + return 0; +} + +static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm) +{ + bool hwsup = false; + + if (!clkdm->clktrctrl_mask) + return 0; + + hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + + if (hwsup) { + /* Disable HW transitions when we are changing deps */ + _disable_hwsup(clkdm); + _clkdm_del_autodeps(clkdm); + _enable_hwsup(clkdm); + } else { + if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP) + omap3_clkdm_sleep(clkdm); + } + + return 0; +} + struct clkdm_ops omap2_clkdm_operations = { .clkdm_add_wkdep = omap2_clkdm_add_wkdep, .clkdm_del_wkdep = omap2_clkdm_del_wkdep, @@ -267,6 +313,6 @@ struct clkdm_ops omap3_clkdm_operations = { .clkdm_wakeup = omap3_clkdm_wakeup, .clkdm_allow_idle = omap3_clkdm_allow_idle, .clkdm_deny_idle = omap3_clkdm_deny_idle, - .clkdm_clk_enable = omap2_clkdm_clk_enable, - .clkdm_clk_disable = omap2_clkdm_clk_disable, + .clkdm_clk_enable = omap3xxx_clkdm_clk_enable, + .clkdm_clk_disable = omap3xxx_clkdm_clk_disable, }; From ed733619d85262439f625cc9d8b00cdaae761070 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 3 Sep 2012 11:50:52 -0600 Subject: [PATCH 285/665] ARM: OMAP3: hwmod data: fix iva2 reset info IVA2 hwmod resets were missing the status bit offsets. Also, as the hwmod itself didn't have prcm info at all, resetting iva hwmod was accessing some bogus memory addresses. Added both infos to fix this. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cm-regbits-34xx.h | 1 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index 766338fe4d34..975f6bda0e0b 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -67,6 +67,7 @@ #define OMAP3430_EN_IVA2_DPLL_MASK (0x7 << 0) /* CM_IDLEST_IVA2 */ +#define OMAP3430_ST_IVA2_SHIFT 0 #define OMAP3430_ST_IVA2_MASK (1 << 0) /* CM_IDLEST_PLL_IVA2 */ diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index c9e38200216b..ce7e6068768f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -100,9 +100,9 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = { /* IVA2 (IVA2) */ static struct omap_hwmod_rst_info omap3xxx_iva_resets[] = { - { .name = "logic", .rst_shift = 0 }, - { .name = "seq0", .rst_shift = 1 }, - { .name = "seq1", .rst_shift = 2 }, + { .name = "logic", .rst_shift = 0, .st_shift = 8 }, + { .name = "seq0", .rst_shift = 1, .st_shift = 9 }, + { .name = "seq1", .rst_shift = 2, .st_shift = 10 }, }; static struct omap_hwmod omap3xxx_iva_hwmod = { @@ -112,6 +112,15 @@ static struct omap_hwmod omap3xxx_iva_hwmod = { .rst_lines = omap3xxx_iva_resets, .rst_lines_cnt = ARRAY_SIZE(omap3xxx_iva_resets), .main_clk = "iva2_ck", + .prcm = { + .omap2 = { + .module_offs = OMAP3430_IVA2_MOD, + .prcm_reg_id = 1, + .module_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430_ST_IVA2_SHIFT, + } + }, }; /* timer class */ From 471a009b6db7670299a8674cd7fb2557c8c2797f Mon Sep 17 00:00:00 2001 From: Misael Lopez Cruz Date: Mon, 3 Sep 2012 11:50:52 -0600 Subject: [PATCH 286/665] ARM: OMAP: hwmod code: Disable module when hwmod enable fails Clock and module mode are explictly enable when hwmod is enabled. But if the hwmod doesn't get ready on time, clocks are disabled but module is left enabled. Signed-off-by: Misael Lopez Cruz Signed-off-by: Rajendra Nayak Cc: Paul Walmsley Cc: Benoit Cousson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 6ca8e519968d..37afbd173c2c 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1889,6 +1889,7 @@ static int _enable(struct omap_hwmod *oh) _enable_sysc(oh); } } else { + _omap4_disable_module(oh); _disable_clocks(oh); pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", oh->name, r); From b360124ea008fcccf440840bde2c7f317bc31509 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 3 Sep 2012 11:50:53 -0600 Subject: [PATCH 287/665] ARM: OMAP4: hwmod data: temporarily comment out data for the sl2if IP block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OMAP4 sl2if IP block requires some special programming for it to enter idle. Without this programming, it will prevent the rest of the chip from entering full chip idle. This patch comments out the IP block data. Later, once the appropriate support is available, this patch can be reverted. Cc: Paul Walmsley Cc: Benoît Cousson Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 242aee498ceb..afb60917a948 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -4210,7 +4210,7 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = { }; /* dsp -> sl2if */ -static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = { +static struct omap_hwmod_ocp_if __maybe_unused omap44xx_dsp__sl2if = { .master = &omap44xx_dsp_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk = "dpll_iva_m5x2_ck", @@ -4828,7 +4828,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = { }; /* iva -> sl2if */ -static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = { +static struct omap_hwmod_ocp_if __maybe_unused omap44xx_iva__sl2if = { .master = &omap44xx_iva_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk = "dpll_iva_m5x2_ck", @@ -5362,7 +5362,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__scrm = { }; /* l3_main_2 -> sl2if */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = { +static struct omap_hwmod_ocp_if __maybe_unused omap44xx_l3_main_2__sl2if = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk = "l3_div_ck", @@ -6032,7 +6032,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_abe__dmic, &omap44xx_l4_abe__dmic_dma, &omap44xx_dsp__iva, - &omap44xx_dsp__sl2if, + /* &omap44xx_dsp__sl2if, */ &omap44xx_l4_cfg__dsp, &omap44xx_l3_main_2__dss, &omap44xx_l4_per__dss, @@ -6068,7 +6068,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_per__i2c4, &omap44xx_l3_main_2__ipu, &omap44xx_l3_main_2__iss, - &omap44xx_iva__sl2if, + /* &omap44xx_iva__sl2if, */ &omap44xx_l3_main_2__iva, &omap44xx_l4_wkup__kbd, &omap44xx_l4_cfg__mailbox, @@ -6099,7 +6099,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_cfg__cm_core, &omap44xx_l4_wkup__prm, &omap44xx_l4_wkup__scrm, - &omap44xx_l3_main_2__sl2if, + /* &omap44xx_l3_main_2__sl2if, */ &omap44xx_l4_abe__slimbus1, &omap44xx_l4_abe__slimbus1_dma, &omap44xx_l4_per__slimbus2, From cab32f39dcc5b35db96497dc0a026b5dea76e4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Locher?= Date: Mon, 27 Aug 2012 15:02:45 +0200 Subject: [PATCH 288/665] can: mcp251x: avoid repeated frame bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MCP2515 has a silicon bug causing repeated frame transmission, see section 5 of MCP2515 Rev. B Silicon Errata Revision G (March 2007). Basically, setting TXBnCTRL.TXREQ in either SPI mode (00 or 11) will eventually cause the bug. The workaround proposed by Microchip is to use mode 00 and send a RTS command on the SPI bus to initiate the transmission. Cc: Signed-off-by: Benoît Locher Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mcp251x.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index a580db29e503..26e7129332ab 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -83,6 +83,11 @@ #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) #define INSTRUCTION_RESET 0xC0 +#define RTS_TXB0 0x01 +#define RTS_TXB1 0x02 +#define RTS_TXB2 0x04 +#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) + /* MPC251x registers */ #define CANSTAT 0x0e @@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, int tx_buf_idx) { + struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u32 sid, eid, exide, rtr; u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); + + /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); + mcp251x_spi_trans(priv->spi, 1); } static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, From b379135c40163ae79ba7a54e6928b53983e74ee8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 1 Sep 2012 03:19:57 +0000 Subject: [PATCH 289/665] fq_codel: dont reinit flow state When fq_codel builds a new flow, it should not reset codel state. Codel algo needs to get previous values (lastcount, drop_next) to get proper behavior. Signed-off-by: Dave Taht Signed-off-by: Eric Dumazet Acked-by: Dave Taht Signed-off-by: David S. Miller --- net/sched/sch_fq_codel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 9fc1c62ec80e..4e606fcb2534 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -191,7 +191,6 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (list_empty(&flow->flowchain)) { list_add_tail(&flow->flowchain, &q->new_flows); - codel_vars_init(&flow->cvars); q->new_flow_count++; flow->deficit = q->quantum; flow->dropped = 0; @@ -418,6 +417,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) struct fq_codel_flow *flow = q->flows + i; INIT_LIST_HEAD(&flow->flowchain); + codel_vars_init(&flow->cvars); } } if (sch->limit >= 1) From 28dcc2d60cb570d9f549c329b2f51400553412a1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 3 Sep 2012 16:25:12 +0300 Subject: [PATCH 290/665] drm/i915: do not expose a dysfunctional backlight interface to userspace Previously intel_panel_setup_backlight() would create a sysfs backlight interface with max brightness of 1 if it was unable to figure out the max backlight brightness. This rendered the backlight interface useless. Do not create a dysfunctional backlight interface to begin with. Signed-off-by: Jani Nikula Tested-by: David Woodhouse Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 31 +++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 3df4f5fa892a..e019b2369861 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -162,19 +162,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) return val; } -u32 intel_panel_get_max_backlight(struct drm_device *dev) +static u32 _intel_panel_get_max_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 max; max = i915_read_blc_pwm_ctl(dev_priv); - if (max == 0) { - /* XXX add code here to query mode clock or hardware clock - * and program max PWM appropriately. - */ - pr_warn_once("fixme: max PWM is zero\n"); - return 1; - } if (HAS_PCH_SPLIT(dev)) { max >>= 16; @@ -188,6 +181,22 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev) max *= 0xff; } + return max; +} + +u32 intel_panel_get_max_backlight(struct drm_device *dev) +{ + u32 max; + + max = _intel_panel_get_max_backlight(dev); + if (max == 0) { + /* XXX add code here to query mode clock or hardware clock + * and program max PWM appropriately. + */ + pr_warn_once("fixme: max PWM is zero\n"); + return 1; + } + DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); return max; } @@ -424,7 +433,11 @@ int intel_panel_setup_backlight(struct drm_device *dev) memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; - props.max_brightness = intel_panel_get_max_backlight(dev); + props.max_brightness = _intel_panel_get_max_backlight(dev); + if (props.max_brightness == 0) { + DRM_ERROR("Failed to get maximum backlight value\n"); + return -ENODEV; + } dev_priv->backlight = backlight_device_register("intel_backlight", &connector->kdev, dev, From 9fef76857feed8e94ca3a5ee37db644f04a9488b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 3 Sep 2012 15:31:00 +0800 Subject: [PATCH 291/665] mISDN: fix possible memory leak in hfcmulti_init() hc has been allocated in this function and missing free it before leaving from some error handling cases. spatch with a semantic match is used to found this problem. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcmulti.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 5e402cf2e795..f02794203bb1 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -5059,6 +5059,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, printk(KERN_INFO "HFC-E1 #%d has overlapping B-channels on fragment #%d\n", E1_cnt + 1, pt); + kfree(hc); return -EINVAL; } maskcheck |= hc->bmask[pt]; @@ -5086,6 +5087,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, if ((poll >> 1) > sizeof(hc->silence_data)) { printk(KERN_ERR "HFCMULTI error: silence_data too small, " "please fix\n"); + kfree(hc); return -EINVAL; } for (i = 0; i < (poll >> 1); i++) From 156bddd8e505b295540f3ca0e27dda68cb0d49aa Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 3 Sep 2012 16:50:42 +0200 Subject: [PATCH 292/665] ext3: Fix fdatasync() for files with only i_size changes Code tracking when transaction needs to be committed on fdatasync(2) forgets to handle a situation when only inode's i_size is changed. Thus in such situations fdatasync(2) doesn't force transaction with new i_size to disk and that can result in wrong i_size after a crash. Fix the issue by updating inode's i_datasync_tid whenever its size is updated. CC: # >= 2.6.32 Reported-by: Kristian Nielsen Signed-off-by: Jan Kara --- fs/ext3/inode.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index a07597307fd1..ff574b4e345e 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3072,6 +3072,8 @@ static int ext3_do_update_inode(handle_t *handle, struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh = iloc->bh; int err = 0, rc, block; + int need_datasync = 0; + __le32 disksize; uid_t i_uid; gid_t i_gid; @@ -3113,7 +3115,11 @@ again: raw_inode->i_gid_high = 0; } raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); - raw_inode->i_size = cpu_to_le32(ei->i_disksize); + disksize = cpu_to_le32(ei->i_disksize); + if (disksize != raw_inode->i_size) { + need_datasync = 1; + raw_inode->i_size = disksize; + } raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); @@ -3129,8 +3135,11 @@ again: if (!S_ISREG(inode->i_mode)) { raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); } else { - raw_inode->i_size_high = - cpu_to_le32(ei->i_disksize >> 32); + disksize = cpu_to_le32(ei->i_disksize >> 32); + if (disksize != raw_inode->i_size_high) { + raw_inode->i_size_high = disksize; + need_datasync = 1; + } if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, @@ -3183,6 +3192,8 @@ again: ext3_clear_inode_state(inode, EXT3_STATE_NEW); atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); + if (need_datasync) + atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); out_brelse: brelse (bh); ext3_std_error(inode->i_sb, err); From c303aa94cdae483a7577230e61720e126e600a52 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Mon, 3 Sep 2012 19:06:27 -0700 Subject: [PATCH 293/665] openvswitch: Fix FLOW_BUFSIZE definition. The vlan encapsulation fields in the maximum flow defintion were never updated when the representation changed before upstreaming. In theory this could cause a kernel panic when a maximum length flow is used. In practice this has never happened (to my knowledge) because skb allocations are padded out to a cache line so you would need the right combination of flow and packet being sent to userspace. Signed-off-by: Jesse Gross --- net/openvswitch/flow.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 9b75617ca4e0..c30df1a10c67 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -145,15 +145,17 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); * OVS_KEY_ATTR_PRIORITY 4 -- 4 8 * OVS_KEY_ATTR_IN_PORT 4 -- 4 8 * OVS_KEY_ATTR_ETHERNET 12 -- 4 16 + * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype) * OVS_KEY_ATTR_8021Q 4 -- 4 8 - * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 + * OVS_KEY_ATTR_ENCAP 0 -- 4 4 (VLAN encapsulation) + * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (inner VLAN ethertype) * OVS_KEY_ATTR_IPV6 40 -- 4 44 * OVS_KEY_ATTR_ICMPV6 2 2 4 8 * OVS_KEY_ATTR_ND 28 -- 4 32 * ------------------------------------------------- - * total 132 + * total 144 */ -#define FLOW_BUFSIZE 132 +#define FLOW_BUFSIZE 144 int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, From 78b495c39add820ab66ab897af9bd77a5f2e91f6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 3 Sep 2012 17:12:29 +0300 Subject: [PATCH 294/665] UBI: fix a horrible memory deallocation bug UBI was mistakingly using 'kfree()' instead of 'kmem_cache_free()' when freeing "attach eraseblock" structures in vtbl.c. Thankfully, this happened only when we were doing auto-format, so many systems were unaffected. However, there are still many users affected. It is strange, but the system did not crash and nothing bad happened when the SLUB memory allocator was used. However, in case of SLOB we observed an crash right away. This problem was introduced in 2.6.39 by commit "6c1e875 UBI: add slab cache for ubi_scan_leb objects" A note for stable trees: Because variable were renamed, this won't cleanly apply to older kernels. Changing names like this should help: 1. ai -> si 2. aeb_slab_cache -> seb_slab_cache 3. new_aeb -> new_seb Reported-by: Richard Genoud Tested-by: Richard Genoud Tested-by: Artem Bityutskiy Cc: stable@vger.kernel.org [v2.6.39+] Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/vtbl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 437bc193e170..568307cc7caf 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -340,7 +340,7 @@ retry: * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'. */ err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0); - kfree(new_aeb); + kmem_cache_free(ai->aeb_slab_cache, new_aeb); ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -353,7 +353,7 @@ write_error: list_add(&new_aeb->u.list, &ai->erase); goto retry; } - kfree(new_aeb); + kmem_cache_free(ai->aeb_slab_cache, new_aeb); out_free: ubi_free_vid_hdr(ubi, vid_hdr); return err; From f319da0c6894fcf55e21320e40506418a2aad629 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 20 Aug 2012 11:26:57 +0200 Subject: [PATCH 295/665] sched: Fix load avg vs cpu-hotplug Rabik and Paul reported two different issues related to the same few lines of code. Rabik's issue is that the nr_uninterruptible migration code is wrong in that he sees artifacts due to this (Rabik please do expand in more detail). Paul's issue is that this code as it stands relies on us using stop_machine() for unplug, we all would like to remove this assumption so that eventually we can remove this stop_machine() usage altogether. The only reason we'd have to migrate nr_uninterruptible is so that we could use for_each_online_cpu() loops in favour of for_each_possible_cpu() loops, however since nr_uninterruptible() is the only such loop and its using possible lets not bother at all. The problem Rabik sees is (probably) caused by the fact that by migrating nr_uninterruptible we screw rq->calc_load_active for both rqs involved. So don't bother with fancy migration schemes (meaning we now have to keep using for_each_possible_cpu()) and instead fold any nr_active delta after we migrate all tasks away to make sure we don't have any skewed nr_active accounting. Reported-by: Rakib Mullick Reported-by: Paul E. McKenney Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1345454817.23018.27.camel@twins Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index fbf1fd098dc6..207a81c769d4 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5304,27 +5304,17 @@ void idle_task_exit(void) } /* - * While a dead CPU has no uninterruptible tasks queued at this point, - * it might still have a nonzero ->nr_uninterruptible counter, because - * for performance reasons the counter is not stricly tracking tasks to - * their home CPUs. So we just add the counter to another CPU's counter, - * to keep the global sum constant after CPU-down: + * Since this CPU is going 'away' for a while, fold any nr_active delta + * we might have. Assumes we're called after migrate_tasks() so that the + * nr_active count is stable. + * + * Also see the comment "Global load-average calculations". */ -static void migrate_nr_uninterruptible(struct rq *rq_src) +static void calc_load_migrate(struct rq *rq) { - struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask)); - - rq_dest->nr_uninterruptible += rq_src->nr_uninterruptible; - rq_src->nr_uninterruptible = 0; -} - -/* - * remove the tasks which were accounted by rq from calc_load_tasks. - */ -static void calc_global_load_remove(struct rq *rq) -{ - atomic_long_sub(rq->calc_load_active, &calc_load_tasks); - rq->calc_load_active = 0; + long delta = calc_load_fold_active(rq); + if (delta) + atomic_long_add(delta, &calc_load_tasks); } /* @@ -5618,8 +5608,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) BUG_ON(rq->nr_running != 1); /* the migration thread */ raw_spin_unlock_irqrestore(&rq->lock, flags); - migrate_nr_uninterruptible(rq); - calc_global_load_remove(rq); + calc_load_migrate(rq); break; #endif } From 749c8814f08f12baa4a9c2812a7c6ede7d69507d Mon Sep 17 00:00:00 2001 From: Charles Wang Date: Mon, 20 Aug 2012 16:02:33 +0800 Subject: [PATCH 296/665] sched: Add missing call to calc_load_exit_idle() Azat Khuzhin reported high loadavg in Linux v3.6 After checking the upstream scheduler code, I found Peter's commit: 5167e8d5417b sched/nohz: Rewrite and fix load-avg computation -- again not fully applied, missing the call to calc_load_exit_idle(). After that idle exit in sampling window will always be calculated to non-idle, and the load will be higher than normal. This patch adds the missing call to calc_load_exit_idle(). Signed-off-by: Charles Wang Cc: stable@kernel.org Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1345449754-27130-1-git-send-email-muming.wq@gmail.com Signed-off-by: Ingo Molnar --- kernel/time/tick-sched.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 024540f97f74..3a9e5d5c1091 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -573,6 +573,7 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now) tick_do_update_jiffies64(now); update_cpu_load_nohz(); + calc_load_exit_idle(); touch_softlockup_watchdog(); /* * Cancel the scheduled timer and restore the tick From a4c96ae319b8047f62dedbe1eac79e321c185749 Mon Sep 17 00:00:00 2001 From: Peter Boonstoppel Date: Thu, 9 Aug 2012 15:34:47 -0700 Subject: [PATCH 297/665] sched: Unthrottle rt runqueues in __disable_runtime() migrate_tasks() uses _pick_next_task_rt() to get tasks from the real-time runqueues to be migrated. When rt_rq is throttled _pick_next_task_rt() won't return anything, in which case migrate_tasks() can't move all threads over and gets stuck in an infinite loop. Instead unthrottle rt runqueues before migrating tasks. Additionally: move unthrottle_offline_cfs_rqs() to rq_offline_fair() Signed-off-by: Peter Boonstoppel Signed-off-by: Peter Zijlstra Cc: Paul Turner Link: http://lkml.kernel.org/r/5FBF8E85CA34454794F0F7ECBA79798F379D3648B7@HQMAIL04.nvidia.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 3 --- kernel/sched/fair.c | 7 +++++-- kernel/sched/rt.c | 1 + kernel/sched/sched.h | 1 - 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 207a81c769d4..a4ea245f3d85 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5342,9 +5342,6 @@ static void migrate_tasks(unsigned int dead_cpu) */ rq->stop = NULL; - /* Ensure any throttled groups are reachable by pick_next_task */ - unthrottle_offline_cfs_rqs(rq); - for ( ; ; ) { /* * There's this thread running, bail when that's the only diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index c219bf8d704c..86ad83c45dae 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2052,7 +2052,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) hrtimer_cancel(&cfs_b->slack_timer); } -void unthrottle_offline_cfs_rqs(struct rq *rq) +static void unthrottle_offline_cfs_rqs(struct rq *rq) { struct cfs_rq *cfs_rq; @@ -2106,7 +2106,7 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg) return NULL; } static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} -void unthrottle_offline_cfs_rqs(struct rq *rq) {} +static inline void unthrottle_offline_cfs_rqs(struct rq *rq) {} #endif /* CONFIG_CFS_BANDWIDTH */ @@ -4956,6 +4956,9 @@ static void rq_online_fair(struct rq *rq) static void rq_offline_fair(struct rq *rq) { update_sysctl(); + + /* Ensure any throttled groups are reachable by pick_next_task */ + unthrottle_offline_cfs_rqs(rq); } #endif /* CONFIG_SMP */ diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 944cb68420e9..e0b7ba9c040f 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -691,6 +691,7 @@ balanced: * runtime - in which case borrowing doesn't make sense. */ rt_rq->rt_runtime = RUNTIME_INF; + rt_rq->rt_throttled = 0; raw_spin_unlock(&rt_rq->rt_runtime_lock); raw_spin_unlock(&rt_b->rt_runtime_lock); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index f6714d009e77..0848fa36c383 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1144,7 +1144,6 @@ extern void print_rt_stats(struct seq_file *m, int cpu); extern void init_cfs_rq(struct cfs_rq *cfs_rq); extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq); -extern void unthrottle_offline_cfs_rqs(struct rq *rq); extern void account_cfs_bandwidth_used(int enabled, int was_enabled); From 9450d57eab5cad36774c297da123062744472588 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Aug 2012 17:45:08 -0700 Subject: [PATCH 298/665] sched: Fix kernel-doc warnings in kernel/sched/fair.c Fix two kernel-doc warnings in kernel/sched/fair.c: Warning(kernel/sched/fair.c:3660): Excess function parameter 'cpus' description in 'update_sg_lb_stats' Warning(kernel/sched/fair.c:3806): Excess function parameter 'cpus' description in 'update_sd_lb_stats' Signed-off-by: Randy Dunlap Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/50303714.3090204@xenotime.net Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 86ad83c45dae..42d9df6a5ca4 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3658,7 +3658,6 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group) * @group: sched_group whose statistics are to be updated. * @load_idx: Load index of sched_domain of this_cpu for load calc. * @local_group: Does group contain this_cpu. - * @cpus: Set of cpus considered for load balancing. * @balance: Should we balance. * @sgs: variable to hold the statistics for this group. */ @@ -3805,7 +3804,6 @@ static bool update_sd_pick_busiest(struct lb_env *env, /** * update_sd_lb_stats - Update sched_domain's statistics for load balancing. * @env: The load balancing environment. - * @cpus: Set of cpus considered for load balancing. * @balance: Should we balance. * @sds: variable to hold the statistics for this sched_domain. */ From 749c59fd15b2c18dd6c15c353a899fb6ac49b865 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Thu, 30 Aug 2012 11:32:13 +0100 Subject: [PATCH 299/665] KVM: PIC: fix use of uninitialised variable. Commit aea218f3cbbc (KVM: PIC: call ack notifiers for irqs that are dropped form irr) used an uninitialised variable to track whether an appropriate apic had been found. This could result in calling the ack notifier incorrectly. Cc: Gleb Natapov Cc: Avi Kivity Signed-off-by: Jamie Iles Signed-off-by: Avi Kivity --- arch/x86/kvm/i8259.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index e498b18f010c..9fc9aa7ac703 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -318,7 +318,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val) if (val & 0x10) { u8 edge_irr = s->irr & ~s->elcr; int i; - bool found; + bool found = false; struct kvm_vcpu *vcpu; s->init4 = val & 1; From 3d2abdfdf14f4d6decc2023708211e19b096f4ca Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 4 Sep 2012 17:44:45 +0300 Subject: [PATCH 300/665] mac80211: clear bssid on auth/assoc failure ifmgd->bssid wasn't cleared properly in some auth/assoc failure cases, causing mac80211 and the low-level driver to go out of sync. Clear ifmgd->bssid on failure, and notify the driver. Cc: stable@kernel.org # 3.4+ Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a4a5acdbaa4d..f76b83341cf9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3248,6 +3248,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, goto out_unlock; err_clear: + memset(ifmgd->bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->auth_data = NULL; err_free: kfree(auth_data); @@ -3439,6 +3441,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, err = 0; goto out; err_clear: + memset(ifmgd->bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->assoc_data = NULL; err_free: kfree(assoc_data); From a6fa941d94b411bbd2b6421ffbde6db3c93e65ab Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Aug 2012 14:59:25 +0100 Subject: [PATCH 301/665] perf_event: Switch to internal refcount, fix race with close() Don't mess with file refcounts (or keep a reference to file, for that matter) in perf_event. Use explicit refcount of its own instead. Deal with the race between the final reference to event going away and new children getting created for it by use of atomic_long_inc_not_zero() in inherit_event(); just have the latter free what it had allocated and return NULL, that works out just fine (children of siblings of something doomed are created as singletons, same as if the child of leader had been created and immediately killed). Signed-off-by: Al Viro Cc: stable@kernel.org Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120820135925.GG23464@ZenIV.linux.org.uk Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 2 +- kernel/events/core.c | 62 ++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 7602ccb3f40e..ad04dfcd6f35 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -926,7 +926,7 @@ struct perf_event { struct hw_perf_event hw; struct perf_event_context *ctx; - struct file *filp; + atomic_long_t refcount; /* * These accumulate total time (in nanoseconds) that children diff --git a/kernel/events/core.c b/kernel/events/core.c index b7935fcec7d9..efef4282b8e8 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2935,12 +2935,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel); /* * Called when the last reference to the file is gone. */ -static int perf_release(struct inode *inode, struct file *file) +static void put_event(struct perf_event *event) { - struct perf_event *event = file->private_data; struct task_struct *owner; - file->private_data = NULL; + if (!atomic_long_dec_and_test(&event->refcount)) + return; rcu_read_lock(); owner = ACCESS_ONCE(event->owner); @@ -2975,7 +2975,13 @@ static int perf_release(struct inode *inode, struct file *file) put_task_struct(owner); } - return perf_event_release_kernel(event); + perf_event_release_kernel(event); +} + +static int perf_release(struct inode *inode, struct file *file) +{ + put_event(file->private_data); + return 0; } u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) @@ -3227,7 +3233,7 @@ unlock: static const struct file_operations perf_fops; -static struct perf_event *perf_fget_light(int fd, int *fput_needed) +static struct file *perf_fget_light(int fd, int *fput_needed) { struct file *file; @@ -3241,7 +3247,7 @@ static struct perf_event *perf_fget_light(int fd, int *fput_needed) return ERR_PTR(-EBADF); } - return file->private_data; + return file; } static int perf_event_set_output(struct perf_event *event, @@ -3273,19 +3279,21 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PERF_EVENT_IOC_SET_OUTPUT: { + struct file *output_file = NULL; struct perf_event *output_event = NULL; int fput_needed = 0; int ret; if (arg != -1) { - output_event = perf_fget_light(arg, &fput_needed); - if (IS_ERR(output_event)) - return PTR_ERR(output_event); + output_file = perf_fget_light(arg, &fput_needed); + if (IS_ERR(output_file)) + return PTR_ERR(output_file); + output_event = output_file->private_data; } ret = perf_event_set_output(event, output_event); if (output_event) - fput_light(output_event->filp, fput_needed); + fput_light(output_file, fput_needed); return ret; } @@ -5950,6 +5958,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, mutex_init(&event->mmap_mutex); + atomic_long_set(&event->refcount, 1); event->cpu = cpu; event->attr = *attr; event->group_leader = group_leader; @@ -6260,12 +6269,12 @@ SYSCALL_DEFINE5(perf_event_open, return event_fd; if (group_fd != -1) { - group_leader = perf_fget_light(group_fd, &fput_needed); - if (IS_ERR(group_leader)) { - err = PTR_ERR(group_leader); + group_file = perf_fget_light(group_fd, &fput_needed); + if (IS_ERR(group_file)) { + err = PTR_ERR(group_file); goto err_fd; } - group_file = group_leader->filp; + group_leader = group_file->private_data; if (flags & PERF_FLAG_FD_OUTPUT) output_event = group_leader; if (flags & PERF_FLAG_FD_NO_GROUP) @@ -6402,7 +6411,6 @@ SYSCALL_DEFINE5(perf_event_open, put_ctx(gctx); } - event->filp = event_file; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); @@ -6496,7 +6504,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, goto err_free; } - event->filp = NULL; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); perf_install_in_context(ctx, event, cpu); @@ -6578,7 +6585,7 @@ static void sync_child_event(struct perf_event *child_event, * Release the parent event, if this was the last * reference to it. */ - fput(parent_event->filp); + put_event(parent_event); } static void @@ -6654,9 +6661,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) * * __perf_event_exit_task() * sync_child_event() - * fput(parent_event->filp) - * perf_release() - * mutex_lock(&ctx->mutex) + * put_event() + * mutex_lock(&ctx->mutex) * * But since its the parent context it won't be the same instance. */ @@ -6724,7 +6730,7 @@ static void perf_free_event(struct perf_event *event, list_del_init(&event->child_list); mutex_unlock(&parent->child_mutex); - fput(parent->filp); + put_event(parent); perf_group_detach(event); list_del_event(event, ctx); @@ -6804,6 +6810,12 @@ inherit_event(struct perf_event *parent_event, NULL, NULL); if (IS_ERR(child_event)) return child_event; + + if (!atomic_long_inc_not_zero(&parent_event->refcount)) { + free_event(child_event); + return NULL; + } + get_ctx(child_ctx); /* @@ -6844,14 +6856,6 @@ inherit_event(struct perf_event *parent_event, add_event_to_ctx(child_event, child_ctx); raw_spin_unlock_irqrestore(&child_ctx->lock, flags); - /* - * Get a reference to the parent filp - we will fput it - * when the child event exits. This is safe to do because - * we are in the parent and we know that the filp still - * exists and has a nonzero count: - */ - atomic_long_inc(&parent_event->filp->f_count); - /* * Link this into the parent event's child list */ From 3ec18cd8b8f8395d0df604c62ab3bc2cf3a966b4 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 20 Aug 2012 11:24:21 +0200 Subject: [PATCH 302/665] perf/x86: Enable Intel Cedarview Atom suppport This patch enables perf_events support for Intel Cedarview Atom (model 54) processors. Support includes PEBS and LBR. Tested on my Atom N2600 netbook. Signed-off-by: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120820092421.GA11284@quad Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel.c | 1 + arch/x86/kernel/cpu/perf_event_intel_lbr.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 7f2739e03e79..0d3d63afa76a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -2008,6 +2008,7 @@ __init int intel_pmu_init(void) break; case 28: /* Atom */ + case 54: /* Cedariew */ memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, sizeof(hw_cache_event_ids)); diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index 520b4265fcd2..da02e9cc3754 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -686,7 +686,8 @@ void intel_pmu_lbr_init_atom(void) * to have an operational LBR which can freeze * on PMU interrupt */ - if (boot_cpu_data.x86_mask < 10) { + if (boot_cpu_data.x86_model == 28 + && boot_cpu_data.x86_mask < 10) { pr_cont("LBR disabled due to erratum"); return; } From 500ad2d8b01390c98bc6dce068bccfa9534b8212 Mon Sep 17 00:00:00 2001 From: "K.Prasad" Date: Thu, 2 Aug 2012 13:46:35 +0530 Subject: [PATCH 303/665] perf/hwpb: Invoke __perf_event_disable() if interrupts are already disabled While debugging a warning message on PowerPC while using hardware breakpoints, it was discovered that when perf_event_disable is invoked through hw_breakpoint_handler function with interrupts disabled, a subsequent IPI in the code path would trigger a WARN_ON_ONCE message in smp_call_function_single function. This patch calls __perf_event_disable() when interrupts are already disabled, instead of perf_event_disable(). Reported-by: Edjunior Barbosa Machado Signed-off-by: K.Prasad [naveen.n.rao@linux.vnet.ibm.com: v3: Check to make sure we target current task] Signed-off-by: Naveen N. Rao Acked-by: Frederic Weisbecker Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120802081635.5811.17737.stgit@localhost.localdomain [ Fixed build error on MIPS. ] Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 2 ++ kernel/events/core.c | 2 +- kernel/events/hw_breakpoint.c | 11 ++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index ad04dfcd6f35..33ed9d605f91 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1296,6 +1296,7 @@ extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); extern void perf_event_enable(struct perf_event *event); extern void perf_event_disable(struct perf_event *event); +extern int __perf_event_disable(void *info); extern void perf_event_task_tick(void); #else static inline void @@ -1334,6 +1335,7 @@ static inline int perf_swevent_get_recursion_context(void) { return -1; } static inline void perf_swevent_put_recursion_context(int rctx) { } static inline void perf_event_enable(struct perf_event *event) { } static inline void perf_event_disable(struct perf_event *event) { } +static inline int __perf_event_disable(void *info) { return -1; } static inline void perf_event_task_tick(void) { } #endif diff --git a/kernel/events/core.c b/kernel/events/core.c index efef4282b8e8..7fee567153f0 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1253,7 +1253,7 @@ retry: /* * Cross CPU call to disable a performance event */ -static int __perf_event_disable(void *info) +int __perf_event_disable(void *info) { struct perf_event *event = info; struct perf_event_context *ctx = event->ctx; diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c index bb38c4d3ee12..9a7b487c6fe2 100644 --- a/kernel/events/hw_breakpoint.c +++ b/kernel/events/hw_breakpoint.c @@ -453,7 +453,16 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att int old_type = bp->attr.bp_type; int err = 0; - perf_event_disable(bp); + /* + * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it + * will not be possible to raise IPIs that invoke __perf_event_disable. + * So call the function directly after making sure we are targeting the + * current task. + */ + if (irqs_disabled() && bp->ctx && bp->ctx->task == current) + __perf_event_disable(bp); + else + perf_event_disable(bp); bp->attr.bp_addr = attr->bp_addr; bp->attr.bp_type = attr->bp_type; From b4e4f47e940bc93c5b1125a4429ff53956754800 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 2 Sep 2012 21:41:04 +0800 Subject: [PATCH 304/665] nl80211: fix possible memory leak nl80211_connect() connkeys is malloced in nl80211_parse_connkeys() and should be freed in the error handling case, otherwise it will cause memory leak. spatch with a semantic match is used to found this problem. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 97026f3b215a..1e37dbf00cb3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5633,8 +5633,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) sizeof(connect.ht_capa_mask)); if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { - if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) + if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) { + kfree(connkeys); return -EINVAL; + } memcpy(&connect.ht_capa, nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]), sizeof(connect.ht_capa)); From c9e67d483776d8d2a5f3f70491161b205930ffe1 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 4 Sep 2012 18:45:54 +0200 Subject: [PATCH 305/665] fuse: fix retrieve length In some cases fuse_retrieve() would return a short byte count if offset was non-zero. The data returned was correct, though. Signed-off-by: Miklos Szeredi Cc: stable@vger.kernel.org --- fs/fuse/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 7df2b5e8fbe1..f4246cfc8d87 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1576,6 +1576,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, req->pages[req->num_pages] = page; req->num_pages++; + offset = 0; num -= this_num; total_len += this_num; index++; From 6cf5c951175abcec4da470c50565cc0afe6cd11d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 04:13:18 +0000 Subject: [PATCH 306/665] netrom: copy_datagram_iovec can fail Check for an error from this and if so bail properly. Signed-off-by: Alan Cox Signed-off-by: David S. Miller --- net/netrom/af_netrom.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 06592d8b4a2b..1b9024ee963c 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1169,7 +1169,12 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_flags |= MSG_TRUNC; } - skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (er < 0) { + skb_free_datagram(sk, skb); + release_sock(sk); + return er; + } if (sax != NULL) { sax->sax25_family = AF_NETROM; From 660d9a9c4f623eeec80cec3705ae872bd5cb556d Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 30 Jul 2012 15:03:02 +0800 Subject: [PATCH 307/665] mmc: bfin_sdh: fix dma_desc_array build error Descriptor array structure has been moved into blackfin dma.h head file. This patch fix below error: drivers/mmc/host/bfin_sdh.c:52:8: error: redefinition of 'struct dma_desc_array' make[4]: *** [drivers/mmc/host/bfin_sdh.o] Error 1 Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu Signed-off-by: Chris Ball --- drivers/mmc/host/bfin_sdh.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 03666174ca48..a17dd7363ceb 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c @@ -49,13 +49,6 @@ #define bfin_write_SDH_CFG bfin_write_RSI_CFG #endif -struct dma_desc_array { - unsigned long start_addr; - unsigned short cfg; - unsigned short x_count; - short x_modify; -} __packed; - struct sdh_host { struct mmc_host *mmc; spinlock_t lock; From 1af36b2a993dddfa3d6860ec4879c9e8abc9b976 Mon Sep 17 00:00:00 2001 From: Lauri Hintsala Date: Tue, 17 Jul 2012 17:16:09 +0300 Subject: [PATCH 308/665] mmc: mxs-mmc: fix deadlock in SDIO IRQ case Release the lock before mmc_signal_sdio_irq is called by mxs_mmc_irq_handler. Backtrace: [ 79.660000] ============================================= [ 79.660000] [ INFO: possible recursive locking detected ] [ 79.660000] 3.4.0-00009-g3e96082-dirty #11 Not tainted [ 79.660000] --------------------------------------------- [ 79.660000] swapper/0 is trying to acquire lock: [ 79.660000] (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xd4 [ 79.660000] [ 79.660000] but task is already holding lock: [ 79.660000] (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_irq_handler+0x1c/0xe8 [ 79.660000] [ 79.660000] other info that might help us debug this: [ 79.660000] Possible unsafe locking scenario: [ 79.660000] [ 79.660000] CPU0 [ 79.660000] ---- [ 79.660000] lock(&(&host->lock)->rlock#2); [ 79.660000] lock(&(&host->lock)->rlock#2); [ 79.660000] [ 79.660000] *** DEADLOCK *** [ 79.660000] [ 79.660000] May be due to missing lock nesting notation [ 79.660000] [ 79.660000] 1 lock held by swapper/0: [ 79.660000] #0: (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_irq_handler+0x1c/0xe8 [ 79.660000] [ 79.660000] stack backtrace: [ 79.660000] [] (unwind_backtrace+0x0/0xf4) from [] (__lock_acquire+0x1948/0x1d48) [ 79.660000] [] (__lock_acquire+0x1948/0x1d48) from [] (lock_acquire+0xe0/0xf8) [ 79.660000] [] (lock_acquire+0xe0/0xf8) from [] (_raw_spin_lock_irqsave+0x44/0x58) [ 79.660000] [] (_raw_spin_lock_irqsave+0x44/0x58) from [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) [ 79.660000] [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) from [] (mxs_mmc_irq_handler+0xd4/0xe8) [ 79.660000] [] (mxs_mmc_irq_handler+0xd4/0xe8) from [] (handle_irq_event_percpu+0x70/0x254) [ 79.660000] [] (handle_irq_event_percpu+0x70/0x254) from [] (handle_irq_event+0x3c/0x5c) [ 79.660000] [] (handle_irq_event+0x3c/0x5c) from [] (handle_level_irq+0x90/0x110) [ 79.660000] [] (handle_level_irq+0x90/0x110) from [] (generic_handle_irq+0x38/0x50) [ 79.660000] [] (generic_handle_irq+0x38/0x50) from [] (handle_IRQ+0x30/0x84) [ 79.660000] [] (handle_IRQ+0x30/0x84) from [] (__irq_svc+0x38/0x60) [ 79.660000] [] (__irq_svc+0x38/0x60) from [] (default_idle+0x2c/0x40) [ 79.660000] [] (default_idle+0x2c/0x40) from [] (cpu_idle+0x64/0xcc) [ 79.660000] [] (cpu_idle+0x64/0xcc) from [] (start_kernel+0x244/0x2c8) [ 79.660000] BUG: spinlock lockup on CPU#0, swapper/0 [ 79.660000] lock: c398cb2c, .magic: dead4ead, .owner: swapper/0, .owner_cpu: 0 [ 79.660000] [] (unwind_backtrace+0x0/0xf4) from [] (do_raw_spin_lock+0xf0/0x144) [ 79.660000] [] (do_raw_spin_lock+0xf0/0x144) from [] (_raw_spin_lock_irqsave+0x4c/0x58) [ 79.660000] [] (_raw_spin_lock_irqsave+0x4c/0x58) from [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) [ 79.660000] [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) from [] (mxs_mmc_irq_handler+0xd4/0xe8) [ 79.660000] [] (mxs_mmc_irq_handler+0xd4/0xe8) from [] (handle_irq_event_percpu+0x70/0x254) [ 79.660000] [] (handle_irq_event_percpu+0x70/0x254) from [] (handle_irq_event+0x3c/0x5c) [ 79.660000] [] (handle_irq_event+0x3c/0x5c) from [] (handle_level_irq+0x90/0x110) [ 79.660000] [] (handle_level_irq+0x90/0x110) from [] (generic_handle_irq+0x38/0x50) [ 79.660000] [] (generic_handle_irq+0x38/0x50) from [] (handle_IRQ+0x30/0x84) [ 79.660000] [] (handle_IRQ+0x30/0x84) from [] (__irq_svc+0x38/0x60) [ 79.660000] [] (__irq_svc+0x38/0x60) from [] (default_idle+0x2c/0x40) [ 79.660000] [] (default_idle+0x2c/0x40) from [] (cpu_idle+0x64/0xcc) [ 79.660000] [] (cpu_idle+0x64/0xcc) from [] (start_kernel+0x244/0x2c8) Signed-off-by: Lauri Hintsala Acked-by: Shawn Guo Cc: stable Signed-off-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index a51f9309ffbb..e62e58e5053d 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -285,11 +285,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) writel(stat & MXS_MMC_IRQ_BITS, host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); + spin_unlock(&host->lock); + if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) mmc_signal_sdio_irq(host->mmc); - spin_unlock(&host->lock); - if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) cmd->error = -ETIMEDOUT; else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) From fc108d24d3a6da63576a460e122fa1df0cbdea20 Mon Sep 17 00:00:00 2001 From: Lauri Hintsala Date: Tue, 17 Jul 2012 17:16:10 +0300 Subject: [PATCH 309/665] mmc: mxs-mmc: fix deadlock caused by recursion loop Release the lock before mmc_signal_sdio_irq is called by mxs_mmc_enable_sdio_irq. Backtrace: [ 65.470000] ============================================= [ 65.470000] [ INFO: possible recursive locking detected ] [ 65.470000] 3.5.0-rc5 #2 Not tainted [ 65.470000] --------------------------------------------- [ 65.470000] ksdioirqd/mmc0/73 is trying to acquire lock: [ 65.470000] (&(&host->lock)->rlock#2){-.-...}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc] [ 65.470000] [ 65.470000] but task is already holding lock: [ 65.470000] (&(&host->lock)->rlock#2){-.-...}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc] [ 65.470000] [ 65.470000] other info that might help us debug this: [ 65.470000] Possible unsafe locking scenario: [ 65.470000] [ 65.470000] CPU0 [ 65.470000] ---- [ 65.470000] lock(&(&host->lock)->rlock#2); [ 65.470000] lock(&(&host->lock)->rlock#2); [ 65.470000] [ 65.470000] *** DEADLOCK *** [ 65.470000] [ 65.470000] May be due to missing lock nesting notation [ 65.470000] [ 65.470000] 1 lock held by ksdioirqd/mmc0/73: [ 65.470000] #0: (&(&host->lock)->rlock#2){-.-...}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc] [ 65.470000] [ 65.470000] stack backtrace: [ 65.470000] [] (unwind_backtrace+0x0/0xf4) from [] (__lock_acquire+0x14f8/0x1b98) [ 65.470000] [] (__lock_acquire+0x14f8/0x1b98) from [] (lock_acquire+0xa0/0x108) [ 65.470000] [] (lock_acquire+0xa0/0x108) from [] (_raw_spin_lock_irqsave+0x48/0x5c) [ 65.470000] [] (_raw_spin_lock_irqsave+0x48/0x5c) from [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) from [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) from [] (sdio_irq_thread+0x1bc/0x274) [ 65.470000] [] (sdio_irq_thread+0x1bc/0x274) from [] (kthread+0x8c/0x98) [ 65.470000] [] (kthread+0x8c/0x98) from [] (kernel_thread_exit+0x0/0x8) [ 65.470000] BUG: spinlock lockup suspected on CPU#0, ksdioirqd/mmc0/73 [ 65.470000] lock: 0xc3358724, .magic: dead4ead, .owner: ksdioirqd/mmc0/73, .owner_cpu: 0 [ 65.470000] [] (unwind_backtrace+0x0/0xf4) from [] (do_raw_spin_lock+0x100/0x144) [ 65.470000] [] (do_raw_spin_lock+0x100/0x144) from [] (_raw_spin_lock_irqsave+0x50/0x5c) [ 65.470000] [] (_raw_spin_lock_irqsave+0x50/0x5c) from [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) from [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) from [] (sdio_irq_thread+0x1bc/0x274) [ 65.470000] [] (sdio_irq_thread+0x1bc/0x274) from [] (kthread+0x8c/0x98) [ 65.470000] [] (kthread+0x8c/0x98) from [] (kernel_thread_exit+0x0/0x8) Reported-by: Attila Kinali Signed-off-by: Lauri Hintsala Acked-by: Shawn Guo Cc: stable Signed-off-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index e62e58e5053d..ad3fcea1269e 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -644,11 +644,6 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL1_SDIO_IRQ_EN, host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); - - if (readl(host->base + HW_SSP_STATUS(host)) & - BM_SSP_STATUS_SDIO_IRQ) - mmc_signal_sdio_irq(host->mmc); - } else { writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); @@ -657,6 +652,11 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) } spin_unlock_irqrestore(&host->lock, flags); + + if (enable && readl(host->base + HW_SSP_STATUS(host)) & + BM_SSP_STATUS_SDIO_IRQ) + mmc_signal_sdio_irq(host->mmc); + } static const struct mmc_host_ops mxs_mmc_ops = { From 74f330bceaa7b88d06062e1cac3d519a3dfc041e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 22 Aug 2012 23:10:01 +0800 Subject: [PATCH 310/665] mmc: sdhci-esdhc: break out early if clock is 0 Since commit 30832ab56 ("mmc: sdhci: Always pass clock request value zero to set_clock host op") was merged, esdhc_set_clock starts hitting "if (clock == 0)" where ESDHC_SYSTEM_CONTROL has been operated. This causes SDHCI card-detection function being broken. Fix the regression by moving "if (clock == 0)" above ESDHC_SYSTEM_CONTROL operation. Signed-off-by: Shawn Guo Cc: Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index b97b2f5dafdb..d25f9ab9a54d 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) int div = 1; u32 temp; + if (clock == 0) + goto out; + temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); - if (clock == 0) - goto out; - while (host->max_clk / pre_div / 16 > clock && pre_div < 256) pre_div *= 2; From 077d40731edc90ee9dedf63249034c8cd5f694ce Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 24 Jul 2012 11:42:04 +0200 Subject: [PATCH 311/665] mmc: atmel-mci: not busy flag has also to be used for read operations Even if the datasheet says that the not busy flag has to be used only for write operations, it's false except for version lesser than v2xx. Not waiting on the not busy flag for read operations can cause the controller to hang-up during the initialization of some SD cards with DMA after the first CMD6 -- the next command is sent too early. Signed-off-by: Ludovic Desroches Cc: stable [3.5, 3.6] Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 322412cec4ee..a53c7c478e05 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -81,6 +81,7 @@ struct atmel_mci_caps { bool has_bad_data_ordering; bool need_reset_after_xfer; bool need_blksz_mul_4; + bool need_notbusy_for_read_ops; }; struct atmel_mci_dma { @@ -1625,7 +1626,8 @@ static void atmci_tasklet_func(unsigned long priv) __func__); atmci_set_completed(host, EVENT_XFER_COMPLETE); - if (host->data->flags & MMC_DATA_WRITE) { + if (host->caps.need_notbusy_for_read_ops || + (host->data->flags & MMC_DATA_WRITE)) { atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); state = STATE_WAITING_NOTBUSY; } else if (host->mrq->stop) { @@ -2218,6 +2220,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) host->caps.has_bad_data_ordering = 1; host->caps.need_reset_after_xfer = 1; host->caps.need_blksz_mul_4 = 1; + host->caps.need_notbusy_for_read_ops = 0; /* keep only major version number */ switch (version & 0xf00) { @@ -2238,6 +2241,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) case 0x200: host->caps.has_rwproof = 1; host->caps.need_blksz_mul_4 = 0; + host->caps.need_notbusy_for_read_ops = 1; case 0x100: host->caps.has_bad_data_ordering = 0; host->caps.need_reset_after_xfer = 0; From 182c90815993452f1902837cc342ac2c05ef13f5 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 1 Aug 2012 09:30:30 +0900 Subject: [PATCH 312/665] mmc: dw_mmc: amend using error interrupt status RINTSTS status includes masked interrupts as well as unmasked. data_status and cmd_status are set by value of RINTSTS in interrupt handler and tasklet finally uses it to decide whether error is happened or not. In addition, MINTSTS status is used for setting data_status in PIO. Masked error interrupt will not be handled and that status can be considered non-error case. Signed-off-by: Seungwon Jeon Reviewed By: Girish K S Acked-by: Jaehoon Chung Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 72dc3cde646d..7baed457dc3b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1547,12 +1547,11 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) { struct dw_mci *host = dev_id; - u32 status, pending; + u32 pending; unsigned int pass_count = 0; int i; do { - status = mci_readl(host, RINTSTS); pending = mci_readl(host, MINTSTS); /* read-only mask reg */ /* @@ -1570,7 +1569,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & DW_MCI_CMD_ERROR_FLAGS) { mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); - host->cmd_status = status; + host->cmd_status = pending; smp_wmb(); set_bit(EVENT_CMD_COMPLETE, &host->pending_events); } @@ -1578,7 +1577,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & DW_MCI_DATA_ERROR_FLAGS) { /* if there is an error report DATA_ERROR */ mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); - host->data_status = status; + host->data_status = pending; smp_wmb(); set_bit(EVENT_DATA_ERROR, &host->pending_events); if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | @@ -1589,7 +1588,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_DATA_OVER) { mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); if (!host->data_status) - host->data_status = status; + host->data_status = pending; smp_wmb(); if (host->dir_status == DW_MCI_RECV_STATUS) { if (host->sg != NULL) @@ -1613,7 +1612,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_CMD_DONE) { mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); - dw_mci_cmd_interrupt(host, status); + dw_mci_cmd_interrupt(host, pending); } if (pending & SDMMC_INT_CD) { From 9b2026a12511439d906a5d8d302ae285ebe7378a Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 1 Aug 2012 09:30:40 +0900 Subject: [PATCH 313/665] mmc: dw_mmc: correct mishandling error interrupt Datasheet of SYNOPSYS mentions that DTO(Data Transfer Over) interrupt will be raised even if some error interrupts, however it is actually found that DTO does not occur. SYNOPSYS has confirmed this issue. Current implementation defers the call of tasklet_schedule until DTO when the error interrupts is happened. This patch fixes error handling. Signed-off-by: Seungwon Jeon Acked-by: Jaehoon Chung Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7baed457dc3b..1a5db20133ee 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1580,9 +1580,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) host->data_status = pending; smp_wmb(); set_bit(EVENT_DATA_ERROR, &host->pending_events); - if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | - SDMMC_INT_SBE | SDMMC_INT_EBE))) - tasklet_schedule(&host->tasklet); + tasklet_schedule(&host->tasklet); } if (pending & SDMMC_INT_DATA_OVER) { From e74f3a9c993a088f0a067e13941075e4acb7300a Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 1 Aug 2012 09:30:46 +0900 Subject: [PATCH 314/665] mmc: dw_mmc: fix error handling in PIO mode Data transfer will be continued until all the bytes are transmitted, even if data crc error occurs during a multiple-block data transfer. This means RXDR/TXDR interrupts will occurs until data transfer is terminated. Early setting of host->sg to NULL prevents going into xxx_data_pio functions, hence permanent unhandled RXDR/TXDR interrupts occurs. And checking error interrupt status in the xxx_data_pio functions is no need because dw_mci_interrupt does do the same. This patch also removes it. Signed-off-by: Seungwon Jeon Acked-by: Jaehoon Chung Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1a5db20133ee..cf8511b80782 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1429,22 +1429,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host) nbytes += len; remain -= len; } while (remain); - sg_miter->consumed = offset; + sg_miter->consumed = offset; status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_RXDR); - if (status & DW_MCI_DATA_ERROR_FLAGS) { - host->data_status = status; - data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; - smp_wmb(); - - set_bit(EVENT_DATA_ERROR, &host->pending_events); - - tasklet_schedule(&host->tasklet); - return; - } } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ data->bytes_xfered += nbytes; @@ -1497,23 +1485,10 @@ static void dw_mci_write_data_pio(struct dw_mci *host) nbytes += len; remain -= len; } while (remain); - sg_miter->consumed = offset; + sg_miter->consumed = offset; status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_TXDR); - if (status & DW_MCI_DATA_ERROR_FLAGS) { - host->data_status = status; - data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; - - smp_wmb(); - - set_bit(EVENT_DATA_ERROR, &host->pending_events); - - tasklet_schedule(&host->tasklet); - return; - } } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ data->bytes_xfered += nbytes; From 9623b5b9192b349bcadb31cce159072a78ac6972 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Wed, 25 Jul 2012 08:33:17 -0700 Subject: [PATCH 315/665] mmc: dw_mmc: Disable low power mode if SDIO interrupts are used The documentation for the dw_mmc part says that the low power mode should normally only be set for MMC and SD memory and should be turned off for SDIO cards that need interrupts detected. The best place I could find to do this is when the SDIO interrupt was first enabled. I rely on the fact that dw_mci_setup_bus() will be called when it's time to reenable. Signed-off-by: Doug Anderson Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 41 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cf8511b80782..af40d227bece 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) { struct dw_mci *host = slot->host; u32 div; + u32 clk_en_a; if (slot->clock != host->current_speed) { div = host->bus_hz / slot->clock; @@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); - /* enable clock */ - mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE | - SDMMC_CLKEN_LOW_PWR) << slot->id)); + /* enable clock; only low power if no SDIO */ + clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; + if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) + clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; + mci_writel(host, CLKENA, clk_en_a); /* inform CIU */ mci_send_cmd(slot, @@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc) return present; } +/* + * Disable lower power mode. + * + * Low power mode will stop the card clock when idle. According to the + * description of the CLKENA register we should disable low power mode + * for SDIO cards if we need SDIO interrupts to work. + * + * This function is fast if low power mode is already disabled. + */ +static void dw_mci_disable_low_power(struct dw_mci_slot *slot) +{ + struct dw_mci *host = slot->host; + u32 clk_en_a; + const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; + + clk_en_a = mci_readl(host, CLKENA); + + if (clk_en_a & clken_low_pwr) { + mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); + } +} + static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) { struct dw_mci_slot *slot = mmc_priv(mmc); @@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) /* Enable/disable Slot Specific SDIO interrupt */ int_mask = mci_readl(host, INTMASK); if (enb) { + /* + * Turn off low power mode if it was enabled. This is a bit of + * a heavy operation and we disable / enable IRQs a lot, so + * we'll leave low power mode disabled and it will get + * re-enabled again in dw_mci_setup_bus(). + */ + dw_mci_disable_low_power(slot); + mci_writel(host, INTMASK, (int_mask | SDMMC_INT_SDIO(slot->id))); } else { From 3550ccdb9d8d350e526b809bf3dd92b550a74fe1 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 29 Aug 2012 15:05:36 +0900 Subject: [PATCH 316/665] mmc: card: Skip secure erase on MoviNAND; causes unrecoverable corruption. For several MoviNAND eMMC parts, there are known issues with secure erase and secure trim. For these specific MoviNAND devices, we skip these operations. Specifically, there is a bug in the eMMC firmware that causes unrecoverable corruption when the MMC is erased with MMC_CAP_ERASE enabled. References: http://forum.xda-developers.com/showthread.php?t=1644364 https://plus.google.com/111398485184813224730/posts/21pTYfTsCkB#111398485184813224730/posts/21pTYfTsCkB Signed-off-by: Ian Chen Reviewed-by: Namjae Jeon Acked-by: Jaehoon Chung Reviewed-by: Linus Walleij Cc: stable [3.0+] Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 26 +++++++++++++++++++++++++- include/linux/mmc/card.h | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index f1c84decb192..172a768036d8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1411,7 +1411,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); - if (req->cmd_flags & REQ_SECURE) + if (req->cmd_flags & REQ_SECURE && + !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) ret = mmc_blk_issue_secdiscard_rq(mq, req); else ret = mmc_blk_issue_discard_rq(mq, req); @@ -1716,6 +1717,7 @@ force_ro_fail: #define CID_MANFID_SANDISK 0x2 #define CID_MANFID_TOSHIBA 0x11 #define CID_MANFID_MICRON 0x13 +#define CID_MANFID_SAMSUNG 0x15 static const struct mmc_fixup blk_fixups[] = { @@ -1752,6 +1754,28 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, MMC_QUIRK_LONG_READ_TIME), + /* + * On these Samsung MoviNAND parts, performing secure erase or + * secure trim can result in unrecoverable corruption due to a + * firmware bug. + */ + MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + END_FIXUP }; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 111aca5e97f3..4b27f9f503e4 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -239,6 +239,7 @@ struct mmc_card { #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ +#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ /* byte mode */ unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ #define MMC_NO_POWER_NOTIFICATION 0 From 75b53aee2f4fe6375c6007226bf68d75b5c4a929 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 24 Aug 2012 06:00:18 +0000 Subject: [PATCH 317/665] mmc: omap: fix broken PIO mode After commit 26b88520b80695a6fa5fd95b5d97c03f4daf87e0 ("mmc: omap_hsmmc: remove private DMA API implementation"), the Nokia N800 here stopped booting: [ 2.086181] Waiting for root device /dev/mmcblk0p1... [ 2.324066] Unhandled fault: imprecise external abort (0x406) at 0x00000000 [ 2.331451] Internal error: : 406 [#1] ARM [ 2.335784] Modules linked in: [ 2.339050] CPU: 0 Not tainted (3.6.0-rc3 #60) [ 2.344146] PC is at default_idle+0x28/0x30 [ 2.348602] LR is at trace_hardirqs_on_caller+0x15c/0x1b0 ... This turned out to be due to memory corruption caused by long-broken PIO code in drivers/mmc/host/omap.c. (Previously, this driver had been using DMA; but the above commit caused the MMC driver to fall back to PIO mode with an unmodified Kconfig.) The PIO code, added with the rest of the driver in commit 730c9b7e6630f786fcec026fb11d2e6f2c90fdcb ("[MMC] Add OMAP MMC host driver"), confused bytes with 16-bit words. This bug caused memory located after the PIO transfer buffer to be corrupted with transfers larger than 32 bytes. The driver also did not increment the buffer pointer after the transfer occurred. This bug resulted in data corruption during any transfer larger than 64 bytes. Signed-off-by: Paul Walmsley Reviewed-by: Felipe Balbi Tested-by: Tony Lindgren Signed-off-by: Chris Ball --- drivers/mmc/host/omap.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 50e08f03aa65..a5999a74496a 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -668,7 +668,7 @@ mmc_omap_clk_timer(unsigned long data) static void mmc_omap_xfer_data(struct mmc_omap_host *host, int write) { - int n; + int n, nwords; if (host->buffer_bytes_left == 0) { host->sg_idx++; @@ -678,15 +678,23 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) n = 64; if (n > host->buffer_bytes_left) n = host->buffer_bytes_left; + + nwords = n / 2; + nwords += n & 1; /* handle odd number of bytes to transfer */ + host->buffer_bytes_left -= n; host->total_bytes_left -= n; host->data->bytes_xfered += n; if (write) { - __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); + __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), + host->buffer, nwords); } else { - __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); + __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), + host->buffer, nwords); } + + host->buffer += nwords; } static inline void mmc_omap_report_irq(u16 status) From 37159ef2c1ae1e696b24b260b241209a19f92c60 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 4 Sep 2012 07:18:57 +0000 Subject: [PATCH 318/665] l2tp: fix a lockdep splat Fixes following lockdep splat : [ 1614.734896] ============================================= [ 1614.734898] [ INFO: possible recursive locking detected ] [ 1614.734901] 3.6.0-rc3+ #782 Not tainted [ 1614.734903] --------------------------------------------- [ 1614.734905] swapper/11/0 is trying to acquire lock: [ 1614.734907] (slock-AF_INET){+.-...}, at: [] l2tp_xmit_skb+0x172/0xa50 [l2tp_core] [ 1614.734920] [ 1614.734920] but task is already holding lock: [ 1614.734922] (slock-AF_INET){+.-...}, at: [] tcp_v4_err+0x163/0x6b0 [ 1614.734932] [ 1614.734932] other info that might help us debug this: [ 1614.734935] Possible unsafe locking scenario: [ 1614.734935] [ 1614.734937] CPU0 [ 1614.734938] ---- [ 1614.734940] lock(slock-AF_INET); [ 1614.734943] lock(slock-AF_INET); [ 1614.734946] [ 1614.734946] *** DEADLOCK *** [ 1614.734946] [ 1614.734949] May be due to missing lock nesting notation [ 1614.734949] [ 1614.734952] 7 locks held by swapper/11/0: [ 1614.734954] #0: (rcu_read_lock){.+.+..}, at: [] __netif_receive_skb+0x251/0xd00 [ 1614.734964] #1: (rcu_read_lock){.+.+..}, at: [] ip_local_deliver_finish+0x4c/0x4e0 [ 1614.734972] #2: (rcu_read_lock){.+.+..}, at: [] icmp_socket_deliver+0x46/0x230 [ 1614.734982] #3: (slock-AF_INET){+.-...}, at: [] tcp_v4_err+0x163/0x6b0 [ 1614.734989] #4: (rcu_read_lock){.+.+..}, at: [] ip_queue_xmit+0x0/0x680 [ 1614.734997] #5: (rcu_read_lock_bh){.+....}, at: [] ip_finish_output+0x135/0x890 [ 1614.735004] #6: (rcu_read_lock_bh){.+....}, at: [] dev_queue_xmit+0x0/0xe00 [ 1614.735012] [ 1614.735012] stack backtrace: [ 1614.735016] Pid: 0, comm: swapper/11 Not tainted 3.6.0-rc3+ #782 [ 1614.735018] Call Trace: [ 1614.735020] [] __lock_acquire+0x144c/0x1b10 [ 1614.735033] [] ? check_usage+0x9b/0x4d0 [ 1614.735037] [] ? mark_held_locks+0x82/0x130 [ 1614.735042] [] lock_acquire+0x90/0x200 [ 1614.735047] [] ? l2tp_xmit_skb+0x172/0xa50 [l2tp_core] [ 1614.735051] [] ? trace_hardirqs_on+0xd/0x10 [ 1614.735060] [] _raw_spin_lock+0x41/0x50 [ 1614.735065] [] ? l2tp_xmit_skb+0x172/0xa50 [l2tp_core] [ 1614.735069] [] l2tp_xmit_skb+0x172/0xa50 [l2tp_core] [ 1614.735075] [] l2tp_eth_dev_xmit+0x32/0x60 [l2tp_eth] [ 1614.735079] [] dev_hard_start_xmit+0x502/0xa70 [ 1614.735083] [] ? dev_hard_start_xmit+0x5e/0xa70 [ 1614.735087] [] ? dev_queue_xmit+0x141/0xe00 [ 1614.735093] [] sch_direct_xmit+0xfe/0x290 [ 1614.735098] [] dev_queue_xmit+0x1e5/0xe00 [ 1614.735102] [] ? dev_hard_start_xmit+0xa70/0xa70 [ 1614.735106] [] ? eth_header+0x3a/0xf0 [ 1614.735111] [] ? fib_get_table+0x2e/0x280 [ 1614.735117] [] arp_xmit+0x22/0x60 [ 1614.735121] [] arp_send+0x43/0x50 [ 1614.735125] [] arp_solicit+0x18f/0x450 [ 1614.735132] [] neigh_probe+0x4a/0x70 [ 1614.735137] [] __neigh_event_send+0xea/0x300 [ 1614.735141] [] neigh_resolve_output+0x163/0x260 [ 1614.735146] [] ip_finish_output+0x505/0x890 [ 1614.735150] [] ? ip_finish_output+0x135/0x890 [ 1614.735154] [] ip_output+0x59/0xf0 [ 1614.735158] [] ip_local_out+0x2d/0xa0 [ 1614.735162] [] ip_queue_xmit+0x1c3/0x680 [ 1614.735165] [] ? ip_local_out+0xa0/0xa0 [ 1614.735172] [] tcp_transmit_skb+0x402/0xa60 [ 1614.735177] [] tcp_retransmit_skb+0x1a1/0x620 [ 1614.735181] [] tcp_retransmit_timer+0x393/0x960 [ 1614.735185] [] ? tcp_v4_err+0x163/0x6b0 [ 1614.735189] [] tcp_v4_err+0x657/0x6b0 [ 1614.735194] [] ? icmp_socket_deliver+0x46/0x230 [ 1614.735199] [] icmp_socket_deliver+0xce/0x230 [ 1614.735203] [] ? icmp_socket_deliver+0x46/0x230 [ 1614.735208] [] icmp_unreach+0xe4/0x2c0 [ 1614.735213] [] icmp_rcv+0x350/0x4a0 [ 1614.735217] [] ip_local_deliver_finish+0x135/0x4e0 [ 1614.735221] [] ? ip_local_deliver_finish+0x4c/0x4e0 [ 1614.735225] [] ip_local_deliver+0x4a/0x90 [ 1614.735229] [] ip_rcv_finish+0x187/0x730 [ 1614.735233] [] ip_rcv+0x21d/0x300 [ 1614.735237] [] __netif_receive_skb+0x46b/0xd00 [ 1614.735241] [] ? __netif_receive_skb+0x251/0xd00 [ 1614.735245] [] process_backlog+0xb8/0x180 [ 1614.735249] [] net_rx_action+0x159/0x330 [ 1614.735257] [] __do_softirq+0xd0/0x3e0 [ 1614.735264] [] ? tick_program_event+0x24/0x30 [ 1614.735270] [] call_softirq+0x1c/0x30 [ 1614.735278] [] do_softirq+0x8d/0xc0 [ 1614.735282] [] irq_exit+0xae/0xe0 [ 1614.735287] [] smp_apic_timer_interrupt+0x6e/0x99 [ 1614.735291] [] apic_timer_interrupt+0x6c/0x80 [ 1614.735293] [] ? trace_hardirqs_off+0xd/0x10 [ 1614.735306] [] ? intel_idle+0xf5/0x150 [ 1614.735310] [] ? intel_idle+0xee/0x150 [ 1614.735317] [] cpuidle_enter+0x19/0x20 [ 1614.735321] [] cpuidle_idle_call+0xa8/0x630 [ 1614.735327] [] cpu_idle+0x8a/0xe0 [ 1614.735333] [] start_secondary+0x220/0x222 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 513cab08a986..1a9f3723c13c 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1501,6 +1501,8 @@ out: return err; } +static struct lock_class_key l2tp_socket_class; + int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp) { struct l2tp_tunnel *tunnel = NULL; @@ -1605,6 +1607,8 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 tunnel->old_sk_destruct = sk->sk_destruct; sk->sk_destruct = &l2tp_tunnel_destruct; tunnel->sock = sk; + lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock"); + sk->sk_allocation = GFP_ATOMIC; /* Add tunnel to our list */ From 3b59df46a449ec9975146d71318c4777ad086744 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Tue, 4 Sep 2012 00:03:29 +0000 Subject: [PATCH 319/665] xfrm: Workaround incompatibility of ESN and async crypto ESN for esp is defined in RFC 4303. This RFC assumes that the sequence number counters are always up to date. However, this is not true if an async crypto algorithm is employed. If the sequence number counters are not up to date on sequence number check, we may incorrectly update the upper 32 bit of the sequence number. This leads to a DOS. We workaround this by comparing the upper sequence number, (used for authentication) with the upper sequence number computed after the async processing. We drop the packet if these numbers are different. To do this, we introduce a recheck function that does this check in the ESN case. Signed-off-by: Steffen Klassert Acked-by: Herbert Xu Signed-off-by: David S. Miller --- include/net/xfrm.h | 3 +++ net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_replay.c | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 976a81abe1a2..639dd1316d37 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -273,6 +273,9 @@ struct xfrm_replay { int (*check)(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); + int (*recheck)(struct xfrm_state *x, + struct sk_buff *skb, + __be32 net_seq); void (*notify)(struct xfrm_state *x, int event); int (*overflow)(struct xfrm_state *x, struct sk_buff *skb); }; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 54a0dc2e2f8d..ab2bb42fe094 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -212,7 +212,7 @@ resume: /* only the first xfrm gets the encap type */ encap_type = 0; - if (async && x->repl->check(x, skb, seq)) { + if (async && x->repl->recheck(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f6d11d04a2b..3efb07d3eb27 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -420,6 +420,18 @@ err: return -EINVAL; } +static int xfrm_replay_recheck_esn(struct xfrm_state *x, + struct sk_buff *skb, __be32 net_seq) +{ + if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi != + htonl(xfrm_replay_seqhi(x, net_seq)))) { + x->stats.replay_window++; + return -EINVAL; + } + + return xfrm_replay_check_esn(x, skb, net_seq); +} + static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) { unsigned int bitnr, nr, i; @@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) static struct xfrm_replay xfrm_replay_legacy = { .advance = xfrm_replay_advance, .check = xfrm_replay_check, + .recheck = xfrm_replay_check, .notify = xfrm_replay_notify, .overflow = xfrm_replay_overflow, }; @@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_legacy = { static struct xfrm_replay xfrm_replay_bmp = { .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, + .recheck = xfrm_replay_check_bmp, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_bmp, }; @@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bmp = { static struct xfrm_replay xfrm_replay_esn = { .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, + .recheck = xfrm_replay_recheck_esn, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_esn, }; From cadf84bfeb80e216fde328d357fe856160157d2c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:38 +0100 Subject: [PATCH 320/665] staging: comedi: amplc_pci224: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pci224_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pci224_find_pci_dev()`). It is decremented when the `detach` hook (`pci224_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pci224_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pci224_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Cc: stable # 3.5.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 4e17f13e57f6..8bf109e7bb05 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1503,6 +1503,13 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) DRIVER_NAME ": BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pci224_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pci224_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pci224_attach_common(dev, pci_dev, NULL); } From 1a6671d208bb8f558dc12b6a7d2f55e80cf5828d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:39 +0100 Subject: [PATCH 321/665] staging: comedi: amplc_dio200: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`dio200_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `dio200_find_pci_dev()`). It is decremented when the `detach` hook (`dio200_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`dio200_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `dio200_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 6c81e377262c..cc8931fde839 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1412,6 +1412,13 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in dio200_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via dio200_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return dio200_pci_common_attach(dev, pci_dev); } From 3abcfe0eeda850481143d05bdd206dd2b170d07d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:40 +0100 Subject: [PATCH 322/665] staging: comedi: amplc_pc236: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pc236_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pc236_find_pci_dev()`). It is decremented when the `detach` hook (`pc236_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pc236_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pc236_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index aabba9886b7d..f50287903038 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -565,6 +565,13 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pc236_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pc236_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pc236_pci_common_attach(dev, pci_dev); } From a0234ade63ce2c14841d9d6e802ed735b4ed2829 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:41 +0100 Subject: [PATCH 323/665] staging: comedi: amplc_pc263: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pc263_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pc263_find_pci_dev()`). It is decremented when the `detach` hook (`pc263_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pc263_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pc263_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 40ec1ffebba6..8191c4e28e0a 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -298,6 +298,13 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pc263_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pc263_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pc263_pci_common_attach(dev, pci_dev); } From 4375e61ed21d629fe922b3e5591ad6588f715137 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:42 +0100 Subject: [PATCH 324/665] staging: comedi: amplc_pci230: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pci230_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pci230_find_pci_dev()`). It is decremented when the `detach` hook (`pci230_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pci230_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pci230_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 1b67d0c61fa7..66e74bd12267 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2925,6 +2925,13 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev, "amplc_pci230: BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pci230_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pci230_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pci230_attach_common(dev, pci_dev); } From 4a7a4f95a5e15648f24a971b36b82adc36d2cb6b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:43 +0100 Subject: [PATCH 325/665] staging: comedi: das08: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`das08_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `das08_find_pci()`). It is decremented when the `detach` hook (`das08_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`das08_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `das08_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 874e02e47668..c5676e267518 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -922,6 +922,13 @@ das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev) dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in das08_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via das08_attach() + * has been removed. + */ + pci_dev_get(pdev); return das08_pci_attach_common(dev, pdev); } From c3f52af3e03013db5237e339c817beaae5ec9e3a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 3 Sep 2012 14:56:02 -0400 Subject: [PATCH 326/665] NFS: Fix the initialisation of the readdir 'cookieverf' array When the NFS_COOKIEVERF helper macro was converted into a static inline function in commit 99fadcd764 (nfs: convert NFS_*(inode) helpers to static inline), we broke the initialisation of the readdir cookies, since that depended on doing a memset with an argument of 'sizeof(NFS_COOKIEVERF(inode))' which therefore changed from sizeof(be32 cookieverf[2]) to sizeof(be32 *). At this point, NFS_COOKIEVERF seems to be more of an obfuscation than a helper, so the best thing would be to just get rid of it. Also see: https://bugzilla.kernel.org/show_bug.cgi?id=46881 Reported-by: Andi Kleen Reported-by: David Binderman Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org --- fs/nfs/inode.c | 2 +- fs/nfs/nfs3proc.c | 2 +- fs/nfs/nfs4proc.c | 4 ++-- include/linux/nfs_fs.h | 5 ----- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c6e895f0fbf3..9b47610338f5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -154,7 +154,7 @@ static void nfs_zap_caches_locked(struct inode *inode) nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo_timestamp = jiffies; - memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); + memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; else diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index d6b3b5f2d779..69322096c325 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -643,7 +643,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page **pages, unsigned int count, int plus) { struct inode *dir = dentry->d_inode; - __be32 *verf = NFS_COOKIEVERF(dir); + __be32 *verf = NFS_I(dir)->cookieverf; struct nfs3_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 635274140b18..86b4c7361036 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3215,11 +3215,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long long)cookie); - nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); + nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args); res.pgbase = args.pgbase; status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); if (status >= 0) { - memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); + memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; } diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 1f8fc7f9bcd8..4b03f56e280e 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -265,11 +265,6 @@ static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode) return NFS_SERVER(inode)->nfs_client->rpc_ops; } -static inline __be32 *NFS_COOKIEVERF(const struct inode *inode) -{ - return NFS_I(inode)->cookieverf; -} - static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode) { struct nfs_server *nfss = NFS_SERVER(inode); From 872ece86ea5c367aa92f44689c2d01a1c767aeb3 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 4 Sep 2012 11:05:07 -0400 Subject: [PATCH 327/665] NFS: Fix a problem with the legacy binary mount code Apparently, am-utils is still using the legacy binary mountdata interface, and is having trouble parsing /proc/mounts due to the 'port=' field being incorrectly set. The following patch should fix up the regression. Reported-by: Marius Tolzmann Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org --- fs/nfs/super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 239aff7338eb..b8eda700584b 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options, memcpy(sap, &data->addr, sizeof(data->addr)); args->nfs_server.addrlen = sizeof(data->addr); + args->nfs_server.port = ntohs(data->addr.sin_port); if (!nfs_verify_server_address(sap)) goto out_no_address; @@ -2564,6 +2565,7 @@ static int nfs4_validate_mount_data(void *options, return -EFAULT; if (!nfs_verify_server_address(sap)) goto out_no_address; + args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); if (data->auth_flavourlen) { if (data->auth_flavourlen > 1) From 21f498c2f73bd6150d82931f09965826dca0b5f2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 24 Aug 2012 10:59:25 -0400 Subject: [PATCH 328/665] NFSv4: Fix range checking in __nfs4_get_acl_uncached and __nfs4_proc_set_acl Ensure that the user supplied buffer size doesn't cause us to overflow the 'pages' array. Also fix up some confusion between the use of PAGE_SIZE and PAGE_CACHE_SIZE when calculating buffer sizes. We're not using the page cache for anything here. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 86b4c7361036..6b94f2d52532 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3653,11 +3653,11 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server) && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL); } -/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that - * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on +/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that + * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on * the stack. */ -#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT) +#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE) static int buf_to_pages_noslab(const void *buf, size_t buflen, struct page **pages, unsigned int *pgbase) @@ -3668,7 +3668,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen, spages = pages; do { - len = min_t(size_t, PAGE_CACHE_SIZE, buflen); + len = min_t(size_t, PAGE_SIZE, buflen); newpage = alloc_page(GFP_KERNEL); if (newpage == NULL) @@ -3782,17 +3782,16 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu .rpc_argp = &args, .rpc_resp = &res, }; - int ret = -ENOMEM, npages, i; + unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); + int ret = -ENOMEM, i; size_t acl_len = 0; - npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; /* As long as we're doing a round trip to the server anyway, * let's be prepared for a page of acl data. */ if (npages == 0) npages = 1; - - /* Add an extra page to handle the bitmap returned */ - npages++; + if (npages > ARRAY_SIZE(pages)) + return -ERANGE; for (i = 0; i < npages; i++) { pages[i] = alloc_page(GFP_KERNEL); @@ -3891,10 +3890,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl .rpc_argp = &arg, .rpc_resp = &res, }; + unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); int ret, i; if (!nfs4_server_supports_acls(server)) return -EOPNOTSUPP; + if (npages > ARRAY_SIZE(pages)) + return -ERANGE; i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); if (i < 0) return i; From e6391a182865efc896cb2a8d79e07b7ac2f45b48 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 31 Aug 2012 20:41:29 +0100 Subject: [PATCH 329/665] staging: comedi: das08: Correct AI encoding for das08jr-16-ao The element of `das08_boards[]` for the 'das08jr-16-ao' board has the `ai_encoding` member set to `das08_encode12`. It should be set to `das08_encode16` same as the 'das08jr/16' board. After all, this board has 16-bit AI resolution. The description of the A/D LSB register at offset 0 seems incorrect in the user manual "cio-das08jr-16-ao.pdf" as it implies that the AI resolution is only 12 bits. The diagrams of the A/D LSB and MSB registers show 15 data bits and a sign bit, which matches what the software expects for the `das08_encode16` AI encoding method. Cc: stable Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c5676e267518..e5eb3b9ba17f 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -623,7 +623,7 @@ static const struct das08_board_struct das08_boards[] = { .ai = das08_ai_rinsn, .ai_nbits = 16, .ai_pg = das08_pg_none, - .ai_encoding = das08_encode12, + .ai_encoding = das08_encode16, .ao = das08jr_ao_winsn, .ao_nbits = 16, .di = das08jr_di_rbits, From 61ed59ed09e6ad2b8395178ea5ad5f653bba08e3 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 31 Aug 2012 20:41:30 +0100 Subject: [PATCH 330/665] staging: comedi: das08: Correct AO output for das08jr-16-ao Don't zero out bits 15..12 of the data value in `das08jr_ao_winsn()` as that knobbles the upper three-quarters of the output range for the 'das08jr-16-ao' board. Cc: stable Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index e5eb3b9ba17f..67a914a10b55 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -378,7 +378,7 @@ das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, int chan; lsb = data[0] & 0xff; - msb = (data[0] >> 8) & 0xf; + msb = (data[0] >> 8) & 0xff; chan = CR_CHAN(insn->chanspec); From b320e97240de0f98b81f866d59f47af41780eab0 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Sep 2012 21:25:46 +0000 Subject: [PATCH 331/665] i825xx: fix paging fault on znet_probe() In znet_probe(), strncmp() may access beyond 0x100000 and trigger the below oops in kvm. Fix it by limiting the loop under 0x100000-8. I suspect the limit could be further decreased to 0x100000-sizeof(struct netidblk), however no datasheet at hand.. [ 3.744312] BUG: unable to handle kernel paging request at 80100000 [ 3.746145] IP: [<8119d12a>] strncmp+0xc/0x20 [ 3.747446] *pde = 01d10067 *pte = 00100160 [ 3.747493] Oops: 0000 [#1] DEBUG_PAGEALLOC [ 3.747493] Pid: 1, comm: swapper Not tainted 3.6.0-rc1-00018-g57bfc0a #73 Bochs Bochs [ 3.747493] EIP: 0060:[<8119d12a>] EFLAGS: 00010206 CPU: 0 [ 3.747493] EIP is at strncmp+0xc/0x20 [ 3.747493] EAX: 800fff4e EBX: 00000006 ECX: 00000006 EDX: 814d2bb9 [ 3.747493] ESI: 80100000 EDI: 814d2bba EBP: 8e03dfa0 ESP: 8e03df98 [ 3.747493] DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068 [ 3.747493] CR0: 8005003b CR2: 80100000 CR3: 016f7000 CR4: 00000690 [ 3.747493] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 3.747493] DR6: ffff0ff0 DR7: 00000400 [ 3.747493] Process swapper (pid: 1, ti=8e03c000 task=8e040000 task.ti=8e03c000) [ 3.747493] Stack: [ 3.747493] 800fffff 00000000 8e03dfb4 816a1376 00000006 816a134a 00000000 8e03dfd0 [ 3.747493] 816819b5 816ed1c0 8e03dfe4 00000006 00000123 816ed604 8e03dfe4 81681b29 [ 3.747493] 00000000 81681a5b 00000000 00000000 8134e542 00000000 00000000 00000000 [ 3.747493] Call Trace: [ 3.747493] [<816a1376>] znet_probe+0x2c/0x26b [ 3.747493] [<816a134a>] ? dnet_driver_init+0xf/0xf [ 3.747493] [<816819b5>] do_one_initcall+0x6a/0x110 [ 3.747493] [<81681b29>] kernel_init+0xce/0x14b Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/i825xx/znet.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/i825xx/znet.c b/drivers/net/ethernet/i825xx/znet.c index bd1f1ef91e19..ba4e0cea3506 100644 --- a/drivers/net/ethernet/i825xx/znet.c +++ b/drivers/net/ethernet/i825xx/znet.c @@ -139,8 +139,11 @@ struct znet_private { /* Only one can be built-in;-> */ static struct net_device *znet_dev; +#define NETIDBLK_MAGIC "NETIDBLK" +#define NETIDBLK_MAGIC_SIZE 8 + struct netidblk { - char magic[8]; /* The magic number (string) "NETIDBLK" */ + char magic[NETIDBLK_MAGIC_SIZE]; /* The magic number (string) "NETIDBLK" */ unsigned char netid[8]; /* The physical station address */ char nettype, globalopt; char vendor[8]; /* The machine vendor and product name. */ @@ -373,14 +376,16 @@ static int __init znet_probe (void) struct znet_private *znet; struct net_device *dev; char *p; + char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE); int err = -ENOMEM; /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ - for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++) - if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0) + for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++) + if (*p == 'N' && + strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0) break; - if (p >= (char *)phys_to_virt(0x100000)) { + if (p > plast) { if (znet_debug > 1) printk(KERN_INFO "No Z-Note ethernet adaptor found.\n"); return -ENODEV; From 01f8a27e3c9109c0187f473e593fa7b45cdb65e8 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Fri, 17 Aug 2012 19:31:04 +0200 Subject: [PATCH 332/665] staging: wlan-ng: Fix problem with wrong arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function pointer scan in struct cfg80211_ops is not supposed to be assigned a function with a struct net_device pointer as an argument. Instead access the net_device struct in the following way: struct net_device *dev = request->wdev->netdev; sparse gives these warnings: drivers/staging/wlan-ng/cfg80211.c:726:17: warning: incorrect type in initializer (incompatible argument 2 (different base types)) expected int ( *scan )( ... ) got int ( extern [toplevel] * )( ... ) drivers/staging/wlan-ng/cfg80211.c:726:2: warning: initialization from incompatible pointer type [enabled by default] drivers/staging/wlan-ng/cfg80211.c:726:2: warning: (near initialization for ‘prism2_usb_cfg_ops.scan’) [enabled by default] Signed-off-by: Emil Goode Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index fabff4d650ef..0970127344e6 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -327,9 +327,9 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, return result; } -int prism2_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request) +int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { + struct net_device *dev = request->wdev->netdev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = dev->ml_priv; struct p80211msg_dot11req_scan msg1; From 07732be2efa7d4ade66d224ea84d2c30740d0b77 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 19 Aug 2012 19:36:37 +0300 Subject: [PATCH 333/665] staging: ozwpan: fix memcmp() test in oz_set_active_pd() "addr" is a pointer so it's either 4 or 8 bytes, but actually we want to compare 6 bytes (ETH_ALEN). As network stack already provides helper function is_zero_ether_addr() we use that instead of memcmp Signed-off-by: Tomas Winkler Acked-by: Dan Carpenter Acked-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozcdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index d98321945802..758ce0a8d82e 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "ozconfig.h" @@ -213,7 +214,7 @@ static int oz_set_active_pd(u8 *addr) if (old_pd) oz_pd_put(old_pd); } else { - if (!memcmp(addr, "\0\0\0\0\0\0", sizeof(addr))) { + if (is_zero_ether_addr(addr)) { spin_lock_bh(&g_cdev.lock); pd = g_cdev.active_pd; g_cdev.active_pd = 0; From c0cc88a7627c333de50b07b7c60b1d49d9d2e6cc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 4 Sep 2012 15:54:55 -0400 Subject: [PATCH 334/665] l2tp: fix a typo in l2tp_eth_dev_recv() While investigating l2tp bug, I hit a bug in eth_type_trans(), because not enough bytes were pulled in skb head. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/l2tp/l2tp_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index f9ee74deeac2..3bfb34aaee29 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -153,7 +153,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length); } - if (!pskb_may_pull(skb, sizeof(ETH_HLEN))) + if (!pskb_may_pull(skb, ETH_HLEN)) goto error; secpath_reset(skb); From aa209eef3ce8419ff2926c2fa944dfbfb5afbacb Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 29 Aug 2012 23:08:21 +0100 Subject: [PATCH 335/665] staging: vt6656: [BUG] - Failed connection, incorrect endian. Hi, This patch fixes a bug with driver failing to negotiate a connection. The bug was traced to commit 203e4615ee9d9fa8d3506b9d0ef30095e4d5bc90 staging: vt6656: removed custom definitions of Ethernet packet types In that patch, definitions in include/linux/if_ether.h replaced ones in tether.h which had both big and little endian definitions. include/linux/if_ether.h only refers to big endian values, cpu_to_be16 should be used for the correct endian architectures. Signed-off-by: Malcolm Priestley Cc: stable # 2.6.37+ Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/dpc.c | 2 +- drivers/staging/vt6656/rxtx.c | 38 +++++++++++++++++------------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index e4bdf2a2b582..3aa895ec6507 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -200,7 +200,7 @@ s_vProcessRxMACHeader ( } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { cbHeaderSize += 6; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); - if ((*pwType == cpu_to_le16(ETH_P_IPX)) || + if ((*pwType == cpu_to_be16(ETH_P_IPX)) || (*pwType == cpu_to_le16(0xF380))) { cbHeaderSize -= 8; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index bb464527fc1b..b6e04e7b629b 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1699,7 +1699,7 @@ s_bPacketToWirelessUsb( // 802.1H if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) { if (pDevice->dwDiagRefCount == 0) { - if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) || + if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) || (psEthHeader->wType == cpu_to_le16(0xF380))) { memcpy((PBYTE) (pbyPayloadHead), abySNAP_Bridgetunnel, 6); @@ -2838,10 +2838,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) Packet_Type = skb->data[ETH_HLEN+1]; Descriptor_type = skb->data[ETH_HLEN+1+1+2]; Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - /* 802.1x OR eapol-key challenge frame transfer */ - if (((Protocol_Version == 1) || (Protocol_Version == 2)) && - (Packet_Type == 3)) { + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + /* 802.1x OR eapol-key challenge frame transfer */ + if (((Protocol_Version == 1) || (Protocol_Version == 2)) && + (Packet_Type == 3)) { bTxeapol_key = TRUE; if(!(Key_info & BIT3) && //WPA or RSN group-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key @@ -2987,19 +2987,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) } } - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - if (pDevice->byBBType != BB_TYPE_11A) { - pDevice->wCurrentRate = RATE_1M; - pDevice->byACKRate = RATE_1M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } else { - pDevice->wCurrentRate = RATE_6M; - pDevice->byACKRate = RATE_6M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } - } + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + if (pDevice->byBBType != BB_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n", @@ -3015,7 +3015,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) if (bNeedEncryption == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); - if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) { + if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) { bNeedEncryption = FALSE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { From 6bd4a5d96c08dc2380f8053b1bd4f879f55cd3c9 Mon Sep 17 00:00:00 2001 From: "Dae S. Kim" Date: Fri, 31 Aug 2012 02:00:51 +0200 Subject: [PATCH 336/665] Staging: Android alarm: IOCTL command encoding fix Fixed a bug. Data was being written to user space using an IOCTL command encoded with _IOC_WRITE access mode. Signed-off-by: Dae S. Kim Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/android_alarm.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index d0cafd637199..f2ffd963f1c3 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -51,10 +51,12 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) +#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) + /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) From 29d214576f936db627ff62afb9ef438eea18bcd2 Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Wed, 22 Aug 2012 11:53:18 -0500 Subject: [PATCH 337/665] xhci: Recognize USB 3.0 devices as superspeed at powerup On Intel Panther Point chipset USB 3.0 devices show up as high-speed devices on powerup, but after an s3 cycle they are correctly recognized as SuperSpeed. At powerup switch the port to xHCI so that USB 3.0 devices are correctly recognized. BugLink: http://bugs.launchpad.net/bugs/1000424 This patch should be backported to kernels as old as 3.0, that contain commit ID 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Manoj Iyer Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index c5e9e4a76f14..486e8122f0d8 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -870,9 +870,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) /* Disable any BIOS SMIs and clear all SMI events*/ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); +hc_init: if (usb_is_intel_switchable_xhci(pdev)) usb_enable_xhci_ports(pdev); -hc_init: + op_reg_base = base + XHCI_HC_LENGTH(readl(base)); /* Wait for the host controller to be ready before writing any From a96874a2a92feaef607ddd3137277a788cb927a6 Mon Sep 17 00:00:00 2001 From: Keng-Yu Lin Date: Fri, 10 Aug 2012 01:39:23 +0800 Subject: [PATCH 338/665] Intel xhci: Only switch the switchable ports With a previous patch to enable the EHCI/XHCI port switching, it switches all the available ports. The assumption is not correct because the BIOS may expect some ports not switchable by the OS. There are two more registers that contains the information of the switchable and non-switchable ports. This patch adds the checking code for the two register so that only the switchable ports are altered. This patch should be backported to kernels as old as 3.0, that contain commit ID 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Keng-Yu Lin Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 486e8122f0d8..20b9f45f931c 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -75,7 +75,9 @@ #define NB_PIF0_PWRDOWN_1 0x01100013 #define USB_INTEL_XUSB2PR 0xD0 +#define USB_INTEL_USB2PRM 0xD4 #define USB_INTEL_USB3_PSSEN 0xD8 +#define USB_INTEL_USB3PRM 0xDC static struct amd_chipset_info { struct pci_dev *nb_dev; @@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) return; } - ports_available = 0xffffffff; + /* Read USB3PRM, the USB 3.0 Port Routing Mask Register + * Indicate the ports that can be changed from OS. + */ + pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", + ports_available); + /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable - * Register, to turn on SuperSpeed terminations for all - * available ports. + * Register, to turn on SuperSpeed terminations for the + * switchable ports. */ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, cpu_to_le32(ports_available)); @@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " "under xHCI: 0x%x\n", ports_available); - ports_available = 0xffffffff; + /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register + * Indicate the USB 2.0 ports to be controlled by the xHCI host. + */ + + pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", + ports_available); + /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to * switch the USB 2.0 power and data lines over to the xHCI * host. From 96e65306b81351b656835c15931d1d237b252f27 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 2 Sep 2012 00:28:19 +0800 Subject: [PATCH 339/665] workqueue: UNBOUND -> REBIND morphing in rebind_workers() should be atomic The compiler may compile the following code into TWO write/modify instructions. worker->flags &= ~WORKER_UNBOUND; worker->flags |= WORKER_REBIND; so the other CPU may temporarily see worker->flags which doesn't have either WORKER_UNBOUND or WORKER_REBIND set and perform local wakeup prematurely. Fix it by using single explicit assignment via ACCESS_ONCE(). Because idle workers have another WORKER_NOT_RUNNING flag, this bug doesn't exist for them; however, update it to use the same pattern for consistency. tj: Applied the change to idle workers too and updated comments and patch description a bit. Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- kernel/workqueue.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 692d97628a10..c462cd60c374 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1396,12 +1396,15 @@ retry: /* set REBIND and kick idle ones, we'll wait for these later */ for_each_worker_pool(pool, gcwq) { list_for_each_entry(worker, &pool->idle_list, entry) { + unsigned long worker_flags = worker->flags; + if (worker->flags & WORKER_REBIND) continue; - /* morph UNBOUND to REBIND */ - worker->flags &= ~WORKER_UNBOUND; - worker->flags |= WORKER_REBIND; + /* morph UNBOUND to REBIND atomically */ + worker_flags &= ~WORKER_UNBOUND; + worker_flags |= WORKER_REBIND; + ACCESS_ONCE(worker->flags) = worker_flags; idle_rebind.cnt++; worker->idle_rebind = &idle_rebind; @@ -1434,10 +1437,12 @@ retry: /* rebind busy workers */ for_each_busy_worker(worker, i, pos, gcwq) { struct work_struct *rebind_work = &worker->rebind_work; + unsigned long worker_flags = worker->flags; - /* morph UNBOUND to REBIND */ - worker->flags &= ~WORKER_UNBOUND; - worker->flags |= WORKER_REBIND; + /* morph UNBOUND to REBIND atomically */ + worker_flags &= ~WORKER_UNBOUND; + worker_flags |= WORKER_REBIND; + ACCESS_ONCE(worker->flags) = worker_flags; if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(rebind_work))) From e534e871a94ba2e3bfdf0edd3685eb805fc960d8 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 4 Sep 2012 17:22:45 -0700 Subject: [PATCH 340/665] ARM: OMAP4: Fix array size for irq_target_cpu If NR_IRQS is less than MAX_IRQS, we end up writing past the irq_target_cpu array in omap_wakeupgen_init(): /* Associate all the IRQs to boot CPU like GIC init does. */ for (i = 0; i < max_irqs; i++) irq_target_cpu[i] = boot_cpu; This can happen if SPARSE_IRQ is enabled as by default NR_IRQS is set to 16. Without this patch we're overwriting other data during the boot. Looks like a similar fix was posted by Benoit Cousson earlier as "ARM: OMAP2+: wakeupgen: Fix wrong array size for irq_target_cpu" but was lost. Cc: stable@vger.kernel.org Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap-wakeupgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 05fdebfaa195..330d4c6e746b 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -46,7 +46,7 @@ static void __iomem *wakeupgen_base; static void __iomem *sar_base; static DEFINE_SPINLOCK(wakeupgen_lock); -static unsigned int irq_target_cpu[NR_IRQS]; +static unsigned int irq_target_cpu[MAX_IRQS]; static unsigned int irq_banks = MAX_NR_REG_BANKS; static unsigned int max_irqs = MAX_IRQS; static unsigned int omap_secure_apis; From e829c66745e66558b624fd635be4a384fe854944 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 30 Aug 2012 19:22:36 +0200 Subject: [PATCH 341/665] ARM: gemini: fix the gemini build Test-compiling obscure machines I notice that the gemini (which by the way lacks a defconfig) is broken since some time back. Adding a simple missing include makes it build again. Signed-off-by: Linus Walleij Signed-off-by: Olof Johansson --- arch/arm/mach-gemini/irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c index ca70e5fcc7ac..020852d3bdd8 100644 --- a/arch/arm/mach-gemini/irq.c +++ b/arch/arm/mach-gemini/irq.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #define IRQ_SOURCE(base_addr) (base_addr + 0x00) From 79c5fcebfe4021f326a6715009f0b6b622d5df92 Mon Sep 17 00:00:00 2001 From: Jesse Larrew Date: Thu, 7 Jun 2012 16:04:34 -0500 Subject: [PATCH 342/665] powerpc/vphn: Fix arch_update_cpu_topology() return value arch_update_cpu_topology() should only return 1 when the topology has actually changed, and should return 0 otherwise. This patch fixes a potential bug where rebuild_sched_domains() would reinitialize the sched domains even when the topology hasn't changed. Signed-off-by: Jesse Larrew Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/mm/numa.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 39b159751c35..59213cfaeca9 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1436,11 +1436,11 @@ static long vphn_get_associativity(unsigned long cpu, /* * Update the node maps and sysfs entries for each cpu whose home node - * has changed. + * has changed. Returns 1 when the topology has changed, and 0 otherwise. */ int arch_update_cpu_topology(void) { - int cpu, nid, old_nid; + int cpu, nid, old_nid, changed = 0; unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; struct device *dev; @@ -1466,9 +1466,10 @@ int arch_update_cpu_topology(void) dev = get_cpu_device(cpu); if (dev) kobject_uevent(&dev->kobj, KOBJ_CHANGE); + changed = 1; } - return 1; + return changed; } static void topology_work_fn(struct work_struct *work) From dabe859ec6360a12e71f39bf695d174e19ff2688 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 26 Jul 2012 13:56:11 +0000 Subject: [PATCH 343/665] powerpc: Give hypervisor decrementer interrupts their own handler At the moment the handler for hypervisor decrementer interrupts is the same as for decrementer interrupts, i.e. timer_interrupt(). This is bogus; if we ever do get a hypervisor decrementer interrupt it won't have anything to do with the next timer event. In fact the only time we get hypervisor decrementer interrupts is when one is left pending on exit from a KVM guest. When we get a hypervisor decrementer interrupt we don't need to do anything special to clear it, since they are edge-triggered on the transition of HDEC from 0 to -1. Thus this adds an empty handler function for them. We don't need to have them masked when interrupts are soft-disabled, so we use STD_EXCEPTION_HV instead of MASKABLE_EXCEPTION_HV. Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/exceptions-64s.S | 3 ++- arch/powerpc/kernel/time.c | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index e894515e77bb..39aa97d3ff88 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -186,7 +186,7 @@ hardware_interrupt_hv: KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800) MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer) - MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer) + STD_EXCEPTION_HV(0x980, 0x982, hdecrementer) STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a) KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00) @@ -486,6 +486,7 @@ machine_check_common: STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ) STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt) + STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt) STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception) STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index be171ee73bf8..e49e93191b69 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -535,6 +535,15 @@ void timer_interrupt(struct pt_regs * regs) trace_timer_interrupt_exit(regs); } +/* + * Hypervisor decrementer interrupts shouldn't occur but are sometimes + * left pending on exit from a KVM guest. We don't need to do anything + * to clear them, as they are edge-triggered. + */ +void hdec_interrupt(struct pt_regs *regs) +{ +} + #ifdef CONFIG_SUSPEND static void generic_suspend_disable_irqs(void) { From 375f561a4131a0f501c8845a2a20f2ca1abc8f7a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 26 Jul 2012 18:51:09 +0000 Subject: [PATCH 344/665] powerpc/powernv: Always go into nap mode when CPU is offline The CPU hotplug code for the powernv platform currently only puts offline CPUs into nap mode if the powersave_nap variable is set. However, HV-style KVM on this platform requires secondary CPU threads to be offline and in nap mode. Since we know nap mode works just fine on all POWER7 machines, and the only machines that support the powernv platform are POWER7 machines, this changes the code to always put offline CPUs into nap mode, regardless of powersave_nap. Powersave_nap still controls whether or not CPUs go into nap mode when idle, as before. Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/kernel/idle_power7.S | 2 ++ arch/powerpc/platforms/powernv/smp.c | 10 +--------- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 53b6dfa83344..54b73a28c205 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -386,6 +386,7 @@ extern unsigned long cpuidle_disable; enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; extern int powersave_nap; /* set if nap mode can be used in idle loop */ +extern void power7_nap(void); #ifdef CONFIG_PSERIES_IDLE extern void update_smt_snooze_delay(int snooze); diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index 7140d838339e..e11863f4e595 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S @@ -28,7 +28,9 @@ _GLOBAL(power7_idle) lwz r4,ADDROFF(powersave_nap)(r3) cmpwi 0,r4,0 beqlr + /* fall through */ +_GLOBAL(power7_nap) /* NAP is a state loss, we create a regs frame on the * stack, fill it up with the state we care about and * stick a pointer to it in PACAR1. We really only diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 3ef46254c35b..7698b6e13c57 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c @@ -106,14 +106,6 @@ static void pnv_smp_cpu_kill_self(void) { unsigned int cpu; - /* If powersave_nap is enabled, use NAP mode, else just - * spin aimlessly - */ - if (!powersave_nap) { - generic_mach_cpu_die(); - return; - } - /* Standard hot unplug procedure */ local_irq_disable(); idle_task_exit(); @@ -128,7 +120,7 @@ static void pnv_smp_cpu_kill_self(void) */ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1); while (!generic_check_cpu_restart(cpu)) { - power7_idle(); + power7_nap(); if (!generic_check_cpu_restart(cpu)) { DBG("CPU%d Unexpected exit while offline !\n", cpu); /* We may be getting an IPI, so we re-enable From 1b6ca2a6fe56e7697d57348646e07df08f43b1bb Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:47:56 +0000 Subject: [PATCH 345/665] powerpc: Update DSCR on all CPUs when writing sysfs dscr_default Writing to dscr_default in sysfs doesn't actually change the DSCR - we rely on a context switch on each CPU to do the work. There is no guarantee we will get a context switch in a reasonable amount of time so fire off an IPI to force an immediate change. This issue was found with the following test case: http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c Signed-off-by: Anton Blanchard Cc: # 3.0+ Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/sysfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 3529446c2abd..d4cbbd1fa75f 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -194,6 +194,12 @@ static ssize_t show_dscr_default(struct device *dev, return sprintf(buf, "%lx\n", dscr_default); } +static void update_dscr(void *dummy) +{ + if (!current->thread.dscr_inherit) + mtspr(SPRN_DSCR, dscr_default); +} + static ssize_t __used store_dscr_default(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -206,6 +212,8 @@ static ssize_t __used store_dscr_default(struct device *dev, return -EINVAL; dscr_default = val; + on_each_cpu(update_dscr, NULL, 1); + return count; } From 00ca0de02f80924dfff6b4f630e1dff3db005e35 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:48:46 +0000 Subject: [PATCH 346/665] powerpc: Keep thread.dscr and thread.dscr_inherit in sync When we update the DSCR either via emulation of mtspr(DSCR) or via a change to dscr_default in sysfs we don't update thread.dscr. We will eventually update it at context switch time but there is a period where thread.dscr is incorrect. If we fork at this point we will copy the old value of thread.dscr into the child. To avoid this, always keep thread.dscr in sync with reality. This issue was found with the following testcase: http://ozlabs.org/~anton/junkcode/dscr_inherit_test.c Signed-off-by: Anton Blanchard Cc: # 3.0+ Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/sysfs.c | 4 +++- arch/powerpc/kernel/traps.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index d4cbbd1fa75f..8302af649219 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -196,8 +196,10 @@ static ssize_t show_dscr_default(struct device *dev, static void update_dscr(void *dummy) { - if (!current->thread.dscr_inherit) + if (!current->thread.dscr_inherit) { + current->thread.dscr = dscr_default; mtspr(SPRN_DSCR, dscr_default); + } } static ssize_t __used store_dscr_default(struct device *dev, diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 158972341a2d..ae0843fa7a61 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -972,8 +972,9 @@ static int emulate_instruction(struct pt_regs *regs) cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mtdscr, regs); rd = (instword >> 21) & 0x1f; - mtspr(SPRN_DSCR, regs->gpr[rd]); + current->thread.dscr = regs->gpr[rd]; current->thread.dscr_inherit = 1; + mtspr(SPRN_DSCR, current->thread.dscr); return 0; } #endif From 1021cb268b3025573c4811f1dee4a11260c4507b Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:49:47 +0000 Subject: [PATCH 347/665] powerpc: Fix DSCR inheritance in copy_thread() If the default DSCR is non zero we set thread.dscr_inherit in copy_thread() meaning the new thread and all its children will ignore future updates to the default DSCR. This is not intended and is a change in behaviour that a number of our users have hit. We just need to inherit thread.dscr and thread.dscr_inherit from the parent which ends up being much simpler. This was found with the following test case: http://ozlabs.org/~anton/junkcode/dscr_default_test.c Signed-off-by: Anton Blanchard Cc: # 3.0+ Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/process.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 710f400476de..1a1f2ddfb581 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -802,16 +802,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, #endif /* CONFIG_PPC_STD_MMU_64 */ #ifdef CONFIG_PPC64 if (cpu_has_feature(CPU_FTR_DSCR)) { - if (current->thread.dscr_inherit) { - p->thread.dscr_inherit = 1; - p->thread.dscr = current->thread.dscr; - } else if (0 != dscr_default) { - p->thread.dscr_inherit = 1; - p->thread.dscr = dscr_default; - } else { - p->thread.dscr_inherit = 0; - p->thread.dscr = 0; - } + p->thread.dscr_inherit = current->thread.dscr_inherit; + p->thread.dscr = current->thread.dscr; } #endif From 714332858bfd40dcf8f741498336d93875c23aa7 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:51:10 +0000 Subject: [PATCH 348/665] powerpc: Restore correct DSCR in context switch During a context switch we always restore the per thread DSCR value. If we aren't doing explicit DSCR management (ie thread.dscr_inherit == 0) and the default DSCR changed while the process has been sleeping we end up with the wrong value. Check thread.dscr_inherit and select the default DSCR or per thread DSCR as required. This was found with the following test case, when running with more threads than CPUs (ie forcing context switching): http://ozlabs.org/~anton/junkcode/dscr_default_test.c With the four patches applied I can run a combination of all test cases successfully at the same time: http://ozlabs.org/~anton/junkcode/dscr_default_test.c http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c http://ozlabs.org/~anton/junkcode/dscr_inherit_test.c Signed-off-by: Anton Blanchard Cc: # 3.0+ Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kernel/entry_64.S | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 85b05c463fae..e8995727b1c1 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -76,6 +76,7 @@ int main(void) DEFINE(SIGSEGV, SIGSEGV); DEFINE(NMI_MASK, NMI_MASK); DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr)); + DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit)); #else DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 4b01a25e29ef..b40e0b4815b3 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -370,6 +370,12 @@ _GLOBAL(ret_from_fork) li r3,0 b syscall_exit + .section ".toc","aw" +DSCR_DEFAULT: + .tc dscr_default[TC],dscr_default + + .section ".text" + /* * This routine switches between two different tasks. The process * state of one is saved on its kernel stack. Then the state @@ -509,9 +515,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) mr r1,r8 /* start using new stack pointer */ std r7,PACAKSAVE(r13) - ld r6,_CCR(r1) - mtcrf 0xFF,r6 - #ifdef CONFIG_ALTIVEC BEGIN_FTR_SECTION ld r0,THREAD_VRSAVE(r4) @@ -520,14 +523,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_PPC64 BEGIN_FTR_SECTION + lwz r6,THREAD_DSCR_INHERIT(r4) + ld r7,DSCR_DEFAULT@toc(2) ld r0,THREAD_DSCR(r4) - cmpd r0,r25 - beq 1f + cmpwi r6,0 + bne 1f + ld r0,0(r7) +1: cmpd r0,r25 + beq 2f mtspr SPRN_DSCR,r0 -1: +2: END_FTR_SECTION_IFSET(CPU_FTR_DSCR) #endif + ld r6,_CCR(r1) + mtcrf 0xFF,r6 + /* r3-r13 are destroyed -- Cort */ REST_8GPRS(14, r1) REST_10GPRS(22, r1) From 9fb1b36ca1234e64a5d1cc573175303395e3354d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 4 Sep 2012 18:33:08 +0000 Subject: [PATCH 349/665] powerpc: Make sure IPI handlers see data written by IPI senders We have been observing hangs, both of KVM guest vcpu tasks and more generally, where a process that is woken doesn't properly wake up and continue to run, but instead sticks in TASK_WAKING state. This happens because the update of rq->wake_list in ttwu_queue_remote() is not ordered with the update of ipi_message in smp_muxed_ipi_message_pass(), and the reading of rq->wake_list in scheduler_ipi() is not ordered with the reading of ipi_message in smp_ipi_demux(). Thus it is possible for the IPI receiver not to see the updated rq->wake_list and therefore conclude that there is nothing for it to do. In order to make sure that anything done before smp_send_reschedule() is ordered before anything done in the resulting call to scheduler_ipi(), this adds barriers in smp_muxed_message_pass() and smp_ipi_demux(). The barrier in smp_muxed_message_pass() is a full barrier to ensure that there is a full ordering between the smp_send_reschedule() caller and scheduler_ipi(). In smp_ipi_demux(), we use xchg() rather than xchg_local() because xchg() includes release and acquire barriers. Using xchg() rather than xchg_local() makes sense given that ipi_message is not just accessed locally. This moves the barrier between setting the message and calling the cause_ipi() function into the individual cause_ipi implementations. Most of them -- those that used outb, out_8 or similar -- already had a full barrier because out_8 etc. include a sync before the MMIO store. This adds an explicit barrier in the two remaining cases. These changes made no measurable difference to the speed of IPIs as measured using a simple ping-pong latency test across two CPUs on different cores of a POWER7 machine. The analysis of the reason why processes were not waking up properly is due to Milton Miller. Cc: stable@vger.kernel.org # v3.0+ Reported-by: Milton Miller Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/dbell.c | 2 ++ arch/powerpc/kernel/smp.c | 11 +++++++++-- arch/powerpc/sysdev/xics/icp-hv.c | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c index 5b25c8060fd6..a892680668d8 100644 --- a/arch/powerpc/kernel/dbell.c +++ b/arch/powerpc/kernel/dbell.c @@ -28,6 +28,8 @@ void doorbell_setup_this_cpu(void) void doorbell_cause_ipi(int cpu, unsigned long data) { + /* Order previous accesses vs. msgsnd, which is treated as a store */ + mb(); ppc_msgsnd(PPC_DBELL, 0, data); } diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 0321007086f7..8d4214afc21d 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -198,8 +198,15 @@ void smp_muxed_ipi_message_pass(int cpu, int msg) struct cpu_messages *info = &per_cpu(ipi_message, cpu); char *message = (char *)&info->messages; + /* + * Order previous accesses before accesses in the IPI handler. + */ + smp_mb(); message[msg] = 1; - mb(); + /* + * cause_ipi functions are required to include a full barrier + * before doing whatever causes the IPI. + */ smp_ops->cause_ipi(cpu, info->data); } @@ -211,7 +218,7 @@ irqreturn_t smp_ipi_demux(void) mb(); /* order any irq clear */ do { - all = xchg_local(&info->messages, 0); + all = xchg(&info->messages, 0); #ifdef __BIG_ENDIAN if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION))) diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c index 14469cf9df68..df0fc5821469 100644 --- a/arch/powerpc/sysdev/xics/icp-hv.c +++ b/arch/powerpc/sysdev/xics/icp-hv.c @@ -65,7 +65,11 @@ static inline void icp_hv_set_xirr(unsigned int value) static inline void icp_hv_set_qirr(int n_cpu , u8 value) { int hw_cpu = get_hard_smp_processor_id(n_cpu); - long rc = plpar_hcall_norets(H_IPI, hw_cpu, value); + long rc; + + /* Make sure all previous accesses are ordered before IPI sending */ + mb(); + rc = plpar_hcall_norets(H_IPI, hw_cpu, value); if (rc != H_SUCCESS) { pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x " "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc); From 636802ef96eebe279b22ad9f9dacfe29291e45c7 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 4 Sep 2012 15:08:28 +0000 Subject: [PATCH 350/665] powerpc: Don't use __put_user() in patch_instruction patch_instruction() can be called very early on ppc32, when the kernel isn't yet running at it's linked address. That can cause the ! is_kernel_addr() test in __put_user() to trip and call might_sleep() which is very bad at that point during boot. Use a lower level function instead for now, at least until we get to rework ppc32 boot process to do the code patching later, like ppc64 does. Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/lib/code-patching.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index dd223b3eb333..17e5b2364312 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -20,7 +20,7 @@ int patch_instruction(unsigned int *addr, unsigned int instr) { int err; - err = __put_user(instr, addr); + __put_user_size(instr, addr, 4, err); if (err) return err; asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr)); From 15674868d6c5985466835c56dd89d39235f16302 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 4 Sep 2012 13:55:05 +0530 Subject: [PATCH 351/665] mm/memblock: Use NULL instead of 0 for pointers This type cleanup also fixes the following sparse warning: mm/memblock.c:249:49: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Acked-by: Tejun Heo Cc: Andrew Morton Cc: patches@linaro.org Cc: linux-mm@kvack.org Signed-off-by: Ingo Molnar --- mm/memblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memblock.c b/mm/memblock.c index 4d9393c7edc9..82aa349d2f7a 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -246,7 +246,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type, min(new_area_start, memblock.current_limit), new_alloc_size, PAGE_SIZE); - new_array = addr ? __va(addr) : 0; + new_array = addr ? __va(addr) : NULL; } if (!addr) { pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n", From e93c7d1bc350189511d32cec2f0af79c30e7fa47 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Aug 2012 17:06:15 +0300 Subject: [PATCH 352/665] ASoC: omap-mcbsp: Fix compilation error due to leftover code Part of commit (which patches sound/soc/omap/mcbsp.c file): 8fef626 ARM/ASoC: omap-mcbsp: Remove CLKR/FSR mux configuration code since the tree where it has been applied did not had the earlier patch: d0db84e ASoC: omap-mcbsp: Fix 6pin mux configuration which changed code around omap_mcbsp_6pin_src_mux(). Because of the missing part from 8fef626 the sound/soc/omap/mcbsp.c does not compile in linux-next. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/mcbsp.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 935ccf633976..bc06175e6367 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -762,37 +762,6 @@ int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) } -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) -{ - const char *signal, *src; - - if (!mcbsp->pdata->mux_signal) - return -EINVAL; - - switch (mux) { - case CLKR_SRC_CLKR: - signal = "clkr"; - src = "clkr"; - break; - case CLKR_SRC_CLKX: - signal = "clkr"; - src = "clkx"; - break; - case FSR_SRC_FSR: - signal = "fsr"; - src = "fsr"; - break; - case FSR_SRC_FSX: - signal = "fsr"; - src = "fsx"; - break; - default: - return -EINVAL; - } - - return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); -} - #define max_thres(m) (mcbsp->pdata->buffer_size) #define valid_threshold(m, val) ((val) <= max_thres(m)) #define THRESHOLD_PROP_BUILDER(prop) \ From 50e900417b8096939d12a46848f965e27a905e36 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 4 Sep 2012 15:45:17 -0400 Subject: [PATCH 353/665] xen/p2m: Fix one-off error in checking the P2M tree directory. We would traverse the full P2M top directory (from 0->MAX_DOMAIN_PAGES inclusive) when trying to figure out whether we can re-use some of the P2M middle leafs. Which meant that if the kernel was compiled with MAX_DOMAIN_PAGES=512 we would try to use the 512th entry. Fortunately for us the p2m_top_index has a check for this: BUG_ON(pfn >= MAX_P2M_PFN); which we hit and saw this: (XEN) domain_crash_sync called from entry.S (XEN) Domain 0 (vcpu#0) crashed on cpu#0: (XEN) ----[ Xen-4.1.2-OVM x86_64 debug=n Tainted: C ]---- (XEN) CPU: 0 (XEN) RIP: e033:[] (XEN) RFLAGS: 0000000000000212 EM: 1 CONTEXT: pv guest (XEN) rax: ffffffff81db5000 rbx: ffffffff81db4000 rcx: 0000000000000000 (XEN) rdx: 0000000000480211 rsi: 0000000000000000 rdi: ffffffff81db4000 (XEN) rbp: ffffffff81793db8 rsp: ffffffff81793d38 r8: 0000000008000000 (XEN) r9: 4000000000000000 r10: 0000000000000000 r11: ffffffff81db7000 (XEN) r12: 0000000000000ff8 r13: ffffffff81df1ff8 r14: ffffffff81db6000 (XEN) r15: 0000000000000ff8 cr0: 000000008005003b cr4: 00000000000026f0 (XEN) cr3: 0000000661795000 cr2: 0000000000000000 Fixes-Oracle-Bug: 14570662 CC: stable@vger.kernel.org # only for v3.5 Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/p2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index d4b255463253..76ba0e97e530 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -599,7 +599,7 @@ bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_ if (p2m_index(set_pfn)) return false; - for (pfn = 0; pfn <= MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) { + for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) { topidx = p2m_top_index(pfn); if (!p2m_top[topidx]) From 9c2fc0de1a6e638fe58c354a463f544f42a90a09 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 5 Sep 2012 15:48:23 +0200 Subject: [PATCH 354/665] udf: Fix data corruption for files in ICB When a file is stored in ICB (inode), we overwrite part of the file, and the page containing file's data is not in page cache, we end up corrupting file's data by overwriting them with zeros. The problem is we use simple_write_begin() which simply zeroes parts of the page which are not written to. The problem has been introduced by be021ee4 (udf: convert to new aops). Fix the problem by providing a ->write_begin function which makes the page properly uptodate. CC: # >= 2.6.24 Reported-by: Ian Abbott Signed-off-by: Jan Kara --- fs/udf/file.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/fs/udf/file.c b/fs/udf/file.c index 7f3f7ba3df6e..d1c6093fd3d3 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -39,20 +39,24 @@ #include "udf_i.h" #include "udf_sb.h" -static int udf_adinicb_readpage(struct file *file, struct page *page) +static void __udf_adinicb_readpage(struct page *page) { struct inode *inode = page->mapping->host; char *kaddr; struct udf_inode_info *iinfo = UDF_I(inode); - BUG_ON(!PageLocked(page)); - kaddr = kmap(page); - memset(kaddr, 0, PAGE_CACHE_SIZE); memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); + memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size); flush_dcache_page(page); SetPageUptodate(page); kunmap(page); +} + +static int udf_adinicb_readpage(struct file *file, struct page *page) +{ + BUG_ON(!PageLocked(page)); + __udf_adinicb_readpage(page); unlock_page(page); return 0; @@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page, return 0; } +static int udf_adinicb_write_begin(struct file *file, + struct address_space *mapping, loff_t pos, + unsigned len, unsigned flags, struct page **pagep, + void **fsdata) +{ + struct page *page; + + if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE)) + return -EIO; + page = grab_cache_page_write_begin(mapping, 0, flags); + if (!page) + return -ENOMEM; + *pagep = page; + + if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) + __udf_adinicb_readpage(page); + return 0; +} + static int udf_adinicb_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, @@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct file *file, const struct address_space_operations udf_adinicb_aops = { .readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, - .write_begin = simple_write_begin, - .write_end = udf_adinicb_write_end, + .write_begin = udf_adinicb_write_begin, + .write_end = udf_adinicb_write_end, }; static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, From 7ce8c7a3433c6d6f4adfec0611d250782f0b4b0c Mon Sep 17 00:00:00 2001 From: LEO Airwarosu Yoichi Shinoda Date: Mon, 27 Aug 2012 22:28:16 +0900 Subject: [PATCH 355/665] mac80211: Various small fixes for cfg.c: mpath_set_pinfo() Various small fixes for net/mac80211/cfg.c:mpath_set_pinfo(): Initialize *pinfo before filling members in, handle MESH_PATH_RESOLVED correctly, and remove bogus assignment; result in correct display of FLAGS values and meaningful EXPTIME for expired paths in iw utility. Signed-off-by: Yoichi Shinoda Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d41974aacf51..a58c0b649ba1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1378,6 +1378,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, else memset(next_hop, 0, ETH_ALEN); + memset(pinfo, 0, sizeof(*pinfo)); + pinfo->generation = mesh_paths_generation; pinfo->filled = MPATH_INFO_FRAME_QLEN | @@ -1396,7 +1398,6 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, pinfo->discovery_timeout = jiffies_to_msecs(mpath->discovery_timeout); pinfo->discovery_retries = mpath->discovery_retries; - pinfo->flags = 0; if (mpath->flags & MESH_PATH_ACTIVE) pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; if (mpath->flags & MESH_PATH_RESOLVING) @@ -1405,10 +1406,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID; if (mpath->flags & MESH_PATH_FIXED) pinfo->flags |= NL80211_MPATH_FLAG_FIXED; - if (mpath->flags & MESH_PATH_RESOLVING) - pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; - - pinfo->flags = mpath->flags; + if (mpath->flags & MESH_PATH_RESOLVED) + pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED; } static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, From ce7184bdbd38d920fb515266fbbdc585ad2e5493 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Fri, 24 Aug 2012 08:55:13 +0000 Subject: [PATCH 356/665] xen: fix logical error in tlb flushing While TLB_FLUSH_ALL gets passed as 'end' argument to flush_tlb_others(), the Xen code was made to check its 'start' parameter. That may give a incorrect op.cmd to MMUEXT_INVLPG_MULTI instead of MMUEXT_TLB_FLUSH_MULTI. Then it causes some page can not be flushed from TLB. This patch fixed this issue. Reported-by: Jan Beulich Signed-off-by: Alex Shi Acked-by: Jan Beulich Tested-by: Yongjie Ren Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index b65a76133f4f..5141d808e751 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1283,7 +1283,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask)); args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; - if (start != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) { + if (end != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) { args->op.cmd = MMUEXT_INVLPG_MULTI; args->op.arg1.linear_addr = start; } From b5031ed1be0aa419250557123633453753181643 Mon Sep 17 00:00:00 2001 From: Ronny Hegewald Date: Fri, 31 Aug 2012 09:57:52 +0000 Subject: [PATCH 357/665] xen: Use correct masking in xen_swiotlb_alloc_coherent. When running 32-bit pvops-dom0 and a driver tries to allocate a coherent DMA-memory the xen swiotlb-implementation returned memory beyond 4GB. The underlaying reason is that if the supplied driver passes in a DMA_BIT_MASK(64) ( hwdev->coherent_dma_mask is set to 0xffffffffffffffff) our dma_mask will be u64 set to 0xffffffffffffffff even if we set it to DMA_BIT_MASK(32) previously. Meaning we do not reset the upper bits. By using the dma_alloc_coherent_mask function - it does the proper casting and we get 0xfffffffff. This caused not working sound on a system with 4 GB and a 64-bit compatible sound-card with sets the DMA-mask to 64bit. On bare-metal and the forward-ported xen-dom0 patches from OpenSuse a coherent DMA-memory is always allocated inside the 32-bit address-range by calling dma_alloc_coherent_mask. This patch adds the same functionality to xen swiotlb and is a rebase of the original patch from Ronny Hegewald which never got upstream b/c the underlaying reason was not understood until now. The original email with the original patch is in: http://old-list-archives.xen.org/archives/html/xen-devel/2010-02/msg00038.html the original thread from where the discussion started is in: http://old-list-archives.xen.org/archives/html/xen-devel/2010-01/msg00928.html Signed-off-by: Ronny Hegewald Signed-off-by: Stefano Panella Acked-By: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk CC: stable@vger.kernel.org --- drivers/xen/swiotlb-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 1afb4fba11b4..4d519488d304 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, return ret; if (hwdev && hwdev->coherent_dma_mask) - dma_mask = hwdev->coherent_dma_mask; + dma_mask = dma_alloc_coherent_mask(hwdev, flags); phys = virt_to_phys(ret); dev_addr = xen_phys_to_bus(phys); From da25186fc605af8ad636073621fa326fbc23a130 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Wed, 22 Aug 2012 20:26:31 -0700 Subject: [PATCH 358/665] mwifiex: fix skb length issue when send a command to firmware When we send a command to firmware, we assumed that cmd_size will be always less than or equal to the structure size of host_cmd_ds_command. However, this is no longer true after we added AP support. There are some AP commands that Custom IE TLVs are included in command buffer, hence the cmd_size gets enlarged by the TLV data. We need to increase the skb length for the extra data. Signed-off-by: Stone Piao Signed-off-by: Avinash Patil Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index c68adec3cc8b..565527aee0ea 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, cmd_code = le16_to_cpu(host_cmd->command); cmd_size = le16_to_cpu(host_cmd->size); - skb_trim(cmd_node->cmd_skb, cmd_size); + /* Adjust skb length */ + if (cmd_node->cmd_skb->len > cmd_size) + /* + * cmd_size is less than sizeof(struct host_cmd_ds_command). + * Trim off the unused portion. + */ + skb_trim(cmd_node->cmd_skb, cmd_size); + else if (cmd_node->cmd_skb->len < cmd_size) + /* + * cmd_size is larger than sizeof(struct host_cmd_ds_command) + * because we have appended custom IE TLV. Increase skb length + * accordingly. + */ + skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); do_gettimeofday(&tstamp); dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," From d0f21fe6585dda550b279ceccd2609111d7f1baa Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 27 Aug 2012 00:26:37 +0200 Subject: [PATCH 359/665] rt2x00: fix voltage setting for RT3572/RT3592 According to the vendor driver v2.6.0.1, during the rf register init the SRAM voltage should be increased to 1.35V and after 1ms decreased back to 1.2V. This patch adds the field setting of LDO_CFG0_LDO_CORE_VLEVEL accordingly. Cc: Gertjan van Wingerde Signed-off-by: Marc Kleine-Budde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index cb8c2aca54e4..b93516d832fb 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4089,6 +4089,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, LDO_CFG0, reg); msleep(1); rt2800_register_read(rt2x00dev, LDO_CFG0, ®); + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); rt2800_register_write(rt2x00dev, LDO_CFG0, reg); } From 280b9a9de19b0819dcf1ab38c88e37bb82dbea0c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:03 +0200 Subject: [PATCH 360/665] ath9k_hw: do not enable the MIB interrupt in the interrupt mask register The interrupt is no longer handling it. While it shouldn't fire (wraparound is highly unlikely), the consequences would be fatal (interrupt storm). Disable the interrupt to prevent that from happening. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 60b6a9daff7e..d95474ecb6c9 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -978,9 +978,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, else imr_reg |= AR_IMR_TXOK; - if (opmode == NL80211_IFTYPE_AP) - imr_reg |= AR_IMR_MIB; - ENABLE_REGWRITE_BUFFER(ah); REG_WRITE(ah, AR_IMR, imr_reg); From 26228959938b25bd41311a3f133a695b9da60e72 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:04 +0200 Subject: [PATCH 361/665] ath9k_hw: clear the AM2PM predistortion mask on AR933x That predistortion type is not supported Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2c9f7d7ed4cc..2173bd75dd21 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah) }; int training_power; int i, val; + u32 am2pm_mask = ah->paprd_ratemask; if (IS_CHAN_2GHZ(ah->curchan)) training_power = ar9003_get_training_power_2g(ah); @@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah) } ah->paprd_training_power = training_power; + if (AR_SREV_9330(ah)) + am2pm_mask = 0; + REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, ah->paprd_ratemask); REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, - ah->paprd_ratemask); + am2pm_mask); REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ah->paprd_ratemask_ht40); From 381c726c09bb43aea8088ede5ce24eaa158289dc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:05 +0200 Subject: [PATCH 362/665] ath9k_hw: calibrate PA input for PA predistortion Re-train if the calibrated PA linearization curve is out of bounds (affects AR933x and AR9485). Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 99 +++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_phy.h | 4 + drivers/net/wireless/ath/ath9k/link.c | 9 +- 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2173bd75dd21..0ed3846f9cbb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -786,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) } EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); +static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah, + struct ath9k_hw_cal_data *caldata, + int chain) +{ + u32 *pa_in = caldata->pa_table[chain]; + int capdiv_offset, quick_drop_offset; + int capdiv2g, quick_drop; + int count = 0; + int i; + + if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah)) + return false; + + capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, + AR_PHY_65NM_CH0_TXRF3_CAPDIV2G); + + quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP); + + if (quick_drop) + quick_drop -= 0x40; + + for (i = 0; i < NUM_BIN + 1; i++) { + if (pa_in[i] == 1400) + count++; + } + + if (AR_SREV_9485(ah)) { + if (pa_in[23] < 800) { + capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150); + capdiv2g += capdiv_offset; + if (capdiv2g > 7) { + capdiv2g = 7; + if (pa_in[23] < 600) { + quick_drop++; + if (quick_drop > 0) + quick_drop = 0; + } + } + } else if (pa_in[23] == 1400) { + quick_drop_offset = min_t(int, count / 3, 2); + quick_drop += quick_drop_offset; + capdiv2g += quick_drop_offset / 2; + + if (capdiv2g > 7) + capdiv2g = 7; + + if (quick_drop > 0) { + quick_drop = 0; + capdiv2g -= quick_drop_offset; + if (capdiv2g < 0) + capdiv2g = 0; + } + } else { + return false; + } + } else if (AR_SREV_9330(ah)) { + if (pa_in[23] < 1000) { + capdiv_offset = (1000 - pa_in[23]) / 100; + capdiv2g += capdiv_offset; + if (capdiv_offset > 3) { + capdiv_offset = 1; + quick_drop--; + } + + capdiv2g += capdiv_offset; + if (capdiv2g > 6) + capdiv2g = 6; + if (quick_drop < -4) + quick_drop = -4; + } else if (pa_in[23] == 1400) { + if (count > 3) { + quick_drop++; + capdiv2g -= count / 4; + if (quick_drop > -2) + quick_drop = -2; + } else { + capdiv2g--; + } + + if (capdiv2g < 0) + capdiv2g = 0; + } else { + return false; + } + } + + REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, + AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, + quick_drop); + + return true; +} + int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_hw_cal_data *caldata, int chain) { @@ -821,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah, if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) status = -2; + if (ar9003_paprd_retrain_pa_in(ah, caldata, chain)) + status = -EINPROGRESS; + REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 7bfbaf065a43..84d3d4956861 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -625,6 +625,10 @@ #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0) #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc) +#define AR_PHY_65NM_CH0_TXRF3 0x16048 +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1 + #define AR_PHY_65NM_CH0_SYNTH4 0x1608c #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002) #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1) diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index d4549e9aac5c..1c241921f95e 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -254,6 +254,7 @@ void ath_paprd_calibrate(struct work_struct *work) int chain_ok = 0; int chain; int len = 1800; + int ret; if (!caldata) return; @@ -302,7 +303,13 @@ void ath_paprd_calibrate(struct work_struct *work) break; } - if (ar9003_paprd_create_curve(ah, caldata, chain)) { + ret = ar9003_paprd_create_curve(ah, caldata, chain); + if (ret == -EINPROGRESS) { + ath_dbg(common, CALIBRATE, + "PAPRD curve on chain %d needs to be re-trained\n", + chain); + break; + } else if (ret) { ath_dbg(common, CALIBRATE, "PAPRD create curve failed on chain %d\n", chain); From 1630d25fd00f195f0923d4b895e0529fdbba83c3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:06 +0200 Subject: [PATCH 363/665] ath9k_hw: disable PA linearization for AR9462 Support for it is incomplete Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d95474ecb6c9..64a00d2f18f2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2499,7 +2499,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); if (!ah->config.paprd_disable && - ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) + ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && + !AR_SREV_9462(ah)) pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); From 51dea9be7e01d7e825ed1882246693f09c21374c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:07 +0200 Subject: [PATCH 364/665] ath9k: fix PA linearization calibration related crash Before PAPRD training can run, the card needs to have sent a packet for thermal calibration. Sending a dummy packet with the PAPRD training flag set causes a crash under some circumstance. Fix the code by replacing the dummy tx with a delay that waits for a real packet tx to have occurred. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 ++ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/link.c | 9 +-------- drivers/net/wireless/ath/ath9k/xmit.c | 3 +++ 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 64a00d2f18f2..e4b9f35343e5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1775,6 +1775,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, /* Operating channel changed, reset channel calibration data */ memset(caldata, 0, sizeof(*caldata)); ath9k_init_nfcal_hist_buffer(ah, chan); + } else if (caldata) { + caldata->paprd_packet_sent = false; } ah->noise = ath9k_hw_getchan_noise(ah, chan); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ce7332c64efb..6599a75f01fe 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -405,6 +405,7 @@ struct ath9k_hw_cal_data { int8_t iCoff; int8_t qCoff; bool rtt_done; + bool paprd_packet_sent; bool paprd_done; bool nfcal_pending; bool nfcal_interference; diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 1c241921f95e..825a29cc9313 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -256,7 +256,7 @@ void ath_paprd_calibrate(struct work_struct *work) int len = 1800; int ret; - if (!caldata) + if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done) return; ath9k_ps_wakeup(sc); @@ -283,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work) continue; chain_ok = 0; - - ath_dbg(common, CALIBRATE, - "Sending PAPRD frame for thermal measurement on chain %d\n", - chain); - if (!ath_paprd_send_frame(sc, skb, chain)) - goto fail_paprd; - ar9003_paprd_setup_gain_table(ah, chain); ath_dbg(common, CALIBRATE, diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c9da6b2ecb1..0d4155aec48d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2018,6 +2018,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); + if (sc->sc_ah->caldata) + sc->sc_ah->caldata->paprd_packet_sent = true; + if (!(tx_flags & ATH_TX_ERROR)) /* Frame was ACKed */ tx_info->flags |= IEEE80211_TX_STAT_ACK; From b3ccc1a56280119fe1fbf9929a76b4034358bfef Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:08 +0200 Subject: [PATCH 365/665] ath9k_hw: enable PA linearization This feature had been disabled in ath9k because the code to support it was incomplete, but now the code is in sync with the internal QCA codebase, so it's time to enable it. On many newer devices, the calibration is assumed to be done with PA linearization enabled. Tests with a particular AR933x device showed that the signal emitted at full power was highly distorted and unreliable with PA linearization disabled. With this patch, the signal becomes clear and stability is improved. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e4b9f35343e5..48af40151d23 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } - /* PAPRD needs some more work to be enabled */ - ah->config.paprd_disable = 1; - ah->config.rx_intr_mitigation = true; ah->config.pcieSerDesWrite = true; From 5d9b6f263995d7f43202d76cf2e23d43f9240a90 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 28 Aug 2012 12:14:48 +0530 Subject: [PATCH 366/665] ath9k: Fix a crash in 2 WIRE btcoex chipsets Generic timers for BTCOEX functionality is applicable only for 3 WIRE BTCOEX (and MCI) chipsets. Hence btcoex->no_stomp_timer is allocated only 3 WIRE btcoex chipsets and in all the other cases its NULL. Make sure we stop the generic timer only if 'btcoex->hw_timer_enabled' is true(only if its up and running) Fixes the following crash [68757.020454] BUG: unable to handle kernel NULL pointer dereference at 0000000c [68757.020916] IP: [] ath9k_hw_gen_timer_stop+0x13/0x80 [ath9k_hw] [68757.021251] *pde = 00000000 [68757.024384] EIP: 0060:[] EFLAGS: 00010082 CPU: 0 [68757.024384] EIP is at ath9k_hw_gen_timer_stop+0x13/0x80 [ath9k_hw] [68757.024384] EAX: d32d0000 EBX: d32d0000 ECX: 00000000 EDX: 00000000 [68757.024384] ESI: e67c24c0 EDI: 00000296 EBP: e137be2c ESP: e137be20 [68757.024384] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [68757.024384] CR0: 8005003b CR2: 0000000c CR3: 00b99000 CR4: 000407d0 [68757.024384] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [68757.024384] DR6: ffff0ff0 DR7: 00000400 [68757.024384] Process kworker/u:2 (pid: 8917, ti=e137a000 task=ea7a6860 task.ti=e137a000) [68757.024384] Stack: [68757.024384] c06c4676 d32d0000 e67c24c0 e137be38 f81c9590 e67c1ca0 e137be40 f81c95d9 [68757.024384] e137be64 f81cd1c5 00000246 00000002 d32d0000 e67c05e0 e67c1ca0 e67c05e0 [68757.024384] 00000000 e137beac f81cdfa0 e137be84 00000246 00000246 e67c1ca0 e67c1ca0 [68757.024384] Call Trace: [68757.024384] [] ? _raw_spin_lock_irqsave+0x86/0xa0 [68757.024384] [] ath9k_gen_timer_stop+0x10/0x40 [ath9k] [68757.024384] [] ath9k_btcoex_stop_gen_timer+0x19/0x20 [ath9k] [68757.024384] [] ath9k_ps_restore+0x85/0x110 [ath9k] [68757.024384] [] ath9k_config+0x220/0x520 [ath9k] [68757.024384] [] ? ath9k_flush+0x15d/0x1b0 [ath9k] [68757.024384] [] ieee80211_hw_config+0x135/0x2c0 [mac80211] [68757.024384] [] ieee80211_dynamic_ps_enable_work+0x198/0x5f0 [mac80211] Cc: Rajkumar Manoharan Cc: Bala Shanmugam Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index bacdb8fb4ef4..9f83f71742a5 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -341,7 +341,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) { struct ath_btcoex *btcoex = &sc->btcoex; - ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); } u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) From 01e3331b30b48fe96d016435707af050700c8421 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 30 Aug 2012 10:05:34 +0200 Subject: [PATCH 367/665] brcmfmac: fix use of dev_kfree_skb() in irq context The USB part of the brcmfmac did a dev_kfree_skb() that resulted in a warning in net/core/skbuff.c: Jul 11 04:53:33 lb-bun-10 kernel: [53282.667745] WARNING: at net/core/skbuff.c:490 skb_release_head_state+0xcc/0xe0() The brcmutil modules provides brcmu_pkt_buf_free_skb() which takes the context into account. This patch makes use of this function instead of dev_kfree_skb(). Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a299d42da8e7..f72dfb70ba0b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb) else devinfo->bus_pub.bus->dstats.tx_errors++; - dev_kfree_skb(req->skb); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); @@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) devinfo->bus_pub.bus->dstats.rx_packets++; } else { devinfo->bus_pub.bus->dstats.rx_errors++; - dev_kfree_skb(skb); + brcmu_pkt_buf_free_skb(skb); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); return; } @@ -556,7 +556,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) brcmf_usb_rx_refill(devinfo, req); } } else { - dev_kfree_skb(skb); + brcmu_pkt_buf_free_skb(skb); } return; @@ -588,7 +588,7 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, if (ret == 0) { brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); } else { - dev_kfree_skb(req->skb); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); } From 474ab7cea4001f07ec8599a680fd19d8761fa7d8 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 30 Aug 2012 10:05:35 +0200 Subject: [PATCH 368/665] brcmfmac: dont use ZERO flag for usb IN URB_ZERO_PACKET should only be set or bulk OUT and this condition is checked with a WARN_ON in usb_submit_urb(). This patch fixes brcmfmac to get rid of this warning filling the logs. Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index f72dfb70ba0b..8ea2db7326b8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -581,7 +581,6 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe, skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, req); - req->urb->transfer_flags |= URB_ZERO_PACKET; req->devinfo = devinfo; ret = usb_submit_urb(req->urb, GFP_ATOMIC); From 2e875acd399fcc6e301063e5ead371ad089d5920 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 30 Aug 2012 10:05:36 +0200 Subject: [PATCH 369/665] brcmfmac: fix race condition for rx and tx data. On both rx and tx there is was a race condition on the queueing of usb requests. When for example frame gets submitted it is possible that complete function gets called even before usb_submit_urb() returns. As a result it is possible that usb requests get losts, which was noticed on OMAP4 pandaboard platform. This patch fixes the race condition. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 8ea2db7326b8..58f89fa9c9f8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -550,6 +550,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { brcmf_dbg(ERROR, "rx protocol error\n"); brcmu_pkt_buf_free_skb(skb); + brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); devinfo->bus_pub.bus->dstats.rx_errors++; } else { brcmf_rx_packet(devinfo->dev, ifidx, skb); @@ -557,6 +558,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) } } else { brcmu_pkt_buf_free_skb(skb); + brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); } return; @@ -582,11 +584,11 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, req); req->devinfo = devinfo; + brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (ret == 0) { - brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); - } else { + if (ret) { + brcmf_usb_del_fromq(devinfo, req); brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); @@ -682,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq); if (!req) { + brcmu_pkt_buf_free_skb(skb); brcmf_dbg(ERROR, "no req to send\n"); return -ENOMEM; } - if (!req->urb) { - brcmf_dbg(ERROR, "no urb for req %p\n", req); - return -ENOBUFS; - } req->skb = skb; req->devinfo = devinfo; usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe, skb->data, skb->len, brcmf_usb_tx_complete, req); req->urb->transfer_flags |= URB_ZERO_PACKET; + brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (!ret) { - brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); - } else { + if (ret) { + brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n"); + brcmf_usb_del_fromq(devinfo, req); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); } From 7f6c562dfa52425a28933982df7d21edba7e3d71 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 30 Aug 2012 10:05:37 +0200 Subject: [PATCH 370/665] brcmfmac: fix get rssi by clearing getvar struct. The function brcmf_cfg80211_get_station requests the RSSI from the device. The complete structure used needs to be cleared before sending the request to firmware. Otherwise the request fails filling the logs with "Could not get rssi (-2)" messages. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 28c5fbb4af26..c36e92312443 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -1876,16 +1876,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, } if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { - scb_val.val = cpu_to_le32(0); + memset(&scb_val, 0, sizeof(scb_val)); err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, sizeof(struct brcmf_scb_val_le)); - if (err) + if (err) { WL_ERR("Could not get rssi (%d)\n", err); - - rssi = le32_to_cpu(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_CONN("RSSI %d dBm\n", rssi); + } else { + rssi = le32_to_cpu(scb_val.val); + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_CONN("RSSI %d dBm\n", rssi); + } } done: From 177ef8360fabdc49ff08d2598c06e7f7a36b53e3 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:09 +0200 Subject: [PATCH 371/665] rt2x00: Identify ASUS USB-N53 device. This is an RT3572 based device. Signed-off-by: Maximilian Engelhardt Signed-off-by: Gertjan van Wingerde Cc: Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6cf336595e25..6681bfc03201 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1157,6 +1157,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1690, 0x0744) }, { USB_DEVICE(0x1690, 0x0761) }, { USB_DEVICE(0x1690, 0x0764) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x179d) }, /* Cisco */ { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ @@ -1222,7 +1224,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, - { USB_DEVICE(0x0b05, 0x179d) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, From 6ced58a5dbb94dbfbea1b33ca3c56d1e929cd548 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:10 +0200 Subject: [PATCH 372/665] rt2x00: Fix word size of rt2500usb MAC_CSR19 register. The register is 16 bits wide, not 32. Signed-off-by: Gertjan van Wingerde Cc: Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3aae36bb0a9e..b3a1d732f3d1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u16 reg; rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field32(reg, MAC_CSR19_BIT7); + return rt2x00_get_field16(reg, MAC_CSR19_BIT7); } #ifdef CONFIG_RT2X00_LIB_LEDS diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7eed..192531db0b65 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,14 @@ * MAC_CSR19: GPIO control register. */ #define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD32(0x0001) -#define MAC_CSR19_BIT1 FIELD32(0x0002) -#define MAC_CSR19_BIT2 FIELD32(0x0004) -#define MAC_CSR19_BIT3 FIELD32(0x0008) -#define MAC_CSR19_BIT4 FIELD32(0x0010) -#define MAC_CSR19_BIT5 FIELD32(0x0020) -#define MAC_CSR19_BIT6 FIELD32(0x0040) -#define MAC_CSR19_BIT7 FIELD32(0x0080) +#define MAC_CSR19_BIT0 FIELD16(0x0001) +#define MAC_CSR19_BIT1 FIELD16(0x0002) +#define MAC_CSR19_BIT2 FIELD16(0x0004) +#define MAC_CSR19_BIT3 FIELD16(0x0008) +#define MAC_CSR19_BIT4 FIELD16(0x0010) +#define MAC_CSR19_BIT5 FIELD16(0x0020) +#define MAC_CSR19_BIT6 FIELD16(0x0040) +#define MAC_CSR19_BIT7 FIELD16(0x0080) /* * MAC_CSR20: LED control register. From a396e10019eaf3809b0219c966865aaafec12630 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:11 +0200 Subject: [PATCH 373/665] rt2x00: Fix rfkill polling prior to interface start. We need to program the rfkill switch GPIO pin direction to input at device initialization time, not only when the interface is brought up. Doing this only when the interface is brought up could lead to rfkill detecting the switch is turned on erroneously and inability to create the interface and bringing it up. Reported-and-tested-by: Andreas Messer Signed-off-by: Gertjan van Wingerde Cc: Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2400pci.h | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2500usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2500usb.h | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2800usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt61pci.h | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt73usb.h | 3 +++ 11 files changed, 69 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 8b9dbd76a252..64328af496f5 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_BIT8, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc439..7564ae992b73 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@ #define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_BIT7 FIELD32(0x00000080) +#define GPIOCSR_BIT8 FIELD32(0x00000100) /* * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d2cf8a4bc8b5..3de0406735f6 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_DIR0, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index b3a1d732f3d1..89fee311d8fd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u16 reg; /* * Allocate eeprom data. @@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 192531db0b65..196bd5103e4f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -197,6 +197,7 @@ #define MAC_CSR19_BIT5 FIELD16(0x0020) #define MAC_CSR19_BIT6 FIELD16(0x0040) #define MAC_CSR19_BIT7 FIELD16(0x0080) +#define MAC_CSR19_BIT8 FIELD16(0x0100) /* * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 98aa426a3564..4765bbd654cd 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -983,6 +983,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -995,6 +996,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6681bfc03201..52a32b5baea0 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -736,6 +736,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -748,6 +749,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3f7bc5cadf9a..b8ec96163922 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Disable power saving. @@ -2849,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0e..8f3da5a56766 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ba6e434b859d..248436c13ce0 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d3..df1cc116b83b 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) +#define MAC_CSR13_BIT14 FIELD32(0x00004000) +#define MAC_CSR13_BIT15 FIELD32(0x00008000) /* * MAC_CSR14: LED control register. From efd5d6b03bd9c9e0df646c56fb5f4f3e25e5c1ac Mon Sep 17 00:00:00 2001 From: Sergei Poselenov Date: Sun, 2 Sep 2012 13:14:32 +0400 Subject: [PATCH 374/665] rt2800usb: Added rx packet length validity check On our system (ARM Cortex-M3 SOC running linux-2.6.33) frequent crashes were observed in the rt2800usb module because of the invalid length of the received packet (3392, 46920...). This patch adds the sanity check on the packet legth. Also, changed WARNING to ERROR in rt2x00lib_rxdone() so that the bad packet condition would be noticed. The fix was tested on the latest compat-wireless-3.5.1-1-snpc. Cc: stable@vger.kernel.org Signed-off-by: Sergei Poselenov Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 10 +++++++++- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 52a32b5baea0..6b4226b71618 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, skb_pull(entry->skb, RXINFO_DESC_SIZE); /* - * FIXME: we need to check for rx_pkt_len validity + * Check for rx_pkt_len validity. Return if invalid, leaving + * rxdesc->size zeroed out by the upper level. */ + if (unlikely(rx_pkt_len == 0 || + rx_pkt_len > entry->queue->data_size)) { + ERROR(entry->queue->rt2x00dev, + "Bad frame size %d, forcing to 0\n", rx_pkt_len); + return; + } + rxd = (__le32 *)(entry->skb->data + rx_pkt_len); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a6b88bd4a1a5..3f07e36f462b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp) */ if (unlikely(rxdesc.size == 0 || rxdesc.size > entry->queue->data_size)) { - WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", + ERROR(rt2x00dev, "Wrong frame size %d max %d.\n", rxdesc.size, entry->queue->data_size); dev_kfree_skb(entry->skb); goto renew_skb; From f10723841e624c0726c70356b31d91befed01dd6 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 3 Sep 2012 15:49:09 -0400 Subject: [PATCH 375/665] libertas sdio: fix suspend when interface is down When the interface is down, the hardware is powered off. However, the suspend handler currently tries to send host sleep commands (when wakeup params are set) in this configuration, causing a system hang when going into suspend (the commands will never complete). Avoid this by detecting this situation and simply returning from the suspend handler without doing anything special. Signed-off-by: Daniel Drake Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index e970897f6ab5..4cb234349fbf 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev) mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); + /* If we're powered off anyway, just let the mmc layer remove the + * card. */ + if (!lbs_iface_active(card->priv)) + return -ENOSYS; + dev_info(dev, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), flags); From 6d7d9798ad5c97ee4e911dd070dc12dc5ae55bd0 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 29 Aug 2012 16:58:45 -0500 Subject: [PATCH 376/665] staging: zcache: fix cleancache race condition with shrinker This patch fixes a race condition that results in memory corruption when using cleancache. The race exists between the zcache shrinker handler, shrink_zcache_memory() and cleancache_get_page(). In most cases, the shrinker will both evict a zbpg from its buddy list and flush it from tmem before a cleancache_get_page() occurs on that page. A subsequent cleancache_get_page() will fail in the tmem layer. In the rare case that two occur together and the cleancache_get_page() path gets through the tmem layer before the shrinker path can flush tmem, zbud_decompress() does a check to see if the zbpg is a "zombie", i.e. not on a buddy list, which means the shrinker is in the process of reclaiming it. If the zbpg is a zombie, zbud_decompress() returns -EINVAL. However, this return code is being ignored by the caller, zcache_pampd_get_data_and_free(), which results in the caller of cleancache_get_page() thinking that the page has been properly retrieved when it has not. This patch modifies zcache_pampd_get_data_and_free() to convey the failure up the stack so that the caller of cleancache_get_page() knows the page retrieval failed. This needs to be applied to stable trees as well. zcache-main.c was named zcache.c before v3.1, so I'm not sure how you want to handle trees earlier than that. Signed-off-by: Seth Jennings Cc: stable Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Minchan Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index c214977b4ab4..52b43b7b83d7 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1251,13 +1251,12 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, void *pampd, struct tmem_pool *pool, struct tmem_oid *oid, uint32_t index) { - int ret = 0; - BUG_ON(!is_ephemeral(pool)); - zbud_decompress((struct page *)(data), pampd); + if (zbud_decompress((struct page *)(data), pampd) < 0) + return -EINVAL; zbud_free_and_delist((struct zbud_hdr *)pampd); atomic_dec(&zcache_curr_eph_pampd_count); - return ret; + return 0; } /* From 052c7f9ffb0e95843e75448d02664459253f9ff8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 13 Aug 2012 19:57:03 +0300 Subject: [PATCH 377/665] xhci: Fix a logical vs bitwise AND bug The intent was to test whether the flag was set. This patch should be backported to stable kernels as old as 3.0, since it fixes a bug in commit e95829f474f0db3a4d940cae1423783edd966027 "xhci: Switch PPT ports to EHCI on shutdown.", which was marked for stable. Signed-off-by: Dan Carpenter Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c59d5b5b6c7d..617b0a77b2b4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -659,7 +659,7 @@ void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - if (xhci->quirks && XHCI_SPURIOUS_REBOOT) + if (xhci->quirks & XHCI_SPURIOUS_REBOOT) usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); spin_lock_irq(&xhci->lock); From e955a1cd086de4d165ae0f4c7be7289d84b63bdc Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 14 Aug 2012 16:44:49 -0400 Subject: [PATCH 378/665] xhci: Make handover code more robust My test platform (Intel DX79SI) boots reliably under BIOS, but frequently crashes when booting via UEFI. I finally tracked this down to the xhci handoff code. It seems that reads from the device occasionally just return 0xff, resulting in xhci_find_next_cap_offset generating a value that's larger than the resource region. We then oops when attempting to read the value. Sanity checking that value lets us avoid the crash. I've no idea what's causing the underlying problem, and xhci still doesn't actually *work* even with this, but the machine at least boots which will probably make further debugging easier. This should be backported to kernels as old as 2.6.31, that contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: BIOS handoff and HW initialization." Signed-off-by: Matthew Garrett Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 20b9f45f931c..966d1484ee79 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -841,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) void __iomem *op_reg_base; u32 val; int timeout; + int len = pci_resource_len(pdev, 0); if (!mmio_resource_enabled(pdev, 0)) return; - base = ioremap_nocache(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + base = ioremap_nocache(pci_resource_start(pdev, 0), len); if (base == NULL) return; @@ -856,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) */ ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); do { + if ((ext_cap_offset + sizeof(val)) > len) { + /* We're reading garbage from the controller */ + dev_warn(&pdev->dev, + "xHCI controller failing to respond"); + return; + } + if (!ext_cap_offset) /* We've reached the end of the extended capabilities */ goto hc_init; + val = readl(base + ext_cap_offset); if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) break; From 71c731a296f1b08a3724bd1b514b64f1bda87a23 Mon Sep 17 00:00:00 2001 From: "Alexis R. Cortes" Date: Fri, 3 Aug 2012 14:00:27 -0500 Subject: [PATCH 379/665] usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware This patch is intended to work around a known issue on the SN65LVPE502CP USB3.0 re-driver that can delay the negotiation between a device and the host past the usual handshake timeout. If that happens on the first insertion, the host controller port will enter in Compliance Mode and NO port status event will be generated (as per xHCI Spec) making impossible to detect this event by software. The port will remain in compliance mode until a warm reset is applied to it. As a result of this, the port will seem "dead" to the user and no device connections or disconnections will be detected. For solving this, the patch creates a timer which polls every 2 seconds the link state of each host controller's port (this by reading the PORTSC register) and recovers the port by issuing a Warm reset every time Compliance mode is detected. If a xHC USB3.0 port has previously entered to U0, the compliance mode issue will NOT occur only until system resumes from sleep/hibernate, therefore, the compliance mode timer is stopped when all xHC USB 3.0 ports have entered U0. The timer is initialized again after each system resume. Since the issue is being caused by a piece of hardware, the timer will be enabled ONLY on those systems that have the SN65LVPE502CP installed (this patch uses DMI strings for detecting those systems) therefore making this patch to act as a quirk (XHCI_COMP_MODE_QUIRK has been added to the xhci stack). This patch applies for these systems: Vendor: Hewlett-Packard. System Models: Z420, Z620 and Z820. This patch should be backported to kernels as old as 3.2, as that was the first kernel to support warm reset. The kernels will need to contain both commit 10d674a82e553cb8a1f41027bb3c3e309b3f6804 "USB: When hot reset for USB3 fails, try warm reset" and commit 8bea2bd37df08aaa599aa361a9f8b836ba98e554 "usb: Add support for root hub port status CAS". The first patch add warm reset support, and the second patch modifies the USB core to issue a warm reset when the port is in compliance mode. Signed-off-by: Alexis R. Cortes Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-hub.c | 42 +++++++++++++ drivers/usb/host/xhci.c | 121 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 6 ++ 3 files changed, 169 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 74bfc868b7ad..d5eb357aa5c4 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg) * when this bit is set. */ pls |= USB_PORT_STAT_CONNECTION; + } else { + /* + * If CAS bit isn't set but the Port is already at + * Compliance Mode, fake a connection so the USB core + * notices the Compliance state and resets the port. + * This resolves an issue generated by the SN65LVPE502CP + * in which sometimes the port enters compliance mode + * caused by a delay on the host-device negotiation. + */ + if (pls == USB_SS_PORT_LS_COMP_MOD) + pls |= USB_PORT_STAT_CONNECTION; } + /* update status field */ *status |= pls; } +/* + * Function for Compliance Mode Quirk. + * + * This Function verifies if all xhc USB3 ports have entered U0, if so, + * the compliance mode timer is deleted. A port won't enter + * compliance mode if it has previously entered U0. + */ +void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) +{ + u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); + bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); + + if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) + return; + + if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { + xhci->port_status_u0 |= 1 << wIndex; + if (xhci->port_status_u0 == all_ports_seen_u0) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n"); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n"); + } + } +} + int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -651,6 +688,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Update Port Link State for super speed ports*/ if (hcd->speed == HCD_USB3) { xhci_hub_report_link_state(&status, temp); + /* + * Verify if all USB3 Ports Have entered U0 already. + * Delete Compliance Mode Timer if so. + */ + xhci_del_comp_mod_timer(xhci, temp, wIndex); } if (bus_state->port_c_suspend & (1 << wIndex)) status |= 1 << USB_PORT_FEAT_C_SUSPEND; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 617b0a77b2b4..6ece0ed288d4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "xhci.h" @@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) #endif +static void compliance_mode_recovery(unsigned long arg) +{ + struct xhci_hcd *xhci; + struct usb_hcd *hcd; + u32 temp; + int i; + + xhci = (struct xhci_hcd *)arg; + + for (i = 0; i < xhci->num_usb3_ports; i++) { + temp = xhci_readl(xhci, xhci->usb3_ports[i]); + if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { + /* + * Compliance Mode Detected. Letting USB Core + * handle the Warm Reset + */ + xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", + i + 1); + xhci_dbg(xhci, "Attempting Recovery routine!\n"); + hcd = xhci->shared_hcd; + + if (hcd->state == HC_STATE_SUSPENDED) + usb_hcd_resume_root_hub(hcd); + + usb_hcd_poll_rh_status(hcd); + } + } + + if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) + mod_timer(&xhci->comp_mode_recovery_timer, + jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +} + +/* + * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver + * that causes ports behind that hardware to enter compliance mode sometimes. + * The quirk creates a timer that polls every 2 seconds the link state of + * each host controller's port and recovers it by issuing a Warm reset + * if Compliance mode is detected, otherwise the port will become "dead" (no + * device connections or disconnections will be detected anymore). Becasue no + * status event is generated when entering compliance mode (per xhci spec), + * this quirk is needed on systems that have the failing hardware installed. + */ +static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) +{ + xhci->port_status_u0 = 0; + init_timer(&xhci->comp_mode_recovery_timer); + + xhci->comp_mode_recovery_timer.data = (unsigned long) xhci; + xhci->comp_mode_recovery_timer.function = compliance_mode_recovery; + xhci->comp_mode_recovery_timer.expires = jiffies + + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS); + + set_timer_slack(&xhci->comp_mode_recovery_timer, + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); + add_timer(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); +} + +/* + * This function identifies the systems that have installed the SN65LVPE502CP + * USB3.0 re-driver and that need the Compliance Mode Quirk. + * Systems: + * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 + */ +static bool compliance_mode_recovery_timer_quirk_check(void) +{ + const char *dmi_product_name, *dmi_sys_vendor; + + dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + + if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) + return false; + + if (strstr(dmi_product_name, "Z420") || + strstr(dmi_product_name, "Z620") || + strstr(dmi_product_name, "Z820")) + return true; + + return false; +} + +static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) +{ + return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1)); +} + + /* * Initialize memory for HCD and xHC (one-time init). * @@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd) retval = xhci_mem_init(xhci, GFP_KERNEL); xhci_dbg(xhci, "Finished xhci_init\n"); + /* Initializing Compliance Mode Recovery Data If Needed */ + if (compliance_mode_recovery_timer_quirk_check()) { + xhci->quirks |= XHCI_COMP_MODE_QUIRK; + compliance_mode_recovery_timer_init(xhci); + } + return retval; } @@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd) del_timer_sync(&xhci->event_ring_timer); #endif + /* Deleting Compliance Mode Recovery Timer */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) + del_timer_sync(&xhci->comp_mode_recovery_timer); + if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_dev_put(); @@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci) } spin_unlock_irq(&xhci->lock); + /* + * Deleting Compliance Mode Recovery Timer because the xHCI Host + * is about to be suspended. + */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); + } + /* step 5: remove core well power */ /* synchronize irq when using MSI-X */ xhci_msix_sync_irqs(xhci); @@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(xhci->shared_hcd); } + + /* + * If system is subject to the Quirk, Compliance Mode Timer needs to + * be re-initialized Always after a system resume. Ports are subject + * to suffer the Compliance Mode issue again. It doesn't matter if + * ports have entered previously to U0 before system's suspension. + */ + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + compliance_mode_recovery_timer_init(xhci); + return retval; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c713256297ac..1a05908c6673 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1495,6 +1495,7 @@ struct xhci_hcd { #define XHCI_LPM_SUPPORT (1 << 11) #define XHCI_INTEL_HOST (1 << 12) #define XHCI_SPURIOUS_REBOOT (1 << 13) +#define XHCI_COMP_MODE_QUIRK (1 << 14) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ @@ -1511,6 +1512,11 @@ struct xhci_hcd { unsigned sw_lpm_support:1; /* support xHCI 1.0 spec USB2 hardware LPM */ unsigned hw_lpm_support:1; + /* Compliance Mode Recovery Data */ + struct timer_list comp_mode_recovery_timer; + u32 port_status_u0; +/* Compliance Mode Timer Triggered every 2 seconds */ +#define COMP_MODE_RCVRY_MSECS 2000 }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ From 319acdfc064169023cd9ada5085b434fbcdacec2 Mon Sep 17 00:00:00 2001 From: Ruchika Kharwar Date: Fri, 10 Aug 2012 09:58:30 +0300 Subject: [PATCH 380/665] usb: host: xhci-plat: use ioremap_nocache Use the ioremap_nocache variant of the ioremap API in order to make sure our memory will be marked uncachable. This patch should be backported to kernels as old as 3.4, that contain the commit 3429e91a661e1f383aecc86c6bbcf65afb15c892 "usb: host: xhci: add platform driver support". Signed-off-by: Ruchika Kharwar Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-plat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 689bc18b051d..df90fe51b4aa 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_hcd; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; From 296365781903226a3fb8758901eaeec09d2798e4 Mon Sep 17 00:00:00 2001 From: Moiz Sonasath Date: Wed, 5 Sep 2012 08:34:26 +0300 Subject: [PATCH 381/665] usb: host: xhci: fix compilation error for non-PCI based stacks For non PCI-based stacks, this function call usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); made from xhci_shutdown is not applicable. Ideally, we wouldn't have any PCI-specific code on a generic driver such as the xHCI stack, but it looks like we should just stub usb_disable_xhci_ports() out for non-PCI devices. [ balbi@ti.com: slight improvement to commit log ] This patch should be backported to kernels as old as 3.0, since the commit it fixes (e95829f474f0db3a4d940cae1423783edd966027 "xhci: Switch PPT ports to EHCI on shutdown.") was marked for stable. Signed-off-by: Moiz Sonasath Signed-off-by: Ruchika Kharwar Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index ef004a5de20f..7f69a39163ce 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} static inline void usb_amd_dev_put(void) {} +static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} #endif /* CONFIG_PCI */ #endif /* __LINUX_USB_PCI_QUIRKS_H */ From 9ec1882df244c4ee1baa692676fef5e8b0f5487d Mon Sep 17 00:00:00 2001 From: Xinyu Chen Date: Mon, 27 Aug 2012 09:36:51 +0200 Subject: [PATCH 382/665] tty: serial: imx: console write routing is unsafe on SMP The console feature's write routing is unsafe on SMP with the startup/shutdown call. There could be several consumers of the console * the kernel printk * the init process using /dev/kmsg to call printk to show log * shell, which open /dev/console and write with sys_write() The shell goes into the normal uart open/write routing, but the other two go into the console operations. The open routing calls imx serial startup, which will write USR1/2 register without any lock and critical with imx_console_write call. Add a spin_lock for startup/shutdown/console_write routing. This patch is a port from Freescale's Android kernel. Signed-off-by: Xinyu Chen Tested-by: Dirk Behme CC: Sascha Hauer Acked-by: Shawn Guo Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d5c689d6217e..908178fc5a33 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -754,6 +754,7 @@ static int imx_startup(struct uart_port *port) } } + spin_lock_irqsave(&sport->port.lock, flags); /* * Finally, clear and enable interrupts */ @@ -807,7 +808,6 @@ static int imx_startup(struct uart_port *port) /* * Enable modem status interrupts */ - spin_lock_irqsave(&sport->port.lock,flags); imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock,flags); @@ -837,10 +837,13 @@ static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; unsigned long temp; + unsigned long flags; + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; @@ -869,12 +872,14 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); if (USE_IRDA(sport)) temp &= ~(UCR1_IREN); writel(temp, sport->port.membase + UCR1); + spin_unlock_irqrestore(&sport->port.lock, flags); } static void @@ -1217,6 +1222,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count) struct imx_port *sport = imx_ports[co->index]; struct imx_port_ucrs old_ucr; unsigned int ucr1; + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); /* * First, save UCR1/2/3 and then disable interrupts @@ -1242,6 +1250,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count) while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); imx_port_ucrs_restore(&sport->port, &old_ucr); + + spin_unlock_irqrestore(&sport->port.lock, flags); } /* From 7be0670f7b9198382938a03ff3db7f47ef6b4780 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Fri, 31 Aug 2012 10:02:47 +0200 Subject: [PATCH 383/665] tty: serial: imx: don't reinit clock in imx_setup_ufcr() Remove the clock configuration from imx_setup_ufcr(). This isn't needed here and will cause garbage output if done. To be be sure that we only touch the bits we want (TXTL and RXTL) we have to mask out all other bits of the UFCR register. Add one non-existing bit macro for this, too (bit 6, DCEDTE on i.MX6). Signed-off-by: Dirk Behme CC: Shawn Guo CC: Sascha Hauer CC: Troy Kisky CC: Xinyu Chen Cc: stable Acked-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 908178fc5a33..e309e8b0aaba 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -132,6 +132,7 @@ #define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ #define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ #define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ +#define UFCR_DCEDTE (1<<6) /* DCE/DTE mode select */ #define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ #define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7) #define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ @@ -667,22 +668,11 @@ static void imx_break_ctl(struct uart_port *port, int break_state) static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) { unsigned int val; - unsigned int ufcr_rfdiv; - - /* set receiver / transmitter trigger level. - * RFDIV is set such way to satisfy requested uartclk value - */ - val = TXTL << 10 | RXTL; - ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2) - / sport->port.uartclk; - - if(!ufcr_rfdiv) - ufcr_rfdiv = 1; - - val |= UFCR_RFDIV_REG(ufcr_rfdiv); + /* set receiver / transmitter trigger level */ + val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE); + val |= TXTL << UFCR_TXTL_SHF | RXTL; writel(val, sport->port.membase + UFCR); - return 0; } From 804d74abe2e3f361ead5c5c6850d5b1ab0203862 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Jul 2012 15:40:07 -0700 Subject: [PATCH 384/665] drm: use drm_compat_ioctl for 32-bit apps Most of the DRM drivers appear to be missing the .compat_ioctl file operation entry necessary for 32-bit application compatibility. This patch uses drm_compat_ioctl for all drivers which don't have their own, and which are using drm_ioctl for .unlocked_ioctl. This leaves drivers/gpu/drm/psb/psb_drv.c unchanged; it has a custom .unlocked_ioctl and will presumably need a custom .compat_ioctl as well. Signed-off-by: Keith Packard Signed-off-by: Dave Airlie --- drivers/gpu/drm/ast/ast_drv.c | 3 +++ drivers/gpu/drm/cirrus/cirrus_drv.c | 3 +++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 3 +++ drivers/gpu/drm/i810/i810_dma.c | 3 +++ drivers/gpu/drm/i810/i810_drv.c | 3 +++ drivers/gpu/drm/mgag200/mgag200_drv.c | 3 +++ drivers/gpu/drm/savage/savage_drv.c | 3 +++ drivers/gpu/drm/sis/sis_drv.c | 3 +++ drivers/gpu/drm/tdfx/tdfx_drv.c | 3 +++ drivers/gpu/drm/udl/udl_drv.c | 3 +++ drivers/gpu/drm/via/via_drv.c | 3 +++ 11 files changed, 33 insertions(+) diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index d0c4574ef49c..36164806b9d4 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -193,6 +193,9 @@ static const struct file_operations ast_fops = { .mmap = ast_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .read = drm_read, }; diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 7053140c6596..b83a2d7ddd1a 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -74,6 +74,9 @@ static const struct file_operations cirrus_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = cirrus_mmap, .poll = drm_poll, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .fasync = drm_fasync, }; static struct drm_driver driver = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index ebacec6f1e48..6345abe9fdee 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -241,6 +241,9 @@ static const struct file_operations exynos_drm_driver_fops = { .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .release = drm_release, }; diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 57d892eaaa6e..463ec6871fe9 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -115,6 +115,9 @@ static const struct file_operations i810_buffer_fops = { .unlocked_ioctl = drm_ioctl, .mmap = i810_mmap_buffers, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index f9924ad04d09..48cfcca2b350 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -51,6 +51,9 @@ static const struct file_operations i810_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index ea1024d79974..e5f145d2cb3b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -84,6 +84,9 @@ static const struct file_operations mgag200_driver_fops = { .mmap = mgag200_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .read = drm_read, }; diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index d31d4cca9a4c..c5a164337bd5 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -43,6 +43,9 @@ static const struct file_operations savage_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 7f119870147c..867dc03000e6 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -74,6 +74,9 @@ static const struct file_operations sis_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 90f6b13acfac..a7f4d6bd1330 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -49,6 +49,9 @@ static const struct file_operations tdfx_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 6e52069894b3..9f84128505bb 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -66,6 +66,9 @@ static const struct file_operations udl_driver_fops = { .unlocked_ioctl = drm_ioctl, .release = drm_release, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index e927b4c052f5..af1b914b17e3 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -65,6 +65,9 @@ static const struct file_operations via_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; From d013ef2aba8fe765ca683598e404203215632373 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 5 Sep 2012 10:53:18 +0000 Subject: [PATCH 385/665] tcp: fix possible socket refcount problem for ipv6 commit 144d56e91044181ec0ef67aeca91e9a8b5718348 ("tcp: fix possible socket refcount problem") is missing the IPv6 part. As tcp_release_cb is shared by both protocols we should hold sock reference for the TCP_MTU_REDUCED_DEFERRED bit. Signed-off-by: Julian Anastasov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index a3e60cc04a8a..acd32e3f1b68 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -403,8 +403,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, tp->mtu_info = ntohl(info); if (!sock_owned_by_user(sk)) tcp_v6_mtu_reduced(sk); - else - set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); + else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, + &tp->tsq_flags)) + sock_hold(sk); goto out; } From d90c92fee89ccd75ef2646f3bde0b4c0450666c3 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Tue, 4 Sep 2012 14:41:37 +0000 Subject: [PATCH 386/665] ibmveth: Fix alignment of rx queue bug This patch fixes a bug found by Nish Aravamudan (https://lkml.org/lkml/2012/5/15/220) where the driver is not following the spec (it is not aligning the rx buffer on a 16-byte boundary) and the hypervisor aborts the registration, making the device unusable. The fix follows BenH's recommendation (https://lkml.org/lkml/2012/7/20/461) to replace the kmalloc+map for a single call to dma_alloc_coherent() because that function always aligns to a 16-byte boundary. The stable trees will run into this bug whenever the rx buffer kmalloc call returns something not aligned on a 16-byte boundary. Cc: Signed-off-by: Santiago Leon Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmveth.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 9010cea68bc3..b68d28a130e6 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) } if (adapter->rx_queue.queue_addr != NULL) { - if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { - dma_unmap_single(dev, - adapter->rx_queue.queue_dma, - adapter->rx_queue.queue_len, - DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = DMA_ERROR_CODE; - } - kfree(adapter->rx_queue.queue_addr); + dma_free_coherent(dev, adapter->rx_queue.queue_len, + adapter->rx_queue.queue_addr, + adapter->rx_queue.queue_dma); adapter->rx_queue.queue_addr = NULL; } @@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } + dev = &adapter->vdev->dev; + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; - adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, - GFP_KERNEL); + adapter->rx_queue.queue_addr = + dma_alloc_coherent(dev, adapter->rx_queue.queue_len, + &adapter->rx_queue.queue_dma, GFP_KERNEL); if (!adapter->rx_queue.queue_addr) { netdev_err(netdev, "unable to allocate rx queue pages\n"); @@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } - dev = &adapter->vdev->dev; - adapter->buffer_list_dma = dma_map_single(dev, adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); adapter->filter_list_dma = dma_map_single(dev, adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = dma_map_single(dev, - adapter->rx_queue.queue_addr, - adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || - (dma_mapping_error(dev, adapter->filter_list_dma)) || - (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { + (dma_mapping_error(dev, adapter->filter_list_dma))) { netdev_err(netdev, "unable to map filter or buffer list " "pages\n"); rc = -ENOMEM; From 58d468328646effa72ada4deaa33e80d678980d6 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Thu, 30 Aug 2012 08:16:52 -0700 Subject: [PATCH 387/665] ASoC: wm0010: Add missing IRQF_ONESHOT FYI, there are new coccinelle warnings show up in tree: git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-3.7 head: e3523e01869da20fdd12ffd19ae1df7bf492650e commit: e3523e01869da20fdd12ffd19ae1df7bf492650e [95/95] ASoC: wm0010: Add initial wm0010 DSP driver All coccinelle warnings: + sound/soc/codecs/wm0010.c:850:7-27: ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT -- + sound/soc/codecs/wm0010.c:660:1-7: preceding lock on line 359 vim +850 sound/soc/codecs/wm0010.c 847 trigger = IRQF_TRIGGER_FALLING; 848 trigger |= IRQF_ONESHOT; 849 > 850 ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, 851 "wm0010", wm0010); 852 if (ret) 853 dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", Please consider folding the attached diff :-) Signed-off-by: Fengguang Wu Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 5f99148447e1..a4c35119792e 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -881,7 +881,7 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi) trigger = IRQF_TRIGGER_FALLING; trigger |= IRQF_ONESHOT; - ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, + ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger | IRQF_ONESHOT, "wm0010", wm0010); if (ret) { dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", From 4f3ad7956d91a5371a572f0420cc07f8c4f32c22 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 Sep 2012 15:29:46 +0300 Subject: [PATCH 388/665] ASoC: wm0010: unlock on error path We're holding the wm0010->lock mutex when we goto err_core. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index a4c35119792e..0274f04a940a 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -663,7 +663,9 @@ abort: wm0010_halt(codec); mutex_unlock(&wm0010->lock); return ret; + err_core: + mutex_unlock(&wm0010->lock); regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), wm0010->core_supplies); err: From 5d86e25c70407cd97a5aa8f39cc3be390bcab116 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Wed, 5 Sep 2012 22:22:24 +0200 Subject: [PATCH 389/665] ASoC: wm0010: Fix warning, use format %zu for type size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix warning by using format specifier %zu for type size_t Sparse warning: sound/soc/codecs/wm0010.c:411:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t’ [-Wformat] Signed-off-by: Emil Goode Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 0274f04a940a..f8d6c31db870 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -408,7 +408,7 @@ static int wm0010_boot(struct snd_soc_codec *codec) wm0010->state = WM0010_BOOTROM; spin_unlock_irqrestore(&wm0010->irq_lock, flags); - dev_dbg(codec->dev, "Downloading %d byte stage 2 loader\n", fw->size); + dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); /* Copy to local buffer first as vmalloc causes problems for dma */ img = kzalloc(fw->size, GFP_KERNEL); From 03f67433758a3eeb37b9c1559886c377da874ad2 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 5 Sep 2012 10:27:14 -0600 Subject: [PATCH 390/665] ASoC: tegra: move platform data header Move the Tegra+WM8903 ASoC platform data header out of arch/arm/mach-tegra, as a pre-requisite of single zImage. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- .../tegra_wm8903_pdata.h => include/sound/tegra_wm8903.h | 7 +++++-- sound/soc/tegra/tegra_wm8903.c | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) rename arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h => include/sound/tegra_wm8903.h (89%) diff --git a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h b/include/sound/tegra_wm8903.h similarity index 89% rename from arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h rename to include/sound/tegra_wm8903.h index 9d293344a7ff..57b202ee97c3 100644 --- a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h +++ b/include/sound/tegra_wm8903.h @@ -1,6 +1,4 @@ /* - * arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h - * * Copyright 2011 NVIDIA, Inc. * * This software is licensed under the terms of the GNU General Public @@ -14,6 +12,9 @@ * */ +#ifndef __SOUND_TEGRA_WM38903_H +#define __SOUND_TEGRA_WM38903_H + struct tegra_wm8903_platform_data { int gpio_spkr_en; int gpio_hp_det; @@ -21,3 +22,5 @@ struct tegra_wm8903_platform_data { int gpio_int_mic_en; int gpio_ext_mic_en; }; + +#endif diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index d4f14e492341..cee13b7bfb94 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -34,13 +34,12 @@ #include #include -#include - #include #include #include #include #include +#include #include "../codecs/wm8903.h" From 4758be37c01c658dec5c0ad08d456fa031493de4 Mon Sep 17 00:00:00 2001 From: Heather Lomond Date: Wed, 5 Sep 2012 05:02:10 -0400 Subject: [PATCH 391/665] ASoC: arizona: Fix typo in 44.1kHz rates Signed-off-by: Heather Lomond Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5c9cacaf2d52..1cf7a32d1b21 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -426,7 +426,7 @@ static const int arizona_44k1_bclk_rates[] = { 940800, 1411200, 1881600, - 2882400, + 2822400, 3763200, 5644800, 7526400, From 90beca5de591e12482a812f23a7f10690962ed4a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 4 Sep 2012 23:12:33 -0700 Subject: [PATCH 392/665] workqueue: move WORKER_REBIND clearing in rebind_workers() to the end of the function This doesn't make any functional difference and is purely to help the next patch to be simpler. Signed-off-by: Tejun Heo Cc: Lai Jiangshan --- kernel/workqueue.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index c462cd60c374..d79a18d0c42e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1422,19 +1422,7 @@ retry: goto retry; } - /* - * All idle workers are rebound and waiting for %WORKER_REBIND to - * be cleared inside idle_worker_rebind(). Clear and release. - * Clearing %WORKER_REBIND from this foreign context is safe - * because these workers are still guaranteed to be idle. - */ - for_each_worker_pool(pool, gcwq) - list_for_each_entry(worker, &pool->idle_list, entry) - worker->flags &= ~WORKER_REBIND; - - wake_up_all(&gcwq->rebind_hold); - - /* rebind busy workers */ + /* all idle workers are rebound, rebind busy workers */ for_each_busy_worker(worker, i, pos, gcwq) { struct work_struct *rebind_work = &worker->rebind_work; unsigned long worker_flags = worker->flags; @@ -1454,6 +1442,18 @@ retry: worker->scheduled.next, work_color_to_flags(WORK_NO_COLOR)); } + + /* + * All idle workers are rebound and waiting for %WORKER_REBIND to + * be cleared inside idle_worker_rebind(). Clear and release. + * Clearing %WORKER_REBIND from this foreign context is safe + * because these workers are still guaranteed to be idle. + */ + for_each_worker_pool(pool, gcwq) + list_for_each_entry(worker, &pool->idle_list, entry) + worker->flags &= ~WORKER_REBIND; + + wake_up_all(&gcwq->rebind_hold); } static struct worker *alloc_worker(void) From ec58815ab0409a921a7c9744eb4ca44866b14d71 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 4 Sep 2012 23:16:32 -0700 Subject: [PATCH 393/665] workqueue: fix possible deadlock in idle worker rebinding Currently, rebind_workers() and idle_worker_rebind() are two-way interlocked. rebind_workers() waits for idle workers to finish rebinding and rebound idle workers wait for rebind_workers() to finish rebinding busy workers before proceeding. Unfortunately, this isn't enough. The second wait from idle workers is implemented as follows. wait_event(gcwq->rebind_hold, !(worker->flags & WORKER_REBIND)); rebind_workers() clears WORKER_REBIND, wakes up the idle workers and then returns. If CPU hotplug cycle happens again before one of the idle workers finishes the above wait_event(), rebind_workers() will repeat the first part of the handshake - set WORKER_REBIND again and wait for the idle worker to finish rebinding - and this leads to deadlock because the idle worker would be waiting for WORKER_REBIND to clear. This is fixed by adding another interlocking step at the end - rebind_workers() now waits for all the idle workers to finish the above WORKER_REBIND wait before returning. This ensures that all rebinding steps are complete on all idle workers before the next hotplug cycle can happen. This problem was diagnosed by Lai Jiangshan who also posted a patch to fix the issue, upon which this patch is based. This is the minimal fix and further patches are scheduled for the next merge window to simplify the CPU hotplug path. Signed-off-by: Tejun Heo Original-patch-by: Lai Jiangshan LKML-Reference: <1346516916-1991-3-git-send-email-laijs@cn.fujitsu.com> --- kernel/workqueue.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index d79a18d0c42e..dc7b8458e275 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1326,6 +1326,15 @@ static void idle_worker_rebind(struct worker *worker) /* we did our part, wait for rebind_workers() to finish up */ wait_event(gcwq->rebind_hold, !(worker->flags & WORKER_REBIND)); + + /* + * rebind_workers() shouldn't finish until all workers passed the + * above WORKER_REBIND wait. Tell it when done. + */ + spin_lock_irq(&worker->pool->gcwq->lock); + if (!--worker->idle_rebind->cnt) + complete(&worker->idle_rebind->done); + spin_unlock_irq(&worker->pool->gcwq->lock); } /* @@ -1448,12 +1457,28 @@ retry: * be cleared inside idle_worker_rebind(). Clear and release. * Clearing %WORKER_REBIND from this foreign context is safe * because these workers are still guaranteed to be idle. + * + * We need to make sure all idle workers passed WORKER_REBIND wait + * in idle_worker_rebind() before returning; otherwise, workers can + * get stuck at the wait if hotplug cycle repeats. */ - for_each_worker_pool(pool, gcwq) - list_for_each_entry(worker, &pool->idle_list, entry) + idle_rebind.cnt = 1; + INIT_COMPLETION(idle_rebind.done); + + for_each_worker_pool(pool, gcwq) { + list_for_each_entry(worker, &pool->idle_list, entry) { worker->flags &= ~WORKER_REBIND; + idle_rebind.cnt++; + } + } wake_up_all(&gcwq->rebind_hold); + + if (--idle_rebind.cnt) { + spin_unlock_irq(&gcwq->lock); + wait_for_completion(&idle_rebind.done); + spin_lock_irq(&gcwq->lock); + } } static struct worker *alloc_worker(void) From dafc4f7be1a556ca3868d343c00127728b397068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Tue, 4 Sep 2012 17:25:06 +0200 Subject: [PATCH 394/665] USB: ftdi-sio: add support for more Physik Instrumente devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b69cc672052540 added support for the E-861. After acquiring a C-867, I realised that every Physik Instrumente's device has a different PID. They are listed in the Windows device driver's .inf file. So here are all PIDs for the current (and probably future) USB devices from Physik Instrumente. Compiled, but only actually tested on the E-861 and C-867. Signed-off-by: Éric Piel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 17 +++++++++++++++++ drivers/usb/serial/ftdi_sio_ids.h | 21 ++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5620db6469e5..1197d4780b9a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -810,7 +810,24 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, + { USB_DEVICE(FTDI_VID, PI_C865_PID) }, + { USB_DEVICE(FTDI_VID, PI_C857_PID) }, + { USB_DEVICE(PI_VID, PI_C866_PID) }, + { USB_DEVICE(PI_VID, PI_C663_PID) }, + { USB_DEVICE(PI_VID, PI_C725_PID) }, + { USB_DEVICE(PI_VID, PI_E517_PID) }, + { USB_DEVICE(PI_VID, PI_C863_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) }, + { USB_DEVICE(PI_VID, PI_C867_PID) }, + { USB_DEVICE(PI_VID, PI_E609_PID) }, + { USB_DEVICE(PI_VID, PI_E709_PID) }, + { USB_DEVICE(PI_VID, PI_100F_PID) }, + { USB_DEVICE(PI_VID, PI_1011_PID) }, + { USB_DEVICE(PI_VID, PI_1012_PID) }, + { USB_DEVICE(PI_VID, PI_1013_PID) }, + { USB_DEVICE(PI_VID, PI_1014_PID) }, + { USB_DEVICE(PI_VID, PI_1015_PID) }, + { USB_DEVICE(PI_VID, PI_1016_PID) }, { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5dd96ca6c380..080d1580db99 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -791,8 +791,27 @@ * Physik Instrumente * http://www.physikinstrumente.com/en/products/ */ +/* These two devices use the VID of FTDI */ +#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */ +#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */ + #define PI_VID 0x1a72 /* Vendor ID */ -#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ +#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */ +#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */ +#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */ +#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */ +#define PI_C863_PID 0x1007 /* PI C-863 */ +#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */ +#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */ +#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */ +#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */ +#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */ +#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */ +#define PI_1012_PID 0x1012 /* PI Motion Controller */ +#define PI_1013_PID 0x1013 /* PI Motion Controller */ +#define PI_1014_PID 0x1014 /* PI Device */ +#define PI_1015_PID 0x1015 /* PI Device */ +#define PI_1016_PID 0x1016 /* PI Digital Servo Module */ /* * Kondo Kagaku Co.Ltd. From 26a538b9ea2a3ee10dafc0068f0560dfd7b7ba37 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Fri, 31 Aug 2012 00:00:28 +0200 Subject: [PATCH 395/665] USB: ftdi_sio: PID for NZR SEM 16+ USB This adds the USB PID for the NZR SEM 16+ USB energy monitor device . It works perfectly with the GPL software on . Signed-off-by: Horst Schirmeier Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1197d4780b9a..e2fa7881067d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -704,6 +704,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 080d1580db99..9bcaf9c3d3e4 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -75,6 +75,9 @@ #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GBM_PID 0xBFDC +/* NZR SEM 16+ USB (http://www.nzr.de) */ +#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ + /* * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) */ From 6fffb77c8393151b0cf8cef1b9c2ba90587dd2e8 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 29 Aug 2012 11:49:18 +0200 Subject: [PATCH 396/665] USB: ohci-at91: fix PIO handling in relation with number of ports If the number of ports present on the SoC/board is not the maximum and that the platform data is not filled with all data, there is an easy way to mess the PIO setup for this interface. This quick fix addresses mis-configuration in USB host platform data that is common in at91 boards since commit 0ee6d1e (USB: ohci-at91: change maximum number of ports) that did not modified the associatd board files. Reported-by: Klaus Falkner Signed-off-by: Nicolas Ferre Cc: Stable [3.4+] Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index a665b3eaa746..aaa8d2bce217 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -570,6 +570,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) if (pdata) { at91_for_each_port(i) { + /* + * do not configure PIO if not in relation with + * real USB port on board + */ + if (i >= pdata->ports) { + pdata->vbus_pin[i] = -EINVAL; + pdata->overcurrent_pin[i] = -EINVAL; + break; + } + if (!gpio_is_valid(pdata->vbus_pin[i])) continue; gpio = pdata->vbus_pin[i]; From 92fc7a8b0f20bdb243c706daf42658e8e0cd2ef0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 4 Sep 2012 10:41:02 -0400 Subject: [PATCH 397/665] USB: add device quirk for Joss Optical touchboard This patch (as1604) adds a CONFIG_INTF_STRINGS quirk for the Joss infrared touchboard device. The device doesn't like to be asked for its interface strings. Signed-off-by: Alan Stern Reported-by: adam ? Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f15501f4c585..e77a8e8eaa23 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04b4, 0x0526), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Microchip Joss Optical infrared touchboard device */ + { USB_DEVICE(0x04d8, 0x000c), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Samsung Android phone modem - ID conflict with SPH-I500 */ { USB_DEVICE(0x04e8, 0x6601), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, From 85da89f562579b001831b71d49946bfa0a93529d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Sep 2012 10:34:26 +0200 Subject: [PATCH 398/665] ASoC: Remove unused 'saved_value' field from snd_soc_dapm_widget struct The only user was removed over two years ago in commit a6c65736 ("ASoC: Remove current PGA control handling"). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index abe373d57adc..0a1553748d65 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -510,7 +510,6 @@ struct snd_soc_dapm_widget { /* dapm control */ int reg; /* negative reg = no direct dapm */ unsigned char shift; /* bits to shift */ - unsigned int saved_value; /* widget saved value */ unsigned int value; /* widget current value */ unsigned int mask; /* non-shifted mask */ unsigned int on_val; /* on state value */ From 37f45cc54cb03cac4a6b865b32bc705bb0cb1d29 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 3 Sep 2012 13:04:13 -0300 Subject: [PATCH 399/665] ASoC: mc13783: Remove mono support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Playing a mono track on a mc13783 codec results in incorrect playback rate. Remove mono support so that a mono track can be played correctly. Signed-off-by: Fabio Estevam Tested-by: Gaëtan Carlier Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 8f726c063f42..115a40301810 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -659,7 +659,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = { .id = MC13783_ID_STEREO_DAC, .playback = { .stream_name = "Playback", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = MC13783_FORMATS, @@ -670,7 +670,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = { .id = MC13783_ID_STEREO_CODEC, .capture = { .stream_name = "Capture", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = MC13783_RATES_RECORD, .formats = MC13783_FORMATS, @@ -692,14 +692,14 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = { .id = MC13783_ID_SYNC, .playback = { .stream_name = "Playback", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = MC13783_FORMATS, }, .capture = { .stream_name = "Capture", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = MC13783_RATES_RECORD, .formats = MC13783_FORMATS, From 6138ed2ab8791d7a9c5ba66cadadd5eaf1fc1dac Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:09:13 +0200 Subject: [PATCH 400/665] target: move transport_get_sense_data We will be calling it from transport_complete_cmd, avoid forward declarations. No semantic change. Signed-off-by: Paolo Bonzini Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 110 ++++++++++++------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 3425098ef728..d0afdaa06255 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -567,6 +567,61 @@ static void target_complete_failure_work(struct work_struct *work) transport_generic_request_failure(cmd); } +/* + * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd + */ +static int transport_get_sense_data(struct se_cmd *cmd) +{ + unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; + struct se_device *dev = cmd->se_dev; + unsigned long flags; + u32 offset = 0; + + WARN_ON(!cmd->se_lun); + + if (!dev) + return 0; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return 0; + } + + if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) + goto out; + + if (!dev->transport->get_sense_buffer) { + pr_err("dev->transport->get_sense_buffer is NULL\n"); + goto out; + } + + sense_buffer = dev->transport->get_sense_buffer(cmd); + if (!sense_buffer) { + pr_err("ITT 0x%08x cmd %p: Unable to locate" + " sense buffer for task with sense\n", + cmd->se_tfo->get_task_tag(cmd), cmd); + goto out; + } + + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + + offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); + + memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); + + /* Automatically padded */ + cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; + + pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", + dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); + return 0; + +out: + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return -1; +} + void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) { struct se_device *dev = cmd->se_dev; @@ -1820,61 +1875,6 @@ execute: } EXPORT_SYMBOL(target_execute_cmd); -/* - * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd - */ -static int transport_get_sense_data(struct se_cmd *cmd) -{ - unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; - struct se_device *dev = cmd->se_dev; - unsigned long flags; - u32 offset = 0; - - WARN_ON(!cmd->se_lun); - - if (!dev) - return 0; - - spin_lock_irqsave(&cmd->t_state_lock, flags); - if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return 0; - } - - if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) - goto out; - - if (!dev->transport->get_sense_buffer) { - pr_err("dev->transport->get_sense_buffer is NULL\n"); - goto out; - } - - sense_buffer = dev->transport->get_sense_buffer(cmd); - if (!sense_buffer) { - pr_err("ITT 0x%08x cmd %p: Unable to locate" - " sense buffer for task with sense\n", - cmd->se_tfo->get_task_tag(cmd), cmd); - goto out; - } - - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - - offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); - - memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); - - /* Automatically padded */ - cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; - - pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", - dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); - return 0; - -out: - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return -1; -} - /* * Process all commands up to the last received ORDERED task attribute which * requires another blocking boundary From 27a2709912ac19c755d34c79fe11994b0bf8082b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:09:14 +0200 Subject: [PATCH 401/665] target: simplify code around transport_get_sense_data The error conditions in transport_get_sense_data are superfluous and complicate the code unnecessarily: * SCF_TRANSPORT_TASK_SENSE is checked in the caller; * it's simply part of the invariants of dev->transport->get_sense_buffer that it must be there if transport_complete ever returns 1, and that it must not return NULL. Besides, the entire callback will disappear with the next patch. * similarly in the caller we can expect that sense data is only sent for non-zero cmd->scsi_status. Signed-off-by: Paolo Bonzini Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 49 +++++++------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d0afdaa06255..040f05fde4d6 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -570,7 +570,7 @@ static void target_complete_failure_work(struct work_struct *work) /* * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd */ -static int transport_get_sense_data(struct se_cmd *cmd) +static void transport_get_sense_data(struct se_cmd *cmd) { unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; struct se_device *dev = cmd->se_dev; @@ -580,30 +580,15 @@ static int transport_get_sense_data(struct se_cmd *cmd) WARN_ON(!cmd->se_lun); if (!dev) - return 0; + return; spin_lock_irqsave(&cmd->t_state_lock, flags); if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return 0; - } - - if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) - goto out; - - if (!dev->transport->get_sense_buffer) { - pr_err("dev->transport->get_sense_buffer is NULL\n"); - goto out; + return; } sense_buffer = dev->transport->get_sense_buffer(cmd); - if (!sense_buffer) { - pr_err("ITT 0x%08x cmd %p: Unable to locate" - " sense buffer for task with sense\n", - cmd->se_tfo->get_task_tag(cmd), cmd); - goto out; - } - spin_unlock_irqrestore(&cmd->t_state_lock, flags); offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); @@ -615,11 +600,6 @@ static int transport_get_sense_data(struct se_cmd *cmd) pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); - return 0; - -out: - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return -1; } void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) @@ -1990,7 +1970,7 @@ static void transport_handle_queue_full( static void target_complete_ok_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - int reason = 0, ret; + int ret; /* * Check if we need to move delayed/dormant tasks from cmds on the @@ -2011,19 +1991,16 @@ static void target_complete_ok_work(struct work_struct *work) * the struct se_cmd in question. */ if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { - if (transport_get_sense_data(cmd) < 0) - reason = TCM_NON_EXISTENT_LUN; + WARN_ON(!cmd->scsi_status); + transport_get_sense_data(cmd); + ret = transport_send_check_condition_and_sense( + cmd, 0, 1); + if (ret == -EAGAIN || ret == -ENOMEM) + goto queue_full; - if (cmd->scsi_status) { - ret = transport_send_check_condition_and_sense( - cmd, reason, 1); - if (ret == -EAGAIN || ret == -ENOMEM) - goto queue_full; - - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; - } + transport_lun_remove_cmd(cmd); + transport_cmd_check_stop_to_fabric(cmd); + return; } /* * Check for a callback, used by amongst other things From d5829eac5f7cfff89c6d1cf11717eee97cf030d0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:09:15 +0200 Subject: [PATCH 402/665] target: fix use-after-free with PSCSI sense data The pointer to the sense buffer is fetched by transport_get_sense_data, but this is called by target_complete_ok_work long after pscsi_req_done has freed the struct that contains it. Pass instead the fabric's sense buffer to transport_complete, and copy the data to it directly in transport_complete. Setting SCF_TRANSPORT_TASK_SENSE also becomes a duty of transport_complete. Signed-off-by: Paolo Bonzini Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pscsi.c | 21 +++++---------- drivers/target/target_core_transport.c | 36 ++++++++++---------------- include/target/target_core_backend.h | 4 ++- 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 5552fa7426bc..5f7151d90344 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -667,7 +667,8 @@ static void pscsi_free_device(void *p) kfree(pdv); } -static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) +static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, + unsigned char *sense_buffer) { struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; struct scsi_device *sd = pdv->pdv_sd; @@ -679,7 +680,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) * not been allocated because TCM is handling the emulation directly. */ if (!pt) - return 0; + return; cdb = &pt->pscsi_cdb[0]; result = pt->pscsi_result; @@ -750,10 +751,10 @@ after_mode_sense: } after_mode_select: - if (status_byte(result) & CHECK_CONDITION) - return 1; - - return 0; + if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) { + memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER); + cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; + } } enum { @@ -1184,13 +1185,6 @@ fail: return -ENOMEM; } -static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd) -{ - struct pscsi_plugin_task *pt = cmd->priv; - - return pt->pscsi_sense; -} - /* pscsi_get_device_rev(): * * @@ -1273,7 +1267,6 @@ static struct se_subsystem_api pscsi_template = { .check_configfs_dev_params = pscsi_check_configfs_dev_params, .set_configfs_dev_params = pscsi_set_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params, - .get_sense_buffer = pscsi_get_sense_buffer, .get_device_rev = pscsi_get_device_rev, .get_device_type = pscsi_get_device_type, .get_blocks = pscsi_get_blocks, diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 040f05fde4d6..8a29e3fd0195 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -568,38 +568,31 @@ static void target_complete_failure_work(struct work_struct *work) } /* - * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd + * Used when asking transport to copy Sense Data from the underlying + * Linux/SCSI struct scsi_cmnd */ -static void transport_get_sense_data(struct se_cmd *cmd) +static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd) { - unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; + unsigned char *buffer = cmd->sense_buffer; struct se_device *dev = cmd->se_dev; - unsigned long flags; u32 offset = 0; WARN_ON(!cmd->se_lun); if (!dev) - return; + return NULL; - spin_lock_irqsave(&cmd->t_state_lock, flags); - if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return; - } - - sense_buffer = dev->transport->get_sense_buffer(cmd); - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) + return NULL; offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); - memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); - /* Automatically padded */ cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; - pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", + pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n", dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); + return &buffer[offset]; } void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) @@ -615,11 +608,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) cmd->transport_state &= ~CMD_T_BUSY; if (dev && dev->transport->transport_complete) { - if (dev->transport->transport_complete(cmd, - cmd->t_data_sg) != 0) { - cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; + dev->transport->transport_complete(cmd, + cmd->t_data_sg, + transport_get_sense_buffer(cmd)); + if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) success = 1; - } } /* @@ -1987,12 +1980,11 @@ static void target_complete_ok_work(struct work_struct *work) schedule_work(&cmd->se_dev->qf_work_queue); /* - * Check if we need to retrieve a sense buffer from + * Check if we need to send a sense buffer from * the struct se_cmd in question. */ if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { WARN_ON(!cmd->scsi_status); - transport_get_sense_data(cmd); ret = transport_send_check_condition_and_sense( cmd, 0, 1); if (ret == -EAGAIN || ret == -ENOMEM) diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index f1405d335a96..941c84bf1065 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -23,7 +23,9 @@ struct se_subsystem_api { struct se_device *(*create_virtdevice)(struct se_hba *, struct se_subsystem_dev *, void *); void (*free_device)(void *); - int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *); + void (*transport_complete)(struct se_cmd *cmd, + struct scatterlist *, + unsigned char *); int (*parse_cdb)(struct se_cmd *cmd); ssize_t (*check_configfs_dev_params)(struct se_hba *, From e5ec69da24803c68f5c035662a68d367359a4132 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 3 Sep 2012 13:40:40 +0530 Subject: [PATCH 403/665] ASoC: Davinci: McASP: add support new McASP IP Variant The OMAP2+ variant of McASP is different from Davinci variant w.r.to some register offset. Changes - Add new MCASP_VERSION_3 to identify new variant. New DT compatible "ti,omap2-mcasp-audio" to identify version 3 controller. - The register offsets are handled depending on the version. Note: DMA parameters (dma fifo offset) are not updated and will be done later. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- .../bindings/sound/davinci-mcasp-audio.txt | 1 + include/linux/platform_data/davinci_asp.h | 1 + sound/soc/davinci/davinci-mcasp.c | 86 ++++++++++++++++--- 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index e6148eca2942..374e145c2ef1 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -4,6 +4,7 @@ Required properties: - compatible : "ti,dm646x-mcasp-audio" : for DM646x platforms "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms + "ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx) - reg : Should contain McASP registers offset and length - interrupts : Interrupt number for McASP diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 79c26aa11db6..d0c5825876f8 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -87,6 +87,7 @@ struct snd_platform_data { enum { MCASP_VERSION_1 = 0, /* DM646x */ MCASP_VERSION_2, /* DA8xx/OMAPL1x */ + MCASP_VERSION_3, /* TI81xx/AM33xx */ }; enum mcbsp_clk_input_pin { diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index c3eae1d8e077..714e51e5be5b 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -111,6 +111,10 @@ #define DAVINCI_MCASP_WFIFOSTS (0x1014) #define DAVINCI_MCASP_RFIFOCTL (0x1018) #define DAVINCI_MCASP_RFIFOSTS (0x101C) +#define MCASP_VER3_WFIFOCTL (0x1000) +#define MCASP_VER3_WFIFOSTS (0x1004) +#define MCASP_VER3_RFIFOCTL (0x1008) +#define MCASP_VER3_RFIFOSTS (0x100C) /* * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management @@ -384,18 +388,36 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { if (dev->txnumevt) { /* enable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); + break; + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); + mcasp_set_bits(dev->base + + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); + } } mcasp_start_tx(dev); } else { if (dev->rxnumevt) { /* enable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); + break; + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + mcasp_set_bits(dev->base + + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + } } mcasp_start_rx(dev); } @@ -416,14 +438,31 @@ static void mcasp_stop_tx(struct davinci_audio_dev *dev) static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + if (dev->txnumevt) { /* disable FIFO */ + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); + break; + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); + } + } mcasp_stop_tx(dev); } else { - if (dev->rxnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + if (dev->rxnumevt) { /* disable FIFO */ + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); + break; + + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + } + } mcasp_stop_rx(dev); } } @@ -622,20 +661,37 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) if (dev->txnumevt * tx_ser > 64) dev->txnumevt = 1; - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser, NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); + break; + default: + mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + tx_ser, NUMDMA_MASK); + mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); + } } if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { if (dev->rxnumevt * rx_ser > 64) dev->rxnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser, NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); + break; + default: + mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + rx_ser, NUMDMA_MASK); + mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); + } } } @@ -874,6 +930,10 @@ static const struct of_device_id mcasp_dt_ids[] = { .compatible = "ti,da830-mcasp-audio", .data = (void *)MCASP_VERSION_2, }, + { + .compatible = "ti,omap2-mcasp-audio", + .data = (void *)MCASP_VERSION_3, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mcasp_dt_ids); From e2d32ff6ce4ee9958f3973a086f3fa5d009e6306 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 31 Aug 2012 17:38:32 -0700 Subject: [PATCH 404/665] ASoC: dapm: Ensure bypass paths are suspended and resumed Since bypass paths aren't part of DAPM streams and we may not have any DAPM streams there may not be anything that triggers a DAPM sync for them. Mark all input and output widgets as dirty and then sync to do so at the end of suspend and resume. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- include/sound/soc-dapm.h | 1 + sound/soc/soc-core.c | 8 ++++++++ sound/soc/soc-dapm.c | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 0a1553748d65..07e2510619a1 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -412,6 +412,7 @@ 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 */ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b95d1fb388a1..ad65459da28e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -609,6 +609,10 @@ int snd_soc_suspend(struct device *dev) SND_SOC_DAPM_STREAM_SUSPEND); } + /* Recheck all analogue paths too */ + dapm_mark_io_dirty(&card->dapm); + snd_soc_dapm_sync(&card->dapm); + /* suspend all CODECs */ list_for_each_entry(codec, &card->codec_dev_list, card_list) { /* If there are paths active then the CODEC will be held with @@ -756,6 +760,10 @@ static void soc_resume_deferred(struct work_struct *work) /* userspace can access us now we are back as we were before */ snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); + + /* Recheck all analogue paths too */ + dapm_mark_io_dirty(&card->dapm); + snd_soc_dapm_sync(&card->dapm); } /* powers up audio subsystem after a suspend */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dd7c49fafd75..f7999e949acb 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -141,6 +141,28 @@ void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) } EXPORT_SYMBOL_GPL(dapm_mark_dirty); +void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) +{ + struct snd_soc_card *card = dapm->card; + struct snd_soc_dapm_widget *w; + + mutex_lock(&card->dapm_mutex); + + list_for_each_entry(w, &card->widgets, list) { + switch (w->id) { + case snd_soc_dapm_input: + case snd_soc_dapm_output: + dapm_mark_dirty(w, "Rechecking inputs and outputs"); + break; + default: + break; + } + } + + mutex_unlock(&card->dapm_mutex); +} +EXPORT_SYMBOL_GPL(dapm_mark_io_dirty); + /* create a new dapm widget */ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( const struct snd_soc_dapm_widget *_widget) From 104c229932f18605acef2351373f8fd8f6c6f8c6 Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Wed, 5 Sep 2012 21:30:10 -0300 Subject: [PATCH 405/665] ASoC: Revert 'ASoC: imx-ssi: Remove mono support' Revert 0865a75(ASoC: imx-ssi: Remove mono support). The bug this patch is meant to solve doesn't occur in Visstrim_M10 boards. Furthermore, after applying this patch sound in Visstrim_M10 is played at slower rates. Signed-off-by: Javier Martin Signed-off-by: Mark Brown --- sound/soc/fsl/imx-ssi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 7074ae689984..3c520c46fa4a 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -380,14 +380,13 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) static struct snd_soc_dai_driver imx_ssi_dai = { .probe = imx_ssi_dai_probe, .playback = { - /* The SSI does not support monaural audio. */ - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, From ed6fe9d614fc1bca95eb8c0ccd0e92db00ef9d5d Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Sat, 1 Sep 2012 12:34:07 -0400 Subject: [PATCH 406/665] Fix order of arguments to compat_put_time[spec|val] Commit 644595f89620 ("compat: Handle COMPAT_USE_64BIT_TIME in net/socket.c") introduced a bug where the helper functions to take either a 64-bit or compat time[spec|val] got the arguments in the wrong order, passing the kernel stack pointer off as a user pointer (and vice versa). Because of the user address range check, that in turn then causes an EFAULT due to the user pointer range checking failing for the kernel address. Incorrectly resuling in a failed system call for 32-bit processes with a 64-bit kernel. On odder architectures like HP-PA (with separate user/kernel address spaces), it can be used read kernel memory. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds --- net/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/socket.c b/net/socket.c index a5471f804d99..edc3c4af9085 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2604,7 +2604,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); set_fs(old_fs); if (!err) - err = compat_put_timeval(up, &ktv); + err = compat_put_timeval(&ktv, up); return err; } @@ -2620,7 +2620,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); set_fs(old_fs); if (!err) - err = compat_put_timespec(up, &kts); + err = compat_put_timespec(&kts, up); return err; } From 8a55ade76551e3927b4e41ee9e7751875d18bc25 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 15:10:08 +0100 Subject: [PATCH 407/665] dj: memory scribble in logi_dj Allocate a structure not a pointer to it ! Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/hid/hid-logitech-dj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 0f9c146fc00d..4d524b5f52f5 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -439,7 +439,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; - dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL); + dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; dj_report->report_id = REPORT_ID_DJ_SHORT; @@ -456,7 +456,7 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report; int retval; - dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL); + dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; dj_report->report_id = REPORT_ID_DJ_SHORT; From bc6c83641e1df61cff67748987f95ca62953565e Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 5 Sep 2012 18:38:50 +0200 Subject: [PATCH 408/665] uml: fix compile error in deliver_alarm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compile error on UML. arch/um/os-Linux/time.c: In function 'deliver_alarm': arch/um/os-Linux/time.c:117:3: error: too few arguments to function 'alarm_handler' arch/um/os-Linux/internal.h:1:6: note: declared here The error was introduced by commit d3c1cfcd ("um: pass siginfo to guest process") in 3.6-rc1. Signed-off-by: Miklos Szeredi CC: Martin Pärtel Signed-off-by: Linus Torvalds --- arch/um/os-Linux/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index f60238559af3..0748fe0c8a73 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -114,7 +114,7 @@ static void deliver_alarm(void) skew += this_tick - last_tick; while (skew >= one_tick) { - alarm_handler(SIGVTALRM, NULL); + alarm_handler(SIGVTALRM, NULL, NULL); skew -= one_tick; } From 6d97c09c64974ab41708e2d38394928ec0eeb2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Carlier?= Date: Thu, 6 Sep 2012 09:40:12 +0200 Subject: [PATCH 409/665] ASoC: imx-mc13783: use defines instead of numerical address of register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This uses already defined name of registers and makes code more readable. Signed-off-by: Gaëtan Carlier Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 58 ++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 8f726c063f42..bbfa5535cdd3 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -426,16 +426,16 @@ static int mc13783_set_tdm_slot_sync(struct snd_soc_dai *dai, } static const struct snd_kcontrol_new mc1l_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 7, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 7, 1, 0); static const struct snd_kcontrol_new mc1r_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 5, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 5, 1, 0); static const struct snd_kcontrol_new mc2_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 9, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 9, 1, 0); static const struct snd_kcontrol_new atx_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 11, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 11, 1, 0); /* Virtual mux. The chip does the input selection automatically @@ -461,22 +461,22 @@ static const struct snd_kcontrol_new right_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcr_enum); static const struct snd_kcontrol_new samp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 3, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0); static const struct snd_kcontrol_new lamp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 5, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 5, 1, 0); static const struct snd_kcontrol_new hlamp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 10, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 10, 1, 0); static const struct snd_kcontrol_new hramp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 9, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 9, 1, 0); static const struct snd_kcontrol_new llamp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 16, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 16, 1, 0); static const struct snd_kcontrol_new lramp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 15, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 15, 1, 0); static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { /* Input */ @@ -487,13 +487,13 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { SND_SOC_DAPM_INPUT("RXINL"), SND_SOC_DAPM_INPUT("TXIN"), - SND_SOC_DAPM_SUPPLY("MC1 Bias", 38, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("MC2 Bias", 38, 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MC1 Bias", MC13783_AUDIO_TX, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MC2 Bias", MC13783_AUDIO_TX, 1, 0, NULL, 0), - SND_SOC_DAPM_SWITCH("MC1L Amp", 38, 7, 0, &mc1l_amp_ctl), - SND_SOC_DAPM_SWITCH("MC1R Amp", 38, 5, 0, &mc1r_amp_ctl), - SND_SOC_DAPM_SWITCH("MC2 Amp", 38, 9, 0, &mc2_amp_ctl), - SND_SOC_DAPM_SWITCH("TXIN Amp", 38, 11, 0, &atx_amp_ctl), + SND_SOC_DAPM_SWITCH("MC1L Amp", MC13783_AUDIO_TX, 7, 0, &mc1l_amp_ctl), + SND_SOC_DAPM_SWITCH("MC1R Amp", MC13783_AUDIO_TX, 5, 0, &mc1r_amp_ctl), + SND_SOC_DAPM_SWITCH("MC2 Amp", MC13783_AUDIO_TX, 9, 0, &mc2_amp_ctl), + SND_SOC_DAPM_SWITCH("TXIN Amp", MC13783_AUDIO_TX, 11, 0, &atx_amp_ctl), SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0, &left_input_mux), @@ -503,12 +503,12 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", 40, 11, 0), - SND_SOC_DAPM_SUPPLY("ADC_Reset", 40, 15, 0, NULL, 0), + SND_SOC_DAPM_ADC("ADC", "Capture", MC13783_AUDIO_CODEC, 11, 0), + SND_SOC_DAPM_SUPPLY("ADC_Reset", MC13783_AUDIO_CODEC, 15, 0, NULL, 0), /* Output */ - SND_SOC_DAPM_SUPPLY("DAC_E", 41, 11, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("DAC_Reset", 41, 15, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_E", MC13783_AUDIO_DAC, 11, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_Reset", MC13783_AUDIO_DAC, 15, 0, NULL, 0), SND_SOC_DAPM_OUTPUT("RXOUTL"), SND_SOC_DAPM_OUTPUT("RXOUTR"), SND_SOC_DAPM_OUTPUT("HSL"), @@ -516,14 +516,18 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("LSP"), SND_SOC_DAPM_OUTPUT("SP"), - SND_SOC_DAPM_SWITCH("Speaker Amp", 36, 3, 0, &samp_ctl), + SND_SOC_DAPM_SWITCH("Speaker Amp", MC13783_AUDIO_RX0, 3, 0, &samp_ctl), SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl), - SND_SOC_DAPM_SWITCH("Headset Amp Left", 36, 10, 0, &hlamp_ctl), - SND_SOC_DAPM_SWITCH("Headset Amp Right", 36, 9, 0, &hramp_ctl), - SND_SOC_DAPM_SWITCH("Line out Amp Left", 36, 16, 0, &llamp_ctl), - SND_SOC_DAPM_SWITCH("Line out Amp Right", 36, 15, 0, &lramp_ctl), - SND_SOC_DAPM_DAC("DAC", "Playback", 36, 22, 0), - SND_SOC_DAPM_PGA("DAC PGA", 37, 5, 0, NULL, 0), + SND_SOC_DAPM_SWITCH("Headset Amp Left", MC13783_AUDIO_RX0, 10, 0, + &hlamp_ctl), + SND_SOC_DAPM_SWITCH("Headset Amp Right", MC13783_AUDIO_RX0, 9, 0, + &hramp_ctl), + SND_SOC_DAPM_SWITCH("Line out Amp Left", MC13783_AUDIO_RX0, 16, 0, + &llamp_ctl), + SND_SOC_DAPM_SWITCH("Line out Amp Right", MC13783_AUDIO_RX0, 15, 0, + &lramp_ctl), + SND_SOC_DAPM_DAC("DAC", "Playback", MC13783_AUDIO_RX0, 22, 0), + SND_SOC_DAPM_PGA("DAC PGA", MC13783_AUDIO_RX1, 5, 0, NULL, 0), }; static struct snd_soc_dapm_route mc13783_routes[] = { From 57b2d68863f281737d8596cb3d76d89d9cc54fd8 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Sat, 1 Sep 2012 01:38:19 -0700 Subject: [PATCH 410/665] ASoC: samsung dma - Don't indicate support for pause/resume. The pause and resume operations indicate that the stream can be un-paused/resumed from the exact location they were paused/suspended. This is not true for this driver, the pause and suspend triggers share the same code path with stop, they flush all pending DMA transfers. This drops all pending samples. The pause_release/resume triggers are the same as start, except that prepare won't be called beforehand, nothing will be enqueued to the DMA engine and nothing will happen (no audio). Removing the pause flag will let apps know that it isn't supported. Removing the resume flag will cause user space to call prepare and start instead of resume, so audio will continue playing when the system wakes up. Before removing the pause and resume flags, I tested this on an exynos 5250, using 'aplay -i'. Pause/un-pause leads to silence followed by a write error. Suspend/resume testing led to the same result. Removing the two flags fixes suspend/resume (since snd_pcm_prepare is called again). And leads to a proper reporting of pause not supported. Signed-off-by: Dylan Reid Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/samsung/dma.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index f3ebc38c10fe..b70964ea448c 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -34,9 +34,7 @@ static const struct snd_pcm_hardware dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, + SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U8 | @@ -248,15 +246,11 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->state |= ST_RUNNING; prtd->params->ops->trigger(prtd->params->ch); break; case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: prtd->state &= ~ST_RUNNING; prtd->params->ops->stop(prtd->params->ch); break; From 0626af3139572610b56376580d11eb65d45d9dd7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 4 Sep 2012 07:49:03 +0000 Subject: [PATCH 411/665] netfilter: take care of timewait sockets Sami Farin reported crashes in xt_LOG because it assumes skb->sk is a full blown socket. Since (41063e9 ipv4: Early TCP socket demux), we can have skb->sk pointing to a timewait socket. Same fix is needed in nfnetlink_log. Diagnosed-by: Florian Westphal Reported-by: Sami Farin Signed-off-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_log.c | 14 ++++++++------ net/netfilter/xt_LOG.c | 33 +++++++++++++++++---------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 14e2f3903142..5cfb5bedb2b8 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -381,6 +381,7 @@ __build_packet_message(struct nfulnl_instance *inst, struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; sk_buff_data_t old_tail = inst->skb->tail; + struct sock *sk; nlh = nlmsg_put(inst->skb, 0, 0, NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET, @@ -499,18 +500,19 @@ __build_packet_message(struct nfulnl_instance *inst, } /* UID */ - if (skb->sk) { - read_lock_bh(&skb->sk->sk_callback_lock); - if (skb->sk->sk_socket && skb->sk->sk_socket->file) { - struct file *file = skb->sk->sk_socket->file; + sk = skb->sk; + if (sk && sk->sk_state != TCP_TIME_WAIT) { + read_lock_bh(&sk->sk_callback_lock); + if (sk->sk_socket && sk->sk_socket->file) { + struct file *file = sk->sk_socket->file; __be32 uid = htonl(file->f_cred->fsuid); __be32 gid = htonl(file->f_cred->fsgid); - read_unlock_bh(&skb->sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); if (nla_put_be32(inst->skb, NFULA_UID, uid) || nla_put_be32(inst->skb, NFULA_GID, gid)) goto nla_put_failure; } else - read_unlock_bh(&skb->sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); } /* local sequence number */ diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index ff5f75fddb15..2a4f9693e799 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c @@ -145,6 +145,19 @@ static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb, return 0; } +static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk) +{ + if (!sk || sk->sk_state == TCP_TIME_WAIT) + return; + + read_lock_bh(&sk->sk_callback_lock); + if (sk->sk_socket && sk->sk_socket->file) + sb_add(m, "UID=%u GID=%u ", + sk->sk_socket->file->f_cred->fsuid, + sk->sk_socket->file->f_cred->fsgid); + read_unlock_bh(&sk->sk_callback_lock); +} + /* One level of recursion won't kill us */ static void dump_ipv4_packet(struct sbuff *m, const struct nf_loginfo *info, @@ -361,14 +374,8 @@ static void dump_ipv4_packet(struct sbuff *m, } /* Max length: 15 "UID=4294967295 " */ - if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { - read_lock_bh(&skb->sk->sk_callback_lock); - if (skb->sk->sk_socket && skb->sk->sk_socket->file) - sb_add(m, "UID=%u GID=%u ", - skb->sk->sk_socket->file->f_cred->fsuid, - skb->sk->sk_socket->file->f_cred->fsgid); - read_unlock_bh(&skb->sk->sk_callback_lock); - } + if ((logflags & XT_LOG_UID) && !iphoff) + dump_sk_uid_gid(m, skb->sk); /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!iphoff && skb->mark) @@ -717,14 +724,8 @@ static void dump_ipv6_packet(struct sbuff *m, } /* Max length: 15 "UID=4294967295 " */ - if ((logflags & XT_LOG_UID) && recurse && skb->sk) { - read_lock_bh(&skb->sk->sk_callback_lock); - if (skb->sk->sk_socket && skb->sk->sk_socket->file) - sb_add(m, "UID=%u GID=%u ", - skb->sk->sk_socket->file->f_cred->fsuid, - skb->sk->sk_socket->file->f_cred->fsgid); - read_unlock_bh(&skb->sk->sk_callback_lock); - } + if ((logflags & XT_LOG_UID) && recurse) + dump_sk_uid_gid(m, skb->sk); /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!recurse && skb->mark) From 80ba77dfbce85f2d1be54847de3c866de1b18a9a Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 5 Sep 2012 16:35:20 -0400 Subject: [PATCH 412/665] xen/pciback: Fix proper FLR steps. When we do FLR and save PCI config we did it in the wrong order. The end result was that if a PCI device was unbind from its driver, then binded to xen-pciback, and then back to its driver we would get: > lspci -s 04:00.0 04:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection 13:42:12 # 4 :~/ > echo "0000:04:00.0" > /sys/bus/pci/drivers/pciback/unbind > modprobe e1000e e1000e: Intel(R) PRO/1000 Network Driver - 2.0.0-k e1000e: Copyright(c) 1999 - 2012 Intel Corporation. e1000e 0000:04:00.0: Disabling ASPM L0s L1 e1000e 0000:04:00.0: enabling device (0000 -> 0002) xen: registering gsi 48 triggering 0 polarity 1 Already setup the GSI :48 e1000e 0000:04:00.0: Interrupt Throttling Rate (ints/sec) set to dynamic conservative mode e1000e: probe of 0000:04:00.0 failed with error -2 This fixes it by first saving the PCI configuration space, then doing the FLR. Reported-by: Ren, Yongjie Reported-and-Tested-by: Tobias Geiger Signed-off-by: Konrad Rzeszutek Wilk CC: stable@vger.kernel.org --- drivers/xen/xen-pciback/pci_stub.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 097e536e8672..03342728bf23 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) if (err) goto config_release; - dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); - __pci_reset_function_locked(dev); - /* We need the device active to save the state. */ dev_dbg(&dev->dev, "save state of device\n"); pci_save_state(dev); dev_data->pci_saved_state = pci_store_saved_state(dev); if (!dev_data->pci_saved_state) dev_err(&dev->dev, "Could not store PCI conf saved state!\n"); - + else { + dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); + __pci_reset_function_locked(dev); + } /* Now disable the device (this also ensures some private device * data is setup before we export) */ From 1f1ea6c2d9d8c0be9ec56454b05315273b5de8ce Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 26 Aug 2012 11:44:43 -0700 Subject: [PATCH 413/665] NFSv4: Fix buffer overflow checking in __nfs4_get_acl_uncached Pass the checks made by decode_getacl back to __nfs4_get_acl_uncached so that it knows if the acl has been truncated. The current overflow checking is broken, resulting in Oopses on user-triggered nfs4_getfacl calls, and is opaque to the point where several attempts at fixing it have failed. This patch tries to clean up the code in addition to fixing the Oopses by ensuring that the overflow checks are performed in a single place (decode_getacl). If the overflow check failed, we will still be able to report the acl length, but at least we will no longer attempt to cache the acl or copy the truncated contents to user space. Reported-by: Sachin Prabhu Signed-off-by: Trond Myklebust Tested-by: Sachin Prabhu --- fs/nfs/nfs4proc.c | 31 ++++++++++++------------------- fs/nfs/nfs4xdr.c | 14 +++++--------- include/linux/nfs_xdr.h | 2 +- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6b94f2d52532..1e50326d00dd 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3739,7 +3739,7 @@ static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size struct nfs4_cached_acl *acl; size_t buflen = sizeof(*acl) + acl_len; - if (pages && buflen <= PAGE_SIZE) { + if (buflen <= PAGE_SIZE) { acl = kmalloc(buflen, GFP_KERNEL); if (acl == NULL) goto out; @@ -3784,7 +3784,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu }; unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); int ret = -ENOMEM, i; - size_t acl_len = 0; /* As long as we're doing a round trip to the server anyway, * let's be prepared for a page of acl data. */ @@ -3807,11 +3806,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu args.acl_len = npages * PAGE_SIZE; args.acl_pgbase = 0; - /* Let decode_getfacl know not to fail if the ACL data is larger than - * the page we send as a guess */ - if (buf == NULL) - res.acl_flags |= NFS4_ACL_LEN_REQUEST; - dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", __func__, buf, buflen, npages, args.acl_len); ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), @@ -3819,20 +3813,19 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu if (ret) goto out_free; - acl_len = res.acl_len; - if (acl_len > args.acl_len) - nfs4_write_cached_acl(inode, NULL, 0, acl_len); - else - nfs4_write_cached_acl(inode, pages, res.acl_data_offset, - acl_len); - if (buf) { + /* Handle the case where the passed-in buffer is too short */ + if (res.acl_flags & NFS4_ACL_TRUNC) { + /* Did the user only issue a request for the acl length? */ + if (buf == NULL) + goto out_ok; ret = -ERANGE; - if (acl_len > buflen) - goto out_free; - _copy_from_pages(buf, pages, res.acl_data_offset, - acl_len); + goto out_free; } - ret = acl_len; + nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); + if (buf) + _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); +out_ok: + ret = res.acl_len; out_free: for (i = 0; i < npages; i++) if (pages[i]) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 1bfbd67c556d..541e796e6db5 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -5072,18 +5072,14 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, * are stored with the acl data to handle the problem of * variable length bitmaps.*/ res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset; - - /* We ignore &savep and don't do consistency checks on - * the attr length. Let userspace figure it out.... */ res->acl_len = attrlen; - if (attrlen > (xdr->nwords << 2)) { - if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { - /* getxattr interface called with a NULL buf */ - goto out; - } + + /* Check for receive buffer overflow */ + if (res->acl_len > (xdr->nwords << 2) || + res->acl_len + res->acl_data_offset > xdr->buf->page_len) { + res->acl_flags |= NFS4_ACL_TRUNC; dprintk("NFS: acl reply: attrlen %u > page_len %u\n", attrlen, xdr->nwords << 2); - return -EINVAL; } } else status = -EOPNOTSUPP; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index ac7c8ae254f2..be9cf3c7e79e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -652,7 +652,7 @@ struct nfs_getaclargs { }; /* getxattr ACL interface flags */ -#define NFS4_ACL_LEN_REQUEST 0x0001 /* zero length getxattr buffer */ +#define NFS4_ACL_TRUNC 0x0001 /* ACL was truncated */ struct nfs_getaclres { size_t acl_len; size_t acl_data_offset; From 80de7c3138ee9fd86a98696fd2cf7ad89b995d0a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 6 Sep 2012 12:01:00 -0400 Subject: [PATCH 414/665] Remove user-triggerable BUG from mpol_to_str Trivially triggerable, found by trinity: kernel BUG at mm/mempolicy.c:2546! Process trinity-child2 (pid: 23988, threadinfo ffff88010197e000, task ffff88007821a670) Call Trace: show_numa_map+0xd5/0x450 show_pid_numa_map+0x13/0x20 traverse+0xf2/0x230 seq_read+0x34b/0x3e0 vfs_read+0xac/0x180 sys_pread64+0xa2/0xc0 system_call_fastpath+0x1a/0x1f RIP: mpol_to_str+0x156/0x360 Cc: stable@vger.kernel.org Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds --- mm/mempolicy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index bd92431d4c49..4ada3be6e252 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2562,7 +2562,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) break; default: - BUG(); + return -EINVAL; } l = strlen(policy_modes[mode]); From ea0e627623e236e4cbec9f44b4a755bc4a4b852d Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 11 Jun 2012 11:13:15 +0200 Subject: [PATCH 415/665] usb: gadget: add multiple definition guards If f_fs.c and u_serial.c are combined together using #include, which has been a common practice so far, the pr_vdebug macro is defined multiple times. Define it only once. Acked-by: Randy Dunlap Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 4 ++++ drivers/usb/gadget/u_serial.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 8adc79d1b402..829aba75a6df 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -34,11 +34,15 @@ /* Debugging ****************************************************************/ #ifdef VERBOSE_DEBUG +#ifndef pr_vdebug # define pr_vdebug pr_debug +#endif /* pr_vdebug */ # define ffs_dump_mem(prefix, ptr, len) \ print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) #else +#ifndef pr_vdebug # define pr_vdebug(...) do { } while (0) +#endif /* pr_vdebug */ # define ffs_dump_mem(prefix, ptr, len) do { } while (0) #endif /* VERBOSE_DEBUG */ diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 5b3f5fffea92..da6d479ff9a6 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -132,11 +132,15 @@ static unsigned n_ports; #ifdef VERBOSE_DEBUG +#ifndef pr_vdebug #define pr_vdebug(fmt, arg...) \ pr_debug(fmt, ##arg) +#endif /* pr_vdebug */ #else +#ifndef pr_vdebig #define pr_vdebug(fmt, arg...) \ ({ if (0) pr_debug(fmt, ##arg); }) +#endif /* pr_vdebug */ #endif /*-------------------------------------------------------------------------*/ From 0416e494ce7dc84e2719bc9fb7daecb330476074 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 10 Aug 2012 13:42:16 +0530 Subject: [PATCH 416/665] usb: dwc3: ep0: correct cache sync issue in case of ep0_bounced In case of ep0 out, if length is not aligned to maxpacket size then we use dwc->ep_bounce_addr for dma transfer and not request->dma. Since, we have alreday done memcpy from dwc->ep0_bounce to request->buf, so we do not need to issue cache sync function. In fact, cache sync function will bring wrong data in request->buf from request->dma in this scenario. So, cache sync function must not be executed in case of ep0 bounced. Cc: # v3.4 v3.5 Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 1 - drivers/usb/dwc3/gadget.c | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9b94886b66e5..e4d5ca86b9da 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -720,7 +720,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, transferred = min_t(u32, ur->length, transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); - dwc->ep0_bounced = false; } else { transferred = ur->length - length; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 58fdfad96b4d..c99568eb4292 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -263,8 +263,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->request.status == -EINPROGRESS) req->request.status = status; - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); + if (dwc->ep0_bounced && dep->number == 0) + dwc->ep0_bounced = false; + else + usb_gadget_unmap_request(&dwc->gadget, &req->request, + req->direction); dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", req, dep->name, req->request.actual, From c8e6507bdec67f1c50390a69a14568c5115cc658 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 08:47:34 +0200 Subject: [PATCH 417/665] usb: gadget: s3c-hsotg.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index b13e0bb5f5b8..0bb617e1dda2 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) if (hsotg->num_of_eps == 0) { dev_err(dev, "wrong number of EPs (zero)\n"); + ret = -EINVAL; goto err_supplies; } @@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!eps) { dev_err(dev, "cannot get memory\n"); + ret = -ENOMEM; goto err_supplies; } @@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!hsotg->ctrl_req) { dev_err(dev, "failed to allocate ctrl req\n"); + ret = -ENOMEM; goto err_ep_mem; } From 1b68a4ca2d038addb7314211d122fb6d7002b38b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 19 Aug 2012 21:54:58 +0200 Subject: [PATCH 418/665] usb: gadget: dummy_hcd: fixup error probe path If USB2 host controller probes fine but USB3 does not then we don't remove the USB controller properly and lock up the system while the HUB code will try to enumerate the USB2 controller and access memory which is no longer available in case the dummy_hcd was compiled as a module. This is a problem since 448b6eb1 ("USB: Make sure to fetch the BOS desc for roothubs.) if used in USB3 mode because dummy does not provide this descriptor and explodes later. Cc: stable@vger.kernel.org # v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index b799106027ad..0e58a46956ae 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -2503,10 +2503,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) hs_hcd->has_tt = 1; retval = usb_add_hcd(hs_hcd, 0, 0); - if (retval != 0) { - usb_put_hcd(hs_hcd); - return retval; - } + if (retval) + goto put_usb2_hcd; if (mod_data.is_super_speed) { ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev, @@ -2525,6 +2523,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) put_usb3_hcd: usb_put_hcd(ss_hcd); dealloc_usb2_hcd: + usb_remove_hcd(hs_hcd); +put_usb2_hcd: usb_put_hcd(hs_hcd); the_controller.hs_hcd = the_controller.ss_hcd = NULL; return retval; From 3b9c1c5ba7a95caae8440ea47308496b14f7301a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 19 Aug 2012 21:54:59 +0200 Subject: [PATCH 419/665] usb: gadget: dummy_hcd: add support for USB_DT_BOS on rh Without a reply for USB_DT_BOS the USB3 mode does not work since 448b6eb1 ("USB: Make sure to fetch the BOS desc for roothubs.). Cc: stable@vger.kernel.org #v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 0e58a46956ae..afdbb1cbf5d9 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1916,6 +1916,27 @@ done: return retval; } +/* usb 3.0 root hub device descriptor */ +struct { + struct usb_bos_descriptor bos; + struct usb_ss_cap_descriptor ss_cap; +} __packed usb3_bos_desc = { + + .bos = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + .wTotalLength = cpu_to_le16(sizeof(usb3_bos_desc)), + .bNumDeviceCaps = 1, + }, + .ss_cap = { + .bLength = USB_DT_USB_SS_CAP_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_SS_CAP_TYPE, + .wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION), + .bFunctionalitySupport = ilog2(USB_5GBPS_OPERATION), + }, +}; + static inline void ss_hub_descriptor(struct usb_hub_descriptor *desc) { @@ -2006,6 +2027,18 @@ static int dummy_hub_control( else hub_descriptor((struct usb_hub_descriptor *) buf); break; + + case DeviceRequest | USB_REQ_GET_DESCRIPTOR: + if (hcd->speed != HCD_USB3) + goto error; + + if ((wValue >> 8) != USB_DT_BOS) + goto error; + + memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc)); + retval = sizeof(usb3_bos_desc); + break; + case GetHubStatus: *(__le32 *) buf = cpu_to_le32(0); break; From 3067779b1566ae5fb6af40f03ae874ac47035523 Mon Sep 17 00:00:00 2001 From: yuzheng ma Date: Wed, 15 Aug 2012 16:11:40 +0800 Subject: [PATCH 420/665] usb: musb: host: fix for musb_start_urb Oops when using musb_urb_enqueue to submit three urbs to the same endpoint, when hep->hcpriv is NULL, qh will be allocated when the first urb is completed. When the IRQ completes the next two urbs, qh->hep->hcpriv will be set to NULL. Now the second urb get musb->lock and executes musb_schedule(), but next_urb(qh) is NULL, so musb_start_urb will Oops. [ balbi@ti.com : practically rewrote commit log so it makes sense ] Signed-off-by: mayuzheng Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 4bb717d0bd41..1ae378d5fc6f 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2049,7 +2049,7 @@ static int musb_urb_enqueue( * we only have work to do in the former case. */ spin_lock_irqsave(&musb->lock, flags); - if (hep->hcpriv) { + if (hep->hcpriv || !next_urb(qh)) { /* some concurrent activity submitted another urb to hep... * odd, rare, error prone, but legal. */ From ff41aaa3b6c181a713078d8ad96da4ba822de436 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 20 Aug 2012 22:31:41 +0400 Subject: [PATCH 421/665] usb: musb: tusb6010: fix error path in tusb_probe() On platform_device_add() failure, the TUSB6010 glue layer forgets to call platform_device_put() -- probably due to a typo... Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi --- drivers/usb/musb/tusb6010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1a1bd9cf40c5..341625442377 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev) ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err1; + goto err2; } return 0; From 7effdbd6512083e21c007edbaca0ceff4aa5159f Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 20 Aug 2012 22:34:46 +0400 Subject: [PATCH 422/665] usb: musb: musbhsdma: fix IRQ check dma_controller_create() in this MUSB DMA driver only regards 0 as a wrong IRQ number, despite platform_get_irq_byname() that it calls returns -ENXIO in that case. It leads to calling request_irq() with a negative IRQ number, and when it naturally fails, the following is printed to the console: request_irq -6 failed! and the DMA controller is not created. Fix this function to filter out the error values as well as 0. Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi --- drivers/usb/musb/musbhsdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 57a608584e16..c1be687e00ec 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base) struct platform_device *pdev = to_platform_device(dev); int irq = platform_get_irq_byname(pdev, "dma"); - if (irq == 0) { + if (irq <= 0) { dev_err(dev, "No DMA interrupt line!\n"); return NULL; } From 066618bc350cc6035c3a0fc559a8ac02f55785a9 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 21 Aug 2012 14:56:16 +0530 Subject: [PATCH 423/665] usb: dwc3: core: fix incorrect usage of resource pointer Populate the resources for xhci afresh instead of directly using the *struct resource* of core. *resource* structure has parent, sibling, child pointers which should be filled only by resource API's. By directly using the *resource* pointer of core in xhci, these parent, sibling, child pointers are already populated even before *platform_device_add* causing side effects. Cc: stable@vger.kernel.org # v3.4, v3.5 Reported-by: Ruchika Kharwar Tested-by: Moiz Sonasath Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a7304f..a68ff53124dc 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -436,16 +436,21 @@ static int __devinit dwc3_probe(struct platform_device *pdev) dev_err(dev, "missing IRQ\n"); return -ENODEV; } - dwc->xhci_resources[1] = *res; + dwc->xhci_resources[1].start = res->start; + dwc->xhci_resources[1].end = res->end; + dwc->xhci_resources[1].flags = res->flags; + dwc->xhci_resources[1].name = res->name; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } - dwc->xhci_resources[0] = *res; + dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; + dwc->xhci_resources[0].flags = res->flags; + dwc->xhci_resources[0].name = res->name; /* * Request memory region but exclude xHCI regs, From 8b7dda554cf61e87523dee412eaf598f8646bd79 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 20 Jul 2012 20:34:24 +0200 Subject: [PATCH 424/665] usb: gadget: at91udc: don't overwrite driver data The driver was converted to the new start/stop interface in f3d8bf34c2 ("usb: gadget: at91_udc: convert to new style start/stop interface"). I overlooked that the driver is overwritting the private data which is used by the composite framework. The udc driver doesn't read it, it is only written here. Tested-by: Fabio Porcedda Tested-by: Mario Isidoro Cc: # v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index c9e66dfb02e6..14df835991af 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1635,7 +1635,6 @@ static int at91_start(struct usb_gadget *gadget, udc->driver = driver; udc->gadget.dev.driver = &driver->driver; udc->gadget.dev.of_node = udc->pdev->dev.of_node; - dev_set_drvdata(&udc->gadget.dev, &driver->driver); udc->enabled = 1; udc->selfpowered = 1; @@ -1656,7 +1655,6 @@ static int at91_stop(struct usb_gadget *gadget, spin_unlock_irqrestore(&udc->lock, flags); udc->gadget.dev.driver = NULL; - dev_set_drvdata(&udc->gadget.dev, NULL); udc->driver = NULL; DBG("unbound from %s\n", driver->driver.name); From f3bb8e63a8ee0398dffe412e774d8801db7e1bf1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 20 Jul 2012 20:34:25 +0200 Subject: [PATCH 425/665] usb: gadget: at91udc: Don't check for ep->ep.desc Earlier we used to check for ep->ep.desc to figure out if this ep has already been enabled and if so, abort. Ido Shayevitz removed the usb_endpoint_descriptor from private udc structure 5a6506f00 ("usb: gadget: Update at91_udc to use usb_endpoint_descriptor inside the struct usb_ep") but did not fix up the ep_enable condition because _now_ the member is always true and we can't check if this ep is enabled twice. Cc: Ido Shayevitz Tested-by: Fabio Porcedda Tested-by: Mario Isidoro Cc: # v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 14df835991af..1e35963bd4ed 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -475,8 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep, unsigned long flags; if (!_ep || !ep - || !desc || ep->ep.desc - || _ep->name == ep0name + || !desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || (maxpacket = usb_endpoint_maxp(desc)) == 0 || maxpacket > ep->maxpacket) { @@ -530,7 +529,6 @@ ok: tmp |= AT91_UDP_EPEDS; __raw_writel(tmp, ep->creg); - ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; /* From 77975eec149506e457e6abe2ce43259895a9a16e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2012 18:01:13 -0700 Subject: [PATCH 426/665] usb: renesas_usbhs: fixup DMA transport data alignment renesas_usbhs dma can transport 8byte alignment data, not 4byte. This patch fixup it. Reported-by: Sugnan Prabhu S Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index ecd173032fd4..143c4e9e1be4 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) usbhs_pipe_is_dcp(pipe)) goto usbhsf_pio_prepare_push; - if (len % 4) /* 32bit alignment */ + if (len & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_push; if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ @@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) /* use PIO if packet is less than pio_dma_border */ len = usbhsf_fifo_rcv_len(priv, fifo); len = min(pkt->length - pkt->actual, len); - if (len % 4) /* 32bit alignment */ + if (len & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_pop_unselect; if (len < usbhs_get_dparam(priv, pio_dma_border)) From f4a53c55117b82e895ec98b1765c9d66940377fc Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Thu, 30 Aug 2012 12:21:43 +0530 Subject: [PATCH 427/665] usb: dwc3: gadget: fix pending isoc handling If xfernotready is received and there is no request in request_list then REQUEST_PENDING flag must be set, so that next request in ep queue is executed. In case of isoc transfer, if xfernotready is already elapsed and even first request has not been queued to request_list, then issue END TRANSFER, so that you can receive xfernotready again and can have notion of current microframe. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c99568eb4292..c2813c2b005a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1029,6 +1029,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, if (list_empty(&dep->request_list)) { dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", dep->name); + dep->flags |= DWC3_EP_PENDING_REQUEST; return; } @@ -1092,6 +1093,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (dep->flags & DWC3_EP_PENDING_REQUEST) { int ret; + /* + * If xfernotready is already elapsed and it is a case + * of isoc transfer, then issue END TRANSFER, so that + * you can receive xfernotready again and can have + * notion of current microframe. + */ + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + dwc3_stop_active_transfer(dwc, dep->number); + return 0; + } + ret = __dwc3_gadget_kick_transfer(dep, 0, true); if (ret && ret != -EBUSY) { struct dwc3 *dwc = dep->dwc; From 60e233a56609fd963c59e99bd75c663d63fa91b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 2 Sep 2012 15:41:34 +0200 Subject: [PATCH 428/665] kobject: fix oops with "input0: bad kobj_uevent_env content in show_uevent()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fengguang Wu writes: > After the __devinit* removal series, I can still get kernel panic in > show_uevent(). So there are more sources of bug.. > > Debug patch: > > @@ -343,8 +343,11 @@ static ssize_t show_uevent(struct device > goto out; > > /* copy keys to file */ > - for (i = 0; i < env->envp_idx; i++) > + dev_err(dev, "uevent %d env[%d]: %s/.../%s\n", env->buflen, env->envp_idx, top_kobj->name, dev->kobj.name); > + for (i = 0; i < env->envp_idx; i++) { > + printk(KERN_ERR "uevent %d env[%d]: %s\n", (int)count, i, env->envp[i]); > count += sprintf(&buf[count], "%s\n", env->envp[i]); > + } > > Oops message, the env[] is again not properly initilized: > > [ 44.068623] input input0: uevent 61 env[805306368]: input0/.../input0 > [ 44.069552] uevent 0 env[0]: (null) This is a completely different CONFIG_HOTPLUG problem, only demonstrating another reason why CONFIG_HOTPLUG should go away. I had a hard time trying to disable it anyway ;-) The problem this time is lots of code assuming that a call to add_uevent_var() will guarantee that env->buflen > 0. This is not true if CONFIG_HOTPLUG is unset. So things like this end up overwriting env->envp_idx because the array index is -1: if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; len = input_print_modalias(&env->buf[env->buflen - 1], sizeof(env->buf) - env->buflen, dev, 0); Don't know what the best action is, given that there seem to be a *lot* of this around the kernel. This patch "fixes" the problem for me, but I don't know if it can be considered an appropriate fix. [ It is the correct fix for now, for 3.7 forcing CONFIG_HOTPLUG to always be on is the longterm fix, but it's too late for 3.6 and older kernels to resolve this that way - gregkh ] Reported-by: Fengguang Wu Signed-off-by: Bjørn Mork Tested-by: Fengguang Wu Cc: stable Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/kobject.h b/include/linux/kobject.h index fc615a97e2d3..1e57449395b1 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -224,7 +224,7 @@ static inline int kobject_uevent_env(struct kobject *kobj, static inline __printf(2, 3) int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) -{ return 0; } +{ return -ENOMEM; } static inline int kobject_action_type(const char *buf, size_t count, enum kobject_action *type) From e2f2886a824ff0a56da1eaa13019fde86aa89fa6 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Wed, 29 Aug 2012 21:13:38 +0400 Subject: [PATCH 429/665] CIFS: Fix error handling in cifs_push_mandatory_locks Cc: Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9154192b0683..71e9ad9f5961 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -917,7 +917,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) if (!buf) { mutex_unlock(&cinode->lock_mutex); free_xid(xid); - return rc; + return -ENOMEM; } for (i = 0; i < 2; i++) { From b2ede58e98c87c7f0f44a926f974262f65c3402f Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Tue, 4 Sep 2012 15:49:31 +0400 Subject: [PATCH 430/665] CIFS: Fix endianness conversion Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/smb2pdu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index c5fbfac5d576..15dc8eea8273 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -96,7 +96,7 @@ * */ -#define SMB2_HEADER_STRUCTURE_SIZE __constant_le16_to_cpu(64) +#define SMB2_HEADER_STRUCTURE_SIZE __constant_cpu_to_le16(64) struct smb2_hdr { __be32 smb2_buf_length; /* big endian on wire */ @@ -140,7 +140,7 @@ struct smb2_pdu { * */ -#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9) +#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_cpu_to_le16(9) struct smb2_err_rsp { struct smb2_hdr hdr; From 01913b49cf1dc6409a07dd2a4cc6af2e77f3c410 Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Thu, 6 Sep 2012 15:54:27 -0400 Subject: [PATCH 431/665] NFS: return error from decode_getfh in decode open If decode_getfh failed, nfs4_xdr_dec_open would return 0 since the last decode_* call must have succeeded. Cc: stable@vger.kernel.org Signed-off-by: Weston Andros Adamson Signed-off-by: Trond Myklebust --- fs/nfs/nfs4xdr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 541e796e6db5..8dba6bd48557 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -6225,7 +6225,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, status = decode_open(xdr, res); if (status) goto out; - if (decode_getfh(xdr, &res->fh) != 0) + status = decode_getfh(xdr, &res->fh); + if (status) goto out; decode_getfattr(xdr, res->f_attr, res->server); out: From 3b75a2c126c4b573553856e0fe08d1bb020ca8c3 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Thu, 23 Aug 2012 18:39:57 -0400 Subject: [PATCH 432/665] crypto/caam: Export gen_split_key symbol for other modules In 3.6-rc3, without this patch, the following error occurs with a modular build: ERROR: "gen_split_key" [drivers/crypto/caam/caamhash.ko] undefined! ERROR: "gen_split_key" [drivers/crypto/caam/caamalg.ko] undefined! Signed-off-by: Ben Collins Cc: Yuan Kang Acked-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/key_gen.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c index 002888185f17..d216cd3cc569 100644 --- a/drivers/crypto/caam/key_gen.c +++ b/drivers/crypto/caam/key_gen.c @@ -120,3 +120,4 @@ u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, return ret; } +EXPORT_SYMBOL(gen_split_key); From a32826e4aefa905b392d2d862d51365d50d4829b Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 6 Sep 2012 17:47:33 -0600 Subject: [PATCH 433/665] ASoC: tegra: fix maxburst settings in dmaengine code The I2S controllers are programmed with an "attention" level of 4 DWORDs. This must match the configuration passed to the DMA driver, so that when they burst in data, they don't overflow the available FIFO space. Also, the burst size is relevant to the destination for playback, and source for capture, not vice-versa as originally written. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/tegra/tegra_pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 5658bcec1931..8d6900c1ee47 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -334,11 +334,11 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.dst_addr = dmap->addr; - slave_config.src_maxburst = 0; + slave_config.dst_maxburst = 4; } else { slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.src_addr = dmap->addr; - slave_config.dst_maxburst = 0; + slave_config.src_maxburst = 4; } slave_config.slave_id = dmap->req_sel; From 5d2afab958f8cd203a8fe639082b5b5e74f748f9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 21:38:49 -0400 Subject: [PATCH 434/665] drm/vmwgfx: allow a kconfig option to choose if fbcon is enabled This makes things easier for distros where we'd like to have fbcon enabled all the time. Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/Kconfig | 8 ++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig index 794ff67c5701..b71bcd0bfbbf 100644 --- a/drivers/gpu/drm/vmwgfx/Kconfig +++ b/drivers/gpu/drm/vmwgfx/Kconfig @@ -12,3 +12,11 @@ config DRM_VMWGFX This is a KMS enabled DRM driver for the VMware SVGA2 virtual hardware. The compiled module will be called "vmwgfx.ko". + +config DRM_VMWGFX_FBCON + depends on DRM_VMWGFX + bool "Enable framebuffer console under vmwgfx by default" + help + Choose this option if you are shipping a new vmwgfx + userspace driver that supports using the kernel driver. + diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4d9edead01ac..7f4f4eecf45a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -183,7 +183,7 @@ static struct pci_device_id vmw_pci_id_list[] = { {0, 0, 0} }; -static int enable_fbdev; +static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON); static int vmw_probe(struct pci_dev *, const struct pci_device_id *); static void vmw_master_init(struct vmw_master *); From c4903429a92be60e6fe59868924a65eca4cd1a38 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 21:40:51 -0400 Subject: [PATCH 435/665] drm/vmwgfx: add MODULE_DEVICE_TABLE so vmwgfx loads at boot This will cause udev to load vmwgfx instead of waiting for X to do it. Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 7f4f4eecf45a..33bfc2033009 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -182,6 +182,7 @@ static struct pci_device_id vmw_pci_id_list[] = { {0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII}, {0, 0, 0} }; +MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON); From 50888469bda11bcff306893bbaff21f25894be0b Mon Sep 17 00:00:00 2001 From: Steven Miao Date: Tue, 31 Jul 2012 17:28:10 +0800 Subject: [PATCH 436/665] blackfin: smp: adapt to generic smp helpers Replace blackfin ipi message queue with generic smp helper function. Signed-off-by: Steven Miao Signed-off-by: Bob Liu --- arch/blackfin/Kconfig | 1 + arch/blackfin/include/asm/smp.h | 2 + arch/blackfin/mach-common/smp.c | 217 ++++++++++---------------------- 3 files changed, 66 insertions(+), 154 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index f34861920634..c7092e6057c5 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -38,6 +38,7 @@ config BLACKFIN select GENERIC_ATOMIC64 select GENERIC_IRQ_PROBE select IRQ_PER_CPU if SMP + select USE_GENERIC_SMP_HELPERS if SMP select HAVE_NMI_WATCHDOG if NMI_WATCHDOG select GENERIC_SMP_IDLE_THREAD select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h index dc3d144b4bb5..9631598dcc5d 100644 --- a/arch/blackfin/include/asm/smp.h +++ b/arch/blackfin/include/asm/smp.h @@ -18,6 +18,8 @@ #define raw_smp_processor_id() blackfin_core_id() extern void bfin_relocate_coreb_l1_mem(void); +extern void arch_send_call_function_single_ipi(int cpu); +extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); #if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1) asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr); diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 00bbe672b3b3..a40151306b77 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -48,10 +48,13 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS]; struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; -#define BFIN_IPI_TIMER 0 -#define BFIN_IPI_RESCHEDULE 1 -#define BFIN_IPI_CALL_FUNC 2 -#define BFIN_IPI_CPU_STOP 3 +enum ipi_message_type { + BFIN_IPI_TIMER, + BFIN_IPI_RESCHEDULE, + BFIN_IPI_CALL_FUNC, + BFIN_IPI_CALL_FUNC_SINGLE, + BFIN_IPI_CPU_STOP, +}; struct blackfin_flush_data { unsigned long start; @@ -60,35 +63,20 @@ struct blackfin_flush_data { void *secondary_stack; - -struct smp_call_struct { - void (*func)(void *info); - void *info; - int wait; - cpumask_t *waitmask; -}; - static struct blackfin_flush_data smp_flush_data; static DEFINE_SPINLOCK(stop_lock); -struct ipi_message { - unsigned long type; - struct smp_call_struct call_struct; -}; - /* A magic number - stress test shows this is safe for common cases */ #define BFIN_IPI_MSGQ_LEN 5 /* Simple FIFO buffer, overflow leads to panic */ -struct ipi_message_queue { - spinlock_t lock; +struct ipi_data { unsigned long count; - unsigned long head; /* head of the queue */ - struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN]; + unsigned long bits; }; -static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue); +static DEFINE_PER_CPU(struct ipi_data, bfin_ipi); static void ipi_cpu_stop(unsigned int cpu) { @@ -129,28 +117,6 @@ static void ipi_flush_icache(void *info) blackfin_icache_flush_range(fdata->start, fdata->end); } -static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) -{ - int wait; - void (*func)(void *info); - void *info; - func = msg->call_struct.func; - info = msg->call_struct.info; - wait = msg->call_struct.wait; - func(info); - if (wait) { -#ifdef __ARCH_SYNC_CORE_DCACHE - /* - * 'wait' usually means synchronization between CPUs. - * Invalidate D cache in case shared data was changed - * by func() to ensure cache coherence. - */ - resync_core_dcache(); -#endif - cpumask_clear_cpu(cpu, msg->call_struct.waitmask); - } -} - /* Use IRQ_SUPPLE_0 to request reschedule. * When returning from interrupt to user space, * there is chance to reschedule */ @@ -172,152 +138,95 @@ void ipi_timer(void) static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) { - struct ipi_message *msg; - struct ipi_message_queue *msg_queue; + struct ipi_data *bfin_ipi_data; unsigned int cpu = smp_processor_id(); - unsigned long flags; + unsigned long pending; + unsigned long msg; platform_clear_ipi(cpu, IRQ_SUPPLE_1); - msg_queue = &__get_cpu_var(ipi_msg_queue); + bfin_ipi_data = &__get_cpu_var(bfin_ipi); - spin_lock_irqsave(&msg_queue->lock, flags); + while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) { + msg = 0; + do { + msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); + switch (msg) { + case BFIN_IPI_TIMER: + ipi_timer(); + break; + case BFIN_IPI_RESCHEDULE: + scheduler_ipi(); + break; + case BFIN_IPI_CALL_FUNC: + generic_smp_call_function_interrupt(); + break; - while (msg_queue->count) { - msg = &msg_queue->ipi_message[msg_queue->head]; - switch (msg->type) { - case BFIN_IPI_TIMER: - ipi_timer(); - break; - case BFIN_IPI_RESCHEDULE: - scheduler_ipi(); - break; - case BFIN_IPI_CALL_FUNC: - ipi_call_function(cpu, msg); - break; - case BFIN_IPI_CPU_STOP: - ipi_cpu_stop(cpu); - break; - default: - printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n", - cpu, msg->type); - break; - } - msg_queue->head++; - msg_queue->head %= BFIN_IPI_MSGQ_LEN; - msg_queue->count--; + case BFIN_IPI_CALL_FUNC_SINGLE: + generic_smp_call_function_single_interrupt(); + break; + + case BFIN_IPI_CPU_STOP: + ipi_cpu_stop(cpu); + break; + } + } while (msg < BITS_PER_LONG); + + smp_mb(); } - spin_unlock_irqrestore(&msg_queue->lock, flags); return IRQ_HANDLED; } -static void ipi_queue_init(void) +static void bfin_ipi_init(void) { unsigned int cpu; - struct ipi_message_queue *msg_queue; + struct ipi_data *bfin_ipi_data; for_each_possible_cpu(cpu) { - msg_queue = &per_cpu(ipi_msg_queue, cpu); - spin_lock_init(&msg_queue->lock); - msg_queue->count = 0; - msg_queue->head = 0; + bfin_ipi_data = &per_cpu(bfin_ipi, cpu); + bfin_ipi_data->bits = 0; + bfin_ipi_data->count = 0; } } -static inline void smp_send_message(cpumask_t callmap, unsigned long type, - void (*func) (void *info), void *info, int wait) +void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg) { unsigned int cpu; - struct ipi_message_queue *msg_queue; - struct ipi_message *msg; - unsigned long flags, next_msg; - cpumask_t waitmask; /* waitmask is shared by all cpus */ + struct ipi_data *bfin_ipi_data; + unsigned long flags; - cpumask_copy(&waitmask, &callmap); - for_each_cpu(cpu, &callmap) { - msg_queue = &per_cpu(ipi_msg_queue, cpu); - spin_lock_irqsave(&msg_queue->lock, flags); - if (msg_queue->count < BFIN_IPI_MSGQ_LEN) { - next_msg = (msg_queue->head + msg_queue->count) - % BFIN_IPI_MSGQ_LEN; - msg = &msg_queue->ipi_message[next_msg]; - msg->type = type; - if (type == BFIN_IPI_CALL_FUNC) { - msg->call_struct.func = func; - msg->call_struct.info = info; - msg->call_struct.wait = wait; - msg->call_struct.waitmask = &waitmask; - } - msg_queue->count++; - } else - panic("IPI message queue overflow\n"); - spin_unlock_irqrestore(&msg_queue->lock, flags); + local_irq_save(flags); + + for_each_cpu(cpu, cpumask) { + bfin_ipi_data = &per_cpu(bfin_ipi, cpu); + smp_mb(); + set_bit(msg, &bfin_ipi_data->bits); + bfin_ipi_data->count++; platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); } - if (wait) { - while (!cpumask_empty(&waitmask)) - blackfin_dcache_invalidate_range( - (unsigned long)(&waitmask), - (unsigned long)(&waitmask)); -#ifdef __ARCH_SYNC_CORE_DCACHE - /* - * Invalidate D cache in case shared data was changed by - * other processors to ensure cache coherence. - */ - resync_core_dcache(); -#endif - } + local_irq_restore(flags); } -int smp_call_function(void (*func)(void *info), void *info, int wait) +void arch_send_call_function_single_ipi(int cpu) { - cpumask_t callmap; - - preempt_disable(); - cpumask_copy(&callmap, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), &callmap); - if (!cpumask_empty(&callmap)) - smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); - - preempt_enable(); - - return 0; + send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC_SINGLE); } -EXPORT_SYMBOL_GPL(smp_call_function); -int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, - int wait) +void arch_send_call_function_ipi_mask(const struct cpumask *mask) { - unsigned int cpu = cpuid; - cpumask_t callmap; - - if (cpu_is_offline(cpu)) - return 0; - cpumask_clear(&callmap); - cpumask_set_cpu(cpu, &callmap); - - smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); - - return 0; + send_ipi(mask, BFIN_IPI_CALL_FUNC); } -EXPORT_SYMBOL_GPL(smp_call_function_single); void smp_send_reschedule(int cpu) { - cpumask_t callmap; - /* simply trigger an ipi */ - - cpumask_clear(&callmap); - cpumask_set_cpu(cpu, &callmap); - - smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0); + send_ipi(cpumask_of(cpu), BFIN_IPI_RESCHEDULE); return; } void smp_send_msg(const struct cpumask *mask, unsigned long type) { - smp_send_message(*mask, type, NULL, NULL, 0); + send_ipi(mask, type); } void smp_timer_broadcast(const struct cpumask *mask) @@ -333,7 +242,7 @@ void smp_send_stop(void) cpumask_copy(&callmap, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), &callmap); if (!cpumask_empty(&callmap)) - smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0); + send_ipi(&callmap, BFIN_IPI_CPU_STOP); preempt_enable(); @@ -436,7 +345,7 @@ void __init smp_prepare_boot_cpu(void) void __init smp_prepare_cpus(unsigned int max_cpus) { platform_prepare_cpus(max_cpus); - ipi_queue_init(); + bfin_ipi_init(); platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0); platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1); } From aad932e75c573aec37a0652ff1c27a975d8d5373 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Thu, 30 Aug 2012 14:37:14 +0200 Subject: [PATCH 437/665] HID: tpkbd: work even if the new Lenovo Keyboard driver is not configured c1dcad2d32d0252e8a3023d20311b52a187ecda3 added a new driver configured by HID_LENOVO_TPKBD but made the hid_have_special_driver entry non-optional which lead to a recognized but non-working device if the new driver wasn't configured (which is the correct default). Signed-off-by: Andres Freund Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b8485a0106c9..8bcd168fffae 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1559,7 +1559,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, +#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD) + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, +#endif { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, From f39c1bfb5a03e2d255451bff05be0d7255298fa4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 7 Sep 2012 11:08:50 -0400 Subject: [PATCH 438/665] SUNRPC: Fix a UDP transport regression Commit 43cedbf0e8dfb9c5610eb7985d5f21263e313802 (SUNRPC: Ensure that we grab the XPRT_LOCK before calling xprt_alloc_slot) is causing hangs in the case of NFS over UDP mounts. Since neither the UDP or the RDMA transport mechanism use dynamic slot allocation, we can skip grabbing the socket lock for those transports. Add a new rpc_xprt_op to allow switching between the TCP and UDP/RDMA case. Note that the NFSv4.1 back channel assigns the slot directly through rpc_run_bc_task, so we can ignore that case. Reported-by: Dick Streefland Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>= 3.1] --- include/linux/sunrpc/xprt.h | 3 +++ net/sunrpc/xprt.c | 34 +++++++++++++++++++-------------- net/sunrpc/xprtrdma/transport.c | 1 + net/sunrpc/xprtsock.c | 3 +++ 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index cff40aa7db62..bf8c49ff7530 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -114,6 +114,7 @@ struct rpc_xprt_ops { void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); + void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task); void (*rpcbind)(struct rpc_task *task); void (*set_port)(struct rpc_xprt *xprt, unsigned short port); void (*connect)(struct rpc_task *task); @@ -281,6 +282,8 @@ void xprt_connect(struct rpc_task *task); void xprt_reserve(struct rpc_task *task); int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); +void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); +void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_prepare_transmit(struct rpc_task *task); void xprt_transmit(struct rpc_task *task); void xprt_end_transmit(struct rpc_task *task); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index a5a402a7d21f..5d7f61d7559c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) return false; } -static void xprt_alloc_slot(struct rpc_task *task) +void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; struct rpc_rqst *req; + spin_lock(&xprt->reserve_lock); if (!list_empty(&xprt->free)) { req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); list_del(&req->rq_list); @@ -994,12 +994,29 @@ static void xprt_alloc_slot(struct rpc_task *task) default: task->tk_status = -EAGAIN; } + spin_unlock(&xprt->reserve_lock); return; out_init_req: task->tk_status = 0; task->tk_rqstp = req; xprt_request_init(task, xprt); + spin_unlock(&xprt->reserve_lock); } +EXPORT_SYMBOL_GPL(xprt_alloc_slot); + +void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) +{ + /* Note: grabbing the xprt_lock_write() ensures that we throttle + * new slot allocation if the transport is congested (i.e. when + * reconnecting a stream transport or when out of socket write + * buffer space). + */ + if (xprt_lock_write(xprt, task)) { + xprt_alloc_slot(xprt, task); + xprt_release_write(xprt, task); + } +} +EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) { @@ -1083,20 +1100,9 @@ void xprt_reserve(struct rpc_task *task) if (task->tk_rqstp != NULL) return; - /* Note: grabbing the xprt_lock_write() here is not strictly needed, - * but ensures that we throttle new slot allocation if the transport - * is congested (e.g. if reconnecting or if we're out of socket - * write buffer space). - */ task->tk_timeout = 0; task->tk_status = -EAGAIN; - if (!xprt_lock_write(xprt, task)) - return; - - spin_lock(&xprt->reserve_lock); - xprt_alloc_slot(task); - spin_unlock(&xprt->reserve_lock); - xprt_release_write(xprt, task); + xprt->ops->alloc_slot(xprt, task); } static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 06cdbff79e4a..5d9202dc7cb1 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -713,6 +713,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) static struct rpc_xprt_ops xprt_rdma_procs = { .reserve_xprt = xprt_rdma_reserve_xprt, .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ + .alloc_slot = xprt_alloc_slot, .release_request = xprt_release_rqst_cong, /* ditto */ .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 400567243f84..a35b8e52e551 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2473,6 +2473,7 @@ static void bc_destroy(struct rpc_xprt *xprt) static struct rpc_xprt_ops xs_local_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, + .alloc_slot = xprt_alloc_slot, .rpcbind = xs_local_rpcbind, .set_port = xs_local_set_port, .connect = xs_connect, @@ -2489,6 +2490,7 @@ static struct rpc_xprt_ops xs_udp_ops = { .set_buffer_size = xs_udp_set_buffer_size, .reserve_xprt = xprt_reserve_xprt_cong, .release_xprt = xprt_release_xprt_cong, + .alloc_slot = xprt_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, @@ -2506,6 +2508,7 @@ static struct rpc_xprt_ops xs_udp_ops = { static struct rpc_xprt_ops xs_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, + .alloc_slot = xprt_lock_and_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, From a8edc3bf05a3465726afdf635a820761fae0d50b Mon Sep 17 00:00:00 2001 From: Hadar Hen Zion Date: Wed, 5 Sep 2012 22:50:48 +0000 Subject: [PATCH 439/665] net/mlx4_core: Put Firmware flow steering structures in common header files To allow for usage of the flow steering Firmware structures in more locations over the driver, such as the resource tracker, move them from mcg.c to common header files. Signed-off-by: Hadar Hen Zion Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/mcg.c | 90 ++--------------------- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 76 +++++++++++++++++++ include/linux/mlx4/device.h | 2 + 3 files changed, 85 insertions(+), 83 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index a018ea2a43de..2673f3ba935f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -650,13 +650,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port, return err; } -struct mlx4_net_trans_rule_hw_ctrl { - __be32 ctrl; - __be32 vf_vep_port; - __be32 qpn; - __be32 reserved; -}; - static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, struct mlx4_net_trans_rule_hw_ctrl *hw) { @@ -680,87 +673,18 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, hw->qpn = cpu_to_be32(ctrl->qpn); } -struct mlx4_net_trans_rule_hw_ib { - u8 size; - u8 rsvd1; - __be16 id; - u32 rsvd2; - __be32 qpn; - __be32 qpn_mask; - u8 dst_gid[16]; - u8 dst_gid_msk[16]; -} __packed; - -struct mlx4_net_trans_rule_hw_eth { - u8 size; - u8 rsvd; - __be16 id; - u8 rsvd1[6]; - u8 dst_mac[6]; - u16 rsvd2; - u8 dst_mac_msk[6]; - u16 rsvd3; - u8 src_mac[6]; - u16 rsvd4; - u8 src_mac_msk[6]; - u8 rsvd5; - u8 ether_type_enable; - __be16 ether_type; - __be16 vlan_id_msk; - __be16 vlan_id; -} __packed; - -struct mlx4_net_trans_rule_hw_tcp_udp { - u8 size; - u8 rsvd; - __be16 id; - __be16 rsvd1[3]; - __be16 dst_port; - __be16 rsvd2; - __be16 dst_port_msk; - __be16 rsvd3; - __be16 src_port; - __be16 rsvd4; - __be16 src_port_msk; -} __packed; - -struct mlx4_net_trans_rule_hw_ipv4 { - u8 size; - u8 rsvd; - __be16 id; - __be32 rsvd1; - __be32 dst_ip; - __be32 dst_ip_msk; - __be32 src_ip; - __be32 src_ip_msk; -} __packed; - -struct _rule_hw { - union { - struct { - u8 size; - u8 rsvd; - __be16 id; - }; - struct mlx4_net_trans_rule_hw_eth eth; - struct mlx4_net_trans_rule_hw_ib ib; - struct mlx4_net_trans_rule_hw_ipv4 ipv4; - struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; - }; +const u16 __sw_id_hw[] = { + [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, + [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, + [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, + [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, + [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, + [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 }; static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec, struct _rule_hw *rule_hw) { - static const u16 __sw_id_hw[] = { - [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, - [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, - [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, - [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, - [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, - [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 - }; - static const size_t __rule_hw_sz[] = { [MLX4_NET_TRANS_RULE_ID_ETH] = sizeof(struct mlx4_net_trans_rule_hw_eth), diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 4d9df8f2a126..dba69d98734a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -690,6 +690,82 @@ struct mlx4_steer { struct list_head steer_entries[MLX4_NUM_STEERS]; }; +struct mlx4_net_trans_rule_hw_ctrl { + __be32 ctrl; + __be32 vf_vep_port; + __be32 qpn; + __be32 reserved; +}; + +struct mlx4_net_trans_rule_hw_ib { + u8 size; + u8 rsvd1; + __be16 id; + u32 rsvd2; + __be32 qpn; + __be32 qpn_mask; + u8 dst_gid[16]; + u8 dst_gid_msk[16]; +} __packed; + +struct mlx4_net_trans_rule_hw_eth { + u8 size; + u8 rsvd; + __be16 id; + u8 rsvd1[6]; + u8 dst_mac[6]; + u16 rsvd2; + u8 dst_mac_msk[6]; + u16 rsvd3; + u8 src_mac[6]; + u16 rsvd4; + u8 src_mac_msk[6]; + u8 rsvd5; + u8 ether_type_enable; + __be16 ether_type; + __be16 vlan_id_msk; + __be16 vlan_id; +} __packed; + +struct mlx4_net_trans_rule_hw_tcp_udp { + u8 size; + u8 rsvd; + __be16 id; + __be16 rsvd1[3]; + __be16 dst_port; + __be16 rsvd2; + __be16 dst_port_msk; + __be16 rsvd3; + __be16 src_port; + __be16 rsvd4; + __be16 src_port_msk; +} __packed; + +struct mlx4_net_trans_rule_hw_ipv4 { + u8 size; + u8 rsvd; + __be16 id; + __be32 rsvd1; + __be32 dst_ip; + __be32 dst_ip_msk; + __be32 src_ip; + __be32 src_ip_msk; +} __packed; + +struct _rule_hw { + union { + struct { + u8 size; + u8 rsvd; + __be16 id; + }; + struct mlx4_net_trans_rule_hw_eth eth; + struct mlx4_net_trans_rule_hw_ib ib; + struct mlx4_net_trans_rule_hw_ipv4 ipv4; + struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; + }; +}; + struct mlx4_priv { struct mlx4_dev dev; diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index bd6c9fcdf2dd..244ba902ab72 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -796,6 +796,8 @@ enum mlx4_net_trans_rule_id { MLX4_NET_TRANS_RULE_NUM, /* should be last */ }; +extern const u16 __sw_id_hw[]; + enum mlx4_net_trans_promisc_mode { MLX4_FS_PROMISC_NONE = 0, MLX4_FS_PROMISC_UPLINK, From 7fb40f87c4195ec1728527f30bc744c47a45b366 Mon Sep 17 00:00:00 2001 From: Hadar Hen Zion Date: Wed, 5 Sep 2012 22:50:49 +0000 Subject: [PATCH 440/665] net/mlx4_core: Add security check / enforcement for flow steering rules set for VMs Since VFs may be mapped to VMs which aren't trusted entities, flow steering rules attached through the wrapper on behalf of VFs must be checked to make sure that their L2 specification relate to MAC address assigned to that VF, and add L2 specification if its missing. Signed-off-by: Hadar Hen Zion Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlx4/resource_tracker.c | 116 ++++++++++++++++++ include/linux/mlx4/device.h | 11 ++ 2 files changed, 127 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 94ceddd17ab2..293c9e820c49 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "mlx4.h" #include "fw.h" @@ -2776,18 +2777,133 @@ ex_put: return err; } +/* + * MAC validation for Flow Steering rules. + * VF can attach rules only with a mac address which is assigned to it. + */ +static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header, + struct list_head *rlist) +{ + struct mac_res *res, *tmp; + __be64 be_mac; + + /* make sure it isn't multicast or broadcast mac*/ + if (!is_multicast_ether_addr(eth_header->eth.dst_mac) && + !is_broadcast_ether_addr(eth_header->eth.dst_mac)) { + list_for_each_entry_safe(res, tmp, rlist, list) { + be_mac = cpu_to_be64(res->mac << 16); + if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN)) + return 0; + } + pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n", + eth_header->eth.dst_mac, slave); + return -EINVAL; + } + return 0; +} + +/* + * In case of missing eth header, append eth header with a MAC address + * assigned to the VF. + */ +static int add_eth_header(struct mlx4_dev *dev, int slave, + struct mlx4_cmd_mailbox *inbox, + struct list_head *rlist, int header_id) +{ + struct mac_res *res, *tmp; + u8 port; + struct mlx4_net_trans_rule_hw_ctrl *ctrl; + struct mlx4_net_trans_rule_hw_eth *eth_header; + struct mlx4_net_trans_rule_hw_ipv4 *ip_header; + struct mlx4_net_trans_rule_hw_tcp_udp *l4_header; + __be64 be_mac = 0; + __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); + + ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; + port = be32_to_cpu(ctrl->vf_vep_port) & 0xff; + eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1); + + /* Clear a space in the inbox for eth header */ + switch (header_id) { + case MLX4_NET_TRANS_RULE_ID_IPV4: + ip_header = + (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1); + memmove(ip_header, eth_header, + sizeof(*ip_header) + sizeof(*l4_header)); + break; + case MLX4_NET_TRANS_RULE_ID_TCP: + case MLX4_NET_TRANS_RULE_ID_UDP: + l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *) + (eth_header + 1); + memmove(l4_header, eth_header, sizeof(*l4_header)); + break; + default: + return -EINVAL; + } + list_for_each_entry_safe(res, tmp, rlist, list) { + if (port == res->port) { + be_mac = cpu_to_be64(res->mac << 16); + break; + } + } + if (!be_mac) { + pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n", + port); + return -EINVAL; + } + + memset(eth_header, 0, sizeof(*eth_header)); + eth_header->size = sizeof(*eth_header) >> 2; + eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]); + memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN); + memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN); + + return 0; + +} + int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd) { + + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; + struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; int err; + struct mlx4_net_trans_rule_hw_ctrl *ctrl; + struct _rule_hw *rule_header; + int header_id; if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) return -EOPNOTSUPP; + ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; + rule_header = (struct _rule_hw *)(ctrl + 1); + header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); + + switch (header_id) { + case MLX4_NET_TRANS_RULE_ID_ETH: + if (validate_eth_header_mac(slave, rule_header, rlist)) + return -EINVAL; + break; + case MLX4_NET_TRANS_RULE_ID_IPV4: + case MLX4_NET_TRANS_RULE_ID_TCP: + case MLX4_NET_TRANS_RULE_ID_UDP: + pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); + if (add_eth_header(dev, slave, inbox, rlist, header_id)) + return -EINVAL; + vhcr->in_modifier += + sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; + break; + default: + pr_err("Corrupted mailbox.\n"); + return -EINVAL; + } + err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, vhcr->in_modifier, 0, MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 244ba902ab72..6e1b0f973a03 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -798,6 +798,17 @@ enum mlx4_net_trans_rule_id { extern const u16 __sw_id_hw[]; +static inline int map_hw_to_sw_id(u16 header_id) +{ + + int i; + for (i = 0; i < MLX4_NET_TRANS_RULE_NUM; i++) { + if (header_id == __sw_id_hw[i]) + return i; + } + return -EINVAL; +} + enum mlx4_net_trans_promisc_mode { MLX4_FS_PROMISC_NONE = 0, MLX4_FS_PROMISC_UPLINK, From 60d31c1475f20b6966f7efbd646b1123d0fba5b1 Mon Sep 17 00:00:00 2001 From: Aviad Yehezkel Date: Wed, 5 Sep 2012 22:50:50 +0000 Subject: [PATCH 441/665] net/mlx4_core: Looking for promiscuous entries on the correct port The search for promisc entries was always done on the first port, While the addition is done on the correct port. This lead to resource leackage of promisc entries on the second port and brought to a state where we could no longer enter to promiscuous mode after enough iterations of "ifconfig promisc" on the second port. Fix that by using the correct port when searching. Reported-by: Marcelo Ricardo Leitner Signed-off-by: Aviad Yehezkel Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/mcg.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 2673f3ba935f..e151c21baf2b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, return err; } -static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, +static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port, enum mlx4_steer_type steer, u32 qpn) { - struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num]; + struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1]; struct mlx4_promisc_qp *pqp; list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { @@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, /* If the given qpn is also a promisc qp, * it should be inserted to duplicates list */ - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, port, steer, qpn); if (pqp) { dqp = kmalloc(sizeof *dqp, GFP_KERNEL); if (!dqp) { @@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, port, steer, qpn); if (!pqp) return 0; /* nothing to do */ @@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; /* if qp is not promisc, it cannot be duplicated */ - if (!get_promisc_qp(dev, 0, steer, qpn)) + if (!get_promisc_qp(dev, port, steer, qpn)) return false; /* The qp is promisc qp so it is a duplicate on this index @@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, members_count = be32_to_cpu(mgm->members_count) & 0xffffff; for (i = 0; i < members_count; i++) { qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; - if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { + if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) { /* the qp is not promisc, the entry can't be removed */ goto out; } @@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, mutex_lock(&priv->mcg_table.mutex); - if (get_promisc_qp(dev, 0, steer, qpn)) { + if (get_promisc_qp(dev, port, steer, qpn)) { err = 0; /* Noting to do, already exists */ goto out_mutex; } @@ -503,7 +503,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; mutex_lock(&priv->mcg_table.mutex); - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, port, steer, qpn); if (unlikely(!pqp)) { mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); /* nothing to do */ From bef772eb06051f49e84c3168f189b65074f19c3d Mon Sep 17 00:00:00 2001 From: Aviad Yehezkel Date: Wed, 5 Sep 2012 22:50:51 +0000 Subject: [PATCH 442/665] net/mlx4_core: Fixing error flow in case of QUERY_FW failure The order of operations was wrong on the teardown flow. Signed-off-by: Aviad Yehezkel Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 827b72dfce99..0fadac546b00 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1234,13 +1234,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev) mlx4_info(dev, "non-primary physical function, skipping.\n"); else mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); - goto unmap_bf; + return err; } err = mlx4_load_fw(dev); if (err) { mlx4_err(dev, "Failed to start FW, aborting.\n"); - goto unmap_bf; + return err; } mlx4_cfg.log_pg_sz_m = 1; @@ -1304,7 +1304,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) err = mlx4_init_slave(dev); if (err) { mlx4_err(dev, "Failed to initialize slave\n"); - goto unmap_bf; + return err; } err = mlx4_slave_cap(dev); @@ -1324,7 +1324,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) err = mlx4_QUERY_ADAPTER(dev, &adapter); if (err) { mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); - goto err_close; + goto unmap_bf; } priv->eq_table.inta_pin = adapter.inta_pin; @@ -1332,6 +1332,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev) return 0; +unmap_bf: + unmap_bf_area(dev); + err_close: mlx4_close_hca(dev); @@ -1344,8 +1347,6 @@ err_stop_fw: mlx4_UNMAP_FA(dev); mlx4_free_icm(dev, priv->fw.fw_icm, 0); } -unmap_bf: - unmap_bf_area(dev); return err; } From 521130d11fd37b328543477df5522704a0e7cf2c Mon Sep 17 00:00:00 2001 From: Eugenia Emantayev Date: Wed, 5 Sep 2012 22:50:52 +0000 Subject: [PATCH 443/665] net/mlx4_core: Return the error value in case of command initialization failure If mlx4_cmd_init() failed, the init_one function returned success, although no resources were opened. Signed-off-by: Eugenia Emantayev Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 0fadac546b00..2f816c6aed72 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1997,7 +1997,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) } slave_start: - if (mlx4_cmd_init(dev)) { + err = mlx4_cmd_init(dev); + if (err) { mlx4_err(dev, "Failed to init command interface, aborting.\n"); goto err_sriov; } From 979402b16cde048ced4839e21cc49e0779352b80 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 5 Sep 2012 23:34:44 +0000 Subject: [PATCH 444/665] udp: increment UDP_MIB_INERRORS if copy failed In UDP recvmsg(), we miss an increase of UDP_MIB_INERRORS if the copy of skb to userspace failed for whatever reason. Reported-by: Shawn Bohrer Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/udp.c | 5 +++++ net/ipv6/udp.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6f6d1aca3c3d..2814f66dac64 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1226,6 +1226,11 @@ try_again: if (unlikely(err)) { trace_kfree_skb(skb, udp_recvmsg); + if (!peeked) { + atomic_inc(&sk->sk_drops); + UDP_INC_STATS_USER(sock_net(sk), + UDP_MIB_INERRORS, is_udplite); + } goto out_free; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 99d0077b56b8..07e2bfef6845 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -394,6 +394,17 @@ try_again: } if (unlikely(err)) { trace_kfree_skb(skb, udpv6_recvmsg); + if (!peeked) { + atomic_inc(&sk->sk_drops); + if (is_udp4) + UDP_INC_STATS_USER(sock_net(sk), + UDP_MIB_INERRORS, + is_udplite); + else + UDP6_INC_STATS_USER(sock_net(sk), + UDP_MIB_INERRORS, + is_udplite); + } goto out_free; } if (!peeked) { From b8dfc6a0a7235aed452c0e376b6feff182a86992 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 6 Sep 2012 00:47:05 +0000 Subject: [PATCH 445/665] |PATCH] seeq: Add missing spinlock init It doesn't seem this spinlock was properly initialized. Signed-off-by: Jean Delvare Signed-off-by: David S. Miller --- drivers/net/ethernet/seeq/sgiseeq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index bb8c8222122b..4d15bf413bdc 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -751,6 +751,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev) sp->srings = sr; sp->rx_desc = sp->srings->rxvector; sp->tx_desc = sp->srings->txvector; + spin_lock_init(&sp->tx_lock); /* A couple calculations now, saves many cycles later. */ setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS); From 306c11b28d7bb85a7adda741798a2b6b60dd305a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:32 +0200 Subject: [PATCH 446/665] target: go through normal processing for zero-length PSCSI commands Right now, commands with a zero-size payload are skipped completely. This is wrong; such commands should be passed down to the device and processed normally. For physical backends, this ignores completely things such as START STOP UNIT. For virtual backends, we have a hack in place to clear a unit attention state on a zero-size REQUEST SENSE, but we still do not report errors properly on zero-length commands---out-of-bounds 0-block reads and writes, too small parameter list lengths, etc. This patch fixes this for PSCSI. Uses of transport_kmap_data_sg are guarded with a check for non-zero cmd->data_length; for all other commands a zero length is handled properly in pscsi_execute_cmd. The sole exception will be for now REPORT LUNS, which is handled through the normal SPC emulation. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pscsi.c | 8 ++++---- drivers/target/target_core_transport.c | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 5f7151d90344..9d7ce3daa262 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -688,11 +688,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, * Hack to make sure that Write-Protect modepage is set if R/O mode is * forced. */ + if (!cmd->se_deve || !cmd->data_length) + goto after_mode_sense; + if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && (status_byte(result) << 1) == SAM_STAT_GOOD) { - if (!cmd->se_deve) - goto after_mode_sense; - if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { unsigned char *buf = transport_kmap_data_sg(cmd); @@ -709,7 +709,7 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, } after_mode_sense: - if (sd->type != TYPE_TAPE) + if (sd->type != TYPE_TAPE || !cmd->data_length) goto after_mode_select; /* diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 8a29e3fd0195..7ddb0c33f644 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2300,7 +2300,9 @@ int transport_generic_new_cmd(struct se_cmd *cmd) * into the fabric for data transfers, go ahead and complete it right * away. */ - if (!cmd->data_length) { + if (!cmd->data_length && + (cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV || + cmd->t_task_cdb[0] == REPORT_LUNS) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; From 0d7f1299ca5540b9a63ab6e8bf0e89ea963eb6af Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:33 +0200 Subject: [PATCH 447/665] target: report too-small parameter lists everywhere Several places were not checking that the parameter list length was large enough, and thus accessing invalid memory. Zero-length parameter lists are just a special case of this. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 7 +++++++ drivers/target/target_core_iblock.c | 17 +++++++++++++++-- drivers/target/target_core_pr.c | 8 ++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 91799973081a..41641ba54828 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -218,6 +218,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -EINVAL; } + if (cmd->data_length < 4) { + pr_warn("SET TARGET PORT GROUPS parameter list length %u too" + " small\n", cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; + } + buf = transport_kmap_data_sg(cmd); /* diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 76db75e836ed..9ba495477fd2 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -325,17 +325,30 @@ static int iblock_execute_unmap(struct se_cmd *cmd) struct iblock_dev *ibd = dev->dev_ptr; unsigned char *buf, *ptr = NULL; sector_t lba; - int size = cmd->data_length; + int size; u32 range; int ret = 0; int dl, bd_dl; + if (cmd->data_length < 8) { + pr_warn("UNMAP parameter list length %u too small\n", + cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; + } + buf = transport_kmap_data_sg(cmd); dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); - size = min(size - 8, bd_dl); + size = cmd->data_length - 8; + if (bd_dl > size) + pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", + cmd->data_length, bd_dl); + else + size = bd_dl; + if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = -EINVAL; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 1e946502c378..956c84c6b666 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1540,6 +1540,14 @@ static int core_scsi3_decode_spec_i_port( tidh_new->dest_local_nexus = 1; list_add_tail(&tidh_new->dest_list, &tid_dest_list); + if (cmd->data_length < 28) { + pr_warn("SPC-PR: Received PR OUT parameter list" + " length too small: %u\n", cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; + goto out; + } + buf = transport_kmap_data_sg(cmd); /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, From 9b16b9edb4fd0dc86ee0fbe1f7ede580e26e85f4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:34 +0200 Subject: [PATCH 448/665] target: fail REPORT LUNS with less than 16 bytes of payload SPC says: "The ALLOCATION LENGTH field is defined in 4.3.5.6. The allocation length should be at least 16. Device servers compliant with SPC return CHECK CONDITION status, with the sense key set to ILLEGAL REQUEST, and the additional sense code set to INVALID FIELD IN CDB when the allocation length is less than 16 bytes". Testcase: sg_raw -r8 /dev/sdb a0 00 00 00 00 00 00 00 00 08 00 00 should fail with ILLEGAL REQUEST / INVALID FIELD IN CDB sense does not fail without the patch fails correctly with the patch Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index cf2c66f3c116..9fc9a6006ca0 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -669,6 +669,13 @@ int target_report_luns(struct se_cmd *se_cmd) unsigned char *buf; u32 lun_count = 0, offset = 8, i; + if (se_cmd->data_length < 16) { + pr_warn("REPORT LUNS allocation length %u too small\n", + se_cmd->data_length); + se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } + buf = transport_kmap_data_sg(se_cmd); if (!buf) return -ENOMEM; From 3717ef0c63e90686d959158e9728a13a49229be6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:35 +0200 Subject: [PATCH 449/665] target: support zero-size allocation lengths in transport_kmap_data_sg In order to support zero-size allocation lengths, do not assert that we have a scatterlist until after checking cmd->data_length. But once we do this, we can have two cases of transport_kmap_data_sg returning NULL: a zero-size allocation length, or an out-of-memory condition. Report the latter using sense codes, so that the SCSI command that triggered it will fail. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7ddb0c33f644..4403477882b3 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2190,7 +2190,6 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) struct page **pages; int i; - BUG_ON(!sg); /* * We need to take into account a possible offset here for fabrics like * tcm_loop who may be using a contig buffer from the SCSI midlayer for @@ -2198,13 +2197,17 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) */ if (!cmd->t_data_nents) return NULL; - else if (cmd->t_data_nents == 1) + + BUG_ON(!sg); + if (cmd->t_data_nents == 1) return kmap(sg_page(sg)) + sg->offset; /* >1 page. use vmap */ pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); - if (!pages) + if (!pages) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return NULL; + } /* convert sg[] to pages[] */ for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { @@ -2213,8 +2216,10 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); kfree(pages); - if (!cmd->t_data_vmap) + if (!cmd->t_data_vmap) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return NULL; + } return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } From 32a8811ff164f882712c17946e58e52444f464a7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:36 +0200 Subject: [PATCH 450/665] target: support zero allocation length in REQUEST SENSE Similar to INQUIRY and MODE SENSE, construct the sense data in a buffer and later copy it to the scatterlist. Do not do anything, but still clear a pending unit attention condition, if the allocation length is zero. However, SPC tells us that "If a REQUEST SENSE command is terminated with CHECK CONDITION status [and] the REQUEST SENSE command was received on an I_T nexus with a pending unit attention condition (i.e., before the device server reports CHECK CONDITION status), then the device server shall not clear the pending unit attention condition." Do the transport_kmap_data_sg early to detect this case. It also tells us "Device servers shall not adjust the additional sense length to reflect truncation if the allocation length is less than the sense data available", so do not do that! Note that the err variable is write-only. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_spc.c | 35 ++++++++++++++++--------------- include/target/target_core_base.h | 1 + 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4c861de538c9..388a922c8f6d 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -877,9 +877,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd) static int spc_emulate_request_sense(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - unsigned char *buf; + unsigned char *rbuf; u8 ua_asc = 0, ua_ascq = 0; - int err = 0; + unsigned char buf[SE_SENSE_BUF]; + + memset(buf, 0, SE_SENSE_BUF); if (cdb[1] & 0x01) { pr_err("REQUEST_SENSE description emulation not" @@ -888,20 +890,21 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return -ENOSYS; } - buf = transport_kmap_data_sg(cmd); - - if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { + rbuf = transport_kmap_data_sg(cmd); + if (cmd->scsi_sense_reason != 0) { + /* + * Out of memory. We will fail with CHECK CONDITION, so + * we must not clear the unit attention condition. + */ + target_complete_cmd(cmd, CHECK_CONDITION); + return 0; + } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* * CURRENT ERROR, UNIT ATTENTION */ buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; - if (cmd->data_length < 18) { - buf[7] = 0x00; - err = -EINVAL; - goto end; - } /* * The Additional Sense Code (ASC) from the UNIT ATTENTION */ @@ -915,11 +918,6 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; - if (cmd->data_length < 18) { - buf[7] = 0x00; - err = -EINVAL; - goto end; - } /* * NO ADDITIONAL SENSE INFORMATION */ @@ -927,8 +925,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[7] = 0x0A; } -end: - transport_kunmap_data_sg(cmd); + if (rbuf) { + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); + } + target_complete_cmd(cmd, GOOD); return 0; } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 015cea01ae39..5be89373ceac 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -121,6 +121,7 @@ #define SE_INQUIRY_BUF 512 #define SE_MODE_PAGE_BUF 512 +#define SE_SENSE_BUF 96 /* struct se_hba->hba_flags */ enum hba_flags_table { From 6abbdf38363f064c8a50150c9b709682764483b3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:37 +0200 Subject: [PATCH 451/665] target: go through normal processing for zero-length REQUEST_SENSE Now that spc_emulate_request_sense has been taught to process zero-length REQUEST SENSE correctly, drop the special handling of unit attention conditions from transport_generic_new_cmd. However, for now REQUEST SENSE will be the only command that goes through emulation for zero lengths. (nab: Fix up zero-length check in transport_generic_new_cmd) Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4403477882b3..269f54488397 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2306,20 +2306,13 @@ int transport_generic_new_cmd(struct se_cmd *cmd) * away. */ if (!cmd->data_length && - (cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV || - cmd->t_task_cdb[0] == REPORT_LUNS) { + cmd->t_task_cdb[0] != REQUEST_SENSE && + cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; spin_unlock_irq(&cmd->t_state_lock); - if (cmd->t_task_cdb[0] == REQUEST_SENSE) { - u8 ua_asc = 0, ua_ascq = 0; - - core_scsi3_ua_clear_for_request_sense(cmd, - &ua_asc, &ua_ascq); - } - INIT_WORK(&cmd->work, target_complete_ok_work); queue_work(target_completion_wq, &cmd->work); return 0; From b4ad51559c2f12c34a0340b26ffb02e4b285bc51 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 4 Sep 2012 20:04:35 +0100 Subject: [PATCH 452/665] ARM: 7512/1: Fix XIP build due to PHYS_OFFSET definition moving During the p2v changes, the PHYS_OFFSET #define moved into a !__ASSEMBLY__ section. This causes a XIP build to fail with arch/arm/kernel/head.o: In function 'stext': arch/arm/kernel/head.S:146: undefined reference to 'PHYS_OFFSET' Momentarily leave the #ifndef __ASSEMBLY__ section so we can define PHYS_OFFSET for all compilation units. Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/include/asm/memory.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index e965f1b560f1..5f6ddcc56452 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -187,6 +187,7 @@ static inline unsigned long __phys_to_virt(unsigned long x) #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) #endif #endif +#endif /* __ASSEMBLY__ */ #ifndef PHYS_OFFSET #ifdef PLAT_PHYS_OFFSET @@ -196,6 +197,8 @@ static inline unsigned long __phys_to_virt(unsigned long x) #endif #endif +#ifndef __ASSEMBLY__ + /* * PFNs are used to describe any physical page; this means * PFN 0 == physical address 0. From 70b0476a2394de4f4e32e0b67288d80ff71ca963 Mon Sep 17 00:00:00 2001 From: David Brown Date: Tue, 4 Sep 2012 21:36:37 +0100 Subject: [PATCH 453/665] ARM: 7513/1: Make sure dtc is built before running it 'make dtbs' in a clean tree will try running the dtc before actually building it. Make these rules depend upon the scripts to build it. Cc: Signed-off-by: David Brown Signed-off-by: Russell King --- arch/arm/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 30eae87ead6d..a051dfbdd7db 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -284,10 +284,10 @@ zImage Image xipImage bootpImage uImage: vmlinux zinstall uinstall install: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ -%.dtb: +%.dtb: scripts $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ -dtbs: +dtbs: scripts $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ # We use MRPROPER_FILES and CLEAN_FILES now From 62194bdab89b30f451d210247d09e1c146e6d0ad Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 6 Sep 2012 21:24:32 +0100 Subject: [PATCH 454/665] ARM: 7521/1: Fix semihosting Kconfig text It seems we were missing some text in the title for the semihosting DEBUG_LL option. Add in the "/O" and fix up some minor typos in the help text. Signed-off-by: Stephen Boyd Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig.debug | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index f15f82bf3a50..e968a52e4881 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -356,15 +356,15 @@ choice is nothing connected to read from the DCC. config DEBUG_SEMIHOSTING - bool "Kernel low-level debug output via semihosting I" + bool "Kernel low-level debug output via semihosting I/O" help Semihosting enables code running on an ARM target to use the I/O facilities on a host debugger/emulator through a - simple SVC calls. The host debugger or emulator must have + simple SVC call. The host debugger or emulator must have semihosting enabled for the special svc call to be trapped otherwise the kernel will crash. - This is known to work with OpenOCD, as wellas + This is known to work with OpenOCD, as well as ARM's Fast Models, or any other controlling environment that implements semihosting. From 2b2040af0b64cd93e5d4df2494c4486cf604090d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Sep 2012 18:21:44 +0100 Subject: [PATCH 455/665] ARM: 7526/1: traps: send SIGILL if get_user fails on undef handling path get_user may fail to load from the provided __user address due to an unhandled fault generated by the access. In the case of the undefined instruction trap, this results in failure to load the faulting instruction, in which case we should send SIGILL to the task rather than continue with potentially uninitialised data. Signed-off-by: Will Deacon Cc: stable@vger.kernel.org Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index f7945218b8c6..b0179b89a04c 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -420,20 +420,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) #endif instr = *(u32 *) pc; } else if (thumb_mode(regs)) { - get_user(instr, (u16 __user *)pc); + if (get_user(instr, (u16 __user *)pc)) + goto die_sig; if (is_wide_instruction(instr)) { unsigned int instr2; - get_user(instr2, (u16 __user *)pc+1); + if (get_user(instr2, (u16 __user *)pc+1)) + goto die_sig; instr <<= 16; instr |= instr2; } - } else { - get_user(instr, (u32 __user *)pc); + } else if (get_user(instr, (u32 __user *)pc)) { + goto die_sig; } if (call_undef_hook(regs, instr) == 0) return; +die_sig: #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_UNDEFINED) { printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", From 822b4b8d63e09076a4487eb881d3b7a13b28121c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Sep 2012 10:54:32 +0800 Subject: [PATCH 456/665] ASoC: dapm: Add flags to regulator supplies This will be used to enable additional control of the regulators. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- include/sound/soc-dapm.h | 5 +++-- sound/soc/codecs/ab8500-codec.c | 8 ++++---- sound/soc/codecs/wm2200.c | 4 ++-- sound/soc/codecs/wm5100.c | 6 +++--- sound/soc/codecs/wm5102.c | 12 ++++++------ sound/soc/codecs/wm5110.c | 12 ++++++------ sound/soc/codecs/wm8996.c | 2 +- 7 files changed, 25 insertions(+), 24 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 07e2510619a1..c96bf5ae80a6 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -244,10 +244,11 @@ struct device; { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ .shift = wshift, .invert = winvert, .event = wevent, \ .event_flags = wflags} -#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay) \ +#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ { .id = snd_soc_dapm_regulator_supply, .name = wname, \ .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ + .invert = wflags} /* dapm kcontrol types */ diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index b7836503dc69..3f46bffeb0c3 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -390,10 +390,10 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), /* Regulators */ - SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0), - SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0), - SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0), - SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0, 0), /* Power */ SND_SOC_DAPM_SUPPLY("Audio Power", diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 71debd0a3822..efa93dbb0191 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1117,8 +1117,8 @@ SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20, 0), SND_SOC_DAPM_INPUT("IN1L"), SND_SOC_DAPM_INPUT("IN1R"), diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index f4817292ef45..4da1b92b22c2 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -848,9 +848,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0, SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index e2fb07ee68a7..4a2db4e10885 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -305,12 +305,12 @@ SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), SND_SOC_DAPM_SIGGEN("TONE"), SND_SOC_DAPM_SIGGEN("NOISE"), diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 57c7d9c0aadb..bf47914234b3 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -310,12 +310,12 @@ SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), SND_SOC_DAPM_SIGGEN("TONE"), SND_SOC_DAPM_SIGGEN("NOISE"), diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 00f183dfa454..6dcb02c3666f 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -931,7 +931,7 @@ SND_SOC_DAPM_INPUT("IN2RP"), SND_SOC_DAPM_INPUT("DMIC1DAT"), SND_SOC_DAPM_INPUT("DMIC2DAT"), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), From 99d0b1db6ccd0c0e554398e8a579ff3dd4d119ee Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 31 Aug 2012 15:50:55 +0300 Subject: [PATCH 457/665] drm/i915: initialize dpio_lock spin lock This thing is killing lockdep. Signed-off-by: Alexander Shishkin [Jani: move the init next to the other spin lock inits] Signed-off-by: Jani Nikula Acked-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9cf7dfe022b9..914c0dfabe60 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1587,6 +1587,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->rps_lock); + spin_lock_init(&dev_priv->dpio_lock); if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) dev_priv->num_pipe = 3; From 6862234238e84648c305526af2edd98badcad1e0 Mon Sep 17 00:00:00 2001 From: Chema Gonzalez Date: Fri, 7 Sep 2012 13:40:50 +0000 Subject: [PATCH 458/665] net: small bug on rxhash calculation In the current rxhash calculation function, while the sorting of the ports/addrs is coherent (you get the same rxhash for packets sharing the same 4-tuple, in both directions), ports and addrs are sorted independently. This implies packets from a connection between the same addresses but crossed ports hash to the same rxhash. For example, traffic between A=S:l and B=L:s is hashed (in both directions) from {L, S, {s, l}}. The same rxhash is obtained for packets between C=S:s and D=L:l. This patch ensures that you either swap both addrs and ports, or you swap none. Traffic between A and B, and traffic between C and D, get their rxhash from different sources ({L, S, {l, s}} for A<->B, and {L, S, {s, l}} for C<->D) The patch is co-written with Eric Dumazet Signed-off-by: Chema Gonzalez Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 83988362805e..d7fe32c946c1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2647,15 +2647,16 @@ void __skb_get_rxhash(struct sk_buff *skb) if (!skb_flow_dissect(skb, &keys)) return; - if (keys.ports) { - if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]) - swap(keys.port16[0], keys.port16[1]); + if (keys.ports) skb->l4_rxhash = 1; - } /* get a consistent hash (same value on both flow directions) */ - if ((__force u32)keys.dst < (__force u32)keys.src) + if (((__force u32)keys.dst < (__force u32)keys.src) || + (((__force u32)keys.dst == (__force u32)keys.src) && + ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { swap(keys.dst, keys.src); + swap(keys.port16[0], keys.port16[1]); + } hash = jhash_3words((__force u32)keys.dst, (__force u32)keys.src, From 55d512e245bc7699a8800e23df1a24195dd08217 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 8 Sep 2012 16:43:45 -0700 Subject: [PATCH 459/665] Linux 3.6-rc5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 371ce8899f5c..0f66f146d57e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = Saber-toothed Squirrel # *DOCUMENTATION* From 4f97704555672f9ab48ca623561e96a9430bec9a Mon Sep 17 00:00:00 2001 From: "Ren, Yongjie" Date: Fri, 7 Sep 2012 07:36:59 +0000 Subject: [PATCH 460/665] KVM: x86: Check INVPCID feature bit in EBX of leaf 7 Checks and operations on the INVPCID feature bit should use EBX of CPUID leaf 7 instead of ECX. Signed-off-by: Junjie Mao Signed-off-by: Yongjie Ren Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c00f03de1b79..002b4a566e2d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -6575,7 +6575,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) /* Exposing INVPCID only when PCID is exposed */ best = kvm_find_cpuid_entry(vcpu, 0x7, 0); if (vmx_invpcid_supported() && - best && (best->ecx & bit(X86_FEATURE_INVPCID)) && + best && (best->ebx & bit(X86_FEATURE_INVPCID)) && guest_cpuid_has_pcid(vcpu)) { exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; vmcs_write32(SECONDARY_VM_EXEC_CONTROL, @@ -6585,7 +6585,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); if (best) - best->ecx &= ~bit(X86_FEATURE_INVPCID); + best->ebx &= ~bit(X86_FEATURE_INVPCID); } } From 8404663f81d212918ff85f493649a7991209fa04 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 7 Sep 2012 18:22:28 +0100 Subject: [PATCH 461/665] ARM: 7527/1: uaccess: explicitly check __user pointer when !CPU_USE_DOMAINS The {get,put}_user macros don't perform range checking on the provided __user address when !CPU_HAS_DOMAINS. This patch reworks the out-of-line assembly accessors to check the user address against a specified limit, returning -EFAULT if is is out of range. [will: changed get_user register allocation to match put_user] [rmk: fixed building on older ARM architectures] Reported-by: Catalin Marinas Signed-off-by: Will Deacon Cc: stable@vger.kernel.org Signed-off-by: Russell King --- arch/arm/include/asm/assembler.h | 8 +++++++ arch/arm/include/asm/uaccess.h | 40 +++++++++++++++++++++----------- arch/arm/lib/getuser.S | 23 +++++++++++------- arch/arm/lib/putuser.S | 6 +++++ 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 03fb93621d0d..5c8b3bf4d825 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -320,4 +320,12 @@ .size \name , . - \name .endm + .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req +#ifndef CONFIG_CPU_USE_DOMAINS + adds \tmp, \addr, #\size - 1 + sbcccs \tmp, \tmp, \limit + bcs \bad +#endif + .endm + #endif /* __ASM_ASSEMBLER_H__ */ diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 479a6352e0b5..6f83ad6e4d3d 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -101,28 +101,39 @@ extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); -#define __get_user_x(__r2,__p,__e,__s,__i...) \ +#define __GUP_CLOBBER_1 "lr", "cc" +#ifdef CONFIG_CPU_USE_DOMAINS +#define __GUP_CLOBBER_2 "ip", "lr", "cc" +#else +#define __GUP_CLOBBER_2 "lr", "cc" +#endif +#define __GUP_CLOBBER_4 "lr", "cc" + +#define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%1", "r2") \ + __asmeq("%3", "r1") \ "bl __get_user_" #__s \ : "=&r" (__e), "=r" (__r2) \ - : "0" (__p) \ - : __i, "cc") + : "0" (__p), "r" (__l) \ + : __GUP_CLOBBER_##__s) #define get_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ register unsigned long __r2 asm("r2"); \ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __get_user_x(__r2, __p, __e, 1, "lr"); \ - break; \ + __get_user_x(__r2, __p, __e, __l, 1); \ + break; \ case 2: \ - __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ + __get_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __get_user_x(__r2, __p, __e, 4, "lr"); \ + __get_user_x(__r2, __p, __e, __l, 4); \ break; \ default: __e = __get_user_bad(); break; \ } \ @@ -135,31 +146,34 @@ extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); extern int __put_user_8(void *, unsigned long long); -#define __put_user_x(__r2,__p,__e,__s) \ +#define __put_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%2", "r2") \ + __asmeq("%3", "r1") \ "bl __put_user_" #__s \ : "=&r" (__e) \ - : "0" (__p), "r" (__r2) \ + : "0" (__p), "r" (__r2), "r" (__l) \ : "ip", "lr", "cc") #define put_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __r2 asm("r2") = (x); \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __put_user_x(__r2, __p, __e, 1); \ + __put_user_x(__r2, __p, __e, __l, 1); \ break; \ case 2: \ - __put_user_x(__r2, __p, __e, 2); \ + __put_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __put_user_x(__r2, __p, __e, 4); \ + __put_user_x(__r2, __p, __e, __l, 4); \ break; \ case 8: \ - __put_user_x(__r2, __p, __e, 8); \ + __put_user_x(__r2, __p, __e, __l, 8); \ break; \ default: __e = __put_user_bad(); break; \ } \ diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 11093a7c3e32..9b06bb41fca6 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -16,8 +16,9 @@ * __get_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * Outputs: r0 is the error code - * r2, r3 contains the zero-extended value + * r2 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see @@ -27,33 +28,39 @@ * Note also that it is intended that __get_user_bad is not global. */ #include +#include #include #include ENTRY(__get_user_1) + check_uaccess r0, 1, r1, r2, __get_user_bad 1: TUSER(ldrb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__get_user_1) ENTRY(__get_user_2) -#ifdef CONFIG_THUMB2_KERNEL -2: TUSER(ldrb) r2, [r0] -3: TUSER(ldrb) r3, [r0, #1] + check_uaccess r0, 2, r1, r2, __get_user_bad +#ifdef CONFIG_CPU_USE_DOMAINS +rb .req ip +2: ldrbt r2, [r0], #1 +3: ldrbt rb, [r0], #0 #else -2: TUSER(ldrb) r2, [r0], #1 -3: TUSER(ldrb) r3, [r0] +rb .req r0 +2: ldrb r2, [r0] +3: ldrb rb, [r0, #1] #endif #ifndef __ARMEB__ - orr r2, r2, r3, lsl #8 + orr r2, r2, rb, lsl #8 #else - orr r2, r3, r2, lsl #8 + orr r2, rb, r2, lsl #8 #endif mov r0, #0 mov pc, lr ENDPROC(__get_user_2) ENTRY(__get_user_4) + check_uaccess r0, 4, r1, r2, __get_user_bad 4: TUSER(ldr) r2, [r0] mov r0, #0 mov pc, lr diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 7db25990c589..3d73dcb959b0 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -16,6 +16,7 @@ * __put_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * r2, r3 contains the value * Outputs: r0 is the error code * lr corrupted @@ -27,16 +28,19 @@ * Note also that it is intended that __put_user_bad is not global. */ #include +#include #include #include ENTRY(__put_user_1) + check_uaccess r0, 1, r1, ip, __put_user_bad 1: TUSER(strb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_1) ENTRY(__put_user_2) + check_uaccess r0, 2, r1, ip, __put_user_bad mov ip, r2, lsr #8 #ifdef CONFIG_THUMB2_KERNEL #ifndef __ARMEB__ @@ -60,12 +64,14 @@ ENTRY(__put_user_2) ENDPROC(__put_user_2) ENTRY(__put_user_4) + check_uaccess r0, 4, r1, ip, __put_user_bad 4: TUSER(str) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_4) ENTRY(__put_user_8) + check_uaccess r0, 8, r1, ip, __put_user_bad #ifdef CONFIG_THUMB2_KERNEL 5: TUSER(str) r2, [r0] 6: TUSER(str) r3, [r0, #4] From ad72907acd2943304c292ae36960bb66e6dc23c9 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Sep 2012 18:24:10 +0100 Subject: [PATCH 462/665] ARM: 7528/1: uaccess: annotate [__]{get,put}_user functions with might_fault() The user access functions may generate a fault, resulting in invocation of a handler that may sleep. This patch annotates the accessors with might_fault() so that we print a warning if they are invoked from atomic context and help lockdep keep track of mmap_sem. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/uaccess.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 6f83ad6e4d3d..77bd79f2ffdb 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -118,7 +118,7 @@ extern int __get_user_4(void *); : "0" (__p), "r" (__l) \ : __GUP_CLOBBER_##__s) -#define get_user(x,p) \ +#define __get_user_check(x,p) \ ({ \ unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ @@ -141,6 +141,12 @@ extern int __get_user_4(void *); __e; \ }) +#define get_user(x,p) \ + ({ \ + might_fault(); \ + __get_user_check(x,p); \ + }) + extern int __put_user_1(void *, unsigned int); extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); @@ -155,7 +161,7 @@ extern int __put_user_8(void *, unsigned long long); : "0" (__p), "r" (__r2), "r" (__l) \ : "ip", "lr", "cc") -#define put_user(x,p) \ +#define __put_user_check(x,p) \ ({ \ unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __r2 asm("r2") = (x); \ @@ -180,6 +186,12 @@ extern int __put_user_8(void *, unsigned long long); __e; \ }) +#define put_user(x,p) \ + ({ \ + might_fault(); \ + __put_user_check(x,p); \ + }) + #else /* CONFIG_MMU */ /* @@ -233,6 +245,7 @@ do { \ unsigned long __gu_addr = (unsigned long)(ptr); \ unsigned long __gu_val; \ __chk_user_ptr(ptr); \ + might_fault(); \ switch (sizeof(*(ptr))) { \ case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ @@ -314,6 +327,7 @@ do { \ unsigned long __pu_addr = (unsigned long)(ptr); \ __typeof__(*(ptr)) __pu_val = (x); \ __chk_user_ptr(ptr); \ + might_fault(); \ switch (sizeof(*(ptr))) { \ case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ From beafa0de3d3e0d0ece7638cded879815f359f1cb Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Sep 2012 18:24:53 +0100 Subject: [PATCH 463/665] ARM: 7529/1: delay: set loops_per_jiffy when moving to timer-based loop The delay functions may be called by some platforms between switching to the timer-based delay loop but before calibration. In this case, the initial loops_per_jiffy may not be suitable for the timer (although a compromise may be achievable) and delay times may be considered too inaccurate. This patch updates loops_per_jiffy when switching to the timer-based delay loop so that delays are consistent prior to calibration. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/lib/delay.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index d6dacc69254e..395d5fbb8fa2 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -59,6 +59,7 @@ void __init init_current_timer_delay(unsigned long freq) { pr_info("Switching to timer-based delay loop\n"); lpj_fine = freq / HZ; + loops_per_jiffy = lpj_fine; arm_delay_ops.delay = __timer_delay; arm_delay_ops.const_udelay = __timer_const_udelay; arm_delay_ops.udelay = __timer_udelay; From 64f509ce71b08d037998e93dd51180c19b2f464c Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 31 Aug 2012 09:55:53 +0000 Subject: [PATCH 464/665] netfilter: Mark SYN/ACK packets as invalid from original direction Clients should not send such packets. By accepting them, we open up a hole by wich ephemeral ports can be discovered in an off-path attack. See: "Reflection scan: an Off-Path Attack on TCP" by Jan Wrobel, http://arxiv.org/abs/1201.2074 Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_proto_tcp.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index a5ac11ebef33..aba98f942979 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sCL -> sSS */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ -/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, +/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR }, /* * sNO -> sIV Too late and no reason to do anything * sSS -> sIV Client can't send SYN and then SYN/ACK * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open - * sSR -> sIG - * sES -> sIG Error: SYNs in window outside the SYN_SENT state - * are errors. Receiver will reply with RST - * and close the connection. - * Or we are not in sync and hold a dead connection. - * sFW -> sIG - * sCW -> sIG - * sLA -> sIG - * sTW -> sIG - * sCL -> sIG + * sSR -> sSR Late retransmitted SYN/ACK in simultaneous open + * sES -> sIV Invalid SYN/ACK packets sent by the client + * sFW -> sIV + * sCW -> sIV + * sLA -> sIV + * sTW -> sIV + * sCL -> sIV */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ /*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, From 4a70bbfaef0361d27272629d1a250a937edcafe4 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 31 Aug 2012 09:55:54 +0000 Subject: [PATCH 465/665] netfilter: Validate the sequence number of dataless ACK packets as well We spare nothing by not validating the sequence number of dataless ACK packets and enabling it makes harder off-path attacks. See: "Reflection scan: an Off-Path Attack on TCP" by Jan Wrobel, http://arxiv.org/abs/1201.2074 Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_proto_tcp.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index aba98f942979..e046b3756aab 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -630,15 +630,9 @@ static bool tcp_in_window(const struct nf_conn *ct, ack = sack = receiver->td_end; } - if (seq == end - && (!tcph->rst - || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT))) + if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT) /* - * Packets contains no data: we assume it is valid - * and check the ack value only. - * However RST segments are always validated by their - * SEQ number, except when seq == 0 (reset sent answering - * SYN. + * RST sent answering SYN. */ seq = end = sender->td_end; From d6e2dc150ba748c4de518532b0d71275e3c3d959 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 15:14:16 +0800 Subject: [PATCH 466/665] ASoC: wm8983: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8983.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 367388fdc486..57c33fc19681 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1085,7 +1085,7 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) struct wm8983_priv *wm8983; int ret; - wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); + wm8983 = devm_kzalloc(&spi->dev, sizeof *wm8983, GFP_KERNEL); if (!wm8983) return -ENOMEM; @@ -1094,15 +1094,12 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8983, &wm8983_dai, 1); - if (ret < 0) - kfree(wm8983); return ret; } static int __devexit wm8983_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); return 0; } @@ -1123,7 +1120,7 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, struct wm8983_priv *wm8983; int ret; - wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); + wm8983 = devm_kzalloc(&i2c->dev, sizeof *wm8983, GFP_KERNEL); if (!wm8983) return -ENOMEM; @@ -1132,15 +1129,13 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8983, &wm8983_dai, 1); - if (ret < 0) - kfree(wm8983); + return ret; } static __devexit int wm8983_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } From 2ee01ac63b72a3101d6293b50d70d830959bbe8f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 15:28:19 +0800 Subject: [PATCH 467/665] ASoC: wm8983: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8983.c | 151 +++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 57c33fc19681..d8879f262d27 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -27,61 +28,60 @@ #include "wm8983.h" -static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { - [0x00] = 0x0000, /* R0 - Software Reset */ - [0x01] = 0x0000, /* R1 - Power management 1 */ - [0x02] = 0x0000, /* R2 - Power management 2 */ - [0x03] = 0x0000, /* R3 - Power management 3 */ - [0x04] = 0x0050, /* R4 - Audio Interface */ - [0x05] = 0x0000, /* R5 - Companding control */ - [0x06] = 0x0140, /* R6 - Clock Gen control */ - [0x07] = 0x0000, /* R7 - Additional control */ - [0x08] = 0x0000, /* R8 - GPIO Control */ - [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ - [0x0A] = 0x0000, /* R10 - DAC Control */ - [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ - [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ - [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ - [0x0E] = 0x0100, /* R14 - ADC Control */ - [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ - [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ - [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ - [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ - [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ - [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ - [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ - [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ - [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ - [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ - [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ - [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ - [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ - [0x20] = 0x0038, /* R32 - ALC control 1 */ - [0x21] = 0x000B, /* R33 - ALC control 2 */ - [0x22] = 0x0032, /* R34 - ALC control 3 */ - [0x23] = 0x0000, /* R35 - Noise Gate */ - [0x24] = 0x0008, /* R36 - PLL N */ - [0x25] = 0x000C, /* R37 - PLL K 1 */ - [0x26] = 0x0093, /* R38 - PLL K 2 */ - [0x27] = 0x00E9, /* R39 - PLL K 3 */ - [0x29] = 0x0000, /* R41 - 3D control */ - [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ - [0x2B] = 0x0000, /* R43 - Beep control */ - [0x2C] = 0x0033, /* R44 - Input ctrl */ - [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ - [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ - [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ - [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ - [0x31] = 0x0002, /* R49 - Output ctrl */ - [0x32] = 0x0001, /* R50 - Left mixer ctrl */ - [0x33] = 0x0001, /* R51 - Right mixer ctrl */ - [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ - [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ - [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ - [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ - [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ - [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ - [0x3D] = 0x0000 /* R61 - BIAS CTRL */ +static const struct reg_default wm8983_defaults[] = { + { 0x01, 0x0000 }, /* R1 - Power management 1 */ + { 0x02, 0x0000 }, /* R2 - Power management 2 */ + { 0x03, 0x0000 }, /* R3 - Power management 3 */ + { 0x04, 0x0050 }, /* R4 - Audio Interface */ + { 0x05, 0x0000 }, /* R5 - Companding control */ + { 0x06, 0x0140 }, /* R6 - Clock Gen control */ + { 0x07, 0x0000 }, /* R7 - Additional control */ + { 0x08, 0x0000 }, /* R8 - GPIO Control */ + { 0x09, 0x0000 }, /* R9 - Jack Detect Control 1 */ + { 0x0A, 0x0000 }, /* R10 - DAC Control */ + { 0x0B, 0x00FF }, /* R11 - Left DAC digital Vol */ + { 0x0C, 0x00FF }, /* R12 - Right DAC digital vol */ + { 0x0D, 0x0000 }, /* R13 - Jack Detect Control 2 */ + { 0x0E, 0x0100 }, /* R14 - ADC Control */ + { 0x0F, 0x00FF }, /* R15 - Left ADC Digital Vol */ + { 0x10, 0x00FF }, /* R16 - Right ADC Digital Vol */ + { 0x12, 0x012C }, /* R18 - EQ1 - low shelf */ + { 0x13, 0x002C }, /* R19 - EQ2 - peak 1 */ + { 0x14, 0x002C }, /* R20 - EQ3 - peak 2 */ + { 0x15, 0x002C }, /* R21 - EQ4 - peak 3 */ + { 0x16, 0x002C }, /* R22 - EQ5 - high shelf */ + { 0x18, 0x0032 }, /* R24 - DAC Limiter 1 */ + { 0x19, 0x0000 }, /* R25 - DAC Limiter 2 */ + { 0x1B, 0x0000 }, /* R27 - Notch Filter 1 */ + { 0x1C, 0x0000 }, /* R28 - Notch Filter 2 */ + { 0x1D, 0x0000 }, /* R29 - Notch Filter 3 */ + { 0x1E, 0x0000 }, /* R30 - Notch Filter 4 */ + { 0x20, 0x0038 }, /* R32 - ALC control 1 */ + { 0x21, 0x000B }, /* R33 - ALC control 2 */ + { 0x22, 0x0032 }, /* R34 - ALC control 3 */ + { 0x23, 0x0000 }, /* R35 - Noise Gate */ + { 0x24, 0x0008 }, /* R36 - PLL N */ + { 0x25, 0x000C }, /* R37 - PLL K 1 */ + { 0x26, 0x0093 }, /* R38 - PLL K 2 */ + { 0x27, 0x00E9 }, /* R39 - PLL K 3 */ + { 0x29, 0x0000 }, /* R41 - 3D control */ + { 0x2A, 0x0000 }, /* R42 - OUT4 to ADC */ + { 0x2B, 0x0000 }, /* R43 - Beep control */ + { 0x2C, 0x0033 }, /* R44 - Input ctrl */ + { 0x2D, 0x0010 }, /* R45 - Left INP PGA gain ctrl */ + { 0x2E, 0x0010 }, /* R46 - Right INP PGA gain ctrl */ + { 0x2F, 0x0100 }, /* R47 - Left ADC BOOST ctrl */ + { 0x30, 0x0100 }, /* R48 - Right ADC BOOST ctrl */ + { 0x31, 0x0002 }, /* R49 - Output ctrl */ + { 0x32, 0x0001 }, /* R50 - Left mixer ctrl */ + { 0x33, 0x0001 }, /* R51 - Right mixer ctrl */ + { 0x34, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */ + { 0x35, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */ + { 0x36, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */ + { 0x37, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */ + { 0x38, 0x0001 }, /* R56 - OUT3 mixer ctrl */ + { 0x39, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */ + { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ }; static const struct wm8983_reg_access { @@ -159,7 +159,7 @@ static const int vol_update_regs[] = { }; struct wm8983_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; u32 sysclk; u32 bclk; }; @@ -610,7 +610,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, return 0; } -static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8983_readable(struct device *dev, unsigned int reg) { if (reg > WM8983_MAX_REGISTER) return 0; @@ -905,6 +905,7 @@ static int wm8983_set_sysclk(struct snd_soc_dai *dai, static int wm8983_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { @@ -917,7 +918,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); + ret = regcache_sync(wm8983->regmap); if (ret < 0) { dev_err(codec->dev, "Failed to sync cache: %d\n", ret); return ret; @@ -994,10 +995,9 @@ static int wm8983_remove(struct snd_soc_codec *codec) static int wm8983_probe(struct snd_soc_codec *codec) { int ret; - struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); int i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); return ret; @@ -1067,16 +1067,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { .suspend = wm8983_suspend, .resume = wm8983_resume, .set_bias_level = wm8983_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8983_reg_defs, .controls = wm8983_snd_controls, .num_controls = ARRAY_SIZE(wm8983_snd_controls), .dapm_widgets = wm8983_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), .dapm_routes = wm8983_audio_map, .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), - .readable_register = wm8983_readable +}; + +static const struct regmap_config wm8983_regmap = { + .reg_bits = 7, + .val_bits = 9, + + .reg_defaults = wm8983_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), + .cache_type = REGCACHE_RBTREE, + + .readable_reg = wm8983_readable, }; #if defined(CONFIG_SPI_MASTER) @@ -1089,7 +1096,13 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) if (!wm8983) return -ENOMEM; - wm8983->control_type = SND_SOC_SPI; + wm8983->regmap = devm_regmap_init_spi(spi, &wm8983_regmap); + if (IS_ERR(wm8983->regmap)) { + ret = PTR_ERR(wm8983->regmap); + dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + spi_set_drvdata(spi, wm8983); ret = snd_soc_register_codec(&spi->dev, @@ -1124,7 +1137,13 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, if (!wm8983) return -ENOMEM; - wm8983->control_type = SND_SOC_I2C; + wm8983->regmap = devm_regmap_init_i2c(i2c, &wm8983_regmap); + if (IS_ERR(wm8983->regmap)) { + ret = PTR_ERR(wm8983->regmap); + dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8983); ret = snd_soc_register_codec(&i2c->dev, From 4a8f1ddde942e232387e6129ce4f4c412e43802f Mon Sep 17 00:00:00 2001 From: James Ralston Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: [PATCH 468/665] i2c-i801: Add Device IDs for Intel Lynx Point-LP PCH Add the SMBus Device IDs for the Intel Lynx Point-LP PCH. Signed-off-by: James Ralston Signed-off-by: Jean Delvare --- Documentation/i2c/busses/i2c-i801 | 1 + drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-i801.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index 615142da4ef6..157416e78cc4 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -21,6 +21,7 @@ Supported adapters: * Intel DH89xxCC (PCH) * Intel Panther Point (PCH) * Intel Lynx Point (PCH) + * Intel Lynx Point-LP (PCH) Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b4aaa1bd6728..af8bc83fd857 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -104,6 +104,7 @@ config I2C_I801 DH89xxCC (PCH) Panther Point (PCH) Lynx Point (PCH) + Lynx Point-LP (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 898dcf9c7ade..33e9b0c09af2 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -52,6 +52,7 @@ DH89xxCC (PCH) 0x2330 32 hard yes yes yes Panther Point (PCH) 0x1e22 32 hard yes yes yes Lynx Point (PCH) 0x8c22 32 hard yes yes yes + Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -155,6 +156,7 @@ #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 struct i801_priv { struct i2c_adapter adapter; @@ -771,6 +773,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, { 0, } }; From e68bb91baa0bb9817567bd45d560919e8e26373b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: [PATCH 469/665] i2c-designware: Fix build error if CONFIG_I2C_DESIGNWARE_PLATFORM=y && CONFIG_I2C_DESIGNWARE_PCI=y This patch adds config I2C_DESIGNWARE_CORE in Kconfig, and let I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_PCI select I2C_DESIGNWARE_CORE. Because both I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_PCI can be built as built-in or module, we also need to export the functions in i2c-designware-core. This fixes below build error when CONFIG_I2C_DESIGNWARE_PLATFORM=y && CONFIG_I2C_DESIGNWARE_PCI=y: LD drivers/i2c/busses/built-in.o drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_clear_int': i2c-designware-core.c:(.text+0xa10): multiple definition of `i2c_dw_clear_int' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x928): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_init': i2c-designware-core.c:(.text+0x178): multiple definition of `i2c_dw_init' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x90): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `dw_readl': i2c-designware-core.c:(.text+0xe8): multiple definition of `dw_readl' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x0): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_isr': i2c-designware-core.c:(.text+0x724): multiple definition of `i2c_dw_isr' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x63c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_xfer': i2c-designware-core.c:(.text+0x4b0): multiple definition of `i2c_dw_xfer' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x3c8): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_is_enabled': i2c-designware-core.c:(.text+0x9d4): multiple definition of `i2c_dw_is_enabled' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8ec): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `dw_writel': i2c-designware-core.c:(.text+0x124): multiple definition of `dw_writel' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x3c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_xfer_msg': i2c-designware-core.c:(.text+0x2e8): multiple definition of `i2c_dw_xfer_msg' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x200): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_enable': i2c-designware-core.c:(.text+0x9c8): multiple definition of `i2c_dw_enable' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8e0): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_read_comp_param': i2c-designware-core.c:(.text+0xa24): multiple definition of `i2c_dw_read_comp_param' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x93c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_disable': i2c-designware-core.c:(.text+0x9dc): multiple definition of `i2c_dw_disable' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8f4): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_func': i2c-designware-core.c:(.text+0x710): multiple definition of `i2c_dw_func' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x628): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_disable_int': i2c-designware-core.c:(.text+0xa18): multiple definition of `i2c_dw_disable_int' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x930): first defined here make[3]: *** [drivers/i2c/busses/built-in.o] Error 1 make[2]: *** [drivers/i2c/busses] Error 2 make[1]: *** [drivers/i2c] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Signed-off-by: Jean Delvare Tested-by: Jiri Slaby Cc: stable@vger.kernel.org [3.2+] --- drivers/i2c/busses/Kconfig | 5 +++++ drivers/i2c/busses/Makefile | 5 +++-- drivers/i2c/busses/i2c-designware-core.c | 11 +++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index af8bc83fd857..970a1612e795 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -355,9 +355,13 @@ config I2C_DAVINCI devices such as DaVinci NIC. For details please see http://www.ti.com/davinci +config I2C_DESIGNWARE_CORE + tristate + config I2C_DESIGNWARE_PLATFORM tristate "Synopsys DesignWare Platform" depends on HAVE_CLK + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. @@ -368,6 +372,7 @@ config I2C_DESIGNWARE_PLATFORM config I2C_DESIGNWARE_PCI tristate "Synopsys DesignWare PCI" depends on PCI + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ce3c2be7fb40..37c4182cc98b 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o +obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o +i2c-designware-platform-objs := i2c-designware-platdrv.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o +i2c-designware-pci-objs := i2c-designware-pcidrv.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 1e48bec80edf..7b8ebbefb581 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -25,6 +25,7 @@ * ---------------------------------------------------------------------------- * */ +#include #include #include #include @@ -316,6 +317,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) dw_writel(dev, dev->master_cfg , DW_IC_CON); return 0; } +EXPORT_SYMBOL_GPL(i2c_dw_init); /* * Waiting for bus not busy @@ -568,12 +570,14 @@ done: return ret; } +EXPORT_SYMBOL_GPL(i2c_dw_xfer); u32 i2c_dw_func(struct i2c_adapter *adap) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); return dev->functionality; } +EXPORT_SYMBOL_GPL(i2c_dw_func); static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) { @@ -678,17 +682,20 @@ tx_aborted: return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(i2c_dw_isr); void i2c_dw_enable(struct dw_i2c_dev *dev) { /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_enable); u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_is_enabled); void i2c_dw_disable(struct dw_i2c_dev *dev) { @@ -699,18 +706,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev) dw_writel(dev, 0, DW_IC_INTR_MASK); dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_disable); void i2c_dw_clear_int(struct dw_i2c_dev *dev) { dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_clear_int); void i2c_dw_disable_int(struct dw_i2c_dev *dev) { dw_writel(dev, 0, DW_IC_INTR_MASK); } +EXPORT_SYMBOL_GPL(i2c_dw_disable_int); u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_COMP_PARAM_1); } +EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); From 390946b17260797635cd9e65496b5a17b2db0a5d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: [PATCH 470/665] i2c-core: Fix for lockdep validator If kernel is compiled with CONFIG_PROVE_LOCKING the validator raises an error when a multiplexer is removed via sysfs and sub-clients are connected to it. This is a false positive. Documentation/lockdep-design.txt recommends to handle this via calls to mutex_lock_nested(). Based on an earlier fix from Michael Lawnick. Note that the extra code resolves to nothing unless CONFIG_DEBUG_LOCK_ALLOC=y. Signed-off-by: Jean Delvare Cc: Michael Lawnick --- drivers/i2c/i2c-core.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2efa56c5ff2c..2091ae8f539a 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev) complete(&adap->dev_released); } +/* + * This function is only needed for mutex_lock_nested, so it is never + * called unless locking correctness checking is enabled. Thus we + * make it inline to avoid a compiler warning. That's what gcc ends up + * doing anyway. + */ +static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) +{ + unsigned int depth = 0; + + while ((adapter = i2c_parent_is_i2c_adapter(adapter))) + depth++; + + return depth; +} + /* * Let users instantiate I2C devices through sysfs. This can be used when * platform initialization code doesn't contain the proper data for @@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, /* Make sure the device was added through sysfs */ res = -ENOENT; - mutex_lock(&adap->userspace_clients_lock); + mutex_lock_nested(&adap->userspace_clients_lock, + i2c_adapter_depth(adap)); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { if (client->addr == addr) { @@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap) return res; /* Remove devices instantiated from sysfs */ - mutex_lock(&adap->userspace_clients_lock); + mutex_lock_nested(&adap->userspace_clients_lock, + i2c_adapter_depth(adap)); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, From 4484141a94f4a5afea6ebc0b2abba0aa1b0ae9d1 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Fri, 7 Sep 2012 14:14:20 +0800 Subject: [PATCH 471/665] KVM: fix error paths for failed gfn_to_page() calls This bug was triggered: [ 4220.198458] BUG: unable to handle kernel paging request at fffffffffffffffe [ 4220.203907] IP: [] put_page+0xf/0x34 ...... [ 4220.237326] Call Trace: [ 4220.237361] [] kvm_arch_destroy_vm+0xf9/0x101 [kvm] [ 4220.237382] [] kvm_put_kvm+0xcc/0x127 [kvm] [ 4220.237401] [] kvm_vcpu_release+0x18/0x1c [kvm] [ 4220.237407] [] __fput+0x111/0x1ed [ 4220.237411] [] ____fput+0xe/0x10 [ 4220.237418] [] task_work_run+0x5d/0x88 [ 4220.237424] [] do_exit+0x2bf/0x7ca The test case: printf(fmt, ##args); \ exit(-1);} while (0) static int create_vm(void) { int sys_fd, vm_fd; sys_fd = open("/dev/kvm", O_RDWR); if (sys_fd < 0) die("open /dev/kvm fail.\n"); vm_fd = ioctl(sys_fd, KVM_CREATE_VM, 0); if (vm_fd < 0) die("KVM_CREATE_VM fail.\n"); return vm_fd; } static int create_vcpu(int vm_fd) { int vcpu_fd; vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0); if (vcpu_fd < 0) die("KVM_CREATE_VCPU ioctl.\n"); printf("Create vcpu.\n"); return vcpu_fd; } static void *vcpu_thread(void *arg) { int vm_fd = (int)(long)arg; create_vcpu(vm_fd); return NULL; } int main(int argc, char *argv[]) { pthread_t thread; int vm_fd; (void)argc; (void)argv; vm_fd = create_vm(); pthread_create(&thread, NULL, vcpu_thread, (void *)(long)vm_fd); printf("Exit.\n"); return 0; } It caused by release kvm->arch.ept_identity_map_addr which is the error page. The parent thread can send KILL signal to the vcpu thread when it was exiting which stops faulting pages and potentially allocating memory. So gfn_to_pfn/gfn_to_page may fail at this time Fixed by checking the page before it is used Signed-off-by: Xiao Guangrong Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 19 ++++++++++++++++--- arch/x86/kvm/x86.c | 13 ++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 002b4a566e2d..b1eb202ee76a 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3619,6 +3619,7 @@ static void seg_setup(int seg) static int alloc_apic_access_page(struct kvm *kvm) { + struct page *page; struct kvm_userspace_memory_region kvm_userspace_mem; int r = 0; @@ -3633,7 +3634,13 @@ static int alloc_apic_access_page(struct kvm *kvm) if (r) goto out; - kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00); + page = gfn_to_page(kvm, 0xfee00); + if (is_error_page(page)) { + r = -EFAULT; + goto out; + } + + kvm->arch.apic_access_page = page; out: mutex_unlock(&kvm->slots_lock); return r; @@ -3641,6 +3648,7 @@ out: static int alloc_identity_pagetable(struct kvm *kvm) { + struct page *page; struct kvm_userspace_memory_region kvm_userspace_mem; int r = 0; @@ -3656,8 +3664,13 @@ static int alloc_identity_pagetable(struct kvm *kvm) if (r) goto out; - kvm->arch.ept_identity_pagetable = gfn_to_page(kvm, - kvm->arch.ept_identity_map_addr >> PAGE_SHIFT); + page = gfn_to_page(kvm, kvm->arch.ept_identity_map_addr >> PAGE_SHIFT); + if (is_error_page(page)) { + r = -EFAULT; + goto out; + } + + kvm->arch.ept_identity_pagetable = page; out: mutex_unlock(&kvm->slots_lock); return r; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 148ed666e311..2966c847d489 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5113,17 +5113,20 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) !kvm_event_needs_reinjection(vcpu); } -static void vapic_enter(struct kvm_vcpu *vcpu) +static int vapic_enter(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic = vcpu->arch.apic; struct page *page; if (!apic || !apic->vapic_addr) - return; + return 0; page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); + if (is_error_page(page)) + return -EFAULT; vcpu->arch.apic->vapic_page = page; + return 0; } static void vapic_exit(struct kvm_vcpu *vcpu) @@ -5430,7 +5433,11 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) } vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); - vapic_enter(vcpu); + r = vapic_enter(vcpu); + if (r) { + srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); + return r; + } r = 1; while (r > 0) { From 7d014db8baf70bcc7e9cf1457350b11bc2affbbd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 16:18:56 +0800 Subject: [PATCH 472/665] ASoC: wm8523: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 1c3ffb290cdc..af2289ee6cd6 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -516,7 +516,8 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, struct wm8523_priv *wm8523; int ret; - wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); + wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), + GFP_KERNEL); if (wm8523 == NULL) return -ENOMEM; @@ -525,8 +526,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8523, &wm8523_dai, 1); - if (ret < 0) - kfree(wm8523); + return ret; } @@ -534,7 +534,6 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, static __devexit int wm8523_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } From 719b0c593cbb2a199e977b4dcca1d096a4a0d6a7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 16:23:34 +0800 Subject: [PATCH 473/665] ASoC: wm8523: Move regulator acquisition to I2C probe() This is better style since we acquire all needed resources before we try to do the ASoC card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index af2289ee6cd6..c4c64e225c42 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -402,7 +402,7 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - int ret, i; + int ret; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = @@ -414,16 +414,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) return ret; } - for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) - wm8523->supplies[i].supply = wm8523_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); if (ret != 0) { @@ -471,7 +461,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); err_get: - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); return ret; } @@ -481,7 +470,6 @@ static int wm8523_remove(struct snd_soc_codec *codec) struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); return 0; } @@ -514,13 +502,23 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8523_priv *wm8523; - int ret; + int ret, i; wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), GFP_KERNEL); if (wm8523 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) + wm8523->supplies[i].supply = wm8523_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8523->supplies), + wm8523->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8523); wm8523->control_type = SND_SOC_I2C; From b9288f49dc5ac8342cc34163093c9f7d096b6378 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 16:27:45 +0800 Subject: [PATCH 474/665] ASoC: wm8523: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 69 +++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index c4c64e225c42..d7d5fe6866a6 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -39,33 +40,31 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { /* codec private data */ struct wm8523_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; unsigned int rate_constraint_list[WM8523_NUM_RATES]; struct snd_pcm_hw_constraint_list rate_constraint; }; -static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { - 0x8523, /* R0 - DEVICE_ID */ - 0x0001, /* R1 - REVISION */ - 0x0000, /* R2 - PSCTRL1 */ - 0x1812, /* R3 - AIF_CTRL1 */ - 0x0000, /* R4 - AIF_CTRL2 */ - 0x0001, /* R5 - DAC_CTRL3 */ - 0x0190, /* R6 - DAC_GAINL */ - 0x0190, /* R7 - DAC_GAINR */ - 0x0000, /* R8 - ZERO_DETECT */ +static const struct reg_default wm8523_reg_defaults[] = { + { 2, 0x0000 }, /* R2 - PSCTRL1 */ + { 3, 0x1812 }, /* R3 - AIF_CTRL1 */ + { 4, 0x0000 }, /* R4 - AIF_CTRL2 */ + { 5, 0x0001 }, /* R5 - DAC_CTRL3 */ + { 6, 0x0190 }, /* R6 - DAC_GAINL */ + { 7, 0x0190 }, /* R7 - DAC_GAINR */ + { 8, 0x0000 }, /* R8 - ZERO_DETECT */ }; -static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8523_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case WM8523_DEVICE_ID: case WM8523_REVISION: - return 1; + return true; default: - return 0; + return false; } } @@ -301,8 +300,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; - int ret, i; + int ret; switch (level) { case SND_SOC_BIAS_ON: @@ -325,16 +323,13 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, return ret; } + /* Sync back default/cached values */ + regcache_sync(wm8523->regmap); + /* Initial power up */ snd_soc_update_bits(codec, WM8523_PSCTRL1, WM8523_SYS_ENA_MASK, 1); - /* Sync back default/cached values */ - for (i = WM8523_AIF_CTRL1; - i < WM8523_MAX_REGISTER; i++) - snd_soc_write(codec, i, reg_cache[i]); - - msleep(100); } @@ -408,7 +403,7 @@ static int wm8523_probe(struct snd_soc_codec *codec) wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); + 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; @@ -426,7 +421,7 @@ static int wm8523_probe(struct snd_soc_codec *codec) dev_err(codec->dev, "Failed to read ID register\n"); goto err_enable; } - if (ret != wm8523_reg[WM8523_DEVICE_ID]) { + if (ret != 0x8523) { dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); ret = -EINVAL; goto err_enable; @@ -467,8 +462,6 @@ err_get: static int wm8523_remove(struct snd_soc_codec *codec) { - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } @@ -479,10 +472,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { .suspend = wm8523_suspend, .resume = wm8523_resume, .set_bias_level = wm8523_set_bias_level, - .reg_cache_size = WM8523_REGISTER_COUNT, - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8523_reg, - .volatile_register = wm8523_volatile_register, .controls = wm8523_controls, .num_controls = ARRAY_SIZE(wm8523_controls), @@ -497,6 +486,18 @@ static const struct of_device_id wm8523_of_match[] = { { }, }; +static const struct regmap_config wm8523_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = WM8523_ZERO_DETECT, + + .reg_defaults = wm8523_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8523_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8523_volatile_register, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -509,6 +510,13 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, if (wm8523 == NULL) return -ENOMEM; + wm8523->regmap = devm_regmap_init_i2c(i2c, &wm8523_regmap); + if (IS_ERR(wm8523->regmap)) { + ret = PTR_ERR(wm8523->regmap); + dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); + return ret; + } + for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) wm8523->supplies[i].supply = wm8523_supply_names[i]; @@ -520,7 +528,6 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, } i2c_set_clientdata(i2c, wm8523); - wm8523->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8523, &wm8523_dai, 1); From 59ac2149aee9b69732dad602ea250ecb60b9e617 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 17:07:24 +0800 Subject: [PATCH 475/665] ASoC: wm8523: Move device ID verification and reset to I2C probe Ensure that we have confirmed that we've got the device in place before we register with ASoC. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 84 ++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index d7d5fe6866a6..8d5c27673501 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -68,11 +68,6 @@ static bool wm8523_volatile_register(struct device *dev, unsigned int reg) } } -static int wm8523_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8523_DEVICE_ID, 0); -} - static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); static const char *wm8523_zd_count_text[] = { @@ -409,38 +404,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) return ret; } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = snd_soc_read(codec, WM8523_DEVICE_ID); - if (ret < 0) { - dev_err(codec->dev, "Failed to read ID register\n"); - goto err_enable; - } - if (ret != 0x8523) { - dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); - ret = -EINVAL; - goto err_enable; - } - - ret = snd_soc_read(codec, WM8523_REVISION); - if (ret < 0) { - dev_err(codec->dev, "Failed to read revision register\n"); - goto err_enable; - } - dev_info(codec->dev, "revision %c\n", - (ret & WM8523_CHIP_REV_MASK) + 'A'); - - ret = wm8523_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - /* Change some default settings - latch VU and enable ZC */ snd_soc_update_bits(codec, WM8523_DAC_GAINR, WM8523_DACR_VU, WM8523_DACR_VU); @@ -448,16 +411,7 @@ static int wm8523_probe(struct snd_soc_codec *codec) wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err_get: - - return ret; } static int wm8523_remove(struct snd_soc_codec *codec) @@ -503,6 +457,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8523_priv *wm8523; + unsigned int val; int ret, i; wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), @@ -527,6 +482,40 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, return ret; } + ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), + wm8523->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + ret = regmap_read(wm8523->regmap, WM8523_DEVICE_ID, &val); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read ID register\n"); + goto err_enable; + } + if (val != 0x8523) { + dev_err(&i2c->dev, "Device is not a WM8523, ID is %x\n", ret); + ret = -EINVAL; + goto err_enable; + } + + ret = regmap_read(wm8523->regmap, WM8523_REVISION, &val); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read revision register\n"); + goto err_enable; + } + dev_info(&i2c->dev, "revision %c\n", + (val & WM8523_CHIP_REV_MASK) + 'A'); + + ret = regmap_write(wm8523->regmap, WM8523_DEVICE_ID, 0x8523); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to reset device: %d\n", ret); + goto err_enable; + } + + regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); + i2c_set_clientdata(i2c, wm8523); ret = snd_soc_register_codec(&i2c->dev, @@ -534,6 +523,9 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, return ret; +err_enable: + regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); + return ret; } static __devexit int wm8523_i2c_remove(struct i2c_client *client) From aff041af948f5cdf51e2115f267957a89f28ac0f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 10:59:51 +0800 Subject: [PATCH 476/665] ASoC: sta32x: Move regulator acquisition to I2C probe This is better style as it ensures we don't try to do the ASoC probe without required resources. Also convert to devm_ while we're at it, saving a bit of code, and fix a leak of enable on error. Signed-off-by: Mark Brown Acked-by: Johannes Stezenbach --- sound/soc/codecs/sta32x.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 51b7313a4c14..039597e66987 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -825,22 +825,11 @@ static int sta32x_probe(struct snd_soc_codec *codec) sta32x->codec = codec; sta32x->pdata = dev_get_platdata(codec->dev); - /* regulators */ - for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) - sta32x->supplies[i].supply = sta32x_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), - sta32x->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; + return ret; } /* Tell ASoC what kind of I/O to use to read the registers. ASoC will @@ -849,7 +838,7 @@ static int sta32x_probe(struct snd_soc_codec *codec) ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - return ret; + goto err; } /* Chip documentation explicitly requires that the reset values @@ -915,9 +904,8 @@ static int sta32x_probe(struct snd_soc_codec *codec) return 0; -err_get: - regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); err: + regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return ret; } @@ -928,7 +916,6 @@ static int sta32x_remove(struct snd_soc_codec *codec) sta32x_watchdog_stop(sta32x); sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return 0; } @@ -966,13 +953,24 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct sta32x_priv *sta32x; - int ret; + int ret, i; sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), GFP_KERNEL); if (!sta32x) return -ENOMEM; + /* regulators */ + for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) + sta32x->supplies[i].supply = sta32x_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(sta32x->supplies), + sta32x->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, sta32x); ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); From 29fdf4fbbe0891349d8444bde4c09f9cfaf744b6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 10:59:56 +0800 Subject: [PATCH 477/665] ASoC: sta32x: Convert to regmap Long term all drivers should be using regmap directly. This is more idiomatic and moves us towards the removal of the ASoC level cache code. The initialiasation of reserved register bits in probe() is slightly odd as the defaults being written don't appear to match the silicon defaults but the new code should have the same effect as the old code. The watchdog code will now unconditionally do a mute and unmute when resyncing but since we only sync when we are very sure there is something to sync this should have no impact. Signed-off-by: Mark Brown Acked-by: Johannes Stezenbach --- sound/soc/codecs/sta32x.c | 107 ++++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 039597e66987..0935bfe62471 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -55,12 +56,50 @@ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) /* Power-up register defaults */ -static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { - 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, - 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, - 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, - 0xc0, 0xf3, 0x33, 0x00, 0x0c, +static const struct reg_default sta32x_regs[] = { + { 0x0, 0x63 }, + { 0x1, 0x80 }, + { 0x2, 0xc2 }, + { 0x3, 0x40 }, + { 0x4, 0xc2 }, + { 0x5, 0x5c }, + { 0x6, 0x10 }, + { 0x7, 0xff }, + { 0x8, 0x60 }, + { 0x9, 0x60 }, + { 0xa, 0x60 }, + { 0xb, 0x80 }, + { 0xc, 0x00 }, + { 0xd, 0x00 }, + { 0xe, 0x00 }, + { 0xf, 0x40 }, + { 0x10, 0x80 }, + { 0x11, 0x77 }, + { 0x12, 0x6a }, + { 0x13, 0x69 }, + { 0x14, 0x6a }, + { 0x15, 0x69 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x00 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x2d }, + { 0x28, 0xc0 }, + { 0x2b, 0x00 }, + { 0x2c, 0x0c }, }; /* regulator power supply names */ @@ -72,6 +111,7 @@ static const char *sta32x_supply_names[] = { /* codec private data */ struct sta32x_priv { + struct regmap *regmap; struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; struct snd_soc_codec *codec; struct sta32x_platform_data *pdata; @@ -291,17 +331,15 @@ 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; unsigned int mute; int rc; - if (!codec->cache_sync) - return 0; - /* mute during register sync */ mute = snd_soc_read(codec, STA32X_MMUTE); snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); sta32x_sync_coef_shadow(codec); - rc = snd_soc_cache_sync(codec); + rc = regcache_sync(sta32x->regmap); snd_soc_write(codec, STA32X_MMUTE, mute); return rc; } @@ -316,11 +354,11 @@ static void sta32x_watchdog(struct work_struct *work) /* check if sta32x has reset itself */ confa_cached = snd_soc_read(codec, STA32X_CONFA); - codec->cache_bypass = 1; + regcache_cache_bypass(sta32x->regmap, true); confa = snd_soc_read(codec, STA32X_CONFA); - codec->cache_bypass = 0; + regcache_cache_bypass(sta32x->regmap, false); if (confa != confa_cached) { - codec->cache_sync = 1; + regcache_mark_dirty(sta32x->regmap); sta32x_cache_sync(codec); } @@ -835,7 +873,8 @@ static int sta32x_probe(struct snd_soc_codec *codec) /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); + codec->control_data = sta32x->regmap; + 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 (ret=%i)\n", ret); goto err; @@ -847,13 +886,15 @@ static int sta32x_probe(struct snd_soc_codec *codec) * so the write to the these registers are suppressed by the cache * restore code when it skips writes of default registers. */ - snd_soc_cache_write(codec, STA32X_CONFC, 0xc2); - snd_soc_cache_write(codec, STA32X_CONFE, 0xc2); - snd_soc_cache_write(codec, STA32X_CONFF, 0x5c); - snd_soc_cache_write(codec, STA32X_MMUTE, 0x10); - snd_soc_cache_write(codec, STA32X_AUTO1, 0x60); - snd_soc_cache_write(codec, STA32X_AUTO3, 0x00); - snd_soc_cache_write(codec, STA32X_C3CFG, 0x40); + regcache_cache_only(sta32x->regmap, true); + snd_soc_write(codec, STA32X_CONFC, 0xc2); + snd_soc_write(codec, STA32X_CONFE, 0xc2); + snd_soc_write(codec, STA32X_CONFF, 0x5c); + snd_soc_write(codec, STA32X_MMUTE, 0x10); + snd_soc_write(codec, STA32X_AUTO1, 0x60); + snd_soc_write(codec, STA32X_AUTO3, 0x00); + snd_soc_write(codec, STA32X_C3CFG, 0x40); + regcache_cache_only(sta32x->regmap, false); /* set thermal warning adjustment and recovery */ if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) @@ -920,8 +961,7 @@ static int sta32x_remove(struct snd_soc_codec *codec) return 0; } -static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, - unsigned int reg) +static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg) { switch (reg) { case STA32X_CONFA ... STA32X_L2ATRT: @@ -936,10 +976,6 @@ static const struct snd_soc_codec_driver sta32x_codec = { .remove = sta32x_remove, .suspend = sta32x_suspend, .resume = sta32x_resume, - .reg_cache_size = STA32X_REGISTER_COUNT, - .reg_word_size = sizeof(u8), - .reg_cache_default = sta32x_regs, - .volatile_register = sta32x_reg_is_volatile, .set_bias_level = sta32x_set_bias_level, .controls = sta32x_snd_controls, .num_controls = ARRAY_SIZE(sta32x_snd_controls), @@ -949,6 +985,16 @@ static const struct snd_soc_codec_driver sta32x_codec = { .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), }; +static const struct regmap_config sta32x_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = STA32X_FDRC2, + .reg_defaults = sta32x_regs, + .num_reg_defaults = ARRAY_SIZE(sta32x_regs), + .cache_type = REGCACHE_RBTREE, + .volatile_reg = sta32x_reg_is_volatile, +}; + static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -971,6 +1017,13 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, return ret; } + sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); + if (IS_ERR(sta32x->regmap)) { + ret = PTR_ERR(sta32x->regmap); + dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, sta32x); ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); From c35e005f3115cd27d85625805645b90ba961f16f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Sep 2012 02:13:52 -0700 Subject: [PATCH 478/665] ASoC: fsi: fixup pm_runtime_disable() timing on fsi_probe() pm_runtime_disable() error handling timing on fsi_probe() was wrong. This patch fixes it up. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 0540408a9fa9..8534989836aa 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1730,12 +1730,12 @@ exit_snd_soc: exit_free_irq: free_irq(irq, master); exit_fsib: + pm_runtime_disable(&pdev->dev); fsi_stream_remove(&master->fsib); exit_fsia: fsi_stream_remove(&master->fsia); exit_iounmap: iounmap(master->base); - pm_runtime_disable(&pdev->dev); exit_kfree: kfree(master); master = NULL; From dbd4e51cd164e7d94b00c0c0dd3ac5517364a8fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Sep 2012 02:14:10 -0700 Subject: [PATCH 479/665] ASoC: fsi: tidyup: remove un-necessary operation from fsi_probe() struct fsi_master *master became member of struct fsi_priv from 71f6e0645be42f93c0f90dfcc93b9d2d277c2ee6 (ASoC: sh_fsi: avoid using global variable) So, master = NULL is not necessary on fsi_probe() now. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 8534989836aa..a5ee2faa1073 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1738,7 +1738,6 @@ exit_iounmap: iounmap(master->base); exit_kfree: kfree(master); - master = NULL; exit: return ret; } From 6ac4262f367fd0d9b0219dfd014ffcca4a6cfa6a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Sep 2012 02:14:31 -0700 Subject: [PATCH 480/665] ASoC: fsi: convert to devm_xxx() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index a5ee2faa1073..5328ae5539f1 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1655,22 +1655,20 @@ static int fsi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (!res || (int)irq <= 0) { dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); - ret = -ENODEV; - goto exit; + return -ENODEV; } - master = kzalloc(sizeof(*master), GFP_KERNEL); + master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); if (!master) { dev_err(&pdev->dev, "Could not allocate master\n"); - ret = -ENOMEM; - goto exit; + return -ENOMEM; } - master->base = ioremap_nocache(res->start, resource_size(res)); + master->base = devm_ioremap_nocache(&pdev->dev, + res->start, resource_size(res)); if (!master->base) { - ret = -ENXIO; dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); - goto exit_kfree; + return -ENXIO; } /* master setting */ @@ -1686,7 +1684,7 @@ static int fsi_probe(struct platform_device *pdev) ret = fsi_stream_probe(&master->fsia, &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "FSIA stream probe failed\n"); - goto exit_iounmap; + return ret; } /* FSI B setting */ @@ -1734,11 +1732,7 @@ exit_fsib: fsi_stream_remove(&master->fsib); exit_fsia: fsi_stream_remove(&master->fsia); -exit_iounmap: - iounmap(master->base); -exit_kfree: - kfree(master); -exit: + return ret; } @@ -1757,9 +1751,6 @@ static int fsi_remove(struct platform_device *pdev) fsi_stream_remove(&master->fsia); fsi_stream_remove(&master->fsib); - iounmap(master->base); - kfree(master); - return 0; } From d9780550a354058bc47db6ac48d3b77f186882c6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 17:52:59 +0800 Subject: [PATCH 481/665] ASoC: wm8741: Move regulator acquisition to I2C/SPI probe() Better style as we acquire resources before trying the ASoC card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 35f3d23200e0..742744b4bba7 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -403,17 +403,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) { struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); int ret = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) - wm8741->supplies[i].supply = wm8741_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), - wm8741->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); @@ -450,7 +439,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err_get: - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err: return ret; } @@ -460,7 +448,6 @@ static int wm8741_remove(struct snd_soc_codec *codec) struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); return 0; } @@ -492,13 +479,23 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8741_priv *wm8741; - int ret; + int ret, i; wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), GFP_KERNEL); if (wm8741 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) + wm8741->supplies[i].supply = wm8741_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), + wm8741->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + goto err; + } + i2c_set_clientdata(i2c, wm8741); wm8741->control_type = SND_SOC_I2C; @@ -536,13 +533,23 @@ static struct i2c_driver wm8741_i2c_driver = { static int __devinit wm8741_spi_probe(struct spi_device *spi) { struct wm8741_priv *wm8741; - int ret; + int ret, i; wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), GFP_KERNEL); if (wm8741 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) + wm8741->supplies[i].supply = wm8741_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), + wm8741->supplies); + if (ret != 0) { + dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); + goto err; + } + wm8741->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8741); From fe98c0cf40883e7d12456e0abc269e4fa31bed69 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 18:00:21 +0800 Subject: [PATCH 482/665] ASoC: wm8741: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 86 ++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 742744b4bba7..4281a0802138 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -40,26 +41,43 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { /* codec private data */ struct wm8741_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; }; -static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = { - 0x0000, /* R0 - DACLLSB Attenuation */ - 0x0000, /* R1 - DACLMSB Attenuation */ - 0x0000, /* R2 - DACRLSB Attenuation */ - 0x0000, /* R3 - DACRMSB Attenuation */ - 0x0000, /* R4 - Volume Control */ - 0x000A, /* R5 - Format Control */ - 0x0000, /* R6 - Filter Control */ - 0x0000, /* R7 - Mode Control 1 */ - 0x0002, /* R8 - Mode Control 2 */ - 0x0000, /* R9 - Reset */ - 0x0002, /* R32 - ADDITONAL_CONTROL_1 */ +static const struct reg_default wm8741_reg_defaults[] = { + { 0, 0x0000 }, /* R0 - DACLLSB Attenuation */ + { 1, 0x0000 }, /* R1 - DACLMSB Attenuation */ + { 2, 0x0000 }, /* R2 - DACRLSB Attenuation */ + { 3, 0x0000 }, /* R3 - DACRMSB Attenuation */ + { 4, 0x0000 }, /* R4 - Volume Control */ + { 5, 0x000A }, /* R5 - Format Control */ + { 6, 0x0000 }, /* R6 - Filter Control */ + { 7, 0x0000 }, /* R7 - Mode Control 1 */ + { 8, 0x0002 }, /* R8 - Mode Control 2 */ + { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ }; +static bool wm8741_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8741_DACLLSB_ATTENUATION: + case WM8741_DACLMSB_ATTENUATION: + case WM8741_DACRLSB_ATTENUATION: + case WM8741_DACRMSB_ATTENUATION: + case WM8741_VOLUME_CONTROL: + case WM8741_FORMAT_CONTROL: + case WM8741_FILTER_CONTROL: + case WM8741_MODE_CONTROL_1: + case WM8741_MODE_CONTROL_2: + case WM8741_ADDITIONAL_CONTROL_1: + return true; + default: + return false; + } +} static int wm8741_reset(struct snd_soc_codec *codec) { @@ -411,7 +429,7 @@ static int wm8741_probe(struct snd_soc_codec *codec) goto err_get; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); goto err_enable; @@ -439,7 +457,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err_get: -err: return ret; } @@ -456,9 +473,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { .probe = wm8741_probe, .remove = wm8741_remove, .resume = wm8741_resume, - .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8741_reg_defaults, .controls = wm8741_snd_controls, .num_controls = ARRAY_SIZE(wm8741_snd_controls), @@ -474,6 +488,18 @@ static const struct of_device_id wm8741_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8741_of_match); +static const struct regmap_config wm8741_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8741_MAX_REGISTER, + + .reg_defaults = wm8741_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .readable_reg = wm8741_readable, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8741_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -492,12 +518,18 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), wm8741->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + + wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap); + if (IS_ERR(wm8741->regmap)) { + ret = PTR_ERR(wm8741->regmap); + dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); + return ret; } i2c_set_clientdata(i2c, wm8741); - wm8741->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8741, &wm8741_dai, 1); @@ -543,14 +575,20 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi) for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) wm8741->supplies[i].supply = wm8741_supply_names[i]; - ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), + ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8741->supplies), wm8741->supplies); if (ret != 0) { dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; + } + + wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap); + if (IS_ERR(wm8741->regmap)) { + ret = PTR_ERR(wm8741->regmap); + dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); + return ret; } - wm8741->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8741); ret = snd_soc_register_codec(&spi->dev, From a044b75779201b1eb293ffcb887404357b21421e Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 10 Sep 2012 17:50:33 +0800 Subject: [PATCH 483/665] ASoC: wm8904: remove redundant code The core_intercon is added two times, remove the redundant one Signed-off-by: Bo Shen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 0013afe48e66..2b9766d55384 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1185,8 +1185,6 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec) snd_soc_dapm_new_controls(dapm, wm8904_dapm_widgets, ARRAY_SIZE(wm8904_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, core_intercon, - ARRAY_SIZE(core_intercon)); snd_soc_dapm_add_routes(dapm, adc_intercon, ARRAY_SIZE(adc_intercon)); snd_soc_dapm_add_routes(dapm, dac_intercon, From 0ebe36c6c4fe8fcfeee3192f37f2ff8318a029bd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 19:23:57 +0800 Subject: [PATCH 484/665] ASoC: wm8960: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 107 ++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 804f4116912f..7cb0d07ca8a6 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -52,25 +52,72 @@ * We can't read the WM8960 register space when we are * using 2 wire for device control, so we cache them instead. */ -static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { - 0x0097, 0x0097, 0x0000, 0x0000, - 0x0000, 0x0008, 0x0000, 0x000a, - 0x01c0, 0x0000, 0x00ff, 0x00ff, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x007b, 0x0100, 0x0032, - 0x0000, 0x00c3, 0x00c3, 0x01c0, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0100, 0x0100, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0040, 0x0000, - 0x0000, 0x0050, 0x0050, 0x0000, - 0x0002, 0x0037, 0x004d, 0x0080, - 0x0008, 0x0031, 0x0026, 0x00e9, +static const struct reg_default wm8960_reg_defaults[] = { + { 0x0, 0x0097 }, + { 0x1, 0x0097 }, + { 0x2, 0x0000 }, + { 0x3, 0x0000 }, + { 0x4, 0x0000 }, + { 0x5, 0x0008 }, + { 0x6, 0x0000 }, + { 0x7, 0x000a }, + { 0x8, 0x01c0 }, + { 0x9, 0x0000 }, + { 0xa, 0x00ff }, + { 0xb, 0x00ff }, + + { 0x10, 0x0000 }, + { 0x11, 0x007b }, + { 0x12, 0x0100 }, + { 0x13, 0x0032 }, + { 0x14, 0x0000 }, + { 0x15, 0x00c3 }, + { 0x16, 0x00c3 }, + { 0x17, 0x01c0 }, + { 0x18, 0x0000 }, + { 0x19, 0x0000 }, + { 0x1a, 0x0000 }, + { 0x1b, 0x0000 }, + { 0x1c, 0x0000 }, + { 0x1d, 0x0000 }, + + { 0x20, 0x0100 }, + { 0x21, 0x0100 }, + { 0x22, 0x0050 }, + + { 0x25, 0x0050 }, + { 0x26, 0x0000 }, + { 0x27, 0x0000 }, + { 0x28, 0x0000 }, + { 0x29, 0x0000 }, + { 0x2a, 0x0040 }, + { 0x2b, 0x0000 }, + { 0x2c, 0x0000 }, + { 0x2d, 0x0050 }, + { 0x2e, 0x0050 }, + { 0x2f, 0x0000 }, + { 0x30, 0x0002 }, + { 0x31, 0x0037 }, + + { 0x33, 0x0080 }, + { 0x34, 0x0008 }, + { 0x35, 0x0031 }, + { 0x36, 0x0026 }, + { 0x37, 0x00e9 }, }; +static bool wm8960_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8960_RESET: + return true; + default: + return false; + } +} + struct wm8960_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; int (*set_bias_level)(struct snd_soc_codec *, enum snd_soc_bias_level level); struct snd_soc_dapm_widget *lout1; @@ -555,6 +602,8 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + switch (level) { case SND_SOC_BIAS_ON: break; @@ -566,7 +615,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); + regcache_sync(wm8960->regmap); /* Enable anti-pop features */ snd_soc_write(codec, WM8960_APOP1, @@ -667,7 +716,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - snd_soc_cache_sync(codec); + regcache_sync(wm8960->regmap); break; default: break; @@ -915,7 +964,7 @@ static int wm8960_probe(struct snd_soc_codec *codec) wm8960->set_bias_level = wm8960_set_bias_level_capless; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -963,9 +1012,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { .suspend = wm8960_suspend, .resume = wm8960_resume, .set_bias_level = wm8960_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8960_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8960_reg, +}; + +static const struct regmap_config wm8960_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8960_PLL4, + + .reg_defaults = wm8960_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8960_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8960_volatile, }; static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, @@ -979,8 +1037,11 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, if (wm8960 == NULL) return -ENOMEM; + wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap); + if (IS_ERR(wm8960->regmap)) + return PTR_ERR(wm8960->regmap); + i2c_set_clientdata(i2c, wm8960); - wm8960->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8960, &wm8960_dai, 1); From f3d87524975f01b885fc3d009c6ab6afd0d00746 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 10 Sep 2012 16:14:16 +0200 Subject: [PATCH 485/665] arm: mm: fix DMA pool affiliation check The __free_from_pool() function was changed in e9da6e9905e639b0f842a244bc770b48ad0523e9. Unfortunately, the test that checks whether the provided (start,size) is within the DMA pool has been improperly modified. It used to be: if (start < coherent_head.vm_start || end > coherent_head.vm_end) Where coherent_head.vm_end was non-inclusive (i.e, it did not include the first byte after the pool). The test has been changed to: if (start < pool->vaddr || start > pool->vaddr + pool->size) So now pool->vaddr + pool->size is inclusive (i.e, it includes the first byte after the pool), so the test should be >= instead of >. This bug causes the following message when freeing the *first* DMA coherent buffer that has been allocated, because its virtual address is exactly equal to pool->vaddr + pool->size : WARNING: at /home/thomas/projets/linux-2.6/arch/arm/mm/dma-mapping.c:463 __free_from_pool+0xa4/0xc0() freeing wrong coherent size from pool Signed-off-by: Thomas Petazzoni Cc: Marek Szyprowski Cc: Russell King Cc: Lior Amsalem Cc: Maen Suleiman Cc: Tawfik Bayouk Cc: Shadi Ammouri Cc: Eran Ben-Avi Cc: Yehuda Yitschak Cc: Nadav Haklai [m.szyprowski: rebased onto v3.6-rc5 and resolved conflict] Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 051204fc4617..e59c4ab71bcb 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -489,7 +489,7 @@ static bool __in_atomic_pool(void *start, size_t size) void *pool_start = pool->vaddr; void *pool_end = pool->vaddr + pool->size; - if (start < pool_start || start > pool_end) + if (start < pool_start || start >= pool_end) return false; if (end <= pool_end) From c06fad9d28c95b024ea10455cf1397432b12848d Mon Sep 17 00:00:00 2001 From: "Philip, Avinash" Date: Thu, 23 Aug 2012 12:29:46 +0530 Subject: [PATCH 486/665] pwm: pwm-tiecap: Disable APWM mode after configure APWM mode is enabled while configuring PWM device. This was done to handle shadow & immediate mode update of period and compare registers. However, leaving it enabled after configuring will cause APWM output on PWM pin even before enabling PWM device. Fix the same by disabling APWM mode after configuring if PWM device is not running. Signed-off-by: Philip, Avinash Signed-off-by: Thierry Reding --- drivers/pwm/pwm-tiecap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 0b66d0f25922..4b6688909fee 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -100,6 +100,13 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } + if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + reg_val = readw(pc->mmio_base + ECCTL2); + /* Disable APWM mode to put APWM output Low */ + reg_val &= ~ECCTL2_APWM_MODE; + writew(reg_val, pc->mmio_base + ECCTL2); + } + pm_runtime_put_sync(pc->chip.dev); return 0; } From 01b2d4536f0215c6d97d77e157afee04300ffc90 Mon Sep 17 00:00:00 2001 From: "Philip, Avinash" Date: Thu, 6 Sep 2012 10:44:25 +0530 Subject: [PATCH 487/665] pwm: pwm-tiehrpwm: Fix conflicting channel period setting EHRPWM hardware supports 2 independent PWM channels. However the device uses only one register to handle period setting for both channels. So both channels should be configured for same period (in nsec). Fix the same by returning error for conflicting period values. However, allow 1. Configuration of period settings if not conflicting with other channels 2. Re-configuring of period settings if no other channels being configured Signed-off-by: Philip, Avinash Signed-off-by: Thierry Reding --- drivers/pwm/pwm-tiehrpwm.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index c3756d1be194..b1996bcd5b78 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -104,6 +104,7 @@ struct ehrpwm_pwm_chip { struct pwm_chip chip; unsigned int clk_rate; void __iomem *mmio_base; + unsigned long period_cycles[NUM_PWM_CHANNEL]; }; static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) @@ -210,6 +211,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long long c; unsigned long period_cycles, duty_cycles; unsigned short ps_divval, tb_divval; + int i; if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) return -ERANGE; @@ -229,6 +231,28 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, duty_cycles = (unsigned long)c; } + /* + * Period values should be same for multiple PWM channels as IP uses + * same period register for multiple channels. + */ + for (i = 0; i < NUM_PWM_CHANNEL; i++) { + if (pc->period_cycles[i] && + (pc->period_cycles[i] != period_cycles)) { + /* + * Allow channel to reconfigure period if no other + * channels being configured. + */ + if (i == pwm->hwpwm) + continue; + + dev_err(chip->dev, "Period value conflicts with channel %d\n", + i); + return -EINVAL; + } + } + + pc->period_cycles[pwm->hwpwm] = period_cycles; + /* Configure clock prescaler to support Low frequency PWM wave */ if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval, &tb_divval)) { @@ -320,10 +344,15 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + if (test_bit(PWMF_ENABLED, &pwm->flags)) { dev_warn(chip->dev, "Removing PWM device without disabling\n"); pm_runtime_put_sync(chip->dev); } + + /* set period value to zero on free */ + pc->period_cycles[pwm->hwpwm] = 0; } static const struct pwm_ops ehrpwm_pwm_ops = { From 552a37e9360a293cd20e7f8ff1fb326a244c5f1e Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 10 Sep 2012 10:03:33 -0700 Subject: [PATCH 488/665] workqueue: restore POOL_MANAGING_WORKERS This patch restores POOL_MANAGING_WORKERS which was replaced by pool->manager_mutex by 6037315269 "workqueue: use mutex for global_cwq manager exclusion". There's a subtle idle worker depletion bug across CPU hotplug events and we need to distinguish an actual manager and CPU hotplug preventing management. POOL_MANAGING_WORKERS will be used for the former and manager_mutex the later. This patch just lays POOL_MANAGING_WORKERS on top of the existing manager_mutex and doesn't introduce any synchronization changes. The next patch will update it. Note that this patch fixes a non-critical anomaly where too_many_workers() may return %true spuriously while CPU hotplug is in progress. While the issue could schedule idle timer spuriously, it didn't trigger any actual misbehavior. tj: Rewrote patch description. Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo --- kernel/workqueue.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index dc7b8458e275..383548ed0b54 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -66,6 +66,7 @@ enum { /* pool flags */ POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ + POOL_MANAGING_WORKERS = 1 << 1, /* managing workers */ /* worker flags */ WORKER_STARTED = 1 << 0, /* started */ @@ -652,7 +653,7 @@ static bool need_to_manage_workers(struct worker_pool *pool) /* Do we have too many workers and should some go away? */ static bool too_many_workers(struct worker_pool *pool) { - bool managing = mutex_is_locked(&pool->manager_mutex); + bool managing = pool->flags & POOL_MANAGING_WORKERS; int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ int nr_busy = pool->nr_workers - nr_idle; @@ -1827,6 +1828,7 @@ static bool manage_workers(struct worker *worker) if (!mutex_trylock(&pool->manager_mutex)) return ret; + pool->flags |= POOL_MANAGING_WORKERS; pool->flags &= ~POOL_MANAGE_WORKERS; /* @@ -1836,6 +1838,7 @@ static bool manage_workers(struct worker *worker) ret |= maybe_destroy_workers(pool); ret |= maybe_create_worker(pool); + pool->flags &= ~POOL_MANAGING_WORKERS; mutex_unlock(&pool->manager_mutex); return ret; } From ee378aa49b594da9bda6a2c768cc5b2ad585f911 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 10 Sep 2012 10:03:44 -0700 Subject: [PATCH 489/665] workqueue: fix possible idle worker depletion across CPU hotplug To simplify both normal and CPU hotplug paths, worker management is prevented while CPU hoplug is in progress. This is achieved by CPU hotplug holding the same exclusion mechanism used by workers to ensure there's only one manager per pool. If someone else seems to be performing the manager role, workers proceed to execute work items. CPU hotplug using the same mechanism can lead to idle worker depletion because all workers could proceed to execute work items while CPU hotplug is in progress and CPU hotplug itself wouldn't actually perform the worker management duty - it doesn't guarantee that there's an idle worker left when it releases management. This idle worker depletion, under extreme circumstances, can break forward-progress guarantee and thus lead to deadlock. This patch fixes the bug by using separate mechanisms for manager exclusion among workers and hotplug exclusion. For manager exclusion, POOL_MANAGING_WORKERS which was restored by the previous patch is used. pool->manager_mutex is now only used for exclusion between the elected manager and CPU hotplug. The elected manager won't proceed without holding pool->manager_mutex. This ensures that the worker which won the manager position can't skip managing while CPU hotplug is in progress. It will block on manager_mutex and perform management after CPU hotplug is complete. Note that hotplug may happen while waiting for manager_mutex. A manager isn't either on idle or busy list and thus the hoplug code can't unbind/rebind it. Make the manager handle its own un/rebinding. tj: Updated comment and description. Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo --- kernel/workqueue.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 383548ed0b54..1e1373bcb3e3 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1825,10 +1825,45 @@ static bool manage_workers(struct worker *worker) struct worker_pool *pool = worker->pool; bool ret = false; - if (!mutex_trylock(&pool->manager_mutex)) + if (pool->flags & POOL_MANAGING_WORKERS) return ret; pool->flags |= POOL_MANAGING_WORKERS; + + /* + * To simplify both worker management and CPU hotplug, hold off + * management while hotplug is in progress. CPU hotplug path can't + * grab %POOL_MANAGING_WORKERS to achieve this because that can + * lead to idle worker depletion (all become busy thinking someone + * else is managing) which in turn can result in deadlock under + * extreme circumstances. Use @pool->manager_mutex to synchronize + * manager against CPU hotplug. + * + * manager_mutex would always be free unless CPU hotplug is in + * progress. trylock first without dropping @gcwq->lock. + */ + if (unlikely(!mutex_trylock(&pool->manager_mutex))) { + spin_unlock_irq(&pool->gcwq->lock); + mutex_lock(&pool->manager_mutex); + /* + * CPU hotplug could have happened while we were waiting + * for manager_mutex. Hotplug itself can't handle us + * because manager isn't either on idle or busy list, and + * @gcwq's state and ours could have deviated. + * + * As hotplug is now excluded via manager_mutex, we can + * simply try to bind. It will succeed or fail depending + * on @gcwq's current state. Try it and adjust + * %WORKER_UNBOUND accordingly. + */ + if (worker_maybe_bind_and_lock(worker)) + worker->flags &= ~WORKER_UNBOUND; + else + worker->flags |= WORKER_UNBOUND; + + ret = true; + } + pool->flags &= ~POOL_MANAGE_WORKERS; /* From f08dea734844aa42ec57c229b0b73b3d7d21f810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 10 Sep 2012 12:01:05 +0200 Subject: [PATCH 490/665] USB: ftdi_sio: do not claim CDC ACM function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Microchip vid:pid 04d8:000a is used for their CDC ACM demo firmware application. This is a device with a single function conforming to the CDC ACM specification and with the intention of demonstrating CDC ACM class firmware and driver interaction. The demo is used on a number of development boards, and may also be used unmodified by vendors using Microchip hardware. Some vendors have re-used this vid:pid for other types of firmware, emulating FTDI chips. Attempting to continue to support such devices without breaking class based applications that by matching on interface class/subclass/proto being ff/ff/00. I have no information about the actual device or interface descriptors, but this will at least make the proper CDC ACM devices work again. Anyone having details of the offending device's descriptors should update this entry with the details. Reported-by: Florian Wöhrl Reported-by: Xiaofan Chen Cc: stable Cc: Alan Cox Cc: Bruno Thomsen Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 +++- drivers/usb/serial/ftdi_sio_ids.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e2fa7881067d..f906b3aec217 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -805,7 +805,9 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, + { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, + USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_VENDOR_SPEC, 0x00) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9bcaf9c3d3e4..41fe5826100c 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -542,7 +542,10 @@ /* * Microchip Technology, Inc. * - * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are + * used by single function CDC ACM class based firmware demo + * applications. The VID/PID has also been used in firmware + * emulating FTDI serial chips by: * Hornby Elite - Digital Command Control Console * http://www.hornby.com/hornby-dcc/controllers/ */ From 2120c52da6fe741454a60644018ad2a6abd957ac Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Fri, 7 Sep 2012 12:14:02 +0000 Subject: [PATCH 491/665] sierra_net: Endianess bug fix. I discovered I couldn't get sierra_net to work on a powerpc. Turns out the firmware attribute check assumes the system is little endian and hence fails because the attributes is a 16 bit value. Signed-off-by: Len Sorensen Signed-off-by: David S. Miller --- drivers/net/usb/sierra_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 7be49ea60b6d..8e22417fa6c1 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -656,7 +656,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) return -EIO; } - *datap = *attrdata; + *datap = le16_to_cpu(*attrdata); kfree(attrdata); return result; From 974a3b0f9f05b748fe11f1afc31efc32aa5160cb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 9 Sep 2012 11:54:16 +0200 Subject: [PATCH 492/665] drm/i915: set the right gen3 flip_done mode also at resume Currently we've only frobbed this bit at irq_init time, but did not restore it at resume time. Move it to the gen3 clock gating function to fix this. Notice while reading through code. Cc: stable@vger.kernel.org (for 3.5 only) Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 3 --- drivers/gpu/drm/i915/intel_pm.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8a3828528b9d..5249640cce13 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2700,9 +2700,6 @@ void intel_irq_init(struct drm_device *dev) dev->driver->irq_handler = i8xx_irq_handler; dev->driver->irq_uninstall = i8xx_irq_uninstall; } else if (INTEL_INFO(dev)->gen == 3) { - /* IIR "flip pending" means done if this bit is set */ - I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); - dev->driver->irq_preinstall = i915_irq_preinstall; dev->driver->irq_postinstall = i915_irq_postinstall; dev->driver->irq_uninstall = i915_irq_uninstall; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1881c8c83f0e..ba8a27b1757a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3672,6 +3672,9 @@ static void gen3_init_clock_gating(struct drm_device *dev) if (IS_PINEVIEW(dev)) I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); + + /* IIR "flip pending" means done if this bit is set */ + I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); } static void i85x_init_clock_gating(struct drm_device *dev) From 566f26aa705609d05940289036ab914c8a3be707 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 9 Sep 2012 18:38:27 +0000 Subject: [PATCH 493/665] caif: move the dereference below the NULL test The dereference should be moved below the NULL test. spatch with a semantic match is used to found this. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/caif/cfsrvl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index dd485f6128e8..ba217e90765e 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -211,9 +211,10 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer, void (*put)(struct cflayer *lyr)) { struct cfsrvl *service; - service = container_of(adapt_layer->dn, struct cfsrvl, layer); - WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); + if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL)) + return; + service = container_of(adapt_layer->dn, struct cfsrvl, layer); service->hold = hold; service->put = put; } From 0b836ddde177bdd5790ade83772860940bd481ea Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 10 Sep 2012 14:06:58 +0200 Subject: [PATCH 494/665] ixp4xx_hss: fix build failure due to missing linux/module.h inclusion Commit 36a1211970193ce215de50ed1e4e1272bc814df1 (netprio_cgroup.h: dont include module.h from other includes) made the following build error on ixp4xx_hss pop up: CC [M] drivers/net/wan/ixp4xx_hss.o drivers/net/wan/ixp4xx_hss.c:1412:20: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1413:25: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1414:21: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1415:19: error: expected ';', ',' or ')' before string constant make[8]: *** [drivers/net/wan/ixp4xx_hss.o] Error 1 This was previously hidden because ixp4xx_hss includes linux/hdlc.h which includes linux/netdevice.h which includes linux/netprio_cgroup.h which used to include linux/module.h. The real issue was actually present since the initial commit that added this driver since it uses macros from linux/module.h without including this file. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/wan/ixp4xx_hss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index aaaca9aa2293..3f575afd8cfc 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include From 1c463e57b32e3b6a3250fe75d1d56cb598d664e6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 10 Sep 2012 09:13:07 -0700 Subject: [PATCH 495/665] net: fix net/core/sock.c build error Fix net/core/sock.c build error when CONFIG_INET is not enabled: net/built-in.o: In function `sock_edemux': (.text+0xd396): undefined reference to `inet_twsk_put' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- net/core/sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/sock.c b/net/core/sock.c index 7f64467535d1..305792076121 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1525,9 +1525,11 @@ void sock_edemux(struct sk_buff *skb) { struct sock *sk = skb->sk; +#ifdef CONFIG_INET if (sk->sk_state == TCP_TIME_WAIT) inet_twsk_put(inet_twsk(sk)); else +#endif sock_put(sk); } EXPORT_SYMBOL(sock_edemux); From 6a44886899ef8cc396e230e492e6a56a883889f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 10 Sep 2012 22:17:34 +0200 Subject: [PATCH 496/665] USB: cdc-wdm: fix wdm_find_device* return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A logic error made the wdm_find_device* functions return a bogus pointer into static data instead of the intended NULL no matching device was found. Cc: stable # v3.4+ Cc: Oliver Neukum Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 65a55abb791f..5f0cb417b736 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -109,12 +109,14 @@ static struct usb_driver wdm_driver; /* return intfdata if we own the interface, else look up intf in the list */ static struct wdm_device *wdm_find_device(struct usb_interface *intf) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf == intf) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; @@ -122,12 +124,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf) static struct wdm_device *wdm_find_device_by_minor(int minor) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf->minor == minor) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; From abf02cfc179bb4bd30d05f582d61b3b8f429b813 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 10 Sep 2012 21:22:11 +0200 Subject: [PATCH 497/665] staging: r8712u: fix bug in r8712_recv_indicatepkt() 64bit arches have a buggy r8712u driver, let's fix it. skb->tail must be set properly or network stack behavior is undefined. Addresses https://bugzilla.redhat.com/show_bug.cgi?id=847525 Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45071 Signed-off-by: Eric Dumazet Cc: Dave Jones Cc: stable [2.6.37+] Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 0e26d5f6cf2d..495ee1205e02 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -117,13 +117,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter, if (skb == NULL) goto _recv_indicatepkt_drop; skb->data = precv_frame->u.hdr.rx_data; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail - - precv_frame->u.hdr.rx_head); -#else - skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail; -#endif skb->len = precv_frame->u.hdr.len; + skb_set_tail_pointer(skb, skb->len); if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) skb->ip_summed = CHECKSUM_UNNECESSARY; else From 3d037774b42ed677f699b1dce7d548d55f4e4c2b Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Fri, 7 Sep 2012 11:23:28 +0530 Subject: [PATCH 498/665] EHCI: Update qTD next pointer in QH overlay region during unlink There is a possibility of QH overlay region having reference to a stale qTD pointer during unlink. Consider an endpoint having two pending qTD before unlink process begins. The endpoint's QH queue looks like this. qTD1 --> qTD2 --> Dummy To unlink qTD2, QH is removed from asynchronous list and Asynchronous Advance Doorbell is programmed. The qTD1's next qTD pointer is set to qTD2'2 next qTD pointer and qTD2 is retired upon controller's doorbell interrupt. If QH's current qTD pointer points to qTD1, transfer overlay region still have reference to qTD2. But qtD2 is just unlinked and freed. This may cause EHCI system error. Fix this by updating qTD next pointer in QH overlay region with the qTD next pointer of the current qTD. Signed-off-by: Pavankumar Kondeti Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 9bc39ca460c8..4b66374bdc8e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) else { qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list); - /* first qtd may already be partially processed */ - if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) + /* + * first qtd may already be partially processed. + * If we come here during unlink, the QH overlay region + * might have reference to the just unlinked qtd. The + * qtd is updated in qh_completions(). Update the QH + * overlay here. + */ + if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { + qh->hw->hw_qtd_next = qtd->hw_next; qtd = NULL; + } } if (qtd) From 0b0d7b62bed81a76dd2b3f12ba6a33eb144a1df6 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 5 Sep 2012 16:48:53 -0500 Subject: [PATCH 499/665] drm/omap: update for interlaced 'struct omap_video_timings' was updated w/ a 'bool interlaced'. Without a matching update in omap_connector, this field could have undefined values from the stack, which isn't quite ideal. Update the fxns to convert omapdss<->drm timings structs, and zero-init 'struct omap_video_timings' when it is declared on stack to avoid issues like this in the future. Signed-off-by: Rob Clark Reviewed-by: Sumit Semwal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/omap_connector.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5e2856c0e0bb..5f4a89be3dda 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -48,13 +48,10 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->vsync_end = mode->vsync_start + timings->vsw; mode->vtotal = mode->vsync_end + timings->vbp; - /* note: whether or not it is interlaced, +/- h/vsync, etc, - * which should be set in the mode flags, is not exposed in - * the omap_video_timings struct.. but hdmi driver tracks - * those separately so all we have to have to set the mode - * is the way to recover these timings values, and the - * omap_dss_driver would do the rest. - */ + mode->flags = 0; + + if (timings->interlace) + mode->flags |= DRM_MODE_FLAG_INTERLACE; } static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -71,6 +68,8 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vfp = mode->vsync_start - mode->vdisplay; timings->vsw = mode->vsync_end - mode->vsync_start; timings->vbp = mode->vtotal - mode->vsync_end; + + timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); } static void omap_connector_dpms(struct drm_connector *connector, int mode) @@ -187,7 +186,7 @@ static int omap_connector_get_modes(struct drm_connector *connector) } } else { struct drm_display_mode *mode = drm_mode_create(dev); - struct omap_video_timings timings; + struct omap_video_timings timings = {0}; dssdrv->get_timings(dssdev, &timings); @@ -291,7 +290,7 @@ void omap_connector_mode_set(struct drm_connector *connector, struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; - struct omap_video_timings timings; + struct omap_video_timings timings = {0}; copy_timings_drm_to_omap(&timings, mode); From 94254edc9c5b4e864767c97bfa0e4ccff2ecb5e5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 7 Sep 2012 12:59:45 -0500 Subject: [PATCH 500/665] drm/omap: add more new timings fields Without these, DVI is broken. Signed-off-by: Rob Clark Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/omap_connector.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5f4a89be3dda..55e9c8655850 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -52,6 +52,16 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, if (timings->interlace) mode->flags |= DRM_MODE_FLAG_INTERLACE; + + if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + mode->flags |= DRM_MODE_FLAG_PHSYNC; + else + mode->flags |= DRM_MODE_FLAG_NHSYNC; + + if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + mode->flags |= DRM_MODE_FLAG_PVSYNC; + else + mode->flags |= DRM_MODE_FLAG_NVSYNC; } static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -70,6 +80,20 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vbp = mode->vtotal - mode->vsync_end; timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + + if (mode->flags & DRM_MODE_FLAG_PHSYNC) + timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + else + timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW; + + if (mode->flags & DRM_MODE_FLAG_PVSYNC) + timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + else + timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW; + + timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; + timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; } static void omap_connector_dpms(struct drm_connector *connector, int mode) From 19ace0e97a605042c481c2ea3f7aeb59c0eb54ed Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 12:48:11 +0800 Subject: [PATCH 501/665] ASoC: cs4270: Conver to data based control init Signed-off-by: Mark Brown Acked-by: Timur Tabi --- sound/soc/codecs/cs4270.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 44a176f74170..c6e5a73a9f17 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -521,14 +521,6 @@ static int cs4270_probe(struct snd_soc_codec *codec) return ret; } - /* Add the non-DAPM controls */ - ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls, - ARRAY_SIZE(cs4270_snd_controls)); - if (ret < 0) { - dev_err(codec->dev, "failed to add controls\n"); - return ret; - } - /* get the power supply regulators */ for (i = 0; i < ARRAY_SIZE(supply_names); i++) cs4270->supplies[i].supply = supply_names[i]; @@ -634,6 +626,9 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .remove = cs4270_remove, .suspend = cs4270_soc_suspend, .resume = cs4270_soc_resume, + + .controls = cs4270_snd_controls, + .num_controls = ARRAY_SIZE(cs4270_snd_controls), .volatile_register = cs4270_reg_is_volatile, .readable_register = cs4270_reg_is_readable, .reg_cache_size = CS4270_LASTREG + 1, From b61d6d40323997d9da3b95ecce2570f0b782a07f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 12:53:12 +0800 Subject: [PATCH 502/665] ASoC: cs4270: Move regulator acquisition to I2C probe() This is better style since it has us obtaining all resources before we try the ASoC probe. This change also fixes a potential issue where we don't enable the regulators before trying to confirm the device ID which could cause a failure during probe in some system configurations. Signed-off-by: Mark Brown Acked-by: Timur Tabi --- sound/soc/codecs/cs4270.c | 46 ++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index c6e5a73a9f17..64c29b8a379f 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -487,7 +487,7 @@ static struct snd_soc_dai_driver cs4270_dai = { static int cs4270_probe(struct snd_soc_codec *codec) { struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int i, ret; + int ret; /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. @@ -521,25 +521,8 @@ static int cs4270_probe(struct snd_soc_codec *codec) return ret; } - /* get the power supply regulators */ - for (i = 0; i < ARRAY_SIZE(supply_names); i++) - cs4270->supplies[i].supply = supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - if (ret < 0) - return ret; - ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - if (ret < 0) - goto error_free_regulators; - - return 0; - -error_free_regulators: - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); return ret; } @@ -555,7 +538,6 @@ static int cs4270_remove(struct snd_soc_codec *codec) struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); return 0; }; @@ -658,7 +640,24 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, { struct device_node *np = i2c_client->dev.of_node; struct cs4270_private *cs4270; - int ret; + int ret, i; + + cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), + GFP_KERNEL); + if (!cs4270) { + dev_err(&i2c_client->dev, "could not allocate codec\n"); + return -ENOMEM; + } + + /* get the power supply regulators */ + for (i = 0; i < ARRAY_SIZE(supply_names); i++) + cs4270->supplies[i].supply = supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c_client->dev, + ARRAY_SIZE(cs4270->supplies), + cs4270->supplies); + if (ret < 0) + return ret; /* See if we have a way to bring the codec out of reset */ if (np) { @@ -694,13 +693,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, i2c_client->addr); dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); - cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), - GFP_KERNEL); - if (!cs4270) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); - return -ENOMEM; - } - i2c_set_clientdata(i2c_client, cs4270); cs4270->control_type = SND_SOC_I2C; From 1ca6517566b52662f1dea65e3c3d02997282cb01 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 12:57:03 +0800 Subject: [PATCH 503/665] ASoC: cs4270: Convert to direct regmap API usage Signed-off-by: Mark Brown Acked-by: Timur Tabi --- sound/soc/codecs/cs4270.c | 55 +++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 64c29b8a379f..815b53bc2d27 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -112,14 +112,15 @@ * This array contains the power-on default values of the registers, with the * exception of the "CHIPID" register (01h). The lower four bits of that * register contain the hardware revision, so it is treated as volatile. - * - * Also note that on the CS4270, the first readable register is 1, but ASoC - * assumes the first register is 0. Therfore, the array must have an entry for - * register 0, but we use cs4270_reg_is_readable() to tell ASoC that it can't - * be read. */ -static const u8 cs4270_default_reg_cache[CS4270_LASTREG + 1] = { - 0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x20, 0x00, 0x00 +static const struct reg_default cs4270_reg_defaults[] = { + { 2, 0x00 }, + { 3, 0x30 }, + { 4, 0x00 }, + { 5, 0x60 }, + { 6, 0x20 }, + { 7, 0x00 }, + { 8, 0x00 }, }; static const char *supply_names[] = { @@ -128,7 +129,7 @@ static const char *supply_names[] = { /* Private data for the CS4270 */ struct cs4270_private { - enum snd_soc_control_type control_type; + struct regmap *regmap; unsigned int mclk; /* Input frequency of the MCLK pin */ unsigned int mode; /* The mode (I2S or left-justified) */ unsigned int slave_mode; @@ -193,12 +194,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = { /* The number of MCLK/LRCK ratios supported by the CS4270 */ #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) -static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg) +static bool cs4270_reg_is_readable(struct device *dev, unsigned int reg) { return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); } -static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg) +static bool cs4270_reg_is_volatile(struct device *dev, unsigned int reg) { /* Unreadable registers are considered volatile */ if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) @@ -492,7 +493,7 @@ static int cs4270_probe(struct snd_soc_codec *codec) /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->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 (ret=%i)\n", ret); return ret; @@ -587,7 +588,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) ndelay(500); /* first restore the entire register cache ... */ - snd_soc_cache_sync(codec); + regcache_sync(cs4270->regmap); /* ... then disable the power-down bits */ reg = snd_soc_read(codec, CS4270_PWRCTL); @@ -611,11 +612,6 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .controls = cs4270_snd_controls, .num_controls = ARRAY_SIZE(cs4270_snd_controls), - .volatile_register = cs4270_reg_is_volatile, - .readable_register = cs4270_reg_is_readable, - .reg_cache_size = CS4270_LASTREG + 1, - .reg_word_size = sizeof(u8), - .reg_cache_default = cs4270_default_reg_cache, }; /* @@ -627,6 +623,18 @@ static const struct of_device_id cs4270_of_match[] = { }; MODULE_DEVICE_TABLE(of, cs4270_of_match); +static const struct regmap_config cs4270_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = CS4270_LASTREG, + .reg_defaults = cs4270_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs4270_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .readable_reg = cs4270_reg_is_readable, + .volatile_reg = cs4270_reg_is_volatile, +}; + /** * cs4270_i2c_probe - initialize the I2C interface of the CS4270 * @i2c_client: the I2C client object @@ -640,6 +648,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, { struct device_node *np = i2c_client->dev.of_node; struct cs4270_private *cs4270; + unsigned int val; int ret, i; cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), @@ -674,16 +683,19 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, } } - /* Verify that we have a CS4270 */ + cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap); + if (IS_ERR(cs4270->regmap)) + return PTR_ERR(cs4270->regmap); - ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); + /* Verify that we have a CS4270 */ + ret = regmap_read(cs4270->regmap, CS4270_CHIPID, &val); if (ret < 0) { dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", i2c_client->addr); return ret; } /* The top four bits of the chip ID should be 1100. */ - if ((ret & 0xF0) != 0xC0) { + if ((val & 0xF0) != 0xC0) { dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", i2c_client->addr); return -ENODEV; @@ -691,10 +703,9 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, dev_info(&i2c_client->dev, "found device at i2c address %X\n", i2c_client->addr); - dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); + dev_info(&i2c_client->dev, "hardware revision %X\n", val & 0xF); i2c_set_clientdata(i2c_client, cs4270); - cs4270->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c_client->dev, &soc_codec_device_cs4270, &cs4270_dai, 1); From 6895f97e15895625e03c95df904d92befdac7118 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 6 Sep 2012 22:11:25 +0100 Subject: [PATCH 504/665] kbuild: add symbol prefix arg to kallsyms Commit 1f2bfbd00e466ff3489b2ca5cc75b1cccd14c123 ("kbuild: link of vmlinux moved to a script") introduced in v3.5-rc1 broke kallsyms on architectures which have symbol prefixes. The --symbol-prefix argument used to be added to the KALLSYMS command line from the architecture Makefile, however this isn't picked up by the new scripts/link-vmlinux.sh. This resulted in symbols like kallsyms_addresses being added which weren't correctly overriding the weak symbols such as _kallsyms_addresses. These could then trigger BUG_ONs in kallsyms code. This is fixed by removing the KALLSYMS addition from the architecture Makefile, and using CONFIG_SYMBOL_PREFIX in the link-vmlinux.sh script to determine whether to add the --symbol-prefix argument. Signed-off-by: James Hogan Signed-off-by: Bob Liu --- arch/blackfin/Makefile | 1 - scripts/link-vmlinux.sh | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index d3d7e64ca96d..66cf00095b84 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -20,7 +20,6 @@ endif KBUILD_AFLAGS += $(call cc-option,-mno-fdpic) KBUILD_CFLAGS_MODULE += -mlong-calls LDFLAGS += -m elf32bfin -KALLSYMS += --symbol-prefix=_ KBUILD_DEFCONFIG := BF537-STAMP_defconfig diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 4629038c9e5a..df48dda8a2da 100644 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -74,8 +74,13 @@ kallsyms() info KSYM ${2} local kallsymopt; + if [ -n "${CONFIG_SYMBOL_PREFIX}" ]; then + kallsymopt="${kallsymopt} \ + --symbol-prefix=${CONFIG_SYMBOL_PREFIX}" + fi + if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then - kallsymopt=--all-symbols + kallsymopt="${kallsymopt} --all-symbols" fi local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ From 1867b2cdd8b3ce377f7c415ee10ce0cf1e581316 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Sep 2012 15:55:17 +0300 Subject: [PATCH 505/665] ASoC: am3517evm: Remove unused cpu_dai from hw_params cpu_dai is not in use in this function and just generates warning at compile time. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/am3517evm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index a997988af147..77a87012977c 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -41,7 +41,6 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set the codec system clock for DAC and ADC */ From 57d9a477f908cd20c1b4da06fdfe864722487d8b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Sep 2012 13:10:08 -0300 Subject: [PATCH 506/665] ASoC: Revert "ASoC: mc13783: Provide codec->control_data" Since commit 98d3088e5 (SoC: core: Fix check before defaulting to regmap) , it is not necessary to provide codec->control_data anymore. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index bbfa5535cdd3..d89e343ff108 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -585,8 +585,6 @@ static int mc13783_probe(struct snd_soc_codec *codec) { struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); - codec->control_data = priv->mc13xxx; - mc13xxx_lock(priv->mc13xxx); /* these are the reset values */ From 4ac7903f1d2cc3dce289d15ce6a6929e935983f5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Sep 2012 13:10:09 -0300 Subject: [PATCH 507/665] ASoC: Revert "ASoC: ab8500: Inform SoC Core that we have our own I/O arrangements" Since commit 98d3088e5 (SoC: core: Fix check before defaulting to regmap) , it is not necessary to provide codec->control_data anymore. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 3f46bffeb0c3..2c1c2524ef8c 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2404,9 +2404,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) dev_dbg(dev, "%s: Enter.\n", __func__); - /* Inform SoC Core that we have our own I/O arrangements. */ - codec->control_data = (void *)true; - /* Setup AB8500 according to board-settings */ pdata = dev_get_platdata(dev->parent); From dbad34eac26f3d31d168486ffb906b9f46657f63 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Sep 2012 13:10:10 -0300 Subject: [PATCH 508/665] Revert "ASoC: AC97 doesn't use regmap by default" Since commit 98d3088e5 (SoC: core: Fix check before defaulting to regmap) , it is not necessary to provide codec->control_data anymore. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/ad1980.c | 1 - sound/soc/codecs/stac9766.c | 1 - sound/soc/codecs/wm9712.c | 1 - sound/soc/codecs/wm9713.c | 1 - 4 files changed, 4 deletions(-) diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 11b1b714b8b5..8c39dddd7d00 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -186,7 +186,6 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) printk(KERN_INFO "AD1980 SoC Audio Codec\n"); - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 33c0f3d39c87..982e437799a8 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -340,7 +340,6 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) goto codec_err; diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1992a6295a16..4dd73ea08d0b 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -635,7 +635,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) { int ret = 0; - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index d0b8a3287a85..3eb19fb71d17 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1196,7 +1196,6 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) if (wm9713 == NULL) return -ENOMEM; snd_soc_codec_set_drvdata(codec, wm9713); - codec->control_data = wm9713; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) From 6a58870df89b1941dc9a47e5ccb3c91bffad5b03 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 09:19:19 +0800 Subject: [PATCH 509/665] ASoC: wm8900: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 077c9628c70d..5f7a78ea518c 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1226,7 +1226,8 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi) struct wm8900_priv *wm8900; int ret; - wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); + wm8900 = devm_kzalloc(&spi->dev, sizeof(struct wm8900_priv), + GFP_KERNEL); if (wm8900 == NULL) return -ENOMEM; @@ -1235,15 +1236,13 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8900, &wm8900_dai, 1); - if (ret < 0) - kfree(wm8900); + return ret; } static int __devexit wm8900_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); return 0; } @@ -1264,7 +1263,8 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, struct wm8900_priv *wm8900; int ret; - wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); + wm8900 = devm_kzalloc(&i2c->dev, sizeof(struct wm8900_priv), + GFP_KERNEL); if (wm8900 == NULL) return -ENOMEM; @@ -1273,15 +1273,13 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8900, &wm8900_dai, 1); - if (ret < 0) - kfree(wm8900); + return ret; } static __devexit int wm8900_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } From 499926246ec77d64b028a953f7a79e941e36b802 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 09:25:41 +0800 Subject: [PATCH 510/665] ASoC: wm8900: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 148 +++++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5f7a78ea518c..5bc877b916eb 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,7 @@ #define WM8900_LRC_MASK 0x03ff struct wm8900_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; u32 fll_in; /* FLL input frequency */ u32 fll_out; /* FLL output frequency */ @@ -147,54 +148,77 @@ struct wm8900_priv { * wm8900 register cache. We can't read the entire register space and we * have slow control buses so we cache the registers. */ -static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { - 0x8900, 0x0000, - 0xc000, 0x0000, - 0x4050, 0x4000, - 0x0008, 0x0000, - 0x0040, 0x0040, - 0x1004, 0x00c0, - 0x00c0, 0x0000, - 0x0100, 0x00c0, - 0x00c0, 0x0000, - 0xb001, 0x0000, - 0x0000, 0x0044, - 0x004c, 0x004c, - 0x0044, 0x0044, - 0x0000, 0x0044, - 0x0000, 0x0000, - 0x0002, 0x0000, - 0x0000, 0x0000, - 0x0000, 0x0000, - 0x0008, 0x0000, - 0x0000, 0x0008, - 0x0097, 0x0100, - 0x0000, 0x0000, - 0x0050, 0x0050, - 0x0055, 0x0055, - 0x0055, 0x0000, - 0x0000, 0x0079, - 0x0079, 0x0079, - 0x0079, 0x0000, - /* Remaining registers all zero */ +static const struct reg_default wm8900_reg_defaults[] = { + { 1, 0x0000 }, + { 2, 0xc000 }, + { 3, 0x0000 }, + { 4, 0x4050 }, + { 5, 0x4000 }, + { 6, 0x0008 }, + { 7, 0x0000 }, + { 8, 0x0040 }, + { 9, 0x0040 }, + { 10, 0x1004 }, + { 11, 0x00c0 }, + { 12, 0x00c0 }, + { 13, 0x0000 }, + { 14, 0x0100 }, + { 15, 0x00c0 }, + { 16, 0x00c0 }, + { 17, 0x0000 }, + { 18, 0xb001 }, + { 19, 0x0000 }, + { 20, 0x0000 }, + { 21, 0x0044 }, + { 22, 0x004c }, + { 23, 0x004c }, + { 24, 0x0044 }, + { 25, 0x0044 }, + { 26, 0x0000 }, + { 27, 0x0044 }, + { 28, 0x0000 }, + { 29, 0x0000 }, + { 30, 0x0002 }, + { 31, 0x0000 }, + { 32, 0x0000 }, + { 33, 0x0000 }, + { 34, 0x0000 }, + { 35, 0x0000 }, + { 36, 0x0008 }, + { 37, 0x0000 }, + { 38, 0x0000 }, + { 39, 0x0008 }, + { 40, 0x0097 }, + { 41, 0x0100 }, + { 42, 0x0000 }, + { 43, 0x0000 }, + { 44, 0x0050 }, + { 45, 0x0050 }, + { 46, 0x0055 }, + { 47, 0x0055 }, + { 48, 0x0055 }, + { 49, 0x0000 }, + { 50, 0x0000 }, + { 51, 0x0079 }, + { 52, 0x0079 }, + { 53, 0x0079 }, + { 54, 0x0079 }, + { 55, 0x0000 }, }; -static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8900_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case WM8900_REG_ID: - return 1; + return true; default: - return 0; + return false; } } static void wm8900_reset(struct snd_soc_codec *codec) { snd_soc_write(codec, WM8900_REG_RESET, 0); - - memcpy(codec->reg_cache, wm8900_reg_defaults, - sizeof(wm8900_reg_defaults)); } static int wm8900_hp_event(struct snd_soc_dapm_widget *w, @@ -1119,13 +1143,16 @@ static int wm8900_suspend(struct snd_soc_codec *codec) static int wm8900_resume(struct snd_soc_codec *codec) { struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); - u16 *cache; - int i, ret; - - cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults), - GFP_KERNEL); + int ret; wm8900_reset(codec); + + ret = regcache_sync(wm8900->regmap); + if (ret != 0) { + dev_err(codec->dev, "Failed to restore cache: %d\n", ret); + return ret; + } + wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Restart the FLL? */ @@ -1139,27 +1166,18 @@ static int wm8900_resume(struct snd_soc_codec *codec) ret = wm8900_set_fll(codec, 0, fll_in, fll_out); if (ret != 0) { dev_err(codec->dev, "Failed to restart FLL\n"); - kfree(cache); return ret; } } - if (cache) { - for (i = 0; i < WM8900_MAXREG; i++) - snd_soc_write(codec, i, cache[i]); - kfree(cache); - } else - dev_err(codec->dev, "Unable to allocate register cache\n"); - return 0; } static int wm8900_probe(struct snd_soc_codec *codec) { - struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); int ret = 0, reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); + 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; @@ -1207,10 +1225,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { .suspend = wm8900_suspend, .resume = wm8900_resume, .set_bias_level = wm8900_set_bias_level, - .volatile_register = wm8900_volatile_register, - .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8900_reg_defaults, .controls = wm8900_snd_controls, .num_controls = ARRAY_SIZE(wm8900_snd_controls), @@ -1220,6 +1234,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), }; +static const struct regmap_config wm8900_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = WM8900_MAXREG, + + .reg_defaults = wm8900_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8900_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8900_volatile_register, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8900_spi_probe(struct spi_device *spi) { @@ -1231,7 +1257,10 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi) if (wm8900 == NULL) return -ENOMEM; - wm8900->control_type = SND_SOC_SPI; + wm8900->regmap = devm_regmap_init_spi(spi, &wm8900_regmap); + if (IS_ERR(wm8900->regmap)) + return PTR_ERR(wm8900->regmap); + spi_set_drvdata(spi, wm8900); ret = snd_soc_register_codec(&spi->dev, @@ -1268,8 +1297,11 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, if (wm8900 == NULL) return -ENOMEM; + wm8900->regmap = devm_regmap_init_i2c(i2c, &wm8900_regmap); + if (IS_ERR(wm8900->regmap)) + return PTR_ERR(wm8900->regmap); + i2c_set_clientdata(i2c, wm8900); - wm8900->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8900, &wm8900_dai, 1); From 7e94ca4752991c3830515f6e17ee5a7334a7f590 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 09:26:09 +0800 Subject: [PATCH 511/665] ASoC: wm8900: Fix typo of name to wm9700 Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5bc877b916eb..e781f865e5d7 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -493,10 +493,10 @@ SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0), SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), }; -static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" }; +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, wm9700_lp_mux); +SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux); static const struct snd_kcontrol_new wm8900_lineout2_lp = SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); From 9b2f4cb65f7083cde86553cd56d6c2878e04932a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 11 Sep 2012 12:05:45 +0800 Subject: [PATCH 512/665] crypto: authenc - Fix crash with zero-length assoc data The authenc code doesn't deal with zero-length associated data correctly and ends up constructing a zero-length sg entry which causes a crash when it's fed into the crypto system. This patch fixes this by avoiding the code-path that triggers the SG construction if we have no associated data. This isn't the most optimal fix as it means that we'll end up using the fallback code-path even when we could still execute the digest function. However, this isn't a big deal as nobody but the test path would supply zero-length associated data. Reported-by: Romain Francoise Signed-off-by: Herbert Xu Tested-by: Romain Francoise --- crypto/authenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/authenc.c b/crypto/authenc.c index 5ef7ba6b6a76..d0583a4489e6 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -336,7 +336,7 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv, cryptlen += ivsize; } - if (sg_is_last(assoc)) { + if (req->assoclen && sg_is_last(assoc)) { authenc_ahash_fn = crypto_authenc_ahash; sg_init_table(asg, 2); sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset); @@ -490,7 +490,7 @@ static int crypto_authenc_iverify(struct aead_request *req, u8 *iv, cryptlen += ivsize; } - if (sg_is_last(assoc)) { + if (req->assoclen && sg_is_last(assoc)) { authenc_ahash_fn = crypto_authenc_ahash; sg_init_table(asg, 2); sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset); From b48d6f8bed430922f78f648d1f73f7c1591e472c Mon Sep 17 00:00:00 2001 From: Pierre Sauter Date: Mon, 10 Sep 2012 07:02:59 +0000 Subject: [PATCH 513/665] net: qmi_wwan: fix Gobi device probing for un2430 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HP un2430 is a Gobi 3000 device. It was mistakenly treated as Gobi 1000 in patch b9f90eb2740203ff2592efe640409ad48335d1c2. I own this device and qmi_wwan works again with this fix. Signed-off-by: Pierre Sauter Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index adfab3fc5478..17b8f3e37687 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -398,7 +398,6 @@ static const struct usb_device_id products[] = { /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ - {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ {QMI_GOBI1K_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ @@ -440,6 +439,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ From 912bfe76528c287bc4812521b8d53366954b39a5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 19 Aug 2012 14:05:59 -0300 Subject: [PATCH 514/665] ARM: clk-imx25: Fix SSI clock registration SSI block has two types of clock: ipg: bus clock, the clock needed for accessing registers. per: peripheral clock, the clock needed for generating the bit rate. Currently SSI driver only supports slave mode and only need to handle the ipg clock, because the peripheral clock comes from the master codec. Only register the ipg clock and do not register the peripheral clock for ssi. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer Cc: stable@vger.kernel.org --- arch/arm/mach-imx/clk-imx25.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index fdd8cc87c9fe..4431a62fff5b 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c @@ -222,10 +222,8 @@ int __init mx25_clocks_init(void) clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0"); clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0"); clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0"); - clk_register_clkdev(clk[ssi1_ipg_per], "per", "imx-ssi.0"); - clk_register_clkdev(clk[ssi1_ipg], "ipg", "imx-ssi.0"); - clk_register_clkdev(clk[ssi2_ipg_per], "per", "imx-ssi.1"); - clk_register_clkdev(clk[ssi2_ipg], "ipg", "imx-ssi.1"); + clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0"); + clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1"); clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0"); clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0"); clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0"); From 48540058612786d365602f3324ed97f9071092de Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 20 Aug 2012 09:39:22 -0300 Subject: [PATCH 515/665] ARM: clk-imx35: Fix SSI clock registration SSI block has two types of clock: ipg: bus clock, the clock needed for accessing registers. per: peripheral clock, the clock needed for generating the bit rate. Currently SSI driver only supports slave mode and only need to handle the ipg clock, because the peripheral clock comes from the master codec. Only register the ipg clock and do not register the peripheral clock for ssi. Signed-off-by: Fabio Estevam Tested-by: Mark Brown Signed-off-by: Sascha Hauer Cc: stable@vger.kernel.org --- arch/arm/mach-imx/clk-imx35.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index c6422fb10bae..65fb8bcd86cb 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -230,10 +230,8 @@ int __init mx35_clocks_init() clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1"); clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma"); - clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.0"); - clk_register_clkdev(clk[ssi1_div_post], "per", "imx-ssi.0"); - clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.1"); - clk_register_clkdev(clk[ssi2_div_post], "per", "imx-ssi.1"); + clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0"); + clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1"); /* i.mx35 has the i.mx21 type uart */ clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0"); From 75c5da279e06577190abba52cabf0dc2a56edb97 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 10 Sep 2012 21:58:29 +0200 Subject: [PATCH 516/665] drm/i915: fix up the IBX transcoder B check This has been added in commit de9a35abb3b343a25065449234e47a76c4f3454a Author: Daniel Vetter Date: Tue Jun 5 11:03:40 2012 +0200 drm/i915: assert that the IBX port transcoder select w/a is implemented Unfortunately I've failed to notice that these checks are not just called for the port that is about to be disabled, but for all (which makes sense for an assert ...), and the WARN missfired when disabling another pipe than the one with the dp port. Hence also check whether the port is actually disabled. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54688 Reviewed-by: Paulo Zanoni Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2dfa6cf4886b..bc2ad348e5d8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1376,7 +1376,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 + && (val & DP_PIPEB_SELECT), "IBX PCH dp port still using transcoder B\n"); } @@ -1388,7 +1389,8 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0 + && (val & SDVO_PIPE_B_SELECT), "IBX PCH hdmi port still using transcoder B\n"); } From ba9edaa468869a8cea242a411066b0f490751798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 11 Sep 2012 09:40:31 +0200 Subject: [PATCH 517/665] USB: option: replace ZTE K5006-Z entry with vendor class rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the ZTE K5006-Z entry so that it actually matches anything commit f1b5c997 USB: option: add ZTE K5006-Z added a device specific entry assuming that the device would use class/subclass/proto == ff/ff/ff like other ZTE devices. It turns out that ZTE has started using vendor specific subclass and protocol codes: T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=19d2 ProdID=1018 Rev= 0.00 S: Manufacturer=ZTE,Incorporated S: Product=ZTE LTE Technologies MSM S: SerialNumber=MF821Vxxxxxxx C:* #Ifs= 5 Cfg#= 1 Atr=c0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=86 Prot=10 Driver=(none) E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=02 Prot=05 Driver=(none) E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=02 Prot=01 Driver=(none) E: Ad=83(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=06 Prot=00 Driver=qmi_wwan E: Ad=85(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms We do not have any information on how ZTE intend to use these codes, but let us assume for now that the 3 sets matching serial functions in the K5006-Z always will identify a serial function in a ZTE device. Cc: Thomas Schäfer Cc: stable Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index cc40f47ecea1..5ce88d1bc6f1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ From 7b281ee026552f10862b617a2a51acf49c829554 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 11 Sep 2012 15:38:32 -0400 Subject: [PATCH 518/665] NFS: fsync() must exit with an error if page writeback failed We need to ensure that if the call to filemap_write_and_wait_range() fails, then we report that error back to the application. Signed-off-by: Trond Myklebust --- fs/nfs/file.c | 4 +++- fs/nfs/nfs4file.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 75d6d0a3d32e..6a7fcab7ecb3 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -287,10 +287,12 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) struct inode *inode = file->f_path.dentry->d_inode; ret = filemap_write_and_wait_range(inode->i_mapping, start, end); + if (ret != 0) + goto out; mutex_lock(&inode->i_mutex); ret = nfs_file_fsync_commit(file, start, end, datasync); mutex_unlock(&inode->i_mutex); - +out: return ret; } diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index acb65e7887f8..eb5eb8eef4d3 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -96,13 +96,15 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) struct inode *inode = file->f_path.dentry->d_inode; ret = filemap_write_and_wait_range(inode->i_mapping, start, end); + if (ret != 0) + goto out; mutex_lock(&inode->i_mutex); ret = nfs_file_fsync_commit(file, start, end, datasync); if (!ret && !datasync) /* application has asked for meta-data sync */ ret = pnfs_layoutcommit_inode(inode, true); mutex_unlock(&inode->i_mutex); - +out: return ret; } From 3217b0f5b6fd91440fd72cf24a8986b3f99d0d84 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:24:12 +0800 Subject: [PATCH 519/665] ASoC: wm8510: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8510.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 56a049555e2c..98f28a006faf 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -592,7 +592,8 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) struct wm8510_priv *wm8510; int ret; - wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); + wm8510 = devm_kzalloc(&spi->dev, sizeof(struct wm8510_priv), + GFP_KERNEL); if (wm8510 == NULL) return -ENOMEM; @@ -601,8 +602,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8510, &wm8510_dai, 1); - if (ret < 0) - kfree(wm8510); + return ret; } @@ -630,7 +630,8 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, struct wm8510_priv *wm8510; int ret; - wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); + wm8510 = devm_kzalloc(&i2c->dev, sizeof(struct wm8510_priv), + GFP_KERNEL); if (wm8510 == NULL) return -ENOMEM; @@ -639,8 +640,7 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8510, &wm8510_dai, 1); - if (ret < 0) - kfree(wm8510); + return ret; } From 398c02f6c213c5d0a791ebf9517b6e7029dc5cf0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:25:59 +0800 Subject: [PATCH 520/665] ASoC: wm8580: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 7c68226376e4..cc198df15e6e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -899,7 +899,8 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, struct wm8580_priv *wm8580; int ret; - wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); + wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv), + GFP_KERNEL); if (wm8580 == NULL) return -ENOMEM; @@ -908,15 +909,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); - if (ret < 0) - kfree(wm8580); + return ret; } static int wm8580_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } From e908ef40e4824a000889b0ab3f9eb9660bbe3f18 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:12 +0800 Subject: [PATCH 521/665] ASoC: wm8711: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8711.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 0b76d1dca5ea..1b1209a4c791 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -414,7 +414,8 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi) struct wm8711_priv *wm8711; int ret; - wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); + wm8711 = devm_kzalloc(&spi->dev, sizeof(struct wm8711_priv), + GFP_KERNEL); if (wm8711 == NULL) return -ENOMEM; @@ -423,15 +424,14 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); - if (ret < 0) - kfree(wm8711); + return ret; } static int __devexit wm8711_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); + return 0; } @@ -453,7 +453,8 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, struct wm8711_priv *wm8711; int ret; - wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); + wm8711 = devm_kzalloc(&client->dev, sizeof(struct wm8711_priv), + GFP_KERNEL); if (wm8711 == NULL) return -ENOMEM; @@ -462,15 +463,13 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); - if (ret < 0) - kfree(wm8711); + return ret; } static __devexit int wm8711_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } From 1a9585b0f7b3e21858f9a893d66a845f23d28ef1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:25 +0800 Subject: [PATCH 522/665] ASoC: wm8728: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8728.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 1467f97dce21..f274c250d492 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -280,7 +280,8 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) struct wm8728_priv *wm8728; int ret; - wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + wm8728 = devm_kzalloc(&spi->dev, sizeof(struct wm8728_priv), + GFP_KERNEL); if (wm8728 == NULL) return -ENOMEM; @@ -289,15 +290,14 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8728, &wm8728_dai, 1); - if (ret < 0) - kfree(wm8728); + return ret; } static int __devexit wm8728_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); + return 0; } @@ -319,7 +319,8 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, struct wm8728_priv *wm8728; int ret; - wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + wm8728 = devm_kzalloc(&i2c->dev, sizeof(struct wm8728_priv), + GFP_KERNEL); if (wm8728 == NULL) return -ENOMEM; @@ -328,15 +329,13 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8728, &wm8728_dai, 1); - if (ret < 0) - kfree(wm8728); + return ret; } static __devexit int wm8728_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } From 65fdd9bffa1367b75de0c331a105ce36de618794 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:38 +0800 Subject: [PATCH 523/665] ASoC: wm8737: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index d0520124616d..8c25442f9b47 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -647,7 +647,8 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, struct wm8737_priv *wm8737; int ret; - wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); + wm8737 = devm_kzalloc(&i2c->dev, sizeof(struct wm8737_priv), + GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; @@ -656,8 +657,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8737, &wm8737_dai, 1); - if (ret < 0) - kfree(wm8737); + return ret; } @@ -665,7 +665,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, static __devexit int wm8737_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); + return 0; } @@ -693,7 +693,8 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi) struct wm8737_priv *wm8737; int ret; - wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); + wm8737 = devm_kzalloc(&spi->dev, sizeof(struct wm8737_priv), + GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; @@ -702,15 +703,14 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8737, &wm8737_dai, 1); - if (ret < 0) - kfree(wm8737); + return ret; } static int __devexit wm8737_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); + return 0; } From 587cbbb36ef2657cd888b7705e02cfe96ab088b7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:53 +0800 Subject: [PATCH 524/665] ASoC: wm8990: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8990.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index db63c97ddf51..c28c83e5395d 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1388,7 +1388,8 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, struct wm8990_priv *wm8990; int ret; - wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); + wm8990 = devm_kzalloc(&i2c->dev, sizeof(struct wm8990_priv), + GFP_KERNEL); if (wm8990 == NULL) return -ENOMEM; @@ -1396,15 +1397,14 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8990, &wm8990_dai, 1); - if (ret < 0) - kfree(wm8990); + return ret; } static __devexit int wm8990_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); + return 0; } From 046d4f02e8835ff78f8ba5a09e358b2bc4832903 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:28:08 +0800 Subject: [PATCH 525/665] ASoC: wm8991: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index b9dbfebbda13..fe439f027e10 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1363,7 +1363,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, struct wm8991_priv *wm8991; int ret; - wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL); + wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); if (!wm8991) return -ENOMEM; @@ -1372,15 +1372,14 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8991, &wm8991_dai, 1); - if (ret < 0) - kfree(wm8991); + return ret; } static __devexit int wm8991_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); + return 0; } From bdfc87f7d1e253e0a61e2fc6a75ea9d76f7fc03a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 11 Sep 2012 13:11:12 +0000 Subject: [PATCH 526/665] net-sched: sch_cbq: avoid infinite loop Its possible to setup a bad cbq configuration leading to an infinite loop in cbq_classify() DEV_OUT=eth0 ICMP="match ip protocol 1 0xff" U32="protocol ip u32" DST="match ip dst" tc qdisc add dev $DEV_OUT root handle 1: cbq avpkt 1000 \ bandwidth 100mbit tc class add dev $DEV_OUT parent 1: classid 1:1 cbq \ rate 512kbit allot 1500 prio 5 bounded isolated tc filter add dev $DEV_OUT parent 1: prio 3 $U32 \ $ICMP $DST 192.168.3.234 flowid 1: Reported-by: Denys Fedoryschenko Tested-by: Denys Fedoryschenko Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_cbq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 6aabd77d1cfd..564b9fc8efd3 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL) cl = defmap[TC_PRIO_BESTEFFORT]; - if (cl == NULL || cl->level >= head->level) + if (cl == NULL) goto fallback; } - + if (cl->level >= head->level) + goto fallback; #ifdef CONFIG_NET_CLS_ACT switch (result) { case TC_ACT_QUEUED: From 73d7c119255615a26070f9d6cdb722a166a29015 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 19 Jun 2012 08:00:00 -0700 Subject: [PATCH 527/665] hwmon: (twl4030-madc-hwmon) Initialize uninitialized structure elements twl4030_madc_conversion uses do_avg and type structure elements of twl4030_madc_request. Initialize structure to avoid random operation. Fix for: Coverity CID 200794 Uninitialized scalar variable. Cc: Keerthy Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Acked-by: Keerthy --- drivers/hwmon/twl4030-madc-hwmon.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 0018c7dd0097..1a174f0a3cde 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct twl4030_madc_request req; + struct twl4030_madc_request req = { + .channels = 1 << attr->index, + .method = TWL4030_MADC_SW2, + .type = TWL4030_MADC_WAIT, + }; long val; - req.channels = (1 << attr->index); - req.method = TWL4030_MADC_SW2; - req.func_cb = NULL; val = twl4030_madc_conversion(&req); if (val < 0) return val; From e643049d301142cda473bc4d7f4eba4992fe657c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 11:43:44 +0800 Subject: [PATCH 528/665] ASoC: wm8510: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8510.c | 117 ++++++++++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 98f28a006faf..c12a54e72e89 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -33,24 +34,75 @@ * We can't read the WM8510 register space when we are * using 2 wire for device control, so we cache them instead. */ -static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0050, 0x0000, 0x0140, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00ff, - 0x0000, 0x0000, 0x0100, 0x00ff, - 0x0000, 0x0000, 0x012c, 0x002c, - 0x002c, 0x002c, 0x002c, 0x0000, - 0x0032, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0038, 0x000b, 0x0032, 0x0000, - 0x0008, 0x000c, 0x0093, 0x00e9, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0003, 0x0010, 0x0000, 0x0000, - 0x0000, 0x0002, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0039, 0x0000, - 0x0001, +static const struct reg_default wm8510_reg_defaults[] = { + { 1, 0x0000 }, + { 2, 0x0000 }, + { 3, 0x0000 }, + { 4, 0x0050 }, + { 5, 0x0000 }, + { 6, 0x0140 }, + { 7, 0x0000 }, + { 8, 0x0000 }, + { 9, 0x0000 }, + { 10, 0x0000 }, + { 11, 0x00ff }, + { 12, 0x0000 }, + { 13, 0x0000 }, + { 14, 0x0100 }, + { 15, 0x00ff }, + { 16, 0x0000 }, + { 17, 0x0000 }, + { 18, 0x012c }, + { 19, 0x002c }, + { 20, 0x002c }, + { 21, 0x002c }, + { 22, 0x002c }, + { 23, 0x0000 }, + { 24, 0x0032 }, + { 25, 0x0000 }, + { 26, 0x0000 }, + { 27, 0x0000 }, + { 28, 0x0000 }, + { 29, 0x0000 }, + { 30, 0x0000 }, + { 31, 0x0000 }, + { 32, 0x0038 }, + { 33, 0x000b }, + { 34, 0x0032 }, + { 35, 0x0000 }, + { 36, 0x0008 }, + { 37, 0x000c }, + { 38, 0x0093 }, + { 39, 0x00e9 }, + { 40, 0x0000 }, + { 41, 0x0000 }, + { 42, 0x0000 }, + { 43, 0x0000 }, + { 44, 0x0003 }, + { 45, 0x0010 }, + { 46, 0x0000 }, + { 47, 0x0000 }, + { 48, 0x0000 }, + { 49, 0x0002 }, + { 50, 0x0001 }, + { 51, 0x0000 }, + { 52, 0x0000 }, + { 53, 0x0000 }, + { 54, 0x0039 }, + { 55, 0x0000 }, + { 56, 0x0001 }, }; +static bool wm8510_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8510_RESET: + return true; + default: + return false; + } +} + #define WM8510_POWER1_BIASEN 0x08 #define WM8510_POWER1_BUFIOEN 0x10 @@ -58,7 +110,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { /* codec private data */ struct wm8510_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; }; static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; @@ -454,6 +506,7 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) static int wm8510_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; switch (level) { @@ -467,7 +520,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); + regcache_sync(wm8510->regmap); /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); @@ -536,10 +589,9 @@ static int wm8510_resume(struct snd_soc_codec *codec) static int wm8510_probe(struct snd_soc_codec *codec) { - struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); return ret; @@ -569,9 +621,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { .suspend = wm8510_suspend, .resume = wm8510_resume, .set_bias_level = wm8510_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8510_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default =wm8510_reg, .controls = wm8510_snd_controls, .num_controls = ARRAY_SIZE(wm8510_snd_controls), @@ -586,6 +635,18 @@ static const struct of_device_id wm8510_of_match[] = { { }, }; +static const struct regmap_config wm8510_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8510_MONOMIX, + + .reg_defaults = wm8510_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8510_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8510_volatile, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8510_spi_probe(struct spi_device *spi) { @@ -597,7 +658,10 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) if (wm8510 == NULL) return -ENOMEM; - wm8510->control_type = SND_SOC_SPI; + wm8510->regmap = devm_regmap_init_spi(spi, &wm8510_regmap); + if (IS_ERR(wm8510->regmap)) + return PTR_ERR(wm8510->regmap); + spi_set_drvdata(spi, wm8510); ret = snd_soc_register_codec(&spi->dev, @@ -635,8 +699,11 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, if (wm8510 == NULL) return -ENOMEM; + wm8510->regmap = devm_regmap_init_i2c(i2c, &wm8510_regmap); + if (IS_ERR(wm8510->regmap)) + return PTR_ERR(wm8510->regmap); + i2c_set_clientdata(i2c, wm8510); - wm8510->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8510, &wm8510_dai, 1); From b689d9f9961befd9b322783f512195785fe82daa Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 11:59:51 +0800 Subject: [PATCH 529/665] ASoC: wm8580: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 116 +++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index cc198df15e6e..02c75bec7d71 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -1,7 +1,7 @@ /* * wm8580.c -- WM8580 ALSA Soc Audio driver * - * Copyright 2008-11 Wolfson Microelectronics PLC. + * Copyright 2008-12 Wolfson Microelectronics PLC. * * 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 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -157,23 +158,72 @@ * We can't read the WM8580 register space when we * are using 2 wire for device control, so we cache them instead. */ -static const u16 wm8580_reg[] = { - 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ - 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ - 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ - 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ - 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ - 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ - 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/ - 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/ - 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/ - 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/ - 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/ - 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/ - 0x0000, 0x0000 /*R53*/ +static const struct reg_default wm8580_reg_defaults[] = { + { 0, 0x0121 }, + { 1, 0x017e }, + { 2, 0x007d }, + { 3, 0x0014 }, + { 4, 0x0121 }, + { 5, 0x017e }, + { 6, 0x007d }, + { 7, 0x0194 }, + { 8, 0x0010 }, + { 9, 0x0002 }, + { 10, 0x0002 }, + { 11, 0x00c2 }, + { 12, 0x0182 }, + { 13, 0x0082 }, + { 14, 0x000a }, + { 15, 0x0024 }, + { 16, 0x0009 }, + { 17, 0x0000 }, + { 18, 0x00ff }, + { 19, 0x0000 }, + { 20, 0x00ff }, + { 21, 0x00ff }, + { 22, 0x00ff }, + { 23, 0x00ff }, + { 24, 0x00ff }, + { 25, 0x00ff }, + { 26, 0x00ff }, + { 27, 0x00ff }, + { 28, 0x01f0 }, + { 29, 0x0040 }, + { 30, 0x0000 }, + { 31, 0x0000 }, + { 32, 0x0000 }, + { 33, 0x0000 }, + { 34, 0x0031 }, + { 35, 0x000b }, + { 36, 0x0039 }, + { 37, 0x0000 }, + { 38, 0x0010 }, + { 39, 0x0032 }, + { 40, 0x0054 }, + { 41, 0x0076 }, + { 42, 0x0098 }, + { 43, 0x0000 }, + { 44, 0x0000 }, + { 45, 0x0000 }, + { 46, 0x0000 }, + { 47, 0x0000 }, + { 48, 0x0000 }, + { 49, 0x0000 }, + { 50, 0x005e }, + { 51, 0x003e }, + { 52, 0x0000 }, }; +static bool wm8580_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8580_RESET: + return true; + default: + return false; + } +} + struct pll_state { unsigned int in; unsigned int out; @@ -188,7 +238,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { /* codec private data */ struct wm8580_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; struct pll_state a; struct pll_state b; @@ -203,14 +253,16 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; + struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; int ret; - /* Clear the register cache so we write without VU set */ - reg_cache[reg] = 0; - reg_cache[reg2] = 0; + /* Clear the register cache VU so we write without VU set */ + regcache_cache_only(wm8580->regmap, true); + regmap_update_bits(wm8580->regmap, reg, 0x100, 0x000); + regmap_update_bits(wm8580->regmap, reg2, 0x100, 0x000); + regcache_cache_only(wm8580->regmap, false); ret = snd_soc_put_volsw(kcontrol, ucontrol); if (ret < 0) @@ -817,7 +869,7 @@ static int wm8580_probe(struct snd_soc_codec *codec) struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); int ret = 0,i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -875,9 +927,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { .probe = wm8580_probe, .remove = wm8580_remove, .set_bias_level = wm8580_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8580_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8580_reg, .controls = wm8580_snd_controls, .num_controls = ARRAY_SIZE(wm8580_snd_controls), @@ -892,6 +941,18 @@ static const struct of_device_id wm8580_of_match[] = { { }, }; +static const struct regmap_config wm8580_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8580_MAX_REGISTER, + + .reg_defaults = wm8580_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8580_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8580_volatile, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -904,8 +965,11 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, if (wm8580 == NULL) return -ENOMEM; + wm8580->regmap = devm_regmap_init_i2c(i2c, &wm8580_regmap); + if (IS_ERR(wm8580->regmap)) + return PTR_ERR(wm8580->regmap); + i2c_set_clientdata(i2c, wm8580); - wm8580->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); From 18273b05def692d1883745d22e72fa275bc92c17 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:03:51 +0800 Subject: [PATCH 530/665] ASoC: wm8580: Move regulator acquisition to I2C probe Better style as we get all the resources we need prior to starting the ASoC level probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 02c75bec7d71..5e9c40fa7eb2 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -867,7 +867,7 @@ static struct snd_soc_dai_driver wm8580_dai[] = { static int wm8580_probe(struct snd_soc_codec *codec) { struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); - int ret = 0,i; + int ret = 0; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { @@ -875,16 +875,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) return ret; } - for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) - wm8580->supplies[i].supply = wm8580_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); if (ret != 0) { @@ -906,7 +896,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) err_regulator_enable: regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); err_regulator_get: - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); return ret; } @@ -918,7 +907,6 @@ static int wm8580_remove(struct snd_soc_codec *codec) wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); return 0; } @@ -958,7 +946,7 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8580_priv *wm8580; - int ret; + int ret, i; wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv), GFP_KERNEL); @@ -969,6 +957,16 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, if (IS_ERR(wm8580->regmap)) return PTR_ERR(wm8580->regmap); + for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) + wm8580->supplies[i].supply = wm8580_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8580->supplies), + wm8580->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8580); ret = snd_soc_register_codec(&i2c->dev, From 5aa5fa9fdbda20eee3351dd2492cd5c0d6fa7d1d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:15:20 +0800 Subject: [PATCH 531/665] ASoC: wm8711: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8711.c | 50 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 1b1209a4c791..8b8bb70f1eb9 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ /* codec private data */ struct wm8711_priv { - enum snd_soc_control_type bus_type; + struct regmap *regmap; unsigned int sysclk; }; @@ -42,11 +43,21 @@ struct wm8711_priv { * using 2 wire for device control, so we cache them instead. * There is no point in caching the reset register */ -static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { - 0x0079, 0x0079, 0x000a, 0x0008, - 0x009f, 0x000a, 0x0000, 0x0000 +static const struct reg_default wm8711_reg_defaults[] = { + { 0, 0x0079 }, { 1, 0x0079 }, { 2, 0x000a }, { 3, 0x0008 }, + { 4, 0x009f }, { 5, 0x000a }, { 6, 0x0000 }, { 7, 0x0000 }, }; +static bool wm8711_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8711_RESET: + return true; + default: + return false; + } +} + #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); @@ -289,6 +300,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, static int wm8711_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; switch (level) { @@ -299,7 +311,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - snd_soc_cache_sync(codec); + regcache_sync(wm8711->regmap); snd_soc_write(codec, WM8711_PWR, reg | 0x0040); break; @@ -353,10 +365,9 @@ static int wm8711_resume(struct snd_soc_codec *codec) static int wm8711_probe(struct snd_soc_codec *codec) { - struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -391,9 +402,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { .suspend = wm8711_suspend, .resume = wm8711_resume, .set_bias_level = wm8711_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8711_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8711_reg, .controls = wm8711_snd_controls, .num_controls = ARRAY_SIZE(wm8711_snd_controls), .dapm_widgets = wm8711_dapm_widgets, @@ -408,6 +416,18 @@ static const struct of_device_id wm8711_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8711_of_match); +static const struct regmap_config wm8711_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8711_RESET, + + .reg_defaults = wm8711_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8711_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8711_volatile, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8711_spi_probe(struct spi_device *spi) { @@ -419,8 +439,11 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi) if (wm8711 == NULL) return -ENOMEM; + wm8711->regmap = devm_regmap_init_spi(spi, &wm8711_regmap); + if (IS_ERR(wm8711->regmap)) + return PTR_ERR(wm8711->regmap); + spi_set_drvdata(spi, wm8711); - wm8711->bus_type = SND_SOC_SPI; ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); @@ -458,8 +481,11 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, if (wm8711 == NULL) return -ENOMEM; + wm8711->regmap = devm_regmap_init_i2c(client, &wm8711_regmap); + if (IS_ERR(wm8711->regmap)) + return PTR_ERR(wm8711->regmap); + i2c_set_clientdata(client, wm8711); - wm8711->bus_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); From d16383ef2a62fe53a929eac56b662d6def6bb8c7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:30:01 +0800 Subject: [PATCH 532/665] ASoC: wm8728: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8728.c | 45 ++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index f274c250d492..00a12a0c3919 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -35,16 +36,16 @@ * the volume update bits, mute the output and enable infinite zero * detect. */ -static const u16 wm8728_reg_defaults[] = { - 0x1ff, - 0x1ff, - 0x001, - 0x100, +static const struct reg_default wm8728_reg_defaults[] = { + { 0, 0x1ff }, + { 1, 0x1ff }, + { 2, 0x001 }, + { 3, 0x100 }, }; /* codec private data */ struct wm8728_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; }; static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); @@ -162,8 +163,8 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, static int wm8728_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); u16 reg; - int i; switch (level) { case SND_SOC_BIAS_ON: @@ -175,9 +176,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); /* ..then sync in the register cache. */ - for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) - snd_soc_write(codec, i, - snd_soc_read(codec, i)); + regcache_sync(wm8728->regmap); } break; @@ -229,10 +228,9 @@ static int wm8728_resume(struct snd_soc_codec *codec) static int wm8728_probe(struct snd_soc_codec *codec) { - struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", ret); @@ -257,9 +255,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { .suspend = wm8728_suspend, .resume = wm8728_resume, .set_bias_level = wm8728_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8728_reg_defaults, .controls = wm8728_snd_controls, .num_controls = ARRAY_SIZE(wm8728_snd_controls), .dapm_widgets = wm8728_dapm_widgets, @@ -274,6 +269,16 @@ static const struct of_device_id wm8728_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8728_of_match); +static const struct regmap_config wm8728_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8728_IFCTL, + + .reg_defaults = wm8728_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8728_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8728_spi_probe(struct spi_device *spi) { @@ -285,7 +290,10 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) if (wm8728 == NULL) return -ENOMEM; - wm8728->control_type = SND_SOC_SPI; + wm8728->regmap = devm_regmap_init_spi(spi, &wm8728_regmap); + if (IS_ERR(wm8728->regmap)) + return PTR_ERR(wm8728->regmap); + spi_set_drvdata(spi, wm8728); ret = snd_soc_register_codec(&spi->dev, @@ -324,8 +332,11 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, if (wm8728 == NULL) return -ENOMEM; + wm8728->regmap = devm_regmap_init_i2c(i2c, &wm8728_regmap); + if (IS_ERR(wm8728->regmap)) + return PTR_ERR(wm8728->regmap); + i2c_set_clientdata(i2c, wm8728); - wm8728->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8728, &wm8728_dai, 1); From 4f69bb31b8840713f82c6c476bae3f2356819ce2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:36:28 +0800 Subject: [PATCH 533/665] ASoC: wm8737: Move regulator acquisition to device registration This is better style as we acquire resources we will need before we go into the ASoC card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 41 ++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 8c25442f9b47..3bf5bc73e2de 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -557,7 +557,7 @@ static int wm8737_resume(struct snd_soc_codec *codec) static int wm8737_probe(struct snd_soc_codec *codec) { struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - int ret, i; + int ret; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type); if (ret != 0) { @@ -565,16 +565,6 @@ static int wm8737_probe(struct snd_soc_codec *codec) return ret; } - for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) - wm8737->supplies[i].supply = wm8737_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8737->supplies), - wm8737->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); if (ret != 0) { @@ -607,17 +597,12 @@ static int wm8737_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); err_get: - regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); - return ret; } static int wm8737_remove(struct snd_soc_codec *codec) { - struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); return 0; } @@ -645,13 +630,23 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8737_priv *wm8737; - int ret; + int ret, i; wm8737 = devm_kzalloc(&i2c->dev, sizeof(struct wm8737_priv), GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) + wm8737->supplies[i].supply = wm8737_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8737->supplies), + wm8737->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8737); wm8737->control_type = SND_SOC_I2C; @@ -691,13 +686,23 @@ static struct i2c_driver wm8737_i2c_driver = { static int __devinit wm8737_spi_probe(struct spi_device *spi) { struct wm8737_priv *wm8737; - int ret; + int ret, i; wm8737 = devm_kzalloc(&spi->dev, sizeof(struct wm8737_priv), GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) + wm8737->supplies[i].supply = wm8737_supply_names[i]; + + ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8737->supplies), + wm8737->supplies); + if (ret != 0) { + dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + wm8737->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8737); From 3ef8ac0d7bd0532fbfb319f3fbf615538394119f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:48:48 +0800 Subject: [PATCH 534/665] ASoC: wm8737: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 75 ++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 3bf5bc73e2de..5c9634f4c1f0 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -40,29 +41,39 @@ static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = { /* codec private data */ struct wm8737_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES]; unsigned int mclk; }; -static const u16 wm8737_reg[WM8737_REGISTER_COUNT] = { - 0x00C3, /* R0 - Left PGA volume */ - 0x00C3, /* R1 - Right PGA volume */ - 0x0007, /* R2 - AUDIO path L */ - 0x0007, /* R3 - AUDIO path R */ - 0x0000, /* R4 - 3D Enhance */ - 0x0000, /* R5 - ADC Control */ - 0x0000, /* R6 - Power Management */ - 0x000A, /* R7 - Audio Format */ - 0x0000, /* R8 - Clocking */ - 0x000F, /* R9 - MIC Preamp Control */ - 0x0003, /* R10 - Misc Bias Control */ - 0x0000, /* R11 - Noise Gate */ - 0x007C, /* R12 - ALC1 */ - 0x0000, /* R13 - ALC2 */ - 0x0032, /* R14 - ALC3 */ +static const struct reg_default wm8737_reg_defaults[] = { + { 0, 0x00C3 }, /* R0 - Left PGA volume */ + { 1, 0x00C3 }, /* R1 - Right PGA volume */ + { 2, 0x0007 }, /* R2 - AUDIO path L */ + { 3, 0x0007 }, /* R3 - AUDIO path R */ + { 4, 0x0000 }, /* R4 - 3D Enhance */ + { 5, 0x0000 }, /* R5 - ADC Control */ + { 6, 0x0000 }, /* R6 - Power Management */ + { 7, 0x000A }, /* R7 - Audio Format */ + { 8, 0x0000 }, /* R8 - Clocking */ + { 9, 0x000F }, /* R9 - MIC Preamp Control */ + { 10, 0x0003 }, /* R10 - Misc Bias Control */ + { 11, 0x0000 }, /* R11 - Noise Gate */ + { 12, 0x007C }, /* R12 - ALC1 */ + { 13, 0x0000 }, /* R13 - ALC2 */ + { 14, 0x0032 }, /* R14 - ALC3 */ }; +static bool wm8737_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8737_RESET: + return true; + default: + return false; + } +} + static int wm8737_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, WM8737_RESET, 0); @@ -479,7 +490,7 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, return ret; } - snd_soc_cache_sync(codec); + regcache_sync(wm8737->regmap); /* Fast VMID ramp at 2*2.5k */ snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, @@ -559,7 +570,7 @@ static int wm8737_probe(struct snd_soc_codec *codec) struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -612,10 +623,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { .suspend = wm8737_suspend, .resume = wm8737_resume, .set_bias_level = wm8737_set_bias_level, - - .reg_cache_size = WM8737_REGISTER_COUNT - 1, /* Skip reset */ - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8737_reg, }; static const struct of_device_id wm8737_of_match[] = { @@ -625,6 +632,18 @@ static const struct of_device_id wm8737_of_match[] = { MODULE_DEVICE_TABLE(of, wm8737_of_match); +static const struct regmap_config wm8737_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8737_MAX_REGISTER, + + .reg_defaults = wm8737_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8737_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8737_volatile, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -647,8 +666,11 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, return ret; } + wm8737->regmap = devm_regmap_init_i2c(i2c, &wm8737_regmap); + if (IS_ERR(wm8737->regmap)) + return PTR_ERR(wm8737->regmap); + i2c_set_clientdata(i2c, wm8737); - wm8737->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8737, &wm8737_dai, 1); @@ -703,7 +725,10 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi) return ret; } - wm8737->control_type = SND_SOC_SPI; + wm8737->regmap = devm_regmap_init_spi(spi, &wm8737_regmap); + if (IS_ERR(wm8737->regmap)) + return PTR_ERR(wm8737->regmap); + spi_set_drvdata(spi, wm8737); ret = snd_soc_register_codec(&spi->dev, From 080b98e9ab30734bda2f1b8b33cd55a4c4ef406a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 11 Sep 2012 08:22:14 -0700 Subject: [PATCH 535/665] hwmon: (ina2xx) Fix word size register read and write operations The driver uses be16_to_cpu and cpu_to_be16 to convert data in SMBus word operations from chip to host byte order. However, the data passed from and to the SMBus word API functions is in host byte order, not in chip byte order. Conversion should therefore use swab16 instead of be16 to change the byte order. Replace driver internal word conversion functions with SMBus API functions to solve the problem. Signed-off-by: Guenter Roeck Cc: stable@vger.kernel.org # 3.5+ Acked-by: Jean Delvare --- drivers/hwmon/ina2xx.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index 7f3f4a385729..602148299f68 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -69,22 +69,6 @@ struct ina2xx_data { u16 regs[INA2XX_MAX_REGISTERS]; }; -int ina2xx_read_word(struct i2c_client *client, int reg) -{ - int val = i2c_smbus_read_word_data(client, reg); - if (unlikely(val < 0)) { - dev_dbg(&client->dev, - "Failed to read register: %d\n", reg); - return val; - } - return be16_to_cpu(val); -} - -void ina2xx_write_word(struct i2c_client *client, int reg, int data) -{ - i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); -} - static struct ina2xx_data *ina2xx_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -102,7 +86,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev) /* Read all registers */ for (i = 0; i < data->registers; i++) { - int rv = ina2xx_read_word(client, i); + int rv = i2c_smbus_read_word_swapped(client, i); if (rv < 0) { ret = ERR_PTR(rv); goto abort; @@ -279,22 +263,26 @@ static int ina2xx_probe(struct i2c_client *client, switch (data->kind) { case ina219: /* device configuration */ - ina2xx_write_word(client, INA2XX_CONFIG, INA219_CONFIG_DEFAULT); + i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, + INA219_CONFIG_DEFAULT); /* set current LSB to 1mA, shunt is in uOhms */ /* (equation 13 in datasheet) */ - ina2xx_write_word(client, INA2XX_CALIBRATION, 40960000 / shunt); + i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, + 40960000 / shunt); dev_info(&client->dev, "power monitor INA219 (Rshunt = %li uOhm)\n", shunt); data->registers = INA219_REGISTERS; break; case ina226: /* device configuration */ - ina2xx_write_word(client, INA2XX_CONFIG, INA226_CONFIG_DEFAULT); + i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, + INA226_CONFIG_DEFAULT); /* set current LSB to 1mA, shunt is in uOhms */ /* (equation 1 in datasheet)*/ - ina2xx_write_word(client, INA2XX_CALIBRATION, 5120000 / shunt); + i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, + 5120000 / shunt); dev_info(&client->dev, "power monitor INA226 (Rshunt = %li uOhm)\n", shunt); data->registers = INA226_REGISTERS; From 6b315958d330d3ebf46b7d45e0978a97be2c4ac0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 18:44:40 +0800 Subject: [PATCH 536/665] ASoC: arizona: Clarify logging for FLL lock status interrupt Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5e96a0a1669c..b79578e7e10c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -732,7 +732,7 @@ static irqreturn_t arizona_fll_lock(int irq, void *data) { struct arizona_fll *fll = data; - arizona_fll_dbg(fll, "Locked\n"); + arizona_fll_dbg(fll, "Lock status changed\n"); complete(&fll->lock); From 3737e2be505d872bf2b3c1cd4151b2d2b413d7b5 Mon Sep 17 00:00:00 2001 From: Matteo Frigo Date: Wed, 12 Sep 2012 10:12:06 -0400 Subject: [PATCH 537/665] ALSA: ice1724: Use linear scale for AK4396 volume control. The AK4396 DAC has a linear-scale attentuator, but sound/pci/ice1712/prodigy_hifi.c used a log scale instead, which is not quite right. This patch restores the correct scale, borrowing from the ak4396 code in sound/pci/oxygen/oxygen.c. Signed-off-by: Matteo Frigo Cc: Signed-off-by: Takashi Iwai --- sound/pci/ice1712/prodigy_hifi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 764cc93dbca4..075d5aa1fee0 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -297,6 +297,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem } static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); +static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { { @@ -307,7 +308,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { .info = ak4396_dac_vol_info, .get = ak4396_dac_vol_get, .put = ak4396_dac_vol_put, - .tlv = { .p = db_scale_wm_dac }, + .tlv = { .p = ak4396_db_scale }, }, }; From 16af511a666827eaf5802144f09e2fb7b0942c99 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 12 Sep 2012 02:04:53 +0000 Subject: [PATCH 538/665] netfilter: log: Fix log-level processing auto75914331@hushmail.com reports that iptables does not correctly output the KERN_. $IPTABLES -A RULE_0_in -j LOG --log-level notice --log-prefix "DENY in: " result with linux 3.6-rc5 Sep 12 06:37:29 xxxxx kernel: <5>DENY in: IN=eth0 OUT= MAC=....... result with linux 3.5.3 and older: Sep 9 10:43:01 xxxxx kernel: DENY in: IN=eth0 OUT= MAC...... commit 04d2c8c83d0 ("printk: convert the format for KERN_ to a 2 byte pattern") updated the syslog header style but did not update netfilter uses. Do so. Use KERN_SOH and string concatenation instead of "%c" KERN_SOH_ASCII as suggested by Eric Dumazet. Signed-off-by: Joe Perches cc: auto75914331@hushmail.com Signed-off-by: Pablo Neira Ayuso --- net/bridge/netfilter/ebt_log.c | 2 +- net/netfilter/xt_LOG.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index f88ee537fb2b..92de5e5f9db2 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -80,7 +80,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, unsigned int bitmask; spin_lock_bh(&ebt_log_lock); - printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", + printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", '0' + loginfo->u.log.level, prefix, in ? in->name : "", out ? out->name : "", eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index 2a4f9693e799..91e9af4d1f42 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c @@ -443,8 +443,8 @@ log_packet_common(struct sbuff *m, const struct nf_loginfo *loginfo, const char *prefix) { - sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, - prefix, + sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ", + '0' + loginfo->u.log.level, prefix, in ? in->name : "", out ? out->name : ""); #ifdef CONFIG_BRIDGE_NETFILTER From b3aafe80c83097403d2b5edccfc440fac3d5f028 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Aug 2012 09:42:31 +0200 Subject: [PATCH 539/665] i2c: pnx: Fix bit definitions The I2C Control Register bits RFDAIE and RFFIE were mixed up. In addition to this fix, this patch adds the missing bit DRSIE for completeness. Signed-off-by: Roland Stigge Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d54416770b0..b36e21f9fd53 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -48,8 +48,9 @@ enum { mcntrl_afie = 0x00000002, mcntrl_naie = 0x00000004, mcntrl_drmie = 0x00000008, - mcntrl_daie = 0x00000020, - mcntrl_rffie = 0x00000040, + mcntrl_drsie = 0x00000010, + mcntrl_rffie = 0x00000020, + mcntrl_daie = 0x00000040, mcntrl_tffie = 0x00000080, mcntrl_reset = 0x00000100, mcntrl_cdbmode = 0x00000400, From c076ada4e4aaf45e1a31ad6de7c6cce36081e045 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Aug 2012 09:42:32 +0200 Subject: [PATCH 540/665] i2c: pnx: Fix read transactions of >= 2 bytes On transactions with n>=2 bytes, the controller actually wrongly clocks in n+1 bytes. This is caused by the (wrong) assumption that RFE in the Status Register is 1 iff there is no byte already ordered (via a dummy TX byte). This lead to the implementation of synchronized byte ordering, e.g.: Dummy-TX - RX - Dummy-TX - RX - ... But since RFE actually stays high after some Dummy-TX, it rather looks like: Dummy-TX - Dummy-TX - RX - Dummy-TX - RX - (RX) The last RX byte is clocked in by the bus controller, but ignored by the kernel when filling the userspace buffer. This patch fixes the issue by asking for RX via Dummy-TX asynchronously. Introducing a separate counter for TX bytes. Signed-off-by: Roland Stigge Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 48 +++++++++++++++++++++--------------- include/linux/i2c-pnx.h | 1 + 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index b36e21f9fd53..8488bddfe465 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -291,31 +291,37 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) * or we didn't 'ask' for it yet. */ if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { - dev_dbg(&alg_data->adapter.dev, - "%s(): Write dummy data to fill Rx-fifo...\n", - __func__); + /* 'Asking' is done asynchronously, e.g. dummy TX of several + * bytes is done before the first actual RX arrives in FIFO. + * Therefore, ordered bytes (via TX) are counted separately. + */ + if (alg_data->mif.order) { + dev_dbg(&alg_data->adapter.dev, + "%s(): Write dummy data to fill Rx-fifo...\n", + __func__); - if (alg_data->mif.len == 1) { - /* Last byte, do not acknowledge next rcv. */ - val |= stop_bit; + if (alg_data->mif.order == 1) { + /* Last byte, do not acknowledge next rcv. */ + val |= stop_bit; + + /* + * Enable interrupt RFDAIE (data in Rx fifo), + * and disable DRMIE (need data for Tx) + */ + ctl = ioread32(I2C_REG_CTL(alg_data)); + ctl |= mcntrl_rffie | mcntrl_daie; + ctl &= ~mcntrl_drmie; + iowrite32(ctl, I2C_REG_CTL(alg_data)); + } /* - * Enable interrupt RFDAIE (data in Rx fifo), - * and disable DRMIE (need data for Tx) + * Now we'll 'ask' for data: + * For each byte we want to receive, we must + * write a (dummy) byte to the Tx-FIFO. */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl |= mcntrl_rffie | mcntrl_daie; - ctl &= ~mcntrl_drmie; - iowrite32(ctl, I2C_REG_CTL(alg_data)); + iowrite32(val, I2C_REG_TX(alg_data)); + alg_data->mif.order--; } - - /* - * Now we'll 'ask' for data: - * For each byte we want to receive, we must - * write a (dummy) byte to the Tx-FIFO. - */ - iowrite32(val, I2C_REG_TX(alg_data)); - return 0; } @@ -515,6 +521,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) alg_data->mif.buf = pmsg->buf; alg_data->mif.len = pmsg->len; + alg_data->mif.order = pmsg->len; alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ? I2C_SMBUS_READ : I2C_SMBUS_WRITE; alg_data->mif.ret = 0; @@ -567,6 +574,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) /* Cleanup to be sure... */ alg_data->mif.buf = NULL; alg_data->mif.len = 0; + alg_data->mif.order = 0; dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n", __func__, ioread32(I2C_REG_STS(alg_data))); diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h index 1bc74afe7a35..49ed17fdf055 100644 --- a/include/linux/i2c-pnx.h +++ b/include/linux/i2c-pnx.h @@ -22,6 +22,7 @@ struct i2c_pnx_mif { struct timer_list timer; /* Timeout */ u8 * buf; /* Data buffer */ int len; /* Length of data buffer */ + int order; /* RX Bytes to order via TX */ }; struct i2c_pnx_algo_data { From 72ee734a6716aac5aaf336da70a811e308d2a84e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 8 Sep 2012 17:28:06 +0200 Subject: [PATCH 541/665] i2c: mxs: correctly setup speed for non devicetree Commit cd4f2d4 (i2c: mxs: Set I2C timing registers for mxs-i2c) only covered the case for devicetree and made platform_data based boards bail out with -EINVAL. Correctly support the latter one, too. Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mxs.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 088c5c1ed17d..51f05b8520ed 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -365,10 +365,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) struct device_node *node = dev->of_node; int ret; - if (!node) - return -EINVAL; - - i2c->speed = &mxs_i2c_95kHz_config; ret = of_property_read_u32(node, "clock-frequency", &speed); if (ret) dev_warn(dev, "No I2C speed selected, using 100kHz\n"); @@ -419,10 +415,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) return err; i2c->dev = dev; + i2c->speed = &mxs_i2c_95kHz_config; - err = mxs_i2c_get_ofdata(i2c); - if (err) - return err; + if (dev->of_node) { + err = mxs_i2c_get_ofdata(i2c); + if (err) + return err; + } platform_set_drvdata(pdev, i2c); From 7f67c38bdcb6d8bce02e10521fbf1618b586319f Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 12 Sep 2012 14:58:00 +0300 Subject: [PATCH 542/665] usb: chipidea: udc: fix setup of endpoint maxpacket size This patch changes the setup of the endpoint maxpacket size. All non control endpoints are initialized with an undefined ((unsigned short)~0) maxpacket size. The maxpacket size of Endpoint 0 will be kept at CTRL_PAYLOAD_MAX. Some gadget drivers check for the maxpacket size before they enable the endpoint, which leads to a wrong state in these drivers. Cc: stable Signed-off-by: Michael Grzeschik Acked-by: Felipe Balbi Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index c7a032a4f0c5..7801a3f8be90 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1455,7 +1455,12 @@ static int init_eps(struct ci13xxx *ci) mEp->ep.name = mEp->name; mEp->ep.ops = &usb_ep_ops; - mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; + /* + * for ep0: maxP defined in desc, for other + * eps, maxP is set by epautoconfig() called + * by gadget layer + */ + mEp->ep.maxpacket = (unsigned short)~0; INIT_LIST_HEAD(&mEp->qh.queue); mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, @@ -1475,6 +1480,7 @@ static int init_eps(struct ci13xxx *ci) else ci->ep0in = mEp; + mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; continue; } From c0a48e6c75f2ac190d812bea5fc339696e434c2e Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 12 Sep 2012 14:58:01 +0300 Subject: [PATCH 543/665] usb: chipidea: udc: add pullup fuction, needed by the uvc gadget Add function to physicaly enable or disable of pullup connection on the USB-D+ line. The uvc gaget will fail, if this function is not implemented. Cc: stable Signed-off-by: Michael Grzeschik Acked-by: Felipe Balbi Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 7801a3f8be90..32ee8701e199 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n) } /** - * hw_device_state: enables/disables interrupts & starts/stops device (execute - * without interruption) + * hw_device_state: enables/disables interrupts (execute without interruption) * @dma: 0 => disable, !0 => enable and set dma engine * * This function returns an error code @@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma) /* interrupt, error, port change, reset, sleep/suspend */ hw_write(ci, OP_USBINTR, ~0, USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); - hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); } else { - hw_write(ci, OP_USBCMD, USBCMD_RS, 0); hw_write(ci, OP_USBINTR, ~0, 0); } return 0; @@ -1420,6 +1417,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) return -ENOTSUPP; } +/* Change Data+ pullup status + * this func is used by usb_gadget_connect/disconnet + */ +static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) +{ + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); + + if (is_on) + hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); + else + hw_write(ci, OP_USBCMD, USBCMD_RS, 0); + + return 0; +} + static int ci13xxx_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); static int ci13xxx_stop(struct usb_gadget *gadget, @@ -1432,6 +1444,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget, static const struct usb_gadget_ops usb_gadget_ops = { .vbus_session = ci13xxx_vbus_session, .wakeup = ci13xxx_wakeup, + .pullup = ci13xxx_pullup, .vbus_draw = ci13xxx_vbus_draw, .udc_start = ci13xxx_start, .udc_stop = ci13xxx_stop, From c9d1f947a85e38b6dded469470c95ed62430cb3f Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 12 Sep 2012 14:58:02 +0300 Subject: [PATCH 544/665] usb: chipidea: udc: fix error path in udc_start() This patch fixes the error path of udc_start(). Now NULL is used to unset the peripheral with otg_set_peripheral(). Cc: stable Reviewed-by: Richard Zhao Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 32ee8701e199..3a755e5160cf 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1748,7 +1748,7 @@ static int udc_start(struct ci13xxx *ci) remove_trans: if (!IS_ERR_OR_NULL(ci->transceiver)) { - otg_set_peripheral(ci->transceiver->otg, &ci->gadget); + otg_set_peripheral(ci->transceiver->otg, NULL); if (ci->global_phy) usb_put_phy(ci->transceiver); } From ad6b1b97fe8504957d017cd6e4168cac8903d3f3 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 12 Sep 2012 14:58:03 +0300 Subject: [PATCH 545/665] usb: chipidea: cleanup dma_pool if udc_start() fails If udc_start() fails the qh_pool dma-pool cannot be closed because it's still in use. This patch factors out the dma_pool_free() loop into destroy_eps() and calls it in the error path of udc_start(), too. Cc: stable Reviewed-by: Richard Zhao Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 3a755e5160cf..2d8b6092f80d 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1503,6 +1503,17 @@ static int init_eps(struct ci13xxx *ci) return retval; } +static void destroy_eps(struct ci13xxx *ci) +{ + int i; + + for (i = 0; i < ci->hw_ep_max; i++) { + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; + + dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); + } +} + /** * ci13xxx_start: register a gadget driver * @gadget: our gadget @@ -1710,7 +1721,7 @@ static int udc_start(struct ci13xxx *ci) if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (ci->transceiver == NULL) { retval = -ENODEV; - goto free_pools; + goto destroy_eps; } } @@ -1761,6 +1772,8 @@ unreg_device: put_transceiver: if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) usb_put_phy(ci->transceiver); +destroy_eps: + destroy_eps(ci); free_pools: dma_pool_destroy(ci->td_pool); free_qh_pool: @@ -1775,18 +1788,12 @@ free_qh_pool: */ static void udc_stop(struct ci13xxx *ci) { - int i; - if (ci == NULL) return; usb_del_gadget_udc(&ci->gadget); - for (i = 0; i < ci->hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; - - dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); - } + destroy_eps(ci); dma_pool_destroy(ci->td_pool); dma_pool_destroy(ci->qh_pool); From db89960e50f45274c07dc60926b5a49489b8a7a0 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 12 Sep 2012 14:58:04 +0300 Subject: [PATCH 546/665] usb: chipidea: udc: don't stall endpoint if request list is empty in isr_tr_complete_low When attaching an imx28 or imx53 in USB gadget mode to a Windows host and starting a rndis connection we see this message every 4-10 seconds: g_ether gadget: high speed config #2: RNDIS Analysis shows that each time this message is printed, the rndis connection is re-establish due to a reset because of a stalled endpoint (ep 0, dir 1). The endpoint is stalled because the reqeust complete bit on that endpoint is set, but in isr_tr_complete_low() the endpoint request list (mEp->qh.queue) is empty. This patch removed this check, because the code doesn't take the following situation into account: The loop over all endpoints in isr_tr_complete_handler() will call ep_nuke() on both ep0/dir0 and ep/dir1 in the first loop. Pending reqeusts will be flushed and completed here. There seems to be a race condition, the request is nuked, but the request complete bit will be set, too. The subsequent check (in ep0/dir1's loop cycle) for endpoint request list (mEp->qh.queue) empty will fail. Both other mainline chipidea drivers (mv_udc_core.c and fsl_udc_core.c) don't have this check. Cc: stable Signed-off-by: Michael Grzeschik Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 2d8b6092f80d..d214448b677e 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -771,10 +771,7 @@ __acquires(mEp->lock) { struct ci13xxx_req *mReq, *mReqTemp; struct ci13xxx_ep *mEpTemp = mEp; - int uninitialized_var(retval); - - if (list_empty(&mEp->qh.queue)) - return -EINVAL; + int retval = 0; list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, queue) { From bc01637a80f5b670bd70a0279d3f93fa8de1c96d Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Wed, 12 Sep 2012 13:26:55 +0300 Subject: [PATCH 547/665] digsig: add hash size comparision on signature verification When pkcs_1_v1_5_decode_emsa() returns without error and hash sizes do not match, hash comparision is not done and digsig_verify_rsa() returns no error. This is a bug and this patch fixes it. The bug was introduced in v3.3 by commit b35e286a640f ("lib/digsig: pkcs_1_v1_5_decode_emsa cleanup"). Cc: stable@vger.kernel.org Signed-off-by: Dmitry Kasatkin Signed-off-by: Linus Torvalds --- lib/digsig.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/digsig.c b/lib/digsig.c index 286d558033e2..8c0e62975c88 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -163,9 +163,11 @@ static int digsig_verify_rsa(struct key *key, memcpy(out1 + head, p, l); err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); + if (err) + goto err; - if (!err && len == hlen) - err = memcmp(out2, h, hlen); + if (len != hlen || memcmp(out2, h, hlen)) + err = -EINVAL; err: mpi_free(in); From 26df641eac05abe1a3276eea441359b4d1120816 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 12 Sep 2012 10:05:04 +0000 Subject: [PATCH 548/665] gma500: Fix regression on Oaktrail devices The register map patches didn't set one value for the GMA600 which means the Fujitsu Q550 dies on boot with the GMA500 driver enabled. Add the map entry so we don't read from the device MMIO + 0 by mistake. Signed-off-by: Alan Cox Cc: Horses Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/oaktrail_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 0f9b7db80f6b..cf49ba5a54bf 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -476,6 +476,7 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPAPOS, .surf = DSPASURF, .addr = MRST_DSPABASE, + .base = MRST_DSPABASE, .status = PIPEASTAT, .linoff = DSPALINOFF, .tileoff = DSPATILEOFF, @@ -499,6 +500,7 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPBPOS, .surf = DSPBSURF, .addr = DSPBBASE, + .base = DSPBBASE, .status = PIPEBSTAT, .linoff = DSPBLINOFF, .tileoff = DSPBTILEOFF, From 5e1782d224c79b26ab7d5c31e3f87657000714fb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 01:53:54 +0000 Subject: [PATCH 549/665] vmwgfx: add dumb ioctl support Testing and works with the -modesetting driver, Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 10 ++++ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 73 ++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 33bfc2033009..ba2c35dbf10e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1155,6 +1155,11 @@ static struct drm_driver driver = { .open = vmw_driver_open, .preclose = vmw_preclose, .postclose = vmw_postclose, + + .dumb_create = vmw_dumb_create, + .dumb_map_offset = vmw_dumb_map_offset, + .dumb_destroy = vmw_dumb_destroy, + .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d0f2c079ee27..29c984ff7f23 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); /** * Overlay control - vmwgfx_overlay.c */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 22bf9a21ec71..2c6ffe0e2c07 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1917,3 +1917,76 @@ err_ref: vmw_resource_unreference(&res); return ret; } + + +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct vmw_private *dev_priv = vmw_priv(dev); + struct vmw_master *vmaster = vmw_master(file_priv->master); + struct vmw_user_dma_buffer *vmw_user_bo; + struct ttm_buffer_object *tmp; + int ret; + + args->pitch = args->width * ((args->bpp + 7) / 8); + args->size = args->pitch * args->height; + + vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); + if (vmw_user_bo == NULL) + return -ENOMEM; + + ret = ttm_read_lock(&vmaster->lock, true); + if (ret != 0) { + kfree(vmw_user_bo); + return ret; + } + + ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, + &vmw_vram_sys_placement, true, + &vmw_user_dmabuf_destroy); + if (ret != 0) + goto out_no_dmabuf; + + tmp = ttm_bo_reference(&vmw_user_bo->dma.base); + ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, + &vmw_user_bo->base, + false, + ttm_buffer_type, + &vmw_user_dmabuf_release, NULL); + if (unlikely(ret != 0)) + goto out_no_base_object; + + args->handle = vmw_user_bo->base.hash.key; + +out_no_base_object: + ttm_bo_unref(&tmp); +out_no_dmabuf: + ttm_read_unlock(&vmaster->lock); + return ret; +} + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset) +{ + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_dma_buffer *out_buf; + int ret; + + ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); + if (ret != 0) + return -EINVAL; + + *offset = out_buf->base.addr_space_offset; + vmw_dmabuf_unreference(&out_buf); + return 0; +} + +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle) +{ + return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, + handle, TTM_REF_USAGE); +} From da8b8e0f15b375b44ed8ef4b0c5f5f60f19ccb37 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:21:52 +0800 Subject: [PATCH 550/665] ASoC: core: Mark regmap CODEC register maps as dirty when suspending The core has for a long time had support for marking the register maps of devices dirty when suspending so that they are resynced on resume. Also implement this feature for CODECs using regmap. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ad65459da28e..2b418398ec18 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -635,6 +635,8 @@ int snd_soc_suspend(struct device *dev) codec->driver->suspend(codec); codec->suspended = 1; codec->cache_sync = 1; + if (codec->using_regmap) + regcache_mark_dirty(codec->control_data); break; default: dev_dbg(codec->dev, "CODEC is on over suspend\n"); From 7ba073cdd8b770f990916a7b506d7b31fadb70a5 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:16 +0530 Subject: [PATCH 551/665] drm/exynos: Remove redundant check in exynos_hdmi.c file devm_request_and_ioremap function checks the validity of the pointer returned by platform_get_resource. Hence an additional check in the probe function is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_hdmi.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 409e2ec1207c..bb504cbd7898 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2312,11 +2312,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - DRM_ERROR("failed to find registers\n"); - ret = -ENOENT; - goto err_resource; - } hdata->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hdata->regs) { From 16e197417de3414af7c183f7f4abfa2c7e37f297 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:17 +0530 Subject: [PATCH 552/665] drm/exynos: Remove redundant check in exynos_drm_fimd.c file devm_request_and_ioremap function checks the validity of the pointer returned by platform_get_resource. Hence an additional check in the probe function is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a68d2b313f03..b19cd93e7047 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -831,11 +831,6 @@ static int __devinit fimd_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to find registers\n"); - ret = -ENOENT; - goto err_clk; - } ctx->regs = devm_request_and_ioremap(&pdev->dev, res); if (!ctx->regs) { From 59848db5055765a5d012ad7c428124eca1fcc625 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:18 +0530 Subject: [PATCH 553/665] drm/exynos: Use devm_kzalloc in exynos_drm_vidi.c file devm_kzalloc is a device managed function and makes freeing and error handling simpler. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index bb1550c4dd57..537027a74fd5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -633,7 +633,7 @@ static int __devinit vidi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -673,8 +673,6 @@ static int __devexit vidi_remove(struct platform_device *pdev) ctx->raw_edid = NULL; } - kfree(ctx); - return 0; } From ae18294018c7cf098777a33086073321477f723f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:19 +0530 Subject: [PATCH 554/665] drm/exynos: Use devm_kzalloc in exynos_drm_hdmi.c file devm_kzalloc is a device managed function and makes freeing and error handling simpler. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 8ffcdf8b9e22..3fdf0b65f47e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -345,7 +345,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) { DRM_LOG_KMS("failed to alloc common hdmi context.\n"); return -ENOMEM; @@ -371,7 +371,6 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); exynos_drm_subdrv_unregister(&ctx->subdrv); - kfree(ctx); return 0; } From b767593349c92049dcea4a8ce5c534c4a470099b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:20 +0530 Subject: [PATCH 555/665] drm/exynos: Use devm_* functions in exynos_drm_g2d.c file devm_* functions are device managed functions and make error handling and cleanup cleaner and simpler. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 50 +++++-------------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index d2d88f22a037..6adfa4e03265 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -129,7 +129,6 @@ struct g2d_runqueue_node { struct g2d_data { struct device *dev; struct clk *gate_clk; - struct resource *regs_res; void __iomem *regs; int irq; struct workqueue_struct *g2d_workq; @@ -751,7 +750,7 @@ static int __devinit g2d_probe(struct platform_device *pdev) struct exynos_drm_subdrv *subdrv; int ret; - g2d = kzalloc(sizeof(*g2d), GFP_KERNEL); + g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL); if (!g2d) { dev_err(dev, "failed to allocate driver data\n"); return -ENOMEM; @@ -759,10 +758,8 @@ static int __devinit g2d_probe(struct platform_device *pdev) g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab", sizeof(struct g2d_runqueue_node), 0, 0, NULL); - if (!g2d->runqueue_slab) { - ret = -ENOMEM; - goto err_free_mem; - } + if (!g2d->runqueue_slab) + return -ENOMEM; g2d->dev = dev; @@ -794,38 +791,26 @@ static int __devinit g2d_probe(struct platform_device *pdev) pm_runtime_enable(dev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to get I/O memory\n"); - ret = -ENOENT; - goto err_put_clk; - } - g2d->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!g2d->regs_res) { - dev_err(dev, "failed to request I/O memory\n"); - ret = -ENOENT; - goto err_put_clk; - } - - g2d->regs = ioremap(res->start, resource_size(res)); + g2d->regs = devm_request_and_ioremap(&pdev->dev, res); if (!g2d->regs) { dev_err(dev, "failed to remap I/O memory\n"); ret = -ENXIO; - goto err_release_res; + goto err_put_clk; } g2d->irq = platform_get_irq(pdev, 0); if (g2d->irq < 0) { dev_err(dev, "failed to get irq\n"); ret = g2d->irq; - goto err_unmap_base; + goto err_put_clk; } - ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d); + ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0, + "drm_g2d", g2d); if (ret < 0) { dev_err(dev, "irq request failed\n"); - goto err_unmap_base; + goto err_put_clk; } platform_set_drvdata(pdev, g2d); @@ -838,7 +823,7 @@ static int __devinit g2d_probe(struct platform_device *pdev) ret = exynos_drm_subdrv_register(subdrv); if (ret < 0) { dev_err(dev, "failed to register drm g2d device\n"); - goto err_free_irq; + goto err_put_clk; } dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n", @@ -846,13 +831,6 @@ static int __devinit g2d_probe(struct platform_device *pdev) return 0; -err_free_irq: - free_irq(g2d->irq, g2d); -err_unmap_base: - iounmap(g2d->regs); -err_release_res: - release_resource(g2d->regs_res); - kfree(g2d->regs_res); err_put_clk: pm_runtime_disable(dev); clk_put(g2d->gate_clk); @@ -862,8 +840,6 @@ err_destroy_workqueue: destroy_workqueue(g2d->g2d_workq); err_destroy_slab: kmem_cache_destroy(g2d->runqueue_slab); -err_free_mem: - kfree(g2d); return ret; } @@ -873,24 +849,18 @@ static int __devexit g2d_remove(struct platform_device *pdev) cancel_work_sync(&g2d->runqueue_work); exynos_drm_subdrv_unregister(&g2d->subdrv); - free_irq(g2d->irq, g2d); while (g2d->runqueue_node) { g2d_free_runqueue_node(g2d, g2d->runqueue_node); g2d->runqueue_node = g2d_get_runqueue_node(g2d); } - iounmap(g2d->regs); - release_resource(g2d->regs_res); - kfree(g2d->regs_res); - pm_runtime_disable(&pdev->dev); clk_put(g2d->gate_clk); g2d_fini_cmdlist(g2d); destroy_workqueue(g2d->g2d_workq); kmem_cache_destroy(g2d->runqueue_slab); - kfree(g2d); return 0; } From 4fbd9a4539e4eda1e9588509eb31e9dc38ffd653 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 7 Aug 2012 08:57:25 +0200 Subject: [PATCH 556/665] drm/exynos: Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(.. [1] The semantic patch that makes this change is available in scripts/coccinelle/api/err_cast.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index f9efde40c097..da4e3ca219fa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -122,7 +122,7 @@ fail: __free_page(pages[i]); drm_free_large(pages); - return ERR_PTR(PTR_ERR(p)); + return ERR_CAST(p); } static void exynos_gem_put_pages(struct drm_gem_object *obj, From 7da5907c84f8b092dc42b47b5c19684c1b3b4c98 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Fri, 17 Aug 2012 15:24:03 +0900 Subject: [PATCH 557/665] drm/exynos: fixed page align bug. do not align in page unit at dumb creation. the align is done by exynos_drm_gem_create() to be called commonly. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index da4e3ca219fa..a38051c95ec4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -662,7 +662,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, */ args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = PAGE_ALIGN(args->pitch * args->height); + args->size = args->pitch * args->height; exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); if (IS_ERR(exynos_gem_obj)) From 254d4d111ee159a39d4afb30d9515036d1e0b027 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 14 Aug 2012 12:07:20 +0530 Subject: [PATCH 558/665] drm/exynos: Add dependency for G2D in Kconfig Select Exynos DRM based G2D only if non-DRM based Exynos G2D driver is not selected. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 7f5096763b7d..59a26e577b57 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -36,6 +36,6 @@ config DRM_EXYNOS_VIDI config DRM_EXYNOS_G2D bool "Exynos DRM G2D" - depends on DRM_EXYNOS + depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D help Choose this option if you want to use Exynos G2D for DRM. From 9e1355e7d9c0dac39b9bc4e146a49d379f43ba42 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 28 Aug 2012 14:11:41 +0530 Subject: [PATCH 559/665] drm/exynos: Make g2d_pm_ops static Fixes the following warning: drivers/gpu/drm/exynos/exynos_drm_g2d.c:897:1: warning: symbol 'g2d_pm_ops' was not declared. Should it be static? Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 6adfa4e03265..1065e90d0919 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -894,7 +894,7 @@ static int g2d_resume(struct device *dev) } #endif -SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); +static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); struct platform_driver g2d_driver = { .probe = g2d_probe, From adc837ac3c6eb76d734e471512eaeba210fa5e98 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 Aug 2012 15:50:47 +0530 Subject: [PATCH 560/665] drm/exynos: Add missing braces around sizeof in exynos_hdmi.c Fixes the following checkpatch warnings: WARNING: sizeof *res should be sizeof(*res) WARNING: sizeof res->regul_bulk[0] should be sizeof(res->regul_bulk[0]) WARNING: sizeof *res should be sizeof(*res) Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index bb504cbd7898..a6aea6f3ea1a 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2172,7 +2172,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata) DRM_DEBUG_KMS("HDMI resource init\n"); - memset(res, 0, sizeof *res); + memset(res, 0, sizeof(*res)); /* get clocks, power */ res->hdmi = clk_get(dev, "hdmi"); @@ -2204,7 +2204,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata) clk_set_parent(res->sclk_hdmi, res->sclk_pixel); res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * - sizeof res->regul_bulk[0], GFP_KERNEL); + sizeof(res->regul_bulk[0]), GFP_KERNEL); if (!res->regul_bulk) { DRM_ERROR("failed to get memory for regulators\n"); goto fail; @@ -2243,7 +2243,7 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata) clk_put(res->sclk_hdmi); if (!IS_ERR_OR_NULL(res->hdmi)) clk_put(res->hdmi); - memset(res, 0, sizeof *res); + memset(res, 0, sizeof(*res)); return 0; } From e25e1b6654e3d80da7a40561ec6dba6c5e7e12d3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 Aug 2012 15:50:48 +0530 Subject: [PATCH 561/665] drm/exynos: Add missing braces around sizeof in exynos_mixer.c Fixes the following checkpatch warnings: WARNING: sizeof filter_y_horiz_tap8 should be sizeof(filter_y_horiz_tap8) WARNING: sizeof filter_y_vert_tap4 should be sizeof(filter_y_vert_tap4) WARNING: sizeof filter_cr_horiz_tap4 should be sizeof(filter_cr_horiz_tap4) Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_mixer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 30fcc12f81dd..25b97d5e5fcb 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -236,11 +236,11 @@ static inline void vp_filter_set(struct mixer_resources *res, static void vp_default_filter(struct mixer_resources *res) { vp_filter_set(res, VP_POLY8_Y0_LL, - filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); + filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8)); vp_filter_set(res, VP_POLY4_Y0_LL, - filter_y_vert_tap4, sizeof filter_y_vert_tap4); + filter_y_vert_tap4, sizeof(filter_y_vert_tap4)); vp_filter_set(res, VP_POLY4_C0_LL, - filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); + filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4)); } static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) From b716d46e003fc12f64bbdd71e5b9fd733e59b8d4 Mon Sep 17 00:00:00 2001 From: Tomasz Stanislawski Date: Wed, 5 Sep 2012 19:31:56 +0900 Subject: [PATCH 562/665] drm/exynos: add dummy support for dmabuf-mmap This patch adds a stub function for DMABUF mmap. This allows to export a DMABUF. Signed-off-by: Tomasz Stanislawski Signed-off-by: Kyungmin Park Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 613bf8a5d9b2..ae13febe0eaa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -163,6 +163,12 @@ static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf, /* TODO */ } +static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, + struct vm_area_struct *vma) +{ + return -ENOTTY; +} + static struct dma_buf_ops exynos_dmabuf_ops = { .map_dma_buf = exynos_gem_map_dma_buf, .unmap_dma_buf = exynos_gem_unmap_dma_buf, @@ -170,6 +176,7 @@ static struct dma_buf_ops exynos_dmabuf_ops = { .kmap_atomic = exynos_gem_dmabuf_kmap_atomic, .kunmap = exynos_gem_dmabuf_kunmap, .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic, + .mmap = exynos_gem_dmabuf_mmap, .release = exynos_dmabuf_release, }; From 525ee699f08c0d2516103e4ffd57c21041405d0c Mon Sep 17 00:00:00 2001 From: Mandeep Singh Baines Date: Thu, 6 Sep 2012 09:49:23 -0700 Subject: [PATCH 563/665] drm/exynos: fix double call of drm_prime_(init/destroy)_file_private The double invocations are incorrect but seem to be safe so I don't think this will fix any bugs. Before: [ 7.639366] drm_prime_init_file ee3675d0 [ 7.639377] drm_prime_init_file ee3675d0 [ 7.639507] drm_prime_destroy_file ee3675d0 [ 7.639518] drm_prime_destroy_file ee3675d0 [ 7.639802] drm_prime_init_file ee372390 [ 7.639810] drm_prime_init_file ee372390 [ 8.473316] drm_prime_init_file ee356390 [ 8.473331] drm_prime_init_file ee356390 After: [ 6.363842] drm_prime_init_file edc2e5d0 [ 6.363994] drm_prime_destroy_file edc2e5d0 [ 6.364260] drm_prime_init_file edc2e750 [ 8.004837] drm_prime_init_file ee36ded0 Signed-off-by: Mandeep Singh Baines Acked-by: Seung-Woo Kim Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 6345abe9fdee..d07071937453 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -160,7 +160,6 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) if (!file_priv) return -ENOMEM; - drm_prime_init_file_private(&file->prime); file->driver_priv = file_priv; return exynos_drm_subdrv_open(dev, file); @@ -184,7 +183,6 @@ static void exynos_drm_preclose(struct drm_device *dev, e->base.destroy(&e->base); } } - drm_prime_destroy_file_private(&file->prime); spin_unlock_irqrestore(&dev->event_lock, flags); exynos_drm_subdrv_close(dev, file); From ece82d624cd0ca783e3fa2377fbbce6dd01ec1b3 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Fri, 7 Sep 2012 16:18:15 +0900 Subject: [PATCH 564/665] drm/exynos: remove DRM_FORMAT_NV12M from plane module this patch removes DRM_FORMAT_NV12M from plane module because this format is same as DRM_FORMAT_NV12. DRM_FORMAT_NV12M will be identified by mode_cmd->handles and mode_cmd->offsets fields internally. Signed-off-by: Inki Dae Signed-off-by: Kyungmin.park --- drivers/gpu/drm/exynos/exynos_drm_plane.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index b89829e5043a..e1f94b746bd7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -29,7 +29,6 @@ static const uint32_t formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_NV12, - DRM_FORMAT_NV12M, DRM_FORMAT_NV12MT, }; From d9dd85dd4e18c255225bada181ffcee37f4ff9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 20 Apr 2012 18:26:10 +0300 Subject: [PATCH 565/665] drm: Drop the NV12M and YUV420M formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The NV12M/YUV420M formats are identical to the NV12/YUV420 formats. So just remove these duplicated format names. This might look like breaking the ABI, but the code has never actually accepted these formats, so nothing can be using them. Signed-off-by: Ville Syrjälä Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- include/drm/drm_fourcc.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index bdf0152cbbe9..f4621184a9b4 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -107,8 +107,7 @@ #define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ #define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ -/* 2 non contiguous plane YCbCr */ -#define DRM_FORMAT_NV12M fourcc_code('N', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane */ +/* special NV12 tiled format */ #define DRM_FORMAT_NV12MT fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */ /* @@ -131,7 +130,4 @@ #define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ #define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ -/* 3 non contiguous plane YCbCr */ -#define DRM_FORMAT_YUV420M fourcc_code('Y', 'M', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ - #endif /* DRM_FOURCC_H */ From 1fefb8fdc6562057a0e4e4542f3d4323981c9686 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 10 Sep 2012 01:09:04 +0100 Subject: [PATCH 566/665] ahci: Add JMicron 362 device IDs The JMicron JMB362 controller supports AHCI only, but some revisions use the IDE class code. These need to be matched by device ID. These additions have apparently been included by QNAP in their NAS devices using these controllers. References: http://bugs.debian.org/634180 Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 50d5dea0ff59..c3f52eb97fca 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -268,6 +268,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, + /* JMicron 362B and 362C have an AHCI function with IDE class code */ + { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, + { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ From 17c60c6b763cb5b83b0185e7d38d01d18e55a05a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 16:07:18 +0100 Subject: [PATCH 567/665] ahci: Add alternate identifier for the 88SE9172 This can also appear as 0x9192. Reported in bugzilla and confirmed with the board documentation for these boards. Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=42970 Signed-off-by: Alan Cox Cc: The Stables Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index c3f52eb97fca..51548dd60977 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -396,6 +396,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ { PCI_DEVICE(0x1b4b, 0x917a), .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(0x1b4b, 0x9192), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(0x1b4b, 0x91a3), .driver_data = board_ahci_yes_fbs }, From 7b4f6ecacb14f384adc1a5a67ad95eb082c02bd1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 16:25:25 +0100 Subject: [PATCH 568/665] ahci: Add identifiers for ASM106x devices They don't always appear as AHCI class devices but instead as IDE class. Based on an initial patch by Hiroaki Nito Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=42804 Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 51548dd60977..7862d17976b7 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -405,7 +405,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ /* Asmedia */ - { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, From ab7af5c8d456103ea57c7e9e6f5b03162965e665 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 12 Sep 2012 17:06:46 +0200 Subject: [PATCH 569/665] ASoC: core: Remove useless kfree Remove useless kfree() and clean up code related to the removal. The semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ position p1,p2; expression x; @@ if (x@p1 == NULL) { ... kfree@p2(x); ... return ...; } @unchanged exists@ position r.p1,r.p2; expression e <= r.x,x,e1; iterator I; statement S; @@ if (x@p1 == NULL) { ... when != I(x,...) S when != e = e1 when != e += e1 when != e -= e1 when != ++e when != --e when != e++ when != e-- when != &e kfree@p2(x); ... return ...; } @ok depends on unchanged exists@ position any r.p1; position r.p2; expression x; @@ ... when != true x@p1 == NULL kfree@p2(x); @depends on !ok && unchanged@ position r.p2; expression x; @@ *kfree@p2(x); // Signed-off-by: Peter Senna Tschudin Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2b418398ec18..e5b0713e6f3c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4054,8 +4054,6 @@ int snd_soc_register_codec(struct device *dev, return 0; fail: - kfree(codec->reg_def_copy); - codec->reg_def_copy = NULL; kfree(codec->name); kfree(codec); return ret; From da1dfb6af849cb05aa82b0c18866a7b2bafb6905 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 26 Jul 2012 11:30:54 +0100 Subject: [PATCH 570/665] GFS2: Make write size hinting code common This collects up the write size hinting code which is used by the block reservation subsystem into a single function. At the same time this also corrects the rounding for this calculation. Signed-off-by: Steven Whitehouse --- fs/gfs2/file.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index d1d791ef38de..382000ffac1f 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -322,6 +322,29 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOTTY; } +/** + * gfs2_size_hint - Give a hint to the size of a write request + * @file: The struct file + * @offset: The file offset of the write + * @size: The length of the write + * + * When we are about to do a write, this function records the total + * write size in order to provide a suitable hint to the lower layers + * about how many blocks will be required. + * + */ + +static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size) +{ + struct inode *inode = filep->f_dentry->d_inode; + struct gfs2_sbd *sdp = GFS2_SB(inode); + struct gfs2_inode *ip = GFS2_I(inode); + size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift; + int hint = min_t(size_t, INT_MAX, blks); + + atomic_set(&ip->i_res->rs_sizehint, hint); +} + /** * gfs2_allocate_page_backing - Use bmap to allocate blocks * @page: The (locked) page to allocate backing for @@ -382,8 +405,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (ret) return ret; - atomic_set(&ip->i_res->rs_sizehint, - PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift); + gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); @@ -663,7 +685,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, if (ret) return ret; - atomic_set(&ip->i_res->rs_sizehint, writesize >> sdp->sd_sb.sb_bsize_shift); + gfs2_size_hint(file, pos, writesize); + if (file->f_flags & O_APPEND) { struct gfs2_holder gh; @@ -789,7 +812,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, if (unlikely(error)) goto out_uninit; - atomic_set(&ip->i_res->rs_sizehint, len >> sdp->sd_sb.sb_bsize_shift); + gfs2_size_hint(file, offset, len); while (len > 0) { if (len < bytes) From 645b2ccc75d3d15928e3dbfc659659c2b8d4d9a6 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 26 Jul 2012 14:15:17 +0100 Subject: [PATCH 571/665] GFS2: Fix missing allocation data for set/remove xattr These entry points were missed in the original patch to allocate this data structure. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 4ce22e547308..753af3d86bbc 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1722,7 +1722,9 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name, gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); if (ret == 0) { - ret = generic_setxattr(dentry, name, data, size, flags); + ret = gfs2_rs_alloc(ip); + if (ret == 0) + ret = generic_setxattr(dentry, name, data, size, flags); gfs2_glock_dq(&gh); } gfs2_holder_uninit(&gh); @@ -1757,7 +1759,9 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); if (ret == 0) { - ret = generic_removexattr(dentry, name); + ret = gfs2_rs_alloc(ip); + if (ret == 0) + ret = generic_removexattr(dentry, name); gfs2_glock_dq(&gh); } gfs2_holder_uninit(&gh); From 62e252eeefda62eb8cae9f4286270317ab8d5a42 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 30 Jul 2012 11:06:08 +0100 Subject: [PATCH 572/665] GFS2: Take account of blockages when using reserved blocks The claim_reserved_blks() function was not taking account of the possibility of "blockages" while performing allocation. This can be caused by another node allocating something in the same extent which has been reserved locally. This patch tests for this condition and then skips the remainder of the reservation in this case. This is a relatively rare event, so that it should not affect the general performance improvement which the block reservations provide. The claim_reserved_blks() function also appears not to be able to deal with reservations which cross bitmap boundaries, but that can be dealt with in a future patch since we don't generate boundary crossing reservations currently. Signed-off-by: Steven Whitehouse Reported-by: David Teigland Cc: Bob Peterson --- fs/gfs2/rgrp.c | 70 ++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 4d34887a601d..c9ed814eeb6f 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1961,7 +1961,7 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) * @dinode: 1 if this block is a dinode block, otherwise data block * @nblocks: desired extent length * - * Lay claim to previously allocated block reservation blocks. + * Lay claim to previously reserved blocks. * Returns: Starting block number of the blocks claimed. * Sets *nblocks to the actual extent length allocated. */ @@ -1970,19 +1970,17 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode, { struct gfs2_blkreserv *rs = ip->i_res; struct gfs2_rgrpd *rgd = rs->rs_rgd; - struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_bitmap *bi; u64 start_block = gfs2_rs_startblk(rs); const unsigned int elen = *nblocks; - /*BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));*/ - gfs2_assert_withdraw(sdp, rgd); - /*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/ bi = rs->rs_bi; gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); for (*nblocks = 0; *nblocks < elen && rs->rs_free; (*nblocks)++) { - /* Make sure the bitmap hasn't changed */ + if (gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset, + bi->bi_len, rs->rs_biblk) != GFS2_BLKST_FREE) + break; gfs2_setbit(rgd, bi->bi_clone, bi, rs->rs_biblk, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); rs->rs_biblk++; @@ -1991,20 +1989,12 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode, BUG_ON(!rgd->rd_reserved); rgd->rd_reserved--; dinode = false; - trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM); } - if (!rs->rs_free) { - struct gfs2_rgrpd *rgd = ip->i_res->rs_rgd; - + trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM); + if (!rs->rs_free || *nblocks != elen) gfs2_rs_deltree(rs); - /* -nblocks because we haven't returned to do the math yet. - I'm doing the math backwards to prevent negative numbers, - but think of it as: - if (unclaimed_blocks(rgd) - *nblocks >= RGRP_RSRV_MINBLKS */ - if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS + *nblocks) - rg_mblk_search(rgd, ip); - } + return start_block; } @@ -2037,34 +2027,34 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, if (ip->i_res->rs_requested == 0) return -ECANCELED; - /* Check if we have a multi-block reservation, and if so, claim the - next free block from it. */ + /* If we have a reservation, claim blocks from it. */ if (gfs2_rs_active(ip->i_res)) { BUG_ON(!ip->i_res->rs_free); rgd = ip->i_res->rs_rgd; block = claim_reserved_blks(ip, dinode, nblocks); - } else { - rgd = ip->i_rgd; - - if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) - goal = ip->i_goal - rgd->rd_data0; - else - goal = rgd->rd_last_alloc; - - blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); - - /* Since all blocks are reserved in advance, this shouldn't - happen */ - if (blk == BFITNOENT) { - printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", - *nblocks); - printk(KERN_WARNING "FULL=%d\n", - test_bit(GBF_FULL, &rgd->rd_bits->bi_flags)); - goto rgrp_error; - } - - block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); + if (*nblocks) + goto found_blocks; } + + rgd = ip->i_rgd; + + if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) + goal = ip->i_goal - rgd->rd_data0; + else + goal = rgd->rd_last_alloc; + + blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); + + /* Since all blocks are reserved in advance, this shouldn't happen */ + if (blk == BFITNOENT) { + printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", *nblocks); + printk(KERN_WARNING "FULL=%d\n", + test_bit(GBF_FULL, &rgd->rd_bits->bi_flags)); + goto rgrp_error; + } + + block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); +found_blocks: ndata = *nblocks; if (dinode) ndata--; From 040242ccfcd4ae878267b521d16539e7b3000527 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 13 Sep 2012 12:03:23 +0200 Subject: [PATCH 573/665] ASoC: ad193x: Use managed regmap init Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 50 ++++++++------------------------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 13e62be4f990..2f752660f678 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -381,40 +381,25 @@ static const struct regmap_config ad193x_spi_regmap_config = { static int __devinit ad193x_spi_probe(struct spi_device *spi) { struct ad193x_priv *ad193x; - int ret; ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); - if (IS_ERR(ad193x->regmap)) { - ret = PTR_ERR(ad193x->regmap); - goto err_out; - } + 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); - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ad193x, &ad193x_dai, 1); - if (ret < 0) - goto err_regmap_exit; - - return 0; - -err_regmap_exit: - regmap_exit(ad193x->regmap); -err_out: - return ret; + return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } static int __devexit ad193x_spi_remove(struct spi_device *spi) { - struct ad193x_priv *ad193x = spi_get_drvdata(spi); - snd_soc_unregister_codec(&spi->dev); - regmap_exit(ad193x->regmap); return 0; } @@ -449,40 +434,25 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ad193x_priv *ad193x; - int ret; ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); - if (IS_ERR(ad193x->regmap)) { - ret = PTR_ERR(ad193x->regmap); - goto err_out; - } + 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); - ret = snd_soc_register_codec(&client->dev, - &soc_codec_dev_ad193x, &ad193x_dai, 1); - if (ret < 0) - goto err_regmap_exit; - - return 0; - -err_regmap_exit: - regmap_exit(ad193x->regmap); -err_out: - return ret; + return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } static int __devexit ad193x_i2c_remove(struct i2c_client *client) { - struct ad193x_priv *ad193x = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(ad193x->regmap); return 0; } From 7f22fd9c03c0b67ee6aa138bd10ae91bb0d22151 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 13 Sep 2012 12:04:51 +0200 Subject: [PATCH 574/665] ASoC: ad1836: Convert to direct regmap usage. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad1836.c | 76 +++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index ae1eb51bc9da..dce6ebeef452 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -19,6 +19,8 @@ #include #include #include +#include + #include "ad1836.h" enum ad1836_type { @@ -30,6 +32,7 @@ enum ad1836_type { /* codec private data */ struct ad1836_priv { enum ad1836_type type; + struct regmap *regmap; }; /* @@ -161,8 +164,8 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(dai->codec); int word_len = 0; - struct snd_soc_codec *codec = dai->codec; /* bit size */ switch (params_format(params)) { @@ -178,10 +181,12 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, break; } - snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, + regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1, + AD1836_DAC_WORD_LEN_MASK, word_len << AD1836_DAC_WORD_LEN_OFFSET); - snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, + regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, + AD1836_ADC_WORD_LEN_MASK, word_len << AD1836_ADC_WORD_OFFSET); return 0; @@ -223,15 +228,17 @@ static struct snd_soc_dai_driver ad183x_dais[] = { #ifdef CONFIG_PM static int ad1836_suspend(struct snd_soc_codec *codec) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); /* reset clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, AD1836_ADC_SERFMT_MASK, 0); } static int ad1836_resume(struct snd_soc_codec *codec) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); /* restore clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); } #else @@ -250,37 +257,30 @@ static int ad1836_probe(struct snd_soc_codec *codec) num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; - ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", - ret); - return ret; - } - /* default setting for ad1836 */ /* de-emphasis: 48kHz, power-on dac */ - snd_soc_write(codec, AD1836_DAC_CTRL1, 0x300); + regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300); /* unmute dac channels */ - snd_soc_write(codec, AD1836_DAC_CTRL2, 0x0); + regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0); /* high-pass filter enable, power-on adc */ - snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100); /* unmute adc channles, adc aux mode */ - snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180); /* volume */ for (i = 1; i <= num_dacs; ++i) { - snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); - snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); + regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF); + regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF); } if (ad1836->type == AD1836) { /* left/right diff:PGA/MUX */ - snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A); ret = snd_soc_add_codec_controls(codec, ad1836_controls, ARRAY_SIZE(ad1836_controls)); if (ret) return ret; } else { - snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00); } ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); @@ -313,8 +313,9 @@ static int ad1836_probe(struct snd_soc_codec *codec) /* power down chip */ static int ad1836_remove(struct snd_soc_codec *codec) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); /* reset clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, AD1836_ADC_SERFMT_MASK, 0); } @@ -323,8 +324,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .remove = ad1836_remove, .suspend = ad1836_suspend, .resume = ad1836_resume, - .reg_cache_size = AD1836_NUM_REGS, - .reg_word_size = sizeof(u16), .controls = ad183x_controls, .num_controls = ARRAY_SIZE(ad183x_controls), @@ -334,6 +333,33 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), }; +static const struct reg_default ad1836_reg_defaults[] = { + { AD1836_DAC_CTRL1, 0x0000 }, + { AD1836_DAC_CTRL2, 0x0000 }, + { AD1836_DAC_L_VOL(0), 0x0000 }, + { AD1836_DAC_R_VOL(0), 0x0000 }, + { AD1836_DAC_L_VOL(1), 0x0000 }, + { AD1836_DAC_R_VOL(1), 0x0000 }, + { AD1836_DAC_L_VOL(2), 0x0000 }, + { AD1836_DAC_R_VOL(2), 0x0000 }, + { AD1836_DAC_L_VOL(3), 0x0000 }, + { AD1836_DAC_R_VOL(3), 0x0000 }, + { AD1836_ADC_CTRL1, 0x0000 }, + { AD1836_ADC_CTRL2, 0x0000 }, + { AD1836_ADC_CTRL3, 0x0000 }, +}; + +static const struct regmap_config ad1836_regmap_config = { + .val_bits = 12, + .reg_bits = 4, + .read_flag_mask = 0x08, + + .max_register = AD1836_ADC_CTRL3, + .reg_defaults = ad1836_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int __devinit ad1836_spi_probe(struct spi_device *spi) { struct ad1836_priv *ad1836; @@ -344,6 +370,10 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) if (ad1836 == NULL) return -ENOMEM; + ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config); + if (IS_ERR(ad1836->regmap)) + return PTR_ERR(ad1836->regmap); + ad1836->type = spi_get_device_id(spi)->driver_data; spi_set_drvdata(spi, ad1836); From 64f1e00d8edb54f5d25fb0114a46050fb8340df4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 13 Sep 2012 15:28:56 +0200 Subject: [PATCH 575/665] ALSA: hda - Yet another position_fix quirk for ASUS machines ASUS X53S also suffers from the same issue as in commit c302d6133. Use POS_FIX_POSBUF for this hardware, too. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47461 Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 228cdf93fa29..c4763c52eaf6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2701,6 +2701,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF), SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB), From 4b921eda53366b319602351ff4d7256fafa4bd1b Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Thu, 13 Sep 2012 04:36:20 +0000 Subject: [PATCH 576/665] mISDN: Fix wrong usage of flush_work_sync while holding locks It is a bad idea to hold a spinlock and call flush_work_sync. Move the workqueue cleanup outside the spinlock and use cancel_work_sync, on closing the channel this seems to be the more correct function. Remove the never used and constant return value of mISDN_freebchannel. Signed-off-by: Karsten Keil Cc: Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/avmfritz.c | 3 ++- drivers/isdn/hardware/mISDN/mISDNipac.c | 3 ++- drivers/isdn/hardware/mISDN/mISDNisar.c | 3 ++- drivers/isdn/hardware/mISDN/netjet.c | 3 ++- drivers/isdn/hardware/mISDN/w6692.c | 3 ++- drivers/isdn/mISDN/hwchannel.c | 9 ++++----- include/linux/mISDNhw.h | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index fa6ca4733725..dceaec821b0e 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(&fc->lock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); modehdlc(bch, ISDN_P_NONE); spin_unlock_irqrestore(&fc->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 752e0825591f..ccd7d851be26 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(hx->ip->hwlock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); hscx_mode(hx, ISDN_P_NONE); spin_unlock_irqrestore(hx->ip->hwlock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index be5973ded6d6..182ecf0626c2 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(ich->is->hwlock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); modeisar(ich, ISDN_P_NONE); spin_unlock_irqrestore(ich->is->hwlock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index c3e3e7686273..9bcade59eb73 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(&card->lock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); mode_tiger(bc, ISDN_P_NONE); spin_unlock_irqrestore(&card->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 26a86b846099..335fe6455002 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(&card->lock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); w6692_mode(bc, ISDN_P_NONE); spin_unlock_irqrestore(&card->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index ef34fd40867c..2602be23f341 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c @@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch) ch->next_minlen = ch->init_minlen; ch->maxlen = ch->init_maxlen; ch->next_maxlen = ch->init_maxlen; + skb_queue_purge(&ch->rqueue); + ch->rcount = 0; } EXPORT_SYMBOL(mISDN_clear_bchannel); -int +void mISDN_freebchannel(struct bchannel *ch) { + cancel_work_sync(&ch->workq); mISDN_clear_bchannel(ch); - skb_queue_purge(&ch->rqueue); - ch->rcount = 0; - flush_work_sync(&ch->workq); - return 0; } EXPORT_SYMBOL(mISDN_freebchannel); diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h index d0752eca9b44..9d96d5d4dfed 100644 --- a/include/linux/mISDNhw.h +++ b/include/linux/mISDNhw.h @@ -183,7 +183,7 @@ extern int mISDN_initbchannel(struct bchannel *, unsigned short, unsigned short); extern int mISDN_freedchannel(struct dchannel *); extern void mISDN_clear_bchannel(struct bchannel *); -extern int mISDN_freebchannel(struct bchannel *); +extern void mISDN_freebchannel(struct bchannel *); extern int mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *); extern void queue_ch_frame(struct mISDNchannel *, u_int, int, struct sk_buff *); From e29fe837bfa3ca0a9f4ef1d4a90e6e0a74b6b8a0 Mon Sep 17 00:00:00 2001 From: David Ward Date: Thu, 13 Sep 2012 05:22:32 +0000 Subject: [PATCH 577/665] net_sched: gred: correct comment about qavg calculation in RIO mode Signed-off-by: David Ward Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/sch_gred.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index e901583e4ea5..fca73cdf44d9 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -176,7 +176,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch) skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp; } - /* sum up all the qaves of prios <= to ours to get the new qave */ + /* sum up all the qaves of prios < ours to get the new qave */ if (!gred_wred_mode(t) && gred_rio_mode(t)) { int i; From c22e464022f935b0cbd8724b1d99d800d49518a9 Mon Sep 17 00:00:00 2001 From: David Ward Date: Thu, 13 Sep 2012 05:22:33 +0000 Subject: [PATCH 578/665] net_sched: gred: eliminate redundant DP prio comparisons Each pair of DPs only needs to be compared once when searching for a non-unique prio value. Signed-off-by: David Ward Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/sch_gred.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index fca73cdf44d9..e19d4ebfea1c 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -102,9 +102,8 @@ static inline int gred_wred_mode_check(struct Qdisc *sch) if (q == NULL) continue; - for (n = 0; n < table->DPs; n++) - if (table->tab[n] && table->tab[n] != q && - table->tab[n]->prio == q->prio) + for (n = i + 1; n < table->DPs; n++) + if (table->tab[n] && table->tab[n]->prio == q->prio) return 1; } From 1fe37b106b039d9358fd1211c39b1fa199e547a8 Mon Sep 17 00:00:00 2001 From: David Ward Date: Thu, 13 Sep 2012 05:22:34 +0000 Subject: [PATCH 579/665] net_sched: gred: fix qave reporting via netlink q->vars.qavg is a Wlog scaled value, but q->backlog is not. In order to pass q->vars.qavg as the backlog value, we need to un-scale it. Additionally, the qave value returned via netlink should not be Wlog scaled, so we need to un-scale the result of red_calc_qavg(). This caused artificially high values for "Average Queue" to be shown by 'tc -s -d qdisc', but did not affect the actual operation of GRED. Signed-off-by: David Ward Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/sch_gred.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index e19d4ebfea1c..b2570b59d85e 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -534,6 +534,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) for (i = 0; i < MAX_DPs; i++) { struct gred_sched_data *q = table->tab[i]; struct tc_gred_qopt opt; + unsigned long qavg; memset(&opt, 0, sizeof(opt)); @@ -565,7 +566,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) if (gred_wred_mode(table)) gred_load_wred_set(table, q); - opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg); + qavg = red_calc_qavg(&q->parms, &q->vars, + q->vars.qavg >> q->parms.Wlog); + opt.qave = qavg >> q->parms.Wlog; append_opt: if (nla_append(skb, sizeof(opt), &opt) < 0) From ba1bf474eae07a128fae6252bf7d68eaef0eacf8 Mon Sep 17 00:00:00 2001 From: David Ward Date: Thu, 13 Sep 2012 05:22:35 +0000 Subject: [PATCH 580/665] net_sched: gred: actually perform idling in WRED mode gred_dequeue() and gred_drop() do not seem to get called when the queue is empty, meaning that we never start idling while in WRED mode. And since qidlestart is not stored by gred_store_wred_set(), we would never stop idling while in WRED mode if we ever started. This messes up the average queue size calculation that influences packet marking/dropping behavior. Now, we start WRED mode idling as we are removing the last packet from the queue. Also we now actually stop WRED mode idling when we are enqueuing a packet. Cc: Bruce Osler Signed-off-by: David Ward Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/sch_gred.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index b2570b59d85e..d42234c0f13b 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -136,6 +136,7 @@ static inline void gred_store_wred_set(struct gred_sched *table, struct gred_sched_data *q) { table->wred_set.qavg = q->vars.qavg; + table->wred_set.qidlestart = q->vars.qidlestart; } static inline int gred_use_ecn(struct gred_sched *t) @@ -259,16 +260,18 @@ static struct sk_buff *gred_dequeue(struct Qdisc *sch) } else { q->backlog -= qdisc_pkt_len(skb); - if (!q->backlog && !gred_wred_mode(t)) - red_start_of_idle_period(&q->vars); + if (gred_wred_mode(t)) { + if (!sch->qstats.backlog) + red_start_of_idle_period(&t->wred_set); + } else { + if (!q->backlog) + red_start_of_idle_period(&q->vars); + } } return skb; } - if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) - red_start_of_idle_period(&t->wred_set); - return NULL; } @@ -290,19 +293,20 @@ static unsigned int gred_drop(struct Qdisc *sch) q->backlog -= len; q->stats.other++; - if (!q->backlog && !gred_wred_mode(t)) - red_start_of_idle_period(&q->vars); + if (gred_wred_mode(t)) { + if (!sch->qstats.backlog) + red_start_of_idle_period(&t->wred_set); + } else { + if (!q->backlog) + red_start_of_idle_period(&q->vars); + } } qdisc_drop(skb, sch); return len; } - if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) - red_start_of_idle_period(&t->wred_set); - return 0; - } static void gred_reset(struct Qdisc *sch) From 8624dd2a3e33b647cd672211b54ba276ddee2a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 12 Sep 2012 20:44:35 +0000 Subject: [PATCH 581/665] net: qmi_wwan: call subdriver with control intf only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a hang on suspend due to calling wdm_suspend on the unregistered data interface. The hang should have been a NULL pointer reference had it not been for a logic error in the cdc_wdm code. commit 230718bd net: qmi_wwan: bind to both control and data interface changed qmi_wwan to use cdc_wdm as a subdriver for devices with a two-interface QMI/wwan function. The commit failed to update qmi_wwan_suspend and qmi_wwan_resume, which were written to handle either a single combined interface function, or no subdriver at all. The result was that we called into the subdriver both when the control interface was suspended and when the data interface was suspended. Calling the subdriver suspend function with an unregistered interface is not supported and will make the subdriver bug out. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 17b8f3e37687..b1ba68f1a049 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -297,7 +297,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message) if (ret < 0) goto err; - if (info->subdriver && info->subdriver->suspend) + if (intf == info->control && info->subdriver && info->subdriver->suspend) ret = info->subdriver->suspend(intf, message); if (ret < 0) usbnet_resume(intf); @@ -310,13 +310,14 @@ static int qmi_wwan_resume(struct usb_interface *intf) struct usbnet *dev = usb_get_intfdata(intf); struct qmi_wwan_state *info = (void *)&dev->data; int ret = 0; + bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume); - if (info->subdriver && info->subdriver->resume) + if (callsub) ret = info->subdriver->resume(intf); if (ret < 0) goto err; ret = usbnet_resume(intf); - if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend) + if (ret < 0 && callsub && info->subdriver->suspend) info->subdriver->suspend(intf, PMSG_SUSPEND); err: return ret; From 985f61f7ee647ad570c05eab0b74915da2ac8e19 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 31 Aug 2012 11:56:50 -0400 Subject: [PATCH 582/665] drm/radeon: rework pll selection (v3) For DP we can use the same PPLL for all active DP encoders. Take advantage of that to prevent cases where we may end up sharing a PPLL between DP and non-DP which won't work. Also clean up the code a bit. v2: - fix missing pll_id assignment in crtc init v3: - fix DP PPLL check - document functions - break in main encoder search loop after matching. no need to keep checking additional encoders. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=54471 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 163 +++++++++++++++++++------ 1 file changed, 129 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 2817101fb167..e721e3087b99 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1479,14 +1479,98 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) } } +/** + * radeon_get_pll_use_mask - look up a mask of which pplls are in use + * + * @crtc: drm crtc + * + * Returns the mask of which PPLLs (Pixel PLLs) are in use. + */ +static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc *test_crtc; + struct radeon_crtc *radeon_test_crtc; + u32 pll_in_use = 0; + + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + + radeon_test_crtc = to_radeon_crtc(test_crtc); + if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) + pll_in_use |= (1 << radeon_test_crtc->pll_id); + } + return pll_in_use; +} + +/** + * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is + * also in DP mode. For DP, a single PPLL can be used for all DP + * crtcs/encoders. + */ +static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_encoder *test_encoder; + struct radeon_crtc *radeon_test_crtc; + + list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { + if (test_encoder->crtc && (test_encoder->crtc != crtc)) { + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { + /* for DP use the same PLL for all */ + radeon_test_crtc = to_radeon_crtc(test_encoder->crtc); + if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) + return radeon_test_crtc->pll_id; + } + } + } + return ATOM_PPLL_INVALID; +} + +/** + * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc. + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors + * a single PPLL can be used for all DP crtcs/encoders. For non-DP + * monitors a dedicated PPLL must be used. If a particular board has + * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming + * as there is no need to program the PLL itself. If we are not able to + * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to + * avoid messing up an existing monitor. + * + * Asic specific PLL information + * + * DCE 6.1 + * - PPLL2 is only available to UNIPHYA (both DP and non-DP) + * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP) + * + * DCE 6.0 + * - PPLL0 is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 5.0 + * - DCPLL is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 3.0/4.0/4.1 + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + */ static int radeon_atom_pick_pll(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct drm_encoder *test_encoder; - struct drm_crtc *test_crtc; - uint32_t pll_in_use = 0; + u32 pll_in_use; + int pll; if (ASIC_IS_DCE61(rdev)) { list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { @@ -1498,32 +1582,40 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) if ((test_radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && - (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ + (dig->linkb == false)) + /* UNIPHY A uses PPLL2 */ return ATOM_PPLL2; + else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { + /* UNIPHY B/C/D/E/F */ + if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ + return ATOM_PPLL_INVALID; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + } + break; } } /* UNIPHY B/C/D/E/F */ - list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_test_crtc; - - if (crtc == test_crtc) - continue; - - radeon_test_crtc = to_radeon_crtc(test_crtc); - if ((radeon_test_crtc->pll_id == ATOM_PPLL0) || - (radeon_test_crtc->pll_id == ATOM_PPLL1)) - pll_in_use |= (1 << radeon_test_crtc->pll_id); - } - if (!(pll_in_use & 4)) + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL0))) return ATOM_PPLL0; - return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; } else if (ASIC_IS_DCE4(rdev)) { list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { if (test_encoder->crtc && (test_encoder->crtc == crtc)) { /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, * depending on the asic: * DCE4: PPLL or ext clock - * DCE5: DCPLL or ext clock + * DCE5: PPLL, DCPLL, or ext clock + * DCE6: PPLL, PPLL0, or ext clock * * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip * PPLL/DCPLL programming and only program the DP DTO for the @@ -1531,31 +1623,34 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ return ATOM_PPLL_INVALID; else if (ASIC_IS_DCE6(rdev)) + /* use PPLL0 for all DP */ return ATOM_PPLL0; else if (ASIC_IS_DCE5(rdev)) + /* use DCPLL for all DP */ return ATOM_DCPLL; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } } + break; } } - - /* otherwise, pick one of the plls */ - list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_test_crtc; - - if (crtc == test_crtc) - continue; - - radeon_test_crtc = to_radeon_crtc(test_crtc); - if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) && - (radeon_test_crtc->pll_id <= ATOM_PPLL2)) - pll_in_use |= (1 << radeon_test_crtc->pll_id); - } - if (!(pll_in_use & 1)) + /* all other cases */ + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; - return ATOM_PPLL2; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; } else + /* use PPLL1 or PPLL2 */ return radeon_crtc->crtc_id; } @@ -1697,7 +1792,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) break; } done: - radeon_crtc->pll_id = -1; + radeon_crtc->pll_id = ATOM_PPLL_INVALID; } static const struct drm_crtc_helper_funcs atombios_helper_funcs = { @@ -1746,6 +1841,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev, else radeon_crtc->crtc_offset = 0; } - radeon_crtc->pll_id = -1; + radeon_crtc->pll_id = ATOM_PPLL_INVALID; drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); } From f492c171a38d77fc13a8998a0721f2da50835224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 13 Sep 2012 10:33:47 +0200 Subject: [PATCH 583/665] drm/radeon: make 64bit fences more robust v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only increase the higher 32bits if we really detect a wrap around. v2: instead of increasing the higher 32bits just use the higher 32bits from the last emitted fence. v3: also use last emitted fence value as upper limit. The intention of this patch is to make fences as robust as they where before introducing 64bit fences. This is necessary because on older systems it looks like the fence value gets corrupted on initialization. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=51344 Should also fix: https://bugs.freedesktop.org/show_bug.cgi?id=54129 https://bugs.freedesktop.org/show_bug.cgi?id=54662 https://bugzilla.redhat.com/show_bug.cgi?id=846505 https://bugzilla.redhat.com/show_bug.cgi?id=845639 3.5 needs a separate patch due to changes in the fence code. Will send that out separately. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_fence.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 7b737b9339ad..2a59375dbe52 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -131,7 +131,7 @@ int radeon_fence_emit(struct radeon_device *rdev, */ void radeon_fence_process(struct radeon_device *rdev, int ring) { - uint64_t seq, last_seq; + uint64_t seq, last_seq, last_emitted; unsigned count_loop = 0; bool wake = false; @@ -158,13 +158,15 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) */ last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq); do { + last_emitted = rdev->fence_drv[ring].sync_seq[ring]; seq = radeon_fence_read(rdev, ring); seq |= last_seq & 0xffffffff00000000LL; if (seq < last_seq) { - seq += 0x100000000LL; + seq &= 0xffffffff; + seq |= last_emitted & 0xffffffff00000000LL; } - if (seq == last_seq) { + if (seq <= last_seq || seq > last_emitted) { break; } /* If we loop over we don't want to return without From bef05406ac0ea6f468e1e25e9934f3011ea9259b Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 11 Sep 2012 04:34:08 +0000 Subject: [PATCH 584/665] bnx2x: Avoid sending multiple statistics queries During traffic when DCB is enabled, it is possible for multiple instances of statistics queries to be sent to the chip - this may cause the FW to assert. This patch prevents the sending of an additional instance of statistics query while the previous query hasn't completed. Signed-off-by: Dmitry Kravkov Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 332db64dd5be..d848dc9db7b0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -1151,9 +1151,11 @@ static void bnx2x_stats_update(struct bnx2x *bp) if (bp->port.pmf) bnx2x_hw_stats_update(bp); - if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) { - BNX2X_ERR("storm stats were not updated for 3 times\n"); - bnx2x_panic(); + if (bnx2x_storm_stats_update(bp)) { + if (bp->stats_pending++ == 3) { + BNX2X_ERR("storm stats were not updated for 3 times\n"); + bnx2x_panic(); + } return; } From 217aeb896a4a9f00006ce4b193c216f739234296 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Tue, 11 Sep 2012 04:34:09 +0000 Subject: [PATCH 585/665] bnx2x: fix stats copying logic FW needs the driver statistics for management. Current logic is broken in that the function that gathers the port statistics does not copy its own statistics to a place where the FW can use it. This patch causes every function that can pass statistics to the FW to do so. Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index d848dc9db7b0..a1d0446b39b3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -101,6 +101,11 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp) if (CHIP_REV_IS_SLOW(bp)) return; + /* Update MCP's statistics if possible */ + if (bp->func_stx) + memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, + sizeof(bp->func_stats)); + /* loader */ if (bp->executer_idx) { int loader_idx = PMF_DMAE_C(bp); @@ -128,8 +133,6 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp) } else if (bp->func_stx) { *stats_comp = 0; - memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, - sizeof(bp->func_stats)); bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp)); } } From 375944cb7c96bf66914a73b1858e5865c439b335 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Tue, 11 Sep 2012 04:34:10 +0000 Subject: [PATCH 586/665] bnx2x: prevent timeouts when using PFC Prevent updating the xmac PFC configuration when using a link speed slower than 10G -the umac block is responsible for 1G or slower connections, therefore it is possible the xmac block is reset when connection is slower. Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index f4beb46c4709..40a7b8d877cf 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -2667,9 +2667,11 @@ int bnx2x_update_pfc(struct link_params *params, return bnx2x_status; DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n"); - if (CHIP_IS_E3(bp)) - bnx2x_update_pfc_xmac(params, vars, 0); - else { + + if (CHIP_IS_E3(bp)) { + if (vars->mac_type == MAC_TYPE_XMAC) + bnx2x_update_pfc_xmac(params, vars, 0); + } else { val = REG_RD(bp, MISC_REG_RESET_REG_2); if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) From 430d172a635c3dd791a56c59573418e02735b006 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Tue, 11 Sep 2012 04:34:11 +0000 Subject: [PATCH 587/665] bnx2x: display the correct duplex value Prior to this fix, the driver reported the chip's active duplex state is always 'full', even if using half-duplex mode. Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 40a7b8d877cf..b046beb435b2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -5434,7 +5434,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, switch (speed_mask) { case GP_STATUS_10M: vars->line_speed = SPEED_10; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_10TFD; else vars->link_status |= LINK_10THD; @@ -5442,7 +5442,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_100M: vars->line_speed = SPEED_100; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_100TXFD; else vars->link_status |= LINK_100TXHD; @@ -5451,7 +5451,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_1G: case GP_STATUS_1G_KX: vars->line_speed = SPEED_1000; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_1000TFD; else vars->link_status |= LINK_1000THD; @@ -5459,7 +5459,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_2_5G: vars->line_speed = SPEED_2500; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_2500TFD; else vars->link_status |= LINK_2500THD; @@ -5533,6 +5533,7 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy, if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { if (SINGLE_MEDIA_DIRECT(params)) { + vars->duplex = duplex; bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status); if (phy->req_line_speed == SPEED_AUTO_NEG) bnx2x_xgxs_an_resolve(phy, params, vars, @@ -5627,6 +5628,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy, LINK_STATUS_PARALLEL_DETECTION_USED; } bnx2x_ext_phy_resolve_fc(phy, params, vars); + vars->duplex = duplex; } } From 5cd75f0c0fd2b068dbd0ce3cb9460c3aafc0aae7 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Tue, 11 Sep 2012 04:34:12 +0000 Subject: [PATCH 588/665] bnx2x: correct advertisement of pause capabilities This patch propagates users' requested flow-control into the link layer, which will later be used to advertise this flow-control for auto-negotiation (until now these values were ignored). Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c37a68d68090..bbf4cf00dd19 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1587,6 +1587,12 @@ static int bnx2x_set_pauseparam(struct net_device *dev, bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO; } + bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_NONE; + if (epause->rx_pause) + bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_RX; + + if (epause->tx_pause) + bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_TX; } DP(BNX2X_MSG_ETHTOOL, From 2ace95103df2bcb574c9da5df96807e9b46f9b38 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 11 Sep 2012 04:34:13 +0000 Subject: [PATCH 589/665] bnx2x: fix registers dumped Under traffic, there are several registers that when read (e.g., via 'ethtool -d') may cause the chip to stall. This patch corrects the registers read in such flows. Signed-off-by: Dmitry Kravkov Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_dump.h | 25 ++++++------------- .../ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 +- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index 3e4cff9b1ebe..b926f58e983b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -401,11 +401,11 @@ static const struct reg_addr reg_addrs[] = { { 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 8184, RI_ALL_OFFLINE }, { 0x78000, 8192, RI_E3E3B0_OFFLINE }, - { 0x85000, 3, RI_ALL_ONLINE }, - { 0x8501c, 7, RI_ALL_ONLINE }, - { 0x85048, 1, RI_ALL_ONLINE }, - { 0x85200, 32, RI_ALL_ONLINE }, - { 0xb0000, 16384, RI_E1H_ONLINE }, + { 0x85000, 3, RI_ALL_OFFLINE }, + { 0x8501c, 7, RI_ALL_OFFLINE }, + { 0x85048, 1, RI_ALL_OFFLINE }, + { 0x85200, 32, RI_ALL_OFFLINE }, + { 0xb0000, 16384, RI_E1H_OFFLINE }, { 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2E3E3B0_ONLINE }, { 0xc1800, 2, RI_ALL_ONLINE }, @@ -581,17 +581,12 @@ static const struct reg_addr reg_addrs[] = { { 0x140188, 3, RI_E1E1HE2E3_ONLINE }, { 0x140194, 13, RI_ALL_ONLINE }, { 0x140200, 6, RI_E1E1HE2E3_ONLINE }, - { 0x140220, 4, RI_E2E3_ONLINE }, - { 0x140240, 4, RI_E2E3_ONLINE }, { 0x140260, 4, RI_E2E3_ONLINE }, { 0x140280, 4, RI_E2E3_ONLINE }, - { 0x1402a0, 4, RI_E2E3_ONLINE }, - { 0x1402c0, 4, RI_E2E3_ONLINE }, { 0x1402e0, 2, RI_E2E3_ONLINE }, { 0x1402e8, 2, RI_E2E3E3B0_ONLINE }, { 0x1402f0, 9, RI_E2E3_ONLINE }, { 0x140314, 44, RI_E3B0_ONLINE }, - { 0x1403d0, 70, RI_E3B0_ONLINE }, { 0x144000, 4, RI_E1E1H_ONLINE }, { 0x148000, 4, RI_E1E1H_ONLINE }, { 0x14c000, 4, RI_E1E1H_ONLINE }, @@ -704,7 +699,6 @@ static const struct reg_addr reg_addrs[] = { { 0x180398, 1, RI_E2E3E3B0_ONLINE }, { 0x1803a0, 5, RI_E2E3E3B0_ONLINE }, { 0x1803b4, 2, RI_E3E3B0_ONLINE }, - { 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_E1E1H_OFFLINE }, { 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE }, @@ -800,9 +794,9 @@ static const struct reg_addr reg_addrs[] = { { 0x1b905c, 1, RI_E3E3B0_ONLINE }, { 0x1b9064, 1, RI_E3B0_ONLINE }, { 0x1b9080, 10, RI_E3B0_ONLINE }, - { 0x1b9400, 14, RI_E2E3E3B0_ONLINE }, - { 0x1b943c, 19, RI_E2E3E3B0_ONLINE }, - { 0x1b9490, 10, RI_E2E3E3B0_ONLINE }, + { 0x1b9400, 14, RI_E2E3E3B0_OFFLINE }, + { 0x1b943c, 19, RI_E2E3E3B0_OFFLINE }, + { 0x1b9490, 10, RI_E2E3E3B0_OFFLINE }, { 0x1c0000, 2, RI_ALL_ONLINE }, { 0x200000, 65, RI_ALL_ONLINE }, { 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE }, @@ -814,7 +808,6 @@ static const struct reg_addr reg_addrs[] = { { 0x200398, 1, RI_E2E3E3B0_ONLINE }, { 0x2003a0, 1, RI_E2E3E3B0_ONLINE }, { 0x2003a8, 2, RI_E2E3E3B0_ONLINE }, - { 0x200400, 1, RI_ALL_ONLINE }, { 0x200404, 255, RI_E1E1H_OFFLINE }, { 0x202000, 4, RI_ALL_ONLINE }, { 0x202010, 2044, RI_ALL_OFFLINE }, @@ -921,7 +914,6 @@ static const struct reg_addr reg_addrs[] = { { 0x280398, 1, RI_E2E3E3B0_ONLINE }, { 0x2803a0, 1, RI_E2E3E3B0_ONLINE }, { 0x2803a8, 2, RI_E2E3E3B0_ONLINE }, - { 0x280400, 1, RI_ALL_ONLINE }, { 0x280404, 255, RI_E1E1H_OFFLINE }, { 0x282000, 4, RI_ALL_ONLINE }, { 0x282010, 2044, RI_ALL_OFFLINE }, @@ -1031,7 +1023,6 @@ static const struct reg_addr reg_addrs[] = { { 0x300398, 1, RI_E2E3E3B0_ONLINE }, { 0x3003a0, 1, RI_E2E3E3B0_ONLINE }, { 0x3003a8, 2, RI_E2E3E3B0_ONLINE }, - { 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_E1E1H_OFFLINE }, { 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE }, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index bbf4cf00dd19..ebf40cd7aa10 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -775,7 +775,7 @@ static void bnx2x_get_regs(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); struct dump_hdr dump_hdr = {0}; - regs->version = 0; + regs->version = 1; memset(p, 0, regs->len); if (!netif_running(bp->dev)) From 7b5342d9026d537cbc01fd30b7cd9bac9b07b5ad Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Tue, 11 Sep 2012 04:34:14 +0000 Subject: [PATCH 590/665] bnx2x: Add missing afex code Commit a334872224a67b614dc888460377862621f3dac7 added afex support but lacked several logical changes. This lack can cause afex to crash, and also have a slight effect on other flows (i.e., driver always assumes the Tx ring has less available buffers than what it actually has). This patch adds the missing segments, fixing said issues. Signed-off-by: Yuval Mintz Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 11 +++++----- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 21 ++++++++++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 21b553229ea4..dfd86a55f1dc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -710,17 +710,15 @@ static inline u16 bnx2x_tx_avail(struct bnx2x *bp, prod = txdata->tx_bd_prod; cons = txdata->tx_bd_cons; - /* NUM_TX_RINGS = number of "next-page" entries - It will be used as a threshold */ - used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS; + used = SUB_S16(prod, cons); #ifdef BNX2X_STOP_ON_ERROR WARN_ON(used < 0); - WARN_ON(used > bp->tx_ring_size); - WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL); + WARN_ON(used > txdata->tx_ring_size); + WARN_ON((txdata->tx_ring_size - used) > MAX_TX_AVAIL); #endif - return (s16)(bp->tx_ring_size) - used; + return (s16)(txdata->tx_ring_size) - used; } static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata) @@ -1088,6 +1086,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp, txdata->txq_index = txq_index; txdata->tx_cons_sb = tx_cons_sb; txdata->parent_fp = fp; + txdata->tx_ring_size = IS_FCOE_FP(fp) ? MAX_TX_AVAIL : bp->tx_ring_size; DP(NETIF_MSG_IFUP, "created tx data cid %d, txq %d\n", txdata->cid, txdata->txq_index); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 21054987257a..211753e01f81 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -7561,8 +7561,14 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, } rc = bnx2x_config_vlan_mac(bp, &ramrod_param); - if (rc < 0) + + if (rc == -EEXIST) { + DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc); + /* do not treat adding same MAC as error */ + rc = 0; + } else if (rc < 0) BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del")); + return rc; } @@ -10294,13 +10300,11 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) dev_info.port_hw_config[port]. fcoe_wwn_node_name_lower); } else if (!IS_MF_SD(bp)) { - u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg); - /* * Read the WWN info only if the FCoE feature is enabled for * this function. */ - if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) + if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp)) bnx2x_get_ext_wwn_info(bp, func); } else if (IS_MF_FCOE_SD(bp)) @@ -11073,7 +11077,14 @@ static int bnx2x_set_uc_list(struct bnx2x *bp) netdev_for_each_uc_addr(ha, dev) { rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true, BNX2X_UC_LIST_MAC, &ramrod_flags); - if (rc < 0) { + if (rc == -EEXIST) { + DP(BNX2X_MSG_SP, + "Failed to schedule ADD operations: %d\n", rc); + /* do not treat adding same MAC as error */ + rc = 0; + + } else if (rc < 0) { + BNX2X_ERR("Failed to schedule ADD operations: %d\n", rc); return rc; From 07f377da7e8a7d3c3a6626333516f9c808637c9e Mon Sep 17 00:00:00 2001 From: Bernhard Froemel Date: Sat, 25 Aug 2012 10:30:49 +0200 Subject: [PATCH 591/665] apple-gmux: Obtain version info from indexed gmux This patch extracts and displays version information from the indexed gmux device as it is also done for the classic gmux device. Signed-off-by: Bernhard Froemel Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index dfb1a92ce949..c9558d1ea88c 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -461,18 +461,22 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { if (gmux_is_indexed(gmux_data)) { + u32 version; mutex_init(&gmux_data->index_lock); gmux_data->indexed = true; + version = gmux_read32(gmux_data, + GMUX_PORT_VERSION_MAJOR); + ver_major = (version >> 24) & 0xff; + ver_minor = (version >> 16) & 0xff; + ver_release = (version >> 8) & 0xff; } else { pr_info("gmux device not present\n"); ret = -ENODEV; goto err_release; } - pr_info("Found indexed gmux\n"); - } else { - pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, - ver_release); } + pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, + ver_release, (gmux_data->indexed ? "indexed" : "classic")); memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_PLATFORM; From c5a5052923c55990e32a3d64bdb4779b01162646 Mon Sep 17 00:00:00 2001 From: Bernhard Froemel Date: Sat, 25 Aug 2012 10:30:48 +0200 Subject: [PATCH 592/665] apple-gmux: Fix index read functions Study of Apple's binary driver revealed that the GMUX_READ_PORT should be written between calls to gmux_index_wait_ready and gmux_index_wait_complete (i.e., the new index protocol must be followed). If this is not done correctly, the indexed gmux device only partially accepts writes which lead to problems concerning GPU switching. Special thanks to Seth Forshee who helped greatly with identifying unnecessary changes. Signed-off-by: Bernhard Froemel Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index c9558d1ea88c..0e43477de337 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -142,8 +142,9 @@ static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port) u8 val; mutex_lock(&gmux_data->index_lock); - outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); gmux_index_wait_ready(gmux_data); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_complete(gmux_data); val = inb(gmux_data->iostart + GMUX_PORT_VALUE); mutex_unlock(&gmux_data->index_lock); @@ -166,8 +167,9 @@ static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port) u32 val; mutex_lock(&gmux_data->index_lock); - outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); gmux_index_wait_ready(gmux_data); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_complete(gmux_data); val = inl(gmux_data->iostart + GMUX_PORT_VALUE); mutex_unlock(&gmux_data->index_lock); From e6d9d3d59ca08fc87688c5953061b4da0d17bf15 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Tue, 21 Aug 2012 21:56:49 -0500 Subject: [PATCH 593/665] apple-gmux: Fix port address calculation in gmux_pio_write32() This function fails to add the start address of the gmux I/O range to the requested port address and thus writes to the wrong location. Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 0e43477de337..5c17ba895692 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -101,7 +101,7 @@ static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port, for (i = 0; i < 4; i++) { tmpval = (val >> (i * 8)) & 0xff; - outb(tmpval, port + i); + outb(tmpval, gmux_data->iostart + port + i); } } From 689db7843d503fae0eb46cb849e4caab35588170 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 20 Aug 2012 23:01:50 +0200 Subject: [PATCH 594/665] drivers-platform-x86: remove useless #ifdef CONFIG_ACPI_VIDEO Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/acer-wmi.c | 2 -- drivers/platform/x86/apple-gmux.c | 4 ---- drivers/platform/x86/asus-wmi.c | 4 ---- drivers/platform/x86/samsung-laptop.c | 4 ---- 4 files changed, 14 deletions(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 3782e1cd3697..934d861a3235 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -2196,10 +2196,8 @@ static int __init acer_wmi_init(void) interface->capability &= ~ACER_CAP_BRIGHTNESS; pr_info("Brightness must be controlled by acpi video driver\n"); } else { -#ifdef CONFIG_ACPI_VIDEO pr_info("Disabling ACPI video driver\n"); acpi_video_unregister(); -#endif } if (wmi_has_guid(WMID_GUID3)) { diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 5c17ba895692..db8f63841b42 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -511,9 +511,7 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, * Disable the other backlight choices. */ acpi_video_dmi_promote_vendor(); -#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_unregister(); -#endif apple_bl_unregister(); gmux_data->power_state = VGA_SWITCHEROO_ON; @@ -599,9 +597,7 @@ static void __devexit gmux_remove(struct pnp_dev *pnp) kfree(gmux_data); acpi_video_dmi_demote_vendor(); -#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_register(); -#endif apple_bl_register(); } diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 2eb9fe8e8efd..c0e9ff489b24 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -47,9 +47,7 @@ #include #include #include -#ifdef CONFIG_ACPI_VIDEO #include -#endif #include "asus-wmi.h" @@ -1704,10 +1702,8 @@ static int asus_wmi_add(struct platform_device *pdev) if (asus->driver->quirks->wmi_backlight_power) acpi_video_dmi_promote_vendor(); if (!acpi_video_backlight_support()) { -#ifdef CONFIG_ACPI_VIDEO pr_info("Disabling ACPI video driver\n"); acpi_video_unregister(); -#endif err = asus_wmi_backlight_init(asus); if (err && err != -ENODEV) goto fail_backlight; diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index c1ca7bcebb66..dd90d15f5210 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -26,9 +26,7 @@ #include #include #include -#ifdef CONFIG_ACPI_VIDEO #include -#endif /* * This driver is needed because a number of Samsung laptops do not hook @@ -1558,9 +1556,7 @@ static int __init samsung_init(void) samsung->handle_backlight = false; } else if (samsung->quirks->broken_acpi_video) { pr_info("Disabling ACPI video driver\n"); -#ifdef CONFIG_ACPI_VIDEO acpi_video_unregister(); -#endif } #endif From 8871e99f89b7d7b1ea99de550eea2a56273f42ab Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 20 Aug 2012 23:01:51 +0200 Subject: [PATCH 595/665] asus-laptop: HRWS/HWRS typo Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=24222 Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index e38f91be0b10..110c7778cbf9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev, * The significance of others is yet to be found. * If we don't find the method, we assume the device are present. */ - rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "HRWS value : %#x\n", + len += sprintf(page + len, "HWRS value : %#x\n", (uint) temp); /* * Another value for userspace: the ASYM method returns 0x02 for @@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) * The significance of others is yet to be found. */ status = - acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); + acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); if (!ACPI_FAILURE(status)) - pr_notice(" HRWS returned %x", (int)hwrs_result); + pr_notice(" HWRS returned %x", (int)hwrs_result); if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; From 3f5449bf39896587ca9f87b76832c5aa30f0f5c7 Mon Sep 17 00:00:00 2001 From: Maxim Nikulin Date: Mon, 20 Aug 2012 23:01:52 +0200 Subject: [PATCH 596/665] platform/x86: fix asus_laptop.wled_type description MODULE_PARM_DESC for wlan_status is further in the same file Signed-off-by: Maxim A. Nikulin Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 110c7778cbf9..4b568df56643 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -85,7 +85,7 @@ static char *wled_type = "unknown"; static char *bled_type = "unknown"; module_param(wled_type, charp, 0444); -MODULE_PARM_DESC(wlan_status, "Set the wled type on boot " +MODULE_PARM_DESC(wled_type, "Set the wled type on boot " "(unknown, led or rfkill). " "default is unknown"); From f661848b74b33069b0b7068c414bd282c407781d Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 14 Sep 2012 00:21:59 +0800 Subject: [PATCH 597/665] eeepc-laptop: fix device reference count leakage in eeepc_rfkill_hotplug() Fix a device reference count leakage issue in function eeepc_rfkill_hotplug(). Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Signed-off-by: Matthew Garrett --- drivers/platform/x86/eeepc-laptop.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index dab91b48d22c..5ca264179f4e 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -610,12 +610,12 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) if (!bus) { pr_warn("Unable to find PCI bus 1?\n"); - goto out_unlock; + goto out_put_dev; } if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) { pr_err("Unable to read PCI config space?\n"); - goto out_unlock; + goto out_put_dev; } absent = (l == 0xffffffff); @@ -627,7 +627,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) absent ? "absent" : "present"); pr_warn("skipped wireless hotplug as probably " "inappropriate for this model\n"); - goto out_unlock; + goto out_put_dev; } if (!blocked) { @@ -635,7 +635,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) if (dev) { /* Device already present */ pci_dev_put(dev); - goto out_unlock; + goto out_put_dev; } dev = pci_scan_single_device(bus, 0); if (dev) { @@ -650,6 +650,8 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) pci_dev_put(dev); } } +out_put_dev: + pci_dev_put(port); } out_unlock: From eceeb4371240aff22e9a535a2bc57d2311820942 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 1 Sep 2012 12:54:07 -0700 Subject: [PATCH 598/665] thinkpad_acpi: buffer overflow in fan_get_status() The acpi_evalf() function modifies four bytes of data but in fan_get_status() we pass a pointer to u8. I have modified the function to use type checking now. Signed-off-by: Dan Carpenter Signed-off-by: Matthew Garrett --- drivers/platform/x86/thinkpad_acpi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 80e377949314..52daaa816e53 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -545,7 +545,7 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */ */ static int acpi_evalf(acpi_handle handle, - void *res, char *method, char *fmt, ...) + int *res, char *method, char *fmt, ...) { char *fmt0 = fmt; struct acpi_object_list params; @@ -606,7 +606,7 @@ static int acpi_evalf(acpi_handle handle, success = (status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER); if (success && res) - *(int *)res = out_obj.integer.value; + *res = out_obj.integer.value; break; case 'v': /* void */ success = status == AE_OK; @@ -7386,17 +7386,18 @@ static int fan_get_status(u8 *status) * Add TPACPI_FAN_RD_ACPI_FANS ? */ switch (fan_status_access_mode) { - case TPACPI_FAN_RD_ACPI_GFAN: + case TPACPI_FAN_RD_ACPI_GFAN: { /* 570, 600e/x, 770e, 770x */ + int res; - if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) + if (unlikely(!acpi_evalf(gfan_handle, &res, NULL, "d"))) return -EIO; if (likely(status)) - *status = s & 0x07; + *status = res & 0x07; break; - + } case TPACPI_FAN_RD_TPEC: /* all except 570, 600e/x, 770e, 770x */ if (unlikely(!acpi_ec_read(fan_status_offset, &s))) From 6af773e786ad617b0264ebe06ba60675c01f3e51 Mon Sep 17 00:00:00 2001 From: Nishank Trivedi Date: Wed, 12 Sep 2012 13:32:49 +0000 Subject: [PATCH 599/665] pktgen: fix crash with vlan and packet size less than 46 If vlan option is being specified in the pktgen and packet size being requested is less than 46 bytes, despite being illogical request, pktgen should not crash the kernel. BUG: unable to handle kernel paging request at ffff88021fb82000 Process kpktgend_0 (pid: 1184, threadinfo ffff880215f1a000, task ffff880218544530) Call Trace: [] ? pktgen_finalize_skb+0x222/0x300 [pktgen] [] ? build_skb+0x34/0x1c0 [] pktgen_thread_worker+0x5d1/0x1790 [pktgen] [] ? igb_xmit_frame_ring+0xa30/0xa30 [igb] [] ? wake_up_bit+0x40/0x40 [] ? wake_up_bit+0x40/0x40 [] ? spin+0x240/0x240 [pktgen] [] kthread+0x93/0xa0 [] kernel_thread_helper+0x4/0x10 [] ? flush_kthread_worker+0x80/0x80 [] ? gs_change+0x13/0x13 The root cause of why pktgen is not able to handle this case is due to comparison of signed (datalen) and unsigned data (sizeof), which eventually passes a huge number to skb_put(). Signed-off-by: Nishank Trivedi Signed-off-by: David S. Miller --- net/core/pktgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index cce9e53528b1..148e73d2c451 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2721,7 +2721,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, /* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - pkt_dev->pkt_overhead; - if (datalen < sizeof(struct pktgen_hdr)) + if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) datalen = sizeof(struct pktgen_hdr); udph->source = htons(pkt_dev->cur_udp_src); From 8f7412a792bc989d1bddd3c802282eec09456d57 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 14 Sep 2012 00:26:24 +0200 Subject: [PATCH 600/665] ACPI / PM: Infer parent power state from child if unknown, v2 It turns out that there are ACPI BIOSes defining device objects with _PSx and without either _PSC or _PRx. For devices corresponding to those ACPI objetcs __acpi_bus_get_power() returns ACPI_STATE_UNKNOWN and their initial power states are regarded as unknown as a result. If such a device is a parent of another power-manageable device, the child cannot be put into a low-power state through ACPI, because __acpi_bus_set_power() refuses to change power states of devices whose parents' power states are unknown. To work around this problem, observe that the ACPI power state of a device cannot be higher-power (lower-number) than the power state of its parent. Thus, if the device's _PSC method or the configuration of its power resources indicates that the device is in D0, the device's parent has to be in D0 as well. Consequently, if the parent's power state is unknown when we've just learned that its child's power state is D0, we can safely set the parent's power.state field to ACPI_STATE_D0. Tested-by: Aaron Lu Cc: stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9628652e080c..e0596954290b 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -237,6 +237,16 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state) } else if (result == ACPI_STATE_D3_HOT) { result = ACPI_STATE_D3; } + + /* + * If we were unsure about the device parent's power state up to this + * point, the fact that the device is in D0 implies that the parent has + * to be in D0 too. + */ + if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN + && result == ACPI_STATE_D0) + device->parent->power.state = ACPI_STATE_D0; + *state = result; out: From 40bf66ec9791f1452b90b82aadc3b6e6aee201f5 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 14 Sep 2012 00:26:33 +0200 Subject: [PATCH 601/665] ACPI / PM: Fix resource_lock dead lock in acpi_power_on_device Commit 0090def("ACPI: Add interface to register/unregister device to/from power resources") used resource_lock to protect the devices list that relies on power resource. It caused a mutex dead lock, as below acpi_power_on ---> lock resource_lock __acpi_power_on acpi_power_on_device acpi_power_get_inferred_state acpi_power_get_list_state ---> lock resource_lock This patch adds a new mutex "devices_lock" to protect the devices list and calls acpi_power_on_device in acpi_power_on, instead of __acpi_power_on, after the resource_lock is released. [rjw: Changed data type of a boolean variable to bool.] Signed-off-by: Lin Ming Signed-off-by: Aaron Lu Cc: stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fc1803414629..cc2a2dcff336 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -107,6 +107,7 @@ struct acpi_power_resource { /* List of devices relying on this power resource */ struct acpi_power_resource_device *devices; + struct mutex devices_lock; }; static struct list_head acpi_power_resource_list; @@ -225,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) static int __acpi_power_on(struct acpi_power_resource *resource) { - struct acpi_power_resource_device *device_list = resource->devices; acpi_status status = AE_OK; status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); @@ -238,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); - while (device_list) { - acpi_power_on_device(device_list->device); - - device_list = device_list->next; - } - return 0; } static int acpi_power_on(acpi_handle handle) { int result = 0; + bool resume_device = false; struct acpi_power_resource *resource = NULL; + struct acpi_power_resource_device *device_list; result = acpi_power_get_context(handle, &resource); if (result) @@ -266,10 +262,25 @@ static int acpi_power_on(acpi_handle handle) result = __acpi_power_on(resource); if (result) resource->ref_count--; + else + resume_device = true; } mutex_unlock(&resource->resource_lock); + if (!resume_device) + return result; + + mutex_lock(&resource->devices_lock); + + device_list = resource->devices; + while (device_list) { + acpi_power_on_device(device_list->device); + device_list = device_list->next; + } + + mutex_unlock(&resource->devices_lock); + return result; } @@ -355,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, if (acpi_power_get_context(res_handle, &resource)) return; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); prev = NULL; curr = resource->devices; while (curr) { @@ -372,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, prev = curr; curr = curr->next; } - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); } /* Unlink dev from all power resources in _PR0 */ @@ -414,10 +425,10 @@ static int __acpi_power_resource_register_device( power_resource_device->device = powered_device; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); power_resource_device->next = resource->devices; resource->devices = power_resource_device; - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); return 0; } @@ -721,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device) resource->device = device; mutex_init(&resource->resource_lock); + mutex_init(&resource->devices_lock); strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); From 610bd7da160f76f1644ecb4cd7f39511b49a22cc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 14 Sep 2012 13:28:23 +1000 Subject: [PATCH 602/665] drm/nouveau: fix booting with plymouth + dumb support We noticed a plymouth bug on Fedora 18, and I then noticed this stupid thinko, fixing it fixed the problem with plymouth. Cc: stable@vger.kernel.org Acked-by: Ben Skeggs Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 69688ef5cf46..7e16dc5e6467 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -598,7 +598,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, args->size = args->pitch * args->height; args->size = roundup(args->size, PAGE_SIZE); - ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); + ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo); if (ret) return ret; From 4a5b2b269e2780790687cfc7c2fc438cb6d8964e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 12 Sep 2012 18:03:26 +0200 Subject: [PATCH 603/665] MAINTAINERS: fix tree for current i2c-embedded development Guide people to where their patches can be found these days. Signed-off-by: Wolfram Sang Acked-by: Jean Delvare Acked-by: Ben Dooks --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fdc0119963e7..53cc13c82cb1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3388,7 +3388,7 @@ M: "Wolfram Sang (embedded platforms)" L: linux-i2c@vger.kernel.org W: http://i2c.wiki.kernel.org/ T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/ -T: git git://git.fluff.org/bjdooks/linux.git +T: git git://git.pengutronix.de/git/wsa/linux.git S: Maintained F: Documentation/i2c/ F: drivers/i2c/ From 5f71a3ef3753ac2068009637eee619e163f44b30 Mon Sep 17 00:00:00 2001 From: Thomas Kavanagh Date: Thu, 13 Sep 2012 08:16:55 -0700 Subject: [PATCH 604/665] i2c: algo: pca: Fix mode selection for PCA9665 The code currently always selects turbo mode for PCA9665, no matter which clock frequency is configured. This is because it compares the clock frequency against constants reflecting (boundary / 100). Compare against real boundary frequencies to fix the problem. Signed-off-by: Thomas Kavanagh Signed-off-by: Guenter Roeck Signed-off-by: Wolfram Sang --- drivers/i2c/algos/i2c-algo-pca.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 73133b1063f0..6f5f98d69af7 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -476,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap) /* To avoid integer overflow, use clock/100 for calculations */ clock = pca_clock(pca_data) / 100; - if (pca_data->i2c_clock > 10000) { + if (pca_data->i2c_clock > 1000000) { mode = I2C_PCA_MODE_TURBO; min_tlow = 14; min_thi = 5; raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 4000) { + } else if (pca_data->i2c_clock > 400000) { mode = I2C_PCA_MODE_FASTP; min_tlow = 17; min_thi = 9; raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 1000) { + } else if (pca_data->i2c_clock > 100000) { mode = I2C_PCA_MODE_FAST; min_tlow = 44; min_thi = 20; From 7149f2558d5b5b988726662fe58b1c388337805b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 12 Sep 2012 18:02:46 -0700 Subject: [PATCH 605/665] eCryptfs: Write out all dirty pages just before releasing the lower file Fixes a regression caused by: 821f749 eCryptfs: Revert to a writethrough cache model That patch reverted some code (specifically, 32001d6f) that was necessary to properly handle open() -> mmap() -> close() -> dirty pages -> munmap(), because the lower file could be closed before the dirty pages are written out. Rather than reapplying 32001d6f, this approach is a better way of ensuring that the lower file is still open in order to handle writing out the dirty pages. It is called from ecryptfs_release(), while we have a lock on the lower file pointer, just before the lower file gets the final fput() and we overwrite the pointer. https://launchpad.net/bugs/1047261 Signed-off-by: Tyler Hicks Reported-by: Artemy Tregubenko Tested-by: Artemy Tregubenko Tested-by: Colin Ian King --- fs/ecryptfs/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 2768138eefee..9b627c15010a 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode) inode_info = ecryptfs_inode_to_private(inode); if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, &inode_info->lower_file_mutex)) { + filemap_write_and_wait(inode->i_mapping); fput(inode_info->lower_file); inode_info->lower_file = NULL; mutex_unlock(&inode_info->lower_file_mutex); From 64e6651dcc10e9d2cc6230208a8e6c2cfd19ae18 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 12 Sep 2012 18:38:00 -0700 Subject: [PATCH 606/665] eCryptfs: Call lower ->flush() from ecryptfs_flush() Since eCryptfs only calls fput() on the lower file in ecryptfs_release(), eCryptfs should call the lower filesystem's ->flush() from ecryptfs_flush(). If the lower filesystem implements ->flush(), then eCryptfs should try to flush out any dirty pages prior to calling the lower ->flush(). If the lower filesystem does not implement ->flush(), then eCryptfs has no need to do anything in ecryptfs_flush() since dirty pages are now written out to the lower filesystem in ecryptfs_release(). Signed-off-by: Tyler Hicks --- fs/ecryptfs/file.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 44ce5c6a541d..d45ba4568128 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -275,8 +275,14 @@ out: static int ecryptfs_flush(struct file *file, fl_owner_t td) { - return file->f_mode & FMODE_WRITE - ? filemap_write_and_wait(file->f_mapping) : 0; + struct file *lower_file = ecryptfs_file_to_lower(file); + + if (lower_file->f_op && lower_file->f_op->flush) { + filemap_write_and_wait(file->f_mapping); + return lower_file->f_op->flush(lower_file, td); + } + + return 0; } static int ecryptfs_release(struct inode *inode, struct file *file) From 8335eafc2859e1a26282bef7c3d19f3d68868b8a Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Thu, 13 Sep 2012 12:00:56 -0700 Subject: [PATCH 607/665] eCryptfs: Copy up attributes of the lower target inode after rename After calling into the lower filesystem to do a rename, the lower target inode's attributes were not copied up to the eCryptfs target inode. This resulted in the eCryptfs target inode staying around, rather than being evicted, because i_nlink was not updated for the eCryptfs inode. This also meant that eCryptfs didn't do the final iput() on the lower target inode so it stayed around, as well. This would result in a failure to free up space occupied by the target file in the rename() operation. Both target inodes would eventually be evicted when the eCryptfs filesystem was unmounted. This patch calls fsstack_copy_attr_all() after the lower filesystem does its ->rename() so that important inode attributes, such as i_nlink, are updated at the eCryptfs layer. ecryptfs_evict_inode() is now called and eCryptfs can drop its final reference on the lower inode. http://launchpad.net/bugs/561129 Signed-off-by: Tyler Hicks Tested-by: Colin Ian King Cc: [2.6.39+] --- fs/ecryptfs/inode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 534b129ea676..cc7709e7c508 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -619,6 +619,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct dentry *lower_old_dir_dentry; struct dentry *lower_new_dir_dentry; struct dentry *trap = NULL; + struct inode *target_inode; lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); @@ -626,6 +627,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, dget(lower_new_dentry); lower_old_dir_dentry = dget_parent(lower_old_dentry); lower_new_dir_dentry = dget_parent(lower_new_dentry); + target_inode = new_dentry->d_inode; trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); /* source should not be ancestor of target */ if (trap == lower_old_dentry) { @@ -641,6 +643,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, lower_new_dir_dentry->d_inode, lower_new_dentry); if (rc) goto out_lock; + if (target_inode) + fsstack_copy_attr_all(target_inode, + ecryptfs_inode_to_lower(target_inode)); fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); if (new_dir != old_dir) fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); From 985b11fa8064d55d0d5a84e68667434598911bb2 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Fri, 14 Sep 2012 16:09:09 +0800 Subject: [PATCH 608/665] ASoC: wm8904: correct the index Signed-off-by: Bo Shen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 0013afe48e66..dc4262eea4b7 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -100,7 +100,7 @@ static const struct reg_default wm8904_reg_defaults[] = { { 14, 0x0000 }, /* R14 - Power Management 2 */ { 15, 0x0000 }, /* R15 - Power Management 3 */ { 18, 0x0000 }, /* R18 - Power Management 6 */ - { 19, 0x945E }, /* R20 - Clock Rates 0 */ + { 20, 0x945E }, /* R20 - Clock Rates 0 */ { 21, 0x0C05 }, /* R21 - Clock Rates 1 */ { 22, 0x0006 }, /* R22 - Clock Rates 2 */ { 24, 0x0050 }, /* R24 - Audio Interface 0 */ From f25b70613c048ceb1df052576fda03321ebf41cf Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 14 Sep 2012 20:54:44 +0200 Subject: [PATCH 609/665] ACPI / PM: Use KERN_DEBUG when no power resources are found commit a606dac368eed5696fb38e16b1394f1d049c09e9 adds support to link devices which have _PRx, if a device does not have _PRx, a warning message will be printed. This commit is for ZPODD on Intel ZPODD capable platforms, on other platforms, it has no problem if there is no power resource for this device, so a warning here is not appropriate, change it to debug. Reported-by: Borislav Petkov Signed-off-by: Aaron Lu Cc: stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index cc2a2dcff336..40e38a06ba85 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -473,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) return ret; no_power_resource: - printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); + printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); return -ENODEV; } EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); From 55815f70147dcfa3ead5738fd56d3574e2e3c1c2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 14 Sep 2012 14:48:21 -0700 Subject: [PATCH 610/665] vfs: make O_PATH file descriptors usable for 'fstat()' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already use them for openat() and friends, but fstat() also wants to be able to use O_PATH file descriptors. This should make it more directly comparable to the O_SEARCH of Solaris. Note that you could already do the same thing with "fstatat()" and an empty path, but just doing "fstat()" directly is simpler and faster, so there is no reason not to just allow it directly. See also commit 332a2e1244bd, which did the same thing for fchdir, for the same reasons. Reported-by: ольга крыжановская Cc: Al Viro Cc: stable@kernel.org # O_PATH introduced in 3.0+ Signed-off-by: Linus Torvalds --- fs/stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/stat.c b/fs/stat.c index b6ff11825fc8..40780229a032 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -58,7 +58,7 @@ EXPORT_SYMBOL(vfs_getattr); int vfs_fstat(unsigned int fd, struct kstat *stat) { int fput_needed; - struct file *f = fget_light(fd, &fput_needed); + struct file *f = fget_raw_light(fd, &fput_needed); int error = -EBADF; if (f) { From f3a87f1b0c4086a408eda48e4c26e32ff80d3124 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 14 Sep 2012 20:06:30 -0400 Subject: [PATCH 611/665] Revert "Btrfs: fix some error codes in btrfs_qgroup_inherit()" This reverts commit 5986802c2fcc754040bb7ed95f30bb16c4a843b7. Both paths are not error paths but regular cases where non-qgroup subvols are involved. Signed-off-by: Chris Mason --- fs/btrfs/qgroup.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 38b42e7bc91d..b65015581744 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1371,10 +1371,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, if (srcid) { srcgroup = find_qgroup_rb(fs_info, srcid); - if (!srcgroup) { - ret = -EINVAL; + if (!srcgroup) goto unlock; - } dstgroup->rfer = srcgroup->rfer - level_size; dstgroup->rfer_cmpr = srcgroup->rfer_cmpr - level_size; srcgroup->excl = level_size; @@ -1383,10 +1381,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, qgroup_dirty(fs_info, srcgroup); } - if (!inherit) { - ret = -EINVAL; + if (!inherit) goto unlock; - } i_qgroups = (u64 *)(inherit + 1); for (i = 0; i < inherit->num_qgroups; ++i) { From 0848c94fb4a5cc213a7fb0fb3a5721ad6e16f096 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 15:16:36 +0800 Subject: [PATCH 612/665] mfd: core: Push irqdomain mapping out into devices Currently the MFD core supports remapping MFD cell interrupts using an irqdomain but only if the MFD is being instantiated using device tree and only if the device tree bindings use the pattern of registering IPs in the device tree with compatible properties. This will be actively harmful for drivers which support non-DT platforms and use this pattern for their DT bindings as it will mean that the core will silently change remapping behaviour and it is also limiting for drivers which don't do DT with this particular pattern. There is also a potential fragility if there are interrupts not associated with MFD cells and all the cells are omitted from the device tree for some reason. Instead change the code to take an IRQ domain as an optional argument, allowing drivers to take the decision about the parent domain for their interrupts. The one current user of this feature is ab8500-core, it has the domain lookup pushed out into the driver. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 5 +++-- drivers/mfd/88pm805.c | 3 ++- drivers/mfd/88pm860x-core.c | 21 +++++++++++---------- drivers/mfd/aat2870-core.c | 2 +- drivers/mfd/ab3100-core.c | 2 +- drivers/mfd/ab8500-core.c | 10 +++++----- drivers/mfd/arizona-core.c | 6 +++--- drivers/mfd/asic3.c | 6 +++--- drivers/mfd/cs5535-mfd.c | 2 +- drivers/mfd/da9052-core.c | 2 +- drivers/mfd/davinci_voicecodec.c | 2 +- drivers/mfd/db8500-prcmu.c | 2 +- drivers/mfd/htc-pasic3.c | 5 +++-- drivers/mfd/intel_msic.c | 4 ++-- drivers/mfd/janz-cmodio.c | 2 +- drivers/mfd/jz4740-adc.c | 3 ++- drivers/mfd/lm3533-core.c | 7 ++++--- drivers/mfd/lpc_ich.c | 4 ++-- drivers/mfd/lpc_sch.c | 6 ++++-- drivers/mfd/max77686.c | 2 +- drivers/mfd/max77693.c | 2 +- drivers/mfd/max8925-core.c | 12 ++++++------ drivers/mfd/max8997.c | 2 +- drivers/mfd/max8998.c | 8 ++++---- drivers/mfd/mc13xxx-core.c | 2 +- drivers/mfd/mfd-core.c | 12 ++++++------ drivers/mfd/palmas.c | 3 ++- drivers/mfd/rc5t583.c | 2 +- drivers/mfd/rdc321x-southbridge.c | 3 ++- drivers/mfd/sec-core.c | 8 ++++---- drivers/mfd/sta2x11-mfd.c | 4 ++-- drivers/mfd/stmpe.c | 2 +- drivers/mfd/t7l66xb.c | 2 +- drivers/mfd/tc3589x.c | 8 ++++---- drivers/mfd/tc6387xb.c | 2 +- drivers/mfd/tc6393xb.c | 4 ++-- drivers/mfd/ti-ssp.c | 2 +- drivers/mfd/timberdale.c | 12 ++++++------ drivers/mfd/tps6105x.c | 2 +- drivers/mfd/tps6507x.c | 2 +- drivers/mfd/tps65090.c | 2 +- drivers/mfd/tps65217.c | 2 +- drivers/mfd/tps6586x.c | 3 ++- drivers/mfd/tps65910.c | 2 +- drivers/mfd/tps65912-core.c | 2 +- drivers/mfd/twl4030-audio.c | 2 +- drivers/mfd/twl6040-core.c | 2 +- drivers/mfd/vx855.c | 2 +- drivers/mfd/wl1273-core.c | 2 +- drivers/mfd/wm831x-core.c | 16 ++++++++-------- drivers/mfd/wm8400-core.c | 2 +- drivers/mfd/wm8994-core.c | 4 ++-- drivers/staging/nvec/nvec.c | 2 +- include/linux/mfd/core.h | 4 +++- 54 files changed, 125 insertions(+), 112 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index b67a3018b136..ce229ea933d1 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -470,7 +470,8 @@ static int __devinit device_800_init(struct pm80x_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], - ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0); + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, + NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -481,7 +482,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip, rtc_devs[0].platform_data = pdata->rtc; rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], - ARRAY_SIZE(rtc_devs), NULL, 0); + ARRAY_SIZE(rtc_devs), NULL, 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out_dev; diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 6146583589f6..c20a31136f04 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -216,7 +216,8 @@ static int __devinit device_805_init(struct pm80x_chip *chip) } ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0, + NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add codec subdev\n"); goto out_codec; diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index d09918cf1b15..b73f033b2c60 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -637,7 +637,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, bk_devs[i].resources = &bk_resources[j]; ret = mfd_add_devices(chip->dev, 0, &bk_devs[i], 1, - &bk_resources[j], 0); + &bk_resources[j], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add " "backlight subdev\n"); @@ -672,7 +672,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip, led_devs[i].resources = &led_resources[j], ret = mfd_add_devices(chip->dev, 0, &led_devs[i], 1, - &led_resources[j], 0); + &led_resources[j], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add " "led subdev\n"); @@ -709,7 +709,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip, regulator_devs[i].resources = ®ulator_resources[seq]; ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, - ®ulator_resources[seq], 0); + ®ulator_resources[seq], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out; @@ -733,7 +733,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip, rtc_devs[0].resources = &rtc_resources[0]; ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), &rtc_resources[0], - chip->irq_base); + chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add rtc subdev\n"); } @@ -752,7 +752,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip, touch_devs[0].resources = &touch_resources[0]; ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), &touch_resources[0], - chip->irq_base); + chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add touch subdev\n"); } @@ -770,7 +770,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[0].num_resources = ARRAY_SIZE(battery_resources); power_devs[0].resources = &battery_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, - &battery_resources[0], chip->irq_base); + &battery_resources[0], chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add battery subdev\n"); @@ -779,7 +779,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[1].num_resources = ARRAY_SIZE(charger_resources); power_devs[1].resources = &charger_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, - &charger_resources[0], chip->irq_base); + &charger_resources[0], chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add charger subdev\n"); @@ -788,7 +788,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[2].num_resources = ARRAY_SIZE(preg_resources); power_devs[2].resources = &preg_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, - &preg_resources[0], chip->irq_base); + &preg_resources[0], chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add preg subdev\n"); } @@ -802,7 +802,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip, onkey_devs[0].resources = &onkey_resources[0], ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), &onkey_resources[0], - chip->irq_base); + chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add onkey subdev\n"); } @@ -815,7 +815,8 @@ static void __devinit device_codec_init(struct pm860x_chip *chip, codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); codec_devs[0].resources = &codec_resources[0], ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0, + NULL); if (ret < 0) dev_err(chip->dev, "Failed to add codec subdev\n"); } diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 44a3fdbadef4..f1beb4971f87 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -424,7 +424,7 @@ static int aat2870_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs, - ARRAY_SIZE(aat2870_devs), NULL, 0); + ARRAY_SIZE(aat2870_devs), NULL, 0, NULL); if (ret != 0) { dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret); goto out_disable; diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 78fca2902c8d..01781ae5d0d7 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -946,7 +946,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, } err = mfd_add_devices(&client->dev, 0, ab3100_devs, - ARRAY_SIZE(ab3100_devs), NULL, 0); + ARRAY_SIZE(ab3100_devs), NULL, 0, NULL); ab3100_setup_debugfs(ab3100); diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 626b4ecaf647..47adf800024e 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1418,25 +1418,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev) ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, ARRAY_SIZE(abx500_common_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) goto out_freeirq; if (is_ab9540(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, ARRAY_SIZE(ab9540_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); else ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, ARRAY_SIZE(ab8500_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) goto out_freeirq; if (is_ab9540(ab8500) || is_ab8505(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, ARRAY_SIZE(ab9540_ab8505_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) goto out_freeirq; @@ -1444,7 +1444,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev) /* Add battery management devices */ ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, ARRAY_SIZE(ab8500_bm_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) dev_err(ab8500->dev, "error adding bm devices\n"); } diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index c7983e862549..1b48f2094806 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -316,7 +316,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) } ret = mfd_add_devices(arizona->dev, -1, early_devs, - ARRAY_SIZE(early_devs), NULL, 0); + ARRAY_SIZE(early_devs), NULL, 0, NULL); if (ret != 0) { dev_err(dev, "Failed to add early children: %d\n", ret); return ret; @@ -516,11 +516,11 @@ int __devinit arizona_dev_init(struct arizona *arizona) switch (arizona->type) { case WM5102: ret = mfd_add_devices(arizona->dev, -1, wm5102_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0); + ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); break; case WM5110: ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0); + ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); break; } diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 683e18a23329..62f0883a7630 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -913,14 +913,14 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, if (pdata->clock_rate) { ds1wm_pdata.clock_rate = pdata->clock_rate; ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_ds1wm, 1, mem, asic->irq_base); + &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL); if (ret < 0) goto out; } if (mem_sdio && (irq >= 0)) { ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_mmc, 1, mem_sdio, irq); + &asic3_cell_mmc, 1, mem_sdio, irq, NULL); if (ret < 0) goto out; } @@ -934,7 +934,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]); } ret = mfd_add_devices(&pdev->dev, 0, - asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0); + asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL); } out: diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index 3419e726de47..2b282133c725 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c @@ -149,7 +149,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev, } err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, - ARRAY_SIZE(cs5535_mfd_cells), NULL, 0); + ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL); if (err) { dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); goto err_disable; diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 2544910e1fd6..a0a62b24621b 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -803,7 +803,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret); ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, - ARRAY_SIZE(da9052_subdev_info), NULL, 0); + ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL); if (ret) goto err; diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 4e2af2cb2d26..45e83a68641b 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -129,7 +129,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) cell->pdata_size = sizeof(*davinci_vc); ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, - DAVINCI_VC_CELLS, NULL, 0); + DAVINCI_VC_CELLS, NULL, 0, NULL); if (ret != 0) { dev_err(&pdev->dev, "fail to register client devices\n"); goto fail4; diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 7040a0081130..0e63cdd9b52a 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3010,7 +3010,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, - ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); + ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL); if (err) { pr_err("prcmu: Failed to add subdevices\n"); return err; diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 04c7093d6499..9e5453d21a68 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -168,7 +168,7 @@ static int __init pasic3_probe(struct platform_device *pdev) /* the first 5 PASIC3 registers control the DS1WM */ ds1wm_resources[0].end = (5 << asic->bus_shift) - 1; ret = mfd_add_devices(&pdev->dev, pdev->id, - &ds1wm_cell, 1, r, irq); + &ds1wm_cell, 1, r, irq, NULL); if (ret < 0) dev_warn(dev, "failed to register DS1WM\n"); } @@ -176,7 +176,8 @@ static int __init pasic3_probe(struct platform_device *pdev) if (pdata && pdata->led_pdata) { led_cell.platform_data = pdata->led_pdata; led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); - ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); + ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, + 0, NULL); if (ret < 0) dev_warn(dev, "failed to register LED device\n"); } diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index 59df5584cb58..266bdc5bd96d 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -344,13 +344,13 @@ static int __devinit intel_msic_init_devices(struct intel_msic *msic) continue; ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL, - pdata->irq[i]); + pdata->irq[i], NULL); if (ret) goto fail; } ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs, - ARRAY_SIZE(msic_other_devs), NULL, 0); + ARRAY_SIZE(msic_other_devs), NULL, 0, NULL); if (ret) goto fail; diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 2ea99989551a..965c4801df8a 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -147,7 +147,7 @@ static int __devinit cmodio_probe_submodules(struct cmodio_device *priv) } return mfd_add_devices(&pdev->dev, 0, priv->cells, - num_probed, NULL, pdev->irq); + num_probed, NULL, pdev->irq, NULL); } /* diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 87662a17dec6..c6b6d7dda517 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -287,7 +287,8 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) writeb(0xff, adc->base + JZ_REG_ADC_CTRL); ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, - ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base); + ARRAY_SIZE(jz4740_adc_cells), mem_base, + irq_base, NULL); if (ret < 0) goto err_clk_put; diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c index 0b2879b87fd9..24212f45b201 100644 --- a/drivers/mfd/lm3533-core.c +++ b/drivers/mfd/lm3533-core.c @@ -393,7 +393,8 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533) lm3533_als_devs[0].platform_data = pdata->als; lm3533_als_devs[0].pdata_size = sizeof(*pdata->als); - ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0); + ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, + 0, NULL); if (ret) { dev_err(lm3533->dev, "failed to add ALS device\n"); return ret; @@ -422,7 +423,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs, - pdata->num_backlights, NULL, 0); + pdata->num_backlights, NULL, 0, NULL); if (ret) { dev_err(lm3533->dev, "failed to add backlight devices\n"); return ret; @@ -451,7 +452,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs, - pdata->num_leds, NULL, 0); + pdata->num_leds, NULL, 0, NULL); if (ret) { dev_err(lm3533->dev, "failed to add LED devices\n"); return ret; diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index a05fdfc2ebcf..092ad4b44b6d 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -750,7 +750,7 @@ gpe0_done: lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], - 1, NULL, 0); + 1, NULL, 0, NULL); gpio_done: if (acpi_conflict) @@ -807,7 +807,7 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], - 1, NULL, 0); + 1, NULL, 0, NULL); wdt_done: return ret; diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index 9f20abc5e393..f6b9c5c96b24 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c @@ -127,7 +127,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, lpc_sch_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, - lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); + lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, + 0, NULL); if (ret) goto out_dev; @@ -153,7 +154,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, tunnelcreek_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, - ARRAY_SIZE(tunnelcreek_cells), NULL, 0); + ARRAY_SIZE(tunnelcreek_cells), NULL, + 0, NULL); } return ret; diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index c03e12b51924..d9e24c849a00 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -126,7 +126,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686_irq_init(max77686); ret = mfd_add_devices(max77686->dev, -1, max77686_devs, - ARRAY_SIZE(max77686_devs), NULL, 0); + ARRAY_SIZE(max77686_devs), NULL, 0, NULL); if (ret < 0) goto err_mfd; diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index a1811cb50ec7..4fdd03d28539 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -159,7 +159,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, pm_runtime_set_active(max77693->dev); ret = mfd_add_devices(max77693->dev, -1, max77693_devs, - ARRAY_SIZE(max77693_devs), NULL, 0); + ARRAY_SIZE(max77693_devs), NULL, 0, NULL); if (ret < 0) goto err_mfd; diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 825a7f06d9ba..ee53757beca7 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), - &rtc_resources[0], chip->irq_base); + &rtc_resources[0], chip->irq_base, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out; @@ -606,7 +606,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), - &onkey_resources[0], 0); + &onkey_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -615,7 +615,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata) { ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], ARRAY_SIZE(regulator_devs), - ®ulator_resources[0], 0); + ®ulator_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out_dev; @@ -625,7 +625,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->backlight) { ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0], ARRAY_SIZE(backlight_devs), - &backlight_resources[0], 0); + &backlight_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add backlight subdev\n"); goto out_dev; @@ -635,7 +635,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->power) { ret = mfd_add_devices(chip->dev, 0, &power_devs[0], ARRAY_SIZE(power_devs), - &power_supply_resources[0], 0); + &power_supply_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add power supply " "subdev\n"); @@ -646,7 +646,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->touch) { ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), - &touch_resources[0], 0); + &touch_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add touch subdev\n"); goto out_dev; diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 10b629c245b6..f123517065ec 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -160,7 +160,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c, mfd_add_devices(max8997->dev, -1, max8997_devs, ARRAY_SIZE(max8997_devs), - NULL, 0); + NULL, 0, NULL); /* * TODO: enable others (flash, muic, rtc, battery, ...) and diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 6ef56d28c056..d7218cc90945 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -161,13 +161,13 @@ static int max8998_i2c_probe(struct i2c_client *i2c, switch (id->driver_data) { case TYPE_LP3974: ret = mfd_add_devices(max8998->dev, -1, - lp3974_devs, ARRAY_SIZE(lp3974_devs), - NULL, 0); + lp3974_devs, ARRAY_SIZE(lp3974_devs), + NULL, 0, NULL); break; case TYPE_MAX8998: ret = mfd_add_devices(max8998->dev, -1, - max8998_devs, ARRAY_SIZE(max8998_devs), - NULL, 0); + max8998_devs, ARRAY_SIZE(max8998_devs), + NULL, 0, NULL); break; default: ret = -EINVAL; diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index b801dc72f041..1ec79b54bd2f 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -612,7 +612,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, if (!cell.name) return -ENOMEM; - return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0); + return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL); } static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 0c3a01cde2f7..f8b77711ad2d 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -74,12 +74,11 @@ static int mfd_platform_add_cell(struct platform_device *pdev, static int mfd_add_device(struct device *parent, int id, const struct mfd_cell *cell, struct resource *mem_base, - int irq_base) + int irq_base, struct irq_domain *domain) { struct resource *res; struct platform_device *pdev; struct device_node *np = NULL; - struct irq_domain *domain = NULL; int ret = -ENOMEM; int r; @@ -97,7 +96,6 @@ static int mfd_add_device(struct device *parent, int id, for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { pdev->dev.of_node = np; - domain = irq_find_host(parent->of_node); break; } } @@ -177,7 +175,7 @@ fail_alloc: int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base) + int irq_base, struct irq_domain *domain) { int i; int ret = 0; @@ -191,7 +189,8 @@ int mfd_add_devices(struct device *parent, int id, for (i = 0; i < n_devs; i++) { atomic_set(&cnts[i], 0); cells[i].usage_count = &cnts[i]; - ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); + ret = mfd_add_device(parent, id, cells + i, mem_base, + irq_base, domain); if (ret) break; } @@ -247,7 +246,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) for (i = 0; i < n_clones; i++) { cell_entry.name = clones[i]; /* don't give up if a single call fails; just report error */ - if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0)) + if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0, + NULL)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index c4a69f193a1d..a345f9bb7b47 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -453,7 +453,8 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(palmas->dev, -1, children, ARRAY_SIZE(palmas_children), - NULL, regmap_irq_chip_get_base(palmas->irq_data)); + NULL, regmap_irq_chip_get_base(palmas->irq_data), + NULL); kfree(children); if (ret < 0) diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c index cdc1df7fa0e9..3a8fa88567b1 100644 --- a/drivers/mfd/rc5t583.c +++ b/drivers/mfd/rc5t583.c @@ -289,7 +289,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c, } ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, - ARRAY_SIZE(rc5t583_subdevs), NULL, 0); + ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL); if (ret) { dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret); goto err_add_devs; diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 685d61e431ad..0f70dce61160 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c @@ -87,7 +87,8 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev, rdc321x_wdt_pdata.sb_pdev = pdev; return mfd_add_devices(&pdev->dev, -1, - rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0); + rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), + NULL, 0, NULL); } static void __devexit rdc321x_sb_remove(struct pci_dev *pdev) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 2988efde11eb..49d361a618d0 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -141,19 +141,19 @@ static int sec_pmic_probe(struct i2c_client *i2c, switch (sec_pmic->device_type) { case S5M8751X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, - ARRAY_SIZE(s5m8751_devs), NULL, 0); + ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL); break; case S5M8763X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, - ARRAY_SIZE(s5m8763_devs), NULL, 0); + ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL); break; case S5M8767X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, - ARRAY_SIZE(s5m8767_devs), NULL, 0); + ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); break; case S2MPS11X: ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, - ARRAY_SIZE(s2mps11_devs), NULL, 0); + ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); break; default: /* If this happens the probe function is problem */ diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c index d31fed07aefb..d35da6820bea 100644 --- a/drivers/mfd/sta2x11-mfd.c +++ b/drivers/mfd/sta2x11-mfd.c @@ -407,7 +407,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar0, ARRAY_SIZE(sta2x11_mfd_bar0), &pdev->resource[0], - 0); + 0, NULL); if (err) { dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err); goto err_disable; @@ -417,7 +417,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar1, ARRAY_SIZE(sta2x11_mfd_bar1), &pdev->resource[1], - 0); + 0, NULL); if (err) { dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err); goto err_disable; diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 2dd8d49cb30b..c94f521f392c 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -962,7 +962,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell, int irq) { return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, - NULL, stmpe->irq_base + irq); + NULL, stmpe->irq_base + irq, NULL); } static int __devinit stmpe_devices_init(struct stmpe *stmpe) diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 2d9e8799e733..b32940ec9034 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -388,7 +388,7 @@ static int t7l66xb_probe(struct platform_device *dev) ret = mfd_add_devices(&dev->dev, dev->id, t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), - iomem, t7l66xb->irq_base); + iomem, t7l66xb->irq_base, NULL); if (!ret) return 0; diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 048bf0532a09..b56ba6b43294 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -262,8 +262,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_GPIO) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, - ARRAY_SIZE(tc3589x_dev_gpio), NULL, - tc3589x->irq_base); + ARRAY_SIZE(tc3589x_dev_gpio), NULL, + tc3589x->irq_base, NULL); if (ret) { dev_err(tc3589x->dev, "failed to add gpio child\n"); return ret; @@ -273,8 +273,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_KEYPAD) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, - ARRAY_SIZE(tc3589x_dev_keypad), NULL, - tc3589x->irq_base); + ARRAY_SIZE(tc3589x_dev_keypad), NULL, + tc3589x->irq_base, NULL); if (ret) { dev_err(tc3589x->dev, "failed to keypad child\n"); return ret; diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index d20a284ad4ba..413c891102f8 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -192,7 +192,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev) printk(KERN_INFO "Toshiba tc6387xb initialised\n"); ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, - ARRAY_SIZE(tc6387xb_cells), iomem, irq); + ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL); if (!ret) return 0; diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 9612264f0e6d..dcab026fcbb2 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -700,8 +700,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data); ret = mfd_add_devices(&dev->dev, dev->id, - tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), - iomem, tcpd->irq_base); + tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), + iomem, tcpd->irq_base, NULL); if (!ret) return 0; diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c index 4fb0e6c8e8fe..7c3675a74f93 100644 --- a/drivers/mfd/ti-ssp.c +++ b/drivers/mfd/ti-ssp.c @@ -412,7 +412,7 @@ static int __devinit ti_ssp_probe(struct platform_device *pdev) cells[id].data_size = data->pdata_size; } - error = mfd_add_devices(dev, 0, cells, 2, NULL, 0); + error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL); if (error < 0) { dev_err(dev, "cannot add mfd cells\n"); goto error_enable; diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index a447f4ec11fb..cccc626c83c8 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -757,25 +757,25 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg0, ARRAY_SIZE(timberdale_cells_bar0_cfg0), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; case TIMB_HW_VER1: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg1, ARRAY_SIZE(timberdale_cells_bar0_cfg1), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; case TIMB_HW_VER2: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg2, ARRAY_SIZE(timberdale_cells_bar0_cfg2), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; case TIMB_HW_VER3: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg3, ARRAY_SIZE(timberdale_cells_bar0_cfg3), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; default: dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n", @@ -792,7 +792,7 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, 0, timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1), - &dev->resource[1], msix_entries[0].vector); + &dev->resource[1], msix_entries[0].vector, NULL); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; @@ -803,7 +803,7 @@ static int __devinit timb_probe(struct pci_dev *dev, ((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) { err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2, ARRAY_SIZE(timberdale_cells_bar2), - &dev->resource[2], msix_entries[0].vector); + &dev->resource[2], msix_entries[0].vector, NULL); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index a293b978e27c..14051bdc714b 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -188,7 +188,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, - ARRAY_SIZE(tps6105x_cells), NULL, 0); + ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL); if (ret) goto fail; diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 33ba7723c967..1b203499c744 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -100,7 +100,7 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, ARRAY_SIZE(tps6507x_devs), - NULL, 0); + NULL, 0, NULL); if (ret < 0) goto err; diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index 80e24f4b47bf..50fd87c87a1c 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -292,7 +292,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps65090->dev, -1, tps65090s, - ARRAY_SIZE(tps65090s), NULL, 0); + ARRAY_SIZE(tps65090s), NULL, 0, NULL); if (ret) { dev_err(&client->dev, "add mfd devices failed with err: %d\n", ret); diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 3bc274409b58..a95e9421b735 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -191,7 +191,7 @@ static int __devinit tps65217_probe(struct i2c_client *client, } ret = mfd_add_devices(tps->dev, -1, tps65217s, - ARRAY_SIZE(tps65217s), NULL, 0); + ARRAY_SIZE(tps65217s), NULL, 0, NULL); if (ret < 0) { dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); return ret; diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 353c34812120..5f58370ccf55 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -493,7 +493,8 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps6586x->dev, -1, - tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0); + tps6586x_cell, ARRAY_SIZE(tps6586x_cell), + NULL, 0, NULL); if (ret < 0) { dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret); goto err_mfd_add; diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 1c563792c777..d3ce4d569deb 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -254,7 +254,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps65910->dev, -1, tps65910s, ARRAY_SIZE(tps65910s), - NULL, 0); + NULL, 0, NULL); if (ret < 0) { dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret); return ret; diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index 74fd8cb5f372..4658b5bdcd84 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -146,7 +146,7 @@ int tps65912_device_init(struct tps65912 *tps65912) ret = mfd_add_devices(tps65912->dev, -1, tps65912s, ARRAY_SIZE(tps65912s), - NULL, 0); + NULL, 0, NULL); if (ret < 0) goto err; diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index 838ce4eb444e..77c9acb14583 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c @@ -223,7 +223,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev) if (childs) ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells, - childs, NULL, 0); + childs, NULL, 0, NULL); else { dev_err(&pdev->dev, "No platform data found for childs\n"); ret = -ENODEV; diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index b0fad0ffca56..3dca5c195a20 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -632,7 +632,7 @@ static int __devinit twl6040_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, - NULL, 0); + NULL, 0, NULL); if (ret) goto mfd_err; diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c index 872aff21e4be..b9a636d44c7f 100644 --- a/drivers/mfd/vx855.c +++ b/drivers/mfd/vx855.c @@ -102,7 +102,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev, vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3; ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells), - NULL, 0); + NULL, 0, NULL); /* we always return -ENODEV here in order to enable other * drivers like old, not-yet-platform_device ported i2c-viapro */ diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index f39b756df561..86e0e4309fc2 100644 --- a/drivers/mfd/wl1273-core.c +++ b/drivers/mfd/wl1273-core.c @@ -241,7 +241,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, __func__, children); r = mfd_add_devices(&client->dev, -1, core->cells, - children, NULL, 0); + children, NULL, 0, NULL); if (r) goto err; diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 946698fd2dc6..301731035940 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8310: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8310_devs, ARRAY_SIZE(wm8310_devs), - NULL, 0); + NULL, 0, NULL); break; case WM8311: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8311_devs, ARRAY_SIZE(wm8311_devs), - NULL, 0); + NULL, 0, NULL); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0); + NULL, 0, NULL); break; case WM8312: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8312_devs, ARRAY_SIZE(wm8312_devs), - NULL, 0); + NULL, 0, NULL); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0); + NULL, 0, NULL); break; case WM8320: @@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8326: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8320_devs, ARRAY_SIZE(wm8320_devs), - NULL, 0); + NULL, 0, NULL); break; default: @@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) if (ret & WM831X_XTAL_ENA) { ret = mfd_add_devices(wm831x->dev, wm831x_num, rtc_devs, ARRAY_SIZE(rtc_devs), - NULL, 0); + NULL, 0, NULL); if (ret != 0) { dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); goto err_irq; @@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) /* Treat errors as non-critical */ ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, ARRAY_SIZE(backlight_devs), NULL, - 0); + 0, NULL); if (ret < 0) dev_err(wm831x->dev, "Failed to add backlight: %d\n", ret); diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 4b7d378551d5..639ca359242f 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) .pdata_size = sizeof(*wm8400), }; - return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); + return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); } /* diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index eec74aa55fdf..2febf88cfce8 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -414,7 +414,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_regulator_devs, ARRAY_SIZE(wm8994_regulator_devs), - NULL, 0); + NULL, 0, NULL); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err; @@ -648,7 +648,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_devs, ARRAY_SIZE(wm8994_devs), - NULL, 0); + NULL, 0, NULL); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err_irq; diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 695ea35f75b0..d0a7e408efe9 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -837,7 +837,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) } ret = mfd_add_devices(nvec->dev, -1, nvec_devices, - ARRAY_SIZE(nvec_devices), base, 0); + ARRAY_SIZE(nvec_devices), base, 0, NULL); if (ret) dev_err(nvec->dev, "error adding subdevices\n"); diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 3a8435a8058f..cebe97ee98b8 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -16,6 +16,8 @@ #include +struct irq_domain; + /* * This struct describes the MFD part ("cell"). * After registration the copy of this structure will become the platform data @@ -98,7 +100,7 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) extern int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base); + int irq_base, struct irq_domain *irq_domain); extern void mfd_remove_devices(struct device *parent); From d51f42d2c5b7e11b47876b8b5c53f0ac317fef24 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 21 Aug 2012 15:15:52 +0900 Subject: [PATCH 613/665] mfd: MAX77693: Fix interrupt handling bug This patch fix bug related to interrupt handling for MAX77693 devices. - Unmask interrupt masking bit for charger/flash/muic to revolve that interrupt isn't happened when external connector is attached. - Fix wrong regmap instance when muic interrupt is happened. This patch were discussed and confirm discussion about this patch on below url: http://lkml.org/lkml/2012/7/16/118 Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park Acked-by: Greg Kroah-Hartman Signed-off-by: Samuel Ortiz --- drivers/mfd/max77693-irq.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c index 2b403569e0a6..1029d018c739 100644 --- a/drivers/mfd/max77693-irq.c +++ b/drivers/mfd/max77693-irq.c @@ -137,6 +137,9 @@ static void max77693_irq_mask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); + if (irq_data->group >= MAX77693_IRQ_GROUP_NR) + return; + if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; else @@ -149,6 +152,9 @@ static void max77693_irq_unmask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); + if (irq_data->group >= MAX77693_IRQ_GROUP_NR) + return; + if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; else @@ -200,7 +206,7 @@ static irqreturn_t max77693_irq_thread(int irq, void *data) if (irq_src & MAX77693_IRQSRC_MUIC) /* MUIC INT1 ~ INT3 */ - max77693_bulk_read(max77693->regmap, MAX77693_MUIC_REG_INT1, + max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1, MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]); /* Apply masking */ @@ -255,7 +261,8 @@ int max77693_irq_init(struct max77693_dev *max77693) { struct irq_domain *domain; int i; - int ret; + int ret = 0; + u8 intsrc_mask; mutex_init(&max77693->irqlock); @@ -287,19 +294,38 @@ int max77693_irq_init(struct max77693_dev *max77693) &max77693_irq_domain_ops, max77693); if (!domain) { dev_err(max77693->dev, "could not create irq domain\n"); - return -ENODEV; + ret = -ENODEV; + goto err_irq; } max77693->irq_domain = domain; + /* Unmask max77693 interrupt */ + ret = max77693_read_reg(max77693->regmap, + MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask); + if (ret < 0) { + dev_err(max77693->dev, "fail to read PMIC register\n"); + goto err_irq; + } + + intsrc_mask &= ~(MAX77693_IRQSRC_CHG); + intsrc_mask &= ~(MAX77693_IRQSRC_FLASH); + intsrc_mask &= ~(MAX77693_IRQSRC_MUIC); + ret = max77693_write_reg(max77693->regmap, + MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask); + if (ret < 0) { + dev_err(max77693->dev, "fail to write PMIC register\n"); + goto err_irq; + } + ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max77693-irq", max77693); - if (ret) dev_err(max77693->dev, "Failed to request IRQ %d: %d\n", max77693->irq, ret); - return 0; +err_irq: + return ret; } void max77693_irq_exit(struct max77693_dev *max77693) From b186b12487efc80c44f2f0d26cc26eb249cf1524 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 21 Aug 2012 15:16:23 +0900 Subject: [PATCH 614/665] mfd: MAX77693: Fix NULL pointer error when initializing irqs This patch initialize register map of MUIC device because mfd driver of Maxim MAX77693 use regmap-muic instance of MUIC device when irqs of Maxim MAX77693 is initialized before call max77693-muic probe() function. Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park Reported-by: Sylwester Nawrocki Acked-by: Greg Kroah-Hartman Signed-off-by: Samuel Ortiz --- drivers/extcon/extcon-max77693.c | 19 ++++++++++++------- drivers/mfd/max77693.c | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 920a609b2c35..38f9e52f358b 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -669,13 +669,18 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) } info->dev = &pdev->dev; info->max77693 = max77693; - info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic, - &max77693_muic_regmap_config); - if (IS_ERR(info->max77693->regmap_muic)) { - ret = PTR_ERR(info->max77693->regmap_muic); - dev_err(max77693->dev, - "failed to allocate register map: %d\n", ret); - goto err_regmap; + if (info->max77693->regmap_muic) + dev_dbg(&pdev->dev, "allocate register map\n"); + else { + info->max77693->regmap_muic = devm_regmap_init_i2c( + info->max77693->muic, + &max77693_muic_regmap_config); + if (IS_ERR(info->max77693->regmap_muic)) { + ret = PTR_ERR(info->max77693->regmap_muic); + dev_err(max77693->dev, + "failed to allocate register map: %d\n", ret); + goto err_regmap; + } } platform_set_drvdata(pdev, info); mutex_init(&info->mutex); diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 4fdd03d28539..cc5155e20494 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -152,6 +152,20 @@ static int max77693_i2c_probe(struct i2c_client *i2c, max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); i2c_set_clientdata(max77693->haptic, max77693); + /* + * Initialize register map for MUIC device because use regmap-muic + * instance of MUIC device when irq of max77693 is initialized + * before call max77693-muic probe() function. + */ + max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic, + &max77693_regmap_config); + if (IS_ERR(max77693->regmap_muic)) { + ret = PTR_ERR(max77693->regmap_muic); + dev_err(max77693->dev, + "failed to allocate register map: %d\n", ret); + goto err_regmap; + } + ret = max77693_irq_init(max77693); if (ret < 0) goto err_irq; From 37407ea7f93864c2cfc03edf8f37872ec539ea2b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Sep 2012 12:29:43 -0700 Subject: [PATCH 615/665] Revert "sched: Improve scalability via 'CPU buddies', which withstand random perturbations" This reverts commit 970e178985cadbca660feb02f4d2ee3a09f7fdda. Nikolay Ulyanitsky reported thatthe 3.6-rc5 kernel has a 15-20% performance drop on PostgreSQL 9.2 on his machine (running "pgbench"). Borislav Petkov was able to reproduce this, and bisected it to this commit 970e178985ca ("sched: Improve scalability via 'CPU buddies' ...") apparently because the new single-idle-buddy model simply doesn't find idle CPU's to reschedule on aggressively enough. Mike Galbraith suspects that it is likely due to the user-mode spinlocks in PostgreSQL not reacting well to preemption, but we don't really know the details - I'll just revert the commit for now. There are hopefully other approaches to improve scheduler scalability without it causing these kinds of downsides. Reported-by: Nikolay Ulyanitsky Bisected-by: Borislav Petkov Acked-by: Mike Galbraith Cc: Andrew Morton Cc: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: Linus Torvalds --- include/linux/sched.h | 1 - kernel/sched/core.c | 39 +-------------------------------------- kernel/sched/fair.c | 28 +++++++++++++++++++++------- 3 files changed, 22 insertions(+), 46 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index b8c86648a2f9..23bddac4bad8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -954,7 +954,6 @@ struct sched_domain { unsigned int smt_gain; int flags; /* See SD_* */ int level; - int idle_buddy; /* cpu assigned to select_idle_sibling() */ /* Runtime fields. */ unsigned long last_balance; /* init to jiffies. units in jiffies */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a4ea245f3d85..649c9f876cb1 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6014,11 +6014,6 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu) * SD_SHARE_PKG_RESOURCE set (Last Level Cache Domain) for this * allows us to avoid some pointer chasing select_idle_sibling(). * - * Iterate domains and sched_groups downward, assigning CPUs to be - * select_idle_sibling() hw buddy. Cross-wiring hw makes bouncing - * due to random perturbation self canceling, ie sw buddies pull - * their counterpart to their CPU's hw counterpart. - * * Also keep a unique ID per domain (we use the first cpu number in * the cpumask of the domain), this allows us to quickly tell if * two cpus are in the same cache domain, see cpus_share_cache(). @@ -6032,40 +6027,8 @@ static void update_top_cache_domain(int cpu) int id = cpu; sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES); - if (sd) { - struct sched_domain *tmp = sd; - struct sched_group *sg, *prev; - bool right; - - /* - * Traverse to first CPU in group, and count hops - * to cpu from there, switching direction on each - * hop, never ever pointing the last CPU rightward. - */ - do { - id = cpumask_first(sched_domain_span(tmp)); - prev = sg = tmp->groups; - right = 1; - - while (cpumask_first(sched_group_cpus(sg)) != id) - sg = sg->next; - - while (!cpumask_test_cpu(cpu, sched_group_cpus(sg))) { - prev = sg; - sg = sg->next; - right = !right; - } - - /* A CPU went down, never point back to domain start. */ - if (right && cpumask_first(sched_group_cpus(sg->next)) == id) - right = false; - - sg = right ? sg->next : prev; - tmp->idle_buddy = cpumask_first(sched_group_cpus(sg)); - } while ((tmp = tmp->child)); - + if (sd) id = cpumask_first(sched_domain_span(sd)); - } rcu_assign_pointer(per_cpu(sd_llc, cpu), sd); per_cpu(sd_llc_id, cpu) = id; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 42d9df6a5ca4..96e2b18b6283 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2637,6 +2637,8 @@ static int select_idle_sibling(struct task_struct *p, int target) int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); struct sched_domain *sd; + struct sched_group *sg; + int i; /* * If the task is going to be woken-up on this cpu and if it is @@ -2653,17 +2655,29 @@ static int select_idle_sibling(struct task_struct *p, int target) return prev_cpu; /* - * Otherwise, check assigned siblings to find an elegible idle cpu. + * Otherwise, iterate the domains and find an elegible idle cpu. */ sd = rcu_dereference(per_cpu(sd_llc, target)); - for_each_lower_domain(sd) { - if (!cpumask_test_cpu(sd->idle_buddy, tsk_cpus_allowed(p))) - continue; - if (idle_cpu(sd->idle_buddy)) - return sd->idle_buddy; - } + sg = sd->groups; + do { + if (!cpumask_intersects(sched_group_cpus(sg), + tsk_cpus_allowed(p))) + goto next; + for_each_cpu(i, sched_group_cpus(sg)) { + if (!idle_cpu(i)) + goto next; + } + + target = cpumask_first_and(sched_group_cpus(sg), + tsk_cpus_allowed(p)); + goto done; +next: + sg = sg->next; + } while (sg != sd->groups); + } +done: return target; } From 5698bd757d55b1bb87edd1a9744ab09c142abfc2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Sep 2012 14:58:51 -0700 Subject: [PATCH 616/665] Linux 3.6-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0f66f146d57e..ae6928cc59d3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Saber-toothed Squirrel # *DOCUMENTATION* From d41789b2660e5b18b8401bf83ebcd502916c2cb5 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 17 Sep 2012 13:34:31 +0800 Subject: [PATCH 617/665] ASoC: mx27vis: retrieve gpio numbers from platform_data Rather than including mach/iomux-mx27.h to define gpio numbers and set up the pins, the patch moves all these into machine code and has the gpio numbers passed to driver via platform_data. As the result, we can remove the mach/iomux-mx27.h inclusion from driver. Signed-off-by: Shawn Guo Acked-by: Javier Martin Signed-off-by: Mark Brown --- arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 42 ++++++++++++++++++++- include/linux/platform_data/asoc-mx27vis.h | 11 ++++++ sound/soc/fsl/mx27vis-aic32x4.c | 42 ++++++++++----------- 3 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 include/linux/platform_data/asoc-mx27vis.h diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index f264ddddd47c..562722959666 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,11 @@ #define EXPBOARD_BIT1 (GPIO_PORTD + 27) #define EXPBOARD_BIT0 (GPIO_PORTD + 28) +#define AMP_GAIN_0 (GPIO_PORTF + 9) +#define AMP_GAIN_1 (GPIO_PORTF + 8) +#define AMP_MUTE_SDL (GPIO_PORTE + 5) +#define AMP_MUTE_SDR (GPIO_PORTF + 7) + static const int visstrim_m10_pins[] __initconst = { /* UART1 (console) */ PE12_PF_UART1_TXD, @@ -139,6 +145,11 @@ static const int visstrim_m10_pins[] __initconst = { EXPBOARD_BIT2 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, EXPBOARD_BIT1 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, EXPBOARD_BIT0 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, + /* Audio AMP control */ + AMP_GAIN_0 | GPIO_GPIO | GPIO_OUT, + AMP_GAIN_1 | GPIO_GPIO | GPIO_OUT, + AMP_MUTE_SDL | GPIO_GPIO | GPIO_OUT, + AMP_MUTE_SDR | GPIO_GPIO | GPIO_OUT, }; static struct gpio visstrim_m10_version_gpios[] = { @@ -166,6 +177,26 @@ static const struct gpio visstrim_m10_gpios[] __initconst = { .flags = GPIOF_DIR_OUT | GPIOF_INIT_LOW, .label = "usbotg_cs", }, + { + .gpio = AMP_GAIN_0, + .flags = GPIOF_DIR_OUT, + .label = "amp-gain-0", + }, + { + .gpio = AMP_GAIN_1, + .flags = GPIOF_DIR_OUT, + .label = "amp-gain-1", + }, + { + .gpio = AMP_MUTE_SDL, + .flags = GPIOF_DIR_OUT, + .label = "amp-mute-sdl", + }, + { + .gpio = AMP_MUTE_SDR, + .flags = GPIOF_DIR_OUT, + .label = "amp-mute-sdr", + }, }; /* Camera */ @@ -405,6 +436,14 @@ static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = { .flags = IMX_SSI_DMA | IMX_SSI_SYN, }; +/* Audio */ +static const struct snd_mx27vis_platform_data snd_mx27vis_pdata __initconst = { + .amp_gain0_gpio = AMP_GAIN_0, + .amp_gain1_gpio = AMP_GAIN_1, + .amp_mutel_gpio = AMP_MUTE_SDL, + .amp_muter_gpio = AMP_MUTE_SDR, +}; + static void __init visstrim_m10_revision(void) { int exp_version = 0; @@ -463,7 +502,8 @@ static void __init visstrim_m10_board_init(void) imx27_add_fec(NULL); imx_add_gpio_keys(&visstrim_gpio_keys_platform_data); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); - imx_add_platform_device("mx27vis", 0, NULL, 0, NULL, 0); + imx_add_platform_device("mx27vis", 0, NULL, 0, &snd_mx27vis_pdata, + sizeof(snd_mx27vis_pdata)); platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0, &iclink_tvp5150, sizeof(iclink_tvp5150)); gpio_led_register_device(0, &visstrim_m10_led_data); diff --git a/include/linux/platform_data/asoc-mx27vis.h b/include/linux/platform_data/asoc-mx27vis.h new file mode 100644 index 000000000000..409adcd04d04 --- /dev/null +++ b/include/linux/platform_data/asoc-mx27vis.h @@ -0,0 +1,11 @@ +#ifndef __PLATFORM_DATA_ASOC_MX27VIS_H +#define __PLATFORM_DATA_ASOC_MX27VIS_H + +struct snd_mx27vis_platform_data { + int amp_gain0_gpio; + int amp_gain1_gpio; + int amp_mutel_gpio; + int amp_muter_gpio; +}; + +#endif /* __PLATFORM_DATA_ASOC_MX27VIS_H */ diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index f6d04ad4bb39..2b76877b1789 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c @@ -26,13 +26,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include "../codecs/tlv320aic32x4.h" #include "imx-ssi.h" @@ -41,20 +41,12 @@ #define MX27VIS_AMP_GAIN 0 #define MX27VIS_AMP_MUTE 1 -#define MX27VIS_PIN_G0 (GPIO_PORTF + 9) -#define MX27VIS_PIN_G1 (GPIO_PORTF + 8) -#define MX27VIS_PIN_SDL (GPIO_PORTE + 5) -#define MX27VIS_PIN_SDR (GPIO_PORTF + 7) - static int mx27vis_amp_gain; static int mx27vis_amp_mute; - -static const int mx27vis_amp_pins[] = { - MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT, -}; +static int mx27vis_amp_gain0_gpio; +static int mx27vis_amp_gain1_gpio; +static int mx27vis_amp_mutel_gpio; +static int mx27vis_amp_muter_gpio; static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -109,13 +101,13 @@ static int mx27vis_amp_set(struct snd_kcontrol *kcontrol, switch (reg) { case MX27VIS_AMP_GAIN: - gpio_set_value(MX27VIS_PIN_G0, value & 1); - gpio_set_value(MX27VIS_PIN_G1, value >> 1); + gpio_set_value(mx27vis_amp_gain0_gpio, value & 1); + gpio_set_value(mx27vis_amp_gain1_gpio, value >> 1); mx27vis_amp_gain = value; break; case MX27VIS_AMP_MUTE: - gpio_set_value(MX27VIS_PIN_SDL, value & 1); - gpio_set_value(MX27VIS_PIN_SDR, value >> 1); + gpio_set_value(mx27vis_amp_mutel_gpio, value & 1); + gpio_set_value(mx27vis_amp_muter_gpio, value >> 1); mx27vis_amp_mute = value; break; } @@ -190,8 +182,19 @@ static struct snd_soc_card mx27vis_aic32x4 = { static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) { + struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data; int ret; + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + + mx27vis_amp_gain0_gpio = pdata->amp_gain0_gpio; + mx27vis_amp_gain1_gpio = pdata->amp_gain1_gpio; + mx27vis_amp_mutel_gpio = pdata->amp_mutel_gpio; + mx27vis_amp_muter_gpio = pdata->amp_muter_gpio; + mx27vis_aic32x4.dev = &pdev->dev; ret = snd_soc_register_card(&mx27vis_aic32x4); if (ret) { @@ -213,11 +216,6 @@ static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) ); - ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, - ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP"); - if (ret) - printk(KERN_ERR "ASoC: unable to setup gpios\n"); - return ret; } From 13c57e5b868b4f023f6436d8c6a079eaffd7f3a8 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 14 Sep 2012 16:14:34 -0500 Subject: [PATCH 618/665] ASoC: fsl: use snd_soc_register_card to register the card Use snd_soc_register_card() instead of platform_device_alloc("soc-audio") to register the sound card from the machine drivers. The use of platform_device_alloc is deprecated. Although several other drivers still use platform_device_alloc(), the Freescale drivers were not using it to pass driver data. Instead of fixing the driver data usage, it's better to replace the deprecated code. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/mpc8610_hpcd.c | 34 ++++++++-------------------------- sound/soc/fsl/p1022_ds.c | 31 ++++++------------------------- 2 files changed, 14 insertions(+), 51 deletions(-) diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 60bcba1bc30e..9ff9318c52b9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -192,7 +192,6 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) container_of(dev, struct platform_device, dev); struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; - struct platform_device *sound_device = NULL; struct mpc8610_hpcd_data *machine_data; int ret = -ENODEV; const char *sprop; @@ -341,34 +340,22 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) machine_data->card.probe = mpc8610_hpcd_machine_probe; machine_data->card.remove = mpc8610_hpcd_machine_remove; machine_data->card.name = pdev->name; /* The platform driver name */ + machine_data->card.owner = THIS_MODULE; + machine_data->card.dev = &pdev->dev; machine_data->card.num_links = 2; machine_data->card.dai_link = machine_data->dai; - /* Allocate a new audio platform device structure */ - sound_device = platform_device_alloc("soc-audio", -1); - if (!sound_device) { - dev_err(&pdev->dev, "platform device alloc failed\n"); - ret = -ENOMEM; + /* Register with ASoC */ + ret = snd_soc_register_card(&machine_data->card); + if (ret) { + dev_err(&pdev->dev, "could not register card\n"); goto error; } - /* Associate the card data with the sound device */ - platform_set_drvdata(sound_device, &machine_data->card); - - /* Register with ASoC */ - ret = platform_device_add(sound_device); - if (ret) { - dev_err(&pdev->dev, "platform device add failed\n"); - goto error_sound; - } - dev_set_drvdata(&pdev->dev, sound_device); - of_node_put(codec_np); return 0; -error_sound: - platform_device_put(sound_device); error: kfree(machine_data); error_alloc: @@ -383,17 +370,12 @@ error_alloc: */ static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) { - struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); - struct snd_soc_card *card = platform_get_drvdata(sound_device); + struct snd_soc_card *card = platform_get_drvdata(pdev); struct mpc8610_hpcd_data *machine_data = container_of(card, struct mpc8610_hpcd_data, card); - platform_device_unregister(sound_device); - + snd_soc_unregister_card(card); kfree(machine_data); - sound_device->dev.platform_data = NULL; - - dev_set_drvdata(&pdev->dev, NULL); return 0; } diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 50adf4032bcc..144d49603637 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -202,7 +202,6 @@ static int p1022_ds_probe(struct platform_device *pdev) container_of(dev, struct platform_device, dev); struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; - struct platform_device *sound_device = NULL; struct machine_data *mdata; int ret = -ENODEV; const char *sprop; @@ -349,36 +348,23 @@ static int p1022_ds_probe(struct platform_device *pdev) mdata->card.probe = p1022_ds_machine_probe; mdata->card.remove = p1022_ds_machine_remove; mdata->card.name = pdev->name; /* The platform driver name */ + mdata->card.owner = THIS_MODULE; + mdata->card.dev = &pdev->dev; mdata->card.num_links = 2; mdata->card.dai_link = mdata->dai; - /* Allocate a new audio platform device structure */ - sound_device = platform_device_alloc("soc-audio", -1); - if (!sound_device) { - dev_err(&pdev->dev, "platform device alloc failed\n"); - ret = -ENOMEM; - goto error; - } - - /* Associate the card data with the sound device */ - platform_set_drvdata(sound_device, &mdata->card); - /* Register with ASoC */ - ret = platform_device_add(sound_device); + ret = snd_soc_register_card(&mdata->card); if (ret) { - dev_err(&pdev->dev, "platform device add failed\n"); + dev_err(&pdev->dev, "could not register card\n"); goto error; } - dev_set_drvdata(&pdev->dev, sound_device); of_node_put(codec_np); return 0; error: - if (sound_device) - platform_device_put(sound_device); - kfree(mdata); error_put: of_node_put(codec_np); @@ -392,17 +378,12 @@ error_put: */ static int __devexit p1022_ds_remove(struct platform_device *pdev) { - struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); - struct snd_soc_card *card = platform_get_drvdata(sound_device); + struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = container_of(card, struct machine_data, card); - platform_device_unregister(sound_device); - + snd_soc_unregister_card(card); kfree(mdata); - sound_device->dev.platform_data = NULL; - - dev_set_drvdata(&pdev->dev, NULL); return 0; } From d55438beb2329493cb54df5175d83be65a8d5100 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 14 Sep 2012 16:14:36 -0500 Subject: [PATCH 619/665] ASoC: fsl: remove unnecessary call to dma_unmap_single Remove a call to dma_unmap_single() from the PowerPC ASoC DMA driver. The buffer is allocated and not actually mapped, so the unmap call doesn't make sense. It was probably left over from some early version of the driver. This bug was unnoticed for so long because the DMA mapping functions normally don't do anything on PowerPC. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 96bb92dd174c..6feb26500580 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -823,12 +823,6 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) if (dma_private->irq) free_irq(dma_private->irq, dma_private); - if (dma_private->ld_buf_phys) { - dma_unmap_single(dev, dma_private->ld_buf_phys, - sizeof(dma_private->link), - DMA_TO_DEVICE); - } - /* Deallocate the fsl_dma_private structure */ dma_free_coherent(dev, sizeof(struct fsl_dma_private), dma_private, dma_private->ld_buf_phys); From 4c2474c007867c102c96482f3bacb1fdf209958c Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 14 Sep 2012 16:14:37 -0500 Subject: [PATCH 620/665] ASoC: wm8960: add support for big-endian audio samples PowerPC ASoC drivers frequently use the _BE variants of the SNDRV_PCM_FORMAT macros, so we need to look for those as well. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 7cb0d07ca8a6..066250e3f7f4 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -557,18 +557,25 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; + snd_pcm_format_t format = params_format(params); int i; /* bit size */ - switch (params_format(params)) { + switch (format) { case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: break; case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S20_3BE: iface |= 0x0004; break; case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_BE: iface |= 0x0008; break; + default: + dev_err(codec->dev, "unsupported format %i\n", format); + return -EINVAL; } /* Update filters for the new rate */ From 86767b7d5b3cdbd105e7d7066d671b52aa208188 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 14 Sep 2012 13:57:27 +0200 Subject: [PATCH 621/665] ASoC: Avoid recalculating the bitmask for SOC_ENUM controls For ENUM controls the bitmask is calculated based on the number of items. Currently this is done each time the control is accessed. And while the performance impact of this should be negligible we can easily do better. The roundup_pow_of_two macro performs the same calculation which is currently done manually, but it is also possible to use this macro with compile time constants and so it can be used to initialize static data. So we can use it to initialize the mask field of a ENUM control during its declaration. Signed-off-by: Lars-Peter Clausen Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown --- include/sound/soc.h | 4 +++- sound/soc/codecs/twl4030.c | 8 +++----- sound/soc/soc-core.c | 16 ++++++---------- sound/soc/soc-dapm.c | 22 ++++++++-------------- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 313b7660562c..91244a096c19 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -160,7 +161,8 @@ .platform_max = xmax} } #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .max = xmax, .texts = xtexts } + .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) \ diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 391fcfc7b63b..2548f5c56885 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -999,7 +999,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *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, bitmask; + unsigned short mask; if (twl4030->configured) { dev_err(codec->dev, @@ -1007,18 +1007,16 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, return -EBUSY; } - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << 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) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; + mask |= e->mask << e->shift_r; } return snd_soc_update_bits(codec, e->reg, mask, val); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e5b0713e6f3c..9a6daf997319 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2413,16 +2413,14 @@ 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, bitmask; + unsigned int val; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; val = snd_soc_read(codec, e->reg); ucontrol->value.enumerated.item[0] - = (val >> e->shift_l) & (bitmask - 1); + = (val >> e->shift_l) & e->mask; if (e->shift_l != e->shift_r) ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & (bitmask - 1); + (val >> e->shift_r) & e->mask; return 0; } @@ -2443,19 +2441,17 @@ 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 val; - unsigned int mask, bitmask; + unsigned int mask; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << 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) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; + mask |= e->mask << e->shift_r; } return snd_soc_update_bits_locked(codec, e->reg, mask, val); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f7999e949acb..a18d115bc507 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -355,12 +355,10 @@ 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, bitmask; + int val, item; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; val = soc_widget_read(w, e->reg); - item = (val >> e->shift_l) & (bitmask - 1); + item = (val >> e->shift_l) & e->mask; p->connect = 0; for (i = 0; i < e->max; i++) { @@ -2677,15 +2675,13 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, bitmask; + unsigned int val; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; val = snd_soc_read(widget->codec, e->reg); - ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); + 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) & (bitmask - 1); + (val >> e->shift_r) & e->mask; return 0; } @@ -2709,22 +2705,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *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, bitmask; + unsigned int mask; struct snd_soc_dapm_update update; int wi; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = mux << e->shift_l; - mask = (bitmask - 1) << 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) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; + mask |= e->mask << e->shift_r; } mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); From d37777a13b4c4b32e274013846d739e5bbbf6f8d Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 18 Sep 2012 17:20:05 +0800 Subject: [PATCH 622/665] ASoC: imx-pcm-dma: check kzalloc return value in function snd_imx_open It fixed smatch warning: sound/soc/fsl/imx-pcm-dma.c:112 snd_imx_open() error: potential null dereference 'dma_data'. (kzalloc returns null) Signed-off-by: Richard Zhao Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-dma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 48f9d886f020..a23505a9ae64 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c @@ -109,6 +109,9 @@ static int snd_imx_open(struct snd_pcm_substream *substream) dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); + if (!dma_data) + return -ENOMEM; + dma_data->peripheral_type = dma_params->shared_peripheral ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI; dma_data->priority = DMA_PRIO_HIGH; From f31e08e160d646952a5142e3f92f3fcdc645a09b Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 18 Sep 2012 17:20:06 +0800 Subject: [PATCH 623/665] ASoC: imx-pcm-dma: open function failed when snd_dmaengine_pcm_open fail snd_imx_open should return error code returned by snd_dmaengine_pcm_open. Signed-off-by: Richard Zhao Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index a23505a9ae64..9a15bc4bd570 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c @@ -120,7 +120,7 @@ static int snd_imx_open(struct snd_pcm_substream *substream) ret = snd_dmaengine_pcm_open(substream, filter, dma_data); if (ret) { kfree(dma_data); - return 0; + return ret; } snd_dmaengine_pcm_set_data(substream, dma_data); From f3a50c95e275c2e553e2a6dcc646eef3daf98a3e Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 18 Sep 2012 16:38:30 +0800 Subject: [PATCH 624/665] ASoC: imx-audmux: remove null check of audmux_base in audmux_read_file When audmux_read_file is called, it means the driver is already initialised successfully, so we don't need to check audmux_base. It also fix smatch warning: sound/soc/fsl/imx-audmux.c:78 audmux_read_file() warn: possible memory leak of 'buf' Signed-off-by: Richard Zhao Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index e7c800ebbd75..524ce6210cee 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -74,9 +74,6 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; - if (!audmux_base) - return -ENOSYS; - if (audmux_clk) clk_prepare_enable(audmux_clk); From f515b67381de0a4a28d639e0f1bb587a3a49f0d2 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 13 Sep 2012 17:43:11 -0400 Subject: [PATCH 625/665] ASoC: fsl: mpc5200 combine psc_dma platform data The mpc5200_psc_ac97 and mpc5200_psc_i2s modules rely on shared platform data with mpc5200_dma. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_dma.c | 24 ++++-------------------- sound/soc/fsl/mpc5200_dma.h | 3 +++ sound/soc/fsl/mpc5200_psc_ac97.c | 5 +++++ sound/soc/fsl/mpc5200_psc_i2s.c | 5 +++++ 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 9a3f7c5ab687..9997c039bb24 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -370,7 +370,7 @@ static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { .pcm_free = &psc_dma_free, }; -static int mpc5200_hpcd_probe(struct platform_device *op) +int mpc5200_audio_dma_create(struct platform_device *op) { phys_addr_t fifo; struct psc_dma *psc_dma; @@ -487,8 +487,9 @@ out_unmap: iounmap(regs); return ret; } +EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); -static int mpc5200_hpcd_remove(struct platform_device *op) +int mpc5200_audio_dma_destroy(struct platform_device *op) { struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); @@ -510,24 +511,7 @@ static int mpc5200_hpcd_remove(struct platform_device *op) return 0; } - -static struct of_device_id mpc5200_hpcd_match[] = { - { .compatible = "fsl,mpc5200-pcm", }, - {} -}; -MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); - -static struct platform_driver mpc5200_hpcd_of_driver = { - .probe = mpc5200_hpcd_probe, - .remove = mpc5200_hpcd_remove, - .driver = { - .owner = THIS_MODULE, - .name = "mpc5200-pcm-audio", - .of_match_table = mpc5200_hpcd_match, - } -}; - -module_platform_driver(mpc5200_hpcd_of_driver); +EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); MODULE_AUTHOR("Grant Likely "); MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index a3c0cd5382fb..dff253fde29a 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -81,4 +81,7 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) return &psc_dma->playback; } +int mpc5200_audio_dma_create(struct platform_device *op); +int mpc5200_audio_dma_destroy(struct platform_device *op); + #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index ffa00a2eb770..9a094535fb26 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -278,6 +278,10 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) struct snd_ac97 ac97; struct mpc52xx_psc __iomem *regs; + rc = mpc5200_audio_dma_create(op); + if (rc != 0) + return rc; + rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); if (rc != 0) { dev_err(&op->dev, "Failed to register DAI\n"); @@ -303,6 +307,7 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) static int __devexit psc_ac97_of_remove(struct platform_device *op) { + mpc5200_audio_dma_destroy(op); snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); return 0; } diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 7b530327553a..c0b7a23ebbfd 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -156,6 +156,10 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) struct psc_dma *psc_dma; struct mpc52xx_psc __iomem *regs; + rc = mpc5200_audio_dma_create(op); + if (rc != 0) + return rc; + rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); if (rc != 0) { pr_err("Failed to register DAI\n"); @@ -200,6 +204,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) static int __devexit psc_i2s_of_remove(struct platform_device *op) { + mpc5200_audio_dma_destroy(op); snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); return 0; } From a4f7b70dc73d611680a485150f2b11bcf23a2d01 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 13 Sep 2012 17:43:12 -0400 Subject: [PATCH 626/665] ASoC: fsl: mpc5200 add missing information to snd_soc_dai_driver Add missing dai_driver information to avoid these runtime errors [ 16.433788] asoc: error - multiple DAI f0002c00.i2s registered with no name [ 16.453551] Failed to register DAI [ 16.461222] mpc5200-psc-i2s: probe of f0002c00.i2s failed with error -22 [ 16.475242] asoc: error - multiple DAI f0002000.ac97 registered with no name [ 16.488087] mpc5200-psc-ac97 f0002000.ac97: Failed to register DAI [ 16.502222] mpc5200-psc-ac97: probe of f0002000.ac97 failed with error -22 Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_psc_ac97.c | 5 +++++ sound/soc/fsl/mpc5200_psc_i2s.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 9a094535fb26..a313c0ae36db 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -237,15 +237,18 @@ static const struct snd_soc_dai_ops psc_ac97_digital_ops = { static struct snd_soc_dai_driver psc_ac97_dai[] = { { + .name = "mpc5200-psc-ac97.0", .ac97_control = 1, .probe = psc_ac97_probe, .playback = { + .stream_name = "AC97 Playback", .channels_min = 1, .channels_max = 6, .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S32_BE, }, .capture = { + .stream_name = "AC97 Capture", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000, @@ -254,8 +257,10 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = { .ops = &psc_ac97_analog_ops, }, { + .name = "mpc5200-psc-ac97.1", .ac97_control = 1, .playback = { + .stream_name = "AC97 SPDIF", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_32000 | \ diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index c0b7a23ebbfd..ba1f0a66358f 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -130,13 +130,16 @@ static const struct snd_soc_dai_ops psc_i2s_dai_ops = { }; static struct snd_soc_dai_driver psc_i2s_dai[] = {{ + .name = "mpc5200-psc-i2s.0", .playback = { + .stream_name = "I2S Playback", .channels_min = 2, .channels_max = 2, .rates = PSC_I2S_RATES, .formats = PSC_I2S_FORMATS, }, .capture = { + .stream_name = "I2S Capture", .channels_min = 2, .channels_max = 2, .rates = PSC_I2S_RATES, From 22bab8ceda6ea2885c6315d07c37b4ef69aefb0c Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 13 Sep 2012 17:43:13 -0400 Subject: [PATCH 627/665] ASoC: fsl: cleanup headers in pcm030-audio-fabric Remove unreferenced header files. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index b3af55dcde9d..1353e8fecd7b 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -12,22 +12,13 @@ #include #include -#include #include -#include #include #include -#include -#include -#include -#include -#include #include #include "mpc5200_dma.h" -#include "mpc5200_psc_ac97.h" -#include "../codecs/wm9712.h" #define DRV_NAME "pcm030-audio-fabric" From 2cbde7abfdd8c3e2c1293b7096477e8bcf10b755 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 20:15:22 +0800 Subject: [PATCH 628/665] ASoC: wm8776: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8776.c | 75 +++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 879c356a9045..c32249ddb2e0 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -37,18 +38,46 @@ enum wm8776_chip_type { /* codec private data */ struct wm8776_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; int sysclk[2]; }; -static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { - 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ - 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ - 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ - 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ - 0xa6, 0x01, 0x01 +static const struct reg_default wm8776_reg_defaults[] = { + { 0, 0x79 }, + { 1, 0x79 }, + { 2, 0x79 }, + { 3, 0xff }, + { 4, 0xff }, + { 5, 0xff }, + { 6, 0x00 }, + { 7, 0x90 }, + { 8, 0x00 }, + { 9, 0x00 }, + { 10, 0x22 }, + { 11, 0x22 }, + { 12, 0x22 }, + { 13, 0x08 }, + { 14, 0xcf }, + { 15, 0xcf }, + { 16, 0x7b }, + { 17, 0x00 }, + { 18, 0x32 }, + { 19, 0x00 }, + { 20, 0xa6 }, + { 21, 0x01 }, + { 22, 0x01 }, }; +static bool wm8776_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8776_RESET: + return true; + default: + return false; + } +} + static int wm8776_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, WM8776_RESET, 0); @@ -306,6 +335,8 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, static int wm8776_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); + switch (level) { case SND_SOC_BIAS_ON: break; @@ -313,7 +344,7 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); + regcache_sync(wm8776->regmap); /* Disable the global powerdown; DAPM does the rest */ snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); @@ -396,10 +427,9 @@ static int wm8776_resume(struct snd_soc_codec *codec) static int wm8776_probe(struct snd_soc_codec *codec) { - struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -434,9 +464,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .suspend = wm8776_suspend, .resume = wm8776_resume, .set_bias_level = wm8776_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8776_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8776_reg, .controls = wm8776_snd_controls, .num_controls = ARRAY_SIZE(wm8776_snd_controls), @@ -452,6 +479,18 @@ static const struct of_device_id wm8776_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8776_of_match); +static const struct regmap_config wm8776_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8776_RESET, + + .reg_defaults = wm8776_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8776_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8776_volatile, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8776_spi_probe(struct spi_device *spi) { @@ -463,7 +502,10 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi) if (wm8776 == NULL) return -ENOMEM; - wm8776->control_type = SND_SOC_SPI; + wm8776->regmap = devm_regmap_init_spi(spi, &wm8776_regmap); + if (IS_ERR(wm8776->regmap)) + return PTR_ERR(wm8776->regmap); + spi_set_drvdata(spi, wm8776); ret = snd_soc_register_codec(&spi->dev, @@ -501,8 +543,11 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, if (wm8776 == NULL) return -ENOMEM; + wm8776->regmap = devm_regmap_init_i2c(i2c, &wm8776_regmap); + if (IS_ERR(wm8776->regmap)) + return PTR_ERR(wm8776->regmap); + i2c_set_clientdata(i2c, wm8776); - wm8776->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); From 3706163140939bccd58fba739a9820f1d5eebeaf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Sep 2012 11:46:58 +0800 Subject: [PATCH 629/665] ASoC: wm8960: Support shared LRCLK If the LRCLK is shared and the WM8960 is clock master then we should enable the LRCM bit to tell the device that it should drive LRCLK when either ADC or DAC is enabled rather than separately driving the two LRCLKs. Signed-off-by: Mark Brown --- include/sound/wm8960.h | 2 ++ sound/soc/codecs/wm8960.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index 74e9a95529c5..b5a1ab9ebb4a 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h @@ -19,6 +19,8 @@ struct wm8960_data { bool capless; /* Headphone outputs configured in capless mode */ int dres; /* Discharge resistance for headphone outputs */ + + bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ }; #endif diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 066250e3f7f4..782faa0a3b49 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1036,6 +1036,7 @@ static const struct regmap_config wm8960_regmap = { static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + struct wm8960_data *pdata = dev_get_platdata(&i2c->dev); struct wm8960_priv *wm8960; int ret; @@ -1048,6 +1049,16 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, if (IS_ERR(wm8960->regmap)) return PTR_ERR(wm8960->regmap); + if (pdata && pdata->shared_lrclk) { + ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, + 0x4, 0x4); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to enable LRCM: %d\n", + ret); + return ret; + } + } + i2c_set_clientdata(i2c, wm8960); ret = snd_soc_register_codec(&i2c->dev, From 35ecf7cd96a79d92c1b8433c950a827a2a723db9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Sep 2012 12:53:59 +0800 Subject: [PATCH 630/665] ASoC: wm8961: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 426 ++++++++++++++------------------------ 1 file changed, 161 insertions(+), 265 deletions(-) diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 719fb69a17c8..4ea64d6e68e2 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -31,277 +32,158 @@ #define WM8961_MAX_REGISTER 0xFC -static u16 wm8961_reg_defaults[] = { - 0x009F, /* R0 - Left Input volume */ - 0x009F, /* R1 - Right Input volume */ - 0x0000, /* R2 - LOUT1 volume */ - 0x0000, /* R3 - ROUT1 volume */ - 0x0020, /* R4 - Clocking1 */ - 0x0008, /* R5 - ADC & DAC Control 1 */ - 0x0000, /* R6 - ADC & DAC Control 2 */ - 0x000A, /* R7 - Audio Interface 0 */ - 0x01F4, /* R8 - Clocking2 */ - 0x0000, /* R9 - Audio Interface 1 */ - 0x00FF, /* R10 - Left DAC volume */ - 0x00FF, /* R11 - Right DAC volume */ - 0x0000, /* R12 */ - 0x0000, /* R13 */ - 0x0040, /* R14 - Audio Interface 2 */ - 0x0000, /* R15 - Software Reset */ - 0x0000, /* R16 */ - 0x007B, /* R17 - ALC1 */ - 0x0000, /* R18 - ALC2 */ - 0x0032, /* R19 - ALC3 */ - 0x0000, /* R20 - Noise Gate */ - 0x00C0, /* R21 - Left ADC volume */ - 0x00C0, /* R22 - Right ADC volume */ - 0x0120, /* R23 - Additional control(1) */ - 0x0000, /* R24 - Additional control(2) */ - 0x0000, /* R25 - Pwr Mgmt (1) */ - 0x0000, /* R26 - Pwr Mgmt (2) */ - 0x0000, /* R27 - Additional Control (3) */ - 0x0000, /* R28 - Anti-pop */ - 0x0000, /* R29 */ - 0x005F, /* R30 - Clocking 3 */ - 0x0000, /* R31 */ - 0x0000, /* R32 - ADCL signal path */ - 0x0000, /* R33 - ADCR signal path */ - 0x0000, /* R34 */ - 0x0000, /* R35 */ - 0x0000, /* R36 */ - 0x0000, /* R37 */ - 0x0000, /* R38 */ - 0x0000, /* R39 */ - 0x0000, /* R40 - LOUT2 volume */ - 0x0000, /* R41 - ROUT2 volume */ - 0x0000, /* R42 */ - 0x0000, /* R43 */ - 0x0000, /* R44 */ - 0x0000, /* R45 */ - 0x0000, /* R46 */ - 0x0000, /* R47 - Pwr Mgmt (3) */ - 0x0023, /* R48 - Additional Control (4) */ - 0x0000, /* R49 - Class D Control 1 */ - 0x0000, /* R50 */ - 0x0003, /* R51 - Class D Control 2 */ - 0x0000, /* R52 */ - 0x0000, /* R53 */ - 0x0000, /* R54 */ - 0x0000, /* R55 */ - 0x0106, /* R56 - Clocking 4 */ - 0x0000, /* R57 - DSP Sidetone 0 */ - 0x0000, /* R58 - DSP Sidetone 1 */ - 0x0000, /* R59 */ - 0x0000, /* R60 - DC Servo 0 */ - 0x0000, /* R61 - DC Servo 1 */ - 0x0000, /* R62 */ - 0x015E, /* R63 - DC Servo 3 */ - 0x0010, /* R64 */ - 0x0010, /* R65 - DC Servo 5 */ - 0x0000, /* R66 */ - 0x0001, /* R67 */ - 0x0003, /* R68 - Analogue PGA Bias */ - 0x0000, /* R69 - Analogue HP 0 */ - 0x0060, /* R70 */ - 0x01FB, /* R71 - Analogue HP 2 */ - 0x0000, /* R72 - Charge Pump 1 */ - 0x0065, /* R73 */ - 0x005F, /* R74 */ - 0x0059, /* R75 */ - 0x006B, /* R76 */ - 0x0038, /* R77 */ - 0x000C, /* R78 */ - 0x000A, /* R79 */ - 0x006B, /* R80 */ - 0x0000, /* R81 */ - 0x0000, /* R82 - Charge Pump B */ - 0x0087, /* R83 */ - 0x0000, /* R84 */ - 0x005C, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 - Write Sequencer 1 */ - 0x0000, /* R88 - Write Sequencer 2 */ - 0x0000, /* R89 - Write Sequencer 3 */ - 0x0000, /* R90 - Write Sequencer 4 */ - 0x0000, /* R91 - Write Sequencer 5 */ - 0x0000, /* R92 - Write Sequencer 6 */ - 0x0000, /* R93 - Write Sequencer 7 */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 */ - 0x0000, /* R97 */ - 0x0000, /* R98 */ - 0x0000, /* R99 */ - 0x0000, /* R100 */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x0000, /* R104 */ - 0x0000, /* R105 */ - 0x0000, /* R106 */ - 0x0000, /* R107 */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 */ - 0x0000, /* R112 */ - 0x0000, /* R113 */ - 0x0000, /* R114 */ - 0x0000, /* R115 */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x0000, /* R128 */ - 0x0000, /* R129 */ - 0x0000, /* R130 */ - 0x0000, /* R131 */ - 0x0000, /* R132 */ - 0x0000, /* R133 */ - 0x0000, /* R134 */ - 0x0000, /* R135 */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0000, /* R140 */ - 0x0000, /* R141 */ - 0x0000, /* R142 */ - 0x0000, /* R143 */ - 0x0000, /* R144 */ - 0x0000, /* R145 */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x0000, /* R152 */ - 0x0000, /* R153 */ - 0x0000, /* R154 */ - 0x0000, /* R155 */ - 0x0000, /* R156 */ - 0x0000, /* R157 */ - 0x0000, /* R158 */ - 0x0000, /* R159 */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 */ - 0x0000, /* R164 */ - 0x0000, /* R165 */ - 0x0000, /* R166 */ - 0x0000, /* R167 */ - 0x0000, /* R168 */ - 0x0000, /* R169 */ - 0x0000, /* R170 */ - 0x0000, /* R171 */ - 0x0000, /* R172 */ - 0x0000, /* R173 */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 */ - 0x0000, /* R177 */ - 0x0000, /* R178 */ - 0x0000, /* R179 */ - 0x0000, /* R180 */ - 0x0000, /* R181 */ - 0x0000, /* R182 */ - 0x0000, /* R183 */ - 0x0000, /* R184 */ - 0x0000, /* R185 */ - 0x0000, /* R186 */ - 0x0000, /* R187 */ - 0x0000, /* R188 */ - 0x0000, /* R189 */ - 0x0000, /* R190 */ - 0x0000, /* R191 */ - 0x0000, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0000, /* R195 */ - 0x0030, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0060, /* R199 */ - 0x0000, /* R200 */ - 0x003F, /* R201 */ - 0x0000, /* R202 */ - 0x0000, /* R203 */ - 0x0000, /* R204 */ - 0x0001, /* R205 */ - 0x0000, /* R206 */ - 0x0181, /* R207 */ - 0x0005, /* R208 */ - 0x0008, /* R209 */ - 0x0008, /* R210 */ - 0x0000, /* R211 */ - 0x013B, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 */ - 0x0000, /* R216 */ - 0x0070, /* R217 */ - 0x0000, /* R218 */ - 0x0000, /* R219 */ - 0x0000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0003, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 */ - 0x0001, /* R226 */ - 0x0008, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0x0000, /* R230 */ - 0x0000, /* R231 */ - 0x0004, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0080, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0052, /* R245 */ - 0x0110, /* R246 */ - 0x0040, /* R247 */ - 0x0000, /* R248 */ - 0x0030, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0001, /* R252 - General test 1 */ +static const struct reg_default wm8961_reg_defaults[] = { + { 0, 0x009F }, /* R0 - Left Input volume */ + { 1, 0x009F }, /* R1 - Right Input volume */ + { 2, 0x0000 }, /* R2 - LOUT1 volume */ + { 3, 0x0000 }, /* R3 - ROUT1 volume */ + { 4, 0x0020 }, /* R4 - Clocking1 */ + { 5, 0x0008 }, /* R5 - ADC & DAC Control 1 */ + { 6, 0x0000 }, /* R6 - ADC & DAC Control 2 */ + { 7, 0x000A }, /* R7 - Audio Interface 0 */ + { 8, 0x01F4 }, /* R8 - Clocking2 */ + { 9, 0x0000 }, /* R9 - Audio Interface 1 */ + { 10, 0x00FF }, /* R10 - Left DAC volume */ + { 11, 0x00FF }, /* R11 - Right DAC volume */ + + { 14, 0x0040 }, /* R14 - Audio Interface 2 */ + + { 17, 0x007B }, /* R17 - ALC1 */ + { 18, 0x0000 }, /* R18 - ALC2 */ + { 19, 0x0032 }, /* R19 - ALC3 */ + { 20, 0x0000 }, /* R20 - Noise Gate */ + { 21, 0x00C0 }, /* R21 - Left ADC volume */ + { 22, 0x00C0 }, /* R22 - Right ADC volume */ + { 23, 0x0120 }, /* R23 - Additional control(1) */ + { 24, 0x0000 }, /* R24 - Additional control(2) */ + { 25, 0x0000 }, /* R25 - Pwr Mgmt (1) */ + { 26, 0x0000 }, /* R26 - Pwr Mgmt (2) */ + { 27, 0x0000 }, /* R27 - Additional Control (3) */ + { 28, 0x0000 }, /* R28 - Anti-pop */ + + { 30, 0x005F }, /* R30 - Clocking 3 */ + + { 32, 0x0000 }, /* R32 - ADCL signal path */ + { 33, 0x0000 }, /* R33 - ADCR signal path */ + + { 40, 0x0000 }, /* R40 - LOUT2 volume */ + { 41, 0x0000 }, /* R41 - ROUT2 volume */ + + { 47, 0x0000 }, /* R47 - Pwr Mgmt (3) */ + { 48, 0x0023 }, /* R48 - Additional Control (4) */ + { 49, 0x0000 }, /* R49 - Class D Control 1 */ + + { 51, 0x0003 }, /* R51 - Class D Control 2 */ + + { 56, 0x0106 }, /* R56 - Clocking 4 */ + { 57, 0x0000 }, /* R57 - DSP Sidetone 0 */ + { 58, 0x0000 }, /* R58 - DSP Sidetone 1 */ + + { 60, 0x0000 }, /* R60 - DC Servo 0 */ + { 61, 0x0000 }, /* R61 - DC Servo 1 */ + + { 63, 0x015E }, /* R63 - DC Servo 3 */ + + { 65, 0x0010 }, /* R65 - DC Servo 5 */ + + { 68, 0x0003 }, /* R68 - Analogue PGA Bias */ + { 69, 0x0000 }, /* R69 - Analogue HP 0 */ + + { 71, 0x01FB }, /* R71 - Analogue HP 2 */ + { 72, 0x0000 }, /* R72 - Charge Pump 1 */ + + { 82, 0x0000 }, /* R82 - Charge Pump B */ + + { 87, 0x0000 }, /* R87 - Write Sequencer 1 */ + { 88, 0x0000 }, /* R88 - Write Sequencer 2 */ + { 89, 0x0000 }, /* R89 - Write Sequencer 3 */ + { 90, 0x0000 }, /* R90 - Write Sequencer 4 */ + { 91, 0x0000 }, /* R91 - Write Sequencer 5 */ + { 92, 0x0000 }, /* R92 - Write Sequencer 6 */ + { 93, 0x0000 }, /* R93 - Write Sequencer 7 */ + + { 252, 0x0001 }, /* R252 - General test 1 */ }; struct wm8961_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; int sysclk; }; -static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8961_volatile(struct device *dev, unsigned int reg) { switch (reg) { case WM8961_SOFTWARE_RESET: case WM8961_WRITE_SEQUENCER_7: case WM8961_DC_SERVO_1: - return 1; + return true; default: - return 0; + return false; + } +} + +static bool wm8961_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8961_LEFT_INPUT_VOLUME: + case WM8961_RIGHT_INPUT_VOLUME: + case WM8961_LOUT1_VOLUME: + case WM8961_ROUT1_VOLUME: + case WM8961_CLOCKING1: + case WM8961_ADC_DAC_CONTROL_1: + case WM8961_ADC_DAC_CONTROL_2: + case WM8961_AUDIO_INTERFACE_0: + case WM8961_CLOCKING2: + case WM8961_AUDIO_INTERFACE_1: + case WM8961_LEFT_DAC_VOLUME: + case WM8961_RIGHT_DAC_VOLUME: + case WM8961_AUDIO_INTERFACE_2: + case WM8961_SOFTWARE_RESET: + case WM8961_ALC1: + case WM8961_ALC2: + case WM8961_ALC3: + case WM8961_NOISE_GATE: + case WM8961_LEFT_ADC_VOLUME: + case WM8961_RIGHT_ADC_VOLUME: + case WM8961_ADDITIONAL_CONTROL_1: + case WM8961_ADDITIONAL_CONTROL_2: + case WM8961_PWR_MGMT_1: + case WM8961_PWR_MGMT_2: + case WM8961_ADDITIONAL_CONTROL_3: + case WM8961_ANTI_POP: + case WM8961_CLOCKING_3: + case WM8961_ADCL_SIGNAL_PATH: + case WM8961_ADCR_SIGNAL_PATH: + case WM8961_LOUT2_VOLUME: + case WM8961_ROUT2_VOLUME: + case WM8961_PWR_MGMT_3: + case WM8961_ADDITIONAL_CONTROL_4: + case WM8961_CLASS_D_CONTROL_1: + case WM8961_CLASS_D_CONTROL_2: + case WM8961_CLOCKING_4: + case WM8961_DSP_SIDETONE_0: + case WM8961_DSP_SIDETONE_1: + case WM8961_DC_SERVO_0: + case WM8961_DC_SERVO_1: + case WM8961_DC_SERVO_3: + case WM8961_DC_SERVO_5: + case WM8961_ANALOGUE_PGA_BIAS: + case WM8961_ANALOGUE_HP_0: + case WM8961_ANALOGUE_HP_2: + case WM8961_CHARGE_PUMP_1: + case WM8961_CHARGE_PUMP_B: + case WM8961_WRITE_SEQUENCER_1: + case WM8961_WRITE_SEQUENCER_2: + case WM8961_WRITE_SEQUENCER_3: + case WM8961_WRITE_SEQUENCER_4: + case WM8961_WRITE_SEQUENCER_5: + case WM8961_WRITE_SEQUENCER_6: + case WM8961_WRITE_SEQUENCER_7: + case WM8961_GENERAL_TEST_1: + return true; + default: + return false; } } @@ -958,11 +840,12 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { + struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); + 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; @@ -975,9 +858,9 @@ static int wm8961_probe(struct snd_soc_codec *codec) } /* This isn't volatile - readback doesn't correspond to write */ - codec->cache_bypass = 1; + regcache_cache_bypass(wm8961->regmap, true); reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); - codec->cache_bypass = 0; + regcache_cache_bypass(wm8961->regmap, false); dev_info(codec->dev, "WM8961 family %d revision %c\n", (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) @@ -1066,10 +949,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { .suspend = wm8961_suspend, .resume = wm8961_resume, .set_bias_level = wm8961_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8961_reg_defaults, - .volatile_register = wm8961_volatile_register, +}; + +static const struct regmap_config wm8961_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = WM8961_MAX_REGISTER, + + .reg_defaults = wm8961_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8961_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8961_volatile, + .readable_reg = wm8961_readable, }; static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, @@ -1083,6 +975,10 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, if (wm8961 == NULL) return -ENOMEM; + wm8961->regmap = devm_regmap_init_i2c(i2c, &wm8961_regmap); + if (IS_ERR(wm8961->regmap)) + return PTR_ERR(wm8961->regmap); + i2c_set_clientdata(i2c, wm8961); ret = snd_soc_register_codec(&i2c->dev, From b306e84f9a15e465812d9b66f8d6ecadae806f4c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Sep 2012 13:31:38 +0800 Subject: [PATCH 631/665] ASoC: wm8961: Move device identification and reset to I2C probe This is more idiomatic as it means we verify that the device is there prior to trying to do the card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 60 +++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 4ea64d6e68e2..f387670d0d75 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -187,11 +187,6 @@ static bool wm8961_readable(struct device *dev, unsigned int reg) } } -static int wm8961_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0); -} - /* * The headphone output supports special anti-pop sequences giving * silent power up and power down. @@ -840,7 +835,6 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { - struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; u16 reg; @@ -851,27 +845,6 @@ static int wm8961_probe(struct snd_soc_codec *codec) return ret; } - reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); - if (reg != 0x1801) { - dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); - return -EINVAL; - } - - /* This isn't volatile - readback doesn't correspond to write */ - regcache_cache_bypass(wm8961->regmap, true); - reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); - regcache_cache_bypass(wm8961->regmap, false); - dev_info(codec->dev, "WM8961 family %d revision %c\n", - (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, - ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) - + 'A'); - - ret = wm8961_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; @@ -968,6 +941,7 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8961_priv *wm8961; + unsigned int val; int ret; wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv), @@ -979,6 +953,38 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, if (IS_ERR(wm8961->regmap)) return PTR_ERR(wm8961->regmap); + ret = regmap_read(wm8961->regmap, WM8961_SOFTWARE_RESET, &val); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); + return ret; + } + + if (val != 0x1801) { + dev_err(&i2c->dev, "Device is not a WM8961: ID=0x%x\n", val); + return -EINVAL; + } + + /* This isn't volatile - readback doesn't correspond to write */ + regcache_cache_bypass(wm8961->regmap, true); + ret = regmap_read(wm8961->regmap, WM8961_RIGHT_INPUT_VOLUME, &val); + regcache_cache_bypass(wm8961->regmap, false); + + if (ret != 0) { + dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret); + return ret; + } + + dev_info(&i2c->dev, "WM8961 family %d revision %c\n", + (val & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, + ((val & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) + + 'A'); + + ret = regmap_write(wm8961->regmap, WM8961_SOFTWARE_RESET, 0x1801); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8961); ret = snd_soc_register_codec(&i2c->dev, From 0534951ba493a97eee646f62101cf88fac2308c6 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 20 Sep 2012 13:57:27 -0500 Subject: [PATCH 632/665] ASoC: wm8960: remove 'dres' field from platform data structure The 'dres' field (discharge resistance for headphone outputs) is no longer used in the driver, so remove it. It was used in the original version of the driver when entering standby from off, but we stopped using it when we switched from having a single startup sequence to having separate cap and capless sequences. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- include/sound/wm8960.h | 2 -- sound/soc/codecs/wm8960.c | 5 ----- 2 files changed, 7 deletions(-) diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index b5a1ab9ebb4a..e8ce8ee7d62d 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h @@ -18,8 +18,6 @@ struct wm8960_data { bool capless; /* Headphone outputs configured in capless mode */ - int dres; /* Discharge resistance for headphone outputs */ - bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ }; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 782faa0a3b49..f0f6f6601785 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -962,11 +962,6 @@ static int wm8960_probe(struct snd_soc_codec *codec) if (!pdata) { dev_warn(codec->dev, "No platform data supplied\n"); } else { - if (pdata->dres > WM8960_DRES_MAX) { - dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); - pdata->dres = 0; - } - if (pdata->capless) wm8960->set_bias_level = wm8960_set_bias_level_capless; } From 7f51e7d30e36ac987d7a0e480d890477c5f8b04f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Sep 2012 16:32:02 +0300 Subject: [PATCH 633/665] ASoC: twl4030: Convert to use DAI DAPM widgets Use DAPM mapping for stream events and give unique names for the streams. This change also fixes the following warning: twl4030-codec twl4030-codec: Failed to create Capture debugfs file Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 48 ++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 2548f5c56885..962341df7ddc 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -1237,16 +1237,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), /* DACs */ - SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback", - SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Right1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Left1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Right2", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Left2", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Voice", NULL, SND_SOC_NOPM, 0, 0), /* Analog bypasses */ SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, @@ -1375,14 +1370,10 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { /* Introducing four virtual ADC, since TWL4030 have four channel for capture */ - SND_SOC_DAPM_ADC("ADC Virtual Left1", "Left Front Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Right1", "Right Front Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Left2", "Left Rear Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Right2", "Right Rear Capture", - SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Left1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Right1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Left2", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Right2", NULL, SND_SOC_NOPM, 0, 0), /* Analog/Digital mic path selection. TX1 Left/Right: either analog Left/Right or Digimic0 @@ -1426,6 +1417,23 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { }; static const struct snd_soc_dapm_route intercon[] = { + /* Stream -> DAC mapping */ + {"DAC Right1", NULL, "HiFi Playback"}, + {"DAC Left1", NULL, "HiFi Playback"}, + {"DAC Right2", NULL, "HiFi Playback"}, + {"DAC Left2", NULL, "HiFi Playback"}, + {"DAC Voice", NULL, "Voice Playback"}, + + /* ADC -> Stream mapping */ + {"HiFi Capture", NULL, "ADC Virtual Left1"}, + {"HiFi Capture", NULL, "ADC Virtual Right1"}, + {"HiFi Capture", NULL, "ADC Virtual Left2"}, + {"HiFi Capture", NULL, "ADC Virtual Right2"}, + {"Voice Capture", NULL, "ADC Virtual Left1"}, + {"Voice Capture", NULL, "ADC Virtual Right1"}, + {"Voice Capture", NULL, "ADC Virtual Left2"}, + {"Voice Capture", NULL, "ADC Virtual Right2"}, + {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, {"Digital L2 Playback Mixer", NULL, "DAC Left2"}, @@ -2170,7 +2178,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { .formats = TWL4030_FORMATS, .sig_bits = 24,}, .capture = { - .stream_name = "Capture", + .stream_name = "HiFi Capture", .channels_min = 2, .channels_max = 4, .rates = TWL4030_RATES, @@ -2187,7 +2195,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .capture = { - .stream_name = "Capture", + .stream_name = "Voice Capture", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, From 805238b1b76c8f4f17a92f50c12664a8e6f3564f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Sep 2012 16:32:15 +0300 Subject: [PATCH 634/665] ASoC: twl6040: Convert to use DAI DAPM widgets Use DAPM mapping for stream events and give unique names for the streams. This change also fixes the following warning: twl6040-codec twl6040-codec: Failed to create Capture debugfs file Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 43 +++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index c084c549942e..e8f97af75928 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -727,10 +727,8 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { TWL6040_REG_MICRCTL, 1, 0, NULL, 0), /* ADCs */ - SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture", - TWL6040_REG_MICLCTL, 2, 0), - SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture", - TWL6040_REG_MICRCTL, 2, 0), + SND_SOC_DAPM_ADC("ADC Left", NULL, TWL6040_REG_MICLCTL, 2, 0), + SND_SOC_DAPM_ADC("ADC Right", NULL, TWL6040_REG_MICRCTL, 2, 0), /* Microphone bias */ SND_SOC_DAPM_SUPPLY("Headset Mic Bias", @@ -743,15 +741,12 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), /* DACs */ - SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback", - TWL6040_REG_HFLCTL, 0, 0), - SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback", - TWL6040_REG_HFRCTL, 0, 0), + SND_SOC_DAPM_DAC("HSDAC Left", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("HSDAC Right", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("HFDAC Left", NULL, TWL6040_REG_HFLCTL, 0, 0), + SND_SOC_DAPM_DAC("HFDAC Right", NULL, TWL6040_REG_HFRCTL, 0, 0), /* Virtual DAC for vibra path (DL4 channel) */ - SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback", - SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("VIBRA DAC", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_MUX("Handsfree Left Playback", SND_SOC_NOPM, 0, 0, &hfl_mux_controls), @@ -810,6 +805,26 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { }; static const struct snd_soc_dapm_route intercon[] = { + /* Stream -> DAC mapping */ + {"HSDAC Left", NULL, "Legacy Playback"}, + {"HSDAC Left", NULL, "Headset Playback"}, + {"HSDAC Right", NULL, "Legacy Playback"}, + {"HSDAC Right", NULL, "Headset Playback"}, + + {"HFDAC Left", NULL, "Legacy Playback"}, + {"HFDAC Left", NULL, "Handsfree Playback"}, + {"HFDAC Right", NULL, "Legacy Playback"}, + {"HFDAC Right", NULL, "Handsfree Playback"}, + + {"VIBRA DAC", NULL, "Legacy Playback"}, + {"VIBRA DAC", NULL, "Vibra Playback"}, + + /* ADC -> Stream mapping */ + {"ADC Left", NULL, "Legacy Capture"}, + {"ADC Left", NULL, "Capture"}, + {"ADC Right", NULL, "Legacy Capture"}, + {"ADC Right", NULL, "Capture"}, + /* Capture path */ {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, @@ -1028,14 +1043,14 @@ static struct snd_soc_dai_driver twl6040_dai[] = { { .name = "twl6040-legacy", .playback = { - .stream_name = "Playback", + .stream_name = "Legacy Playback", .channels_min = 1, .channels_max = 5, .rates = TWL6040_RATES, .formats = TWL6040_FORMATS, }, .capture = { - .stream_name = "Capture", + .stream_name = "Legacy Capture", .channels_min = 1, .channels_max = 2, .rates = TWL6040_RATES, From f99ddef0d8e02884b302701fb7acb6fe51a36749 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 20 Sep 2012 10:36:43 -0400 Subject: [PATCH 635/665] ASoC: fsl: add PPC_MPC52xx dependency to SND_POWERPC_SOC mpc52xx socs do not define FSL_SOC but need SND_POWERPC_SOC defined to build ASoC drivers. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d70133086ac3..4563b28bd625 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -6,7 +6,7 @@ config SND_SOC_FSL_UTILS menuconfig SND_POWERPC_SOC tristate "SoC Audio for Freescale PowerPC CPUs" - depends on FSL_SOC + depends on FSL_SOC || PPC_MPC52xx help Say Y or M if you want to add support for codecs attached to the PowerPC CPUs. From 084011615c1c885232e8d1fb5cc3f85c9d880d14 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 20 Sep 2012 10:36:44 -0400 Subject: [PATCH 636/665] ASoC: fsl: pcm030-audio-fabric use snd_soc_register_card Convert pcm030-audio-fabric to use the new snd_soc_register_card api instead of the older method of registering a separate platform device. Create the dai_link to the mpc5200_psc_ac97 platform using the device tree. Convert the pcm030-audio-fabric driver to a platform-driver and add a remove function. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 65 +++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 1353e8fecd7b..893e24034816 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -28,7 +28,6 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = { .stream_name = "AC97 Analog", .codec_dai_name = "wm9712-hifi", .cpu_dai_name = "mpc5200-psc-ac97.0", - .platform_name = "mpc5200-pcm-audio", .codec_name = "wm9712-codec", }, { @@ -36,44 +35,74 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = { .stream_name = "AC97 IEC958", .codec_dai_name = "wm9712-aux", .cpu_dai_name = "mpc5200-psc-ac97.1", - .platform_name = "mpc5200-pcm-audio", .codec_name = "wm9712-codec", }, }; -static struct snd_soc_card card = { +static struct snd_soc_card pcm030_card = { .name = "pcm030", .owner = THIS_MODULE, .dai_link = pcm030_fabric_dai, .num_links = ARRAY_SIZE(pcm030_fabric_dai), }; -static __init int pcm030_fabric_init(void) +static int __init pcm030_fabric_probe(struct platform_device *op) { - struct platform_device *pdev; - int rc; + struct device_node *np = op->dev.of_node; + struct device_node *platform_np; + struct snd_soc_card *card = &pcm030_card; + int ret; + int i; if (!of_machine_is_compatible("phytec,pcm030")) return -ENODEV; - pdev = platform_device_alloc("soc-audio", 1); - if (!pdev) { - pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); + card->dev = &op->dev; + platform_set_drvdata(op, card); + + platform_np = of_parse_phandle(np, "asoc-platform", 0); + if (!platform_np) { + dev_err(&op->dev, "ac97 not registered\n"); return -ENODEV; } - platform_set_drvdata(pdev, &card); + for (i = 0; i < card->num_links; i++) + card->dai_link[i].platform_of_node = platform_np; - rc = platform_device_add(pdev); - if (rc) { - pr_err("pcm030_fabric_init: platform_device_add() failed\n"); - platform_device_put(pdev); - return -ENODEV; - } - return 0; + ret = snd_soc_register_card(card); + if (ret) + dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; } -module_init(pcm030_fabric_init); +static int __devexit pcm030_fabric_remove(struct platform_device *op) +{ + struct snd_soc_card *card = platform_get_drvdata(op); + int ret; + + ret = snd_soc_unregister_card(card); + + return ret; +} + +static struct of_device_id pcm030_audio_match[] = { + { .compatible = "phytec,pcm030-audio-fabric", }, + {} +}; +MODULE_DEVICE_TABLE(of, pcm030_audio_match); + +static struct platform_driver pcm030_fabric_driver = { + .probe = pcm030_fabric_probe, + .remove = __devexit_p(pcm030_fabric_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = pcm030_audio_match, + }, +}; + +module_platform_driver(pcm030_fabric_driver); MODULE_AUTHOR("Jon Smirl "); From c912fa913446b07147f6cbc1a8fa2fb20d2f7c36 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 20 Sep 2012 10:36:45 -0400 Subject: [PATCH 637/665] ASoC: fsl: register the wm9712-codec The mpc5200-psc-ac97 driver does not enumerate attached ac97 devices, so register the device here. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 32 ++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 893e24034816..4b63ec8eb372 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -22,6 +22,11 @@ #define DRV_NAME "pcm030-audio-fabric" +struct pcm030_audio_data { + struct snd_soc_card *card; + struct platform_device *codec_device; +}; + static struct snd_soc_dai_link pcm030_fabric_dai[] = { { .name = "AC97", @@ -51,14 +56,22 @@ static int __init pcm030_fabric_probe(struct platform_device *op) struct device_node *np = op->dev.of_node; struct device_node *platform_np; struct snd_soc_card *card = &pcm030_card; + struct pcm030_audio_data *pdata; int ret; int i; if (!of_machine_is_compatible("phytec,pcm030")) return -ENODEV; + pdata = devm_kzalloc(&op->dev, sizeof(struct pcm030_audio_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + card->dev = &op->dev; - platform_set_drvdata(op, card); + platform_set_drvdata(op, pdata); + + pdata->card = card; platform_np = of_parse_phandle(np, "asoc-platform", 0); if (!platform_np) { @@ -69,6 +82,18 @@ static int __init pcm030_fabric_probe(struct platform_device *op) for (i = 0; i < card->num_links; i++) card->dai_link[i].platform_of_node = platform_np; + ret = request_module("snd-soc-wm9712"); + if (ret) + dev_err(&op->dev, "request_module returned: %d\n", ret); + + pdata->codec_device = platform_device_alloc("wm9712-codec", -1); + if (!pdata->codec_device) + dev_err(&op->dev, "platform_device_alloc() failed\n"); + + ret = platform_device_add(pdata->codec_device); + if (ret) + dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); + ret = snd_soc_register_card(card); if (ret) dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); @@ -78,10 +103,11 @@ static int __init pcm030_fabric_probe(struct platform_device *op) static int __devexit pcm030_fabric_remove(struct platform_device *op) { - struct snd_soc_card *card = platform_get_drvdata(op); + struct pcm030_audio_data *pdata = platform_get_drvdata(op); int ret; - ret = snd_soc_unregister_card(card); + ret = snd_soc_unregister_card(pdata->card); + platform_device_unregister(pdata->codec_device); return ret; } From ccffa3870a7ec2b59cf051b745220c56f423d182 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:44 +0300 Subject: [PATCH 638/665] dmaengine: omap: Support for element mode in cyclic DMA When src_maxburst/dst_maxburst is set to 0 by the users of cyclic DMA (mostly audio) indicates that we should configure the omap DMA to element sync mode instead of packet mode. Signed-off-by: Peter Ujfalusi Acked-by: Vinod Koul Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- drivers/dma/omap-dma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index ae0561826137..b77a40db2856 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -413,7 +413,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->dev_addr = dev_addr; d->fi = burst; d->es = es; - d->sync_mode = OMAP_DMA_SYNC_PACKET; + if (burst) + d->sync_mode = OMAP_DMA_SYNC_PACKET; + else + d->sync_mode = OMAP_DMA_SYNC_ELEMENT; d->sync_type = sync_type; d->periph_port = OMAP_DMA_PORT_MPUI; d->sg[0].addr = buf_addr; From 2dcdf570936168d488acf90be9b04a3d32dafce7 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:45 +0300 Subject: [PATCH 639/665] dmaengine: omap: Add support for pause/resume in cyclic dma mode The audio stack used omap_stop_dma/omap_start_dma to pause/resume the DMA. This method has been used for years on OMAP based products. We only allow pause/resume when the DMA has been configured in cyclic mode which is used by the audio stack. Signed-off-by: Peter Ujfalusi Acked-by: Vinod Koul Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- drivers/dma/omap-dma.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index b77a40db2856..71d786973dfd 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -34,6 +34,7 @@ struct omap_chan { struct dma_slave_config cfg; unsigned dma_sig; bool cyclic; + bool paused; int dma_ch; struct omap_desc *desc; @@ -470,11 +471,14 @@ static int omap_dma_terminate_all(struct omap_chan *c) */ if (c->desc) { c->desc = NULL; - omap_stop_dma(c->dma_ch); + /* Avoid stopping the dma twice */ + if (!c->paused) + omap_stop_dma(c->dma_ch); } if (c->cyclic) { c->cyclic = false; + c->paused = false; omap_dma_unlink_lch(c->dma_ch, c->dma_ch); } @@ -487,14 +491,30 @@ static int omap_dma_terminate_all(struct omap_chan *c) static int omap_dma_pause(struct omap_chan *c) { - /* FIXME: not supported by platform private API */ - return -EINVAL; + /* Pause/Resume only allowed with cyclic mode */ + if (!c->cyclic) + return -EINVAL; + + if (!c->paused) { + omap_stop_dma(c->dma_ch); + c->paused = true; + } + + return 0; } static int omap_dma_resume(struct omap_chan *c) { - /* FIXME: not supported by platform private API */ - return -EINVAL; + /* Pause/Resume only allowed with cyclic mode */ + if (!c->cyclic) + return -EINVAL; + + if (c->paused) { + omap_start_dma(c->dma_ch); + c->paused = false; + } + + return 0; } static int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, From ec8b5e48c03790a68cb875fe5064007a9cbdfdd0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:47 +0300 Subject: [PATCH 640/665] dmaengine: Pass flags via device_prep_dma_cyclic() callback Change the parameter list of device_prep_dma_cyclic() so the DMA drivers can receive the flags coming from clients. This feature can be used during audio operation to disable all audio related interrupts when the DMA_PREP_INTERRUPT is cleared from the flags. Signed-off-by: Peter Ujfalusi Acked-by: Nicolas Ferre Acked-by: Shawn Guo Acked-by: Vinod Koul Signed-off-by: Mark Brown --- drivers/dma/at_hdmac.c | 3 ++- drivers/dma/ep93xx_dma.c | 4 +++- drivers/dma/imx-dma.c | 2 +- drivers/dma/imx-sdma.c | 2 +- drivers/dma/mmp_tdma.c | 2 +- drivers/dma/mxs-dma.c | 2 +- drivers/dma/omap-dma.c | 3 ++- drivers/dma/pl330.c | 2 +- drivers/dma/sa11x0-dma.c | 2 +- drivers/dma/sirf-dma.c | 2 +- drivers/dma/ste_dma40.c | 3 ++- drivers/dma/tegra20-apb-dma.c | 2 +- include/linux/dmaengine.h | 4 ++-- 13 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3934fcc4e00b..7e5f6b65c651 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -841,12 +841,13 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc, * @buf_len: total number of bytes for the entire buffer * @period_len: number of bytes for each period * @direction: transfer direction, to or from device + * @flags: tx descriptor status flags * @context: transfer context (ignored) */ static struct dma_async_tx_descriptor * atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, - void *context) + unsigned long flags, void *context) { struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma_slave *atslave = chan->private; diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index c64917ec313d..493735b9b2c9 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -1120,6 +1120,7 @@ fail: * @buf_len: length of the buffer (in bytes) * @period_len: lenght of a single period * @dir: direction of the operation + * @flags: tx descriptor status flags * @context: operation context (ignored) * * Prepares a descriptor for cyclic DMA operation. This means that once the @@ -1133,7 +1134,8 @@ fail: static struct dma_async_tx_descriptor * ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, - enum dma_transfer_direction dir, void *context) + enum dma_transfer_direction dir, unsigned long flags, + void *context) { struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); struct ep93xx_dma_desc *desc, *first; diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 5084975d793c..41b4376eb614 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -801,7 +801,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, - void *context) + unsigned long flags, void *context) { struct imxdma_channel *imxdmac = to_imxdma_chan(chan); struct imxdma_engine *imxdma = imxdmac->imxdma; diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 1dc2a4ad0026..2c5fd3e9880c 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1012,7 +1012,7 @@ err_out: static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, - void *context) + unsigned long flags, void *context) { struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 8a15cf2163dc..6d52bd43a527 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c @@ -358,7 +358,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac) static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, - void *context) + unsigned long flags, void *context) { struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); struct mmp_tdma_desc *desc; diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 7f41b25805fa..734a4eb84d65 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -531,7 +531,7 @@ err_out: static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, - void *context) + unsigned long flags, void *context) { struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 71d786973dfd..4d2650f4202c 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -366,7 +366,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, - size_t period_len, enum dma_transfer_direction dir, void *context) + size_t period_len, enum dma_transfer_direction dir, unsigned long flags, + void *context) { struct omap_chan *c = to_omap_dma_chan(chan); enum dma_slave_buswidth dev_width; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index e4feba6b03c0..00356458e399 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2683,7 +2683,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t len, size_t period_len, enum dma_transfer_direction direction, - void *context) + unsigned long flags, void *context) { struct dma_pl330_desc *desc; struct dma_pl330_chan *pch = to_pchan(chan); diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c index f5a73606217e..b893159c1ecb 100644 --- a/drivers/dma/sa11x0-dma.c +++ b/drivers/dma/sa11x0-dma.c @@ -614,7 +614,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg( static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period, - enum dma_transfer_direction dir, void *context) + enum dma_transfer_direction dir, unsigned long flags, void *context) { struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan); struct sa11x0_dma_desc *txd; diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 434ad31174f2..3eed8b35b0f1 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -489,7 +489,7 @@ err_dir: static struct dma_async_tx_descriptor * sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr, size_t buf_len, size_t period_len, - enum dma_transfer_direction direction, void *context) + enum dma_transfer_direction direction, unsigned long flags, void *context) { struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); struct sirfsoc_dma_desc *sdesc = NULL; diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 000d309602b2..eee8d9b9a20b 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -2347,7 +2347,8 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, static struct dma_async_tx_descriptor * dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, - enum dma_transfer_direction direction, void *context) + enum dma_transfer_direction direction, unsigned long flags, + void *context) { unsigned int periods = buf_len / period_len; struct dma_async_tx_descriptor *txd; diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 24acd711e032..b42b6ffb75ad 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -990,7 +990,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, - void *context) + unsigned long flags, void *context) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); struct tegra_dma_desc *dma_desc = NULL; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 9c02a4508b25..09da4e565297 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -591,7 +591,7 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, - void *context); + unsigned long flags, void *context); struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( struct dma_chan *chan, struct dma_interleaved_template *xt, unsigned long flags); @@ -656,7 +656,7 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction dir) { return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, - period_len, dir, NULL); + period_len, dir, flags, NULL); } static inline int dmaengine_terminate_all(struct dma_chan *chan) From 2dde5b909e117cc95a5e31604f9bfd043e78ad9d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:48 +0300 Subject: [PATCH 641/665] dmaengine: omap-dma: Add support to suppress interrupts in cyclic mode When requested (DMA_PREP_INTERRUPT is cleared in flags) disable all DMA interrupts for the channel. In this mode user space does not expect periodic reports from kernel about the progress of the audio stream. PulseAudio for example support this type of mode. Signed-off-by: Peter Ujfalusi Acked-by: Vinod Koul Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- drivers/dma/omap-dma.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 4d2650f4202c..f59f244f60fc 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -429,7 +429,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( if (!c->cyclic) { c->cyclic = true; omap_dma_link_lch(c->dma_ch, c->dma_ch); - omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ); + + if (flags & DMA_PREP_INTERRUPT) + omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ); + omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ); } @@ -438,7 +441,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); } - return vchan_tx_prep(&c->vc, &d->vd, DMA_CTRL_ACK | DMA_PREP_INTERRUPT); + return vchan_tx_prep(&c->vc, &d->vd, flags); } static int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg) From dffb360e64968b95a0a0221ca52234a28cc049c9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:49 +0300 Subject: [PATCH 642/665] ASoC: omap-mcbsp: Use sDMA packet mode instead of frame mode When McBSP is configured in threshold mode we can use sDMA packet mode in all cases. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 45 +++++++++++++------------------------ 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 2e91a86b6114..fe3debcc2d0b 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -81,9 +81,6 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) */ if (dma_data->packet_size) words = dma_data->packet_size; - else if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) - words = snd_pcm_lib_period_bytes(substream) / - (mcbsp->wlen / 8); else words = 1; @@ -251,6 +248,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, dma_data->set_threshold = omap_mcbsp_set_threshold; if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; + int divider = 0; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -258,34 +256,23 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, else max_thrsh = mcbsp->max_rx_thres; /* - * If the period contains less or equal number of words, - * we are using the original threshold mode setup: - * McBSP threshold = sDMA frame size = period_size - * Otherwise we switch to sDMA packet mode: - * McBSP threshold = sDMA packet size - * sDMA frame size = period size + * Use sDMA packet mode if McBSP is in threshold mode: + * If period words less than the FIFO size the packet + * size is set to the number of period words, otherwise + * Look for the biggest threshold value which divides + * the period size evenly. */ - if (period_words > max_thrsh) { - int divider = 0; + divider = period_words / max_thrsh; + if (period_words % max_thrsh) + divider++; + while (period_words % divider && + divider < period_words) + divider++; + if (divider == period_words) + return -EINVAL; - /* - * Look for the biggest threshold value, which - * divides the period size evenly. - */ - divider = period_words / max_thrsh; - if (period_words % max_thrsh) - divider++; - while (period_words % divider && - divider < period_words) - divider++; - if (divider == period_words) - return -EINVAL; - - pkt_size = period_words / divider; - sync_mode = OMAP_DMA_SYNC_PACKET; - } else { - sync_mode = OMAP_DMA_SYNC_FRAME; - } + pkt_size = period_words / divider; + sync_mode = OMAP_DMA_SYNC_PACKET; } else if (channels > 1) { /* Use packet mode for non mono streams */ pkt_size = channels; From e512589c17572e7498693a3e05eefa44e622f62b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:50 +0300 Subject: [PATCH 643/665] ASoC: omap-pcm: Select sDMA synchronization based on packet_size Since we only have element or packet synchronization we can use the dma_data->packet_size to select the desired mode: if packet_size is 0 we use ELEMENT mode if packet_size is not 0 we use PACKET mode for sDMA synchronization. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-pcm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index f0feb06615f8..02eeb2e7ceda 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -165,7 +165,12 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) memset(&dma_params, 0, sizeof(dma_params)); dma_params.data_type = dma_data->data_type; dma_params.trigger = dma_data->dma_req; - dma_params.sync_mode = dma_data->sync_mode; + + if (dma_data->packet_size) + dma_params.sync_mode = OMAP_DMA_SYNC_PACKET; + else + dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; From 061fb36db7c0187aa90b95f1ba56f6192f42b984 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:51 +0300 Subject: [PATCH 644/665] ASoC: OMAP: Remove sync_mode from omap_pcm_dma_data struct The omap-pcm platform driver no longer needs this parameter to select between ELEMENT and PACKET mode. The selection is based on the configured packet_size. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-dmic.c | 1 - sound/soc/omap/omap-hdmi.c | 1 - sound/soc/omap/omap-mcbsp.c | 5 +---- sound/soc/omap/omap-mcpdm.c | 2 -- sound/soc/omap/omap-pcm.h | 1 - 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 75f5dca0e8d2..60b7b8cd1c7d 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -64,7 +64,6 @@ struct omap_dmic { static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { .name = "DMIC capture", .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, }; static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index a08245d9203c..b19464697ac8 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c @@ -290,7 +290,6 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev) hdmi_data->dma_params.dma_req = hdmi_rsrc->start; hdmi_data->dma_params.name = "HDMI playback"; - hdmi_data->dma_params.sync_mode = OMAP_DMA_SYNC_PACKET; /* * TODO: We assume that there is only one DSS HDMI device. Future diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index fe3debcc2d0b..5b3baccd74c3 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -225,7 +225,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; struct omap_pcm_dma_data *dma_data; - int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; + int wlen, channels, wpf; int pkt_size = 0; unsigned int format, div, framesize, master; @@ -272,15 +272,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; pkt_size = period_words / divider; - sync_mode = OMAP_DMA_SYNC_PACKET; } else if (channels > 1) { /* Use packet mode for non mono streams */ pkt_size = channels; - sync_mode = OMAP_DMA_SYNC_PACKET; } } - dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index f7babb374a37..baf92da42aec 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -73,14 +73,12 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { .name = "Audio playback", .dma_req = OMAP44XX_DMA_MCPDM_DL, .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, }, { .name = "Audio capture", .dma_req = OMAP44XX_DMA_MCPDM_UP, .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, }, }; diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index b92248cbd47a..1bf47e4b60c2 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h @@ -33,7 +33,6 @@ struct omap_pcm_dma_data { unsigned long port_addr; /* transmit/receive register */ void (*set_threshold)(struct snd_pcm_substream *substream); int data_type; /* data type 8,16,32 */ - int sync_mode; /* DMA sync mode */ int packet_size; /* packet size only in PACKET mode */ }; From 03945e99a8ac4f596dad9a679816e5b4bb77e5d2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:52 +0300 Subject: [PATCH 645/665] ASoC: omap-pcm: Prepare to configure the DMA data_type based on stream properties Based on the format of the stream the omap-pcm can decide alone what data type should be used with by the sDMA. Keep the possibility for OMAP dai drivers to tell omap-pcm if they want to use different data type. This is needed for the omap-hdmi for example which needs 32bit data type even if the stream format is S16_LE. The check if (dma_data->data_type) is safe at the moment since omap-pcm does not support 8bit samples (OMAP_DMA_DATA_TYPE_S8 == 0x00). The next step is to redefine the meaning of dma_data->data_type to unblock this limitation. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-pcm.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 02eeb2e7ceda..4c13a5f4eebb 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -149,6 +149,24 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream) return 0; } +static int omap_pcm_get_dma_type(int num_bits) +{ + int data_type; + + switch (num_bits) { + case 16: + data_type = OMAP_DMA_DATA_TYPE_S16; + break; + case 32: + data_type = OMAP_DMA_DATA_TYPE_S32; + break; + default: + data_type = -EINVAL; + break; + } + return data_type; +} + static int omap_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -163,7 +181,16 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) return 0; memset(&dma_params, 0, sizeof(dma_params)); - dma_params.data_type = dma_data->data_type; + + if (dma_data->data_type) + dma_params.data_type = dma_data->data_type; + else + dma_params.data_type = omap_pcm_get_dma_type( + snd_pcm_format_physical_width(runtime->format)); + + if (dma_params.data_type < 0) + return dma_params.data_type; + dma_params.trigger = dma_data->dma_req; if (dma_data->packet_size) @@ -195,7 +222,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) * still can get an interrupt at each period bounary */ bytes = snd_pcm_lib_period_bytes(substream); - dma_params.elem_count = bytes >> dma_data->data_type; + dma_params.elem_count = bytes >> dma_params.data_type; dma_params.frame_count = runtime->periods; omap_set_dma_params(prtd->dma_ch, &dma_params); From acd08ecd11dce04d077b7dd5cf65eebc157a5bea Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:53 +0300 Subject: [PATCH 646/665] ARM: OMAP4: hwmod_data: Add resource names to McPDM memory ranges To help the driver to get the correct memory range to access McPDM registers. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 242aee498ceb..f65251e58b35 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -5059,6 +5059,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = { static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = { { + .name = "mpu", .pa_start = 0x40132000, .pa_end = 0x4013207f, .flags = ADDR_TYPE_RT @@ -5077,6 +5078,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = { static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = { { + .name = "dma", .pa_start = 0x49032000, .pa_end = 0x4903207f, .flags = ADDR_TYPE_RT From 5a40c57af55b17dabe25854c9245171515bb5d23 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:54 +0300 Subject: [PATCH 647/665] ASoC: omap-mcpdm: Use platform_get_resource_* to get resources Get the needed resources in a correct way and avoid using defines for them. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index baf92da42aec..f90d5de605c3 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -71,15 +71,11 @@ struct omap_mcpdm { static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { { .name = "Audio playback", - .dma_req = OMAP44XX_DMA_MCPDM_DL, .data_type = OMAP_DMA_DATA_TYPE_S32, - .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, }, { .name = "Audio capture", - .dma_req = OMAP44XX_DMA_MCPDM_UP, .data_type = OMAP_DMA_DATA_TYPE_S32, - .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, }, }; @@ -452,10 +448,33 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) mutex_init(&mcpdm->mutex); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); + if (res == NULL) + return -ENOMEM; + + omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; + omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) return -ENOMEM; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); + if (!res) + return -ENODEV; + + omap_mcpdm_dai_dma_params[0].dma_req = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); + if (!res) + return -ENODEV; + + omap_mcpdm_dai_dma_params[1].dma_req = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); + if (res == NULL) + return -ENOMEM; + if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), "McPDM")) return -EBUSY; From 04564e3258304df607d4536de42603b4c8e21e1a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:55 +0300 Subject: [PATCH 648/665] ASoC: OMAP: mcbsp, mcpdm, dmic: Let omap-pcm to pick the dma_type omap-pcm can figure out the correct dma_type based on the stream's format. In this way we can get rid of the plat/dma.h include from these drivers. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-dmic.c | 2 -- sound/soc/omap/omap-mcbsp.c | 3 --- sound/soc/omap/omap-mcpdm.c | 3 --- 3 files changed, 8 deletions(-) diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 60b7b8cd1c7d..df0ff247f496 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -63,7 +62,6 @@ struct omap_dmic { */ static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { .name = "DMIC capture", - .data_type = OMAP_DMA_DATA_TYPE_S32, }; static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 5b3baccd74c3..a23064644e58 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -34,7 +34,6 @@ #include #include -#include #include #include "mcbsp.h" #include "omap-mcbsp.h" @@ -234,11 +233,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: - dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; wlen = 32; break; default: diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index f90d5de605c3..84743d47e687 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -40,7 +40,6 @@ #include #include -#include #include #include "omap-mcpdm.h" #include "omap-pcm.h" @@ -71,11 +70,9 @@ struct omap_mcpdm { static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { { .name = "Audio playback", - .data_type = OMAP_DMA_DATA_TYPE_S32, }, { .name = "Audio capture", - .data_type = OMAP_DMA_DATA_TYPE_S32, }, }; From f05cc9dac99ac6403d057d2cccb3c754714d2f32 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:56 +0300 Subject: [PATCH 649/665] ASoC: omap-pcm, omap-dmic: Change the use of omap_pcm_dma_data->data_type Instead of the OMAP DMA data type definition the data_type will be used to specify the number of bits the DMA word should be configured or 0 in case when based on the stream's format the omap-pcm can decide the needed DMA word size. This feature is needed for the omap-hdmi where the sDMA need to be configured for 32bit word type regardless of the audio format used. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-hdmi.c | 3 +-- sound/soc/omap/omap-pcm.c | 3 ++- sound/soc/omap/omap-pcm.h | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index b19464697ac8..095176738fd6 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c @@ -34,7 +34,6 @@ #include #include