diff options
author | Hariprasad Shenai <hariprasad@chelsio.com> | 2014-06-06 12:10:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-11 01:49:54 -0400 |
commit | b408ff282dda0ef7a3218dc2e5f1399c665d4c20 (patch) | |
tree | db6345f88bce49d2801cafc38031f5f97cbf4e49 | |
parent | 92e7ae71726ca9e16a8a88ebeee14eb5177575a1 (diff) |
iw_cxgb4: don't truncate the recv window size
Fixed a bug that shows up with recv window sizes that exceed the size of
the RCV_BUFSIZ field in opt0 (>= 1024K). If the recv window exceeds
this, then we specify the max possible in opt0, add add the rest in via
a RX_DATA_ACK credits.
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cm.c | 54 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 1 |
3 files changed, 53 insertions, 4 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index d2e9f72ec9bf..965eaafd5851 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -472,7 +472,7 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) | |||
472 | flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT; | 472 | flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT; |
473 | flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq); | 473 | flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq); |
474 | flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF; | 474 | flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF; |
475 | flowc->mnemval[6].val = cpu_to_be32(snd_win); | 475 | flowc->mnemval[6].val = cpu_to_be32(ep->snd_win); |
476 | flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; | 476 | flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; |
477 | flowc->mnemval[7].val = cpu_to_be32(ep->emss); | 477 | flowc->mnemval[7].val = cpu_to_be32(ep->emss); |
478 | /* Pad WR to 16 byte boundary */ | 478 | /* Pad WR to 16 byte boundary */ |
@@ -565,6 +565,7 @@ static int send_connect(struct c4iw_ep *ep) | |||
565 | struct sockaddr_in *ra = (struct sockaddr_in *)&ep->com.remote_addr; | 565 | struct sockaddr_in *ra = (struct sockaddr_in *)&ep->com.remote_addr; |
566 | struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&ep->com.local_addr; | 566 | struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&ep->com.local_addr; |
567 | struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; | 567 | struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; |
568 | int win; | ||
568 | 569 | ||
569 | wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? | 570 | wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? |
570 | roundup(sizev4, 16) : | 571 | roundup(sizev4, 16) : |
@@ -583,6 +584,15 @@ static int send_connect(struct c4iw_ep *ep) | |||
583 | best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, | 584 | best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, |
584 | enable_tcp_timestamps); | 585 | enable_tcp_timestamps); |
585 | wscale = compute_wscale(rcv_win); | 586 | wscale = compute_wscale(rcv_win); |
587 | |||
588 | /* | ||
589 | * Specify the largest window that will fit in opt0. The | ||
590 | * remainder will be specified in the rx_data_ack. | ||
591 | */ | ||
592 | win = ep->rcv_win >> 10; | ||
593 | if (win > RCV_BUFSIZ_MASK) | ||
594 | win = RCV_BUFSIZ_MASK; | ||
595 | |||
586 | opt0 = (nocong ? NO_CONG(1) : 0) | | 596 | opt0 = (nocong ? NO_CONG(1) : 0) | |
587 | KEEP_ALIVE(1) | | 597 | KEEP_ALIVE(1) | |
588 | DELACK(1) | | 598 | DELACK(1) | |
@@ -593,7 +603,7 @@ static int send_connect(struct c4iw_ep *ep) | |||
593 | SMAC_SEL(ep->smac_idx) | | 603 | SMAC_SEL(ep->smac_idx) | |
594 | DSCP(ep->tos) | | 604 | DSCP(ep->tos) | |
595 | ULP_MODE(ULP_MODE_TCPDDP) | | 605 | ULP_MODE(ULP_MODE_TCPDDP) | |
596 | RCV_BUFSIZ(rcv_win>>10); | 606 | RCV_BUFSIZ(win); |
597 | opt2 = RX_CHANNEL(0) | | 607 | opt2 = RX_CHANNEL(0) | |
598 | CCTRL_ECN(enable_ecn) | | 608 | CCTRL_ECN(enable_ecn) | |
599 | RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); | 609 | RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); |
@@ -1174,6 +1184,14 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits) | |||
1174 | return 0; | 1184 | return 0; |
1175 | } | 1185 | } |
1176 | 1186 | ||
1187 | /* | ||
1188 | * If we couldn't specify the entire rcv window at connection setup | ||
1189 | * due to the limit in the number of bits in the RCV_BUFSIZ field, | ||
1190 | * then add the overage in to the credits returned. | ||
1191 | */ | ||
1192 | if (ep->rcv_win > RCV_BUFSIZ_MASK * 1024) | ||
1193 | credits += ep->rcv_win - RCV_BUFSIZ_MASK * 1024; | ||
1194 | |||
1177 | req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen); | 1195 | req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen); |
1178 | memset(req, 0, wrlen); | 1196 | memset(req, 0, wrlen); |
1179 | INIT_TP_WR(req, ep->hwtid); | 1197 | INIT_TP_WR(req, ep->hwtid); |
@@ -1647,6 +1665,7 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) | |||
1647 | unsigned int mtu_idx; | 1665 | unsigned int mtu_idx; |
1648 | int wscale; | 1666 | int wscale; |
1649 | struct sockaddr_in *sin; | 1667 | struct sockaddr_in *sin; |
1668 | int win; | ||
1650 | 1669 | ||
1651 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); | 1670 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); |
1652 | req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); | 1671 | req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); |
@@ -1672,6 +1691,15 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) | |||
1672 | best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, | 1691 | best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, |
1673 | enable_tcp_timestamps); | 1692 | enable_tcp_timestamps); |
1674 | wscale = compute_wscale(rcv_win); | 1693 | wscale = compute_wscale(rcv_win); |
1694 | |||
1695 | /* | ||
1696 | * Specify the largest window that will fit in opt0. The | ||
1697 | * remainder will be specified in the rx_data_ack. | ||
1698 | */ | ||
1699 | win = ep->rcv_win >> 10; | ||
1700 | if (win > RCV_BUFSIZ_MASK) | ||
1701 | win = RCV_BUFSIZ_MASK; | ||
1702 | |||
1675 | req->tcb.opt0 = (__force __be64) (TCAM_BYPASS(1) | | 1703 | req->tcb.opt0 = (__force __be64) (TCAM_BYPASS(1) | |
1676 | (nocong ? NO_CONG(1) : 0) | | 1704 | (nocong ? NO_CONG(1) : 0) | |
1677 | KEEP_ALIVE(1) | | 1705 | KEEP_ALIVE(1) | |
@@ -1683,7 +1711,7 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) | |||
1683 | SMAC_SEL(ep->smac_idx) | | 1711 | SMAC_SEL(ep->smac_idx) | |
1684 | DSCP(ep->tos) | | 1712 | DSCP(ep->tos) | |
1685 | ULP_MODE(ULP_MODE_TCPDDP) | | 1713 | ULP_MODE(ULP_MODE_TCPDDP) | |
1686 | RCV_BUFSIZ(rcv_win >> 10)); | 1714 | RCV_BUFSIZ(win)); |
1687 | req->tcb.opt2 = (__force __be32) (PACE(1) | | 1715 | req->tcb.opt2 = (__force __be32) (PACE(1) | |
1688 | TX_QUEUE(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | | 1716 | TX_QUEUE(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | |
1689 | RX_CHANNEL(0) | | 1717 | RX_CHANNEL(0) | |
@@ -1720,6 +1748,13 @@ static int is_neg_adv(unsigned int status) | |||
1720 | status == CPL_ERR_KEEPALV_NEG_ADVICE; | 1748 | status == CPL_ERR_KEEPALV_NEG_ADVICE; |
1721 | } | 1749 | } |
1722 | 1750 | ||
1751 | static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi) | ||
1752 | { | ||
1753 | ep->snd_win = snd_win; | ||
1754 | ep->rcv_win = rcv_win; | ||
1755 | PDBG("%s snd_win %d rcv_win %d\n", __func__, ep->snd_win, ep->rcv_win); | ||
1756 | } | ||
1757 | |||
1723 | #define ACT_OPEN_RETRY_COUNT 2 | 1758 | #define ACT_OPEN_RETRY_COUNT 2 |
1724 | 1759 | ||
1725 | static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, | 1760 | static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, |
@@ -1768,6 +1803,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, | |||
1768 | ep->ctrlq_idx = cxgb4_port_idx(pdev); | 1803 | ep->ctrlq_idx = cxgb4_port_idx(pdev); |
1769 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ | 1804 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ |
1770 | cxgb4_port_idx(pdev) * step]; | 1805 | cxgb4_port_idx(pdev) * step]; |
1806 | set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); | ||
1771 | dev_put(pdev); | 1807 | dev_put(pdev); |
1772 | } else { | 1808 | } else { |
1773 | pdev = get_real_dev(n->dev); | 1809 | pdev = get_real_dev(n->dev); |
@@ -1786,6 +1822,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, | |||
1786 | cdev->rdev.lldi.nchan; | 1822 | cdev->rdev.lldi.nchan; |
1787 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ | 1823 | ep->rss_qid = cdev->rdev.lldi.rxq_ids[ |
1788 | cxgb4_port_idx(n->dev) * step]; | 1824 | cxgb4_port_idx(n->dev) * step]; |
1825 | set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); | ||
1789 | 1826 | ||
1790 | if (clear_mpa_v1) { | 1827 | if (clear_mpa_v1) { |
1791 | ep->retry_with_mpa_v1 = 0; | 1828 | ep->retry_with_mpa_v1 = 0; |
@@ -2017,6 +2054,7 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, | |||
2017 | u32 opt2; | 2054 | u32 opt2; |
2018 | int wscale; | 2055 | int wscale; |
2019 | struct cpl_t5_pass_accept_rpl *rpl5 = NULL; | 2056 | struct cpl_t5_pass_accept_rpl *rpl5 = NULL; |
2057 | int win; | ||
2020 | 2058 | ||
2021 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); | 2059 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); |
2022 | BUG_ON(skb_cloned(skb)); | 2060 | BUG_ON(skb_cloned(skb)); |
@@ -2037,6 +2075,14 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, | |||
2037 | best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, | 2075 | best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, |
2038 | enable_tcp_timestamps && req->tcpopt.tstamp); | 2076 | enable_tcp_timestamps && req->tcpopt.tstamp); |
2039 | wscale = compute_wscale(rcv_win); | 2077 | wscale = compute_wscale(rcv_win); |
2078 | |||
2079 | /* | ||
2080 | * Specify the largest window that will fit in opt0. The | ||
2081 | * remainder will be specified in the rx_data_ack. | ||
2082 | */ | ||
2083 | win = ep->rcv_win >> 10; | ||
2084 | if (win > RCV_BUFSIZ_MASK) | ||
2085 | win = RCV_BUFSIZ_MASK; | ||
2040 | opt0 = (nocong ? NO_CONG(1) : 0) | | 2086 | opt0 = (nocong ? NO_CONG(1) : 0) | |
2041 | KEEP_ALIVE(1) | | 2087 | KEEP_ALIVE(1) | |
2042 | DELACK(1) | | 2088 | DELACK(1) | |
@@ -2047,7 +2093,7 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, | |||
2047 | SMAC_SEL(ep->smac_idx) | | 2093 | SMAC_SEL(ep->smac_idx) | |
2048 | DSCP(ep->tos >> 2) | | 2094 | DSCP(ep->tos >> 2) | |
2049 | ULP_MODE(ULP_MODE_TCPDDP) | | 2095 | ULP_MODE(ULP_MODE_TCPDDP) | |
2050 | RCV_BUFSIZ(rcv_win>>10); | 2096 | RCV_BUFSIZ(win); |
2051 | opt2 = RX_CHANNEL(0) | | 2097 | opt2 = RX_CHANNEL(0) | |
2052 | RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); | 2098 | RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); |
2053 | 2099 | ||
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 7474b490760a..7493dfeb812a 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
@@ -805,6 +805,8 @@ struct c4iw_ep { | |||
805 | u8 retry_with_mpa_v1; | 805 | u8 retry_with_mpa_v1; |
806 | u8 tried_with_mpa_v1; | 806 | u8 tried_with_mpa_v1; |
807 | unsigned int retry_count; | 807 | unsigned int retry_count; |
808 | int snd_win; | ||
809 | int rcv_win; | ||
808 | }; | 810 | }; |
809 | 811 | ||
810 | static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) | 812 | static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index a4d7bdb20866..973eb11aa98a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | |||
@@ -227,6 +227,7 @@ struct cpl_pass_open_req { | |||
227 | #define DELACK(x) ((x) << 5) | 227 | #define DELACK(x) ((x) << 5) |
228 | #define ULP_MODE(x) ((x) << 8) | 228 | #define ULP_MODE(x) ((x) << 8) |
229 | #define RCV_BUFSIZ(x) ((x) << 12) | 229 | #define RCV_BUFSIZ(x) ((x) << 12) |
230 | #define RCV_BUFSIZ_MASK 0x3FFU | ||
230 | #define DSCP(x) ((x) << 22) | 231 | #define DSCP(x) ((x) << 22) |
231 | #define SMAC_SEL(x) ((u64)(x) << 28) | 232 | #define SMAC_SEL(x) ((u64)(x) << 28) |
232 | #define L2T_IDX(x) ((u64)(x) << 36) | 233 | #define L2T_IDX(x) ((u64)(x) << 36) |