aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorUpinder Malhi <umalhi@cisco.com>2014-01-09 17:48:09 -0500
committerRoland Dreier <roland@purestorage.com>2014-01-14 03:44:42 -0500
commit256d6a6ac52ee02e897cec88ecc96c3ae7f9cb88 (patch)
treedad8f786129e3aa6636e5512f7012388ce17d37c /drivers/infiniband/hw
parent8af94ac66a4d53a96278ecbb9ef2e8592f0d9ba3 (diff)
IB/usnic: Port over usnic_ib_qp_grp.[hc] to new usnic_fwd.h
This patch ports usnic_ib_qp_grp.[hc] to the new interface of usnic_fwd.h. Signed-off-by: Upinder Malhi <umalhi@cisco.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c347
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h24
2 files changed, 249 insertions, 122 deletions
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
index 5a873f5c2794..2b7e0a1a07b4 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
@@ -15,6 +15,7 @@
15 * SOFTWARE. 15 * SOFTWARE.
16 * 16 *
17 */ 17 */
18#include <linux/bug.h>
18#include <linux/errno.h> 19#include <linux/errno.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/spinlock.h> 21#include <linux/spinlock.h>
@@ -27,6 +28,8 @@
27#include "usnic_ib_sysfs.h" 28#include "usnic_ib_sysfs.h"
28#include "usnic_transport.h" 29#include "usnic_transport.h"
29 30
31#define DFLT_RQ_IDX 0
32
30const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state) 33const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state)
31{ 34{
32 switch (state) { 35 switch (state) {
@@ -58,83 +61,31 @@ int usnic_ib_qp_grp_dump_hdr(char *buf, int buf_sz)
58int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz) 61int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz)
59{ 62{
60 struct usnic_ib_qp_grp *qp_grp = obj; 63 struct usnic_ib_qp_grp *qp_grp = obj;
61 struct usnic_fwd_filter_hndl *default_filter_hndl; 64 struct usnic_ib_qp_grp_flow *default_flow;
62 if (obj) { 65 if (obj) {
63 default_filter_hndl = list_first_entry(&qp_grp->filter_hndls, 66 default_flow = list_first_entry(&qp_grp->flows_lst,
64 struct usnic_fwd_filter_hndl, link); 67 struct usnic_ib_qp_grp_flow, link);
65 return scnprintf(buf, buf_sz, "|%d\t|%s\t|%d\t|%hu\t|%d", 68 return scnprintf(buf, buf_sz, "|%d\t|%s\t|%d\t|%hu\t|%d",
66 qp_grp->ibqp.qp_num, 69 qp_grp->ibqp.qp_num,
67 usnic_ib_qp_grp_state_to_string( 70 usnic_ib_qp_grp_state_to_string(
68 qp_grp->state), 71 qp_grp->state),
69 qp_grp->owner_pid, 72 qp_grp->owner_pid,
70 usnic_vnic_get_index(qp_grp->vf->vnic), 73 usnic_vnic_get_index(qp_grp->vf->vnic),
71 default_filter_hndl->id); 74 default_flow->flow->flow_id);
72 } else { 75 } else {
73 return scnprintf(buf, buf_sz, "|N/A\t|N/A\t|N/A\t|N/A\t|N/A"); 76 return scnprintf(buf, buf_sz, "|N/A\t|N/A\t|N/A\t|N/A\t|N/A");
74 } 77 }
75} 78}
76 79
77static int add_fwd_filter(struct usnic_ib_qp_grp *qp_grp, 80static struct usnic_vnic_res_chunk *
78 struct usnic_fwd_filter *fwd_filter) 81get_qp_res_chunk(struct usnic_ib_qp_grp *qp_grp)
79{
80 struct usnic_fwd_filter_hndl *filter_hndl;
81 int status;
82 struct usnic_vnic_res_chunk *chunk;
83 int rq_idx;
84
85 lockdep_assert_held(&qp_grp->lock);
86
87 chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
88 if (IS_ERR_OR_NULL(chunk) || chunk->cnt < 1) {
89 usnic_err("Failed to get RQ info for qp_grp %u\n",
90 qp_grp->grp_id);
91 return -EFAULT;
92 }
93
94 rq_idx = chunk->res[0]->vnic_idx;
95
96 switch (qp_grp->transport) {
97 case USNIC_TRANSPORT_ROCE_CUSTOM:
98 status = usnic_fwd_add_usnic_filter(qp_grp->ufdev,
99 usnic_vnic_get_index(qp_grp->vf->vnic),
100 rq_idx,
101 fwd_filter,
102 &filter_hndl);
103 break;
104 default:
105 usnic_err("Unable to install filter for qp_grp %u for transport %d",
106 qp_grp->grp_id, qp_grp->transport);
107 status = -EINVAL;
108 }
109
110 if (status)
111 return status;
112
113 list_add_tail(&filter_hndl->link, &qp_grp->filter_hndls);
114 return 0;
115}
116
117static int del_all_filters(struct usnic_ib_qp_grp *qp_grp)
118{ 82{
119 int err, status;
120 struct usnic_fwd_filter_hndl *filter_hndl, *tmp;
121
122 lockdep_assert_held(&qp_grp->lock); 83 lockdep_assert_held(&qp_grp->lock);
123 84 /*
124 status = 0; 85 * The QP res chunk, used to derive qp indices,
125 86 * are just indices of the RQs
126 list_for_each_entry_safe(filter_hndl, tmp, 87 */
127 &qp_grp->filter_hndls, link) { 88 return usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
128 list_del(&filter_hndl->link);
129 err = usnic_fwd_del_filter(filter_hndl);
130 if (err) {
131 usnic_err("Failed to delete filter %u of qp_grp %d\n",
132 filter_hndl->id, qp_grp->grp_id);
133 }
134 status |= err;
135 }
136
137 return status;
138} 89}
139 90
140static int enable_qp_grp(struct usnic_ib_qp_grp *qp_grp) 91static int enable_qp_grp(struct usnic_ib_qp_grp *qp_grp)
@@ -149,22 +100,20 @@ static int enable_qp_grp(struct usnic_ib_qp_grp *qp_grp)
149 100
150 vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic); 101 vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
151 102
152 res_chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ); 103 res_chunk = get_qp_res_chunk(qp_grp);
153 if (IS_ERR_OR_NULL(res_chunk)) { 104 if (IS_ERR_OR_NULL(res_chunk)) {
154 usnic_err("Unable to get %s with err %ld\n", 105 usnic_err("Unable to get qp res with err %ld\n",
155 usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ), 106 PTR_ERR(res_chunk));
156 PTR_ERR(res_chunk));
157 return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM; 107 return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
158 } 108 }
159 109
160 for (i = 0; i < res_chunk->cnt; i++) { 110 for (i = 0; i < res_chunk->cnt; i++) {
161 res = res_chunk->res[i]; 111 res = res_chunk->res[i];
162 status = usnic_fwd_enable_rq(qp_grp->ufdev, vnic_idx, 112 status = usnic_fwd_enable_qp(qp_grp->ufdev, vnic_idx,
163 res->vnic_idx); 113 res->vnic_idx);
164 if (status) { 114 if (status) {
165 usnic_err("Failed to enable rq %d of %s:%d\n with err %d\n", 115 usnic_err("Failed to enable qp %d of %s:%d\n with err %d\n",
166 res->vnic_idx, 116 res->vnic_idx, qp_grp->ufdev->name,
167 netdev_name(qp_grp->ufdev->netdev),
168 vnic_idx, status); 117 vnic_idx, status);
169 goto out_err; 118 goto out_err;
170 } 119 }
@@ -175,7 +124,7 @@ static int enable_qp_grp(struct usnic_ib_qp_grp *qp_grp)
175out_err: 124out_err:
176 for (i--; i >= 0; i--) { 125 for (i--; i >= 0; i--) {
177 res = res_chunk->res[i]; 126 res = res_chunk->res[i];
178 usnic_fwd_disable_rq(qp_grp->ufdev, vnic_idx, 127 usnic_fwd_disable_qp(qp_grp->ufdev, vnic_idx,
179 res->vnic_idx); 128 res->vnic_idx);
180 } 129 }
181 130
@@ -192,22 +141,21 @@ static int disable_qp_grp(struct usnic_ib_qp_grp *qp_grp)
192 lockdep_assert_held(&qp_grp->lock); 141 lockdep_assert_held(&qp_grp->lock);
193 vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic); 142 vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
194 143
195 res_chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ); 144 res_chunk = get_qp_res_chunk(qp_grp);
196 if (IS_ERR_OR_NULL(res_chunk)) { 145 if (IS_ERR_OR_NULL(res_chunk)) {
197 usnic_err("Unable to get %s with err %ld\n", 146 usnic_err("Unable to get qp res with err %ld\n",
198 usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ),
199 PTR_ERR(res_chunk)); 147 PTR_ERR(res_chunk));
200 return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM; 148 return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
201 } 149 }
202 150
203 for (i = 0; i < res_chunk->cnt; i++) { 151 for (i = 0; i < res_chunk->cnt; i++) {
204 res = res_chunk->res[i]; 152 res = res_chunk->res[i];
205 status = usnic_fwd_disable_rq(qp_grp->ufdev, vnic_idx, 153 status = usnic_fwd_disable_qp(qp_grp->ufdev, vnic_idx,
206 res->vnic_idx); 154 res->vnic_idx);
207 if (status) { 155 if (status) {
208 usnic_err("Failed to disable rq %d of %s:%d\n with err %d\n", 156 usnic_err("Failed to disable rq %d of %s:%d\n with err %d\n",
209 res->vnic_idx, 157 res->vnic_idx,
210 netdev_name(qp_grp->ufdev->netdev), 158 qp_grp->ufdev->name,
211 vnic_idx, status); 159 vnic_idx, status);
212 } 160 }
213 } 161 }
@@ -216,17 +164,148 @@ static int disable_qp_grp(struct usnic_ib_qp_grp *qp_grp)
216 164
217} 165}
218 166
167static int init_filter_action(struct usnic_ib_qp_grp *qp_grp,
168 struct usnic_filter_action *uaction)
169{
170 struct usnic_vnic_res_chunk *res_chunk;
171
172 res_chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
173 if (IS_ERR_OR_NULL(res_chunk)) {
174 usnic_err("Unable to get %s with err %ld\n",
175 usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ),
176 PTR_ERR(res_chunk));
177 return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
178 }
179
180 uaction->vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
181 uaction->action.type = FILTER_ACTION_RQ_STEERING;
182 uaction->action.u.rq_idx = res_chunk->res[DFLT_RQ_IDX]->vnic_idx;
183
184 return 0;
185}
186
187static struct usnic_ib_qp_grp_flow*
188create_roce_custom_flow(struct usnic_ib_qp_grp *qp_grp,
189 struct usnic_transport_spec *trans_spec)
190{
191 uint16_t port_num;
192 int err;
193 struct filter filter;
194 struct usnic_filter_action uaction;
195 struct usnic_ib_qp_grp_flow *qp_flow;
196 struct usnic_fwd_flow *flow;
197 enum usnic_transport_type trans_type;
198
199 trans_type = trans_spec->trans_type;
200 port_num = trans_spec->usnic_roce.port_num;
201
202 /* Reserve Port */
203 port_num = usnic_transport_rsrv_port(trans_type, port_num);
204 if (port_num == 0)
205 return ERR_PTR(-EINVAL);
206
207 /* Create Flow */
208 usnic_fwd_init_usnic_filter(&filter, port_num);
209 err = init_filter_action(qp_grp, &uaction);
210 if (err)
211 goto out_unreserve_port;
212
213 flow = usnic_fwd_alloc_flow(qp_grp->ufdev, &filter, &uaction);
214 if (IS_ERR_OR_NULL(flow)) {
215 usnic_err("Unable to alloc flow failed with err %ld\n",
216 PTR_ERR(flow));
217 err = (flow) ? PTR_ERR(flow) : -EFAULT;
218 goto out_unreserve_port;
219 }
220
221 /* Create Flow Handle */
222 qp_flow = kzalloc(sizeof(*qp_flow), GFP_ATOMIC);
223 if (IS_ERR_OR_NULL(qp_flow)) {
224 err = (qp_flow) ? PTR_ERR(qp_flow) : -ENOMEM;
225 goto out_dealloc_flow;
226 }
227 qp_flow->flow = flow;
228 qp_flow->trans_type = trans_type;
229 qp_flow->usnic_roce.port_num = port_num;
230 qp_flow->qp_grp = qp_grp;
231 return qp_flow;
232
233out_dealloc_flow:
234 usnic_fwd_dealloc_flow(flow);
235out_unreserve_port:
236 usnic_transport_unrsrv_port(trans_type, port_num);
237 return ERR_PTR(err);
238}
239
240static void release_roce_custom_flow(struct usnic_ib_qp_grp_flow *qp_flow)
241{
242 usnic_fwd_dealloc_flow(qp_flow->flow);
243 usnic_transport_unrsrv_port(qp_flow->trans_type,
244 qp_flow->usnic_roce.port_num);
245 kfree(qp_flow);
246}
247
248static struct usnic_ib_qp_grp_flow*
249create_and_add_flow(struct usnic_ib_qp_grp *qp_grp,
250 struct usnic_transport_spec *trans_spec)
251{
252 struct usnic_ib_qp_grp_flow *qp_flow;
253 enum usnic_transport_type trans_type;
254
255 trans_type = trans_spec->trans_type;
256 switch (trans_type) {
257 case USNIC_TRANSPORT_ROCE_CUSTOM:
258 qp_flow = create_roce_custom_flow(qp_grp, trans_spec);
259 break;
260 default:
261 usnic_err("Unsupported transport %u\n",
262 trans_spec->trans_type);
263 return ERR_PTR(-EINVAL);
264 }
265
266 if (!IS_ERR_OR_NULL(qp_flow))
267 list_add_tail(&qp_flow->link, &qp_grp->flows_lst);
268
269
270 return qp_flow;
271}
272
273static void release_and_remove_flow(struct usnic_ib_qp_grp_flow *qp_flow)
274{
275 list_del(&qp_flow->link);
276
277 switch (qp_flow->trans_type) {
278 case USNIC_TRANSPORT_ROCE_CUSTOM:
279 release_roce_custom_flow(qp_flow);
280 break;
281 default:
282 WARN(1, "Unsupported transport %u\n",
283 qp_flow->trans_type);
284 break;
285 }
286}
287
288static void release_and_remove_all_flows(struct usnic_ib_qp_grp *qp_grp)
289{
290 struct usnic_ib_qp_grp_flow *qp_flow, *tmp;
291 list_for_each_entry_safe(qp_flow, tmp, &qp_grp->flows_lst, link)
292 release_and_remove_flow(qp_flow);
293}
294
219int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp, 295int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
220 enum ib_qp_state new_state, 296 enum ib_qp_state new_state,
221 struct usnic_fwd_filter *fwd_filter) 297 void *data)
222{ 298{
223 int status = 0; 299 int status = 0;
224 int vnic_idx; 300 int vnic_idx;
225 struct ib_event ib_event; 301 struct ib_event ib_event;
226 enum ib_qp_state old_state; 302 enum ib_qp_state old_state;
303 struct usnic_transport_spec *trans_spec;
304 struct usnic_ib_qp_grp_flow *qp_flow;
227 305
228 old_state = qp_grp->state; 306 old_state = qp_grp->state;
229 vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic); 307 vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
308 trans_spec = (struct usnic_transport_spec *) data;
230 309
231 spin_lock(&qp_grp->lock); 310 spin_lock(&qp_grp->lock);
232 switch (new_state) { 311 switch (new_state) {
@@ -236,13 +315,14 @@ int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
236 /* NO-OP */ 315 /* NO-OP */
237 break; 316 break;
238 case IB_QPS_INIT: 317 case IB_QPS_INIT:
239 status = del_all_filters(qp_grp); 318 release_and_remove_all_flows(qp_grp);
319 status = 0;
240 break; 320 break;
241 case IB_QPS_RTR: 321 case IB_QPS_RTR:
242 case IB_QPS_RTS: 322 case IB_QPS_RTS:
243 case IB_QPS_ERR: 323 case IB_QPS_ERR:
244 status = disable_qp_grp(qp_grp); 324 status = disable_qp_grp(qp_grp);
245 status &= del_all_filters(qp_grp); 325 release_and_remove_all_flows(qp_grp);
246 break; 326 break;
247 default: 327 default:
248 status = -EINVAL; 328 status = -EINVAL;
@@ -251,10 +331,35 @@ int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
251 case IB_QPS_INIT: 331 case IB_QPS_INIT:
252 switch (old_state) { 332 switch (old_state) {
253 case IB_QPS_RESET: 333 case IB_QPS_RESET:
254 status = add_fwd_filter(qp_grp, fwd_filter); 334 if (trans_spec) {
335 qp_flow = create_and_add_flow(qp_grp,
336 trans_spec);
337 if (IS_ERR_OR_NULL(qp_flow)) {
338 status = (qp_flow) ? PTR_ERR(qp_flow) : -EFAULT;
339 break;
340 }
341 } else {
342 /*
343 * Optional to specify filters.
344 */
345 status = 0;
346 }
255 break; 347 break;
256 case IB_QPS_INIT: 348 case IB_QPS_INIT:
257 status = add_fwd_filter(qp_grp, fwd_filter); 349 if (trans_spec) {
350 qp_flow = create_and_add_flow(qp_grp,
351 trans_spec);
352 if (IS_ERR_OR_NULL(qp_flow)) {
353 status = (qp_flow) ? PTR_ERR(qp_flow) : -EFAULT;
354 break;
355 }
356 } else {
357 /*
358 * Doesn't make sense to go into INIT state
359 * from INIT state w/o adding filters.
360 */
361 status = -EINVAL;
362 }
258 break; 363 break;
259 case IB_QPS_RTR: 364 case IB_QPS_RTR:
260 status = disable_qp_grp(qp_grp); 365 status = disable_qp_grp(qp_grp);
@@ -295,14 +400,14 @@ int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
295 qp_grp->ibqp.qp_context); 400 qp_grp->ibqp.qp_context);
296 break; 401 break;
297 case IB_QPS_INIT: 402 case IB_QPS_INIT:
298 status = del_all_filters(qp_grp); 403 release_and_remove_all_flows(qp_grp);
299 qp_grp->ibqp.event_handler(&ib_event, 404 qp_grp->ibqp.event_handler(&ib_event,
300 qp_grp->ibqp.qp_context); 405 qp_grp->ibqp.qp_context);
301 break; 406 break;
302 case IB_QPS_RTR: 407 case IB_QPS_RTR:
303 case IB_QPS_RTS: 408 case IB_QPS_RTS:
304 status = disable_qp_grp(qp_grp); 409 status = disable_qp_grp(qp_grp);
305 status &= del_all_filters(qp_grp); 410 release_and_remove_all_flows(qp_grp);
306 qp_grp->ibqp.event_handler(&ib_event, 411 qp_grp->ibqp.event_handler(&ib_event,
307 qp_grp->ibqp.qp_context); 412 qp_grp->ibqp.qp_context);
308 break; 413 break;
@@ -435,16 +540,33 @@ static void log_spec(struct usnic_vnic_res_spec *res_spec)
435 usnic_dbg("%s\n", buf); 540 usnic_dbg("%s\n", buf);
436} 541}
437 542
543static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow,
544 uint32_t *id)
545{
546 enum usnic_transport_type trans_type = qp_flow->trans_type;
547
548 switch (trans_type) {
549 case USNIC_TRANSPORT_ROCE_CUSTOM:
550 *id = qp_flow->usnic_roce.port_num;
551 break;
552 default:
553 usnic_err("Unsupported transport %u\n", trans_type);
554 return -EINVAL;
555 }
556
557 return 0;
558}
559
438struct usnic_ib_qp_grp * 560struct usnic_ib_qp_grp *
439usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, 561usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
440 struct usnic_ib_vf *vf,
441 struct usnic_ib_pd *pd, 562 struct usnic_ib_pd *pd,
442 struct usnic_vnic_res_spec *res_spec, 563 struct usnic_vnic_res_spec *res_spec,
443 enum usnic_transport_type transport) 564 struct usnic_transport_spec *transport_spec)
444{ 565{
445 struct usnic_ib_qp_grp *qp_grp; 566 struct usnic_ib_qp_grp *qp_grp;
446 u16 port_num;
447 int err; 567 int err;
568 enum usnic_transport_type transport = transport_spec->trans_type;
569 struct usnic_ib_qp_grp_flow *qp_flow;
448 570
449 lockdep_assert_held(&vf->lock); 571 lockdep_assert_held(&vf->lock);
450 572
@@ -457,13 +579,6 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev,
457 return ERR_PTR(err); 579 return ERR_PTR(err);
458 } 580 }
459 581
460 port_num = usnic_transport_rsrv_port(transport, 0);
461 if (!port_num) {
462 usnic_err("Unable to allocate port for %s\n",
463 netdev_name(ufdev->netdev));
464 return ERR_PTR(-EINVAL);
465 }
466
467 qp_grp = kzalloc(sizeof(*qp_grp), GFP_ATOMIC); 582 qp_grp = kzalloc(sizeof(*qp_grp), GFP_ATOMIC);
468 if (!qp_grp) { 583 if (!qp_grp) {
469 usnic_err("Unable to alloc qp_grp - Out of memory\n"); 584 usnic_err("Unable to alloc qp_grp - Out of memory\n");
@@ -477,53 +592,59 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev,
477 PTR_ERR(qp_grp->res_chunk_list) : -ENOMEM; 592 PTR_ERR(qp_grp->res_chunk_list) : -ENOMEM;
478 usnic_err("Unable to alloc res for %d with err %d\n", 593 usnic_err("Unable to alloc res for %d with err %d\n",
479 qp_grp->grp_id, err); 594 qp_grp->grp_id, err);
480 goto out_free_port; 595 goto out_free_qp_grp;
481 } 596 }
482 597
483 INIT_LIST_HEAD(&qp_grp->filter_hndls); 598 err = qp_grp_and_vf_bind(vf, pd, qp_grp);
599 if (err)
600 goto out_free_res;
601
602 INIT_LIST_HEAD(&qp_grp->flows_lst);
484 spin_lock_init(&qp_grp->lock); 603 spin_lock_init(&qp_grp->lock);
485 qp_grp->ufdev = ufdev; 604 qp_grp->ufdev = ufdev;
486 qp_grp->transport = transport;
487 qp_grp->filters[DFLT_FILTER_IDX].transport = transport;
488 qp_grp->filters[DFLT_FILTER_IDX].port_num = port_num;
489 qp_grp->state = IB_QPS_RESET; 605 qp_grp->state = IB_QPS_RESET;
490 qp_grp->owner_pid = current->pid; 606 qp_grp->owner_pid = current->pid;
491 607
492 /* qp_num is same as default filter port_num */ 608 qp_flow = create_and_add_flow(qp_grp, transport_spec);
493 qp_grp->ibqp.qp_num = qp_grp->filters[DFLT_FILTER_IDX].port_num; 609 if (IS_ERR_OR_NULL(qp_flow)) {
494 qp_grp->grp_id = qp_grp->ibqp.qp_num; 610 usnic_err("Unable to create and add flow with err %ld\n",
611 PTR_ERR(qp_flow));
612 err = (qp_flow) ? PTR_ERR(qp_flow) : -EFAULT;
613 goto out_qp_grp_vf_unbind;
614 }
495 615
496 err = qp_grp_and_vf_bind(vf, pd, qp_grp); 616 err = qp_grp_id_from_flow(qp_flow, &qp_grp->grp_id);
497 if (err) 617 if (err)
498 goto out_free_port; 618 goto out_release_flow;
619 qp_grp->ibqp.qp_num = qp_grp->grp_id;
499 620
500 usnic_ib_sysfs_qpn_add(qp_grp); 621 usnic_ib_sysfs_qpn_add(qp_grp);
501 622
502 return qp_grp; 623 return qp_grp;
503 624
504out_free_port: 625out_release_flow:
626 release_and_remove_flow(qp_flow);
627out_qp_grp_vf_unbind:
628 qp_grp_and_vf_unbind(qp_grp);
629out_free_res:
630 free_qp_grp_res(qp_grp->res_chunk_list);
631out_free_qp_grp:
505 kfree(qp_grp); 632 kfree(qp_grp);
506 usnic_transport_unrsrv_port(transport, port_num);
507 633
508 return ERR_PTR(err); 634 return ERR_PTR(err);
509} 635}
510 636
511void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp) 637void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
512{ 638{
513 u16 default_port_num;
514 enum usnic_transport_type transport;
515 639
516 WARN_ON(qp_grp->state != IB_QPS_RESET); 640 WARN_ON(qp_grp->state != IB_QPS_RESET);
517 lockdep_assert_held(&qp_grp->vf->lock); 641 lockdep_assert_held(&qp_grp->vf->lock);
518 642
519 transport = qp_grp->filters[DFLT_FILTER_IDX].transport;
520 default_port_num = qp_grp->filters[DFLT_FILTER_IDX].port_num;
521
522 usnic_ib_sysfs_qpn_remove(qp_grp); 643 usnic_ib_sysfs_qpn_remove(qp_grp);
523 qp_grp_and_vf_unbind(qp_grp); 644 qp_grp_and_vf_unbind(qp_grp);
645 release_and_remove_all_flows(qp_grp);
524 free_qp_grp_res(qp_grp->res_chunk_list); 646 free_qp_grp_res(qp_grp->res_chunk_list);
525 kfree(qp_grp); 647 kfree(qp_grp);
526 usnic_transport_unrsrv_port(transport, default_port_num);
527} 648}
528 649
529struct usnic_vnic_res_chunk* 650struct usnic_vnic_res_chunk*
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
index 6416a956dc4a..570fea2e2cb9 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
@@ -26,9 +26,6 @@
26#include "usnic_fwd.h" 26#include "usnic_fwd.h"
27#include "usnic_vnic.h" 27#include "usnic_vnic.h"
28 28
29#define MAX_QP_GRP_FILTERS 10
30#define DFLT_FILTER_IDX 0
31
32/* 29/*
33 * The qp group struct represents all the hw resources needed to present a ib_qp 30 * The qp group struct represents all the hw resources needed to present a ib_qp
34 */ 31 */
@@ -38,11 +35,8 @@ struct usnic_ib_qp_grp {
38 int grp_id; 35 int grp_id;
39 36
40 struct usnic_fwd_dev *ufdev; 37 struct usnic_fwd_dev *ufdev;
41 short unsigned filter_cnt;
42 struct usnic_fwd_filter filters[MAX_QP_GRP_FILTERS];
43 struct list_head filter_hndls;
44 enum usnic_transport_type transport;
45 struct usnic_ib_ucontext *ctx; 38 struct usnic_ib_ucontext *ctx;
39 struct list_head flows_lst;
46 40
47 struct usnic_vnic_res_chunk **res_chunk_list; 41 struct usnic_vnic_res_chunk **res_chunk_list;
48 42
@@ -55,6 +49,18 @@ struct usnic_ib_qp_grp {
55 struct kobject kobj; 49 struct kobject kobj;
56}; 50};
57 51
52struct usnic_ib_qp_grp_flow {
53 struct usnic_fwd_flow *flow;
54 enum usnic_transport_type trans_type;
55 union {
56 struct {
57 uint16_t port_num;
58 } usnic_roce;
59 };
60 struct usnic_ib_qp_grp *qp_grp;
61 struct list_head link;
62};
63
58static const struct 64static const struct
59usnic_vnic_res_spec min_transport_spec[USNIC_TRANSPORT_MAX] = { 65usnic_vnic_res_spec min_transport_spec[USNIC_TRANSPORT_MAX] = {
60 { /*USNIC_TRANSPORT_UNKNOWN*/ 66 { /*USNIC_TRANSPORT_UNKNOWN*/
@@ -79,11 +85,11 @@ struct usnic_ib_qp_grp *
79usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf, 85usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
80 struct usnic_ib_pd *pd, 86 struct usnic_ib_pd *pd,
81 struct usnic_vnic_res_spec *res_spec, 87 struct usnic_vnic_res_spec *res_spec,
82 enum usnic_transport_type transport); 88 struct usnic_transport_spec *trans_spec);
83void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp); 89void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp);
84int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp, 90int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
85 enum ib_qp_state new_state, 91 enum ib_qp_state new_state,
86 struct usnic_fwd_filter *fwd_filter); 92 void *data);
87struct usnic_vnic_res_chunk 93struct usnic_vnic_res_chunk
88*usnic_ib_qp_grp_get_chunk(struct usnic_ib_qp_grp *qp_grp, 94*usnic_ib_qp_grp_get_chunk(struct usnic_ib_qp_grp *qp_grp,
89 enum usnic_vnic_res_type type); 95 enum usnic_vnic_res_type type);