diff options
author | Upinder Malhi <umalhi@cisco.com> | 2014-01-09 17:48:18 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-01-14 03:44:44 -0500 |
commit | e45e614e4015a489d2f8013eaed45d498d884e86 (patch) | |
tree | 282626234d38d4cb3d32e74012c9fe4dd7b83723 /drivers | |
parent | c7845bcafe4d2ecd5c479fa64d1b425c21dde17c (diff) |
IB/usnic: Add UDP support in usnic_ib_qp_grp.[hc]
UDP support for qp_grps/qps.
Signed-off-by: Upinder Malhi <umalhi@cisco.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c | 88 | ||||
-rw-r--r-- | drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h | 11 |
2 files changed, 99 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c index 2b7e0a1a07b4..d6667a198d0b 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c | |||
@@ -246,6 +246,80 @@ static void release_roce_custom_flow(struct usnic_ib_qp_grp_flow *qp_flow) | |||
246 | } | 246 | } |
247 | 247 | ||
248 | static struct usnic_ib_qp_grp_flow* | 248 | static struct usnic_ib_qp_grp_flow* |
249 | create_udp_flow(struct usnic_ib_qp_grp *qp_grp, | ||
250 | struct usnic_transport_spec *trans_spec) | ||
251 | { | ||
252 | struct socket *sock; | ||
253 | int sock_fd; | ||
254 | int err; | ||
255 | struct filter filter; | ||
256 | struct usnic_filter_action uaction; | ||
257 | struct usnic_ib_qp_grp_flow *qp_flow; | ||
258 | struct usnic_fwd_flow *flow; | ||
259 | enum usnic_transport_type trans_type; | ||
260 | uint32_t addr; | ||
261 | uint16_t port_num; | ||
262 | int proto; | ||
263 | |||
264 | trans_type = trans_spec->trans_type; | ||
265 | sock_fd = trans_spec->udp.sock_fd; | ||
266 | |||
267 | /* Get and check socket */ | ||
268 | sock = usnic_transport_get_socket(sock_fd); | ||
269 | if (IS_ERR_OR_NULL(sock)) | ||
270 | return ERR_CAST(sock); | ||
271 | |||
272 | err = usnic_transport_sock_get_addr(sock, &proto, &addr, &port_num); | ||
273 | if (err) | ||
274 | goto out_put_sock; | ||
275 | |||
276 | if (proto != IPPROTO_UDP) { | ||
277 | usnic_err("Protocol for fd %d is not UDP", sock_fd); | ||
278 | err = -EPERM; | ||
279 | goto out_put_sock; | ||
280 | } | ||
281 | |||
282 | /* Create flow */ | ||
283 | usnic_fwd_init_udp_filter(&filter, addr, port_num); | ||
284 | err = init_filter_action(qp_grp, &uaction); | ||
285 | if (err) | ||
286 | goto out_put_sock; | ||
287 | |||
288 | flow = usnic_fwd_alloc_flow(qp_grp->ufdev, &filter, &uaction); | ||
289 | if (IS_ERR_OR_NULL(flow)) { | ||
290 | usnic_err("Unable to alloc flow failed with err %ld\n", | ||
291 | PTR_ERR(flow)); | ||
292 | err = (flow) ? PTR_ERR(flow) : -EFAULT; | ||
293 | goto out_put_sock; | ||
294 | } | ||
295 | |||
296 | /* Create qp_flow */ | ||
297 | qp_flow = kzalloc(sizeof(*qp_flow), GFP_ATOMIC); | ||
298 | if (IS_ERR_OR_NULL(qp_flow)) { | ||
299 | err = (qp_flow) ? PTR_ERR(qp_flow) : -ENOMEM; | ||
300 | goto out_dealloc_flow; | ||
301 | } | ||
302 | qp_flow->flow = flow; | ||
303 | qp_flow->trans_type = trans_type; | ||
304 | qp_flow->udp.sock = sock; | ||
305 | qp_flow->qp_grp = qp_grp; | ||
306 | return qp_flow; | ||
307 | |||
308 | out_dealloc_flow: | ||
309 | usnic_fwd_dealloc_flow(flow); | ||
310 | out_put_sock: | ||
311 | usnic_transport_put_socket(sock); | ||
312 | return ERR_PTR(err); | ||
313 | } | ||
314 | |||
315 | static void release_udp_flow(struct usnic_ib_qp_grp_flow *qp_flow) | ||
316 | { | ||
317 | usnic_fwd_dealloc_flow(qp_flow->flow); | ||
318 | usnic_transport_put_socket(qp_flow->udp.sock); | ||
319 | kfree(qp_flow); | ||
320 | } | ||
321 | |||
322 | static struct usnic_ib_qp_grp_flow* | ||
249 | create_and_add_flow(struct usnic_ib_qp_grp *qp_grp, | 323 | create_and_add_flow(struct usnic_ib_qp_grp *qp_grp, |
250 | struct usnic_transport_spec *trans_spec) | 324 | struct usnic_transport_spec *trans_spec) |
251 | { | 325 | { |
@@ -257,6 +331,9 @@ create_and_add_flow(struct usnic_ib_qp_grp *qp_grp, | |||
257 | case USNIC_TRANSPORT_ROCE_CUSTOM: | 331 | case USNIC_TRANSPORT_ROCE_CUSTOM: |
258 | qp_flow = create_roce_custom_flow(qp_grp, trans_spec); | 332 | qp_flow = create_roce_custom_flow(qp_grp, trans_spec); |
259 | break; | 333 | break; |
334 | case USNIC_TRANSPORT_IPV4_UDP: | ||
335 | qp_flow = create_udp_flow(qp_grp, trans_spec); | ||
336 | break; | ||
260 | default: | 337 | default: |
261 | usnic_err("Unsupported transport %u\n", | 338 | usnic_err("Unsupported transport %u\n", |
262 | trans_spec->trans_type); | 339 | trans_spec->trans_type); |
@@ -278,6 +355,9 @@ static void release_and_remove_flow(struct usnic_ib_qp_grp_flow *qp_flow) | |||
278 | case USNIC_TRANSPORT_ROCE_CUSTOM: | 355 | case USNIC_TRANSPORT_ROCE_CUSTOM: |
279 | release_roce_custom_flow(qp_flow); | 356 | release_roce_custom_flow(qp_flow); |
280 | break; | 357 | break; |
358 | case USNIC_TRANSPORT_IPV4_UDP: | ||
359 | release_udp_flow(qp_flow); | ||
360 | break; | ||
281 | default: | 361 | default: |
282 | WARN(1, "Unsupported transport %u\n", | 362 | WARN(1, "Unsupported transport %u\n", |
283 | qp_flow->trans_type); | 363 | qp_flow->trans_type); |
@@ -544,11 +624,19 @@ static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow, | |||
544 | uint32_t *id) | 624 | uint32_t *id) |
545 | { | 625 | { |
546 | enum usnic_transport_type trans_type = qp_flow->trans_type; | 626 | enum usnic_transport_type trans_type = qp_flow->trans_type; |
627 | int err; | ||
547 | 628 | ||
548 | switch (trans_type) { | 629 | switch (trans_type) { |
549 | case USNIC_TRANSPORT_ROCE_CUSTOM: | 630 | case USNIC_TRANSPORT_ROCE_CUSTOM: |
550 | *id = qp_flow->usnic_roce.port_num; | 631 | *id = qp_flow->usnic_roce.port_num; |
551 | break; | 632 | break; |
633 | case USNIC_TRANSPORT_IPV4_UDP: | ||
634 | err = usnic_transport_sock_get_addr(qp_flow->udp.sock, | ||
635 | NULL, NULL, | ||
636 | (uint16_t *) id); | ||
637 | if (err) | ||
638 | return err; | ||
639 | break; | ||
552 | default: | 640 | default: |
553 | usnic_err("Unsupported transport %u\n", trans_type); | 641 | usnic_err("Unsupported transport %u\n", trans_type); |
554 | return -EINVAL; | 642 | return -EINVAL; |
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h index 570fea2e2cb9..a8ba1b9224d8 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h +++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h | |||
@@ -56,6 +56,9 @@ struct usnic_ib_qp_grp_flow { | |||
56 | struct { | 56 | struct { |
57 | uint16_t port_num; | 57 | uint16_t port_num; |
58 | } usnic_roce; | 58 | } usnic_roce; |
59 | struct { | ||
60 | struct socket *sock; | ||
61 | } udp; | ||
59 | }; | 62 | }; |
60 | struct usnic_ib_qp_grp *qp_grp; | 63 | struct usnic_ib_qp_grp *qp_grp; |
61 | struct list_head link; | 64 | struct list_head link; |
@@ -76,6 +79,14 @@ usnic_vnic_res_spec min_transport_spec[USNIC_TRANSPORT_MAX] = { | |||
76 | {.type = USNIC_VNIC_RES_TYPE_EOL, .cnt = 0,}, | 79 | {.type = USNIC_VNIC_RES_TYPE_EOL, .cnt = 0,}, |
77 | }, | 80 | }, |
78 | }, | 81 | }, |
82 | { /*USNIC_TRANSPORT_IPV4_UDP*/ | ||
83 | .resources = { | ||
84 | {.type = USNIC_VNIC_RES_TYPE_WQ, .cnt = 1,}, | ||
85 | {.type = USNIC_VNIC_RES_TYPE_RQ, .cnt = 1,}, | ||
86 | {.type = USNIC_VNIC_RES_TYPE_CQ, .cnt = 1,}, | ||
87 | {.type = USNIC_VNIC_RES_TYPE_EOL, .cnt = 0,}, | ||
88 | }, | ||
89 | }, | ||
79 | }; | 90 | }; |
80 | 91 | ||
81 | const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state); | 92 | const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state); |