]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.1 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 2 Nov 2011 16:32:08 +0000 (09:32 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 2 Nov 2011 16:32:08 +0000 (09:32 -0700)
30 files changed:
queue-3.1/arm-mach-ux500-unlock-i-d-l2x0-caches-before-init.patch [new file with mode: 0644]
queue-3.1/arm-pxa-cm-x300-properly-set-bt_reset-pin.patch [new file with mode: 0644]
queue-3.1/asoc-ak4535-fixup-cache-register-table.patch [new file with mode: 0644]
queue-3.1/asoc-ak4642-fixup-cache-register-table.patch [new file with mode: 0644]
queue-3.1/asoc-fix-a-bug-in-wm8962-dsp_a-and-dsp_b-settings.patch [new file with mode: 0644]
queue-3.1/asoc-remove-direct-register-cache-accesses-from-wm8962.patch [new file with mode: 0644]
queue-3.1/asoc-wm8741-fix-setting-interface-format-for-dsp-modes.patch [new file with mode: 0644]
queue-3.1/asoc-wm8940-properly-set-codec-dapm.bias_level.patch [new file with mode: 0644]
queue-3.1/asoc-wm8994-fix-setting-rate_reg-for-wm8994-aif2.patch [new file with mode: 0644]
queue-3.1/asoc-wm8994-use-snd_soc_dapm_aif_out-for-aif3-capture.patch [new file with mode: 0644]
queue-3.1/asoc-wm8996-fix-wrong-mask-for-setting.patch [new file with mode: 0644]
queue-3.1/carminefb-fix-module-parameters-permissions.patch [new file with mode: 0644]
queue-3.1/ccwgroup-move-attributes-to-attribute-group.patch [new file with mode: 0644]
queue-3.1/dib0700-protect-the-dib0700-buffer-access.patch [new file with mode: 0644]
queue-3.1/dibcom-protect-the-i2c-bufer-access.patch [new file with mode: 0644]
queue-3.1/fb-avoid-possible-deadlock-caused-by-fb_set_suspend.patch [new file with mode: 0644]
queue-3.1/fb-sh-mobile-fix-deadlock-risk-between-lock_fb_info-and-console_lock.patch [new file with mode: 0644]
queue-3.1/io-mapping-ensure-io_mapping_map_atomic-_is_-atomic.patch [new file with mode: 0644]
queue-3.1/iommu-amd-fix-wrong-shift-direction.patch [new file with mode: 0644]
queue-3.1/kvm-s390-check-cpu_id-prior-to-using-it.patch [new file with mode: 0644]
queue-3.1/md-raid10-fix-bug-when-activating-a-hot-spare.patch [new file with mode: 0644]
queue-3.1/memory-leak-with-rcu_table_free.patch [new file with mode: 0644]
queue-3.1/plat-mxc-iomux-v3.h-implicitly-enable-pull-up-down-when-that-s-desired.patch [new file with mode: 0644]
queue-3.1/proc-self-numa_maps-restore-huge-tag-for-hugetlb-vmas.patch [new file with mode: 0644]
queue-3.1/series
queue-3.1/tuner_xc2028-allow-selection-of-the-frequency-adjustment-code-for-xc3028.patch [new file with mode: 0644]
queue-3.1/user-per-registers-vs.-ptrace-single-stepping.patch [new file with mode: 0644]
queue-3.1/viafb-improve-pitch-handling.patch [new file with mode: 0644]
queue-3.1/viafb-use-display-information-in-info-not-in-var-for.patch [new file with mode: 0644]
queue-3.1/wmi-properly-cleanup-devices-to-avoid-crashes.patch [new file with mode: 0644]

diff --git a/queue-3.1/arm-mach-ux500-unlock-i-d-l2x0-caches-before-init.patch b/queue-3.1/arm-mach-ux500-unlock-i-d-l2x0-caches-before-init.patch
new file mode 100644 (file)
index 0000000..2f1e4a8
--- /dev/null
@@ -0,0 +1,72 @@
+From 1bf6d2c1bb23533af6930581cc39b74685bc29de Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Fri, 12 Aug 2011 13:54:42 +0200
+Subject: ARM: mach-ux500: unlock I&D l2x0 caches before init
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+commit 1bf6d2c1bb23533af6930581cc39b74685bc29de upstream.
+
+Apparently U8500 U-Boot versions may leave the l2x0 locked down
+before executing the kernel. Make sure we unlock it before we
+initialize the l2x0. This fixes a performance problem reported
+by Jan Rinze.
+
+The l2x0 core has been modified to unlock the l2x0 by default,
+but it will not touch the locking registers if the l2x0 was
+already enabled, as on the ux500, so we need this quirk to
+make sure it is properly turned off.
+
+Cc: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+Cc: Rabin Vincent <rabin.vincent@stericsson.com>
+Cc: Adrian Bunk <adrian.bunk@movial.com>
+Reported-by: Jan Rinze <janrinze@gmail.com>
+Tested-by: Robert Marklund <robert.marklund@stericsson.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/mach-ux500/cpu.c |   25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/mach-ux500/cpu.c
++++ b/arch/arm/mach-ux500/cpu.c
+@@ -99,7 +99,27 @@ static void ux500_l2x0_inv_all(void)
+       ux500_cache_sync();
+ }
+-static int ux500_l2x0_init(void)
++static int __init ux500_l2x0_unlock(void)
++{
++      int i;
++
++      /*
++       * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
++       * apparently locks both caches before jumping to the kernel. The
++       * l2x0 core will not touch the unlock registers if the l2x0 is
++       * already enabled, so we do it right here instead. The PL310 has
++       * 8 sets of registers, one per possible CPU.
++       */
++      for (i = 0; i < 8; i++) {
++              writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
++                             i * L2X0_LOCKDOWN_STRIDE);
++              writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
++                             i * L2X0_LOCKDOWN_STRIDE);
++      }
++      return 0;
++}
++
++static int __init ux500_l2x0_init(void)
+ {
+       if (cpu_is_u5500())
+               l2x0_base = __io_address(U5500_L2CC_BASE);
+@@ -108,6 +128,9 @@ static int ux500_l2x0_init(void)
+       else
+               ux500_unknown_soc();
++      /* Unlock before init */
++      ux500_l2x0_unlock();
++
+       /* 64KB way size, 8 way associativity, force WA */
+       l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
diff --git a/queue-3.1/arm-pxa-cm-x300-properly-set-bt_reset-pin.patch b/queue-3.1/arm-pxa-cm-x300-properly-set-bt_reset-pin.patch
new file mode 100644 (file)
index 0000000..0aab988
--- /dev/null
@@ -0,0 +1,51 @@
+From 1a64200ec5e93be03e27c3b2fc332e04ae443eb2 Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@gmail.com>
+Date: Sat, 17 Sep 2011 22:15:34 +0800
+Subject: ARM: pxa/cm-x300: properly set bt_reset pin
+
+From: Axel Lin <axel.lin@gmail.com>
+
+commit 1a64200ec5e93be03e27c3b2fc332e04ae443eb2 upstream.
+
+Fix below build warning and properly set bt_reset pin.
+
+  CC      arch/arm/mach-pxa/cm-x300.o
+arch/arm/mach-pxa/cm-x300.c: In function 'cm_x300_init_wi2wi':
+arch/arm/mach-pxa/cm-x300.c:779: warning: unused variable 'wlan_en'
+arch/arm/mach-pxa/cm-x300.c:795: warning: 'bt_reset' may be used uninitialized in this function
+
+Signed-off-by: Axel Lin <axel.lin@gmail.com>
+Acked-by: Igor Grinberg <grinberg@compulab.co.il>
+Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/mach-pxa/cm-x300.c |    8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/mach-pxa/cm-x300.c
++++ b/arch/arm/mach-pxa/cm-x300.c
+@@ -775,7 +775,6 @@ static struct gpio cm_x300_wi2wi_gpios[]
+ static void __init cm_x300_init_wi2wi(void)
+ {
+-      int bt_reset, wlan_en;
+       int err;
+       if (system_rev < 130) {
+@@ -791,12 +790,11 @@ static void __init cm_x300_init_wi2wi(vo
+       }
+       udelay(10);
+-      gpio_set_value(bt_reset, 0);
++      gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 0);
+       udelay(10);
+-      gpio_set_value(bt_reset, 1);
++      gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 1);
+-      gpio_free(wlan_en);
+-      gpio_free(bt_reset);
++      gpio_free_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
+ }
+ /* MFP */
diff --git a/queue-3.1/asoc-ak4535-fixup-cache-register-table.patch b/queue-3.1/asoc-ak4535-fixup-cache-register-table.patch
new file mode 100644 (file)
index 0000000..e6e71c2
--- /dev/null
@@ -0,0 +1,38 @@
+From 7c04241acbdaf97f1448dcccd27ea0fcd1a57684 Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@gmail.com>
+Date: Thu, 13 Oct 2011 17:17:06 +0800
+Subject: ASoC: ak4535: fixup cache register table
+
+From: Axel Lin <axel.lin@gmail.com>
+
+commit 7c04241acbdaf97f1448dcccd27ea0fcd1a57684 upstream.
+
+ak4535_reg should be 8bit, but cache table is defined as 16bit.
+
+Signed-off-by: Axel Lin <axel.lin@gmail.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/ak4535.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/sound/soc/codecs/ak4535.c
++++ b/sound/soc/codecs/ak4535.c
+@@ -40,11 +40,11 @@ struct ak4535_priv {
+ /*
+  * ak4535 register cache
+  */
+-static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
+-    0x0000, 0x0080, 0x0000, 0x0003,
+-    0x0002, 0x0000, 0x0011, 0x0001,
+-    0x0000, 0x0040, 0x0036, 0x0010,
+-    0x0000, 0x0000, 0x0057, 0x0000,
++static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
++      0x00, 0x80, 0x00, 0x03,
++      0x02, 0x00, 0x11, 0x01,
++      0x00, 0x40, 0x36, 0x10,
++      0x00, 0x00, 0x57, 0x00,
+ };
+ /*
diff --git a/queue-3.1/asoc-ak4642-fixup-cache-register-table.patch b/queue-3.1/asoc-ak4642-fixup-cache-register-table.patch
new file mode 100644 (file)
index 0000000..f16bb81
--- /dev/null
@@ -0,0 +1,51 @@
+From 19b115e523208a926813751aac8934cf3fc6085e Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 13 Oct 2011 02:03:54 -0700
+Subject: ASoC: ak4642: fixup cache register table
+
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+
+commit 19b115e523208a926813751aac8934cf3fc6085e upstream.
+
+ak4642 register was 8bit, but cache table was defined as 16bit.
+ak4642 doesn't work correctry without this patch.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/ak4642.c |   22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+--- a/sound/soc/codecs/ak4642.c
++++ b/sound/soc/codecs/ak4642.c
+@@ -162,17 +162,17 @@ struct ak4642_priv {
+ /*
+  * ak4642 register cache
+  */
+-static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
+-      0x0000, 0x0000, 0x0001, 0x0000,
+-      0x0002, 0x0000, 0x0000, 0x0000,
+-      0x00e1, 0x00e1, 0x0018, 0x0000,
+-      0x00e1, 0x0018, 0x0011, 0x0008,
+-      0x0000, 0x0000, 0x0000, 0x0000,
+-      0x0000, 0x0000, 0x0000, 0x0000,
+-      0x0000, 0x0000, 0x0000, 0x0000,
+-      0x0000, 0x0000, 0x0000, 0x0000,
+-      0x0000, 0x0000, 0x0000, 0x0000,
+-      0x0000,
++static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
++      0x00, 0x00, 0x01, 0x00,
++      0x02, 0x00, 0x00, 0x00,
++      0xe1, 0xe1, 0x18, 0x00,
++      0xe1, 0x18, 0x11, 0x08,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00,
++      0x00,
+ };
+ /*
diff --git a/queue-3.1/asoc-fix-a-bug-in-wm8962-dsp_a-and-dsp_b-settings.patch b/queue-3.1/asoc-fix-a-bug-in-wm8962-dsp_a-and-dsp_b-settings.patch
new file mode 100644 (file)
index 0000000..6a81cde
--- /dev/null
@@ -0,0 +1,31 @@
+From fbc7c62a3ff831aef24894b7982cd1adb2b7e070 Mon Sep 17 00:00:00 2001
+From: Susan Gao <sgao@opensource.wolfsonmicro.com>
+Date: Thu, 29 Sep 2011 11:08:18 +0100
+Subject: ASoC: Fix a bug in WM8962 DSP_A and DSP_B settings
+
+From: Susan Gao <sgao@opensource.wolfsonmicro.com>
+
+commit fbc7c62a3ff831aef24894b7982cd1adb2b7e070 upstream.
+
+Signed-off-by: Susan Gao <sgao@opensource.wolfsonmicro.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmico.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/wm8962.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/wm8962.c
++++ b/sound/soc/codecs/wm8962.c
+@@ -3059,9 +3059,9 @@ static int wm8962_set_dai_fmt(struct snd
+       int aif0 = 0;
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+-      case SND_SOC_DAIFMT_DSP_A:
+-              aif0 |= WM8962_LRCLK_INV;
+       case SND_SOC_DAIFMT_DSP_B:
++              aif0 |= WM8962_LRCLK_INV | 3;
++      case SND_SOC_DAIFMT_DSP_A:
+               aif0 |= 3;
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
diff --git a/queue-3.1/asoc-remove-direct-register-cache-accesses-from-wm8962.patch b/queue-3.1/asoc-remove-direct-register-cache-accesses-from-wm8962.patch
new file mode 100644 (file)
index 0000000..c22b279
--- /dev/null
@@ -0,0 +1,72 @@
+From 38f3f31a0a797bdbcc0cdb12553bbecc2f9a91c4 Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Date: Fri, 23 Sep 2011 21:26:33 +0100
+Subject: ASoC: Remove direct register cache accesses from WM8962 driver
+
+From: Mark Brown <broonie@opensource.wolfsonmicro.com>
+
+commit 38f3f31a0a797bdbcc0cdb12553bbecc2f9a91c4 upstream.
+
+Also fix return values for speaker switch updates.
+
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/wm8962.c |   21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/sound/soc/codecs/wm8962.c
++++ b/sound/soc/codecs/wm8962.c
+@@ -2021,7 +2021,6 @@ static int wm8962_put_spk_sw(struct snd_
+                           struct snd_ctl_elem_value *ucontrol)
+ {
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+-      u16 *reg_cache = codec->reg_cache;
+       int ret;
+       /* Apply the update (if any) */
+@@ -2030,16 +2029,19 @@ static int wm8962_put_spk_sw(struct snd_
+               return 0;
+       /* If the left PGA is enabled hit that VU bit... */
+-      if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
+-              return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
+-                                   reg_cache[WM8962_SPKOUTL_VOLUME]);
++      ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
++      if (ret & WM8962_SPKOUTL_PGA_ENA) {
++              snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
++                            snd_soc_read(codec, WM8962_SPKOUTL_VOLUME));
++              return 1;
++      }
+       /* ...otherwise the right.  The VU is stereo. */
+-      if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
+-              return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
+-                                   reg_cache[WM8962_SPKOUTR_VOLUME]);
++      if (ret & WM8962_SPKOUTR_PGA_ENA)
++              snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
++                            snd_soc_read(codec, WM8962_SPKOUTR_VOLUME));
+-      return 0;
++      return 1;
+ }
+ static const char *cap_hpf_mode_text[] = {
+@@ -2365,7 +2367,6 @@ static int out_pga_event(struct snd_soc_
+                        struct snd_kcontrol *kcontrol, int event)
+ {
+       struct snd_soc_codec *codec = w->codec;
+-      u16 *reg_cache = codec->reg_cache;
+       int reg;
+       switch (w->shift) {
+@@ -2388,7 +2389,7 @@ static int out_pga_event(struct snd_soc_
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+-              return snd_soc_write(codec, reg, reg_cache[reg]);
++              return snd_soc_write(codec, reg, snd_soc_read(codec, reg));
+       default:
+               BUG();
+               return -EINVAL;
diff --git a/queue-3.1/asoc-wm8741-fix-setting-interface-format-for-dsp-modes.patch b/queue-3.1/asoc-wm8741-fix-setting-interface-format-for-dsp-modes.patch
new file mode 100644 (file)
index 0000000..6e8ad36
--- /dev/null
@@ -0,0 +1,48 @@
+From 3a340104fad6ecbea5ad6792a2ea855f0507a6e0 Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@gmail.com>
+Date: Mon, 17 Oct 2011 20:14:56 +0800
+Subject: ASoC: wm8741: Fix setting interface format for DSP modes
+
+From: Axel Lin <axel.lin@gmail.com>
+
+commit 3a340104fad6ecbea5ad6792a2ea855f0507a6e0 upstream.
+
+According to the datasheet:
+Format Control (05h)
+BITS[3:2]
+        FMT[1:0] Audio data format selection
+                00 = right justified mode
+                01 = left justified mode
+                10 = I2S mode
+                11 = DSP mode
+BIT[4]  LRP Polarity selec for LRCLK/DSP mode select
+                0 = normal LRCLK poalrity/DSP mode A
+                1 = inverted LRCLK poarity/DSP mode B
+
+For SND_SOC_DAIFMT_DSP_A, we should set 0x000C instead of 0x0003.
+For SND_SOC_DAIFMT_DSP_B, we should set 0x001C instead of 0x0013.
+
+Signed-off-by: Axel Lin <axel.lin@gmail.com>
+Acked-by: Liam Girdwood <lrg@ti.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/wm8741.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/wm8741.c
++++ b/sound/soc/codecs/wm8741.c
+@@ -337,10 +337,10 @@ static int wm8741_set_dai_fmt(struct snd
+               iface |= 0x0004;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+-              iface |= 0x0003;
++              iface |= 0x000C;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+-              iface |= 0x0013;
++              iface |= 0x001C;
+               break;
+       default:
+               return -EINVAL;
diff --git a/queue-3.1/asoc-wm8940-properly-set-codec-dapm.bias_level.patch b/queue-3.1/asoc-wm8940-properly-set-codec-dapm.bias_level.patch
new file mode 100644 (file)
index 0000000..86e9e9d
--- /dev/null
@@ -0,0 +1,29 @@
+From 5927f94700e860ae27ff24e7f3bc9e4f7b9922eb Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@gmail.com>
+Date: Wed, 26 Oct 2011 09:53:41 +0800
+Subject: ASoC: wm8940: Properly set codec->dapm.bias_level
+
+From: Axel Lin <axel.lin@gmail.com>
+
+commit 5927f94700e860ae27ff24e7f3bc9e4f7b9922eb upstream.
+
+Reported-by: Chris Paulson-Ellis <chris@edesix.com>
+Signed-off-by: Axel Lin <axel.lin@gmail.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/wm8940.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/soc/codecs/wm8940.c
++++ b/sound/soc/codecs/wm8940.c
+@@ -470,6 +470,8 @@ static int wm8940_set_bias_level(struct
+               break;
+       }
++      codec->dapm.bias_level = level;
++
+       return ret;
+ }
diff --git a/queue-3.1/asoc-wm8994-fix-setting-rate_reg-for-wm8994-aif2.patch b/queue-3.1/asoc-wm8994-fix-setting-rate_reg-for-wm8994-aif2.patch
new file mode 100644 (file)
index 0000000..96acc6b
--- /dev/null
@@ -0,0 +1,30 @@
+From c527e6aadc8f142ad388b6aa59a1ce6a4bfb1966 Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@gmail.com>
+Date: Tue, 4 Oct 2011 22:07:18 +0800
+Subject: ASoC: wm8994: Fix setting rate_reg for wm8994-aif2
+
+From: Axel Lin <axel.lin@gmail.com>
+
+commit c527e6aadc8f142ad388b6aa59a1ce6a4bfb1966 upstream.
+
+For wm8994-aif2, the rate_reg should be WM8994_AIF2_RATE.
+
+Signed-off-by: Axel Lin <axel.lin@gmail.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/wm8994.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/wm8994.c
++++ b/sound/soc/codecs/wm8994.c
+@@ -2311,7 +2311,7 @@ static void wm8994_aif_shutdown(struct s
+               rate_reg = WM8994_AIF1_RATE;
+               break;
+       case 2:
+-              rate_reg = WM8994_AIF1_RATE;
++              rate_reg = WM8994_AIF2_RATE;
+               break;
+       default:
+               break;
diff --git a/queue-3.1/asoc-wm8994-use-snd_soc_dapm_aif_out-for-aif3-capture.patch b/queue-3.1/asoc-wm8994-use-snd_soc_dapm_aif_out-for-aif3-capture.patch
new file mode 100644 (file)
index 0000000..72922a6
--- /dev/null
@@ -0,0 +1,29 @@
+From 35024f4922f7b271e7529673413889aa3d51c5fc Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@gmail.com>
+Date: Thu, 20 Oct 2011 12:13:24 +0800
+Subject: ASoC: wm8994: Use SND_SOC_DAPM_AIF_OUT for AIF3 Capture
+
+From: Axel Lin <axel.lin@gmail.com>
+
+commit 35024f4922f7b271e7529673413889aa3d51c5fc upstream.
+
+Signed-off-by: Axel Lin <axel.lin@gmail.com>
+Acked-by: Liam Girdwood <lrg@ti.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/wm8994.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/wm8994.c
++++ b/sound/soc/codecs/wm8994.c
+@@ -1282,7 +1282,7 @@ SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_
+ SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
+ SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
+-SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
++SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
diff --git a/queue-3.1/asoc-wm8996-fix-wrong-mask-for-setting.patch b/queue-3.1/asoc-wm8996-fix-wrong-mask-for-setting.patch
new file mode 100644 (file)
index 0000000..989f4c3
--- /dev/null
@@ -0,0 +1,30 @@
+From 3205e6629bc0eb747fb7d1b4b8fec00b7b919e58 Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@gmail.com>
+Date: Fri, 21 Oct 2011 10:44:07 +0800
+Subject: ASoC: wm8996: Fix wrong mask for setting
+ WM8996_AIF_CLOCKING_2
+
+From: Axel Lin <axel.lin@gmail.com>
+
+commit 3205e6629bc0eb747fb7d1b4b8fec00b7b919e58 upstream.
+
+Signed-off-by: Axel Lin <axel.lin@gmail.com>
+Acked-by: Liam Girdwood <lrg@ti.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/soc/codecs/wm8996.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/wm8996.c
++++ b/sound/soc/codecs/wm8996.c
+@@ -1847,7 +1847,7 @@ static int wm8996_hw_params(struct snd_p
+       snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK,
+                           lrclk);
+       snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2,
+-                          WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp);
++                          WM8996_DSP1_DIV_MASK << dsp_shift, dsp);
+       return 0;
+ }
diff --git a/queue-3.1/carminefb-fix-module-parameters-permissions.patch b/queue-3.1/carminefb-fix-module-parameters-permissions.patch
new file mode 100644 (file)
index 0000000..46e0331
--- /dev/null
@@ -0,0 +1,61 @@
+From c84c14224bbca6ec60d5851fcc87be0e34df2f44 Mon Sep 17 00:00:00 2001
+From: Jean Delvare <jdelvare@suse.de>
+Date: Fri, 8 Jul 2011 11:04:38 +0200
+Subject: carminefb: Fix module parameters permissions
+
+From: Jean Delvare <jdelvare@suse.de>
+
+commit c84c14224bbca6ec60d5851fcc87be0e34df2f44 upstream.
+
+The third parameter of module_param is supposed to be an octal value.
+The missing leading "0" causes the following:
+
+$ ls -l /sys/module/carminefb/parameters/
+total 0
+-rw-rwxr-- 1 root root 4096 Jul  8 08:55 fb_displays
+-rw-rwxr-- 1 root root 4096 Jul  8 08:55 fb_mode
+-rw-rwxr-- 1 root root 4096 Jul  8 08:55 fb_mode_str
+
+After fixing the perm parameter, we get the expected:
+
+$ ls -l /sys/module/carminefb/parameters/
+total 0
+-r--r--r-- 1 root root 4096 Jul  8 08:56 fb_displays
+-r--r--r-- 1 root root 4096 Jul  8 08:56 fb_mode
+-r--r--r-- 1 root root 4096 Jul  8 08:56 fb_mode_str
+
+Signed-off-by: Jean Delvare <jdelvare@suse.de>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Sebastian Siewior <bigeasy@linutronix.de>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/carminefb.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/video/carminefb.c
++++ b/drivers/video/carminefb.c
+@@ -32,11 +32,11 @@
+ #define CARMINEFB_DEFAULT_VIDEO_MODE  1
+ static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+-module_param(fb_mode, uint, 444);
++module_param(fb_mode, uint, 0444);
+ MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
+ static char *fb_mode_str;
+-module_param(fb_mode_str, charp, 444);
++module_param(fb_mode_str, charp, 0444);
+ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
+ /*
+@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial v
+  * 0b010 Display 1
+  */
+ static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
+-module_param(fb_displays, int, 444);
++module_param(fb_displays, int, 0444);
+ MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
+ struct carmine_hw {
diff --git a/queue-3.1/ccwgroup-move-attributes-to-attribute-group.patch b/queue-3.1/ccwgroup-move-attributes-to-attribute-group.patch
new file mode 100644 (file)
index 0000000..ad50394
--- /dev/null
@@ -0,0 +1,125 @@
+From dbdf1afcaaabe83dea15a3cb9b9013e73ae3b1ad Mon Sep 17 00:00:00 2001
+From: Sebastian Ott <sebott@linux.vnet.ibm.com>
+Date: Sun, 30 Oct 2011 15:16:52 +0100
+Subject: [S390] ccwgroup: move attributes to attribute group
+
+From: Sebastian Ott <sebott@linux.vnet.ibm.com>
+
+commit dbdf1afcaaabe83dea15a3cb9b9013e73ae3b1ad upstream.
+
+Put sysfs attributes of ccwgroup devices in an attribute group to
+ensure that these attributes are actually present when userspace
+is notified via uevents.
+
+Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/s390/cio/ccwgroup.c |   42 ++++++++++++++++++++++--------------------
+ 1 file changed, 22 insertions(+), 20 deletions(-)
+
+--- a/drivers/s390/cio/ccwgroup.c
++++ b/drivers/s390/cio/ccwgroup.c
+@@ -87,6 +87,12 @@ static void __ccwgroup_remove_cdev_refs(
+       }
+ }
++static ssize_t ccwgroup_online_store(struct device *dev,
++                                   struct device_attribute *attr,
++                                   const char *buf, size_t count);
++static ssize_t ccwgroup_online_show(struct device *dev,
++                                  struct device_attribute *attr,
++                                  char *buf);
+ /*
+  * Provide an 'ungroup' attribute so the user can remove group devices no
+  * longer needed or accidentially created. Saves memory :)
+@@ -134,6 +140,20 @@ out:
+ }
+ static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store);
++static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
++
++static struct attribute *ccwgroup_attrs[] = {
++      &dev_attr_online.attr,
++      &dev_attr_ungroup.attr,
++      NULL,
++};
++static struct attribute_group ccwgroup_attr_group = {
++      .attrs = ccwgroup_attrs,
++};
++static const struct attribute_group *ccwgroup_attr_groups[] = {
++      &ccwgroup_attr_group,
++      NULL,
++};
+ static void
+ ccwgroup_release (struct device *dev)
+@@ -293,25 +313,17 @@ int ccwgroup_create_from_string(struct d
+       }
+       dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev));
+-
++      gdev->dev.groups = ccwgroup_attr_groups;
+       rc = device_add(&gdev->dev);
+       if (rc)
+               goto error;
+       get_device(&gdev->dev);
+-      rc = device_create_file(&gdev->dev, &dev_attr_ungroup);
+-
+-      if (rc) {
+-              device_unregister(&gdev->dev);
+-              goto error;
+-      }
+-
+       rc = __ccwgroup_create_symlinks(gdev);
+       if (!rc) {
+               mutex_unlock(&gdev->reg_mutex);
+               put_device(&gdev->dev);
+               return 0;
+       }
+-      device_remove_file(&gdev->dev, &dev_attr_ungroup);
+       device_unregister(&gdev->dev);
+ error:
+       for (i = 0; i < num_devices; i++)
+@@ -423,7 +435,7 @@ ccwgroup_online_store (struct device *de
+       int ret;
+       if (!dev->driver)
+-              return -ENODEV;
++              return -EINVAL;
+       gdev = to_ccwgroupdev(dev);
+       gdrv = to_ccwgroupdrv(dev->driver);
+@@ -456,8 +468,6 @@ ccwgroup_online_show (struct device *dev
+       return sprintf(buf, online ? "1\n" : "0\n");
+ }
+-static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
+-
+ static int
+ ccwgroup_probe (struct device *dev)
+ {
+@@ -469,12 +479,7 @@ ccwgroup_probe (struct device *dev)
+       gdev = to_ccwgroupdev(dev);
+       gdrv = to_ccwgroupdrv(dev->driver);
+-      if ((ret = device_create_file(dev, &dev_attr_online)))
+-              return ret;
+-
+       ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
+-      if (ret)
+-              device_remove_file(dev, &dev_attr_online);
+       return ret;
+ }
+@@ -485,9 +490,6 @@ ccwgroup_remove (struct device *dev)
+       struct ccwgroup_device *gdev;
+       struct ccwgroup_driver *gdrv;
+-      device_remove_file(dev, &dev_attr_online);
+-      device_remove_file(dev, &dev_attr_ungroup);
+-
+       if (!dev->driver)
+               return 0;
diff --git a/queue-3.1/dib0700-protect-the-dib0700-buffer-access.patch b/queue-3.1/dib0700-protect-the-dib0700-buffer-access.patch
new file mode 100644 (file)
index 0000000..71e6fdb
--- /dev/null
@@ -0,0 +1,250 @@
+From bff469f4167fdabfe15294f375577d7eadbaa1bb Mon Sep 17 00:00:00 2001
+From: Olivier Grenie <olivier.grenie@dibcom.fr>
+Date: Mon, 1 Aug 2011 12:45:58 -0300
+Subject: [media] dib0700: protect the dib0700 buffer access
+
+From: Olivier Grenie <olivier.grenie@dibcom.fr>
+
+commit bff469f4167fdabfe15294f375577d7eadbaa1bb upstream.
+
+This patch protects the common buffer access inside the dib0700 in order
+to manage concurrent access. This protection is done using mutex.
+
+Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
+Cc: Florian Mickler <florian@mickler.org>
+Signed-off-by: Javier Marcet <javier@marcet.info>
+Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
+Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr>
+[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info]
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/dvb/dvb-usb/dib0700_core.c |   81 +++++++++++++++++++++++++++----
+ 1 file changed, 72 insertions(+), 9 deletions(-)
+
+--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
+@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_d
+       struct dib0700_state *st = d->priv;
+       int ret;
++      if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++              deb_info("could not acquire lock");
++              return 0;
++      }
++
+       ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+                                 REQUEST_GET_VERSION,
+                                 USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_d
+       if (fwtype != NULL)
+               *fwtype     = (st->buf[12] << 24) | (st->buf[13] << 16) |
+                       (st->buf[14] << 8) | st->buf[15];
++      mutex_unlock(&d->usb_mutex);
+       return ret;
+ }
+@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_devic
+ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
+ {
+       struct dib0700_state *st = d->priv;
+-      s16 ret;
++      int ret;
++
++      if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++              deb_info("could not acquire lock");
++              return 0;
++      }
+       st->buf[0] = REQUEST_SET_GPIO;
+       st->buf[1] = gpio;
+@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_devi
+       ret = dib0700_ctrl_wr(d, st->buf, 3);
++      mutex_unlock(&d->usb_mutex);
+       return ret;
+ }
+@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(stru
+       int ret;
+       if (st->fw_version >= 0x10201) {
++              if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++                      deb_info("could not acquire lock");
++                      return 0;
++              }
++
+               st->buf[0] = REQUEST_SET_USB_XFER_LEN;
+               st->buf[1] = (nb_ts_packets >> 8) & 0xff;
+               st->buf[2] = nb_ts_packets & 0xff;
+@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(stru
+               deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
+               ret = dib0700_ctrl_wr(d, st->buf, 3);
++              mutex_unlock(&d->usb_mutex);
+       } else {
+               deb_info("this firmware does not allow to change the USB xfer len\n");
+               ret = -EIO;
+@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i
+               } else {
+                       /* Write request */
++                      if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++                              deb_info("could not acquire lock");
++                              return 0;
++                      }
+                       st->buf[0] = REQUEST_NEW_I2C_WRITE;
+                       st->buf[1] = msg[i].addr << 1;
+                       st->buf[2] = (en_start << 7) | (en_stop << 6) |
+@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i
+                                                USB_TYPE_VENDOR | USB_DIR_OUT,
+                                                0, 0, st->buf, msg[i].len + 4,
+                                                USB_CTRL_GET_TIMEOUT);
++                      mutex_unlock(&d->usb_mutex);
+                       if (result < 0) {
+                               deb_info("i2c write error (status = %d)\n", result);
+                               break;
+@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struc
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
++      if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++              deb_info("could not acquire lock");
++              return 0;
++      }
+       for (i = 0; i < num; i++) {
+               /* fill in the address */
+@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struc
+                               break;
+               }
+       }
++      mutex_unlock(&d->usb_mutex);
+       mutex_unlock(&d->i2c_mutex);
+       return i;
+@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_
+       u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
+ {
+       struct dib0700_state *st = d->priv;
+-      s16 ret;
++      int ret;
++
++      if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++              deb_info("could not acquire lock");
++              return 0;
++      }
+       st->buf[0] = REQUEST_SET_CLOCK;
+       st->buf[1] = (en_pll << 7) | (pll_src << 6) |
+@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_
+       st->buf[9] =  dsuScaler         & 0xff; /* LSB */
+       ret = dib0700_ctrl_wr(d, st->buf, 10);
++      mutex_unlock(&d->usb_mutex);
+       return ret;
+ }
+@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb
+ {
+       struct dib0700_state *st = d->priv;
+       u16 divider;
++      int ret;
+       if (scl_kHz == 0)
+               return -EINVAL;
++      if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++              deb_info("could not acquire lock");
++              return 0;
++      }
++
+       st->buf[0] = REQUEST_SET_I2C_PARAM;
+       divider = (u16) (30000 / scl_kHz);
+       st->buf[1] = 0;
+@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb
+       deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
+               (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
+               st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
+-      return dib0700_ctrl_wr(d, st->buf, 8);
++
++      ret = dib0700_ctrl_wr(d, st->buf, 8);
++      mutex_unlock(&d->usb_mutex);
++
++      return ret;
+ }
+@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_us
+               }
+       }
++      if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
++              deb_info("could not acquire lock");
++              return 0;
++      }
++
+       st->buf[0] = REQUEST_ENABLE_VIDEO;
+       /* this bit gives a kind of command,
+        * rather than enabling something or not */
+@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_us
+       deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
+-      return dib0700_ctrl_wr(adap->dev, st->buf, 4);
++      ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
++      mutex_unlock(&adap->dev->usb_mutex);
++
++      return ret;
+ }
+ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_de
+       struct dib0700_state *st = d->priv;
+       int new_proto, ret;
++      if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++              deb_info("could not acquire lock");
++              return 0;
++      }
++
+       st->buf[0] = REQUEST_SET_RC;
+       st->buf[1] = 0;
+       st->buf[2] = 0;
+@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_de
+       else if (rc_type == RC_TYPE_NEC)
+               new_proto = 0;
+       else if (rc_type == RC_TYPE_RC6) {
+-              if (st->fw_version < 0x10200)
+-                      return -EINVAL;
++              if (st->fw_version < 0x10200) {
++                      ret = -EINVAL;
++                      goto out;
++              }
+               new_proto = 2;
+-      } else
+-              return -EINVAL;
++      } else {
++              ret = -EINVAL;
++              goto out;
++      }
+       st->buf[1] = new_proto;
+       ret = dib0700_ctrl_wr(d, st->buf, 3);
+       if (ret < 0) {
+               err("ir protocol setup failed");
+-              return ret;
++              goto out;
+       }
+       d->props.rc.core.protocol = rc_type;
++out:
++      mutex_unlock(&d->usb_mutex);
+       return ret;
+ }
diff --git a/queue-3.1/dibcom-protect-the-i2c-bufer-access.patch b/queue-3.1/dibcom-protect-the-i2c-bufer-access.patch
new file mode 100644 (file)
index 0000000..c3ac700
--- /dev/null
@@ -0,0 +1,1145 @@
+From 79fcce3230b140f7675f8529ee53fe2f9644f902 Mon Sep 17 00:00:00 2001
+From: Patrick Boettcher <Patrick.Boettcher@dibcom.fr>
+Date: Wed, 3 Aug 2011 12:08:21 -0300
+Subject: [media] DiBcom: protect the I2C bufer access
+
+From: Patrick Boettcher <Patrick.Boettcher@dibcom.fr>
+
+commit 79fcce3230b140f7675f8529ee53fe2f9644f902 upstream.
+
+This patch protects the I2C buffer access in order to manage concurrent
+access. This protection is done using mutex.
+Furthermore, for the dib9000, if a pid filtering command is
+received during the tuning, this pid filtering command is delayed to
+avoid any concurrent access issue.
+
+Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
+Cc: Florian Mickler <florian@mickler.org>
+Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
+Signed-off-by: Patrick Boettcher <Patrick.Boettcher@dibcom.fr>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/dvb/frontends/dib0070.c        |   37 ++++--
+ drivers/media/dvb/frontends/dib0090.c        |   70 +++++++++--
+ drivers/media/dvb/frontends/dib7000m.c       |   27 ++++
+ drivers/media/dvb/frontends/dib7000p.c       |   32 ++++-
+ drivers/media/dvb/frontends/dib8000.c        |   72 ++++++++++-
+ drivers/media/dvb/frontends/dib9000.c        |  164 +++++++++++++++++++++++----
+ drivers/media/dvb/frontends/dibx000_common.c |   76 ++++++++++--
+ drivers/media/dvb/frontends/dibx000_common.h |    1 
+ 8 files changed, 412 insertions(+), 67 deletions(-)
+
+--- a/drivers/media/dvb/frontends/dib0070.c
++++ b/drivers/media/dvb/frontends/dib0070.c
+@@ -27,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+ #include "dvb_frontend.h"
+@@ -78,10 +79,18 @@ struct dib0070_state {
+       struct i2c_msg msg[2];
+       u8 i2c_write_buffer[3];
+       u8 i2c_read_buffer[2];
++      struct mutex i2c_buffer_lock;
+ };
+-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
++static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
+ {
++      u16 ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
+       state->i2c_write_buffer[0] = reg;
+       memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct
+       if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+               printk(KERN_WARNING "DiB0070 I2C read failed\n");
+-              return 0;
+-      }
+-      return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++              ret = 0;
++      } else
++              ret = (state->i2c_read_buffer[0] << 8)
++                      | state->i2c_read_buffer[1];
++
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
+ {
++      int ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
+       state->i2c_write_buffer[0] = reg;
+       state->i2c_write_buffer[1] = val >> 8;
+       state->i2c_write_buffer[2] = val & 0xff;
+@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0
+       if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+               printk(KERN_WARNING "DiB0070 I2C write failed\n");
+-              return -EREMOTEIO;
+-      }
+-      return 0;
++              ret = -EREMOTEIO;
++      } else
++              ret = 0;
++
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ #define HARD_RESET(state) do { \
+@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(stru
+       state->cfg = cfg;
+       state->i2c = i2c;
+       state->fe  = fe;
++      mutex_init(&state->i2c_buffer_lock);
+       fe->tuner_priv = state;
+       if (dib0070_reset(fe) != 0)
+--- a/drivers/media/dvb/frontends/dib0090.c
++++ b/drivers/media/dvb/frontends/dib0090.c
+@@ -27,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+ #include "dvb_frontend.h"
+@@ -196,6 +197,7 @@ struct dib0090_state {
+       struct i2c_msg msg[2];
+       u8 i2c_write_buffer[3];
+       u8 i2c_read_buffer[2];
++      struct mutex i2c_buffer_lock;
+ };
+ struct dib0090_fw_state {
+@@ -208,10 +210,18 @@ struct dib0090_fw_state {
+       struct i2c_msg msg;
+       u8 i2c_write_buffer[2];
+       u8 i2c_read_buffer[2];
++      struct mutex i2c_buffer_lock;
+ };
+ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
+ {
++      u16 ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
+       state->i2c_write_buffer[0] = reg;
+       memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib00
+       if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+               printk(KERN_WARNING "DiB0090 I2C read failed\n");
+-              return 0;
+-      }
++              ret = 0;
++      } else
++              ret = (state->i2c_read_buffer[0] << 8)
++                      | state->i2c_read_buffer[1];
+-      return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
+ {
++      int ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
+       state->i2c_write_buffer[0] = reg & 0xff;
+       state->i2c_write_buffer[1] = val >> 8;
+       state->i2c_write_buffer[2] = val & 0xff;
+@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0
+       if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+               printk(KERN_WARNING "DiB0090 I2C write failed\n");
+-              return -EREMOTEIO;
+-      }
+-      return 0;
++              ret = -EREMOTEIO;
++      } else
++              ret = 0;
++
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
+ {
++      u16 ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
+       state->i2c_write_buffer[0] = reg;
+       memset(&state->msg, 0, sizeof(struct i2c_msg));
+@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct di
+       state->msg.len = 2;
+       if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+               printk(KERN_WARNING "DiB0090 I2C read failed\n");
+-              return 0;
+-      }
+-      return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++              ret = 0;
++      } else
++              ret = (state->i2c_read_buffer[0] << 8)
++                      | state->i2c_read_buffer[1];
++
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
+ {
++      int ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
+       state->i2c_write_buffer[0] = val >> 8;
+       state->i2c_write_buffer[1] = val & 0xff;
+@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct d
+       state->msg.len = 2;
+       if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+               printk(KERN_WARNING "DiB0090 I2C write failed\n");
+-              return -EREMOTEIO;
+-      }
+-      return 0;
++              ret = -EREMOTEIO;
++      } else
++              ret = 0;
++
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ #define HARD_RESET(state) do {  if (cfg->reset) {  if (cfg->sleep) cfg->sleep(fe, 0); msleep(10);  cfg->reset(fe, 1); msleep(10);  cfg->reset(fe, 0); msleep(10);  }  } while (0)
+@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(st
+       st->config = config;
+       st->i2c = i2c;
+       st->fe = fe;
++      mutex_init(&st->i2c_buffer_lock);
+       fe->tuner_priv = st;
+       if (config->wbd == NULL)
+@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register
+       st->config = config;
+       st->i2c = i2c;
+       st->fe = fe;
++      mutex_init(&st->i2c_buffer_lock);
+       fe->tuner_priv = st;
+       if (dib0090_fw_reset_digital(fe, st->config) != 0)
+--- a/drivers/media/dvb/frontends/dib7000m.c
++++ b/drivers/media/dvb/frontends/dib7000m.c
+@@ -11,6 +11,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+ #include "dvb_frontend.h"
+@@ -55,6 +56,7 @@ struct dib7000m_state {
+       struct i2c_msg msg[2];
+       u8 i2c_write_buffer[4];
+       u8 i2c_read_buffer[2];
++      struct mutex i2c_buffer_lock;
+ };
+ enum dib7000m_power_mode {
+@@ -69,6 +71,13 @@ enum dib7000m_power_mode {
+ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+ {
++      u16 ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
+       state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
+       state->i2c_write_buffer[1] = reg & 0xff;
+@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib
+       if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+               dprintk("i2c read error on %d",reg);
+-      return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++      ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++      mutex_unlock(&state->i2c_buffer_lock);
++
++      return ret;
+ }
+ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+ {
++      int ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
+       state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+       state->i2c_write_buffer[1] = reg & 0xff;
+       state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct di
+       state->msg[0].buf = state->i2c_write_buffer;
+       state->msg[0].len = 4;
+-      return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++      ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
++                      -EREMOTEIO : 0);
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
+ {
+@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(st
+       demod                   = &st->demod;
+       demod->demodulator_priv = st;
+       memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
++      mutex_init(&st->i2c_buffer_lock);
+       st->timf_default = cfg->bw->timf;
+--- a/drivers/media/dvb/frontends/dib7000p.c
++++ b/drivers/media/dvb/frontends/dib7000p.c
+@@ -10,6 +10,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+ #include "dvb_math.h"
+ #include "dvb_frontend.h"
+@@ -68,6 +69,7 @@ struct dib7000p_state {
+       struct i2c_msg msg[2];
+       u8 i2c_write_buffer[4];
+       u8 i2c_read_buffer[2];
++      struct mutex i2c_buffer_lock;
+ };
+ enum dib7000p_power_mode {
+@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(stru
+ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+ {
++      u16 ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
+       state->i2c_write_buffer[0] = reg >> 8;
+       state->i2c_write_buffer[1] = reg & 0xff;
+@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib
+       if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+               dprintk("i2c read error on %d", reg);
+-      return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++      ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+ {
++      int ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
+       state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+       state->i2c_write_buffer[1] = reg & 0xff;
+       state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct di
+       state->msg[0].buf = state->i2c_write_buffer;
+       state->msg[0].len = 4;
+-      return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++      ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
++                      -EREMOTEIO : 0);
++      mutex_unlock(&state->i2c_buffer_lock);
++      return ret;
+ }
+ static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
+@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_
+               return -ENOMEM;
+       dpst->i2c_adap = i2c;
++      mutex_init(&dpst->i2c_buffer_lock);
+       for (k = no_of_demods - 1; k >= 0; k--) {
+               dpst->cfg = cfg[k];
+@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(str
+       demod = &st->demod;
+       demod->demodulator_priv = st;
+       memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
++      mutex_init(&st->i2c_buffer_lock);
+       dib7000p_write_word(st, 1287, 0x0003);  /* sram lead in, rdy */
+@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(str
+       st->version = dib7000p_read_word(st, 897);
+       /* FIXME: make sure the dev.parent field is initialized, or else
+-              request_firmware() will hit an OOPS (this should be moved somewhere
+-              more common) */
++         request_firmware() will hit an OOPS (this should be moved somewhere
++         more common) */
++      st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+       /* FIXME: make sure the dev.parent field is initialized, or else
+          request_firmware() will hit an OOPS (this should be moved somewhere
+--- a/drivers/media/dvb/frontends/dib8000.c
++++ b/drivers/media/dvb/frontends/dib8000.c
+@@ -10,6 +10,8 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
++
+ #include "dvb_math.h"
+ #include "dvb_frontend.h"
+@@ -37,6 +39,7 @@ struct i2c_device {
+       u8 addr;
+       u8 *i2c_write_buffer;
+       u8 *i2c_read_buffer;
++      struct mutex *i2c_buffer_lock;
+ };
+ struct dib8000_state {
+@@ -77,6 +80,7 @@ struct dib8000_state {
+       struct i2c_msg msg[2];
+       u8 i2c_write_buffer[4];
+       u8 i2c_read_buffer[2];
++      struct mutex i2c_buffer_lock;
+ };
+ enum dib8000_power_mode {
+@@ -86,24 +90,39 @@ enum dib8000_power_mode {
+ static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
+ {
++      u16 ret;
+       struct i2c_msg msg[2] = {
+-              {.addr = i2c->addr >> 1, .flags = 0,
+-                      .buf = i2c->i2c_write_buffer, .len = 2},
+-              {.addr = i2c->addr >> 1, .flags = I2C_M_RD,
+-                      .buf = i2c->i2c_read_buffer, .len = 2},
++              {.addr = i2c->addr >> 1, .flags = 0, .len = 2},
++              {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
+       };
++      if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
++      msg[0].buf    = i2c->i2c_write_buffer;
+       msg[0].buf[0] = reg >> 8;
+       msg[0].buf[1] = reg & 0xff;
++      msg[1].buf    = i2c->i2c_read_buffer;
+       if (i2c_transfer(i2c->adap, msg, 2) != 2)
+               dprintk("i2c read error on %d", reg);
+-      return (msg[1].buf[0] << 8) | msg[1].buf[1];
++      ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
++      mutex_unlock(i2c->i2c_buffer_lock);
++      return ret;
+ }
+ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+ {
++      u16 ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
+       state->i2c_write_buffer[0] = reg >> 8;
+       state->i2c_write_buffer[1] = reg & 0xff;
+@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8
+       if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
+               dprintk("i2c read error on %d", reg);
+-      return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++      ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++      mutex_unlock(&state->i2c_buffer_lock);
++
++      return ret;
+ }
+ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
+@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000
+ static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+ {
+-      struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
+-              .buf = i2c->i2c_write_buffer, .len = 4};
++      struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
+       int ret = 0;
++      if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
++      msg.buf    = i2c->i2c_write_buffer;
+       msg.buf[0] = (reg >> 8) & 0xff;
+       msg.buf[1] = reg & 0xff;
+       msg.buf[2] = (val >> 8) & 0xff;
+       msg.buf[3] = val & 0xff;
+       ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++      mutex_unlock(i2c->i2c_buffer_lock);
+       return ret;
+ }
+ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
+ {
++      int ret;
++
++      if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
+       state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+       state->i2c_write_buffer[1] = reg & 0xff;
+       state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib
+       state->msg[0].buf = state->i2c_write_buffer;
+       state->msg[0].len = 4;
+-      return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++      ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
++                      -EREMOTEIO : 0);
++      mutex_unlock(&state->i2c_buffer_lock);
++
++      return ret;
+ }
+ static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
+@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_a
+       if (!client.i2c_read_buffer) {
+               dprintk("%s: not enough memory", __func__);
+               ret = -ENOMEM;
+-              goto error_memory;
++              goto error_memory_read;
++      }
++      client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
++      if (!client.i2c_buffer_lock) {
++              dprintk("%s: not enough memory", __func__);
++              ret = -ENOMEM;
++              goto error_memory_lock;
+       }
++      mutex_init(client.i2c_buffer_lock);
+       for (k = no_of_demods - 1; k >= 0; k--) {
+               /* designated i2c address */
+@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_a
+       }
+ error:
++      kfree(client.i2c_buffer_lock);
++error_memory_lock:
+       kfree(client.i2c_read_buffer);
+-error_memory:
++error_memory_read:
+       kfree(client.i2c_write_buffer);
+       return ret;
+@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(stru
+       state->i2c.addr = i2c_addr;
+       state->i2c.i2c_write_buffer = state->i2c_write_buffer;
+       state->i2c.i2c_read_buffer = state->i2c_read_buffer;
++      mutex_init(&state->i2c_buffer_lock);
++      state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
+       state->gpio_val = cfg->gpio_val;
+       state->gpio_dir = cfg->gpio_dir;
+--- a/drivers/media/dvb/frontends/dib9000.c
++++ b/drivers/media/dvb/frontends/dib9000.c
+@@ -38,6 +38,15 @@ struct i2c_device {
+ #define DibInitLock(lock) mutex_init(lock)
+ #define DibFreeLock(lock)
++struct dib9000_pid_ctrl {
++#define DIB9000_PID_FILTER_CTRL 0
++#define DIB9000_PID_FILTER      1
++      u8 cmd;
++      u8 id;
++      u16 pid;
++      u8 onoff;
++};
++
+ struct dib9000_state {
+       struct i2c_device i2c;
+@@ -99,6 +108,10 @@ struct dib9000_state {
+       struct i2c_msg msg[2];
+       u8 i2c_write_buffer[255];
+       u8 i2c_read_buffer[255];
++      DIB_LOCK demod_lock;
++      u8 get_frontend_internal;
++      struct dib9000_pid_ctrl pid_ctrl[10];
++      s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
+ };
+ static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio);
+ int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+ {
+       struct dib9000_state *state = fe->demodulator_priv;
+-      u16 val = dib9000_read_word(state, 294 + 1) & 0xffef;
++      u16 val;
++      int ret;
++
++      if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
++              /* postpone the pid filtering cmd */
++              dprintk("pid filter cmd postpone");
++              state->pid_ctrl_index++;
++              state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
++              state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
++              return 0;
++      }
++
++      DibAcquireLock(&state->demod_lock);
++
++      val = dib9000_read_word(state, 294 + 1) & 0xffef;
+       val |= (onoff & 0x1) << 4;
+       dprintk("PID filter enabled %d", onoff);
+-      return dib9000_write_word(state, 294 + 1, val);
++      ret = dib9000_write_word(state, 294 + 1, val);
++      DibReleaseLock(&state->demod_lock);
++      return ret;
++
+ }
+ EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
+ int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+ {
+       struct dib9000_state *state = fe->demodulator_priv;
++      int ret;
++
++      if (state->pid_ctrl_index != -2) {
++              /* postpone the pid filtering cmd */
++              dprintk("pid filter postpone");
++              if (state->pid_ctrl_index < 9) {
++                      state->pid_ctrl_index++;
++                      state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
++                      state->pid_ctrl[state->pid_ctrl_index].id = id;
++                      state->pid_ctrl[state->pid_ctrl_index].pid = pid;
++                      state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
++              } else
++                      dprintk("can not add any more pid ctrl cmd");
++              return 0;
++      }
++
++      DibAcquireLock(&state->demod_lock);
+       dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+-      return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0);
++      ret = dib9000_write_word(state, 300 + 1 + id,
++                      onoff ? (1 << 13) | pid : 0);
++      DibReleaseLock(&state->demod_lock);
++      return ret;
+ }
+ EXPORT_SYMBOL(dib9000_fw_pid_filter);
+@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_f
+       DibFreeLock(&state->platform.risc.mbx_lock);
+       DibFreeLock(&state->platform.risc.mem_lock);
+       DibFreeLock(&state->platform.risc.mem_mbx_lock);
++      DibFreeLock(&state->demod_lock);
+       dibx000_exit_i2c_master(&st->i2c_master);
+       i2c_del_adapter(&st->tuner_adap);
+@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_fron
+ {
+       struct dib9000_state *state = fe->demodulator_priv;
+       u8 index_frontend;
+-      int ret;
++      int ret = 0;
++      DibAcquireLock(&state->demod_lock);
+       for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+               ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
+               if (ret < 0)
+-                      return ret;
++                      goto error;
+       }
+-      return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
++      ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
++
++error:
++      DibReleaseLock(&state->demod_lock);
++      return ret;
+ }
+ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
+@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct d
+       struct dib9000_state *state = fe->demodulator_priv;
+       u8 index_frontend, sub_index_frontend;
+       fe_status_t stat;
+-      int ret;
++      int ret = 0;
++
++      if (state->get_frontend_internal == 0)
++              DibAcquireLock(&state->demod_lock);
+       for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+               state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
+@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct d
+                                           state->fe[index_frontend]->dtv_property_cache.rolloff;
+                               }
+                       }
+-                      return 0;
++                      ret = 0;
++                      goto return_value;
+               }
+       }
+       /* get the channel from master chip */
+       ret = dib9000_fw_get_channel(fe, fep);
+       if (ret != 0)
+-              return ret;
++              goto return_value;
+       /* synchronize the cache with the other frontends */
+       for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct d
+               state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
+               state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
+       }
++      ret = 0;
+-      return 0;
++return_value:
++      if (state->get_frontend_internal == 0)
++              DibReleaseLock(&state->demod_lock);
++      return ret;
+ }
+ static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct d
+               dprintk("dib9000: must specify bandwidth ");
+               return 0;
+       }
++
++      state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
++      DibAcquireLock(&state->demod_lock);
++
+       fe->dtv_property_cache.delivery_system = SYS_DVBT;
+       /* set the master status */
+@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct d
+       /* check the tune result */
+       if (exit_condition == 1) {      /* tune failed */
+               dprintk("tune failed");
++              DibReleaseLock(&state->demod_lock);
++              /* tune failed; put all the pid filtering cmd to junk */
++              state->pid_ctrl_index = -1;
+               return 0;
+       }
+       dprintk("tune success on frontend%i", index_frontend_success);
+       /* synchronize all the channel cache */
++      state->get_frontend_internal = 1;
+       dib9000_get_frontend(state->fe[0], fep);
++      state->get_frontend_internal = 0;
+       /* retune the other frontends with the found channel */
+       channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
+@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct d
+       /* turn off the diversity for the last frontend */
+       dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
++      DibReleaseLock(&state->demod_lock);
++      if (state->pid_ctrl_index >= 0) {
++              u8 index_pid_filter_cmd;
++              u8 pid_ctrl_index = state->pid_ctrl_index;
++
++              state->pid_ctrl_index = -2;
++              for (index_pid_filter_cmd = 0;
++                              index_pid_filter_cmd <= pid_ctrl_index;
++                              index_pid_filter_cmd++) {
++                      if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
++                              dib9000_fw_pid_filter_ctrl(state->fe[0],
++                                              state->pid_ctrl[index_pid_filter_cmd].onoff);
++                      else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
++                              dib9000_fw_pid_filter(state->fe[0],
++                                              state->pid_ctrl[index_pid_filter_cmd].id,
++                                              state->pid_ctrl[index_pid_filter_cmd].pid,
++                                              state->pid_ctrl[index_pid_filter_cmd].onoff);
++              }
++      }
++      /* do not postpone any more the pid filtering */
++      state->pid_ctrl_index = -2;
++
+       return 0;
+ }
+@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dv
+       u8 index_frontend;
+       u16 lock = 0, lock_slave = 0;
++      DibAcquireLock(&state->demod_lock);
+       for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+               lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
+@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dv
+       if ((lock & 0x0008) || (lock_slave & 0x0008))
+               *stat |= FE_HAS_LOCK;
++      DibReleaseLock(&state->demod_lock);
++
+       return 0;
+ }
+@@ -2066,10 +2164,14 @@ static int dib9000_read_ber(struct dvb_f
+ {
+       struct dib9000_state *state = fe->demodulator_priv;
+       u16 *c;
++      int ret = 0;
++      DibAcquireLock(&state->demod_lock);
+       DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+-      if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+-              return -EIO;
++      if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
++              ret = -EIO;
++              goto error;
++      }
+       dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
+                       state->i2c_read_buffer, 16 * 2);
+       DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+@@ -2077,7 +2179,10 @@ static int dib9000_read_ber(struct dvb_f
+       c = (u16 *)state->i2c_read_buffer;
+       *ber = c[10] << 16 | c[11];
+-      return 0;
++
++error:
++      DibReleaseLock(&state->demod_lock);
++      return ret;
+ }
+ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+@@ -2086,7 +2191,9 @@ static int dib9000_read_signal_strength(
+       u8 index_frontend;
+       u16 *c = (u16 *)state->i2c_read_buffer;
+       u16 val;
++      int ret = 0;
++      DibAcquireLock(&state->demod_lock);
+       *strength = 0;
+       for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+               state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
+@@ -2097,8 +2204,10 @@ static int dib9000_read_signal_strength(
+       }
+       DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+-      if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+-              return -EIO;
++      if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
++              ret = -EIO;
++              goto error;
++      }
+       dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+       DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+@@ -2107,7 +2216,10 @@ static int dib9000_read_signal_strength(
+               *strength = 65535;
+       else
+               *strength += val;
+-      return 0;
++
++error:
++      DibReleaseLock(&state->demod_lock);
++      return ret;
+ }
+ static u32 dib9000_get_snr(struct dvb_frontend *fe)
+@@ -2151,6 +2263,7 @@ static int dib9000_read_snr(struct dvb_f
+       u8 index_frontend;
+       u32 snr_master;
++      DibAcquireLock(&state->demod_lock);
+       snr_master = dib9000_get_snr(fe);
+       for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+               snr_master += dib9000_get_snr(state->fe[index_frontend]);
+@@ -2161,6 +2274,8 @@ static int dib9000_read_snr(struct dvb_f
+       } else
+               *snr = 0;
++      DibReleaseLock(&state->demod_lock);
++
+       return 0;
+ }
+@@ -2168,15 +2283,22 @@ static int dib9000_read_unc_blocks(struc
+ {
+       struct dib9000_state *state = fe->demodulator_priv;
+       u16 *c = (u16 *)state->i2c_read_buffer;
++      int ret = 0;
++      DibAcquireLock(&state->demod_lock);
+       DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+-      if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+-              return -EIO;
++      if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
++              ret = -EIO;
++              goto error;
++      }
+       dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+       DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+       *unc = c[12];
+-      return 0;
++
++error:
++      DibReleaseLock(&state->demod_lock);
++      return ret;
+ }
+ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
+@@ -2322,6 +2444,10 @@ struct dvb_frontend *dib9000_attach(stru
+       DibInitLock(&st->platform.risc.mbx_lock);
+       DibInitLock(&st->platform.risc.mem_lock);
+       DibInitLock(&st->platform.risc.mem_mbx_lock);
++      DibInitLock(&st->demod_lock);
++      st->get_frontend_internal = 0;
++
++      st->pid_ctrl_index = -2;
+       st->fe[0] = fe;
+       fe->demodulator_priv = st;
+--- a/drivers/media/dvb/frontends/dibx000_common.c
++++ b/drivers/media/dvb/frontends/dibx000_common.c
+@@ -1,4 +1,5 @@
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+ #include "dibx000_common.h"
+@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debuggi
+ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+ {
++      int ret;
++
++      if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
+       mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+       mst->i2c_write_buffer[1] = reg & 0xff;
+       mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dib
+       mst->msg[0].buf = mst->i2c_write_buffer;
+       mst->msg[0].len = 4;
+-      return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
++      ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
++      mutex_unlock(&mst->i2c_buffer_lock);
++
++      return ret;
+ }
+ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
+ {
++      u16 ret;
++
++      if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return 0;
++      }
++
+       mst->i2c_write_buffer[0] = reg >> 8;
+       mst->i2c_write_buffer[1] = reg & 0xff;
+@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx
+       if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
+               dprintk("i2c read error on %d", reg);
+-      return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
++      ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
++      mutex_unlock(&mst->i2c_buffer_lock);
++
++      return ret;
+ }
+ static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
+@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer
+                                       struct i2c_msg msg[], int num)
+ {
+       struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
++      int ret;
+       if (num > 32) {
+               dprintk("%s: too much I2C message to be transmitted (%i).\
+@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer
+               return -ENOMEM;
+       }
+-      memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+-
+       dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
++      if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++
++      memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
++
+       /* open the gate */
+       dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+       mst->msg[0].addr = mst->i2c_addr;
+@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer
+       mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+       mst->msg[num + 1].len = 4;
+-      return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
++      ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
++                      num : -EIO);
++
++      mutex_unlock(&mst->i2c_buffer_lock);
++      return ret;
+ }
+ static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
+@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(
+                                       struct i2c_msg msg[], int num)
+ {
+       struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
++      int ret;
+       if (num > 32) {
+               dprintk("%s: too much I2C message to be transmitted (%i).\
+@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(
+               return -ENOMEM;
+       }
+-      memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+-
+       dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
++      if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++      memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
++
+       /* open the gate */
+       dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+       mst->msg[0].addr = mst->i2c_addr;
+@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(
+       mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+       mst->msg[num + 1].len = 4;
+-      return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
++      ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
++                      num : -EIO);
++      mutex_unlock(&mst->i2c_buffer_lock);
++      return ret;
+ }
+ static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
+@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_a
+ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
+                               struct i2c_adapter *i2c_adap, u8 i2c_addr)
+ {
+-      u8 tx[4];
+-      struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
++      int ret;
++
++      mutex_init(&mst->i2c_buffer_lock);
++      if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++              dprintk("could not acquire lock");
++              return -EINVAL;
++      }
++      memset(mst->msg, 0, sizeof(struct i2c_msg));
++      mst->msg[0].addr = i2c_addr >> 1;
++      mst->msg[0].flags = 0;
++      mst->msg[0].buf = mst->i2c_write_buffer;
++      mst->msg[0].len = 4;
+       mst->device_rev = device_rev;
+       mst->i2c_adap = i2c_adap;
+@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx0
+                               "DiBX000: could not initialize the master i2c_adapter\n");
+       /* initialize the i2c-master by closing the gate */
+-      dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
++      dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
++
++      ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
++      mutex_unlock(&mst->i2c_buffer_lock);
+-      return i2c_transfer(i2c_adap, &m, 1) == 1;
++      return ret;
+ }
+ EXPORT_SYMBOL(dibx000_init_i2c_master);
+--- a/drivers/media/dvb/frontends/dibx000_common.h
++++ b/drivers/media/dvb/frontends/dibx000_common.h
+@@ -33,6 +33,7 @@ struct dibx000_i2c_master {
+       struct i2c_msg msg[34];
+       u8 i2c_write_buffer[8];
+       u8 i2c_read_buffer[2];
++      struct mutex i2c_buffer_lock;
+ };
+ extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
diff --git a/queue-3.1/fb-avoid-possible-deadlock-caused-by-fb_set_suspend.patch b/queue-3.1/fb-avoid-possible-deadlock-caused-by-fb_set_suspend.patch
new file mode 100644 (file)
index 0000000..10d1e3f
--- /dev/null
@@ -0,0 +1,150 @@
+From 9e769ff3f585db8f978f9113be83d36c7e3965dd Mon Sep 17 00:00:00 2001
+From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+Date: Fri, 17 Jun 2011 19:02:39 +0000
+Subject: fb: avoid possible deadlock caused by fb_set_suspend
+
+From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+
+commit 9e769ff3f585db8f978f9113be83d36c7e3965dd upstream.
+
+A lock ordering issue can cause deadlocks: in framebuffer/console code,
+all needed struct fb_info locks are taken before acquire_console_sem(),
+in places which need to take console semaphore.
+
+But fb_set_suspend is always called with console semaphore held, and
+inside it we call lock_fb_info which gets the fb_info lock, inverse
+locking order of what the rest of the code does. This causes a real
+deadlock issue, when we write to state fb sysfs attribute (which calls
+fb_set_suspend) while a framebuffer is being unregistered by
+remove_conflicting_framebuffers, as can be shown by following show
+blocked state trace on a test program which loads i915 and runs another
+forked processes writing to state attribute:
+
+Test process with semaphore held and trying to get fb_info lock:
+..
+fb-test2      D 0000000000000000     0   237    228 0x00000000
+ ffff8800774f3d68 0000000000000082 00000000000135c0 00000000000135c0
+ ffff880000000000 ffff8800774f3fd8 ffff8800774f3fd8 ffff880076ee4530
+ 00000000000135c0 ffff8800774f3fd8 ffff8800774f2000 00000000000135c0
+Call Trace:
+ [<ffffffff8141287a>] __mutex_lock_slowpath+0x11a/0x1e0
+ [<ffffffff814142f2>] ? _raw_spin_lock_irq+0x22/0x40
+ [<ffffffff814123d3>] mutex_lock+0x23/0x50
+ [<ffffffff8125dfc5>] lock_fb_info+0x25/0x60
+ [<ffffffff8125e3f0>] fb_set_suspend+0x20/0x80
+ [<ffffffff81263e2f>] store_fbstate+0x4f/0x70
+ [<ffffffff812e7f70>] dev_attr_store+0x20/0x30
+ [<ffffffff811c46b4>] sysfs_write_file+0xd4/0x160
+ [<ffffffff81155a26>] vfs_write+0xc6/0x190
+ [<ffffffff81155d51>] sys_write+0x51/0x90
+ [<ffffffff8100c012>] system_call_fastpath+0x16/0x1b
+..
+modprobe process stalled because has the fb_info lock (got inside
+unregister_framebuffer) but waiting for the semaphore held by the
+test process which is waiting to get the fb_info lock:
+..
+modprobe      D 0000000000000000     0   230    218 0x00000000
+ ffff880077a4d618 0000000000000082 0000000000000001 0000000000000001
+ ffff880000000000 ffff880077a4dfd8 ffff880077a4dfd8 ffff8800775a2e20
+ 00000000000135c0 ffff880077a4dfd8 ffff880077a4c000 00000000000135c0
+Call Trace:
+ [<ffffffff81411fe5>] schedule_timeout+0x215/0x310
+ [<ffffffff81058051>] ? get_parent_ip+0x11/0x50
+ [<ffffffff814130dd>] __down+0x6d/0xb0
+ [<ffffffff81089f71>] down+0x41/0x50
+ [<ffffffff810629ac>] acquire_console_sem+0x2c/0x50
+ [<ffffffff812ca53d>] unbind_con_driver+0xad/0x2d0
+ [<ffffffff8126f5f7>] fbcon_event_notify+0x457/0x890
+ [<ffffffff814144ff>] ? _raw_spin_unlock_irqrestore+0x1f/0x50
+ [<ffffffff81058051>] ? get_parent_ip+0x11/0x50
+ [<ffffffff8141836d>] notifier_call_chain+0x4d/0x70
+ [<ffffffff8108a3b8>] __blocking_notifier_call_chain+0x58/0x80
+ [<ffffffff8108a3f6>] blocking_notifier_call_chain+0x16/0x20
+ [<ffffffff8125dabb>] fb_notifier_call_chain+0x1b/0x20
+ [<ffffffff8125e6ac>] unregister_framebuffer+0x7c/0x130
+ [<ffffffff8125e8b3>] remove_conflicting_framebuffers+0x153/0x180
+ [<ffffffff8125eef3>] register_framebuffer+0x93/0x2c0
+ [<ffffffffa0331112>] drm_fb_helper_single_fb_probe+0x252/0x2f0 [drm_kms_helper]
+ [<ffffffffa03314a3>] drm_fb_helper_initial_config+0x2f3/0x6d0 [drm_kms_helper]
+ [<ffffffffa03318dd>] ? drm_fb_helper_single_add_all_connectors+0x5d/0x1c0 [drm_kms_helper]
+ [<ffffffffa037b588>] intel_fbdev_init+0xa8/0x160 [i915]
+ [<ffffffffa0343d74>] i915_driver_load+0x854/0x12b0 [i915]
+ [<ffffffffa02f0e7e>] drm_get_pci_dev+0x19e/0x360 [drm]
+ [<ffffffff8141821d>] ? sub_preempt_count+0x9d/0xd0
+ [<ffffffffa0386f91>] i915_pci_probe+0x15/0x17 [i915]
+ [<ffffffff8124481f>] local_pci_probe+0x5f/0xd0
+ [<ffffffff81244f89>] pci_device_probe+0x119/0x120
+ [<ffffffff812eccaa>] ? driver_sysfs_add+0x7a/0xb0
+ [<ffffffff812ed003>] driver_probe_device+0xa3/0x290
+ [<ffffffff812ed1f0>] ? __driver_attach+0x0/0xb0
+ [<ffffffff812ed29b>] __driver_attach+0xab/0xb0
+ [<ffffffff812ed1f0>] ? __driver_attach+0x0/0xb0
+ [<ffffffff812ebd3e>] bus_for_each_dev+0x5e/0x90
+ [<ffffffff812ecc2e>] driver_attach+0x1e/0x20
+ [<ffffffff812ec6f2>] bus_add_driver+0xe2/0x320
+ [<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
+ [<ffffffff812ed536>] driver_register+0x76/0x140
+ [<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
+ [<ffffffff81245216>] __pci_register_driver+0x56/0xd0
+ [<ffffffffa02f1264>] drm_pci_init+0xe4/0xf0 [drm]
+ [<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
+ [<ffffffffa02e84a8>] drm_init+0x58/0x70 [drm]
+ [<ffffffffa03aa094>] i915_init+0x94/0x96 [i915]
+ [<ffffffff81002194>] do_one_initcall+0x44/0x190
+ [<ffffffff810a066b>] sys_init_module+0xcb/0x210
+ [<ffffffff8100c012>] system_call_fastpath+0x16/0x1b
+..
+
+fb-test2 which reproduces above is available on kernel.org bug #26232.
+To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
+and move it out to where needed (callers of fb_set_suspend must call
+lock_fb_info before if needed). So far, the only place which needs to
+call lock_fb_info is store_fbstate, all other places which calls
+fb_set_suspend are suspend/resume hooks that should not need the lock as
+they should be run only when processes are already frozen in
+suspend/resume.
+
+References: https://bugzilla.kernel.org/show_bug.cgi?id=26232
+Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/fbmem.c   |    3 ---
+ drivers/video/fbsysfs.c |    3 +++
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/video/fbmem.c
++++ b/drivers/video/fbmem.c
+@@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info
+ {
+       struct fb_event event;
+-      if (!lock_fb_info(info))
+-              return;
+       event.info = info;
+       if (state) {
+               fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
+@@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info
+               info->state = FBINFO_STATE_RUNNING;
+               fb_notifier_call_chain(FB_EVENT_RESUME, &event);
+       }
+-      unlock_fb_info(info);
+ }
+ /**
+--- a/drivers/video/fbsysfs.c
++++ b/drivers/video/fbsysfs.c
+@@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct devi
+       state = simple_strtoul(buf, &last, 0);
++      if (!lock_fb_info(fb_info))
++              return -ENODEV;
+       console_lock();
+       fb_set_suspend(fb_info, (int)state);
+       console_unlock();
++      unlock_fb_info(fb_info);
+       return count;
+ }
diff --git a/queue-3.1/fb-sh-mobile-fix-deadlock-risk-between-lock_fb_info-and-console_lock.patch b/queue-3.1/fb-sh-mobile-fix-deadlock-risk-between-lock_fb_info-and-console_lock.patch
new file mode 100644 (file)
index 0000000..b93d502
--- /dev/null
@@ -0,0 +1,117 @@
+From 4a47a0e09c504e3ce0ccdb405411aefc5b09deb8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org>
+Date: Fri, 2 Sep 2011 19:24:03 +0200
+Subject: fb: sh-mobile: Fix deadlock risk between lock_fb_info() and console_lock()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org>
+
+commit 4a47a0e09c504e3ce0ccdb405411aefc5b09deb8 upstream.
+
+Following on Herton's patch "fb: avoid possible deadlock caused by
+fb_set_suspend" which moves lock_fb_info() out of fb_set_suspend()
+to its callers, correct sh-mobile's locking around call to
+fb_set_suspend() and the same sort of deaklocks with console_lock()
+due to order of taking the lock.
+
+console_lock() must be taken while fb_info is already locked and fb_info
+must be locked while calling fb_set_suspend().
+
+Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/sh_mobile_hdmi.c |   47 ++++++++++++++++++++++-------------------
+ 1 file changed, 26 insertions(+), 21 deletions(-)
+
+--- a/drivers/video/sh_mobile_hdmi.c
++++ b/drivers/video/sh_mobile_hdmi.c
+@@ -1111,6 +1111,7 @@ static long sh_hdmi_clk_configure(struct
+ static void sh_hdmi_edid_work_fn(struct work_struct *work)
+ {
+       struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
++      struct fb_info *info;
+       struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
+       struct sh_mobile_lcdc_chan *ch;
+       int ret;
+@@ -1123,8 +1124,9 @@ static void sh_hdmi_edid_work_fn(struct
+       mutex_lock(&hdmi->mutex);
++      info = hdmi->info;
++
+       if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
+-              struct fb_info *info = hdmi->info;
+               unsigned long parent_rate = 0, hdmi_rate;
+               ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
+@@ -1148,42 +1150,45 @@ static void sh_hdmi_edid_work_fn(struct
+               ch = info->par;
+-              console_lock();
++              if (lock_fb_info(info)) {
++                      console_lock();
+-              /* HDMI plug in */
+-              if (!sh_hdmi_must_reconfigure(hdmi) &&
+-                  info->state == FBINFO_STATE_RUNNING) {
+-                      /*
+-                       * First activation with the default monitor - just turn
+-                       * on, if we run a resume here, the logo disappears
+-                       */
+-                      if (lock_fb_info(info)) {
++                      /* HDMI plug in */
++                      if (!sh_hdmi_must_reconfigure(hdmi) &&
++                          info->state == FBINFO_STATE_RUNNING) {
++                              /*
++                               * First activation with the default monitor - just turn
++                               * on, if we run a resume here, the logo disappears
++                               */
+                               info->var.width = hdmi->var.width;
+                               info->var.height = hdmi->var.height;
+                               sh_hdmi_display_on(hdmi, info);
+-                              unlock_fb_info(info);
++                      } else {
++                              /* New monitor or have to wake up */
++                              fb_set_suspend(info, 0);
+                       }
+-              } else {
+-                      /* New monitor or have to wake up */
+-                      fb_set_suspend(info, 0);
+-              }
+-              console_unlock();
++                      console_unlock();
++                      unlock_fb_info(info);
++              }
+       } else {
+               ret = 0;
+-              if (!hdmi->info)
++              if (!info)
+                       goto out;
+               hdmi->monspec.modedb_len = 0;
+               fb_destroy_modedb(hdmi->monspec.modedb);
+               hdmi->monspec.modedb = NULL;
+-              console_lock();
++              if (lock_fb_info(info)) {
++                      console_lock();
+-              /* HDMI disconnect */
+-              fb_set_suspend(hdmi->info, 1);
++                      /* HDMI disconnect */
++                      fb_set_suspend(info, 1);
+-              console_unlock();
++                      console_unlock();
++                      unlock_fb_info(info);
++              }
+       }
+ out:
diff --git a/queue-3.1/io-mapping-ensure-io_mapping_map_atomic-_is_-atomic.patch b/queue-3.1/io-mapping-ensure-io_mapping_map_atomic-_is_-atomic.patch
new file mode 100644 (file)
index 0000000..20bdf97
--- /dev/null
@@ -0,0 +1,55 @@
+From 24dd85ff723f142093f44244764b9b5c152235b8 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Wed, 28 Sep 2011 11:57:23 +0200
+Subject: io-mapping: ensure io_mapping_map_atomic _is_ atomic
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit 24dd85ff723f142093f44244764b9b5c152235b8 upstream.
+
+For the !HAVE_ATOMIC_IOMAP case the stub functions did not call
+pagefault_disable/_enable. The i915 driver relies on the map
+actually being atomic, otherwise it can deadlock with it's own
+pagefault handler in the gtt pwrite fastpath.
+
+This is exercised by gem_mmap_gtt from the intel-gpu-toosl gem
+testsuite.
+
+v2: Chris Wilson noted the lack of an include.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38115
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/io-mapping.h |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/include/linux/io-mapping.h
++++ b/include/linux/io-mapping.h
+@@ -117,6 +117,8 @@ io_mapping_unmap(void __iomem *vaddr)
+ #else
++#include <linux/uaccess.h>
++
+ /* this struct isn't actually defined anywhere */
+ struct io_mapping;
+@@ -138,12 +140,14 @@ static inline void __iomem *
+ io_mapping_map_atomic_wc(struct io_mapping *mapping,
+                        unsigned long offset)
+ {
++      pagefault_disable();
+       return ((char __force __iomem *) mapping) + offset;
+ }
+ static inline void
+ io_mapping_unmap_atomic(void __iomem *vaddr)
+ {
++      pagefault_enable();
+ }
+ /* Non-atomic map/unmap */
diff --git a/queue-3.1/iommu-amd-fix-wrong-shift-direction.patch b/queue-3.1/iommu-amd-fix-wrong-shift-direction.patch
new file mode 100644 (file)
index 0000000..307b473
--- /dev/null
@@ -0,0 +1,30 @@
+From fcd0861db1cf4e6ed99f60a815b7b72c2ed36ea4 Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <joerg.roedel@amd.com>
+Date: Tue, 11 Oct 2011 17:41:32 +0200
+Subject: iommu/amd: Fix wrong shift direction
+
+From: Joerg Roedel <joerg.roedel@amd.com>
+
+commit fcd0861db1cf4e6ed99f60a815b7b72c2ed36ea4 upstream.
+
+The shift direction was wrong because the function takes a
+page number and i is the address is the loop.
+
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/iommu/amd_iommu.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iommu/amd_iommu.c
++++ b/drivers/iommu/amd_iommu.c
+@@ -1283,7 +1283,7 @@ static int alloc_new_range(struct dma_op
+               if (!pte || !IOMMU_PTE_PRESENT(*pte))
+                       continue;
+-              dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
++              dma_ops_reserve_addresses(dma_dom, i >> PAGE_SHIFT, 1);
+       }
+       update_domain(&dma_dom->domain);
diff --git a/queue-3.1/kvm-s390-check-cpu_id-prior-to-using-it.patch b/queue-3.1/kvm-s390-check-cpu_id-prior-to-using-it.patch
new file mode 100644 (file)
index 0000000..8b1f6c2
--- /dev/null
@@ -0,0 +1,53 @@
+From 4d47555a80495657161a7e71ec3014ff2021e450 Mon Sep 17 00:00:00 2001
+From: Carsten Otte <cotte@de.ibm.com>
+Date: Tue, 18 Oct 2011 12:27:12 +0200
+Subject: KVM: s390: check cpu_id prior to using it
+
+From: Carsten Otte <cotte@de.ibm.com>
+
+commit 4d47555a80495657161a7e71ec3014ff2021e450 upstream.
+
+We use the cpu id provided by userspace as array index here. Thus we
+clearly need to check it first. Ooops.
+
+Signed-off-by: Carsten Otte <cotte@de.ibm.com>
+Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/s390/kvm/kvm-s390.c |   14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/arch/s390/kvm/kvm-s390.c
++++ b/arch/s390/kvm/kvm-s390.c
+@@ -312,11 +312,17 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
+ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
+                                     unsigned int id)
+ {
+-      struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+-      int rc = -ENOMEM;
++      struct kvm_vcpu *vcpu;
++      int rc = -EINVAL;
++      if (id >= KVM_MAX_VCPUS)
++              goto out;
++
++      rc = -ENOMEM;
++
++      vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+       if (!vcpu)
+-              goto out_nomem;
++              goto out;
+       vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
+                                       get_zeroed_page(GFP_KERNEL);
+@@ -352,7 +358,7 @@ out_free_sie_block:
+       free_page((unsigned long)(vcpu->arch.sie_block));
+ out_free_cpu:
+       kfree(vcpu);
+-out_nomem:
++out:
+       return ERR_PTR(rc);
+ }
diff --git a/queue-3.1/md-raid10-fix-bug-when-activating-a-hot-spare.patch b/queue-3.1/md-raid10-fix-bug-when-activating-a-hot-spare.patch
new file mode 100644 (file)
index 0000000..880849d
--- /dev/null
@@ -0,0 +1,40 @@
+From 7fcc7c8acf0fba44d19a713207af7e58267c1179 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Mon, 31 Oct 2011 12:59:44 +1100
+Subject: md/raid10:  Fix bug when activating a hot-spare.
+
+From: NeilBrown <neilb@suse.de>
+
+commit 7fcc7c8acf0fba44d19a713207af7e58267c1179 upstream.
+
+This is a fairly serious bug in RAID10.
+
+When a RAID10 array is degraded and a hot-spare is activated, the
+spare does not take up the empty slot, but rather replaces the first
+working device.
+This is likely to make the array non-functional.   It would normally
+be possible to recover the data, but that would need care and is not
+guaranteed.
+
+This bug was introduced in commit
+   2bb77736ae5dca0a189829fbb7379d43364a9dac
+which first appeared in 3.1.
+
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/raid10.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1337,7 +1337,7 @@ static int raid10_add_disk(mddev_t *mdde
+               mirror_info_t *p = &conf->mirrors[mirror];
+               if (p->recovery_disabled == mddev->recovery_disabled)
+                       continue;
+-              if (!p->rdev)
++              if (p->rdev)
+                       continue;
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
diff --git a/queue-3.1/memory-leak-with-rcu_table_free.patch b/queue-3.1/memory-leak-with-rcu_table_free.patch
new file mode 100644 (file)
index 0000000..a71a94c
--- /dev/null
@@ -0,0 +1,35 @@
+From e73b7fffe487c315fd1a4fa22282e3362b440a06 Mon Sep 17 00:00:00 2001
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Sun, 30 Oct 2011 15:16:08 +0100
+Subject: [S390] memory leak with RCU_TABLE_FREE
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+commit e73b7fffe487c315fd1a4fa22282e3362b440a06 upstream.
+
+The rcu page table free code uses a couple of bits in the page table
+pointer passed to tlb_remove_table to discern the different page table
+types. __tlb_remove_table extracts the type with an incorrect mask which
+leads to memory leaks. The correct mask is ((FRAG_MASK << 4) | FRAG_MASK).
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/s390/mm/pgtable.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/mm/pgtable.c
++++ b/arch/s390/mm/pgtable.c
+@@ -662,8 +662,9 @@ void page_table_free_rcu(struct mmu_gath
+ void __tlb_remove_table(void *_table)
+ {
+-      void *table = (void *)((unsigned long) _table & PAGE_MASK);
+-      unsigned type = (unsigned long) _table & ~PAGE_MASK;
++      const unsigned long mask = (FRAG_MASK << 4) | FRAG_MASK;
++      void *table = (void *)((unsigned long) _table & ~mask);
++      unsigned type = (unsigned long) _table & mask;
+       if (type)
+               __page_table_free_rcu(table, type);
diff --git a/queue-3.1/plat-mxc-iomux-v3.h-implicitly-enable-pull-up-down-when-that-s-desired.patch b/queue-3.1/plat-mxc-iomux-v3.h-implicitly-enable-pull-up-down-when-that-s-desired.patch
new file mode 100644 (file)
index 0000000..17e66fe
--- /dev/null
@@ -0,0 +1,52 @@
+From 6571534b600b8ca1936ff5630b9e0947f21faf16 Mon Sep 17 00:00:00 2001
+From: Paul Fertser <fercerpav@gmail.com>
+Date: Mon, 10 Oct 2011 11:19:23 +0400
+Subject: plat-mxc: iomux-v3.h: implicitly enable pull-up/down when that's desired
+
+From: Paul Fertser <fercerpav@gmail.com>
+
+commit 6571534b600b8ca1936ff5630b9e0947f21faf16 upstream.
+
+To configure pads during the initialisation a set of special constants
+is used, e.g.
+#define MX25_PAD_FEC_MDIO__FEC_MDIO IOMUX_PAD(0x3c4, 0x1cc, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_22K_UP)
+
+The problem is that no pull-up/down is getting activated unless both
+PAD_CTL_PUE (pull-up enable) and PAD_CTL_PKE (pull/keeper module
+enable) set. This is clearly stated in the i.MX25 datasheet and is
+confirmed by the measurements on hardware. This leads to some rather
+hard to understand bugs such as misdetecting an absent ethernet PHY (a
+real bug i had), unstable data transfer etc. This might affect mx25,
+mx35, mx50, mx51 and mx53 SoCs.
+
+It's reasonable to expect that if the pullup value is specified, the
+intention was to have it actually active, so we implicitly add the
+needed bits.
+
+Signed-off-by: Paul Fertser <fercerpav@gmail.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/plat-mxc/include/mach/iomux-v3.h |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
++++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
+@@ -89,11 +89,11 @@ typedef u64 iomux_v3_cfg_t;
+ #define PAD_CTL_HYS                   (1 << 8)
+ #define PAD_CTL_PKE                   (1 << 7)
+-#define PAD_CTL_PUE                   (1 << 6)
+-#define PAD_CTL_PUS_100K_DOWN         (0 << 4)
+-#define PAD_CTL_PUS_47K_UP            (1 << 4)
+-#define PAD_CTL_PUS_100K_UP           (2 << 4)
+-#define PAD_CTL_PUS_22K_UP            (3 << 4)
++#define PAD_CTL_PUE                   (1 << 6 | PAD_CTL_PKE)
++#define PAD_CTL_PUS_100K_DOWN         (0 << 4 | PAD_CTL_PUE)
++#define PAD_CTL_PUS_47K_UP            (1 << 4 | PAD_CTL_PUE)
++#define PAD_CTL_PUS_100K_UP           (2 << 4 | PAD_CTL_PUE)
++#define PAD_CTL_PUS_22K_UP            (3 << 4 | PAD_CTL_PUE)
+ #define PAD_CTL_ODE                   (1 << 3)
diff --git a/queue-3.1/proc-self-numa_maps-restore-huge-tag-for-hugetlb-vmas.patch b/queue-3.1/proc-self-numa_maps-restore-huge-tag-for-hugetlb-vmas.patch
new file mode 100644 (file)
index 0000000..50936c4
--- /dev/null
@@ -0,0 +1,41 @@
+From fc360bd9cdcf875639a77f07fafec26699c546f3 Mon Sep 17 00:00:00 2001
+From: Andrew Morton <akpm@linux-foundation.org>
+Date: Mon, 31 Oct 2011 17:06:32 -0700
+Subject: /proc/self/numa_maps: restore "huge" tag for hugetlb vmas
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+commit fc360bd9cdcf875639a77f07fafec26699c546f3 upstream.
+
+The display of the "huge" tag was accidentally removed in 29ea2f698 ("mm:
+use walk_page_range() instead of custom page table walking code").
+
+Reported-by: Stephen Hemminger <shemminger@vyatta.com>
+Tested-by: Stephen Hemminger <shemminger@vyatta.com>
+Reviewed-by: Stephen Wilson <wilsons@start.ca>
+Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Cc: Hugh Dickins <hughd@google.com>
+Acked-by: David Rientjes <rientjes@google.com>
+Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
+Cc: Alexey Dobriyan <adobriyan@gmail.com>
+Cc: Christoph Lameter <cl@linux-foundation.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/proc/task_mmu.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -1039,6 +1039,9 @@ static int show_numa_map(struct seq_file
+               seq_printf(m, " stack");
+       }
++      if (is_vm_hugetlb_page(vma))
++              seq_printf(m, " huge");
++
+       walk_page_range(vma->vm_start, vma->vm_end, &walk);
+       if (!md->pages)
index fcd927e77f4841be2d3324b45886f588ebe61650..ff7d642d556a60072f7c91cc35dd7fd0f72a7a40 100644 (file)
@@ -118,3 +118,32 @@ nfsd4-permit-read-opens-of-executable-only-files.patch
 nfsd4-fix-open-downgrade-again.patch
 nfsd4-ignore-want-bits-in-open-downgrade.patch
 vfs-add-device-tag-to-proc-self-mountstats.patch
+io-mapping-ensure-io_mapping_map_atomic-_is_-atomic.patch
+asoc-wm8940-properly-set-codec-dapm.bias_level.patch
+asoc-wm8741-fix-setting-interface-format-for-dsp-modes.patch
+asoc-ak4642-fixup-cache-register-table.patch
+asoc-ak4535-fixup-cache-register-table.patch
+asoc-wm8996-fix-wrong-mask-for-setting.patch
+asoc-wm8994-fix-setting-rate_reg-for-wm8994-aif2.patch
+asoc-wm8994-use-snd_soc_dapm_aif_out-for-aif3-capture.patch
+asoc-remove-direct-register-cache-accesses-from-wm8962.patch
+asoc-fix-a-bug-in-wm8962-dsp_a-and-dsp_b-settings.patch
+kvm-s390-check-cpu_id-prior-to-using-it.patch
+user-per-registers-vs.-ptrace-single-stepping.patch
+memory-leak-with-rcu_table_free.patch
+ccwgroup-move-attributes-to-attribute-group.patch
+wmi-properly-cleanup-devices-to-avoid-crashes.patch
+iommu-amd-fix-wrong-shift-direction.patch
+carminefb-fix-module-parameters-permissions.patch
+fb-avoid-possible-deadlock-caused-by-fb_set_suspend.patch
+fb-sh-mobile-fix-deadlock-risk-between-lock_fb_info-and-console_lock.patch
+viafb-use-display-information-in-info-not-in-var-for.patch
+viafb-improve-pitch-handling.patch
+dibcom-protect-the-i2c-bufer-access.patch
+dib0700-protect-the-dib0700-buffer-access.patch
+tuner_xc2028-allow-selection-of-the-frequency-adjustment-code-for-xc3028.patch
+proc-self-numa_maps-restore-huge-tag-for-hugetlb-vmas.patch
+md-raid10-fix-bug-when-activating-a-hot-spare.patch
+plat-mxc-iomux-v3.h-implicitly-enable-pull-up-down-when-that-s-desired.patch
+arm-pxa-cm-x300-properly-set-bt_reset-pin.patch
+arm-mach-ux500-unlock-i-d-l2x0-caches-before-init.patch
diff --git a/queue-3.1/tuner_xc2028-allow-selection-of-the-frequency-adjustment-code-for-xc3028.patch b/queue-3.1/tuner_xc2028-allow-selection-of-the-frequency-adjustment-code-for-xc3028.patch
new file mode 100644 (file)
index 0000000..464529d
--- /dev/null
@@ -0,0 +1,32 @@
+From 9bed77ee2fb46b74782d0d9d14b92e9d07f3df6e Mon Sep 17 00:00:00 2001
+From: Mauro Carvalho Chehab <mchehab@redhat.com>
+Date: Thu, 28 Jul 2011 16:38:54 -0300
+Subject: [media] tuner_xc2028: Allow selection of the frequency adjustment code for XC3028
+
+From: Mauro Carvalho Chehab <mchehab@redhat.com>
+
+commit 9bed77ee2fb46b74782d0d9d14b92e9d07f3df6e upstream.
+
+This device is not using the proper demod IF. Instead of using the
+IF macro, it is specifying a IF frequency. This doesn't work, as xc3028
+needs to load an specific SCODE for the tuner. In this case, there's
+no IF table for 5 MHz.
+
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/media/video/cx23885/cx23885-dvb.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/video/cx23885/cx23885-dvb.c
++++ b/drivers/media/video/cx23885/cx23885-dvb.c
+@@ -844,7 +844,7 @@ static int dvb_register(struct cx23885_t
+                       static struct xc2028_ctrl ctl = {
+                               .fname   = XC3028L_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+-                              .demod   = 5000,
++                              .demod   = XC3028_FE_DIBCOM52,
+                               /* This is true for all demods with
+                                       v36 firmware? */
+                               .type    = XC2028_D2633,
diff --git a/queue-3.1/user-per-registers-vs.-ptrace-single-stepping.patch b/queue-3.1/user-per-registers-vs.-ptrace-single-stepping.patch
new file mode 100644 (file)
index 0000000..897ec75
--- /dev/null
@@ -0,0 +1,74 @@
+From a45aff5285871bf7be1781d9462d3fdbb6c913f9 Mon Sep 17 00:00:00 2001
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Sun, 30 Oct 2011 15:16:07 +0100
+Subject: [S390] user per registers vs. ptrace single stepping
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+commit a45aff5285871bf7be1781d9462d3fdbb6c913f9 upstream.
+
+git commit 5e9a2692 "[S390] ptrace cleanup" introduced a regression
+for the case when both a user PER set (e.g. a storage alteration trace) and
+PTRACE_SINGLESTEP are active. The new code will overrule the user PER set
+with a instruction-fetch PER set over the whole address space for ptrace
+single stepping. The inferior process will be stopped after each instruction
+with an instruction fetch event. Any other events that may have occurred
+concurrently are not reported (e.g. storage alteration event) because the
+control bits for them are not set. The solution is to merge the PER control
+bits of the user PER set with the PER_EVENT_IFETCH control bit for
+PTRACE_SINGLESTEP.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/s390/kernel/ptrace.c |   28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+--- a/arch/s390/kernel/ptrace.c
++++ b/arch/s390/kernel/ptrace.c
+@@ -47,29 +47,31 @@ enum s390_regset {
+ void update_per_regs(struct task_struct *task)
+ {
+-      static const struct per_regs per_single_step = {
+-              .control = PER_EVENT_IFETCH,
+-              .start = 0,
+-              .end = PSW_ADDR_INSN,
+-      };
+       struct pt_regs *regs = task_pt_regs(task);
+       struct thread_struct *thread = &task->thread;
+-      const struct per_regs *new;
+-      struct per_regs old;
++      struct per_regs old, new;
+-      /* TIF_SINGLE_STEP overrides the user specified PER registers. */
+-      new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?
+-              &per_single_step : &thread->per_user;
++      /* Copy user specified PER registers */
++      new.control = thread->per_user.control;
++      new.start = thread->per_user.start;
++      new.end = thread->per_user.end;
++
++      /* merge TIF_SINGLE_STEP into user specified PER registers. */
++      if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
++              new.control |= PER_EVENT_IFETCH;
++              new.start = 0;
++              new.end = PSW_ADDR_INSN;
++      }
+       /* Take care of the PER enablement bit in the PSW. */
+-      if (!(new->control & PER_EVENT_MASK)) {
++      if (!(new.control & PER_EVENT_MASK)) {
+               regs->psw.mask &= ~PSW_MASK_PER;
+               return;
+       }
+       regs->psw.mask |= PSW_MASK_PER;
+       __ctl_store(old, 9, 11);
+-      if (memcmp(new, &old, sizeof(struct per_regs)) != 0)
+-              __ctl_load(*new, 9, 11);
++      if (memcmp(&new, &old, sizeof(struct per_regs)) != 0)
++              __ctl_load(new, 9, 11);
+ }
+ void user_enable_single_step(struct task_struct *task)
diff --git a/queue-3.1/viafb-improve-pitch-handling.patch b/queue-3.1/viafb-improve-pitch-handling.patch
new file mode 100644 (file)
index 0000000..5b104db
--- /dev/null
@@ -0,0 +1,62 @@
+From 936a3f770b8de7042d793272f008ef1bb08522e9 Mon Sep 17 00:00:00 2001
+From: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Date: Mon, 6 Jun 2011 01:27:34 +0000
+Subject: viafb: improve pitch handling
+
+From: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+
+commit 936a3f770b8de7042d793272f008ef1bb08522e9 upstream.
+
+This patch adds checks for minimum and maximum pitch size to prevent
+invalid settings which could otherwise crash the machine. Also the
+alignment is done in a slightly more readable way.
+
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/via/via_modesetting.h |    5 +++++
+ drivers/video/via/viafbdev.c        |   11 ++++++++---
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/video/via/via_modesetting.h
++++ b/drivers/video/via/via_modesetting.h
+@@ -28,6 +28,11 @@
+ #include <linux/types.h>
++
++#define VIA_PITCH_SIZE        (1<<3)
++#define VIA_PITCH_MAX 0x3FF8
++
++
+ void via_set_primary_address(u32 addr);
+ void via_set_secondary_address(u32 addr);
+ void via_set_primary_pitch(u32 pitch);
+--- a/drivers/video/via/viafbdev.c
++++ b/drivers/video/via/viafbdev.c
+@@ -151,7 +151,8 @@ static void viafb_update_fix(struct fb_i
+       info->fix.visual =
+               bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+-      info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
++      info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
++              VIA_PITCH_SIZE);
+ }
+ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
+@@ -238,8 +239,12 @@ static int viafb_check_var(struct fb_var
+               depth = 24;
+       viafb_fill_var_color_info(var, depth);
+-      line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
+-      if (line * var->yres_virtual > ppar->memsize)
++      if (var->xres_virtual < var->xres)
++              var->xres_virtual = var->xres;
++
++      line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
++              VIA_PITCH_SIZE);
++      if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
+               return -EINVAL;
+       /* Based on var passed in to calculate the refresh,
diff --git a/queue-3.1/viafb-use-display-information-in-info-not-in-var-for.patch b/queue-3.1/viafb-use-display-information-in-info-not-in-var-for.patch
new file mode 100644 (file)
index 0000000..d3250bb
--- /dev/null
@@ -0,0 +1,37 @@
+From d933990c57b498c092ceef591c7c5d69dbfe9f30 Mon Sep 17 00:00:00 2001
+From: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Date: Mon, 23 May 2011 21:39:58 +0000
+Subject: viafb: use display information in info not in var for panning
+
+From: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+
+commit d933990c57b498c092ceef591c7c5d69dbfe9f30 upstream.
+
+As Laurent pointed out we must not use any information in the passed
+var besides xoffset, yoffset and vmode as otherwise applications
+might abuse it. Also use the aligned fix.line_length and not the
+(possible) unaligned xres_virtual.
+
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Reported-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/via/viafbdev.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/video/via/viafbdev.c
++++ b/drivers/video/via/viafbdev.c
+@@ -348,8 +348,9 @@ static int viafb_pan_display(struct fb_v
+       struct fb_info *info)
+ {
+       struct viafb_par *viapar = info->par;
+-      u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
+-              * (var->bits_per_pixel / 8) + viapar->vram_addr;
++      u32 vram_addr = viapar->vram_addr
++              + var->yoffset * info->fix.line_length
++              + var->xoffset * info->var.bits_per_pixel / 8;
+       DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
+       if (!viafb_dual_fb) {
diff --git a/queue-3.1/wmi-properly-cleanup-devices-to-avoid-crashes.patch b/queue-3.1/wmi-properly-cleanup-devices-to-avoid-crashes.patch
new file mode 100644 (file)
index 0000000..9da4cd2
--- /dev/null
@@ -0,0 +1,41 @@
+From 023b9565972a4a5e0f01b9aa32680af6e9b5c388 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Wed, 7 Sep 2011 15:00:02 -0700
+Subject: WMI: properly cleanup devices to avoid crashes
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 023b9565972a4a5e0f01b9aa32680af6e9b5c388 upstream.
+
+We need to remove devices that we destroy from the list, otherwise
+we'll crash if there are more than one "_WDG" methods in DSDT.
+
+This fixes https://bugzilla.kernel.org/show_bug.cgi?id=32052
+
+Tested-by: Ilya Tumaykin <librarian_rus@yahoo.com>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+Acked-by: Carlos Corbacho <carlos@strangeworlds.co.uk>
+Signed-off-by: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/platform/x86/wmi.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/platform/x86/wmi.c
++++ b/drivers/platform/x86/wmi.c
+@@ -754,9 +754,13 @@ static void wmi_free_devices(void)
+       struct wmi_block *wblock, *next;
+       /* Delete devices for all the GUIDs */
+-      list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
++      list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
++              list_del(&wblock->list);
+               if (wblock->dev.class)
+                       device_unregister(&wblock->dev);
++              else
++                      kfree(wblock);
++      }
+ }
+ static bool guid_already_parsed(const char *guid_string)