]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Dec 2013 20:02:14 +0000 (12:02 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Dec 2013 20:02:14 +0000 (12:02 -0800)
added patches:
asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch
asoc-wm8731-fix-dsp-mode-configuration.patch
asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch
can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch
can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch
can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch
efi-pstore-make-efi-pstore-return-a-unique-id.patch
efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch
vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch

queue-3.12/asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch [new file with mode: 0644]
queue-3.12/asoc-wm8731-fix-dsp-mode-configuration.patch [new file with mode: 0644]
queue-3.12/asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch [new file with mode: 0644]
queue-3.12/can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch [new file with mode: 0644]
queue-3.12/can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch [new file with mode: 0644]
queue-3.12/can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch [new file with mode: 0644]
queue-3.12/efi-pstore-make-efi-pstore-return-a-unique-id.patch [new file with mode: 0644]
queue-3.12/efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch [new file with mode: 0644]
queue-3.12/series
queue-3.12/vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch [new file with mode: 0644]

diff --git a/queue-3.12/asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch b/queue-3.12/asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch
new file mode 100644 (file)
index 0000000..eb41589
--- /dev/null
@@ -0,0 +1,39 @@
+From faf6615bf05bc5cecc6e22013b9cb21c77784fd1 Mon Sep 17 00:00:00 2001
+From: Stephen Warren <swarren@nvidia.com>
+Date: Fri, 22 Nov 2013 10:29:18 -0700
+Subject: ASoC: dapm: Use SND_SOC_DAPM_INIT_REG_VAL in SND_SOC_DAPM_MUX
+
+From: Stephen Warren <swarren@nvidia.com>
+
+commit faf6615bf05bc5cecc6e22013b9cb21c77784fd1 upstream.
+
+SND_SOC_DAPM_MUX() doesn't currently initialize the .mask field. This
+results in the mux never affecting HW, since no bits are ever set or
+cleared. Fix SND_SOC_DAPM_MUX() to use SND_SOC_DAPM_INIT_REG_VAL() to
+set up the reg, shift, on_val, and off_val fields like almost all other
+SND_SOC_xxx() macros. It looks like this was a "typo" in the fixed
+commit linked below.
+
+This makes the speakers on the Toshiba AC100 (PAZ00) laptop work again.
+
+Fixes: de9ba98b6d26 ("ASoC: dapm: Make widget power register settings more flexible")
+Signed-off-by: Stephen Warren <swarren@nvidia.com>
+Signed-off-by: Mark Brown <broonie@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/sound/soc-dapm.h |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/include/sound/soc-dapm.h
++++ b/include/sound/soc-dapm.h
+@@ -104,7 +104,8 @@ struct device;
+       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+       .kcontrol_news = wcontrols, .num_kcontrols = 1}
+ #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
+-{     .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
++{     .id = snd_soc_dapm_mux, .name = wname, \
++      SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+       .kcontrol_news = wcontrols, .num_kcontrols = 1}
+ #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
+ {     .id = snd_soc_dapm_virt_mux, .name = wname, \
diff --git a/queue-3.12/asoc-wm8731-fix-dsp-mode-configuration.patch b/queue-3.12/asoc-wm8731-fix-dsp-mode-configuration.patch
new file mode 100644 (file)
index 0000000..d6b3117
--- /dev/null
@@ -0,0 +1,37 @@
+From b4af6ef99a60c5b56df137d7accd81ba1ee1254e Mon Sep 17 00:00:00 2001
+From: Bo Shen <voice.shen@atmel.com>
+Date: Tue, 3 Dec 2013 18:04:54 +0800
+Subject: ASoC: wm8731: fix dsp mode configuration
+
+From: Bo Shen <voice.shen@atmel.com>
+
+commit b4af6ef99a60c5b56df137d7accd81ba1ee1254e upstream.
+
+According to WM8731 "PD, Rev 4.9 October 2012" datasheet, when it
+works in DSP mode A, LRP = 1, while works in DSP mode B, LRP = 0.
+So, fix LRP for DSP mode as the datesheet specification.
+
+Signed-off-by: Bo Shen <voice.shen@atmel.com>
+Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
+Signed-off-by: Mark Brown <broonie@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/codecs/wm8731.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/wm8731.c
++++ b/sound/soc/codecs/wm8731.c
+@@ -447,10 +447,10 @@ static int wm8731_set_dai_fmt(struct snd
+               iface |= 0x0001;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+-              iface |= 0x0003;
++              iface |= 0x0013;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+-              iface |= 0x0013;
++              iface |= 0x0003;
+               break;
+       default:
+               return -EINVAL;
diff --git a/queue-3.12/asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch b/queue-3.12/asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch
new file mode 100644 (file)
index 0000000..7db220e
--- /dev/null
@@ -0,0 +1,30 @@
+From 2ab2b74277a86afe0dd92976db695a2bb8b93366 Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@linaro.org>
+Date: Fri, 22 Nov 2013 14:17:18 +0000
+Subject: ASoC: wm8990: Mark the register map as dirty when powering down
+
+From: Mark Brown <broonie@linaro.org>
+
+commit 2ab2b74277a86afe0dd92976db695a2bb8b93366 upstream.
+
+Otherwise we'll skip sync on resume.
+
+Signed-off-by: Mark Brown <broonie@linaro.org>
+Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/codecs/wm8990.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/soc/codecs/wm8990.c
++++ b/sound/soc/codecs/wm8990.c
+@@ -1259,6 +1259,8 @@ static int wm8990_set_bias_level(struct
+               /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
+               snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
++
++              codec->cache_sync = 1;
+               break;
+       }
diff --git a/queue-3.12/can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch b/queue-3.12/can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch
new file mode 100644 (file)
index 0000000..20a7866
--- /dev/null
@@ -0,0 +1,74 @@
+From e35d46adc49b469fd92bdb64fea8af93640e6651 Mon Sep 17 00:00:00 2001
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+Date: Sun, 24 Nov 2013 23:31:24 +0100
+Subject: can: c_can: don't call pm_runtime_get_sync() from interrupt context
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+commit e35d46adc49b469fd92bdb64fea8af93640e6651 upstream.
+
+The c_can driver contians a callpath (c_can_poll -> c_can_state_change ->
+c_can_get_berr_counter) which may call pm_runtime_get_sync() from the IRQ
+handler, which is not allowed and results in "BUG: scheduling while atomic".
+
+This problem is fixed by introducing __c_can_get_berr_counter, which will not
+call pm_runtime_get_sync().
+
+Reported-by: Andrew Glen <AGlen@bepmarine.com>
+Tested-by: Andrew Glen <AGlen@bepmarine.com>
+Signed-off-by: Andrew Glen <AGlen@bepmarine.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/c_can/c_can.c |   21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/can/c_can/c_can.c
++++ b/drivers/net/can/c_can/c_can.c
+@@ -712,22 +712,31 @@ static int c_can_set_mode(struct net_dev
+       return 0;
+ }
+-static int c_can_get_berr_counter(const struct net_device *dev,
+-                                      struct can_berr_counter *bec)
++static int __c_can_get_berr_counter(const struct net_device *dev,
++                                  struct can_berr_counter *bec)
+ {
+       unsigned int reg_err_counter;
+       struct c_can_priv *priv = netdev_priv(dev);
+-      c_can_pm_runtime_get_sync(priv);
+-
+       reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
+       bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
+                               ERR_CNT_REC_SHIFT;
+       bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;
++      return 0;
++}
++
++static int c_can_get_berr_counter(const struct net_device *dev,
++                                struct can_berr_counter *bec)
++{
++      struct c_can_priv *priv = netdev_priv(dev);
++      int err;
++
++      c_can_pm_runtime_get_sync(priv);
++      err = __c_can_get_berr_counter(dev, bec);
+       c_can_pm_runtime_put_sync(priv);
+-      return 0;
++      return err;
+ }
+ /*
+@@ -872,7 +881,7 @@ static int c_can_handle_state_change(str
+       if (unlikely(!skb))
+               return 0;
+-      c_can_get_berr_counter(dev, &bec);
++      __c_can_get_berr_counter(dev, &bec);
+       reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
+       rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
+                               ERR_CNT_RP_SHIFT;
diff --git a/queue-3.12/can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch b/queue-3.12/can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch
new file mode 100644 (file)
index 0000000..7c638e5
--- /dev/null
@@ -0,0 +1,40 @@
+From 1a3e5173f5e72cbf7f0c8927b33082e361c16d72 Mon Sep 17 00:00:00 2001
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+Date: Mon, 25 Nov 2013 22:15:20 +0100
+Subject: can: flexcan: use correct clock as base for bit rate calculation
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+commit 1a3e5173f5e72cbf7f0c8927b33082e361c16d72 upstream.
+
+The flexcan IP core uses the peripheral clock ("per") as basic clock for the
+bit timing calculation. However the driver uses the the wrong clock ("ipg").
+This leads to wrong bit rates if the rates on both clock are different.
+
+This patch fixes the problem by using the correct clock for the bit rate
+calculation.
+
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/flexcan.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/can/flexcan.c
++++ b/drivers/net/can/flexcan.c
+@@ -1020,13 +1020,13 @@ static int flexcan_probe(struct platform
+                       dev_err(&pdev->dev, "no ipg clock defined\n");
+                       return PTR_ERR(clk_ipg);
+               }
+-              clock_freq = clk_get_rate(clk_ipg);
+               clk_per = devm_clk_get(&pdev->dev, "per");
+               if (IS_ERR(clk_per)) {
+                       dev_err(&pdev->dev, "no per clock defined\n");
+                       return PTR_ERR(clk_per);
+               }
++              clock_freq = clk_get_rate(clk_per);
+       }
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/queue-3.12/can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch b/queue-3.12/can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch
new file mode 100644 (file)
index 0000000..fd23f06
--- /dev/null
@@ -0,0 +1,74 @@
+From 2fea6cd303c0d0cd9067da31d873b6a6d5bd75e7 Mon Sep 17 00:00:00 2001
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+Date: Thu, 21 Nov 2013 18:03:07 +0100
+Subject: can: sja1000: fix {pre,post}_irq() handling and IRQ handler return value
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+commit 2fea6cd303c0d0cd9067da31d873b6a6d5bd75e7 upstream.
+
+This patch fixes the issue that the sja1000_interrupt() function may have
+returned IRQ_NONE without processing the optional pre_irq() and post_irq()
+function before. Further the irq processing counter 'n' is moved to the end of
+the while statement to return correct IRQ_[NONE|HANDLED] values at error
+conditions.
+
+Reported-by: Wolfgang Grandegger <wg@grandegger.com>
+Acked-by: Wolfgang Grandegger <wg@grandegger.com>
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/sja1000/sja1000.c |   17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/can/sja1000/sja1000.c
++++ b/drivers/net/can/sja1000/sja1000.c
+@@ -494,20 +494,20 @@ irqreturn_t sja1000_interrupt(int irq, v
+       uint8_t isrc, status;
+       int n = 0;
+-      /* Shared interrupts and IRQ off? */
+-      if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
+-              return IRQ_NONE;
+-
+       if (priv->pre_irq)
+               priv->pre_irq(priv);
++      /* Shared interrupts and IRQ off? */
++      if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
++              goto out;
++
+       while ((isrc = priv->read_reg(priv, SJA1000_IR)) &&
+              (n < SJA1000_MAX_IRQ)) {
+-              n++;
++
+               status = priv->read_reg(priv, SJA1000_SR);
+               /* check for absent controller due to hw unplug */
+               if (status == 0xFF && sja1000_is_absent(priv))
+-                      return IRQ_NONE;
++                      goto out;
+               if (isrc & IRQ_WUI)
+                       netdev_warn(dev, "wakeup interrupt\n");
+@@ -535,7 +535,7 @@ irqreturn_t sja1000_interrupt(int irq, v
+                               status = priv->read_reg(priv, SJA1000_SR);
+                               /* check for absent controller */
+                               if (status == 0xFF && sja1000_is_absent(priv))
+-                                      return IRQ_NONE;
++                                      goto out;
+                       }
+               }
+               if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
+@@ -543,8 +543,9 @@ irqreturn_t sja1000_interrupt(int irq, v
+                       if (sja1000_err(dev, isrc, status))
+                               break;
+               }
++              n++;
+       }
+-
++out:
+       if (priv->post_irq)
+               priv->post_irq(priv);
diff --git a/queue-3.12/efi-pstore-make-efi-pstore-return-a-unique-id.patch b/queue-3.12/efi-pstore-make-efi-pstore-return-a-unique-id.patch
new file mode 100644 (file)
index 0000000..b616921
--- /dev/null
@@ -0,0 +1,84 @@
+From fdeadb43fdf1e7d5698c027b555c389174548e5a Mon Sep 17 00:00:00 2001
+From: Madper Xie <cxie@redhat.com>
+Date: Fri, 29 Nov 2013 15:58:57 +0800
+Subject: efi-pstore: Make efi-pstore return a unique id
+
+From: Madper Xie <cxie@redhat.com>
+
+commit fdeadb43fdf1e7d5698c027b555c389174548e5a upstream.
+
+Pstore fs expects that backends provide a unique id which could avoid
+pstore making entries as duplication or denominating entries the same
+name. So I combine the timestamp, part and count into id.
+
+Signed-off-by: Madper Xie <cxie@redhat.com>
+Cc: Seiji Aguchi <seiji.aguchi@hds.com>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firmware/efi/efi-pstore.c |   20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+--- a/drivers/firmware/efi/efi-pstore.c
++++ b/drivers/firmware/efi/efi-pstore.c
+@@ -37,6 +37,12 @@ struct pstore_read_data {
+       char **buf;
+ };
++static inline u64 generic_id(unsigned long timestamp,
++                           unsigned int part, int count)
++{
++      return (timestamp * 100 + part) * 1000 + count;
++}
++
+ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
+ {
+       efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+@@ -55,7 +61,7 @@ static int efi_pstore_read_func(struct e
+       if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
+                  cb_data->type, &part, &cnt, &time, &data_type) == 5) {
+-              *cb_data->id = part;
++              *cb_data->id = generic_id(time, part, cnt);
+               *cb_data->count = cnt;
+               cb_data->timespec->tv_sec = time;
+               cb_data->timespec->tv_nsec = 0;
+@@ -65,7 +71,7 @@ static int efi_pstore_read_func(struct e
+                       *cb_data->compressed = false;
+       } else if (sscanf(name, "dump-type%u-%u-%d-%lu",
+                  cb_data->type, &part, &cnt, &time) == 4) {
+-              *cb_data->id = part;
++              *cb_data->id = generic_id(time, part, cnt);
+               *cb_data->count = cnt;
+               cb_data->timespec->tv_sec = time;
+               cb_data->timespec->tv_nsec = 0;
+@@ -77,7 +83,7 @@ static int efi_pstore_read_func(struct e
+                * which doesn't support holding
+                * multiple logs, remains.
+                */
+-              *cb_data->id = part;
++              *cb_data->id = generic_id(time, part, 0);
+               *cb_data->count = 0;
+               cb_data->timespec->tv_sec = time;
+               cb_data->timespec->tv_nsec = 0;
+@@ -320,14 +326,16 @@ static int efi_pstore_erase(enum pstore_
+       char name[DUMP_NAME_LEN];
+       efi_char16_t efi_name[DUMP_NAME_LEN];
+       int found, i;
++      unsigned int part;
+-      sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
+-              time.tv_sec);
++      do_div(id, 1000);
++      part = do_div(id, 100);
++      sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec);
+       for (i = 0; i < DUMP_NAME_LEN; i++)
+               efi_name[i] = name[i];
+-      edata.id = id;
++      edata.id = part;
+       edata.type = type;
+       edata.count = count;
+       edata.time = time;
diff --git a/queue-3.12/efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch b/queue-3.12/efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch
new file mode 100644 (file)
index 0000000..4bfb653
--- /dev/null
@@ -0,0 +1,363 @@
+From e0d59733f6b1796b8d6692642c87d7dd862c3e3a Mon Sep 17 00:00:00 2001
+From: Seiji Aguchi <seiji.aguchi@hds.com>
+Date: Wed, 30 Oct 2013 15:27:26 -0400
+Subject: efivars, efi-pstore: Hold off deletion of sysfs entry until the scan is completed
+
+From: Seiji Aguchi <seiji.aguchi@hds.com>
+
+commit e0d59733f6b1796b8d6692642c87d7dd862c3e3a upstream.
+
+Currently, when mounting pstore file system, a read callback of
+efi_pstore driver runs mutiple times as below.
+
+- In the first read callback, scan efivar_sysfs_list from head and pass
+  a kmsg buffer of a entry to an upper pstore layer.
+- In the second read callback, rescan efivar_sysfs_list from the entry
+  and pass another kmsg buffer to it.
+- Repeat the scan and pass until the end of efivar_sysfs_list.
+
+In this process, an entry is read across the multiple read function
+calls. To avoid race between the read and erasion, the whole process
+above is protected by a spinlock, holding in open() and releasing in
+close().
+
+At the same time, kmemdup() is called to pass the buffer to pstore
+filesystem during it. And then, it causes a following lockdep warning.
+
+To make the dynamic memory allocation runnable without taking spinlock,
+holding off a deletion of sysfs entry if it happens while scanning it
+via efi_pstore, and deleting it after the scan is completed.
+
+To implement it, this patch introduces two flags, scanning and deleting,
+to efivar_entry.
+
+On the code basis, it seems that all the scanning and deleting logic is
+not needed because __efivars->lock are not dropped when reading from the
+EFI variable store.
+
+But, the scanning and deleting logic is still needed because an
+efi-pstore and a pstore filesystem works as follows.
+
+In case an entry(A) is found, the pointer is saved to psi->data.  And
+efi_pstore_read() passes the entry(A) to a pstore filesystem by
+releasing  __efivars->lock.
+
+And then, the pstore filesystem calls efi_pstore_read() again and the
+same entry(A), which is saved to psi->data, is used for resuming to scan
+a sysfs-list.
+
+So, to protect the entry(A), the logic is needed.
+
+[    1.143710] ------------[ cut here ]------------
+[    1.144058] WARNING: CPU: 1 PID: 1 at kernel/lockdep.c:2740 lockdep_trace_alloc+0x104/0x110()
+[    1.144058] DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags))
+[    1.144058] Modules linked in:
+[    1.144058] CPU: 1 PID: 1 Comm: systemd Not tainted 3.11.0-rc5 #2
+[    1.144058]  0000000000000009 ffff8800797e9ae0 ffffffff816614a5 ffff8800797e9b28
+[    1.144058]  ffff8800797e9b18 ffffffff8105510d 0000000000000080 0000000000000046
+[    1.144058]  00000000000000d0 00000000000003af ffffffff81ccd0c0 ffff8800797e9b78
+[    1.144058] Call Trace:
+[    1.144058]  [<ffffffff816614a5>] dump_stack+0x54/0x74
+[    1.144058]  [<ffffffff8105510d>] warn_slowpath_common+0x7d/0xa0
+[    1.144058]  [<ffffffff8105517c>] warn_slowpath_fmt+0x4c/0x50
+[    1.144058]  [<ffffffff8131290f>] ? vsscanf+0x57f/0x7b0
+[    1.144058]  [<ffffffff810bbd74>] lockdep_trace_alloc+0x104/0x110
+[    1.144058]  [<ffffffff81192da0>] __kmalloc_track_caller+0x50/0x280
+[    1.144058]  [<ffffffff815147bb>] ? efi_pstore_read_func.part.1+0x12b/0x170
+[    1.144058]  [<ffffffff8115b260>] kmemdup+0x20/0x50
+[    1.144058]  [<ffffffff815147bb>] efi_pstore_read_func.part.1+0x12b/0x170
+[    1.144058]  [<ffffffff81514800>] ? efi_pstore_read_func.part.1+0x170/0x170
+[    1.144058]  [<ffffffff815148b4>] efi_pstore_read_func+0xb4/0xe0
+[    1.144058]  [<ffffffff81512b7b>] __efivar_entry_iter+0xfb/0x120
+[    1.144058]  [<ffffffff8151428f>] efi_pstore_read+0x3f/0x50
+[    1.144058]  [<ffffffff8128d7ba>] pstore_get_records+0x9a/0x150
+[    1.158207]  [<ffffffff812af25c>] ? selinux_d_instantiate+0x1c/0x20
+[    1.158207]  [<ffffffff8128ce30>] ? parse_options+0x80/0x80
+[    1.158207]  [<ffffffff8128ced5>] pstore_fill_super+0xa5/0xc0
+[    1.158207]  [<ffffffff811ae7d2>] mount_single+0xa2/0xd0
+[    1.158207]  [<ffffffff8128ccf8>] pstore_mount+0x18/0x20
+[    1.158207]  [<ffffffff811ae8b9>] mount_fs+0x39/0x1b0
+[    1.158207]  [<ffffffff81160550>] ? __alloc_percpu+0x10/0x20
+[    1.158207]  [<ffffffff811c9493>] vfs_kern_mount+0x63/0xf0
+[    1.158207]  [<ffffffff811cbb0e>] do_mount+0x23e/0xa20
+[    1.158207]  [<ffffffff8115b51b>] ? strndup_user+0x4b/0xf0
+[    1.158207]  [<ffffffff811cc373>] SyS_mount+0x83/0xc0
+[    1.158207]  [<ffffffff81673cc2>] system_call_fastpath+0x16/0x1b
+[    1.158207] ---[ end trace 61981bc62de9f6f4 ]---
+
+Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
+Tested-by: Madper Xie <cxie@redhat.com>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firmware/efi/efi-pstore.c |  143 +++++++++++++++++++++++++++++++++++---
+ drivers/firmware/efi/efivars.c    |   12 ++-
+ drivers/firmware/efi/vars.c       |   12 ++-
+ include/linux/efi.h               |    4 +
+ 4 files changed, 155 insertions(+), 16 deletions(-)
+
+--- a/drivers/firmware/efi/efi-pstore.c
++++ b/drivers/firmware/efi/efi-pstore.c
+@@ -18,14 +18,12 @@ module_param_named(pstore_disable, efiva
+ static int efi_pstore_open(struct pstore_info *psi)
+ {
+-      efivar_entry_iter_begin();
+       psi->data = NULL;
+       return 0;
+ }
+ static int efi_pstore_close(struct pstore_info *psi)
+ {
+-      efivar_entry_iter_end();
+       psi->data = NULL;
+       return 0;
+ }
+@@ -91,19 +89,125 @@ static int efi_pstore_read_func(struct e
+       __efivar_entry_get(entry, &entry->var.Attributes,
+                          &entry->var.DataSize, entry->var.Data);
+       size = entry->var.DataSize;
++      memcpy(*cb_data->buf, entry->var.Data,
++             (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size));
+-      *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL);
+-      if (*cb_data->buf == NULL)
+-              return -ENOMEM;
+       return size;
+ }
++/**
++ * efi_pstore_scan_sysfs_enter
++ * @entry: scanning entry
++ * @next: next entry
++ * @head: list head
++ */
++static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos,
++                                      struct efivar_entry *next,
++                                      struct list_head *head)
++{
++      pos->scanning = true;
++      if (&next->list != head)
++              next->scanning = true;
++}
++
++/**
++ * __efi_pstore_scan_sysfs_exit
++ * @entry: deleting entry
++ * @turn_off_scanning: Check if a scanning flag should be turned off
++ */
++static inline void __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry,
++                                              bool turn_off_scanning)
++{
++      if (entry->deleting) {
++              list_del(&entry->list);
++              efivar_entry_iter_end();
++              efivar_unregister(entry);
++              efivar_entry_iter_begin();
++      } else if (turn_off_scanning)
++              entry->scanning = false;
++}
++
++/**
++ * efi_pstore_scan_sysfs_exit
++ * @pos: scanning entry
++ * @next: next entry
++ * @head: list head
++ * @stop: a flag checking if scanning will stop
++ */
++static void efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
++                                     struct efivar_entry *next,
++                                     struct list_head *head, bool stop)
++{
++      __efi_pstore_scan_sysfs_exit(pos, true);
++      if (stop)
++              __efi_pstore_scan_sysfs_exit(next, &next->list != head);
++}
++
++/**
++ * efi_pstore_sysfs_entry_iter
++ *
++ * @data: function-specific data to pass to callback
++ * @pos: entry to begin iterating from
++ *
++ * You MUST call efivar_enter_iter_begin() before this function, and
++ * efivar_entry_iter_end() afterwards.
++ *
++ * It is possible to begin iteration from an arbitrary entry within
++ * the list by passing @pos. @pos is updated on return to point to
++ * the next entry of the last one passed to efi_pstore_read_func().
++ * To begin iterating from the beginning of the list @pos must be %NULL.
++ */
++static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
++{
++      struct efivar_entry *entry, *n;
++      struct list_head *head = &efivar_sysfs_list;
++      int size = 0;
++
++      if (!*pos) {
++              list_for_each_entry_safe(entry, n, head, list) {
++                      efi_pstore_scan_sysfs_enter(entry, n, head);
++
++                      size = efi_pstore_read_func(entry, data);
++                      efi_pstore_scan_sysfs_exit(entry, n, head, size < 0);
++                      if (size)
++                              break;
++              }
++              *pos = n;
++              return size;
++      }
++
++      list_for_each_entry_safe_from((*pos), n, head, list) {
++              efi_pstore_scan_sysfs_enter((*pos), n, head);
++
++              size = efi_pstore_read_func((*pos), data);
++              efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0);
++              if (size)
++                      break;
++      }
++      *pos = n;
++      return size;
++}
++
++/**
++ * efi_pstore_read
++ *
++ * This function returns a size of NVRAM entry logged via efi_pstore_write().
++ * The meaning and behavior of efi_pstore/pstore are as below.
++ *
++ * size > 0: Got data of an entry logged via efi_pstore_write() successfully,
++ *           and pstore filesystem will continue reading subsequent entries.
++ * size == 0: Entry was not logged via efi_pstore_write(),
++ *            and efi_pstore driver will continue reading subsequent entries.
++ * size < 0: Failed to get data of entry logging via efi_pstore_write(),
++ *           and pstore will stop reading entry.
++ */
+ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+                              int *count, struct timespec *timespec,
+                              char **buf, bool *compressed,
+                              struct pstore_info *psi)
+ {
+       struct pstore_read_data data;
++      ssize_t size;
+       data.id = id;
+       data.type = type;
+@@ -112,8 +216,17 @@ static ssize_t efi_pstore_read(u64 *id,
+       data.compressed = compressed;
+       data.buf = buf;
+-      return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data,
+-                                 (struct efivar_entry **)&psi->data);
++      *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
++      if (!*data.buf)
++              return -ENOMEM;
++
++      efivar_entry_iter_begin();
++      size = efi_pstore_sysfs_entry_iter(&data,
++                                         (struct efivar_entry **)&psi->data);
++      efivar_entry_iter_end();
++      if (size <= 0)
++              kfree(*data.buf);
++      return size;
+ }
+ static int efi_pstore_write(enum pstore_type_id type,
+@@ -184,9 +297,17 @@ static int efi_pstore_erase_func(struct
+                       return 0;
+       }
++      if (entry->scanning) {
++              /*
++               * Skip deletion because this entry will be deleted
++               * after scanning is completed.
++               */
++              entry->deleting = true;
++      } else
++              list_del(&entry->list);
++
+       /* found */
+       __efivar_entry_delete(entry);
+-      list_del(&entry->list);
+       return 1;
+ }
+@@ -214,10 +335,12 @@ static int efi_pstore_erase(enum pstore_
+       efivar_entry_iter_begin();
+       found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry);
+-      efivar_entry_iter_end();
+-      if (found)
++      if (found && !entry->scanning) {
++              efivar_entry_iter_end();
+               efivar_unregister(entry);
++      } else
++              efivar_entry_iter_end();
+       return 0;
+ }
+--- a/drivers/firmware/efi/efivars.c
++++ b/drivers/firmware/efi/efivars.c
+@@ -383,12 +383,16 @@ static ssize_t efivar_delete(struct file
+       else if (__efivar_entry_delete(entry))
+               err = -EIO;
+-      efivar_entry_iter_end();
+-
+-      if (err)
++      if (err) {
++              efivar_entry_iter_end();
+               return err;
++      }
+-      efivar_unregister(entry);
++      if (!entry->scanning) {
++              efivar_entry_iter_end();
++              efivar_unregister(entry);
++      } else
++              efivar_entry_iter_end();
+       /* It's dead Jim.... */
+       return count;
+--- a/drivers/firmware/efi/vars.c
++++ b/drivers/firmware/efi/vars.c
+@@ -683,8 +683,16 @@ struct efivar_entry *efivar_entry_find(e
+       if (!found)
+               return NULL;
+-      if (remove)
+-              list_del(&entry->list);
++      if (remove) {
++              if (entry->scanning) {
++                      /*
++                       * The entry will be deleted
++                       * after scanning is completed.
++                       */
++                      entry->deleting = true;
++              } else
++                      list_del(&entry->list);
++      }
+       return entry;
+ }
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -782,6 +782,8 @@ struct efivar_entry {
+       struct efi_variable var;
+       struct list_head list;
+       struct kobject kobj;
++      bool scanning;
++      bool deleting;
+ };
+ extern struct list_head efivar_sysfs_list;
+@@ -840,6 +842,8 @@ void efivar_run_worker(void);
+ #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
+ int efivars_sysfs_init(void);
++#define EFIVARS_DATA_SIZE_MAX 1024
++
+ #endif /* CONFIG_EFI_VARS */
+ #endif /* _LINUX_EFI_H */
index 763c124e5b5c7189cc04f9b48f3f68db2b46889e..cacff9b29fe915d3d7c6315ffbccc6df128f67a3 100644 (file)
@@ -20,3 +20,12 @@ arm-mvebu-second-pcie-unit-of-armada-xp-mv78230-is-only-x1-capable.patch
 arm-mvebu-fix-second-and-third-pcie-unit-of-armada-xp-mv78260.patch
 arm-mvebu-use-the-virtual-cpu-registers-to-access-coherency-registers.patch
 arm-mvebu-re-enable-pcie-on-armada-370-db.patch
+asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch
+asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch
+asoc-wm8731-fix-dsp-mode-configuration.patch
+vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch
+can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch
+can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch
+can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch
+efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch
+efi-pstore-make-efi-pstore-return-a-unique-id.patch
diff --git a/queue-3.12/vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch b/queue-3.12/vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch
new file mode 100644 (file)
index 0000000..aed9775
--- /dev/null
@@ -0,0 +1,133 @@
+From b0d8d2292160bb63de1972361ebed100c64b5b37 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Mon, 2 Dec 2013 09:44:51 -0800
+Subject: vfs: fix subtle use-after-free of pipe_inode_info
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit b0d8d2292160bb63de1972361ebed100c64b5b37 upstream.
+
+The pipe code was trying (and failing) to be very careful about freeing
+the pipe info only after the last access, with a pattern like:
+
+        spin_lock(&inode->i_lock);
+        if (!--pipe->files) {
+                inode->i_pipe = NULL;
+                kill = 1;
+        }
+        spin_unlock(&inode->i_lock);
+        __pipe_unlock(pipe);
+        if (kill)
+                free_pipe_info(pipe);
+
+where the final freeing is done last.
+
+HOWEVER.  The above is actually broken, because while the freeing is
+done at the end, if we have two racing processes releasing the pipe
+inode info, the one that *doesn't* free it will decrement the ->files
+count, and unlock the inode i_lock, but then still use the
+"pipe_inode_info" afterwards when it does the "__pipe_unlock(pipe)".
+
+This is *very* hard to trigger in practice, since the race window is
+very small, and adding debug options seems to just hide it by slowing
+things down.
+
+Simon originally reported this way back in July as an Oops in
+kmem_cache_allocate due to a single bit corruption (due to the final
+"spin_unlock(pipe->mutex.wait_lock)" incrementing a field in a different
+allocation that had re-used the free'd pipe-info), it's taken this long
+to figure out.
+
+Since the 'pipe->files' accesses aren't even protected by the pipe lock
+(we very much use the inode lock for that), the simple solution is to
+just drop the pipe lock early.  And since there were two users of this
+pattern, create a helper function for it.
+
+Introduced commit ba5bb147330a ("pipe: take allocation and freeing of
+pipe_inode_info out of ->i_mutex").
+
+Reported-by: Simon Kirby <sim@hostway.ca>
+Reported-by: Ian Applegate <ia@cloudflare.com>
+Acked-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/pipe.c |   39 +++++++++++++++++++--------------------
+ 1 file changed, 19 insertions(+), 20 deletions(-)
+
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -726,11 +726,25 @@ pipe_poll(struct file *filp, poll_table
+       return mask;
+ }
++static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
++{
++      int kill = 0;
++
++      spin_lock(&inode->i_lock);
++      if (!--pipe->files) {
++              inode->i_pipe = NULL;
++              kill = 1;
++      }
++      spin_unlock(&inode->i_lock);
++
++      if (kill)
++              free_pipe_info(pipe);
++}
++
+ static int
+ pipe_release(struct inode *inode, struct file *file)
+ {
+-      struct pipe_inode_info *pipe = inode->i_pipe;
+-      int kill = 0;
++      struct pipe_inode_info *pipe = file->private_data;
+       __pipe_lock(pipe);
+       if (file->f_mode & FMODE_READ)
+@@ -743,17 +757,9 @@ pipe_release(struct inode *inode, struct
+               kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+               kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+       }
+-      spin_lock(&inode->i_lock);
+-      if (!--pipe->files) {
+-              inode->i_pipe = NULL;
+-              kill = 1;
+-      }
+-      spin_unlock(&inode->i_lock);
+       __pipe_unlock(pipe);
+-      if (kill)
+-              free_pipe_info(pipe);
+-
++      put_pipe_info(inode, pipe);
+       return 0;
+ }
+@@ -1014,7 +1020,6 @@ static int fifo_open(struct inode *inode
+ {
+       struct pipe_inode_info *pipe;
+       bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
+-      int kill = 0;
+       int ret;
+       filp->f_version = 0;
+@@ -1130,15 +1135,9 @@ err_wr:
+       goto err;
+ err:
+-      spin_lock(&inode->i_lock);
+-      if (!--pipe->files) {
+-              inode->i_pipe = NULL;
+-              kill = 1;
+-      }
+-      spin_unlock(&inode->i_lock);
+       __pipe_unlock(pipe);
+-      if (kill)
+-              free_pipe_info(pipe);
++
++      put_pipe_info(inode, pipe);
+       return ret;
+ }