--- /dev/null
+From: Pramod Kumar <pramod@chelsio.com>
+Subject: [PATCH] RDMA/cxgb4: Configure 0B MRs to match HW implementation
+
+0B MRs need some tweaks to work correctly with HW. When writing the
+TPTE, if the MR length is zero we now:
+
+1) turn off all permissions
+2) set the length to -1
+
+While functionality/capabilities of the MR are the same with these
+changes, it resolves a dapltest 0B RDMA Read test failure. Based on
+original work by Steve Wise <swise@opengridcomputing.com>.
+
+Signed-off-by: Pramod Kumar <pramod@chelsio.com>
+Signed-off-by: Steve Wise <swise@opengridcomputing.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/hw/cxgb4/mem.c | 6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/infiniband/hw/cxgb4/mem.c
++++ b/drivers/infiniband/hw/cxgb4/mem.c
+@@ -369,9 +369,11 @@ static int register_mem(struct c4iw_dev *rhp, struct c4iw_pd *php,
+ int ret;
+
+ ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, mhp->attr.pdid,
+- FW_RI_STAG_NSMR, mhp->attr.perms,
++ FW_RI_STAG_NSMR, mhp->attr.len ?
++ mhp->attr.perms : 0,
+ mhp->attr.mw_bind_enable, mhp->attr.zbva,
+- mhp->attr.va_fbo, mhp->attr.len, shift - 12,
++ mhp->attr.va_fbo, mhp->attr.len ?
++ mhp->attr.len : -1, shift - 12,
+ mhp->attr.pbl_size, mhp->attr.pbl_addr);
+ if (ret)
+ return ret;
--- /dev/null
+From: Hariprasad Shenai <hariprasad@chelsio.com>
+Subject: [PATCH] RDMA/cxgb4: Fix locking issue in process_mpa_request
+
+Fix the following lockdep report:
+
+ =============================================
+ [ INFO: possible recursive locking detected ]
+ 3.17.0+ #3 Tainted: G E
+ ---------------------------------------------
+ kworker/u64:3/299 is trying to acquire lock:
+ (&epc->mutex){+.+.+.}, at: [<ffffffffa074e07a>]
+ process_mpa_request+0x1aa/0x3e0 [iw_cxgb4]
+
+ but task is already holding lock:
+ (&epc->mutex){+.+.+.}, at: [<ffffffffa074e34e>] rx_data+0x9e/0x1f0 [iw_cxgb4]
+
+ other info that might help us debug this:
+ Possible unsafe locking scenario:
+
+ CPU0
+ ----
+ lock(&epc->mutex);
+ lock(&epc->mutex);
+
+ *** DEADLOCK ***
+
+ May be due to missing lock nesting notation
+
+ 3 locks held by kworker/u64:3/299:
+ #0: ("%s""iw_cxgb4"){.+.+.+}, at: [<ffffffff8106f14d>]
+ process_one_work+0x13d/0x4d0
+ #1: (skb_work){+.+.+.}, at: [<ffffffff8106f14d>] process_one_work+0x13d/0x4d0
+ #2: (&epc->mutex){+.+.+.}, at: [<ffffffffa074e34e>] rx_data+0x9e/0x1f0
+ [iw_cxgb4]
+
+ stack backtrace:
+ CPU: 2 PID: 299 Comm: kworker/u64:3 Tainted: G E 3.17.0+ #3
+ Hardware name: Dell Inc. PowerEdge T110/0X744K, BIOS 1.2.1 01/28/2010
+ Workqueue: iw_cxgb4 process_work [iw_cxgb4]
+ ffff8800b91593d0 ffff8800b8a2f9f8 ffffffff815df107 0000000000000001
+ ffff8800b9158750 ffff8800b8a2fa28 ffffffff8109f0e2 ffff8800bb768a00
+ ffff8800b91593d0 ffff8800b9158750 0000000000000000 ffff8800b8a2fa88
+ Call Trace:
+ [<ffffffff815df107>] dump_stack+0x49/0x62
+ [<ffffffff8109f0e2>] print_deadlock_bug+0xf2/0x100
+ [<ffffffff810a0f04>] validate_chain+0x454/0x700
+ [<ffffffff810a1574>] __lock_acquire+0x3c4/0x580
+ [<ffffffffa074e07a>] ? process_mpa_request+0x1aa/0x3e0 [iw_cxgb4]
+ [<ffffffff810a17cc>] lock_acquire+0x9c/0x110
+ [<ffffffffa074e07a>] ? process_mpa_request+0x1aa/0x3e0 [iw_cxgb4]
+ [<ffffffff815e111b>] mutex_lock_nested+0x4b/0x360
+ [<ffffffffa074e07a>] ? process_mpa_request+0x1aa/0x3e0 [iw_cxgb4]
+ [<ffffffff810c181a>] ? del_timer_sync+0xaa/0xd0
+ [<ffffffff810c1770>] ? try_to_del_timer_sync+0x70/0x70
+ [<ffffffffa074e07a>] process_mpa_request+0x1aa/0x3e0 [iw_cxgb4]
+ [<ffffffffa074a3ec>] ? update_rx_credits+0xec/0x140 [iw_cxgb4]
+ [<ffffffffa074e381>] rx_data+0xd1/0x1f0 [iw_cxgb4]
+ [<ffffffff8109ff23>] ? mark_held_locks+0x73/0xa0
+ [<ffffffff815e4b90>] ? _raw_spin_unlock_irqrestore+0x40/0x70
+ [<ffffffff810a020d>] ? trace_hardirqs_on_caller+0xfd/0x1c0
+ [<ffffffff810a02dd>] ? trace_hardirqs_on+0xd/0x10
+ [<ffffffffa074c931>] process_work+0x51/0x80 [iw_cxgb4]
+ [<ffffffff8106f1c8>] process_one_work+0x1b8/0x4d0
+ [<ffffffff8106f14d>] ? process_one_work+0x13d/0x4d0
+ [<ffffffff8106f600>] worker_thread+0x120/0x3c0
+ [<ffffffff8106f4e0>] ? process_one_work+0x4d0/0x4d0
+ [<ffffffff81074a0e>] kthread+0xde/0x100
+ [<ffffffff815e4b40>] ? _raw_spin_unlock_irq+0x30/0x40
+ [<ffffffff81074930>] ? __init_kthread_worker+0x70/0x70
+ [<ffffffff815e512c>] ret_from_fork+0x7c/0xb0
+ [<ffffffff81074930>] ? __init_kthread_worker+0x70/0x70
+
+Based on original work by Steve Wise <swise@opengridcomputing.com>.
+
+Signed-off-by: Steve Wise <swise@opengridcomputing.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/hw/cxgb4/cm.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/infiniband/hw/cxgb4/cm.c
++++ b/drivers/infiniband/hw/cxgb4/cm.c
+@@ -1640,7 +1640,8 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
+ __state_set(&ep->com, MPA_REQ_RCVD);
+
+ /* drive upcall */
+- mutex_lock(&ep->parent_ep->com.mutex);
++ mutex_lock_nested(&ep->parent_ep->com.mutex,
++ SINGLE_DEPTH_NESTING);
+ if (ep->parent_ep->com.state != DEAD) {
+ if (connect_request_upcall(ep))
+ abort_connection(ep, skb, GFP_KERNEL);
--- /dev/null
+From: Hariprasad Shenai <hariprasad@chelsio.com>
+Subject: [PATCH] RDMA/cxgb4: Limit MRs to < 8GB for T4/T5 devices
+
+T4/T5 hardware can't handle MRs >= 8GB due to a hardware bug. So limit
+registrations to < 8GB for thse devices.
+
+Based on original work by Steve Wise <swise@opengridcomputing.com>.
+
+Signed-off-by: Steve Wise <swise@opengridcomputing.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/hw/cxgb4/mem.c | 22 ++++++++++++++++++++++
+ 1 files changed, 22 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/infiniband/hw/cxgb4/mem.c
++++ b/drivers/infiniband/hw/cxgb4/mem.c
+@@ -50,6 +50,13 @@ static int inline_threshold = C4IW_INLINE_THRESHOLD;
+ module_param(inline_threshold, int, 0644);
+ MODULE_PARM_DESC(inline_threshold, "inline vs dsgl threshold (default=128)");
+
++static int mr_exceeds_hw_limits(struct c4iw_dev *dev, u64 length)
++{
++ return (is_t4(dev->rdev.lldi.adapter_type) ||
++ is_t5(dev->rdev.lldi.adapter_type)) &&
++ length >= 8*1024*1024*1024ULL;
++}
++
+ static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr,
+ u32 len, dma_addr_t data, int wait)
+ {
+@@ -538,6 +545,11 @@ int c4iw_reregister_phys_mem(struct ib_mr *mr, int mr_rereg_mask,
+ return ret;
+ }
+
++ if (mr_exceeds_hw_limits(rhp, total_size)) {
++ kfree(page_list);
++ return -EINVAL;
++ }
++
+ ret = reregister_mem(rhp, php, &mh, shift, npages);
+ kfree(page_list);
+ if (ret)
+@@ -598,6 +610,12 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
+ if (ret)
+ goto err;
+
++ if (mr_exceeds_hw_limits(rhp, total_size)) {
++ kfree(page_list);
++ ret = -EINVAL;
++ goto err;
++ }
++
+ ret = alloc_pbl(mhp, npages);
+ if (ret) {
+ kfree(page_list);
+@@ -701,6 +719,10 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+
+ php = to_c4iw_pd(pd);
+ rhp = php->rhp;
++
++ if (mr_exceeds_hw_limits(rhp, length))
++ return ERR_PTR(-EINVAL);
++
+ mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
+ if (!mhp)
+ return ERR_PTR(-ENOMEM);
--- /dev/null
+From: Steve Wise <swise@opengridcomputing.com>
+Subject: [PATCH] RDMA/cxgb4: Wake up waiters after flushing the qp
+
+When transitioning into ERROR state, the QP was getting flushed after
+waking up any waiters. This can cause applications to miss flushed work
+requests which can stall an NFS mount.
+
+Signed-off-by: Steve Wise <swise@opengridcomputing.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/hw/cxgb4/qp.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/infiniband/hw/cxgb4/qp.c
++++ b/drivers/infiniband/hw/cxgb4/qp.c
+@@ -1538,9 +1538,9 @@ err:
+ set_state(qhp, C4IW_QP_STATE_ERROR);
+ free = 1;
+ abort = 1;
+- wake_up(&qhp->wait);
+ BUG_ON(!ep);
+ flush_qp(qhp);
++ wake_up(&qhp->wait);
+ out:
+ mutex_unlock(&qhp->mutex);
+