diff options
author | Upinder Malhi <umalhi@cisco.com> | 2014-01-09 17:48:09 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-01-14 03:44:42 -0500 |
commit | 256d6a6ac52ee02e897cec88ecc96c3ae7f9cb88 (patch) | |
tree | dad8f786129e3aa6636e5512f7012388ce17d37c /drivers/infiniband/hw | |
parent | 8af94ac66a4d53a96278ecbb9ef2e8592f0d9ba3 (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.c | 347 | ||||
-rw-r--r-- | drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h | 24 |
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 | |||
30 | const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state) | 33 | const 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) | |||
58 | int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz) | 61 | int 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 | ||
77 | static int add_fwd_filter(struct usnic_ib_qp_grp *qp_grp, | 80 | static struct usnic_vnic_res_chunk * |
78 | struct usnic_fwd_filter *fwd_filter) | 81 | get_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 | |||
117 | static 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 | ||
140 | static int enable_qp_grp(struct usnic_ib_qp_grp *qp_grp) | 91 | static 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) | |||
175 | out_err: | 124 | out_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 | ||
167 | static 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 | |||
187 | static struct usnic_ib_qp_grp_flow* | ||
188 | create_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 | |||
233 | out_dealloc_flow: | ||
234 | usnic_fwd_dealloc_flow(flow); | ||
235 | out_unreserve_port: | ||
236 | usnic_transport_unrsrv_port(trans_type, port_num); | ||
237 | return ERR_PTR(err); | ||
238 | } | ||
239 | |||
240 | static 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 | |||
248 | static struct usnic_ib_qp_grp_flow* | ||
249 | create_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 | |||
273 | static 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 | |||
288 | static 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 | |||
219 | int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp, | 295 | int 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 | ||
543 | static 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 | |||
438 | struct usnic_ib_qp_grp * | 560 | struct usnic_ib_qp_grp * |
439 | usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, | 561 | usnic_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 | ||
504 | out_free_port: | 625 | out_release_flow: |
626 | release_and_remove_flow(qp_flow); | ||
627 | out_qp_grp_vf_unbind: | ||
628 | qp_grp_and_vf_unbind(qp_grp); | ||
629 | out_free_res: | ||
630 | free_qp_grp_res(qp_grp->res_chunk_list); | ||
631 | out_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 | ||
511 | void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp) | 637 | void 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 | ||
529 | struct usnic_vnic_res_chunk* | 650 | struct 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 | ||
52 | struct 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 | |||
58 | static const struct | 64 | static const struct |
59 | usnic_vnic_res_spec min_transport_spec[USNIC_TRANSPORT_MAX] = { | 65 | usnic_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 * | |||
79 | usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf, | 85 | usnic_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); |
83 | void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp); | 89 | void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp); |
84 | int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp, | 90 | int 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); |
87 | struct usnic_vnic_res_chunk | 93 | struct 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); |