aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb4
diff options
context:
space:
mode:
authorVipul Pandya <vipul@chelsio.com>2012-12-10 04:30:54 -0500
committerRoland Dreier <roland@purestorage.com>2012-12-20 02:02:43 -0500
commit5be78ee924ae8fb2b4a5b8d012a7d003849337ee (patch)
treef1ca2268c5e752401e5cac097460c4fa19b0fa0c /drivers/infiniband/hw/cxgb4
parentdca4faeb812f665dab0607d8e0660ae564387186 (diff)
RDMA/cxgb4: Fix LE hash collision bug for active open connection
It enables establishing active open connection using fw_ofld_connection work request when cpl_act_open_rpl says TCAM full error which may be because of LE hash collision. Current support is only for IPv4 active open connections. Sets ntuple bits in active open requests. For T4 firmware greater than 1.4.10.0 ntuple bits are required to be set. Adds nocong and enable_ecn module parameter options. Signed-off-by: Vipul Pandya <vipul@chelsio.com> [ Move all FW return values to t4fw_api.h. - Roland ] Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb4')
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c158
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h1
2 files changed, 153 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 5de86968379d..4878704b6d70 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -61,6 +61,14 @@ static char *states[] = {
61 NULL, 61 NULL,
62}; 62};
63 63
64static int nocong;
65module_param(nocong, int, 0644);
66MODULE_PARM_DESC(nocong, "Turn of congestion control (default=0)");
67
68static int enable_ecn;
69module_param(enable_ecn, int, 0644);
70MODULE_PARM_DESC(enable_ecn, "Enable ECN (default=0/disabled)");
71
64static int dack_mode = 1; 72static int dack_mode = 1;
65module_param(dack_mode, int, 0644); 73module_param(dack_mode, int, 0644);
66MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)"); 74MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
@@ -441,6 +449,50 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
441 return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 449 return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
442} 450}
443 451
452#define VLAN_NONE 0xfff
453#define FILTER_SEL_VLAN_NONE 0xffff
454#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
455#define FILTER_SEL_WIDTH_VIN_P_FC \
456 (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
457#define FILTER_SEL_WIDTH_TAG_P_FC \
458 (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
459#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
460
461static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
462 struct l2t_entry *l2t)
463{
464 unsigned int ntuple = 0;
465 u32 viid;
466
467 switch (dev->rdev.lldi.filt_mode) {
468
469 /* default filter mode */
470 case HW_TPL_FR_MT_PR_IV_P_FC:
471 if (l2t->vlan == VLAN_NONE)
472 ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
473 else {
474 ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
475 ntuple |= 1 << FILTER_SEL_WIDTH_VLD_TAG_P_FC;
476 }
477 ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
478 FILTER_SEL_WIDTH_VLD_TAG_P_FC;
479 break;
480 case HW_TPL_FR_MT_PR_OV_P_FC: {
481 viid = cxgb4_port_viid(l2t->neigh->dev);
482
483 ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
484 ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
485 ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
486 ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
487 FILTER_SEL_WIDTH_VLD_TAG_P_FC;
488 break;
489 }
490 default:
491 break;
492 }
493 return ntuple;
494}
495
444static int send_connect(struct c4iw_ep *ep) 496static int send_connect(struct c4iw_ep *ep)
445{ 497{
446 struct cpl_act_open_req *req; 498 struct cpl_act_open_req *req;
@@ -463,7 +515,8 @@ static int send_connect(struct c4iw_ep *ep)
463 515
464 cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx); 516 cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
465 wscale = compute_wscale(rcv_win); 517 wscale = compute_wscale(rcv_win);
466 opt0 = KEEP_ALIVE(1) | 518 opt0 = (nocong ? NO_CONG(1) : 0) |
519 KEEP_ALIVE(1) |
467 DELACK(1) | 520 DELACK(1) |
468 WND_SCALE(wscale) | 521 WND_SCALE(wscale) |
469 MSS_IDX(mtu_idx) | 522 MSS_IDX(mtu_idx) |
@@ -474,6 +527,7 @@ static int send_connect(struct c4iw_ep *ep)
474 ULP_MODE(ULP_MODE_TCPDDP) | 527 ULP_MODE(ULP_MODE_TCPDDP) |
475 RCV_BUFSIZ(rcv_win>>10); 528 RCV_BUFSIZ(rcv_win>>10);
476 opt2 = RX_CHANNEL(0) | 529 opt2 = RX_CHANNEL(0) |
530 CCTRL_ECN(enable_ecn) |
477 RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); 531 RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
478 if (enable_tcp_timestamps) 532 if (enable_tcp_timestamps)
479 opt2 |= TSTAMPS_EN(1); 533 opt2 |= TSTAMPS_EN(1);
@@ -492,7 +546,7 @@ static int send_connect(struct c4iw_ep *ep)
492 req->local_ip = ep->com.local_addr.sin_addr.s_addr; 546 req->local_ip = ep->com.local_addr.sin_addr.s_addr;
493 req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; 547 req->peer_ip = ep->com.remote_addr.sin_addr.s_addr;
494 req->opt0 = cpu_to_be64(opt0); 548 req->opt0 = cpu_to_be64(opt0);
495 req->params = 0; 549 req->params = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, ep->l2t));
496 req->opt2 = cpu_to_be32(opt2); 550 req->opt2 = cpu_to_be32(opt2);
497 return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 551 return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
498} 552}
@@ -1383,6 +1437,61 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
1383 return 0; 1437 return 0;
1384} 1438}
1385 1439
1440static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
1441{
1442 struct sk_buff *skb;
1443 struct fw_ofld_connection_wr *req;
1444 unsigned int mtu_idx;
1445 int wscale;
1446
1447 skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
1448 req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req));
1449 memset(req, 0, sizeof(*req));
1450 req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
1451 req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
1452 req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
1453 ep->l2t));
1454 req->le.lport = ep->com.local_addr.sin_port;
1455 req->le.pport = ep->com.remote_addr.sin_port;
1456 req->le.u.ipv4.lip = ep->com.local_addr.sin_addr.s_addr;
1457 req->le.u.ipv4.pip = ep->com.remote_addr.sin_addr.s_addr;
1458 req->tcb.t_state_to_astid =
1459 htonl(V_FW_OFLD_CONNECTION_WR_T_STATE(TCP_SYN_SENT) |
1460 V_FW_OFLD_CONNECTION_WR_ASTID(atid));
1461 req->tcb.cplrxdataack_cplpassacceptrpl =
1462 htons(F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK);
1463 req->tcb.tx_max = jiffies;
1464 cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
1465 wscale = compute_wscale(rcv_win);
1466 req->tcb.opt0 = TCAM_BYPASS(1) |
1467 (nocong ? NO_CONG(1) : 0) |
1468 KEEP_ALIVE(1) |
1469 DELACK(1) |
1470 WND_SCALE(wscale) |
1471 MSS_IDX(mtu_idx) |
1472 L2T_IDX(ep->l2t->idx) |
1473 TX_CHAN(ep->tx_chan) |
1474 SMAC_SEL(ep->smac_idx) |
1475 DSCP(ep->tos) |
1476 ULP_MODE(ULP_MODE_TCPDDP) |
1477 RCV_BUFSIZ(rcv_win >> 10);
1478 req->tcb.opt2 = PACE(1) |
1479 TX_QUEUE(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) |
1480 RX_CHANNEL(0) |
1481 CCTRL_ECN(enable_ecn) |
1482 RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
1483 if (enable_tcp_timestamps)
1484 req->tcb.opt2 |= TSTAMPS_EN(1);
1485 if (enable_tcp_sack)
1486 req->tcb.opt2 |= SACK_EN(1);
1487 if (wscale && enable_tcp_window_scaling)
1488 req->tcb.opt2 |= WND_SCALE_EN(1);
1489 req->tcb.opt0 = cpu_to_be64(req->tcb.opt0);
1490 req->tcb.opt2 = cpu_to_be32(req->tcb.opt2);
1491 set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
1492 c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
1493}
1494
1386/* 1495/*
1387 * Return whether a failed active open has allocated a TID 1496 * Return whether a failed active open has allocated a TID
1388 */ 1497 */
@@ -1419,6 +1528,14 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
1419 case CPL_ERR_CONN_RESET: 1528 case CPL_ERR_CONN_RESET:
1420 case CPL_ERR_CONN_TIMEDOUT: 1529 case CPL_ERR_CONN_TIMEDOUT:
1421 break; 1530 break;
1531 case CPL_ERR_TCAM_FULL:
1532 mutex_lock(&dev->rdev.stats.lock);
1533 dev->rdev.stats.tcam_full++;
1534 mutex_unlock(&dev->rdev.stats.lock);
1535 send_fw_act_open_req(ep,
1536 GET_TID_TID(GET_AOPEN_ATID(ntohl(rpl->atid_status))));
1537 return 0;
1538 break;
1422 default: 1539 default:
1423 printk(KERN_INFO MOD "Active open failure - " 1540 printk(KERN_INFO MOD "Active open failure - "
1424 "atid %u status %u errno %d %pI4:%u->%pI4:%u\n", 1541 "atid %u status %u errno %d %pI4:%u->%pI4:%u\n",
@@ -1510,14 +1627,15 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb,
1510 skb_get(skb); 1627 skb_get(skb);
1511 cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx); 1628 cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
1512 wscale = compute_wscale(rcv_win); 1629 wscale = compute_wscale(rcv_win);
1513 opt0 = KEEP_ALIVE(1) | 1630 opt0 = (nocong ? NO_CONG(1) : 0) |
1631 KEEP_ALIVE(1) |
1514 DELACK(1) | 1632 DELACK(1) |
1515 WND_SCALE(wscale) | 1633 WND_SCALE(wscale) |
1516 MSS_IDX(mtu_idx) | 1634 MSS_IDX(mtu_idx) |
1517 L2T_IDX(ep->l2t->idx) | 1635 L2T_IDX(ep->l2t->idx) |
1518 TX_CHAN(ep->tx_chan) | 1636 TX_CHAN(ep->tx_chan) |
1519 SMAC_SEL(ep->smac_idx) | 1637 SMAC_SEL(ep->smac_idx) |
1520 DSCP(ep->tos) | 1638 DSCP(ep->tos >> 2) |
1521 ULP_MODE(ULP_MODE_TCPDDP) | 1639 ULP_MODE(ULP_MODE_TCPDDP) |
1522 RCV_BUFSIZ(rcv_win>>10); 1640 RCV_BUFSIZ(rcv_win>>10);
1523 opt2 = RX_CHANNEL(0) | 1641 opt2 = RX_CHANNEL(0) |
@@ -1529,6 +1647,15 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb,
1529 opt2 |= SACK_EN(1); 1647 opt2 |= SACK_EN(1);
1530 if (wscale && enable_tcp_window_scaling) 1648 if (wscale && enable_tcp_window_scaling)
1531 opt2 |= WND_SCALE_EN(1); 1649 opt2 |= WND_SCALE_EN(1);
1650 if (enable_ecn) {
1651 const struct tcphdr *tcph;
1652 u32 hlen = ntohl(req->hdr_len);
1653
1654 tcph = (const void *)(req + 1) + G_ETH_HDR_LEN(hlen) +
1655 G_IP_HDR_LEN(hlen);
1656 if (tcph->ece && tcph->cwr)
1657 opt2 |= CCTRL_ECN(1);
1658 }
1532 1659
1533 rpl = cplhdr(skb); 1660 rpl = cplhdr(skb);
1534 INIT_TP_WR(rpl, ep->hwtid); 1661 INIT_TP_WR(rpl, ep->hwtid);
@@ -2647,11 +2774,14 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
2647 struct cpl_fw6_msg *rpl = cplhdr(skb); 2774 struct cpl_fw6_msg *rpl = cplhdr(skb);
2648 struct c4iw_wr_wait *wr_waitp; 2775 struct c4iw_wr_wait *wr_waitp;
2649 int ret; 2776 int ret;
2777 u8 opcode;
2778 struct cpl_fw6_msg_ofld_connection_wr_rpl *req;
2779 struct c4iw_ep *ep;
2650 2780
2651 PDBG("%s type %u\n", __func__, rpl->type); 2781 PDBG("%s type %u\n", __func__, rpl->type);
2652 2782
2653 switch (rpl->type) { 2783 switch (rpl->type) {
2654 case 1: 2784 case FW6_TYPE_WR_RPL:
2655 ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); 2785 ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff);
2656 wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; 2786 wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1];
2657 PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret); 2787 PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret);
@@ -2659,9 +2789,25 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
2659 c4iw_wake_up(wr_waitp, ret ? -ret : 0); 2789 c4iw_wake_up(wr_waitp, ret ? -ret : 0);
2660 kfree_skb(skb); 2790 kfree_skb(skb);
2661 break; 2791 break;
2662 case 2: 2792 case FW6_TYPE_CQE:
2663 sched(dev, skb); 2793 sched(dev, skb);
2664 break; 2794 break;
2795 case FW6_TYPE_OFLD_CONNECTION_WR_RPL:
2796 opcode = *(const u8 *)rpl->data;
2797 if (opcode == FW_OFLD_CONNECTION_WR) {
2798 req =
2799 (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data;
2800 if (req->t_state == TCP_SYN_SENT
2801 && (req->retval == FW_ENOMEM
2802 || req->retval == FW_EADDRINUSE)) {
2803 ep = (struct c4iw_ep *)
2804 lookup_atid(dev->rdev.lldi.tids,
2805 req->tid);
2806 c4iw_l2t_send(&dev->rdev, skb, ep->l2t);
2807 return 0;
2808 }
2809 }
2810 break;
2665 default: 2811 default:
2666 printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__, 2812 printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__,
2667 rpl->type); 2813 rpl->type);
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 9beb3a9f0336..6a17fde51eae 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -130,6 +130,7 @@ struct c4iw_stats {
130 u64 db_empty; 130 u64 db_empty;
131 u64 db_drop; 131 u64 db_drop;
132 u64 db_state_transitions; 132 u64 db_state_transitions;
133 u64 tcam_full;
133}; 134};
134 135
135struct c4iw_rdev { 136struct c4iw_rdev {