Commit 1cab775c authored by Vipul Pandya's avatar Vipul Pandya Committed by Roland Dreier

RDMA/cxgb4: Fix LE hash collision bug for passive open connection

It establishes passive open connection through firmware work request. Passive
open connection will go through this path as now instead of listening server we
create a server filter which will redirect the incoming SYN packet to the
offload queue. After this driver tries to establish the connection using
firmware work request.
Signed-off-by: default avatarVipul Pandya <vipul@chelsio.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 5be78ee9
This diff is collapsed.
......@@ -279,6 +279,7 @@ static int stats_show(struct seq_file *seq, void *v)
seq_printf(seq, " DB State: %s Transitions %llu\n",
db_state_str[dev->db_state],
dev->rdev.stats.db_state_transitions);
seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full);
return 0;
}
......@@ -577,14 +578,76 @@ static void *c4iw_uld_add(const struct cxgb4_lld_info *infop)
return ctx;
}
static inline struct sk_buff *copy_gl_to_skb_pkt(const struct pkt_gl *gl,
const __be64 *rsp,
u32 pktshift)
{
struct sk_buff *skb;
/*
* Allocate space for cpl_pass_accept_req which will be synthesized by
* driver. Once the driver synthesizes the request the skb will go
* through the regular cpl_pass_accept_req processing.
* The math here assumes sizeof cpl_pass_accept_req >= sizeof
* cpl_rx_pkt.
*/
skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req) +
sizeof(struct rss_header) - pktshift, GFP_ATOMIC);
if (unlikely(!skb))
return NULL;
__skb_put(skb, gl->tot_len + sizeof(struct cpl_pass_accept_req) +
sizeof(struct rss_header) - pktshift);
/*
* This skb will contain:
* rss_header from the rspq descriptor (1 flit)
* cpl_rx_pkt struct from the rspq descriptor (2 flits)
* space for the difference between the size of an
* rx_pkt and pass_accept_req cpl (1 flit)
* the packet data from the gl
*/
skb_copy_to_linear_data(skb, rsp, sizeof(struct cpl_pass_accept_req) +
sizeof(struct rss_header));
skb_copy_to_linear_data_offset(skb, sizeof(struct rss_header) +
sizeof(struct cpl_pass_accept_req),
gl->va + pktshift,
gl->tot_len - pktshift);
return skb;
}
static inline int recv_rx_pkt(struct c4iw_dev *dev, const struct pkt_gl *gl,
const __be64 *rsp)
{
unsigned int opcode = *(u8 *)rsp;
struct sk_buff *skb;
if (opcode != CPL_RX_PKT)
goto out;
skb = copy_gl_to_skb_pkt(gl , rsp, dev->rdev.lldi.sge_pktshift);
if (skb == NULL)
goto out;
if (c4iw_handlers[opcode] == NULL) {
pr_info("%s no handler opcode 0x%x...\n", __func__,
opcode);
kfree_skb(skb);
goto out;
}
c4iw_handlers[opcode](dev, skb);
return 1;
out:
return 0;
}
static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
const struct pkt_gl *gl)
{
struct uld_ctx *ctx = handle;
struct c4iw_dev *dev = ctx->dev;
struct sk_buff *skb;
const struct cpl_act_establish *rpl;
unsigned int opcode;
u8 opcode;
if (gl == NULL) {
/* omit RSS and rsp_ctrl at end of descriptor */
......@@ -600,6 +663,18 @@ static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
u32 qid = be32_to_cpu(rc->pldbuflen_qid);
c4iw_ev_handler(dev, qid);
return 0;
} else if (unlikely(*(u8 *)rsp != *(u8 *)gl->va)) {
if (recv_rx_pkt(dev, gl, rsp))
return 0;
pr_info("%s: unexpected FL contents at %p, " \
"RSS %#llx, FL %#llx, len %u\n",
pci_name(ctx->lldi.pdev), gl->va,
(unsigned long long)be64_to_cpu(*rsp),
(unsigned long long)be64_to_cpu(*(u64 *)gl->va),
gl->tot_len);
return 0;
} else {
skb = cxgb4_pktgl_to_skb(gl, 128, 128);
......@@ -607,13 +682,11 @@ static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
goto nomem;
}
rpl = cplhdr(skb);
opcode = rpl->ot.opcode;
opcode = *(u8 *)rsp;
if (c4iw_handlers[opcode])
c4iw_handlers[opcode](dev, skb);
else
printk(KERN_INFO "%s no handler opcode 0x%x...\n", __func__,
pr_info("%s no handler opcode 0x%x...\n", __func__,
opcode);
return 0;
......
......@@ -3317,6 +3317,10 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
adap = netdev2adap(dev);
/* Adjust stid to correct filter index */
stid -= adap->tids.nstids;
stid += adap->tids.nftids;
/* Check to make sure the filter requested is writable ...
*/
f = &adap->tids.ftid_tab[stid];
......@@ -3365,6 +3369,11 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
struct adapter *adap;
adap = netdev2adap(dev);
/* Adjust stid to correct filter index */
stid -= adap->tids.nstids;
stid += adap->tids.nftids;
f = &adap->tids.ftid_tab[stid];
/* Unlock the filter */
f->locked = 0;
......
......@@ -199,6 +199,18 @@ struct work_request_hdr {
#define WR_HDR struct work_request_hdr wr
/* option 0 fields */
#define S_MSS_IDX 60
#define M_MSS_IDX 0xF
#define V_MSS_IDX(x) ((__u64)(x) << S_MSS_IDX)
#define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX)
/* option 2 fields */
#define S_RSS_QUEUE 0
#define M_RSS_QUEUE 0x3FF
#define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE)
#define G_RSS_QUEUE(x) (((x) >> S_RSS_QUEUE) & M_RSS_QUEUE)
struct cpl_pass_open_req {
WR_HDR;
union opcode_tid ot;
......@@ -300,6 +312,9 @@ struct cpl_pass_establish {
union opcode_tid ot;
__be32 rsvd;
__be32 tos_stid;
#define PASS_OPEN_TID(x) ((x) << 0)
#define PASS_OPEN_TOS(x) ((x) << 24)
#define GET_PASS_OPEN_TID(x) (((x) >> 0) & 0xFFFFFF)
#define GET_POPEN_TID(x) ((x) & 0xffffff)
#define GET_POPEN_TOS(x) (((x) >> 24) & 0xff)
__be16 mac_idx;
......@@ -545,6 +560,37 @@ struct cpl_rx_pkt {
__be16 err_vec;
};
/* rx_pkt.l2info fields */
#define S_RX_ETHHDR_LEN 0
#define M_RX_ETHHDR_LEN 0x1F
#define V_RX_ETHHDR_LEN(x) ((x) << S_RX_ETHHDR_LEN)
#define G_RX_ETHHDR_LEN(x) (((x) >> S_RX_ETHHDR_LEN) & M_RX_ETHHDR_LEN)
#define S_RX_MACIDX 8
#define M_RX_MACIDX 0x1FF
#define V_RX_MACIDX(x) ((x) << S_RX_MACIDX)
#define G_RX_MACIDX(x) (((x) >> S_RX_MACIDX) & M_RX_MACIDX)
#define S_RXF_SYN 21
#define V_RXF_SYN(x) ((x) << S_RXF_SYN)
#define F_RXF_SYN V_RXF_SYN(1U)
#define S_RX_CHAN 28
#define M_RX_CHAN 0xF
#define V_RX_CHAN(x) ((x) << S_RX_CHAN)
#define G_RX_CHAN(x) (((x) >> S_RX_CHAN) & M_RX_CHAN)
/* rx_pkt.hdr_len fields */
#define S_RX_TCPHDR_LEN 0
#define M_RX_TCPHDR_LEN 0x3F
#define V_RX_TCPHDR_LEN(x) ((x) << S_RX_TCPHDR_LEN)
#define G_RX_TCPHDR_LEN(x) (((x) >> S_RX_TCPHDR_LEN) & M_RX_TCPHDR_LEN)
#define S_RX_IPHDR_LEN 6
#define M_RX_IPHDR_LEN 0x3FF
#define V_RX_IPHDR_LEN(x) ((x) << S_RX_IPHDR_LEN)
#define G_RX_IPHDR_LEN(x) (((x) >> S_RX_IPHDR_LEN) & M_RX_IPHDR_LEN)
struct cpl_trace_pkt {
u8 opcode;
u8 intf;
......
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