aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHariprasad Shenai <hariprasad@chelsio.com>2014-06-06 12:10:44 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-11 01:49:54 -0400
commitb408ff282dda0ef7a3218dc2e5f1399c665d4c20 (patch)
treedb6345f88bce49d2801cafc38031f5f97cbf4e49
parent92e7ae71726ca9e16a8a88ebeee14eb5177575a1 (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.c54
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h1
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
1751static 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
1725static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, 1760static 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
810static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) 812static 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)