]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.11.2/ib-hfi1-prevent-kernel-qp-post-send-hard-lockups.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.11.2 / ib-hfi1-prevent-kernel-qp-post-send-hard-lockups.patch
CommitLineData
5032628c
GKH
1From b6eac931b9bb2bce4db7032c35b41e5e34ec22a5 Mon Sep 17 00:00:00 2001
2From: Mike Marciniszyn <mike.marciniszyn@intel.com>
3Date: Sun, 9 Apr 2017 10:16:35 -0700
4Subject: IB/hfi1: Prevent kernel QP post send hard lockups
5
6From: Mike Marciniszyn <mike.marciniszyn@intel.com>
7
8commit b6eac931b9bb2bce4db7032c35b41e5e34ec22a5 upstream.
9
10The driver progress routines can call cond_resched() when
11a timeslice is exhausted and irqs are enabled.
12
13If the ULP had been holding a spin lock without disabling irqs and
14the post send directly called the progress routine, the cond_resched()
15could yield allowing another thread from the same ULP to deadlock
16on that same lock.
17
18Correct by replacing the current hfi1_do_send() calldown with a unique
19one for post send and adding an argument to hfi1_do_send() to indicate
20that the send engine is running in a thread. If the routine is not
21running in a thread, avoid calling cond_resched().
22
23Fixes: Commit 831464ce4b74 ("IB/hfi1: Don't call cond_resched in atomic mode when sending packets")
24Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
25Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
26Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
27Signed-off-by: Doug Ledford <dledford@redhat.com>
28Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
29
30---
31 drivers/infiniband/hw/hfi1/ruc.c | 26 ++++++++++++++++----------
32 drivers/infiniband/hw/hfi1/verbs.c | 4 ++--
33 drivers/infiniband/hw/hfi1/verbs.h | 6 ++++--
34 3 files changed, 22 insertions(+), 14 deletions(-)
35
36--- a/drivers/infiniband/hw/hfi1/ruc.c
37+++ b/drivers/infiniband/hw/hfi1/ruc.c
38@@ -1,5 +1,5 @@
39 /*
40- * Copyright(c) 2015, 2016 Intel Corporation.
41+ * Copyright(c) 2015 - 2017 Intel Corporation.
42 *
43 * This file is provided under a dual BSD/GPLv2 license. When using or
44 * redistributing this file, you may do so under either license.
45@@ -784,23 +784,29 @@ void hfi1_make_ruc_header(struct rvt_qp
46 /* when sending, force a reschedule every one of these periods */
47 #define SEND_RESCHED_TIMEOUT (5 * HZ) /* 5s in jiffies */
48
49+void hfi1_do_send_from_rvt(struct rvt_qp *qp)
50+{
51+ hfi1_do_send(qp, false);
52+}
53+
54 void _hfi1_do_send(struct work_struct *work)
55 {
56 struct iowait *wait = container_of(work, struct iowait, iowork);
57 struct rvt_qp *qp = iowait_to_qp(wait);
58
59- hfi1_do_send(qp);
60+ hfi1_do_send(qp, true);
61 }
62
63 /**
64 * hfi1_do_send - perform a send on a QP
65 * @work: contains a pointer to the QP
66+ * @in_thread: true if in a workqueue thread
67 *
68 * Process entries in the send work queue until credit or queue is
69 * exhausted. Only allow one CPU to send a packet per QP.
70 * Otherwise, two threads could send packets out of order.
71 */
72-void hfi1_do_send(struct rvt_qp *qp)
73+void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
74 {
75 struct hfi1_pkt_state ps;
76 struct hfi1_qp_priv *priv = qp->priv;
77@@ -868,8 +874,10 @@ void hfi1_do_send(struct rvt_qp *qp)
78 qp->s_hdrwords = 0;
79 /* allow other tasks to run */
80 if (unlikely(time_after(jiffies, timeout))) {
81- if (workqueue_congested(cpu,
82- ps.ppd->hfi1_wq)) {
83+ if (!in_thread ||
84+ workqueue_congested(
85+ cpu,
86+ ps.ppd->hfi1_wq)) {
87 spin_lock_irqsave(
88 &qp->s_lock,
89 ps.flags);
90@@ -882,11 +890,9 @@ void hfi1_do_send(struct rvt_qp *qp)
91 *ps.ppd->dd->send_schedule);
92 return;
93 }
94- if (!irqs_disabled()) {
95- cond_resched();
96- this_cpu_inc(
97- *ps.ppd->dd->send_schedule);
98- }
99+ cond_resched();
100+ this_cpu_inc(
101+ *ps.ppd->dd->send_schedule);
102 timeout = jiffies + (timeout_int) / 8;
103 }
104 spin_lock_irqsave(&qp->s_lock, ps.flags);
105--- a/drivers/infiniband/hw/hfi1/verbs.c
106+++ b/drivers/infiniband/hw/hfi1/verbs.c
107@@ -1,5 +1,5 @@
108 /*
109- * Copyright(c) 2015, 2016 Intel Corporation.
110+ * Copyright(c) 2015 - 2017 Intel Corporation.
111 *
112 * This file is provided under a dual BSD/GPLv2 license. When using or
113 * redistributing this file, you may do so under either license.
114@@ -1751,7 +1751,7 @@ int hfi1_register_ib_device(struct hfi1_
115 dd->verbs_dev.rdi.driver_f.qp_priv_free = qp_priv_free;
116 dd->verbs_dev.rdi.driver_f.free_all_qps = free_all_qps;
117 dd->verbs_dev.rdi.driver_f.notify_qp_reset = notify_qp_reset;
118- dd->verbs_dev.rdi.driver_f.do_send = hfi1_do_send;
119+ dd->verbs_dev.rdi.driver_f.do_send = hfi1_do_send_from_rvt;
120 dd->verbs_dev.rdi.driver_f.schedule_send = hfi1_schedule_send;
121 dd->verbs_dev.rdi.driver_f.schedule_send_no_lock = _hfi1_schedule_send;
122 dd->verbs_dev.rdi.driver_f.get_pmtu_from_attr = get_pmtu_from_attr;
123--- a/drivers/infiniband/hw/hfi1/verbs.h
124+++ b/drivers/infiniband/hw/hfi1/verbs.h
125@@ -1,5 +1,5 @@
126 /*
127- * Copyright(c) 2015, 2016 Intel Corporation.
128+ * Copyright(c) 2015 - 2017 Intel Corporation.
129 *
130 * This file is provided under a dual BSD/GPLv2 license. When using or
131 * redistributing this file, you may do so under either license.
132@@ -350,7 +350,9 @@ void hfi1_make_ruc_header(struct rvt_qp
133
134 void _hfi1_do_send(struct work_struct *work);
135
136-void hfi1_do_send(struct rvt_qp *qp);
137+void hfi1_do_send_from_rvt(struct rvt_qp *qp);
138+
139+void hfi1_do_send(struct rvt_qp *qp, bool in_thread);
140
141 void hfi1_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe,
142 enum ib_wc_status status);