aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
diff options
context:
space:
mode:
authorUpinder Malhi <umalhi@cisco.com>2014-01-09 17:48:18 -0500
committerRoland Dreier <roland@purestorage.com>2014-01-14 03:44:44 -0500
commite45e614e4015a489d2f8013eaed45d498d884e86 (patch)
tree282626234d38d4cb3d32e74012c9fe4dd7b83723 /drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
parentc7845bcafe4d2ecd5c479fa64d1b425c21dde17c (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/infiniband/hw/usnic/usnic_ib_qp_grp.c')
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c88
1 files changed, 88 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
248static struct usnic_ib_qp_grp_flow* 248static struct usnic_ib_qp_grp_flow*
249create_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
308out_dealloc_flow:
309 usnic_fwd_dealloc_flow(flow);
310out_put_sock:
311 usnic_transport_put_socket(sock);
312 return ERR_PTR(err);
313}
314
315static 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
322static struct usnic_ib_qp_grp_flow*
249create_and_add_flow(struct usnic_ib_qp_grp *qp_grp, 323create_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;