Commit b408ff28 authored by Hariprasad Shenai's avatar Hariprasad Shenai Committed by David S. Miller

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: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarHariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 92e7ae71
...@@ -472,7 +472,7 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) ...@@ -472,7 +472,7 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT; flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq); flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq);
flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF; flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
flowc->mnemval[6].val = cpu_to_be32(snd_win); flowc->mnemval[6].val = cpu_to_be32(ep->snd_win);
flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
flowc->mnemval[7].val = cpu_to_be32(ep->emss); flowc->mnemval[7].val = cpu_to_be32(ep->emss);
/* Pad WR to 16 byte boundary */ /* Pad WR to 16 byte boundary */
...@@ -565,6 +565,7 @@ static int send_connect(struct c4iw_ep *ep) ...@@ -565,6 +565,7 @@ static int send_connect(struct c4iw_ep *ep)
struct sockaddr_in *ra = (struct sockaddr_in *)&ep->com.remote_addr; struct sockaddr_in *ra = (struct sockaddr_in *)&ep->com.remote_addr;
struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&ep->com.local_addr; struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&ep->com.local_addr;
struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr;
int win;
wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? wrlen = (ep->com.remote_addr.ss_family == AF_INET) ?
roundup(sizev4, 16) : roundup(sizev4, 16) :
...@@ -583,6 +584,15 @@ static int send_connect(struct c4iw_ep *ep) ...@@ -583,6 +584,15 @@ static int send_connect(struct c4iw_ep *ep)
best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
enable_tcp_timestamps); enable_tcp_timestamps);
wscale = compute_wscale(rcv_win); wscale = compute_wscale(rcv_win);
/*
* Specify the largest window that will fit in opt0. The
* remainder will be specified in the rx_data_ack.
*/
win = ep->rcv_win >> 10;
if (win > RCV_BUFSIZ_MASK)
win = RCV_BUFSIZ_MASK;
opt0 = (nocong ? NO_CONG(1) : 0) | opt0 = (nocong ? NO_CONG(1) : 0) |
KEEP_ALIVE(1) | KEEP_ALIVE(1) |
DELACK(1) | DELACK(1) |
...@@ -593,7 +603,7 @@ static int send_connect(struct c4iw_ep *ep) ...@@ -593,7 +603,7 @@ static int send_connect(struct c4iw_ep *ep)
SMAC_SEL(ep->smac_idx) | SMAC_SEL(ep->smac_idx) |
DSCP(ep->tos) | DSCP(ep->tos) |
ULP_MODE(ULP_MODE_TCPDDP) | ULP_MODE(ULP_MODE_TCPDDP) |
RCV_BUFSIZ(rcv_win>>10); RCV_BUFSIZ(win);
opt2 = RX_CHANNEL(0) | opt2 = RX_CHANNEL(0) |
CCTRL_ECN(enable_ecn) | CCTRL_ECN(enable_ecn) |
RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
...@@ -1174,6 +1184,14 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits) ...@@ -1174,6 +1184,14 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
return 0; return 0;
} }
/*
* If we couldn't specify the entire rcv window at connection setup
* due to the limit in the number of bits in the RCV_BUFSIZ field,
* then add the overage in to the credits returned.
*/
if (ep->rcv_win > RCV_BUFSIZ_MASK * 1024)
credits += ep->rcv_win - RCV_BUFSIZ_MASK * 1024;
req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen); req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen);
memset(req, 0, wrlen); memset(req, 0, wrlen);
INIT_TP_WR(req, ep->hwtid); 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,6 +1665,7 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
unsigned int mtu_idx; unsigned int mtu_idx;
int wscale; int wscale;
struct sockaddr_in *sin; struct sockaddr_in *sin;
int win;
skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); 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,6 +1691,15 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
enable_tcp_timestamps); enable_tcp_timestamps);
wscale = compute_wscale(rcv_win); wscale = compute_wscale(rcv_win);
/*
* Specify the largest window that will fit in opt0. The
* remainder will be specified in the rx_data_ack.
*/
win = ep->rcv_win >> 10;
if (win > RCV_BUFSIZ_MASK)
win = RCV_BUFSIZ_MASK;
req->tcb.opt0 = (__force __be64) (TCAM_BYPASS(1) | req->tcb.opt0 = (__force __be64) (TCAM_BYPASS(1) |
(nocong ? NO_CONG(1) : 0) | (nocong ? NO_CONG(1) : 0) |
KEEP_ALIVE(1) | KEEP_ALIVE(1) |
...@@ -1683,7 +1711,7 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) ...@@ -1683,7 +1711,7 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
SMAC_SEL(ep->smac_idx) | SMAC_SEL(ep->smac_idx) |
DSCP(ep->tos) | DSCP(ep->tos) |
ULP_MODE(ULP_MODE_TCPDDP) | ULP_MODE(ULP_MODE_TCPDDP) |
RCV_BUFSIZ(rcv_win >> 10)); RCV_BUFSIZ(win));
req->tcb.opt2 = (__force __be32) (PACE(1) | req->tcb.opt2 = (__force __be32) (PACE(1) |
TX_QUEUE(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | TX_QUEUE(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) |
RX_CHANNEL(0) | RX_CHANNEL(0) |
...@@ -1720,6 +1748,13 @@ static int is_neg_adv(unsigned int status) ...@@ -1720,6 +1748,13 @@ static int is_neg_adv(unsigned int status)
status == CPL_ERR_KEEPALV_NEG_ADVICE; status == CPL_ERR_KEEPALV_NEG_ADVICE;
} }
static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
{
ep->snd_win = snd_win;
ep->rcv_win = rcv_win;
PDBG("%s snd_win %d rcv_win %d\n", __func__, ep->snd_win, ep->rcv_win);
}
#define ACT_OPEN_RETRY_COUNT 2 #define ACT_OPEN_RETRY_COUNT 2
static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, 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,6 +1803,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
ep->ctrlq_idx = cxgb4_port_idx(pdev); ep->ctrlq_idx = cxgb4_port_idx(pdev);
ep->rss_qid = cdev->rdev.lldi.rxq_ids[ ep->rss_qid = cdev->rdev.lldi.rxq_ids[
cxgb4_port_idx(pdev) * step]; cxgb4_port_idx(pdev) * step];
set_tcp_window(ep, (struct port_info *)netdev_priv(pdev));
dev_put(pdev); dev_put(pdev);
} else { } else {
pdev = get_real_dev(n->dev); pdev = get_real_dev(n->dev);
...@@ -1786,6 +1822,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, ...@@ -1786,6 +1822,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
cdev->rdev.lldi.nchan; cdev->rdev.lldi.nchan;
ep->rss_qid = cdev->rdev.lldi.rxq_ids[ ep->rss_qid = cdev->rdev.lldi.rxq_ids[
cxgb4_port_idx(n->dev) * step]; cxgb4_port_idx(n->dev) * step];
set_tcp_window(ep, (struct port_info *)netdev_priv(pdev));
if (clear_mpa_v1) { if (clear_mpa_v1) {
ep->retry_with_mpa_v1 = 0; ep->retry_with_mpa_v1 = 0;
...@@ -2017,6 +2054,7 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, ...@@ -2017,6 +2054,7 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
u32 opt2; u32 opt2;
int wscale; int wscale;
struct cpl_t5_pass_accept_rpl *rpl5 = NULL; struct cpl_t5_pass_accept_rpl *rpl5 = NULL;
int win;
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
BUG_ON(skb_cloned(skb)); BUG_ON(skb_cloned(skb));
...@@ -2037,6 +2075,14 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, ...@@ -2037,6 +2075,14 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
enable_tcp_timestamps && req->tcpopt.tstamp); enable_tcp_timestamps && req->tcpopt.tstamp);
wscale = compute_wscale(rcv_win); wscale = compute_wscale(rcv_win);
/*
* Specify the largest window that will fit in opt0. The
* remainder will be specified in the rx_data_ack.
*/
win = ep->rcv_win >> 10;
if (win > RCV_BUFSIZ_MASK)
win = RCV_BUFSIZ_MASK;
opt0 = (nocong ? NO_CONG(1) : 0) | opt0 = (nocong ? NO_CONG(1) : 0) |
KEEP_ALIVE(1) | KEEP_ALIVE(1) |
DELACK(1) | DELACK(1) |
...@@ -2047,7 +2093,7 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, ...@@ -2047,7 +2093,7 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
SMAC_SEL(ep->smac_idx) | SMAC_SEL(ep->smac_idx) |
DSCP(ep->tos >> 2) | DSCP(ep->tos >> 2) |
ULP_MODE(ULP_MODE_TCPDDP) | ULP_MODE(ULP_MODE_TCPDDP) |
RCV_BUFSIZ(rcv_win>>10); RCV_BUFSIZ(win);
opt2 = RX_CHANNEL(0) | opt2 = RX_CHANNEL(0) |
RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
......
...@@ -805,6 +805,8 @@ struct c4iw_ep { ...@@ -805,6 +805,8 @@ struct c4iw_ep {
u8 retry_with_mpa_v1; u8 retry_with_mpa_v1;
u8 tried_with_mpa_v1; u8 tried_with_mpa_v1;
unsigned int retry_count; unsigned int retry_count;
int snd_win;
int rcv_win;
}; };
static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
......
...@@ -227,6 +227,7 @@ struct cpl_pass_open_req { ...@@ -227,6 +227,7 @@ struct cpl_pass_open_req {
#define DELACK(x) ((x) << 5) #define DELACK(x) ((x) << 5)
#define ULP_MODE(x) ((x) << 8) #define ULP_MODE(x) ((x) << 8)
#define RCV_BUFSIZ(x) ((x) << 12) #define RCV_BUFSIZ(x) ((x) << 12)
#define RCV_BUFSIZ_MASK 0x3FFU
#define DSCP(x) ((x) << 22) #define DSCP(x) ((x) << 22)
#define SMAC_SEL(x) ((u64)(x) << 28) #define SMAC_SEL(x) ((u64)(x) << 28)
#define L2T_IDX(x) ((u64)(x) << 36) #define L2T_IDX(x) ((u64)(x) << 36)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment