diff options
author | Vipul Pandya <vipul@chelsio.com> | 2013-07-04 06:40:47 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-08-13 14:55:06 -0400 |
commit | 830662f6f032f2355c7afdfe9afc5ef58ac274e5 (patch) | |
tree | a20ca86528221485393899b63a3fc597413d14c7 /drivers/infiniband/hw/cxgb4 | |
parent | 01bcca68c38300745ea8e2d4e9513111406fd923 (diff) |
RDMA/cxgb4: Add support for active and passive open connection with IPv6 address
Add new cpl messages, cpl_act_open_req6 and cpl_t5_act_open_req6, for
initiating active open connections.
Use LLD api cxgb4_create_server and cxgb4_create_server6 for
initiating passive open connections. Similarly use cxgb4_remove_server
to remove the passive open connections in place of listen_stop.
Add support for iWARP over VLAN device and enable IPv6 support on VLAN device.
Make use of import_ep in c4iw_reconnect.
Signed-off-by: Vipul Pandya <vipul@chelsio.com>
[ Fix build when IPv6 is disabled and make sure iw_cxgb4 is not built-in
when ipv6 is a module. - Roland ]
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb4')
-rw-r--r-- | drivers/infiniband/hw/cxgb4/Kconfig | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cm.c | 814 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/device.c | 116 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 4 |
4 files changed, 636 insertions, 300 deletions
diff --git a/drivers/infiniband/hw/cxgb4/Kconfig b/drivers/infiniband/hw/cxgb4/Kconfig index 6b7e6c543534..d4e8983fba53 100644 --- a/drivers/infiniband/hw/cxgb4/Kconfig +++ b/drivers/infiniband/hw/cxgb4/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config INFINIBAND_CXGB4 | 1 | config INFINIBAND_CXGB4 |
2 | tristate "Chelsio T4 RDMA Driver" | 2 | tristate "Chelsio T4 RDMA Driver" |
3 | depends on CHELSIO_T4 && INET | 3 | depends on CHELSIO_T4 && INET && (IPV6 || IPV6=n) |
4 | select GENERIC_ALLOCATOR | 4 | select GENERIC_ALLOCATOR |
5 | ---help--- | 5 | ---help--- |
6 | This is an iWARP/RDMA driver for the Chelsio T4 1GbE and | 6 | This is an iWARP/RDMA driver for the Chelsio T4 1GbE and |
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 76d8812f9e9a..3f17c01329ec 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include <net/netevent.h> | 44 | #include <net/netevent.h> |
45 | #include <net/route.h> | 45 | #include <net/route.h> |
46 | #include <net/tcp.h> | 46 | #include <net/tcp.h> |
47 | #include <net/ip6_route.h> | ||
48 | #include <net/addrconf.h> | ||
47 | 49 | ||
48 | #include "iw_cxgb4.h" | 50 | #include "iw_cxgb4.h" |
49 | 51 | ||
@@ -333,19 +335,76 @@ static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) | |||
333 | return skb; | 335 | return skb; |
334 | } | 336 | } |
335 | 337 | ||
336 | static struct rtable *find_route(struct c4iw_dev *dev, __be32 local_ip, | 338 | static struct net_device *get_real_dev(struct net_device *egress_dev) |
339 | { | ||
340 | struct net_device *phys_dev = egress_dev; | ||
341 | if (egress_dev->priv_flags & IFF_802_1Q_VLAN) | ||
342 | phys_dev = vlan_dev_real_dev(egress_dev); | ||
343 | return phys_dev; | ||
344 | } | ||
345 | |||
346 | static int our_interface(struct c4iw_dev *dev, struct net_device *egress_dev) | ||
347 | { | ||
348 | int i; | ||
349 | |||
350 | egress_dev = get_real_dev(egress_dev); | ||
351 | for (i = 0; i < dev->rdev.lldi.nports; i++) | ||
352 | if (dev->rdev.lldi.ports[i] == egress_dev) | ||
353 | return 1; | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static struct dst_entry *find_route6(struct c4iw_dev *dev, __u8 *local_ip, | ||
358 | __u8 *peer_ip, __be16 local_port, | ||
359 | __be16 peer_port, u8 tos, | ||
360 | __u32 sin6_scope_id) | ||
361 | { | ||
362 | struct dst_entry *dst = NULL; | ||
363 | |||
364 | if (IS_ENABLED(CONFIG_IPV6)) { | ||
365 | struct flowi6 fl6; | ||
366 | |||
367 | memset(&fl6, 0, sizeof(fl6)); | ||
368 | memcpy(&fl6.daddr, peer_ip, 16); | ||
369 | memcpy(&fl6.saddr, local_ip, 16); | ||
370 | if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) | ||
371 | fl6.flowi6_oif = sin6_scope_id; | ||
372 | dst = ip6_route_output(&init_net, NULL, &fl6); | ||
373 | if (!dst) | ||
374 | goto out; | ||
375 | if (!our_interface(dev, ip6_dst_idev(dst)->dev) && | ||
376 | !(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) { | ||
377 | dst_release(dst); | ||
378 | dst = NULL; | ||
379 | } | ||
380 | } | ||
381 | |||
382 | out: | ||
383 | return dst; | ||
384 | } | ||
385 | |||
386 | static struct dst_entry *find_route(struct c4iw_dev *dev, __be32 local_ip, | ||
337 | __be32 peer_ip, __be16 local_port, | 387 | __be32 peer_ip, __be16 local_port, |
338 | __be16 peer_port, u8 tos) | 388 | __be16 peer_port, u8 tos) |
339 | { | 389 | { |
340 | struct rtable *rt; | 390 | struct rtable *rt; |
341 | struct flowi4 fl4; | 391 | struct flowi4 fl4; |
392 | struct neighbour *n; | ||
342 | 393 | ||
343 | rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip, | 394 | rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip, |
344 | peer_port, local_port, IPPROTO_TCP, | 395 | peer_port, local_port, IPPROTO_TCP, |
345 | tos, 0); | 396 | tos, 0); |
346 | if (IS_ERR(rt)) | 397 | if (IS_ERR(rt)) |
347 | return NULL; | 398 | return NULL; |
348 | return rt; | 399 | n = dst_neigh_lookup(&rt->dst, &peer_ip); |
400 | if (!n) | ||
401 | return NULL; | ||
402 | if (!our_interface(dev, n->dev)) { | ||
403 | dst_release(&rt->dst); | ||
404 | return NULL; | ||
405 | } | ||
406 | neigh_release(n); | ||
407 | return &rt->dst; | ||
349 | } | 408 | } |
350 | 409 | ||
351 | static void arp_failure_discard(void *handle, struct sk_buff *skb) | 410 | static void arp_failure_discard(void *handle, struct sk_buff *skb) |
@@ -512,15 +571,28 @@ static int send_connect(struct c4iw_ep *ep) | |||
512 | { | 571 | { |
513 | struct cpl_act_open_req *req; | 572 | struct cpl_act_open_req *req; |
514 | struct cpl_t5_act_open_req *t5_req; | 573 | struct cpl_t5_act_open_req *t5_req; |
574 | struct cpl_act_open_req6 *req6; | ||
575 | struct cpl_t5_act_open_req6 *t5_req6; | ||
515 | struct sk_buff *skb; | 576 | struct sk_buff *skb; |
516 | u64 opt0; | 577 | u64 opt0; |
517 | u32 opt2; | 578 | u32 opt2; |
518 | unsigned int mtu_idx; | 579 | unsigned int mtu_idx; |
519 | int wscale; | 580 | int wscale; |
520 | int size = is_t4(ep->com.dev->rdev.lldi.adapter_type) ? | 581 | int wrlen; |
521 | sizeof(struct cpl_act_open_req) : | 582 | int sizev4 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ? |
522 | sizeof(struct cpl_t5_act_open_req); | 583 | sizeof(struct cpl_act_open_req) : |
523 | int wrlen = roundup(size, 16); | 584 | sizeof(struct cpl_t5_act_open_req); |
585 | int sizev6 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ? | ||
586 | sizeof(struct cpl_act_open_req6) : | ||
587 | sizeof(struct cpl_t5_act_open_req6); | ||
588 | struct sockaddr_in *la = (struct sockaddr_in *)&ep->com.local_addr; | ||
589 | struct sockaddr_in *ra = (struct sockaddr_in *)&ep->com.remote_addr; | ||
590 | struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&ep->com.local_addr; | ||
591 | struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; | ||
592 | |||
593 | wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? | ||
594 | roundup(sizev4, 16) : | ||
595 | roundup(sizev6, 16); | ||
524 | 596 | ||
525 | PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid); | 597 | PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid); |
526 | 598 | ||
@@ -557,33 +629,82 @@ static int send_connect(struct c4iw_ep *ep) | |||
557 | t4_set_arp_err_handler(skb, NULL, act_open_req_arp_failure); | 629 | t4_set_arp_err_handler(skb, NULL, act_open_req_arp_failure); |
558 | 630 | ||
559 | if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { | 631 | if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { |
560 | req = (struct cpl_act_open_req *) skb_put(skb, wrlen); | 632 | if (ep->com.remote_addr.ss_family == AF_INET) { |
561 | INIT_TP_WR(req, 0); | 633 | req = (struct cpl_act_open_req *) skb_put(skb, wrlen); |
562 | OPCODE_TID(req) = cpu_to_be32( | 634 | INIT_TP_WR(req, 0); |
563 | MK_OPCODE_TID(CPL_ACT_OPEN_REQ, | 635 | OPCODE_TID(req) = cpu_to_be32( |
564 | ((ep->rss_qid << 14) | ep->atid))); | 636 | MK_OPCODE_TID(CPL_ACT_OPEN_REQ, |
565 | req->local_port = ep->com.local_addr.sin_port; | 637 | ((ep->rss_qid << 14) | ep->atid))); |
566 | req->peer_port = ep->com.remote_addr.sin_port; | 638 | req->local_port = la->sin_port; |
567 | req->local_ip = ep->com.local_addr.sin_addr.s_addr; | 639 | req->peer_port = ra->sin_port; |
568 | req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; | 640 | req->local_ip = la->sin_addr.s_addr; |
569 | req->opt0 = cpu_to_be64(opt0); | 641 | req->peer_ip = ra->sin_addr.s_addr; |
570 | req->params = cpu_to_be32(select_ntuple(ep->com.dev, | 642 | req->opt0 = cpu_to_be64(opt0); |
571 | ep->dst, ep->l2t)); | 643 | req->params = cpu_to_be32(select_ntuple(ep->com.dev, |
572 | req->opt2 = cpu_to_be32(opt2); | 644 | ep->dst, ep->l2t)); |
645 | req->opt2 = cpu_to_be32(opt2); | ||
646 | } else { | ||
647 | req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen); | ||
648 | |||
649 | INIT_TP_WR(req6, 0); | ||
650 | OPCODE_TID(req6) = cpu_to_be32( | ||
651 | MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, | ||
652 | ((ep->rss_qid<<14)|ep->atid))); | ||
653 | req6->local_port = la6->sin6_port; | ||
654 | req6->peer_port = ra6->sin6_port; | ||
655 | req6->local_ip_hi = *((__be64 *) | ||
656 | (la6->sin6_addr.s6_addr)); | ||
657 | req6->local_ip_lo = *((__be64 *) | ||
658 | (la6->sin6_addr.s6_addr + 8)); | ||
659 | req6->peer_ip_hi = *((__be64 *) | ||
660 | (ra6->sin6_addr.s6_addr)); | ||
661 | req6->peer_ip_lo = *((__be64 *) | ||
662 | (ra6->sin6_addr.s6_addr + 8)); | ||
663 | req6->opt0 = cpu_to_be64(opt0); | ||
664 | req6->params = cpu_to_be32( | ||
665 | select_ntuple(ep->com.dev, ep->dst, | ||
666 | ep->l2t)); | ||
667 | req6->opt2 = cpu_to_be32(opt2); | ||
668 | } | ||
573 | } else { | 669 | } else { |
574 | t5_req = (struct cpl_t5_act_open_req *) skb_put(skb, wrlen); | 670 | if (ep->com.remote_addr.ss_family == AF_INET) { |
575 | INIT_TP_WR(t5_req, 0); | 671 | t5_req = (struct cpl_t5_act_open_req *) |
576 | OPCODE_TID(t5_req) = cpu_to_be32( | 672 | skb_put(skb, wrlen); |
673 | INIT_TP_WR(t5_req, 0); | ||
674 | OPCODE_TID(t5_req) = cpu_to_be32( | ||
577 | MK_OPCODE_TID(CPL_ACT_OPEN_REQ, | 675 | MK_OPCODE_TID(CPL_ACT_OPEN_REQ, |
578 | ((ep->rss_qid << 14) | ep->atid))); | 676 | ((ep->rss_qid << 14) | ep->atid))); |
579 | t5_req->local_port = ep->com.local_addr.sin_port; | 677 | t5_req->local_port = la->sin_port; |
580 | t5_req->peer_port = ep->com.remote_addr.sin_port; | 678 | t5_req->peer_port = ra->sin_port; |
581 | t5_req->local_ip = ep->com.local_addr.sin_addr.s_addr; | 679 | t5_req->local_ip = la->sin_addr.s_addr; |
582 | t5_req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; | 680 | t5_req->peer_ip = ra->sin_addr.s_addr; |
583 | t5_req->opt0 = cpu_to_be64(opt0); | 681 | t5_req->opt0 = cpu_to_be64(opt0); |
584 | t5_req->params = cpu_to_be64(V_FILTER_TUPLE( | 682 | t5_req->params = cpu_to_be64(V_FILTER_TUPLE( |
585 | select_ntuple(ep->com.dev, ep->dst, ep->l2t))); | 683 | select_ntuple(ep->com.dev, |
586 | t5_req->opt2 = cpu_to_be32(opt2); | 684 | ep->dst, ep->l2t))); |
685 | t5_req->opt2 = cpu_to_be32(opt2); | ||
686 | } else { | ||
687 | t5_req6 = (struct cpl_t5_act_open_req6 *) | ||
688 | skb_put(skb, wrlen); | ||
689 | INIT_TP_WR(t5_req6, 0); | ||
690 | OPCODE_TID(t5_req6) = cpu_to_be32( | ||
691 | MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, | ||
692 | ((ep->rss_qid<<14)|ep->atid))); | ||
693 | t5_req6->local_port = la6->sin6_port; | ||
694 | t5_req6->peer_port = ra6->sin6_port; | ||
695 | t5_req6->local_ip_hi = *((__be64 *) | ||
696 | (la6->sin6_addr.s6_addr)); | ||
697 | t5_req6->local_ip_lo = *((__be64 *) | ||
698 | (la6->sin6_addr.s6_addr + 8)); | ||
699 | t5_req6->peer_ip_hi = *((__be64 *) | ||
700 | (ra6->sin6_addr.s6_addr)); | ||
701 | t5_req6->peer_ip_lo = *((__be64 *) | ||
702 | (ra6->sin6_addr.s6_addr + 8)); | ||
703 | t5_req6->opt0 = cpu_to_be64(opt0); | ||
704 | t5_req6->params = (__force __be64)cpu_to_be32( | ||
705 | select_ntuple(ep->com.dev, ep->dst, ep->l2t)); | ||
706 | t5_req6->opt2 = cpu_to_be32(opt2); | ||
707 | } | ||
587 | } | 708 | } |
588 | 709 | ||
589 | set_bit(ACT_OPEN_REQ, &ep->com.history); | 710 | set_bit(ACT_OPEN_REQ, &ep->com.history); |
@@ -1502,6 +1623,7 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) | |||
1502 | struct fw_ofld_connection_wr *req; | 1623 | struct fw_ofld_connection_wr *req; |
1503 | unsigned int mtu_idx; | 1624 | unsigned int mtu_idx; |
1504 | int wscale; | 1625 | int wscale; |
1626 | struct sockaddr_in *sin; | ||
1505 | 1627 | ||
1506 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); | 1628 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); |
1507 | req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); | 1629 | req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); |
@@ -1510,10 +1632,12 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) | |||
1510 | req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16))); | 1632 | req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16))); |
1511 | req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, | 1633 | req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, |
1512 | ep->l2t)); | 1634 | ep->l2t)); |
1513 | req->le.lport = ep->com.local_addr.sin_port; | 1635 | sin = (struct sockaddr_in *)&ep->com.local_addr; |
1514 | req->le.pport = ep->com.remote_addr.sin_port; | 1636 | req->le.lport = sin->sin_port; |
1515 | req->le.u.ipv4.lip = ep->com.local_addr.sin_addr.s_addr; | 1637 | req->le.u.ipv4.lip = sin->sin_addr.s_addr; |
1516 | req->le.u.ipv4.pip = ep->com.remote_addr.sin_addr.s_addr; | 1638 | sin = (struct sockaddr_in *)&ep->com.remote_addr; |
1639 | req->le.pport = sin->sin_port; | ||
1640 | req->le.u.ipv4.pip = sin->sin_addr.s_addr; | ||
1517 | req->tcb.t_state_to_astid = | 1641 | req->tcb.t_state_to_astid = |
1518 | htonl(V_FW_OFLD_CONNECTION_WR_T_STATE(TCP_SYN_SENT) | | 1642 | htonl(V_FW_OFLD_CONNECTION_WR_T_STATE(TCP_SYN_SENT) | |
1519 | V_FW_OFLD_CONNECTION_WR_ASTID(atid)); | 1643 | V_FW_OFLD_CONNECTION_WR_ASTID(atid)); |
@@ -1564,18 +1688,98 @@ static inline int act_open_has_tid(int status) | |||
1564 | 1688 | ||
1565 | #define ACT_OPEN_RETRY_COUNT 2 | 1689 | #define ACT_OPEN_RETRY_COUNT 2 |
1566 | 1690 | ||
1691 | static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, | ||
1692 | struct dst_entry *dst, struct c4iw_dev *cdev, | ||
1693 | bool clear_mpa_v1) | ||
1694 | { | ||
1695 | struct neighbour *n; | ||
1696 | int err, step; | ||
1697 | struct net_device *pdev; | ||
1698 | |||
1699 | n = dst_neigh_lookup(dst, peer_ip); | ||
1700 | if (!n) | ||
1701 | return -ENODEV; | ||
1702 | |||
1703 | rcu_read_lock(); | ||
1704 | err = -ENOMEM; | ||
1705 | if (n->dev->flags & IFF_LOOPBACK) { | ||
1706 | if (iptype == 4) | ||
1707 | pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip); | ||
1708 | else if (IS_ENABLED(CONFIG_IPV6)) | ||
1709 | for_each_netdev(&init_net, pdev) { | ||
1710 | if (ipv6_chk_addr(&init_net, | ||
1711 | (struct in6_addr *)peer_ip, | ||
1712 | pdev, 1)) | ||
1713 | break; | ||
1714 | } | ||
1715 | else | ||
1716 | pdev = NULL; | ||
1717 | |||
1718 | if (!pdev) { | ||
1719 | err = -ENODEV; | ||
1720 | goto out; | ||
1721 | } | ||
1722 | ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, | ||
1723 | n, pdev, 0); | ||
1724 | if (!ep->l2t) | ||
1725 | goto out; | ||
1726 | ep->mtu = pdev->mtu; | ||
1727 | ep->tx_chan = cxgb4_port_chan(pdev); | ||
1728 | ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; | ||
1729 | step = cdev->rdev.lldi.ntxq / | ||
1730 | cdev->rdev.lldi.nchan; | ||
1731 | ep->txq_idx = cxgb4_port_idx(pdev) * step; | ||
1732 | step = cdev->rdev.lldi.nrxq / | ||
1733 | cdev->rdev.lldi.nchan; | ||
1734 | ep->ctrlq_idx = cxgb4_port_idx(pdev); | ||
1735 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ | ||
1736 | cxgb4_port_idx(pdev) * step]; | ||
1737 | dev_put(pdev); | ||
1738 | } else { | ||
1739 | pdev = get_real_dev(n->dev); | ||
1740 | ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, | ||
1741 | n, pdev, 0); | ||
1742 | if (!ep->l2t) | ||
1743 | goto out; | ||
1744 | ep->mtu = dst_mtu(dst); | ||
1745 | ep->tx_chan = cxgb4_port_chan(n->dev); | ||
1746 | ep->smac_idx = (cxgb4_port_viid(n->dev) & 0x7F) << 1; | ||
1747 | step = cdev->rdev.lldi.ntxq / | ||
1748 | cdev->rdev.lldi.nchan; | ||
1749 | ep->txq_idx = cxgb4_port_idx(n->dev) * step; | ||
1750 | ep->ctrlq_idx = cxgb4_port_idx(n->dev); | ||
1751 | step = cdev->rdev.lldi.nrxq / | ||
1752 | cdev->rdev.lldi.nchan; | ||
1753 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ | ||
1754 | cxgb4_port_idx(n->dev) * step]; | ||
1755 | |||
1756 | if (clear_mpa_v1) { | ||
1757 | ep->retry_with_mpa_v1 = 0; | ||
1758 | ep->tried_with_mpa_v1 = 0; | ||
1759 | } | ||
1760 | } | ||
1761 | err = 0; | ||
1762 | out: | ||
1763 | rcu_read_unlock(); | ||
1764 | |||
1765 | neigh_release(n); | ||
1766 | |||
1767 | return err; | ||
1768 | } | ||
1769 | |||
1567 | static int c4iw_reconnect(struct c4iw_ep *ep) | 1770 | static int c4iw_reconnect(struct c4iw_ep *ep) |
1568 | { | 1771 | { |
1569 | int err = 0; | 1772 | int err = 0; |
1570 | struct rtable *rt; | ||
1571 | struct port_info *pi; | ||
1572 | struct net_device *pdev; | ||
1573 | int step; | ||
1574 | struct neighbour *neigh; | ||
1575 | struct sockaddr_in *laddr = (struct sockaddr_in *) | 1773 | struct sockaddr_in *laddr = (struct sockaddr_in *) |
1576 | &ep->com.cm_id->local_addr; | 1774 | &ep->com.cm_id->local_addr; |
1577 | struct sockaddr_in *raddr = (struct sockaddr_in *) | 1775 | struct sockaddr_in *raddr = (struct sockaddr_in *) |
1578 | &ep->com.cm_id->remote_addr; | 1776 | &ep->com.cm_id->remote_addr; |
1777 | struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *) | ||
1778 | &ep->com.cm_id->local_addr; | ||
1779 | struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *) | ||
1780 | &ep->com.cm_id->remote_addr; | ||
1781 | int iptype; | ||
1782 | __u8 *ra; | ||
1579 | 1783 | ||
1580 | PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); | 1784 | PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); |
1581 | init_timer(&ep->timer); | 1785 | init_timer(&ep->timer); |
@@ -1592,53 +1796,28 @@ static int c4iw_reconnect(struct c4iw_ep *ep) | |||
1592 | insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid); | 1796 | insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid); |
1593 | 1797 | ||
1594 | /* find a route */ | 1798 | /* find a route */ |
1595 | rt = find_route(ep->com.dev, | 1799 | if (ep->com.cm_id->local_addr.ss_family == AF_INET) { |
1596 | laddr->sin_addr.s_addr, raddr->sin_addr.s_addr, | 1800 | ep->dst = find_route(ep->com.dev, laddr->sin_addr.s_addr, |
1597 | laddr->sin_port, raddr->sin_port, 0); | 1801 | raddr->sin_addr.s_addr, laddr->sin_port, |
1598 | if (!rt) { | 1802 | raddr->sin_port, 0); |
1803 | iptype = 4; | ||
1804 | ra = (__u8 *)&raddr->sin_addr; | ||
1805 | } else { | ||
1806 | ep->dst = find_route6(ep->com.dev, laddr6->sin6_addr.s6_addr, | ||
1807 | raddr6->sin6_addr.s6_addr, | ||
1808 | laddr6->sin6_port, raddr6->sin6_port, 0, | ||
1809 | raddr6->sin6_scope_id); | ||
1810 | iptype = 6; | ||
1811 | ra = (__u8 *)&raddr6->sin6_addr; | ||
1812 | } | ||
1813 | if (!ep->dst) { | ||
1599 | pr_err("%s - cannot find route.\n", __func__); | 1814 | pr_err("%s - cannot find route.\n", __func__); |
1600 | err = -EHOSTUNREACH; | 1815 | err = -EHOSTUNREACH; |
1601 | goto fail3; | 1816 | goto fail3; |
1602 | } | 1817 | } |
1603 | ep->dst = &rt->dst; | 1818 | err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false); |
1604 | 1819 | if (err) { | |
1605 | neigh = dst_neigh_lookup(ep->dst, &raddr->sin_addr.s_addr); | ||
1606 | if (!neigh) { | ||
1607 | pr_err("%s - cannot alloc neigh.\n", __func__); | ||
1608 | err = -ENOMEM; | ||
1609 | goto fail4; | ||
1610 | } | ||
1611 | |||
1612 | /* get a l2t entry */ | ||
1613 | if (neigh->dev->flags & IFF_LOOPBACK) { | ||
1614 | PDBG("%s LOOPBACK\n", __func__); | ||
1615 | pdev = ip_dev_find(&init_net, raddr->sin_addr.s_addr); | ||
1616 | ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, | ||
1617 | neigh, pdev, 0); | ||
1618 | pi = (struct port_info *)netdev_priv(pdev); | ||
1619 | ep->mtu = pdev->mtu; | ||
1620 | ep->tx_chan = cxgb4_port_chan(pdev); | ||
1621 | ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; | ||
1622 | dev_put(pdev); | ||
1623 | } else { | ||
1624 | ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, | ||
1625 | neigh, neigh->dev, 0); | ||
1626 | pi = (struct port_info *)netdev_priv(neigh->dev); | ||
1627 | ep->mtu = dst_mtu(ep->dst); | ||
1628 | ep->tx_chan = cxgb4_port_chan(neigh->dev); | ||
1629 | ep->smac_idx = (cxgb4_port_viid(neigh->dev) & | ||
1630 | 0x7F) << 1; | ||
1631 | } | ||
1632 | |||
1633 | step = ep->com.dev->rdev.lldi.ntxq / ep->com.dev->rdev.lldi.nchan; | ||
1634 | ep->txq_idx = pi->port_id * step; | ||
1635 | ep->ctrlq_idx = pi->port_id; | ||
1636 | step = ep->com.dev->rdev.lldi.nrxq / ep->com.dev->rdev.lldi.nchan; | ||
1637 | ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[pi->port_id * step]; | ||
1638 | |||
1639 | if (!ep->l2t) { | ||
1640 | pr_err("%s - cannot alloc l2e.\n", __func__); | 1820 | pr_err("%s - cannot alloc l2e.\n", __func__); |
1641 | err = -ENOMEM; | ||
1642 | goto fail4; | 1821 | goto fail4; |
1643 | } | 1822 | } |
1644 | 1823 | ||
@@ -1681,8 +1860,16 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1681 | ntohl(rpl->atid_status))); | 1860 | ntohl(rpl->atid_status))); |
1682 | struct tid_info *t = dev->rdev.lldi.tids; | 1861 | struct tid_info *t = dev->rdev.lldi.tids; |
1683 | int status = GET_AOPEN_STATUS(ntohl(rpl->atid_status)); | 1862 | int status = GET_AOPEN_STATUS(ntohl(rpl->atid_status)); |
1863 | struct sockaddr_in *la; | ||
1864 | struct sockaddr_in *ra; | ||
1865 | struct sockaddr_in6 *la6; | ||
1866 | struct sockaddr_in6 *ra6; | ||
1684 | 1867 | ||
1685 | ep = lookup_atid(t, atid); | 1868 | ep = lookup_atid(t, atid); |
1869 | la = (struct sockaddr_in *)&ep->com.local_addr; | ||
1870 | ra = (struct sockaddr_in *)&ep->com.remote_addr; | ||
1871 | la6 = (struct sockaddr_in6 *)&ep->com.local_addr; | ||
1872 | ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; | ||
1686 | 1873 | ||
1687 | PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, | 1874 | PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, |
1688 | status, status2errno(status)); | 1875 | status, status2errno(status)); |
@@ -1703,10 +1890,11 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1703 | case CPL_ERR_CONN_TIMEDOUT: | 1890 | case CPL_ERR_CONN_TIMEDOUT: |
1704 | break; | 1891 | break; |
1705 | case CPL_ERR_TCAM_FULL: | 1892 | case CPL_ERR_TCAM_FULL: |
1893 | mutex_lock(&dev->rdev.stats.lock); | ||
1706 | dev->rdev.stats.tcam_full++; | 1894 | dev->rdev.stats.tcam_full++; |
1707 | if (dev->rdev.lldi.enable_fw_ofld_conn) { | 1895 | mutex_unlock(&dev->rdev.stats.lock); |
1708 | mutex_lock(&dev->rdev.stats.lock); | 1896 | if (ep->com.local_addr.ss_family == AF_INET && |
1709 | mutex_unlock(&dev->rdev.stats.lock); | 1897 | dev->rdev.lldi.enable_fw_ofld_conn) { |
1710 | send_fw_act_open_req(ep, | 1898 | send_fw_act_open_req(ep, |
1711 | GET_TID_TID(GET_AOPEN_ATID( | 1899 | GET_TID_TID(GET_AOPEN_ATID( |
1712 | ntohl(rpl->atid_status)))); | 1900 | ntohl(rpl->atid_status)))); |
@@ -1726,13 +1914,17 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1726 | } | 1914 | } |
1727 | break; | 1915 | break; |
1728 | default: | 1916 | default: |
1729 | printk(KERN_INFO MOD "Active open failure - " | 1917 | if (ep->com.local_addr.ss_family == AF_INET) { |
1730 | "atid %u status %u errno %d %pI4:%u->%pI4:%u\n", | 1918 | pr_info("Active open failure - atid %u status %u errno %d %pI4:%u->%pI4:%u\n", |
1731 | atid, status, status2errno(status), | 1919 | atid, status, status2errno(status), |
1732 | &ep->com.local_addr.sin_addr.s_addr, | 1920 | &la->sin_addr.s_addr, ntohs(la->sin_port), |
1733 | ntohs(ep->com.local_addr.sin_port), | 1921 | &ra->sin_addr.s_addr, ntohs(ra->sin_port)); |
1734 | &ep->com.remote_addr.sin_addr.s_addr, | 1922 | } else { |
1735 | ntohs(ep->com.remote_addr.sin_port)); | 1923 | pr_info("Active open failure - atid %u status %u errno %d %pI6:%u->%pI6:%u\n", |
1924 | atid, status, status2errno(status), | ||
1925 | la6->sin6_addr.s6_addr, ntohs(la6->sin6_port), | ||
1926 | ra6->sin6_addr.s6_addr, ntohs(ra6->sin6_port)); | ||
1927 | } | ||
1736 | break; | 1928 | break; |
1737 | } | 1929 | } |
1738 | 1930 | ||
@@ -1770,27 +1962,6 @@ out: | |||
1770 | return 0; | 1962 | return 0; |
1771 | } | 1963 | } |
1772 | 1964 | ||
1773 | static int listen_stop(struct c4iw_listen_ep *ep) | ||
1774 | { | ||
1775 | struct sk_buff *skb; | ||
1776 | struct cpl_close_listsvr_req *req; | ||
1777 | |||
1778 | PDBG("%s ep %p\n", __func__, ep); | ||
1779 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); | ||
1780 | if (!skb) { | ||
1781 | printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__); | ||
1782 | return -ENOMEM; | ||
1783 | } | ||
1784 | req = (struct cpl_close_listsvr_req *) skb_put(skb, sizeof(*req)); | ||
1785 | INIT_TP_WR(req, 0); | ||
1786 | OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, | ||
1787 | ep->stid)); | ||
1788 | req->reply_ctrl = cpu_to_be16( | ||
1789 | QUEUENO(ep->com.dev->rdev.lldi.rxq_ids[0])); | ||
1790 | set_wr_txq(skb, CPL_PRIORITY_SETUP, 0); | ||
1791 | return c4iw_ofld_send(&ep->com.dev->rdev, skb); | ||
1792 | } | ||
1793 | |||
1794 | static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | 1965 | static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) |
1795 | { | 1966 | { |
1796 | struct cpl_close_listsvr_rpl *rpl = cplhdr(skb); | 1967 | struct cpl_close_listsvr_rpl *rpl = cplhdr(skb); |
@@ -1803,7 +1974,7 @@ static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1803 | return 0; | 1974 | return 0; |
1804 | } | 1975 | } |
1805 | 1976 | ||
1806 | static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb, | 1977 | static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, |
1807 | struct cpl_pass_accept_req *req) | 1978 | struct cpl_pass_accept_req *req) |
1808 | { | 1979 | { |
1809 | struct cpl_pass_accept_rpl *rpl; | 1980 | struct cpl_pass_accept_rpl *rpl; |
@@ -1860,11 +2031,9 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb, | |||
1860 | return; | 2031 | return; |
1861 | } | 2032 | } |
1862 | 2033 | ||
1863 | static void reject_cr(struct c4iw_dev *dev, u32 hwtid, __be32 peer_ip, | 2034 | static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb) |
1864 | struct sk_buff *skb) | ||
1865 | { | 2035 | { |
1866 | PDBG("%s c4iw_dev %p tid %u peer_ip %x\n", __func__, dev, hwtid, | 2036 | PDBG("%s c4iw_dev %p tid %u\n", __func__, dev, hwtid); |
1867 | peer_ip); | ||
1868 | BUG_ON(skb_cloned(skb)); | 2037 | BUG_ON(skb_cloned(skb)); |
1869 | skb_trim(skb, sizeof(struct cpl_tid_release)); | 2038 | skb_trim(skb, sizeof(struct cpl_tid_release)); |
1870 | skb_get(skb); | 2039 | skb_get(skb); |
@@ -1872,95 +2041,38 @@ static void reject_cr(struct c4iw_dev *dev, u32 hwtid, __be32 peer_ip, | |||
1872 | return; | 2041 | return; |
1873 | } | 2042 | } |
1874 | 2043 | ||
1875 | static void get_4tuple(struct cpl_pass_accept_req *req, | 2044 | static void get_4tuple(struct cpl_pass_accept_req *req, int *iptype, |
1876 | __be32 *local_ip, __be32 *peer_ip, | 2045 | __u8 *local_ip, __u8 *peer_ip, |
1877 | __be16 *local_port, __be16 *peer_port) | 2046 | __be16 *local_port, __be16 *peer_port) |
1878 | { | 2047 | { |
1879 | int eth_len = G_ETH_HDR_LEN(be32_to_cpu(req->hdr_len)); | 2048 | int eth_len = G_ETH_HDR_LEN(be32_to_cpu(req->hdr_len)); |
1880 | int ip_len = G_IP_HDR_LEN(be32_to_cpu(req->hdr_len)); | 2049 | int ip_len = G_IP_HDR_LEN(be32_to_cpu(req->hdr_len)); |
1881 | struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len); | 2050 | struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len); |
2051 | struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len); | ||
1882 | struct tcphdr *tcp = (struct tcphdr *) | 2052 | struct tcphdr *tcp = (struct tcphdr *) |
1883 | ((u8 *)(req + 1) + eth_len + ip_len); | 2053 | ((u8 *)(req + 1) + eth_len + ip_len); |
1884 | 2054 | ||
1885 | PDBG("%s saddr 0x%x daddr 0x%x sport %u dport %u\n", __func__, | 2055 | if (ip->version == 4) { |
1886 | ntohl(ip->saddr), ntohl(ip->daddr), ntohs(tcp->source), | 2056 | PDBG("%s saddr 0x%x daddr 0x%x sport %u dport %u\n", __func__, |
1887 | ntohs(tcp->dest)); | 2057 | ntohl(ip->saddr), ntohl(ip->daddr), ntohs(tcp->source), |
1888 | 2058 | ntohs(tcp->dest)); | |
1889 | *peer_ip = ip->saddr; | 2059 | *iptype = 4; |
1890 | *local_ip = ip->daddr; | 2060 | memcpy(peer_ip, &ip->saddr, 4); |
2061 | memcpy(local_ip, &ip->daddr, 4); | ||
2062 | } else { | ||
2063 | PDBG("%s saddr %pI6 daddr %pI6 sport %u dport %u\n", __func__, | ||
2064 | ip6->saddr.s6_addr, ip6->daddr.s6_addr, ntohs(tcp->source), | ||
2065 | ntohs(tcp->dest)); | ||
2066 | *iptype = 6; | ||
2067 | memcpy(peer_ip, ip6->saddr.s6_addr, 16); | ||
2068 | memcpy(local_ip, ip6->daddr.s6_addr, 16); | ||
2069 | } | ||
1891 | *peer_port = tcp->source; | 2070 | *peer_port = tcp->source; |
1892 | *local_port = tcp->dest; | 2071 | *local_port = tcp->dest; |
1893 | 2072 | ||
1894 | return; | 2073 | return; |
1895 | } | 2074 | } |
1896 | 2075 | ||
1897 | static int import_ep(struct c4iw_ep *ep, __be32 peer_ip, struct dst_entry *dst, | ||
1898 | struct c4iw_dev *cdev, bool clear_mpa_v1) | ||
1899 | { | ||
1900 | struct neighbour *n; | ||
1901 | int err, step; | ||
1902 | |||
1903 | n = dst_neigh_lookup(dst, &peer_ip); | ||
1904 | if (!n) | ||
1905 | return -ENODEV; | ||
1906 | |||
1907 | rcu_read_lock(); | ||
1908 | err = -ENOMEM; | ||
1909 | if (n->dev->flags & IFF_LOOPBACK) { | ||
1910 | struct net_device *pdev; | ||
1911 | |||
1912 | pdev = ip_dev_find(&init_net, peer_ip); | ||
1913 | if (!pdev) { | ||
1914 | err = -ENODEV; | ||
1915 | goto out; | ||
1916 | } | ||
1917 | ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, | ||
1918 | n, pdev, 0); | ||
1919 | if (!ep->l2t) | ||
1920 | goto out; | ||
1921 | ep->mtu = pdev->mtu; | ||
1922 | ep->tx_chan = cxgb4_port_chan(pdev); | ||
1923 | ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; | ||
1924 | step = cdev->rdev.lldi.ntxq / | ||
1925 | cdev->rdev.lldi.nchan; | ||
1926 | ep->txq_idx = cxgb4_port_idx(pdev) * step; | ||
1927 | step = cdev->rdev.lldi.nrxq / | ||
1928 | cdev->rdev.lldi.nchan; | ||
1929 | ep->ctrlq_idx = cxgb4_port_idx(pdev); | ||
1930 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ | ||
1931 | cxgb4_port_idx(pdev) * step]; | ||
1932 | dev_put(pdev); | ||
1933 | } else { | ||
1934 | ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, | ||
1935 | n, n->dev, 0); | ||
1936 | if (!ep->l2t) | ||
1937 | goto out; | ||
1938 | ep->mtu = dst_mtu(dst); | ||
1939 | ep->tx_chan = cxgb4_port_chan(n->dev); | ||
1940 | ep->smac_idx = (cxgb4_port_viid(n->dev) & 0x7F) << 1; | ||
1941 | step = cdev->rdev.lldi.ntxq / | ||
1942 | cdev->rdev.lldi.nchan; | ||
1943 | ep->txq_idx = cxgb4_port_idx(n->dev) * step; | ||
1944 | ep->ctrlq_idx = cxgb4_port_idx(n->dev); | ||
1945 | step = cdev->rdev.lldi.nrxq / | ||
1946 | cdev->rdev.lldi.nchan; | ||
1947 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ | ||
1948 | cxgb4_port_idx(n->dev) * step]; | ||
1949 | |||
1950 | if (clear_mpa_v1) { | ||
1951 | ep->retry_with_mpa_v1 = 0; | ||
1952 | ep->tried_with_mpa_v1 = 0; | ||
1953 | } | ||
1954 | } | ||
1955 | err = 0; | ||
1956 | out: | ||
1957 | rcu_read_unlock(); | ||
1958 | |||
1959 | neigh_release(n); | ||
1960 | |||
1961 | return err; | ||
1962 | } | ||
1963 | |||
1964 | static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | 2076 | static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) |
1965 | { | 2077 | { |
1966 | struct c4iw_ep *child_ep = NULL, *parent_ep; | 2078 | struct c4iw_ep *child_ep = NULL, *parent_ep; |
@@ -1969,23 +2081,17 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1969 | struct tid_info *t = dev->rdev.lldi.tids; | 2081 | struct tid_info *t = dev->rdev.lldi.tids; |
1970 | unsigned int hwtid = GET_TID(req); | 2082 | unsigned int hwtid = GET_TID(req); |
1971 | struct dst_entry *dst; | 2083 | struct dst_entry *dst; |
1972 | struct rtable *rt; | 2084 | __u8 local_ip[16], peer_ip[16]; |
1973 | __be32 local_ip, peer_ip = 0; | ||
1974 | __be16 local_port, peer_port; | 2085 | __be16 local_port, peer_port; |
1975 | int err; | 2086 | int err; |
1976 | u16 peer_mss = ntohs(req->tcpopt.mss); | 2087 | u16 peer_mss = ntohs(req->tcpopt.mss); |
2088 | int iptype; | ||
1977 | 2089 | ||
1978 | parent_ep = lookup_stid(t, stid); | 2090 | parent_ep = lookup_stid(t, stid); |
1979 | if (!parent_ep) { | 2091 | if (!parent_ep) { |
1980 | PDBG("%s connect request on invalid stid %d\n", __func__, stid); | 2092 | PDBG("%s connect request on invalid stid %d\n", __func__, stid); |
1981 | goto reject; | 2093 | goto reject; |
1982 | } | 2094 | } |
1983 | get_4tuple(req, &local_ip, &peer_ip, &local_port, &peer_port); | ||
1984 | |||
1985 | PDBG("%s parent ep %p hwtid %u laddr 0x%x raddr 0x%x lport %d " \ | ||
1986 | "rport %d peer_mss %d\n", __func__, parent_ep, hwtid, | ||
1987 | ntohl(local_ip), ntohl(peer_ip), ntohs(local_port), | ||
1988 | ntohs(peer_port), peer_mss); | ||
1989 | 2095 | ||
1990 | if (state_read(&parent_ep->com) != LISTEN) { | 2096 | if (state_read(&parent_ep->com) != LISTEN) { |
1991 | printk(KERN_ERR "%s - listening ep not in LISTEN\n", | 2097 | printk(KERN_ERR "%s - listening ep not in LISTEN\n", |
@@ -1993,15 +2099,32 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1993 | goto reject; | 2099 | goto reject; |
1994 | } | 2100 | } |
1995 | 2101 | ||
2102 | get_4tuple(req, &iptype, local_ip, peer_ip, &local_port, &peer_port); | ||
2103 | |||
1996 | /* Find output route */ | 2104 | /* Find output route */ |
1997 | rt = find_route(dev, local_ip, peer_ip, local_port, peer_port, | 2105 | if (iptype == 4) { |
1998 | GET_POPEN_TOS(ntohl(req->tos_stid))); | 2106 | PDBG("%s parent ep %p hwtid %u laddr %pI4 raddr %pI4 lport %d rport %d peer_mss %d\n" |
1999 | if (!rt) { | 2107 | , __func__, parent_ep, hwtid, |
2108 | local_ip, peer_ip, ntohs(local_port), | ||
2109 | ntohs(peer_port), peer_mss); | ||
2110 | dst = find_route(dev, *(__be32 *)local_ip, *(__be32 *)peer_ip, | ||
2111 | local_port, peer_port, | ||
2112 | GET_POPEN_TOS(ntohl(req->tos_stid))); | ||
2113 | } else { | ||
2114 | PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n" | ||
2115 | , __func__, parent_ep, hwtid, | ||
2116 | local_ip, peer_ip, ntohs(local_port), | ||
2117 | ntohs(peer_port), peer_mss); | ||
2118 | dst = find_route6(dev, local_ip, peer_ip, local_port, peer_port, | ||
2119 | PASS_OPEN_TOS(ntohl(req->tos_stid)), | ||
2120 | ((struct sockaddr_in6 *) | ||
2121 | &parent_ep->com.local_addr)->sin6_scope_id); | ||
2122 | } | ||
2123 | if (!dst) { | ||
2000 | printk(KERN_ERR MOD "%s - failed to find dst entry!\n", | 2124 | printk(KERN_ERR MOD "%s - failed to find dst entry!\n", |
2001 | __func__); | 2125 | __func__); |
2002 | goto reject; | 2126 | goto reject; |
2003 | } | 2127 | } |
2004 | dst = &rt->dst; | ||
2005 | 2128 | ||
2006 | child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL); | 2129 | child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL); |
2007 | if (!child_ep) { | 2130 | if (!child_ep) { |
@@ -2011,7 +2134,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | |||
2011 | goto reject; | 2134 | goto reject; |
2012 | } | 2135 | } |
2013 | 2136 | ||
2014 | err = import_ep(child_ep, peer_ip, dst, dev, false); | 2137 | err = import_ep(child_ep, iptype, peer_ip, dst, dev, false); |
2015 | if (err) { | 2138 | if (err) { |
2016 | printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", | 2139 | printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", |
2017 | __func__); | 2140 | __func__); |
@@ -2026,12 +2149,27 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | |||
2026 | state_set(&child_ep->com, CONNECTING); | 2149 | state_set(&child_ep->com, CONNECTING); |
2027 | child_ep->com.dev = dev; | 2150 | child_ep->com.dev = dev; |
2028 | child_ep->com.cm_id = NULL; | 2151 | child_ep->com.cm_id = NULL; |
2029 | child_ep->com.local_addr.sin_family = PF_INET; | 2152 | if (iptype == 4) { |
2030 | child_ep->com.local_addr.sin_port = local_port; | 2153 | struct sockaddr_in *sin = (struct sockaddr_in *) |
2031 | child_ep->com.local_addr.sin_addr.s_addr = local_ip; | 2154 | &child_ep->com.local_addr; |
2032 | child_ep->com.remote_addr.sin_family = PF_INET; | 2155 | sin->sin_family = PF_INET; |
2033 | child_ep->com.remote_addr.sin_port = peer_port; | 2156 | sin->sin_port = local_port; |
2034 | child_ep->com.remote_addr.sin_addr.s_addr = peer_ip; | 2157 | sin->sin_addr.s_addr = *(__be32 *)local_ip; |
2158 | sin = (struct sockaddr_in *)&child_ep->com.remote_addr; | ||
2159 | sin->sin_family = PF_INET; | ||
2160 | sin->sin_port = peer_port; | ||
2161 | sin->sin_addr.s_addr = *(__be32 *)peer_ip; | ||
2162 | } else { | ||
2163 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) | ||
2164 | &child_ep->com.local_addr; | ||
2165 | sin6->sin6_family = PF_INET6; | ||
2166 | sin6->sin6_port = local_port; | ||
2167 | memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); | ||
2168 | sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr; | ||
2169 | sin6->sin6_family = PF_INET6; | ||
2170 | sin6->sin6_port = peer_port; | ||
2171 | memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16); | ||
2172 | } | ||
2035 | c4iw_get_ep(&parent_ep->com); | 2173 | c4iw_get_ep(&parent_ep->com); |
2036 | child_ep->parent_ep = parent_ep; | 2174 | child_ep->parent_ep = parent_ep; |
2037 | child_ep->tos = GET_POPEN_TOS(ntohl(req->tos_stid)); | 2175 | child_ep->tos = GET_POPEN_TOS(ntohl(req->tos_stid)); |
@@ -2044,11 +2182,11 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | |||
2044 | init_timer(&child_ep->timer); | 2182 | init_timer(&child_ep->timer); |
2045 | cxgb4_insert_tid(t, child_ep, hwtid); | 2183 | cxgb4_insert_tid(t, child_ep, hwtid); |
2046 | insert_handle(dev, &dev->hwtid_idr, child_ep, child_ep->hwtid); | 2184 | insert_handle(dev, &dev->hwtid_idr, child_ep, child_ep->hwtid); |
2047 | accept_cr(child_ep, peer_ip, skb, req); | 2185 | accept_cr(child_ep, skb, req); |
2048 | set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); | 2186 | set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); |
2049 | goto out; | 2187 | goto out; |
2050 | reject: | 2188 | reject: |
2051 | reject_cr(dev, hwtid, peer_ip, skb); | 2189 | reject_cr(dev, hwtid, skb); |
2052 | out: | 2190 | out: |
2053 | return 0; | 2191 | return 0; |
2054 | } | 2192 | } |
@@ -2516,14 +2654,79 @@ err: | |||
2516 | return err; | 2654 | return err; |
2517 | } | 2655 | } |
2518 | 2656 | ||
2657 | static int pick_local_ipaddrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) | ||
2658 | { | ||
2659 | struct in_device *ind; | ||
2660 | int found = 0; | ||
2661 | struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr; | ||
2662 | struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr; | ||
2663 | |||
2664 | ind = in_dev_get(dev->rdev.lldi.ports[0]); | ||
2665 | if (!ind) | ||
2666 | return -EADDRNOTAVAIL; | ||
2667 | for_primary_ifa(ind) { | ||
2668 | laddr->sin_addr.s_addr = ifa->ifa_address; | ||
2669 | raddr->sin_addr.s_addr = ifa->ifa_address; | ||
2670 | found = 1; | ||
2671 | break; | ||
2672 | } | ||
2673 | endfor_ifa(ind); | ||
2674 | in_dev_put(ind); | ||
2675 | return found ? 0 : -EADDRNOTAVAIL; | ||
2676 | } | ||
2677 | |||
2678 | static int get_lladdr(struct net_device *dev, struct in6_addr *addr, | ||
2679 | unsigned char banned_flags) | ||
2680 | { | ||
2681 | struct inet6_dev *idev; | ||
2682 | int err = -EADDRNOTAVAIL; | ||
2683 | |||
2684 | rcu_read_lock(); | ||
2685 | idev = __in6_dev_get(dev); | ||
2686 | if (idev != NULL) { | ||
2687 | struct inet6_ifaddr *ifp; | ||
2688 | |||
2689 | read_lock_bh(&idev->lock); | ||
2690 | list_for_each_entry(ifp, &idev->addr_list, if_list) { | ||
2691 | if (ifp->scope == IFA_LINK && | ||
2692 | !(ifp->flags & banned_flags)) { | ||
2693 | memcpy(addr, &ifp->addr, 16); | ||
2694 | err = 0; | ||
2695 | break; | ||
2696 | } | ||
2697 | } | ||
2698 | read_unlock_bh(&idev->lock); | ||
2699 | } | ||
2700 | rcu_read_unlock(); | ||
2701 | return err; | ||
2702 | } | ||
2703 | |||
2704 | static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) | ||
2705 | { | ||
2706 | struct in6_addr uninitialized_var(addr); | ||
2707 | struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->local_addr; | ||
2708 | struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->remote_addr; | ||
2709 | |||
2710 | if (get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) { | ||
2711 | memcpy(la6->sin6_addr.s6_addr, &addr, 16); | ||
2712 | memcpy(ra6->sin6_addr.s6_addr, &addr, 16); | ||
2713 | return 0; | ||
2714 | } | ||
2715 | return -EADDRNOTAVAIL; | ||
2716 | } | ||
2717 | |||
2519 | int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | 2718 | int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) |
2520 | { | 2719 | { |
2521 | struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); | 2720 | struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); |
2522 | struct c4iw_ep *ep; | 2721 | struct c4iw_ep *ep; |
2523 | struct rtable *rt; | ||
2524 | int err = 0; | 2722 | int err = 0; |
2525 | struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr; | 2723 | struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr; |
2526 | struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr; | 2724 | struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr; |
2725 | struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *)&cm_id->local_addr; | ||
2726 | struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *) | ||
2727 | &cm_id->remote_addr; | ||
2728 | __u8 *ra; | ||
2729 | int iptype; | ||
2527 | 2730 | ||
2528 | if ((conn_param->ord > c4iw_max_read_depth) || | 2731 | if ((conn_param->ord > c4iw_max_read_depth) || |
2529 | (conn_param->ird > c4iw_max_read_depth)) { | 2732 | (conn_param->ird > c4iw_max_read_depth)) { |
@@ -2551,7 +2754,11 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2551 | ep->com.dev = dev; | 2754 | ep->com.dev = dev; |
2552 | ep->com.cm_id = cm_id; | 2755 | ep->com.cm_id = cm_id; |
2553 | ep->com.qp = get_qhp(dev, conn_param->qpn); | 2756 | ep->com.qp = get_qhp(dev, conn_param->qpn); |
2554 | BUG_ON(!ep->com.qp); | 2757 | if (!ep->com.qp) { |
2758 | PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn); | ||
2759 | err = -EINVAL; | ||
2760 | goto fail2; | ||
2761 | } | ||
2555 | ref_qp(ep); | 2762 | ref_qp(ep); |
2556 | PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn, | 2763 | PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn, |
2557 | ep->com.qp, cm_id); | 2764 | ep->com.qp, cm_id); |
@@ -2567,21 +2774,56 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2567 | } | 2774 | } |
2568 | insert_handle(dev, &dev->atid_idr, ep, ep->atid); | 2775 | insert_handle(dev, &dev->atid_idr, ep, ep->atid); |
2569 | 2776 | ||
2570 | PDBG("%s saddr 0x%x sport 0x%x raddr 0x%x rport 0x%x\n", __func__, | 2777 | if (cm_id->remote_addr.ss_family == AF_INET) { |
2571 | ntohl(laddr->sin_addr.s_addr), ntohs(laddr->sin_port), | 2778 | iptype = 4; |
2572 | ntohl(raddr->sin_addr.s_addr), ntohs(raddr->sin_port)); | 2779 | ra = (__u8 *)&raddr->sin_addr; |
2573 | 2780 | ||
2574 | /* find a route */ | 2781 | /* |
2575 | rt = find_route(dev, laddr->sin_addr.s_addr, raddr->sin_addr.s_addr, | 2782 | * Handle loopback requests to INADDR_ANY. |
2576 | laddr->sin_port, raddr->sin_port, 0); | 2783 | */ |
2577 | if (!rt) { | 2784 | if ((__force int)raddr->sin_addr.s_addr == INADDR_ANY) { |
2785 | err = pick_local_ipaddrs(dev, cm_id); | ||
2786 | if (err) | ||
2787 | goto fail2; | ||
2788 | } | ||
2789 | |||
2790 | /* find a route */ | ||
2791 | PDBG("%s saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n", | ||
2792 | __func__, &laddr->sin_addr, ntohs(laddr->sin_port), | ||
2793 | ra, ntohs(raddr->sin_port)); | ||
2794 | ep->dst = find_route(dev, laddr->sin_addr.s_addr, | ||
2795 | raddr->sin_addr.s_addr, laddr->sin_port, | ||
2796 | raddr->sin_port, 0); | ||
2797 | } else { | ||
2798 | iptype = 6; | ||
2799 | ra = (__u8 *)&raddr6->sin6_addr; | ||
2800 | |||
2801 | /* | ||
2802 | * Handle loopback requests to INADDR_ANY. | ||
2803 | */ | ||
2804 | if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) { | ||
2805 | err = pick_local_ip6addrs(dev, cm_id); | ||
2806 | if (err) | ||
2807 | goto fail2; | ||
2808 | } | ||
2809 | |||
2810 | /* find a route */ | ||
2811 | PDBG("%s saddr %pI6 sport 0x%x raddr %pI6 rport 0x%x\n", | ||
2812 | __func__, laddr6->sin6_addr.s6_addr, | ||
2813 | ntohs(laddr6->sin6_port), | ||
2814 | raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port)); | ||
2815 | ep->dst = find_route6(dev, laddr6->sin6_addr.s6_addr, | ||
2816 | raddr6->sin6_addr.s6_addr, | ||
2817 | laddr6->sin6_port, raddr6->sin6_port, 0, | ||
2818 | raddr6->sin6_scope_id); | ||
2819 | } | ||
2820 | if (!ep->dst) { | ||
2578 | printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); | 2821 | printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); |
2579 | err = -EHOSTUNREACH; | 2822 | err = -EHOSTUNREACH; |
2580 | goto fail3; | 2823 | goto fail3; |
2581 | } | 2824 | } |
2582 | ep->dst = &rt->dst; | ||
2583 | 2825 | ||
2584 | err = import_ep(ep, raddr->sin_addr.s_addr, ep->dst, ep->com.dev, true); | 2826 | err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true); |
2585 | if (err) { | 2827 | if (err) { |
2586 | printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); | 2828 | printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); |
2587 | goto fail4; | 2829 | goto fail4; |
@@ -2616,6 +2858,60 @@ out: | |||
2616 | return err; | 2858 | return err; |
2617 | } | 2859 | } |
2618 | 2860 | ||
2861 | static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) | ||
2862 | { | ||
2863 | int err; | ||
2864 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ep->com.local_addr; | ||
2865 | |||
2866 | c4iw_init_wr_wait(&ep->com.wr_wait); | ||
2867 | err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0], | ||
2868 | ep->stid, &sin6->sin6_addr, | ||
2869 | sin6->sin6_port, | ||
2870 | ep->com.dev->rdev.lldi.rxq_ids[0]); | ||
2871 | if (!err) | ||
2872 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, | ||
2873 | &ep->com.wr_wait, | ||
2874 | 0, 0, __func__); | ||
2875 | if (err) | ||
2876 | pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n", | ||
2877 | err, ep->stid, | ||
2878 | sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port)); | ||
2879 | return err; | ||
2880 | } | ||
2881 | |||
2882 | static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) | ||
2883 | { | ||
2884 | int err; | ||
2885 | struct sockaddr_in *sin = (struct sockaddr_in *)&ep->com.local_addr; | ||
2886 | |||
2887 | if (dev->rdev.lldi.enable_fw_ofld_conn) { | ||
2888 | do { | ||
2889 | err = cxgb4_create_server_filter( | ||
2890 | ep->com.dev->rdev.lldi.ports[0], ep->stid, | ||
2891 | sin->sin_addr.s_addr, sin->sin_port, 0, | ||
2892 | ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0); | ||
2893 | if (err == -EBUSY) { | ||
2894 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2895 | schedule_timeout(usecs_to_jiffies(100)); | ||
2896 | } | ||
2897 | } while (err == -EBUSY); | ||
2898 | } else { | ||
2899 | c4iw_init_wr_wait(&ep->com.wr_wait); | ||
2900 | err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], | ||
2901 | ep->stid, sin->sin_addr.s_addr, sin->sin_port, | ||
2902 | 0, ep->com.dev->rdev.lldi.rxq_ids[0]); | ||
2903 | if (!err) | ||
2904 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, | ||
2905 | &ep->com.wr_wait, | ||
2906 | 0, 0, __func__); | ||
2907 | } | ||
2908 | if (err) | ||
2909 | pr_err("cxgb4_create_server/filter failed err %d stid %d laddr %pI4 lport %d\n" | ||
2910 | , err, ep->stid, | ||
2911 | &sin->sin_addr, ntohs(sin->sin_port)); | ||
2912 | return err; | ||
2913 | } | ||
2914 | |||
2619 | int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) | 2915 | int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) |
2620 | { | 2916 | { |
2621 | int err = 0; | 2917 | int err = 0; |
@@ -2642,9 +2938,11 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
2642 | * Allocate a server TID. | 2938 | * Allocate a server TID. |
2643 | */ | 2939 | */ |
2644 | if (dev->rdev.lldi.enable_fw_ofld_conn) | 2940 | if (dev->rdev.lldi.enable_fw_ofld_conn) |
2645 | ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, PF_INET, ep); | 2941 | ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, |
2942 | cm_id->local_addr.ss_family, ep); | ||
2646 | else | 2943 | else |
2647 | ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, PF_INET, ep); | 2944 | ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, |
2945 | cm_id->local_addr.ss_family, ep); | ||
2648 | 2946 | ||
2649 | if (ep->stid == -1) { | 2947 | if (ep->stid == -1) { |
2650 | printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); | 2948 | printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); |
@@ -2653,43 +2951,16 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
2653 | } | 2951 | } |
2654 | insert_handle(dev, &dev->stid_idr, ep, ep->stid); | 2952 | insert_handle(dev, &dev->stid_idr, ep, ep->stid); |
2655 | state_set(&ep->com, LISTEN); | 2953 | state_set(&ep->com, LISTEN); |
2656 | if (dev->rdev.lldi.enable_fw_ofld_conn) { | 2954 | if (ep->com.local_addr.ss_family == AF_INET) |
2657 | do { | 2955 | err = create_server4(dev, ep); |
2658 | err = cxgb4_create_server_filter( | 2956 | else |
2659 | ep->com.dev->rdev.lldi.ports[0], ep->stid, | 2957 | err = create_server6(dev, ep); |
2660 | ep->com.local_addr.sin_addr.s_addr, | ||
2661 | ep->com.local_addr.sin_port, | ||
2662 | 0, | ||
2663 | ep->com.dev->rdev.lldi.rxq_ids[0], | ||
2664 | 0, | ||
2665 | 0); | ||
2666 | if (err == -EBUSY) { | ||
2667 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2668 | schedule_timeout(usecs_to_jiffies(100)); | ||
2669 | } | ||
2670 | } while (err == -EBUSY); | ||
2671 | } else { | ||
2672 | c4iw_init_wr_wait(&ep->com.wr_wait); | ||
2673 | err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], | ||
2674 | ep->stid, ep->com.local_addr.sin_addr.s_addr, | ||
2675 | ep->com.local_addr.sin_port, | ||
2676 | 0, | ||
2677 | ep->com.dev->rdev.lldi.rxq_ids[0]); | ||
2678 | if (!err) | ||
2679 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, | ||
2680 | &ep->com.wr_wait, | ||
2681 | 0, 0, __func__); | ||
2682 | } | ||
2683 | if (!err) { | 2958 | if (!err) { |
2684 | cm_id->provider_data = ep; | 2959 | cm_id->provider_data = ep; |
2685 | goto out; | 2960 | goto out; |
2686 | } | 2961 | } |
2687 | pr_err("%s cxgb4_create_server/filter failed err %d " \ | 2962 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, |
2688 | "stid %d laddr %08x lport %d\n", \ | 2963 | ep->com.local_addr.ss_family); |
2689 | __func__, err, ep->stid, | ||
2690 | ntohl(ep->com.local_addr.sin_addr.s_addr), | ||
2691 | ntohs(ep->com.local_addr.sin_port)); | ||
2692 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET); | ||
2693 | fail2: | 2964 | fail2: |
2694 | cm_id->rem_ref(cm_id); | 2965 | cm_id->rem_ref(cm_id); |
2695 | c4iw_put_ep(&ep->com); | 2966 | c4iw_put_ep(&ep->com); |
@@ -2707,20 +2978,24 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id) | |||
2707 | 2978 | ||
2708 | might_sleep(); | 2979 | might_sleep(); |
2709 | state_set(&ep->com, DEAD); | 2980 | state_set(&ep->com, DEAD); |
2710 | if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn) { | 2981 | if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn && |
2982 | ep->com.local_addr.ss_family == AF_INET) { | ||
2711 | err = cxgb4_remove_server_filter( | 2983 | err = cxgb4_remove_server_filter( |
2712 | ep->com.dev->rdev.lldi.ports[0], ep->stid, | 2984 | ep->com.dev->rdev.lldi.ports[0], ep->stid, |
2713 | ep->com.dev->rdev.lldi.rxq_ids[0], 0); | 2985 | ep->com.dev->rdev.lldi.rxq_ids[0], 0); |
2714 | } else { | 2986 | } else { |
2715 | c4iw_init_wr_wait(&ep->com.wr_wait); | 2987 | c4iw_init_wr_wait(&ep->com.wr_wait); |
2716 | err = listen_stop(ep); | 2988 | err = cxgb4_remove_server( |
2989 | ep->com.dev->rdev.lldi.ports[0], ep->stid, | ||
2990 | ep->com.dev->rdev.lldi.rxq_ids[0], 0); | ||
2717 | if (err) | 2991 | if (err) |
2718 | goto done; | 2992 | goto done; |
2719 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, | 2993 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, |
2720 | 0, 0, __func__); | 2994 | 0, 0, __func__); |
2721 | } | 2995 | } |
2722 | remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid); | 2996 | remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid); |
2723 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET); | 2997 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, |
2998 | ep->com.local_addr.ss_family); | ||
2724 | done: | 2999 | done: |
2725 | cm_id->rem_ref(cm_id); | 3000 | cm_id->rem_ref(cm_id); |
2726 | c4iw_put_ep(&ep->com); | 3001 | c4iw_put_ep(&ep->com); |
@@ -3024,7 +3299,6 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) | |||
3024 | struct cpl_pass_accept_req *req = (void *)(rss + 1); | 3299 | struct cpl_pass_accept_req *req = (void *)(rss + 1); |
3025 | struct l2t_entry *e; | 3300 | struct l2t_entry *e; |
3026 | struct dst_entry *dst; | 3301 | struct dst_entry *dst; |
3027 | struct rtable *rt; | ||
3028 | struct c4iw_ep *lep; | 3302 | struct c4iw_ep *lep; |
3029 | u16 window; | 3303 | u16 window; |
3030 | struct port_info *pi; | 3304 | struct port_info *pi; |
@@ -3082,14 +3356,13 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) | |||
3082 | ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), | 3356 | ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), |
3083 | ntohs(tcph->source), iph->tos); | 3357 | ntohs(tcph->source), iph->tos); |
3084 | 3358 | ||
3085 | rt = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source, | 3359 | dst = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source, |
3086 | iph->tos); | 3360 | iph->tos); |
3087 | if (!rt) { | 3361 | if (!dst) { |
3088 | pr_err("%s - failed to find dst entry!\n", | 3362 | pr_err("%s - failed to find dst entry!\n", |
3089 | __func__); | 3363 | __func__); |
3090 | goto reject; | 3364 | goto reject; |
3091 | } | 3365 | } |
3092 | dst = &rt->dst; | ||
3093 | neigh = dst_neigh_lookup_skb(dst, skb); | 3366 | neigh = dst_neigh_lookup_skb(dst, skb); |
3094 | 3367 | ||
3095 | if (!neigh) { | 3368 | if (!neigh) { |
@@ -3106,10 +3379,11 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) | |||
3106 | tx_chan = cxgb4_port_chan(pdev); | 3379 | tx_chan = cxgb4_port_chan(pdev); |
3107 | dev_put(pdev); | 3380 | dev_put(pdev); |
3108 | } else { | 3381 | } else { |
3382 | pdev = get_real_dev(neigh->dev); | ||
3109 | e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, | 3383 | e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, |
3110 | neigh->dev, 0); | 3384 | pdev, 0); |
3111 | pi = (struct port_info *)netdev_priv(neigh->dev); | 3385 | pi = (struct port_info *)netdev_priv(pdev); |
3112 | tx_chan = cxgb4_port_chan(neigh->dev); | 3386 | tx_chan = cxgb4_port_chan(pdev); |
3113 | } | 3387 | } |
3114 | if (!e) { | 3388 | if (!e) { |
3115 | pr_err("%s - failed to allocate l2t entry!\n", | 3389 | pr_err("%s - failed to allocate l2t entry!\n", |
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index ae656016e1ae..33d2cc6ab562 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c | |||
@@ -103,18 +103,43 @@ static int dump_qp(int id, void *p, void *data) | |||
103 | if (space == 0) | 103 | if (space == 0) |
104 | return 1; | 104 | return 1; |
105 | 105 | ||
106 | if (qp->ep) | 106 | if (qp->ep) { |
107 | cc = snprintf(qpd->buf + qpd->pos, space, | 107 | if (qp->ep->com.local_addr.ss_family == AF_INET) { |
108 | "qp sq id %u rq id %u state %u onchip %u " | 108 | struct sockaddr_in *lsin = (struct sockaddr_in *) |
109 | "ep tid %u state %u %pI4:%u->%pI4:%u\n", | 109 | &qp->ep->com.local_addr; |
110 | qp->wq.sq.qid, qp->wq.rq.qid, (int)qp->attr.state, | 110 | struct sockaddr_in *rsin = (struct sockaddr_in *) |
111 | qp->wq.sq.flags & T4_SQ_ONCHIP, | 111 | &qp->ep->com.remote_addr; |
112 | qp->ep->hwtid, (int)qp->ep->com.state, | 112 | |
113 | &qp->ep->com.local_addr.sin_addr.s_addr, | 113 | cc = snprintf(qpd->buf + qpd->pos, space, |
114 | ntohs(qp->ep->com.local_addr.sin_port), | 114 | "rc qp sq id %u rq id %u state %u " |
115 | &qp->ep->com.remote_addr.sin_addr.s_addr, | 115 | "onchip %u ep tid %u state %u " |
116 | ntohs(qp->ep->com.remote_addr.sin_port)); | 116 | "%pI4:%u->%pI4:%u\n", |
117 | else | 117 | qp->wq.sq.qid, qp->wq.rq.qid, |
118 | (int)qp->attr.state, | ||
119 | qp->wq.sq.flags & T4_SQ_ONCHIP, | ||
120 | qp->ep->hwtid, (int)qp->ep->com.state, | ||
121 | &lsin->sin_addr, ntohs(lsin->sin_port), | ||
122 | &rsin->sin_addr, ntohs(rsin->sin_port)); | ||
123 | } else { | ||
124 | struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *) | ||
125 | &qp->ep->com.local_addr; | ||
126 | struct sockaddr_in6 *rsin6 = (struct sockaddr_in6 *) | ||
127 | &qp->ep->com.remote_addr; | ||
128 | |||
129 | cc = snprintf(qpd->buf + qpd->pos, space, | ||
130 | "rc qp sq id %u rq id %u state %u " | ||
131 | "onchip %u ep tid %u state %u " | ||
132 | "%pI6:%u->%pI6:%u\n", | ||
133 | qp->wq.sq.qid, qp->wq.rq.qid, | ||
134 | (int)qp->attr.state, | ||
135 | qp->wq.sq.flags & T4_SQ_ONCHIP, | ||
136 | qp->ep->hwtid, (int)qp->ep->com.state, | ||
137 | &lsin6->sin6_addr, | ||
138 | ntohs(lsin6->sin6_port), | ||
139 | &rsin6->sin6_addr, | ||
140 | ntohs(rsin6->sin6_port)); | ||
141 | } | ||
142 | } else | ||
118 | cc = snprintf(qpd->buf + qpd->pos, space, | 143 | cc = snprintf(qpd->buf + qpd->pos, space, |
119 | "qp sq id %u rq id %u state %u onchip %u\n", | 144 | "qp sq id %u rq id %u state %u onchip %u\n", |
120 | qp->wq.sq.qid, qp->wq.rq.qid, | 145 | qp->wq.sq.qid, qp->wq.rq.qid, |
@@ -351,15 +376,37 @@ static int dump_ep(int id, void *p, void *data) | |||
351 | if (space == 0) | 376 | if (space == 0) |
352 | return 1; | 377 | return 1; |
353 | 378 | ||
354 | cc = snprintf(epd->buf + epd->pos, space, | 379 | if (ep->com.local_addr.ss_family == AF_INET) { |
355 | "ep %p cm_id %p qp %p state %d flags 0x%lx history 0x%lx " | 380 | struct sockaddr_in *lsin = (struct sockaddr_in *) |
356 | "hwtid %d atid %d %pI4:%d <-> %pI4:%d\n", | 381 | &ep->com.local_addr; |
357 | ep, ep->com.cm_id, ep->com.qp, (int)ep->com.state, | 382 | struct sockaddr_in *rsin = (struct sockaddr_in *) |
358 | ep->com.flags, ep->com.history, ep->hwtid, ep->atid, | 383 | &ep->com.remote_addr; |
359 | &ep->com.local_addr.sin_addr.s_addr, | 384 | |
360 | ntohs(ep->com.local_addr.sin_port), | 385 | cc = snprintf(epd->buf + epd->pos, space, |
361 | &ep->com.remote_addr.sin_addr.s_addr, | 386 | "ep %p cm_id %p qp %p state %d flags 0x%lx " |
362 | ntohs(ep->com.remote_addr.sin_port)); | 387 | "history 0x%lx hwtid %d atid %d " |
388 | "%pI4:%d <-> %pI4:%d\n", | ||
389 | ep, ep->com.cm_id, ep->com.qp, | ||
390 | (int)ep->com.state, ep->com.flags, | ||
391 | ep->com.history, ep->hwtid, ep->atid, | ||
392 | &lsin->sin_addr, ntohs(lsin->sin_port), | ||
393 | &rsin->sin_addr, ntohs(rsin->sin_port)); | ||
394 | } else { | ||
395 | struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *) | ||
396 | &ep->com.local_addr; | ||
397 | struct sockaddr_in6 *rsin6 = (struct sockaddr_in6 *) | ||
398 | &ep->com.remote_addr; | ||
399 | |||
400 | cc = snprintf(epd->buf + epd->pos, space, | ||
401 | "ep %p cm_id %p qp %p state %d flags 0x%lx " | ||
402 | "history 0x%lx hwtid %d atid %d " | ||
403 | "%pI6:%d <-> %pI6:%d\n", | ||
404 | ep, ep->com.cm_id, ep->com.qp, | ||
405 | (int)ep->com.state, ep->com.flags, | ||
406 | ep->com.history, ep->hwtid, ep->atid, | ||
407 | &lsin6->sin6_addr, ntohs(lsin6->sin6_port), | ||
408 | &rsin6->sin6_addr, ntohs(rsin6->sin6_port)); | ||
409 | } | ||
363 | if (cc < space) | 410 | if (cc < space) |
364 | epd->pos += cc; | 411 | epd->pos += cc; |
365 | return 0; | 412 | return 0; |
@@ -376,12 +423,27 @@ static int dump_listen_ep(int id, void *p, void *data) | |||
376 | if (space == 0) | 423 | if (space == 0) |
377 | return 1; | 424 | return 1; |
378 | 425 | ||
379 | cc = snprintf(epd->buf + epd->pos, space, | 426 | if (ep->com.local_addr.ss_family == AF_INET) { |
380 | "ep %p cm_id %p state %d flags 0x%lx stid %d backlog %d " | 427 | struct sockaddr_in *lsin = (struct sockaddr_in *) |
381 | "%pI4:%d\n", ep, ep->com.cm_id, (int)ep->com.state, | 428 | &ep->com.local_addr; |
382 | ep->com.flags, ep->stid, ep->backlog, | 429 | |
383 | &ep->com.local_addr.sin_addr.s_addr, | 430 | cc = snprintf(epd->buf + epd->pos, space, |
384 | ntohs(ep->com.local_addr.sin_port)); | 431 | "ep %p cm_id %p state %d flags 0x%lx stid %d " |
432 | "backlog %d %pI4:%d\n", | ||
433 | ep, ep->com.cm_id, (int)ep->com.state, | ||
434 | ep->com.flags, ep->stid, ep->backlog, | ||
435 | &lsin->sin_addr, ntohs(lsin->sin_port)); | ||
436 | } else { | ||
437 | struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *) | ||
438 | &ep->com.local_addr; | ||
439 | |||
440 | cc = snprintf(epd->buf + epd->pos, space, | ||
441 | "ep %p cm_id %p state %d flags 0x%lx stid %d " | ||
442 | "backlog %d %pI6:%d\n", | ||
443 | ep, ep->com.cm_id, (int)ep->com.state, | ||
444 | ep->com.flags, ep->stid, ep->backlog, | ||
445 | &lsin6->sin6_addr, ntohs(lsin6->sin6_port)); | ||
446 | } | ||
385 | if (cc < space) | 447 | if (cc < space) |
386 | epd->pos += cc; | 448 | epd->pos += cc; |
387 | return 0; | 449 | return 0; |
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 485183ad34cd..b3cae9f4c80e 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
@@ -752,8 +752,8 @@ struct c4iw_ep_common { | |||
752 | enum c4iw_ep_state state; | 752 | enum c4iw_ep_state state; |
753 | struct kref kref; | 753 | struct kref kref; |
754 | struct mutex mutex; | 754 | struct mutex mutex; |
755 | struct sockaddr_in local_addr; | 755 | struct sockaddr_storage local_addr; |
756 | struct sockaddr_in remote_addr; | 756 | struct sockaddr_storage remote_addr; |
757 | struct c4iw_wr_wait wr_wait; | 757 | struct c4iw_wr_wait wr_wait; |
758 | unsigned long flags; | 758 | unsigned long flags; |
759 | unsigned long history; | 759 | unsigned long history; |