summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZefan Li <lizefan@huawei.com>2015-10-13 20:43:23 +0800
committerZefan Li <lizefan@huawei.com>2015-10-13 20:43:23 +0800
commit30370a66fcc80d3686e85b658147e80a70b216dc (patch)
tree326d0181560f51048cdc65292deaa992d8d2dd4c
parent1afe6fdedef22bbaaff59f875ce7fd9205a0d2c3 (diff)
downloadlinux-3.4.y-queue-30370a66fcc80d3686e85b658147e80a70b216dc.tar.gz
Add a few fixes
-rw-r--r--patches/ib-qib-change-lkey-table-allocation-to-support-more-mrs.patch119
-rw-r--r--patches/jbd2-avoid-infinite-loop-when-destroying-aborted-journal.patch171
-rw-r--r--patches/series3
-rw-r--r--patches/usb-dwc3-reset-the-transfer-resource-index-on-set_interface.patch53
4 files changed, 346 insertions, 0 deletions
diff --git a/patches/ib-qib-change-lkey-table-allocation-to-support-more-mrs.patch b/patches/ib-qib-change-lkey-table-allocation-to-support-more-mrs.patch
new file mode 100644
index 0000000..6799a4d
--- /dev/null
+++ b/patches/ib-qib-change-lkey-table-allocation-to-support-more-mrs.patch
@@ -0,0 +1,119 @@
+From 9f386b43b12b8051a610e790c74865e83a8804cd Mon Sep 17 00:00:00 2001
+From: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Date: Fri, 9 Oct 2015 01:12:28 +0100
+Subject: [PATCH] IB/qib: Change lkey table allocation to support more MRs
+
+commit d6f1c17e162b2a11e708f28fa93f2f79c164b442 upstream.
+
+The lkey table is allocated with with a get_user_pages() with an
+order based on a number of index bits from a module parameter.
+
+The underlying kernel code cannot allocate that many contiguous pages.
+
+There is no reason the underlying memory needs to be physically
+contiguous.
+
+This patch:
+- switches the allocation/deallocation to vmalloc/vfree
+- caps the number of bits to 23 to insure at least 1 generation bit
+ o this matches the module parameter description
+
+Reviewed-by: Vinit Agnihotri <vinit.abhay.agnihotri@intel.com>
+Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+[bwh: Backported to 3.2:
+ - Adjust context
+ - Add definition of qib_dev_warn(), added upstream by commit ddb887658970
+ ("IB/qib: Convert opcode counters to per-context")]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/infiniband/hw/qib/qib.h | 4 ++++
+ drivers/infiniband/hw/qib/qib_keys.c | 4 ++++
+ drivers/infiniband/hw/qib/qib_verbs.c | 14 ++++++++++----
+ drivers/infiniband/hw/qib/qib_verbs.h | 2 ++
+ 4 files changed, 20 insertions(+), 4 deletions(-)
+
+--- a/drivers/infiniband/hw/qib/qib.h
++++ b/drivers/infiniband/hw/qib/qib.h
+@@ -1429,6 +1429,10 @@ extern struct mutex qib_mutex;
+ qib_get_unit_name((dd)->unit), ##__VA_ARGS__); \
+ } while (0)
+
++#define qib_dev_warn(dd, fmt, ...) \
++ dev_warn(&(dd)->pcidev->dev, "%s: " fmt, \
++ qib_get_unit_name((dd)->unit), ##__VA_ARGS__)
++
+ #define qib_dev_porterr(dd, port, fmt, ...) \
+ do { \
+ dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \
+--- a/drivers/infiniband/hw/qib/qib_keys.c
++++ b/drivers/infiniband/hw/qib/qib_keys.c
+@@ -69,6 +69,10 @@ int qib_alloc_lkey(struct qib_lkey_table
+ * unrestricted LKEY.
+ */
+ rkt->gen++;
++ /*
++ * bits are capped in qib_verbs.c to insure enough bits
++ * for generation number
++ */
+ mr->lkey = (r << (32 - ib_qib_lkey_table_size)) |
+ ((((1 << (24 - ib_qib_lkey_table_size)) - 1) & rkt->gen)
+ << 8);
+--- a/drivers/infiniband/hw/qib/qib_verbs.c
++++ b/drivers/infiniband/hw/qib/qib_verbs.c
+@@ -40,6 +40,7 @@
+ #include <linux/rculist.h>
+ #include <linux/mm.h>
+ #include <linux/random.h>
++#include <linux/vmalloc.h>
+
+ #include "qib.h"
+ #include "qib_common.h"
+@@ -2058,10 +2059,16 @@ int qib_register_ib_device(struct qib_de
+ * the LKEY). The remaining bits act as a generation number or tag.
+ */
+ spin_lock_init(&dev->lk_table.lock);
++ /* insure generation is at least 4 bits see keys.c */
++ if (ib_qib_lkey_table_size > MAX_LKEY_TABLE_BITS) {
++ qib_dev_warn(dd, "lkey bits %u too large, reduced to %u\n",
++ ib_qib_lkey_table_size, MAX_LKEY_TABLE_BITS);
++ ib_qib_lkey_table_size = MAX_LKEY_TABLE_BITS;
++ }
+ dev->lk_table.max = 1 << ib_qib_lkey_table_size;
+ lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
+ dev->lk_table.table = (struct qib_mregion **)
+- __get_free_pages(GFP_KERNEL, get_order(lk_tab_size));
++ vmalloc(lk_tab_size);
+ if (dev->lk_table.table == NULL) {
+ ret = -ENOMEM;
+ goto err_lk;
+@@ -2231,7 +2238,7 @@ err_tx:
+ sizeof(struct qib_pio_header),
+ dev->pio_hdrs, dev->pio_hdrs_phys);
+ err_hdrs:
+- free_pages((unsigned long) dev->lk_table.table, get_order(lk_tab_size));
++ vfree(dev->lk_table.table);
+ err_lk:
+ kfree(dev->qp_table);
+ err_qpt:
+@@ -2285,7 +2292,6 @@ void qib_unregister_ib_device(struct qib
+ sizeof(struct qib_pio_header),
+ dev->pio_hdrs, dev->pio_hdrs_phys);
+ lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
+- free_pages((unsigned long) dev->lk_table.table,
+- get_order(lk_tab_size));
++ vfree(dev->lk_table.table);
+ kfree(dev->qp_table);
+ }
+--- a/drivers/infiniband/hw/qib/qib_verbs.h
++++ b/drivers/infiniband/hw/qib/qib_verbs.h
+@@ -622,6 +622,8 @@ struct qib_qpn_table {
+ struct qpn_map map[QPNMAP_ENTRIES];
+ };
+
++#define MAX_LKEY_TABLE_BITS 23
++
+ struct qib_lkey_table {
+ spinlock_t lock; /* protect changes in this struct */
+ u32 next; /* next unused index (speeds search) */
diff --git a/patches/jbd2-avoid-infinite-loop-when-destroying-aborted-journal.patch b/patches/jbd2-avoid-infinite-loop-when-destroying-aborted-journal.patch
new file mode 100644
index 0000000..eaaa1b5
--- /dev/null
+++ b/patches/jbd2-avoid-infinite-loop-when-destroying-aborted-journal.patch
@@ -0,0 +1,171 @@
+From 841df7df196237ea63233f0f9eaa41db53afd70f Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.com>
+Date: Tue, 28 Jul 2015 14:57:14 -0400
+Subject: jbd2: avoid infinite loop when destroying aborted journal
+
+commit 841df7df196237ea63233f0f9eaa41db53afd70f upstream.
+
+Commit 6f6a6fda2945 "jbd2: fix ocfs2 corrupt when updating journal
+superblock fails" changed jbd2_cleanup_journal_tail() to return EIO
+when the journal is aborted. That makes logic in
+jbd2_log_do_checkpoint() bail out which is fine, except that
+jbd2_journal_destroy() expects jbd2_log_do_checkpoint() to always make
+a progress in cleaning the journal. Without it jbd2_journal_destroy()
+just loops in an infinite loop.
+
+Fix jbd2_journal_destroy() to cleanup journal checkpoint lists of
+jbd2_log_do_checkpoint() fails with error.
+
+Reported-by: Eryu Guan <guaneryu@gmail.com>
+Tested-by: Eryu Guan <guaneryu@gmail.com>
+Fixes: 6f6a6fda294506dfe0e3e0a253bb2d2923f28f0a
+Signed-off-by: Jan Kara <jack@suse.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+[lizf: Backported to 3.4: adjust context]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ fs/jbd2/checkpoint.c | 39 +++++++++++++++++++++++++++++++++------
+ fs/jbd2/commit.c | 2 +-
+ fs/jbd2/journal.c | 11 ++++++++++-
+ include/linux/jbd2.h | 3 ++-
+ 4 files changed, 46 insertions(+), 9 deletions(-)
+
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -467,14 +467,14 @@ int jbd2_cleanup_journal_tail(journal_t
+ * journal_clean_one_cp_list
+ *
+ * Find all the written-back checkpoint buffers in the given list and
+- * release them.
++ * release them. If 'destroy' is set, clean all buffers unconditionally.
+ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ * Returns number of buffers reaped (for debug)
+ */
+
+-static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
++static int journal_clean_one_cp_list(struct journal_head *jh, int *released, bool destroy)
+ {
+ struct journal_head *last_jh;
+ struct journal_head *next_jh = jh;
+@@ -488,7 +488,10 @@ static int journal_clean_one_cp_list(str
+ do {
+ jh = next_jh;
+ next_jh = jh->b_cpnext;
+- ret = __try_to_free_cp_buf(jh);
++ if (!destroy)
++ ret = __try_to_free_cp_buf(jh);
++ else
++ ret = __jbd2_journal_remove_checkpoint(jh) + 1;
+ if (ret) {
+ freed++;
+ if (ret == 2) {
+@@ -514,12 +517,14 @@ static int journal_clean_one_cp_list(str
+ *
+ * Find all the written-back checkpoint buffers in the journal and release them.
+ *
++ * If 'destroy' is set, release all buffers unconditionally.
++ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ * Returns number of buffers reaped (for debug)
+ */
+
+-int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
++int __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
+ {
+ transaction_t *transaction, *last_transaction, *next_transaction;
+ int ret = 0;
+@@ -535,7 +540,7 @@ int __jbd2_journal_clean_checkpoint_list
+ transaction = next_transaction;
+ next_transaction = transaction->t_cpnext;
+ ret += journal_clean_one_cp_list(transaction->
+- t_checkpoint_list, &released);
++ t_checkpoint_list, &released, destroy);
+ /*
+ * This function only frees up some memory if possible so we
+ * dont have an obligation to finish processing. Bail out if
+@@ -551,7 +556,7 @@ int __jbd2_journal_clean_checkpoint_list
+ * we can possibly see not yet submitted buffers on io_list
+ */
+ ret += journal_clean_one_cp_list(transaction->
+- t_checkpoint_io_list, &released);
++ t_checkpoint_io_list, &released, destroy);
+ if (need_resched())
+ goto out;
+ } while (transaction != last_transaction);
+@@ -560,6 +565,28 @@ out:
+ }
+
+ /*
++ * Remove buffers from all checkpoint lists as journal is aborted and we just
++ * need to free memory
++ */
++void jbd2_journal_destroy_checkpoint(journal_t *journal)
++{
++ /*
++ * We loop because __jbd2_journal_clean_checkpoint_list() may abort
++ * early due to a need of rescheduling.
++ */
++ while (1) {
++ spin_lock(&journal->j_list_lock);
++ if (!journal->j_checkpoint_transactions) {
++ spin_unlock(&journal->j_list_lock);
++ break;
++ }
++ __jbd2_journal_clean_checkpoint_list(journal, true);
++ spin_unlock(&journal->j_list_lock);
++ cond_resched();
++ }
++}
++
++/*
+ * journal_remove_checkpoint: called after a buffer has been committed
+ * to disk (either by being write-back flushed to disk, or being
+ * committed to the log).
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -438,7 +438,7 @@ void jbd2_journal_commit_transaction(jou
+ * frees some memory
+ */
+ spin_lock(&journal->j_list_lock);
+- __jbd2_journal_clean_checkpoint_list(journal);
++ __jbd2_journal_clean_checkpoint_list(journal, false);
+ spin_unlock(&journal->j_list_lock);
+
+ jbd_debug(3, "JBD2: commit phase 1\n");
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1591,8 +1591,17 @@ int jbd2_journal_destroy(journal_t *jour
+ while (journal->j_checkpoint_transactions != NULL) {
+ spin_unlock(&journal->j_list_lock);
+ mutex_lock(&journal->j_checkpoint_mutex);
+- jbd2_log_do_checkpoint(journal);
++ err = jbd2_log_do_checkpoint(journal);
+ mutex_unlock(&journal->j_checkpoint_mutex);
++ /*
++ * If checkpointing failed, just free the buffers to avoid
++ * looping forever
++ */
++ if (err) {
++ jbd2_journal_destroy_checkpoint(journal);
++ spin_lock(&journal->j_list_lock);
++ break;
++ }
+ spin_lock(&journal->j_list_lock);
+ }
+
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -981,8 +981,9 @@ void jbd2_update_log_tail(journal_t *jou
+ extern void jbd2_journal_commit_transaction(journal_t *);
+
+ /* Checkpoint list management */
+-int __jbd2_journal_clean_checkpoint_list(journal_t *journal);
++int __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy);
+ int __jbd2_journal_remove_checkpoint(struct journal_head *);
++void jbd2_journal_destroy_checkpoint(journal_t *journal);
+ void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
+
+
diff --git a/patches/series b/patches/series
index 6804feb..a963646 100644
--- a/patches/series
+++ b/patches/series
@@ -58,3 +58,6 @@ revert-drm-radeon-use-drm_calloc_ab-for-cs-relocs.patch
drm-radeon-partially-revert-fix-vm_context-_page_table_end_addr-handling.patch
crypto-s390-ghash-fix-incorrect-backport-of-a1cae34e23b1.patch
arm-fix-incorrect-backport-of-0b59d8806a31.patch
+usb-dwc3-reset-the-transfer-resource-index-on-set_interface.patch
+jbd2-avoid-infinite-loop-when-destroying-aborted-journal.patch
+ib-qib-change-lkey-table-allocation-to-support-more-mrs.patch
diff --git a/patches/usb-dwc3-reset-the-transfer-resource-index-on-set_interface.patch b/patches/usb-dwc3-reset-the-transfer-resource-index-on-set_interface.patch
new file mode 100644
index 0000000..69b9f49
--- /dev/null
+++ b/patches/usb-dwc3-reset-the-transfer-resource-index-on-set_interface.patch
@@ -0,0 +1,53 @@
+From aebda618718157a69c0dc0adb978d69bc2b8723c Mon Sep 17 00:00:00 2001
+From: John Youn <John.Youn@synopsys.com>
+Date: Mon, 17 Sep 2001 00:00:00 -0700
+Subject: usb: dwc3: Reset the transfer resource index on SET_INTERFACE
+
+commit aebda618718157a69c0dc0adb978d69bc2b8723c upstream.
+
+This fixes an issue introduced in commit b23c843992b6 (usb: dwc3:
+gadget: fix DEPSTARTCFG for non-EP0 EPs) that made sure we would
+only use DEPSTARTCFG once per SetConfig.
+
+The trick is that we should use one DEPSTARTCFG per SetConfig *OR*
+SetInterface. SetInterface was completely missed from the original
+patch.
+
+This problem became aparent after commit 76e838c9f776 (usb: dwc3:
+gadget: return error if command sent to DEPCMD register fails)
+added checking of the return status of device endpoint commands.
+
+'Set Endpoint Transfer Resource' command was caught failing
+occasionally. This is because the Transfer Resource
+Index was not getting reset during a SET_INTERFACE request.
+
+Finally, to fix the issue, was we have to do is make sure that
+our start_config_issued flag gets reset whenever we receive a
+SetInterface request.
+
+To verify the problem (and its fix), all we have to do is run
+test 9 from testusb with 'testusb -t 9 -s 2048 -a -c 5000'.
+
+Tested-by: Huang Rui <ray.huang@amd.com>
+Tested-by: Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
+Fixes: b23c843992b6 (usb: dwc3: gadget: fix DEPSTARTCFG for non-EP0 EPs)
+Signed-off-by: John Youn <johnyoun@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/usb/dwc3/ep0.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -644,6 +644,10 @@ static void dwc3_ep0_xfer_complete(struc
+ dev_vdbg(dwc->dev, "Status Phase\n");
+ dwc3_ep0_complete_req(dwc, event);
+ break;
++ case USB_REQ_SET_INTERFACE:
++ dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE");
++ dwc->start_config_issued = false;
++ /* Fall through */
+ default:
+ WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state);
+ }