]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Oct 2012 21:54:48 +0000 (14:54 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Oct 2012 21:54:48 +0000 (14:54 -0700)
added patches:
e1000e-change-wthresh-to-1-to-avoid-possible-tx-stalls.patch
jbd-fix-assertion-failure-in-commit-code-due-to-lacking-transaction-credits.patch
mcs7830-fix-link-state-detection.patch
mtd-nand-allow-nand_no_subpage_write-to-be-set-from-driver.patch
tpm-propagate-error-from-tpm_transmit-to-fix-a-timeout-hang.patch
usb-gadget-at91_udc-fix-dt-support.patch

queue-3.6/e1000e-change-wthresh-to-1-to-avoid-possible-tx-stalls.patch [new file with mode: 0644]
queue-3.6/jbd-fix-assertion-failure-in-commit-code-due-to-lacking-transaction-credits.patch [new file with mode: 0644]
queue-3.6/mcs7830-fix-link-state-detection.patch [new file with mode: 0644]
queue-3.6/mtd-nand-allow-nand_no_subpage_write-to-be-set-from-driver.patch [new file with mode: 0644]
queue-3.6/series
queue-3.6/tpm-propagate-error-from-tpm_transmit-to-fix-a-timeout-hang.patch [new file with mode: 0644]
queue-3.6/usb-gadget-at91_udc-fix-dt-support.patch [new file with mode: 0644]

diff --git a/queue-3.6/e1000e-change-wthresh-to-1-to-avoid-possible-tx-stalls.patch b/queue-3.6/e1000e-change-wthresh-to-1-to-avoid-possible-tx-stalls.patch
new file mode 100644 (file)
index 0000000..0936c33
--- /dev/null
@@ -0,0 +1,81 @@
+From 8edc0e624db3756783233e464879eb2e3b904c13 Mon Sep 17 00:00:00 2001
+From: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
+Date: Wed, 10 Oct 2012 15:34:20 +0000
+Subject: e1000e: Change wthresh to 1 to avoid possible Tx stalls
+
+From: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
+
+commit 8edc0e624db3756783233e464879eb2e3b904c13 upstream.
+
+This patch originated from Hiroaki SHIMODA but has been modified
+by Intel with some minor cleanups and additional commit log text.
+
+Denys Fedoryshchenko and others reported Tx stalls on e1000e with
+BQL enabled.  Issue was root caused to hardware delays. They were
+introduced because some of the e1000e hardware with transmit
+writeback bursting enabled, waits until the driver does an
+explict flush OR there are WTHRESH descriptors to write back.
+
+Sometimes the delays in question were on the order of seconds,
+causing visible lag for ssh sessions and unacceptable tx
+completion latency, especially for BQL enabled kernels.
+
+To avoid possible Tx stalls, change WTHRESH back to 1.
+
+The current plan is to investigate a method for re-enabling
+WTHRESH while not harming BQL, but those patches will be later
+for net-next if they work.
+
+please enqueue for stable since v3.3 as this bug was introduced in
+commit 3f0cfa3bc11e7f00c9994e0f469cbc0e7da7b00c
+Author: Tom Herbert <therbert@google.com>
+Date:   Mon Nov 28 16:33:16 2011 +0000
+
+    e1000e: Support for byte queue limits
+
+    Changes to e1000e to use byte queue limits.
+
+Reported-by: Denys Fedoryshchenko <denys@visp.net.lb>
+Tested-by: Denys Fedoryshchenko <denys@visp.net.lb>
+Signed-off-by: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
+CC: eric.dumazet@gmail.com
+CC: therbert@google.com
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/ethernet/intel/e1000e/e1000.h  |    6 +++---
+ drivers/net/ethernet/intel/e1000e/netdev.c |    2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/intel/e1000e/e1000.h
++++ b/drivers/net/ethernet/intel/e1000e/e1000.h
+@@ -175,13 +175,13 @@ struct e1000_info;
+ /*
+  * in the case of WTHRESH, it appears at least the 82571/2 hardware
+  * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
+- * WTHRESH=4, and since we want 64 bytes at a time written back, set
+- * it to 5
++ * WTHRESH=4, so a setting of 5 gives the most efficient bus
++ * utilization but to avoid possible Tx stalls, set it to 1
+  */
+ #define E1000_TXDCTL_DMA_BURST_ENABLE                          \
+       (E1000_TXDCTL_GRAN | /* set descriptor granularity */  \
+        E1000_TXDCTL_COUNT_DESC |                             \
+-       (5 << 16) | /* wthresh must be +1 more than desired */\
++       (1 << 16) | /* wthresh must be +1 more than desired */\
+        (1 << 8)  | /* hthresh */                             \
+        0x1f)       /* pthresh */
+--- a/drivers/net/ethernet/intel/e1000e/netdev.c
++++ b/drivers/net/ethernet/intel/e1000e/netdev.c
+@@ -2831,7 +2831,7 @@ static void e1000_configure_tx(struct e1
+                * set up some performance related parameters to encourage the
+                * hardware to use the bus more efficiently in bursts, depends
+                * on the tx_int_delay to be enabled,
+-               * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time
++               * wthresh = 1 ==> burst write is disabled to avoid Tx stalls
+                * hthresh = 1 ==> prefetch when one or more available
+                * pthresh = 0x1f ==> prefetch if internal cache 31 or less
+                * BEWARE: this seems to work but should be considered first if
diff --git a/queue-3.6/jbd-fix-assertion-failure-in-commit-code-due-to-lacking-transaction-credits.patch b/queue-3.6/jbd-fix-assertion-failure-in-commit-code-due-to-lacking-transaction-credits.patch
new file mode 100644 (file)
index 0000000..d08d7dc
--- /dev/null
@@ -0,0 +1,230 @@
+From 09e05d4805e6c524c1af74e524e5d0528bb3fef3 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Wed, 11 Jul 2012 23:16:25 +0200
+Subject: jbd: Fix assertion failure in commit code due to lacking transaction credits
+
+From: Jan Kara <jack@suse.cz>
+
+commit 09e05d4805e6c524c1af74e524e5d0528bb3fef3 upstream.
+
+ext3 users of data=journal mode with blocksize < pagesize were occasionally
+hitting assertion failure in journal_commit_transaction() checking whether the
+transaction has at least as many credits reserved as buffers attached.  The
+core of the problem is that when a file gets truncated, buffers that still need
+checkpointing or that are attached to the committing transaction are left with
+buffer_mapped set. When this happens to buffers beyond i_size attached to a
+page stradding i_size, subsequent write extending the file will see these
+buffers and as they are mapped (but underlying blocks were freed) things go
+awry from here.
+
+The assertion failure just coincidentally (and in this case luckily as we would
+start corrupting filesystem) triggers due to journal_head not being properly
+cleaned up as well.
+
+Under some rare circumstances this bug could even hit data=ordered mode users.
+There the assertion won't trigger and we would end up corrupting the
+filesystem.
+
+We fix the problem by unmapping buffers if possible (in lots of cases we just
+need a buffer attached to a transaction as a place holder but it must not be
+written out anyway). And in one case, we just have to bite the bullet and wait
+for transaction commit to finish.
+
+Reviewed-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/jbd/commit.c      |   45 +++++++++++++++++++++++++++--------
+ fs/jbd/transaction.c |   64 +++++++++++++++++++++++++++++++++++----------------
+ 2 files changed, 78 insertions(+), 31 deletions(-)
+
+--- a/fs/jbd/commit.c
++++ b/fs/jbd/commit.c
+@@ -86,7 +86,12 @@ nope:
+ static void release_data_buffer(struct buffer_head *bh)
+ {
+       if (buffer_freed(bh)) {
++              WARN_ON_ONCE(buffer_dirty(bh));
+               clear_buffer_freed(bh);
++              clear_buffer_mapped(bh);
++              clear_buffer_new(bh);
++              clear_buffer_req(bh);
++              bh->b_bdev = NULL;
+               release_buffer_page(bh);
+       } else
+               put_bh(bh);
+@@ -866,17 +871,35 @@ restart_loop:
+                * there's no point in keeping a checkpoint record for
+                * it. */
+-              /* A buffer which has been freed while still being
+-               * journaled by a previous transaction may end up still
+-               * being dirty here, but we want to avoid writing back
+-               * that buffer in the future after the "add to orphan"
+-               * operation been committed,  That's not only a performance
+-               * gain, it also stops aliasing problems if the buffer is
+-               * left behind for writeback and gets reallocated for another
+-               * use in a different page. */
+-              if (buffer_freed(bh) && !jh->b_next_transaction) {
+-                      clear_buffer_freed(bh);
+-                      clear_buffer_jbddirty(bh);
++              /*
++               * A buffer which has been freed while still being journaled by
++               * a previous transaction.
++               */
++              if (buffer_freed(bh)) {
++                      /*
++                       * If the running transaction is the one containing
++                       * "add to orphan" operation (b_next_transaction !=
++                       * NULL), we have to wait for that transaction to
++                       * commit before we can really get rid of the buffer.
++                       * So just clear b_modified to not confuse transaction
++                       * credit accounting and refile the buffer to
++                       * BJ_Forget of the running transaction. If the just
++                       * committed transaction contains "add to orphan"
++                       * operation, we can completely invalidate the buffer
++                       * now. We are rather throughout in that since the
++                       * buffer may be still accessible when blocksize <
++                       * pagesize and it is attached to the last partial
++                       * page.
++                       */
++                      jh->b_modified = 0;
++                      if (!jh->b_next_transaction) {
++                              clear_buffer_freed(bh);
++                              clear_buffer_jbddirty(bh);
++                              clear_buffer_mapped(bh);
++                              clear_buffer_new(bh);
++                              clear_buffer_req(bh);
++                              bh->b_bdev = NULL;
++                      }
+               }
+               if (buffer_jbddirty(bh)) {
+--- a/fs/jbd/transaction.c
++++ b/fs/jbd/transaction.c
+@@ -1843,15 +1843,16 @@ static int __dispose_buffer(struct journ
+  * We're outside-transaction here.  Either or both of j_running_transaction
+  * and j_committing_transaction may be NULL.
+  */
+-static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
++static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
++                              int partial_page)
+ {
+       transaction_t *transaction;
+       struct journal_head *jh;
+       int may_free = 1;
+-      int ret;
+       BUFFER_TRACE(bh, "entry");
++retry:
+       /*
+        * It is safe to proceed here without the j_list_lock because the
+        * buffers cannot be stolen by try_to_free_buffers as long as we are
+@@ -1879,10 +1880,18 @@ static int journal_unmap_buffer(journal_
+        * clear the buffer dirty bit at latest at the moment when the
+        * transaction marking the buffer as freed in the filesystem
+        * structures is committed because from that moment on the
+-       * buffer can be reallocated and used by a different page.
++       * block can be reallocated and used by a different page.
+        * Since the block hasn't been freed yet but the inode has
+        * already been added to orphan list, it is safe for us to add
+        * the buffer to BJ_Forget list of the newest transaction.
++       *
++       * Also we have to clear buffer_mapped flag of a truncated buffer
++       * because the buffer_head may be attached to the page straddling
++       * i_size (can happen only when blocksize < pagesize) and thus the
++       * buffer_head can be reused when the file is extended again. So we end
++       * up keeping around invalidated buffers attached to transactions'
++       * BJ_Forget list just to stop checkpointing code from cleaning up
++       * the transaction this buffer was modified in.
+        */
+       transaction = jh->b_transaction;
+       if (transaction == NULL) {
+@@ -1909,13 +1918,9 @@ static int journal_unmap_buffer(journal_
+                        * committed, the buffer won't be needed any
+                        * longer. */
+                       JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
+-                      ret = __dispose_buffer(jh,
++                      may_free = __dispose_buffer(jh,
+                                       journal->j_running_transaction);
+-                      journal_put_journal_head(jh);
+-                      spin_unlock(&journal->j_list_lock);
+-                      jbd_unlock_bh_state(bh);
+-                      spin_unlock(&journal->j_state_lock);
+-                      return ret;
++                      goto zap_buffer;
+               } else {
+                       /* There is no currently-running transaction. So the
+                        * orphan record which we wrote for this file must have
+@@ -1923,13 +1928,9 @@ static int journal_unmap_buffer(journal_
+                        * the committing transaction, if it exists. */
+                       if (journal->j_committing_transaction) {
+                               JBUFFER_TRACE(jh, "give to committing trans");
+-                              ret = __dispose_buffer(jh,
++                              may_free = __dispose_buffer(jh,
+                                       journal->j_committing_transaction);
+-                              journal_put_journal_head(jh);
+-                              spin_unlock(&journal->j_list_lock);
+-                              jbd_unlock_bh_state(bh);
+-                              spin_unlock(&journal->j_state_lock);
+-                              return ret;
++                              goto zap_buffer;
+                       } else {
+                               /* The orphan record's transaction has
+                                * committed.  We can cleanse this buffer */
+@@ -1950,10 +1951,24 @@ static int journal_unmap_buffer(journal_
+               }
+               /*
+                * The buffer is committing, we simply cannot touch
+-               * it. So we just set j_next_transaction to the
+-               * running transaction (if there is one) and mark
+-               * buffer as freed so that commit code knows it should
+-               * clear dirty bits when it is done with the buffer.
++               * it. If the page is straddling i_size we have to wait
++               * for commit and try again.
++               */
++              if (partial_page) {
++                      tid_t tid = journal->j_committing_transaction->t_tid;
++
++                      journal_put_journal_head(jh);
++                      spin_unlock(&journal->j_list_lock);
++                      jbd_unlock_bh_state(bh);
++                      spin_unlock(&journal->j_state_lock);
++                      log_wait_commit(journal, tid);
++                      goto retry;
++              }
++              /*
++               * OK, buffer won't be reachable after truncate. We just set
++               * j_next_transaction to the running transaction (if there is
++               * one) and mark buffer as freed so that commit code knows it
++               * should clear dirty bits when it is done with the buffer.
+                */
+               set_buffer_freed(bh);
+               if (journal->j_running_transaction && buffer_jbddirty(bh))
+@@ -1976,6 +1991,14 @@ static int journal_unmap_buffer(journal_
+       }
+ zap_buffer:
++      /*
++       * This is tricky. Although the buffer is truncated, it may be reused
++       * if blocksize < pagesize and it is attached to the page straddling
++       * EOF. Since the buffer might have been added to BJ_Forget list of the
++       * running transaction, journal_get_write_access() won't clear
++       * b_modified and credit accounting gets confused. So clear b_modified
++       * here. */
++      jh->b_modified = 0;
+       journal_put_journal_head(jh);
+ zap_buffer_no_jh:
+       spin_unlock(&journal->j_list_lock);
+@@ -2024,7 +2047,8 @@ void journal_invalidatepage(journal_t *j
+               if (offset <= curr_off) {
+                       /* This block is wholly outside the truncation point */
+                       lock_buffer(bh);
+-                      may_free &= journal_unmap_buffer(journal, bh);
++                      may_free &= journal_unmap_buffer(journal, bh,
++                                                       offset > 0);
+                       unlock_buffer(bh);
+               }
+               curr_off = next_off;
diff --git a/queue-3.6/mcs7830-fix-link-state-detection.patch b/queue-3.6/mcs7830-fix-link-state-detection.patch
new file mode 100644 (file)
index 0000000..5235c20
--- /dev/null
@@ -0,0 +1,75 @@
+From dabdaf0caa3af520dbc1df87b2fb4e77224037bd Mon Sep 17 00:00:00 2001
+From: Ondrej Zary <linux@rainbow-software.org>
+Date: Thu, 11 Oct 2012 22:51:41 +0000
+Subject: mcs7830: Fix link state detection
+
+From: Ondrej Zary <linux@rainbow-software.org>
+
+commit dabdaf0caa3af520dbc1df87b2fb4e77224037bd upstream.
+
+The device had an undocumented "feature": it can provide a sequence of
+spurious link-down status data even if the link is up all the time.
+A sequence of 10 was seen so update the link state only after the device
+reports the same link state 20 times.
+
+Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
+Reported-by: Michael Leun <lkml20120218@newton.leun.net>
+Tested-by: Michael Leun <lkml20120218@newton.leun.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/mcs7830.c |   30 +++++++++++++++++++++---------
+ 1 file changed, 21 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/usb/mcs7830.c
++++ b/drivers/net/usb/mcs7830.c
+@@ -117,6 +117,7 @@ enum {
+ struct mcs7830_data {
+       u8 multi_filter[8];
+       u8 config;
++      u8 link_counter;
+ };
+ static const char driver_name[] = "MOSCHIP usb-ethernet driver";
+@@ -632,20 +633,31 @@ static int mcs7830_rx_fixup(struct usbne
+ static void mcs7830_status(struct usbnet *dev, struct urb *urb)
+ {
+       u8 *buf = urb->transfer_buffer;
+-      bool link;
++      bool link, link_changed;
++      struct mcs7830_data *data = mcs7830_get_data(dev);
+       if (urb->actual_length < 16)
+               return;
+       link = !(buf[1] & 0x20);
+-      if (netif_carrier_ok(dev->net) != link) {
+-              if (link) {
+-                      netif_carrier_on(dev->net);
+-                      usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+-              } else
+-                      netif_carrier_off(dev->net);
+-              netdev_dbg(dev->net, "Link Status is: %d\n", link);
+-      }
++      link_changed = netif_carrier_ok(dev->net) != link;
++      if (link_changed) {
++              data->link_counter++;
++              /*
++                 track link state 20 times to guard against erroneous
++                 link state changes reported sometimes by the chip
++               */
++              if (data->link_counter > 20) {
++                      data->link_counter = 0;
++                      if (link) {
++                              netif_carrier_on(dev->net);
++                              usbnet_defer_kevent(dev, EVENT_LINK_RESET);
++                      } else
++                              netif_carrier_off(dev->net);
++                      netdev_dbg(dev->net, "Link Status is: %d\n", link);
++              }
++      } else
++              data->link_counter = 0;
+ }
+ static const struct driver_info moschip_info = {
diff --git a/queue-3.6/mtd-nand-allow-nand_no_subpage_write-to-be-set-from-driver.patch b/queue-3.6/mtd-nand-allow-nand_no_subpage_write-to-be-set-from-driver.patch
new file mode 100644 (file)
index 0000000..18a870c
--- /dev/null
@@ -0,0 +1,71 @@
+From bf7a01bf7987b63b121d572b240c132ec44129c4 Mon Sep 17 00:00:00 2001
+From: Brian Norris <computersforpeace@gmail.com>
+Date: Fri, 13 Jul 2012 09:28:24 -0700
+Subject: mtd: nand: allow NAND_NO_SUBPAGE_WRITE to be set from driver
+
+From: Brian Norris <computersforpeace@gmail.com>
+
+commit bf7a01bf7987b63b121d572b240c132ec44129c4 upstream.
+
+The NAND_CHIPOPTIONS_MSK has limited utility and is causing real bugs. It
+silently masks off at least one flag that might be set by the driver
+(NAND_NO_SUBPAGE_WRITE). This breaks the GPMI NAND driver and possibly
+others.
+
+Really, as long as driver writers exercise a small amount of care with
+NAND_* options, this mask is not necessary at all; it was only here to
+prevent certain options from accidentally being set by the driver. But the
+original thought turns out to be a bad idea occasionally. Thus, kill it.
+
+Note, this patch fixes some major gpmi-nand breakage.
+
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+Tested-by: Huang Shijie <shijie8@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+index a11253a..c429abd 100644
+---
+ drivers/mtd/nand/nand_base.c |    8 +++-----
+ include/linux/mtd/nand.h     |    3 ---
+ 2 files changed, 3 insertions(+), 8 deletions(-)
+
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -2914,8 +2914,7 @@ static int nand_flash_detect_onfi(struct
+       if (le16_to_cpu(p->features) & 1)
+               *busw = NAND_BUSWIDTH_16;
+-      chip->options &= ~NAND_CHIPOPTIONS_MSK;
+-      chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK;
++      chip->options |= NAND_NO_READRDY;
+       pr_info("ONFI flash detected\n");
+       return 1;
+@@ -3080,9 +3079,8 @@ static struct nand_flash_dev *nand_get_f
+                       mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
+               }
+       }
+-      /* Get chip options, preserve non chip based options */
+-      chip->options &= ~NAND_CHIPOPTIONS_MSK;
+-      chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
++      /* Get chip options */
++      chip->options |= type->options;
+       /*
+        * Check if chip is not a Samsung device. Do not clear the
+--- a/include/linux/mtd/nand.h
++++ b/include/linux/mtd/nand.h
+@@ -212,9 +212,6 @@ typedef enum {
+ #define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
+                                       && (chip->page_shift > 9))
+-/* Mask to zero out the chip options, which come from the id table */
+-#define NAND_CHIPOPTIONS_MSK  0x0000ffff
+-
+ /* Non chip related options */
+ /* This option skips the bbt scan during initialization. */
+ #define NAND_SKIP_BBTSCAN     0x00010000
index 0b4462fec2a76f84c308b58cfcb950d19035da53..ab1240da639347a61e85218f86d70dfa63a1e7a2 100644 (file)
@@ -59,3 +59,9 @@ drm-i915-remove-useless-bug_on-which-caused-a-regression-in-3.5.patch
 drm-i915-set-guardband-clipping-workaround-bit-in-the-right-register.patch
 drm-nouveau-bios-fix-shadowing-of-acpi-roms-larger-than-64kib.patch
 drm-i915-use-adjusted_mode-instead-of-mode-for-checking-the-6bpc-force-flag.patch
+mcs7830-fix-link-state-detection.patch
+jbd-fix-assertion-failure-in-commit-code-due-to-lacking-transaction-credits.patch
+mtd-nand-allow-nand_no_subpage_write-to-be-set-from-driver.patch
+e1000e-change-wthresh-to-1-to-avoid-possible-tx-stalls.patch
+tpm-propagate-error-from-tpm_transmit-to-fix-a-timeout-hang.patch
+usb-gadget-at91_udc-fix-dt-support.patch
diff --git a/queue-3.6/tpm-propagate-error-from-tpm_transmit-to-fix-a-timeout-hang.patch b/queue-3.6/tpm-propagate-error-from-tpm_transmit-to-fix-a-timeout-hang.patch
new file mode 100644 (file)
index 0000000..6d4e56b
--- /dev/null
@@ -0,0 +1,95 @@
+From abce9ac292e13da367bbd22c1f7669f988d931ac Mon Sep 17 00:00:00 2001
+From: Peter Huewe <peter.huewe@infineon.com>
+Date: Thu, 27 Sep 2012 16:09:33 +0200
+Subject: tpm: Propagate error from tpm_transmit to fix a timeout hang
+
+From: Peter Huewe <peter.huewe@infineon.com>
+
+commit abce9ac292e13da367bbd22c1f7669f988d931ac upstream.
+
+tpm_write calls tpm_transmit without checking the return value and
+assigns the return value unconditionally to chip->pending_data, even if
+it's an error value.
+This causes three bugs.
+
+So if we write to /dev/tpm0 with a tpm_param_size bigger than
+TPM_BUFSIZE=0x1000 (e.g. 0x100a)
+and a bufsize also bigger than TPM_BUFSIZE (e.g. 0x100a)
+tpm_transmit returns -E2BIG which is assigned to chip->pending_data as
+-7, but tpm_write returns that TPM_BUFSIZE bytes have been successfully
+been written to the TPM, altough this is not true (bug #1).
+
+As we did write more than than TPM_BUFSIZE bytes but tpm_write reports
+that only TPM_BUFSIZE bytes have been written the vfs tries to write
+the remaining bytes (in this case 10 bytes) to the tpm device driver via
+tpm_write which then blocks at
+
+ /* cannot perform a write until the read has cleared
+ either via tpm_read or a user_read_timer timeout */
+ while (atomic_read(&chip->data_pending) != 0)
+        msleep(TPM_TIMEOUT);
+
+for 60 seconds, since data_pending is -7 and nobody is able to
+read it (since tpm_read luckily checks if data_pending is greater than
+0) (#bug 2).
+
+After that the remaining bytes are written to the TPM which are
+interpreted by the tpm as a normal command. (bug #3)
+So if the last bytes of the command stream happen to be a e.g.
+tpm_force_clear this gets accidentally sent to the TPM.
+
+This patch fixes all three bugs, by propagating the error code of
+tpm_write and returning -E2BIG if the input buffer is too big,
+since the response from the tpm for a truncated value is bogus anyway.
+Moreover it returns -EBUSY to userspace if there is a response ready to be
+read.
+
+Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
+Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm.c |   21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+--- a/drivers/char/tpm/tpm.c
++++ b/drivers/char/tpm/tpm.c
+@@ -1186,17 +1186,20 @@ ssize_t tpm_write(struct file *file, con
+                 size_t size, loff_t *off)
+ {
+       struct tpm_chip *chip = file->private_data;
+-      size_t in_size = size, out_size;
++      size_t in_size = size;
++      ssize_t out_size;
+       /* cannot perform a write until the read has cleared
+-         either via tpm_read or a user_read_timer timeout */
+-      while (atomic_read(&chip->data_pending) != 0)
+-              msleep(TPM_TIMEOUT);
+-
+-      mutex_lock(&chip->buffer_mutex);
++         either via tpm_read or a user_read_timer timeout.
++         This also prevents splitted buffered writes from blocking here.
++      */
++      if (atomic_read(&chip->data_pending) != 0)
++              return -EBUSY;
+       if (in_size > TPM_BUFSIZE)
+-              in_size = TPM_BUFSIZE;
++              return -E2BIG;
++
++      mutex_lock(&chip->buffer_mutex);
+       if (copy_from_user
+           (chip->data_buffer, (void __user *) buf, in_size)) {
+@@ -1206,6 +1209,10 @@ ssize_t tpm_write(struct file *file, con
+       /* atomic tpm command send and result receive */
+       out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
++      if (out_size < 0) {
++              mutex_unlock(&chip->buffer_mutex);
++              return out_size;
++      }
+       atomic_set(&chip->data_pending, out_size);
+       mutex_unlock(&chip->buffer_mutex);
diff --git a/queue-3.6/usb-gadget-at91_udc-fix-dt-support.patch b/queue-3.6/usb-gadget-at91_udc-fix-dt-support.patch
new file mode 100644 (file)
index 0000000..b4ac106
--- /dev/null
@@ -0,0 +1,31 @@
+From 9c6d196d5aa35e07482f23c3e37755e7a82140e0 Mon Sep 17 00:00:00 2001
+From: Fabio Porcedda <fabio.porcedda@gmail.com>
+Date: Fri, 7 Sep 2012 15:27:42 +0200
+Subject: usb: gadget: at91_udc: fix dt support
+
+From: Fabio Porcedda <fabio.porcedda@gmail.com>
+
+commit 9c6d196d5aa35e07482f23c3e37755e7a82140e0 upstream.
+
+Don't fail the initialization check for the platform_data
+if there is avaiable an associated device tree node.
+
+Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/at91_udc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/at91_udc.c
++++ b/drivers/usb/gadget/at91_udc.c
+@@ -1699,7 +1699,7 @@ static int __devinit at91udc_probe(struc
+       int             retval;
+       struct resource *res;
+-      if (!dev->platform_data) {
++      if (!dev->platform_data && !pdev->dev.of_node) {
+               /* small (so we copy it) but critical! */
+               DBG("missing platform_data\n");
+               return -ENODEV;