[PATCH net v2 0/5] cxgb4/cxgbi: misc. fixes for cxgb4i
[PATCH net v2 0/5] cxgb4/cxgbi: misc. fixes for cxgb4i This patch set fixes cxgb4i's tx credit calculation and adds handling of additional rx messages and types of negative advice. It also removes the duplicate code in cxgb4i to set the outgoing queues of a packet. Karen Xie (5): cxgb4i: check if wr header is required when calculating tx credit cxgb4/cxgb4i: set max. outgoing pdu length in the f/w cxgb4i: handle non pdu-aligned rx data and additional types of negative advice cxgb4i: use cxgb4's set_wr_txq() for setting outgoing queues libcxgbi: fix the debug print accessing skb after it is freed Sending to net as the fixes are mostly in the network area and it touches cxgb4's header file (t4fw_api.h). v2 corrects the "CHECK"s flagged by checkpatch.pl --strict. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net v2 1/5] cxgb4i: fix tx credit calculation
[PATCH net v2 1/5] cxgb4i: fix tx credit calculation From: Karen Xie - Only data skbs need the wr header added while control skbs do not. Make sure they are treated differently. - Any credit related checking should be done before adding the wr header. - Fixed compiler warning resulted from added cxgbi_skb_test_flag() call in is_ofld_imm(). Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 26 +- drivers/scsi/cxgbi/libcxgbi.h |4 ++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 1508125..5c3f15d 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -173,8 +173,12 @@ static int push_tx_frames(struct cxgbi_sock *, int); */ static inline int is_ofld_imm(const struct sk_buff *skb) { - return skb->len <= (MAX_IMM_TX_PKT_LEN - - sizeof(struct fw_ofld_tx_data_wr)); + int length = skb->len; + + if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) + length += sizeof(struct fw_ofld_tx_data_wr); + + return length <= MAX_IMM_TX_PKT_LEN; } static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, @@ -544,15 +548,17 @@ static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, unsigned int submode = cxgbi_skcb_ulp_mode(skb) & 3; unsigned int wr_ulp_mode = 0; - req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, sizeof(*req)); - if (is_ofld_imm(skb)) { + req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, + sizeof(*req)); req->op_to_immdlen = htonl(FW_WR_OP(FW_OFLD_TX_DATA_WR) | FW_WR_COMPL(1) | FW_WR_IMMDLEN(dlen)); req->flowid_len16 = htonl(FW_WR_FLOWID(csk->tid) | FW_WR_LEN16(credits)); } else { + req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, + sizeof(*req)); req->op_to_immdlen = cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) | FW_WR_COMPL(1) | @@ -597,12 +603,14 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) skb_reset_transport_header(skb); if (is_ofld_imm(skb)) - credits_needed = DIV_ROUND_UP(dlen + - sizeof(struct fw_ofld_tx_data_wr), 16); + credits_needed = DIV_ROUND_UP(dlen, 16); else - credits_needed = DIV_ROUND_UP(8*calc_tx_flits_ofld(skb) - + sizeof(struct fw_ofld_tx_data_wr), - 16); + credits_needed = DIV_ROUND_UP(8*calc_tx_flits_ofld(skb), + 16); + + if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) + credits_needed += DIV_ROUND_UP( + sizeof(struct fw_ofld_tx_data_wr), 16); if (csk->wr_cred < credits_needed) { log_debug(1 << CXGBI_DBG_PDU_TX, diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 2c7cb1c..aba1af7 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -317,8 +317,8 @@ static inline void cxgbi_skcb_clear_flag(struct sk_buff *skb, __clear_bit(flag, &(cxgbi_skcb_flags(skb))); } -static inline int cxgbi_skcb_test_flag(struct sk_buff *skb, - enum cxgbi_skcb_flags flag) +static inline int cxgbi_skcb_test_flag(const struct sk_buff *skb, + enum cxgbi_skcb_flags flag) { return test_bit(flag, &(cxgbi_skcb_flags(skb))); } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net v2 2/5] cxgb4/cxgb4i: set the max. pdu length in firmware
[PATCH net v2 2/5] cxgb4/cxgb4i: set the max. pdu length in firmware. From: Karen Xie Programs the firmware of the maximum outgoing iscsi pdu length per connection. Signed-off-by: Karen Xie --- drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h |1 drivers/scsi/cxgbi/cxgb4i/cxgb4i.c| 69 ++--- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 3409756..743a350 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -529,6 +529,7 @@ enum fw_flowc_mnem { FW_FLOWC_MNEM_RCVNXT, FW_FLOWC_MNEM_SNDBUF, FW_FLOWC_MNEM_MSS, + FW_FLOWC_MNEM_TXDATAPLEN_MAX, }; struct fw_flowc_mnemval { diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 5c3f15d..b834bde 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -75,6 +75,7 @@ typedef void (*cxgb4i_cplhandler_func)(struct cxgbi_device *, struct sk_buff *); static void *t4_uld_add(const struct cxgb4_lld_info *); static int t4_uld_rx_handler(void *, const __be64 *, const struct pkt_gl *); static int t4_uld_state_change(void *, enum cxgb4_state state); +static inline int send_tx_flowc_wr(struct cxgbi_sock *); static const struct cxgb4_uld_info cxgb4i_uld_info = { .name = DRV_MODULE_NAME, @@ -391,6 +392,12 @@ static void send_abort_req(struct cxgbi_sock *csk) if (unlikely(csk->state == CTP_ABORTING) || !skb || !csk->cdev) return; + + if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) { + send_tx_flowc_wr(csk); + cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT); + } + cxgbi_sock_set_state(csk, CTP_ABORTING); cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING); cxgbi_sock_purge_write_queue(csk); @@ -493,20 +500,40 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb) return flits + sgl_len(cnt); } -static inline void send_tx_flowc_wr(struct cxgbi_sock *csk) +#define FLOWC_WR_NPARAMS_MIN 9 +static inline int tx_flowc_wr_credits(int *nparamsp, int *flowclenp) +{ + int nparams, flowclen16, flowclen; + + nparams = FLOWC_WR_NPARAMS_MIN; + flowclen = offsetof(struct fw_flowc_wr, mnemval[nparams]); + flowclen16 = DIV_ROUND_UP(flowclen, 16); + flowclen = flowclen16 * 16; + /* +* Return the number of 16-byte credits used by the FlowC request. +* Pass back the nparams and actual FlowC length if requested. +*/ + if (nparamsp) + *nparamsp = nparams; + if (flowclenp) + *flowclenp = flowclen; + + return flowclen16; +} + +static inline int send_tx_flowc_wr(struct cxgbi_sock *csk) { struct sk_buff *skb; struct fw_flowc_wr *flowc; - int flowclen, i; + int nparams, flowclen16, flowclen; - flowclen = 80; + flowclen16 = tx_flowc_wr_credits(&nparams, &flowclen); skb = alloc_wr(flowclen, 0, GFP_ATOMIC); flowc = (struct fw_flowc_wr *)skb->head; flowc->op_to_nparams = - htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(8)); + htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(nparams)); flowc->flowid_len16 = - htonl(FW_WR_LEN16(DIV_ROUND_UP(72, 16)) | - FW_WR_FLOWID(csk->tid)); + htonl(FW_WR_LEN16(flowclen16) | FW_WR_FLOWID(csk->tid)); flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; flowc->mnemval[0].val = htonl(csk->cdev->pfvf); flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; @@ -525,11 +552,9 @@ static inline void send_tx_flowc_wr(struct cxgbi_sock *csk) flowc->mnemval[7].val = htonl(csk->advmss); flowc->mnemval[8].mnemonic = 0; flowc->mnemval[8].val = 0; - for (i = 0; i < 9; i++) { - flowc->mnemval[i].r4[0] = 0; - flowc->mnemval[i].r4[1] = 0; - flowc->mnemval[i].r4[2] = 0; - } + flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_TXDATAPLEN_MAX; + flowc->mnemval[8].val = 16384; + set_queue(skb, CPL_PRIORITY_DATA, csk); log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, @@ -539,6 +564,8 @@ static inline void send_tx_flowc_wr(struct cxgbi_sock *csk) csk->advmss); cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); + + return flowclen16; } static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, @@ -600,6 +627,7 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) int dlen = skb->len; int len = skb->len; unsigned int credits_needed; + int flowclen16 = 0; skb_reset_transport_header(skb); if (is_ofld_i
[PATCH net v2 4/5] cxgb4i: use cxgb4's set_wr_txq() for setting tx queues
[PATCH net v2 4/5] cxgb4i: use cxgb4's set_wr_txq() for setting tx queues From: Karen Xie use cxgb4's set_wr_txq() to set the tx queue for a outgoing packet. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 16 +--- 1 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 051adab..3c99e5d 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -157,12 +157,6 @@ static struct scsi_transport_template *cxgb4i_stt; #define RCV_BUFSIZ_MASK0x3FFU #define MAX_IMM_TX_PKT_LEN 128 -static inline void set_queue(struct sk_buff *skb, unsigned int queue, - const struct cxgbi_sock *csk) -{ - skb->queue_mapping = queue; -} - static int push_tx_frames(struct cxgbi_sock *, int); /* @@ -404,7 +398,7 @@ static void send_abort_req(struct cxgbi_sock *csk) csk->cpl_abort_req = NULL; req = (struct cpl_abort_req *)skb->head; - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); req->cmd = CPL_ABORT_SEND_RST; t4_set_arp_err_handler(skb, csk, abort_arp_failure); INIT_TP_WR(req, csk->tid); @@ -430,7 +424,7 @@ static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status) csk, csk->state, csk->flags, csk->tid, rst_status); csk->cpl_abort_rpl = NULL; - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); INIT_TP_WR(rpl, csk->tid); OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid)); rpl->cmd = rst_status; @@ -555,7 +549,7 @@ static inline int send_tx_flowc_wr(struct cxgbi_sock *csk) flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_TXDATAPLEN_MAX; flowc->mnemval[8].val = 16384; - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, "csk 0x%p, tid 0x%x, %u,%u,%u,%u,%u,%u,%u.\n", @@ -659,7 +653,7 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) break; } __skb_unlink(skb, &csk->write_queue); - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); skb->csum = credits_needed + flowclen16; csk->wr_cred -= credits_needed; csk->wr_una_cred += credits_needed; @@ -1551,7 +1545,7 @@ static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id, return -ENOMEM; } req = (struct ulp_mem_io *)skb->head; - set_queue(skb, CPL_PRIORITY_CONTROL, NULL); + set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); ulp_mem_io_set_hdr(lldi, req, wr_len, dlen, pm_addr); idata = (struct ulptx_idata *)(req + 1); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net v2 5/5] libcxgbi: free skb after debug prints
[PATCH net v2 5/5] libcxgbi: free skb after debug prints From: Karen Xie The debug print was accessing the skb after it was freed. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/libcxgbi.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 7da59c3..eb58afc 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -2294,10 +2294,12 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) return err; } - kfree_skb(skb); log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", task->itt, skb, skb->len, skb->data_len, err); + + kfree_skb(skb); + iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err); iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED); return err; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net v2 3/5] cxgb4i: handle non-pdu-aligned rx and additional types of negative advice
[PATCH net v2 3/5] cxgb4i: handle non-pdu-aligned rx data and additional types of negative advice From: Karen Xie - abort the connection upon receiving of cpl_rx_data, which means the pdu cannot be recovered from the tcp stream. This could be due to pdu header corruption. - handle additional types of negative advice returned by h/w. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 34 +++--- 1 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index b834bde..051adab 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -845,6 +845,13 @@ static void csk_act_open_retry_timer(unsigned long data) } +static inline int is_neg_adv(unsigned int status) +{ + return status == CPL_ERR_RTX_NEG_ADVICE || + status == CPL_ERR_KEEPALV_NEG_ADVICE || + status == CPL_ERR_PERSIST_NEG_ADVICE; +} + static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb) { struct cxgbi_sock *csk; @@ -866,7 +873,7 @@ static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb) "csk 0x%p,%u,0x%lx. ", (&csk->saddr), (&csk->daddr), atid, tid, status, csk, csk->state, csk->flags); - if (status == CPL_ERR_RTX_NEG_ADVICE) + if (is_neg_adv(status)) goto rel_skb; module_put(THIS_MODULE); @@ -972,8 +979,7 @@ static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb) (&csk->saddr), (&csk->daddr), csk, csk->state, csk->flags, csk->tid, req->status); - if (req->status == CPL_ERR_RTX_NEG_ADVICE || - req->status == CPL_ERR_PERSIST_NEG_ADVICE) + if (is_neg_adv(req->status)) goto rel_skb; cxgbi_sock_get(csk); @@ -1027,6 +1033,27 @@ rel_skb: __kfree_skb(skb); } +static void do_rx_data(struct cxgbi_device *cdev, struct sk_buff *skb) +{ + struct cxgbi_sock *csk; + struct cpl_rx_data *cpl = (struct cpl_rx_data *)skb->data; + unsigned int tid = GET_TID(cpl); + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev); + struct tid_info *t = lldi->tids; + + csk = lookup_tid(t, tid); + if (!csk) { + pr_err("can't find connection for tid %u.\n", tid); + } else { + /* not expecting this, reset the connection. */ + pr_err("csk 0x%p, tid %u, rcv cpl_rx_data.\n", csk, tid); + spin_lock_bh(&csk->lock); + send_abort_req(csk); + spin_unlock_bh(&csk->lock); + } + __kfree_skb(skb); +} + static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb) { struct cxgbi_sock *csk; @@ -1446,6 +1473,7 @@ cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = { [CPL_SET_TCB_RPL] = do_set_tcb_rpl, [CPL_RX_DATA_DDP] = do_rx_data_ddp, [CPL_RX_ISCSI_DDP] = do_rx_data_ddp, + [CPL_RX_DATA] = do_rx_data, }; int cxgb4i_ofld_init(struct cxgbi_device *cdev) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net 2/5] cxgb4/cxgb4i: set the max. pdu length in firmware
[PATCH net 2/5] cxgb4/cxgb4i: set the max. pdu length in firmware. From: Karen Xie Programs the firmware of the maximum outgoing iscsi pdu length per connection. Signed-off-by: Karen Xie --- drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h |1 drivers/scsi/cxgbi/cxgb4i/cxgb4i.c| 69 ++--- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 3409756..743a350 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -529,6 +529,7 @@ enum fw_flowc_mnem { FW_FLOWC_MNEM_RCVNXT, FW_FLOWC_MNEM_SNDBUF, FW_FLOWC_MNEM_MSS, + FW_FLOWC_MNEM_TXDATAPLEN_MAX, }; struct fw_flowc_mnemval { diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index bc4e376..8f61d26 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -75,6 +75,7 @@ typedef void (*cxgb4i_cplhandler_func)(struct cxgbi_device *, struct sk_buff *); static void *t4_uld_add(const struct cxgb4_lld_info *); static int t4_uld_rx_handler(void *, const __be64 *, const struct pkt_gl *); static int t4_uld_state_change(void *, enum cxgb4_state state); +static inline int send_tx_flowc_wr(struct cxgbi_sock *); static const struct cxgb4_uld_info cxgb4i_uld_info = { .name = DRV_MODULE_NAME, @@ -391,6 +392,12 @@ static void send_abort_req(struct cxgbi_sock *csk) if (unlikely(csk->state == CTP_ABORTING) || !skb || !csk->cdev) return; + + if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) { + send_tx_flowc_wr(csk); + cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT); + } + cxgbi_sock_set_state(csk, CTP_ABORTING); cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING); cxgbi_sock_purge_write_queue(csk); @@ -493,20 +500,40 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb) return flits + sgl_len(cnt); } -static inline void send_tx_flowc_wr(struct cxgbi_sock *csk) +#define FLOWC_WR_NPARAMS_MIN 9 +static inline int tx_flowc_wr_credits(int *nparamsp, int *flowclenp) +{ + int nparams, flowclen16, flowclen; + + nparams = FLOWC_WR_NPARAMS_MIN; + flowclen = offsetof(struct fw_flowc_wr, mnemval[nparams]); + flowclen16 = DIV_ROUND_UP(flowclen, 16); + flowclen = flowclen16 * 16; + /* +* Return the number of 16-byte credits used by the FlowC request. +* Pass back the nparams and actual FlowC length if requested. +*/ + if (nparamsp) + *nparamsp = nparams; + if (flowclenp) + *flowclenp = flowclen; + + return flowclen16; +} + +static inline int send_tx_flowc_wr(struct cxgbi_sock *csk) { struct sk_buff *skb; struct fw_flowc_wr *flowc; - int flowclen, i; + int nparams, flowclen16, flowclen; - flowclen = 80; + flowclen16 = tx_flowc_wr_credits(&nparams, &flowclen); skb = alloc_wr(flowclen, 0, GFP_ATOMIC); flowc = (struct fw_flowc_wr *)skb->head; flowc->op_to_nparams = - htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(8)); + htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(nparams)); flowc->flowid_len16 = - htonl(FW_WR_LEN16(DIV_ROUND_UP(72, 16)) | - FW_WR_FLOWID(csk->tid)); + htonl(FW_WR_LEN16(flowclen16) | FW_WR_FLOWID(csk->tid)); flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; flowc->mnemval[0].val = htonl(csk->cdev->pfvf); flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; @@ -525,11 +552,9 @@ static inline void send_tx_flowc_wr(struct cxgbi_sock *csk) flowc->mnemval[7].val = htonl(csk->advmss); flowc->mnemval[8].mnemonic = 0; flowc->mnemval[8].val = 0; - for (i = 0; i < 9; i++) { - flowc->mnemval[i].r4[0] = 0; - flowc->mnemval[i].r4[1] = 0; - flowc->mnemval[i].r4[2] = 0; - } + flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_TXDATAPLEN_MAX; + flowc->mnemval[8].val = 16384; + set_queue(skb, CPL_PRIORITY_DATA, csk); log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, @@ -539,6 +564,8 @@ static inline void send_tx_flowc_wr(struct cxgbi_sock *csk) csk->advmss); cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); + + return flowclen16; } static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, @@ -600,6 +627,7 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) int dlen = skb->len; int len = skb->len; unsigned int credits_needed; + int flowclen16 = 0; skb_reset_transport_header(skb); if (is_ofld_imm(
[PATCH net 3/5] cxgb4i: handle non-pdu-aligned rx and additional types of negative advice
[PATCH net 3/5] cxgb4i: handle non-pdu-aligned rx data and additional types of negative advice From: Karen Xie - abort the connection upon receiving of cpl_rx_data, which means the pdu cannot be recovered from the tcp stream. This could be due to pdu header corruption. - handle additional types of negative advice returned by h/w. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 34 +++--- 1 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 8f61d26..e55a433 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -845,6 +845,13 @@ static void csk_act_open_retry_timer(unsigned long data) } +static inline int is_neg_adv(unsigned int status) +{ + return status == CPL_ERR_RTX_NEG_ADVICE || + status == CPL_ERR_KEEPALV_NEG_ADVICE || + status == CPL_ERR_PERSIST_NEG_ADVICE; +} + static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb) { struct cxgbi_sock *csk; @@ -866,7 +873,7 @@ static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb) "csk 0x%p,%u,0x%lx. ", (&csk->saddr), (&csk->daddr), atid, tid, status, csk, csk->state, csk->flags); - if (status == CPL_ERR_RTX_NEG_ADVICE) + if (is_neg_adv(status)) goto rel_skb; module_put(THIS_MODULE); @@ -972,8 +979,7 @@ static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb) (&csk->saddr), (&csk->daddr), csk, csk->state, csk->flags, csk->tid, req->status); - if (req->status == CPL_ERR_RTX_NEG_ADVICE || - req->status == CPL_ERR_PERSIST_NEG_ADVICE) + if (is_neg_adv(req->status)) goto rel_skb; cxgbi_sock_get(csk); @@ -1027,6 +1033,27 @@ rel_skb: __kfree_skb(skb); } +static void do_rx_data(struct cxgbi_device *cdev, struct sk_buff *skb) +{ + struct cxgbi_sock *csk; + struct cpl_rx_data *cpl = (struct cpl_rx_data *)skb->data; + unsigned int tid = GET_TID(cpl); + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev); + struct tid_info *t = lldi->tids; + + csk = lookup_tid(t, tid); + if (!csk) + pr_err("can't find connection for tid %u.\n", tid); + else { + /* not expecting this, reset the connection. */ + pr_err("csk 0x%p, tid %u, rcv cpl_rx_data.\n", csk, tid); + spin_lock_bh(&csk->lock); + send_abort_req(csk); + spin_unlock_bh(&csk->lock); + } + __kfree_skb(skb); +} + static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb) { struct cxgbi_sock *csk; @@ -1446,6 +1473,7 @@ cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = { [CPL_SET_TCB_RPL] = do_set_tcb_rpl, [CPL_RX_DATA_DDP] = do_rx_data_ddp, [CPL_RX_ISCSI_DDP] = do_rx_data_ddp, + [CPL_RX_DATA] = do_rx_data, }; int cxgb4i_ofld_init(struct cxgbi_device *cdev) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net 4/5] cxgb4i: use cxgb4's set_wr_txq() for setting tx queues
[PATCH net 4/5] cxgb4i: use cxgb4's set_wr_txq() for setting tx queues From: Karen Xie use cxgb4's set_wr_txq() to set the tx queue for a outgoing packet. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 16 +--- 1 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index e55a433..a4e8dbf 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -157,12 +157,6 @@ static struct scsi_transport_template *cxgb4i_stt; #define RCV_BUFSIZ_MASK0x3FFU #define MAX_IMM_TX_PKT_LEN 128 -static inline void set_queue(struct sk_buff *skb, unsigned int queue, - const struct cxgbi_sock *csk) -{ - skb->queue_mapping = queue; -} - static int push_tx_frames(struct cxgbi_sock *, int); /* @@ -404,7 +398,7 @@ static void send_abort_req(struct cxgbi_sock *csk) csk->cpl_abort_req = NULL; req = (struct cpl_abort_req *)skb->head; - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); req->cmd = CPL_ABORT_SEND_RST; t4_set_arp_err_handler(skb, csk, abort_arp_failure); INIT_TP_WR(req, csk->tid); @@ -430,7 +424,7 @@ static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status) csk, csk->state, csk->flags, csk->tid, rst_status); csk->cpl_abort_rpl = NULL; - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); INIT_TP_WR(rpl, csk->tid); OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid)); rpl->cmd = rst_status; @@ -555,7 +549,7 @@ static inline int send_tx_flowc_wr(struct cxgbi_sock *csk) flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_TXDATAPLEN_MAX; flowc->mnemval[8].val = 16384; - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, "csk 0x%p, tid 0x%x, %u,%u,%u,%u,%u,%u,%u.\n", @@ -659,7 +653,7 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) break; } __skb_unlink(skb, &csk->write_queue); - set_queue(skb, CPL_PRIORITY_DATA, csk); + set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); skb->csum = credits_needed + flowclen16; csk->wr_cred -= credits_needed; csk->wr_una_cred += credits_needed; @@ -1551,7 +1545,7 @@ static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id, return -ENOMEM; } req = (struct ulp_mem_io *)skb->head; - set_queue(skb, CPL_PRIORITY_CONTROL, NULL); + set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); ulp_mem_io_set_hdr(lldi, req, wr_len, dlen, pm_addr); idata = (struct ulptx_idata *)(req + 1); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net 5/5] libcxgbi: free skb after debug prints
[PATCH net 5/5] libcxgbi: free skb after debug prints From: Karen Xie The debug print was accessing the skb after it was freed. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/libcxgbi.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 7da59c3..eb58afc 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -2294,10 +2294,12 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) return err; } - kfree_skb(skb); log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", task->itt, skb, skb->len, skb->data_len, err); + + kfree_skb(skb); + iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err); iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED); return err; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net 0/5] cxgb4/cxgbi: misc. fixes for cxgb4i
[PATCH net 0/5] cxgb4/cxgbi: misc. fixes for cxgb4i This patch set fixes cxgb4i's tx credit calculation and adds handling of additional rx messages and types of negative advice. It also removes the duplicate code in cxgb4i to set the outgoing queues of a packet. Karen Xie (5): cxgb4i: check if wr header is required when calculating tx credit cxgb4/cxgb4i: set max. outgoing pdu length in the f/w cxgb4i: handle non pdu-aligned rx data and additional types of negative advice cxgb4i: use cxgb4's set_wr_txq() for setting outgoing queues libcxgbi: fix the debug print accessing skb after it is freed Sending to net as the fixes are mostly in the network area and it touches cxgb4's header file (t4fw_api.h). -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net 1/5] cxgb4i: fix tx credit calculation
[PATCH net 1/5] cxgb4i: fix tx credit calculation From: Karen Xie - Only data skbs need the wr header added while control skbs do not. Make sure they are treated differently. - Any credit related checking should be done before adding the wr header. - Fixed compiler warning resulted from added cxgbi_skb_test_flag() call in is_ofld_imm(). Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 24 drivers/scsi/cxgbi/libcxgbi.h |2 +- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 1508125..bc4e376 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -173,8 +173,12 @@ static int push_tx_frames(struct cxgbi_sock *, int); */ static inline int is_ofld_imm(const struct sk_buff *skb) { - return skb->len <= (MAX_IMM_TX_PKT_LEN - - sizeof(struct fw_ofld_tx_data_wr)); + int length = skb->len; + + if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) + length += sizeof(struct fw_ofld_tx_data_wr); + + return length <= MAX_IMM_TX_PKT_LEN; } static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, @@ -544,15 +548,17 @@ static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, unsigned int submode = cxgbi_skcb_ulp_mode(skb) & 3; unsigned int wr_ulp_mode = 0; - req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, sizeof(*req)); - if (is_ofld_imm(skb)) { + req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, + sizeof(*req)); req->op_to_immdlen = htonl(FW_WR_OP(FW_OFLD_TX_DATA_WR) | FW_WR_COMPL(1) | FW_WR_IMMDLEN(dlen)); req->flowid_len16 = htonl(FW_WR_FLOWID(csk->tid) | FW_WR_LEN16(credits)); } else { + req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, + sizeof(*req)); req->op_to_immdlen = cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) | FW_WR_COMPL(1) | @@ -597,13 +603,15 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) skb_reset_transport_header(skb); if (is_ofld_imm(skb)) - credits_needed = DIV_ROUND_UP(dlen + - sizeof(struct fw_ofld_tx_data_wr), 16); + credits_needed = DIV_ROUND_UP(dlen, 16); else - credits_needed = DIV_ROUND_UP(8*calc_tx_flits_ofld(skb) - + sizeof(struct fw_ofld_tx_data_wr), + credits_needed = DIV_ROUND_UP(8*calc_tx_flits_ofld(skb), 16); + if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) + credits_needed += DIV_ROUND_UP( + sizeof(struct fw_ofld_tx_data_wr), 16); + if (csk->wr_cred < credits_needed) { log_debug(1 << CXGBI_DBG_PDU_TX, "csk 0x%p, skb %u/%u, wr %d < %u.\n", diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 2c7cb1c..631a9b7 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -317,7 +317,7 @@ static inline void cxgbi_skcb_clear_flag(struct sk_buff *skb, __clear_bit(flag, &(cxgbi_skcb_flags(skb))); } -static inline int cxgbi_skcb_test_flag(struct sk_buff *skb, +static inline int cxgbi_skcb_test_flag(const struct sk_buff *skb, enum cxgbi_skcb_flags flag) { return test_bit(flag, &(cxgbi_skcb_flags(skb))); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] cxgb4i: Use cxgb4_select_ntuple to correctly calculate ntuple fields
[PATCH] cxgb4i: Use cxgb4_select_ntuple to correctly calculate ntuple fields From: Karen Xie Fixed calculates wrong tuple values on T5 adapter: switch to use the exported API cxgb4_select_ntuple() from cxgb4 base driver. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 59 1 files changed, 7 insertions(+), 52 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 5a9f842..e8ee5e5 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -175,52 +175,6 @@ static inline int is_ofld_imm(const struct sk_buff *skb) sizeof(struct fw_ofld_tx_data_wr)); } - -#define VLAN_NONE 0xfff -#define FILTER_SEL_VLAN_NONE 0x -#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */ -#define FILTER_SEL_WIDTH_VIN_P_FC \ - (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/ -#define FILTER_SEL_WIDTH_TAG_P_FC \ - (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */ -#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC) - -static unsigned int select_ntuple(struct cxgbi_device *cdev, - struct l2t_entry *l2t) -{ - struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev); - unsigned int ntuple = 0; - u32 viid; - - switch (lldi->filt_mode) { - - /* default filter mode */ - case HW_TPL_FR_MT_PR_IV_P_FC: - if (l2t->vlan == VLAN_NONE) - ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC; - else { - ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC; - ntuple |= 1 << FILTER_SEL_WIDTH_VLD_TAG_P_FC; - } - ntuple |= l2t->lport << S_PORT | IPPROTO_TCP << - FILTER_SEL_WIDTH_VLD_TAG_P_FC; - break; - case HW_TPL_FR_MT_PR_OV_P_FC: { - viid = cxgb4_port_viid(l2t->neigh->dev); - - ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC; - ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC; - ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC; - ntuple |= l2t->lport << S_PORT | IPPROTO_TCP << - FILTER_SEL_WIDTH_VLD_TAG_P_FC; - break; - } - default: - break; - } - return ntuple; -} - static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, struct l2t_entry *e) { @@ -248,8 +202,6 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, struct cpl_act_open_req *req = (struct cpl_act_open_req *)skb->head; - req = (struct cpl_act_open_req *)skb->head; - INIT_TP_WR(req, 0); OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_atid)); @@ -258,7 +210,9 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, req->local_ip = csk->saddr.sin_addr.s_addr; req->peer_ip = csk->daddr.sin_addr.s_addr; req->opt0 = cpu_to_be64(opt0); - req->params = cpu_to_be32(select_ntuple(csk->cdev, csk->l2t)); + req->params = cpu_to_be32(cxgb4_select_ntuple( + csk->cdev->ports[csk->port_id], + csk->l2t)); opt2 |= 1 << 22; req->opt2 = cpu_to_be32(opt2); @@ -271,8 +225,6 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, struct cpl_t5_act_open_req *req = (struct cpl_t5_act_open_req *)skb->head; - req = (struct cpl_t5_act_open_req *)skb->head; - INIT_TP_WR(req, 0); OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_atid)); @@ -281,7 +233,10 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, req->local_ip = csk->saddr.sin_addr.s_addr; req->peer_ip = csk->daddr.sin_addr.s_addr; req->opt0 = cpu_to_be64(opt0); - req->params = cpu_to_be32(select_ntuple(csk->cdev, csk->l2t)); + req->params = cpu_to_be64(V_FILTER_TUPLE( + cxgb4_select_ntuple( + csk->cdev->ports[csk->port_id], + csk->l2t))); opt2 |= 1 << 31; req->opt2 = cpu_to_be32(opt2); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.htm
[PATCH] cxgb4i: add support for t5 adapter
[PATCH] cxgb4i: add support for T5 adapter From: Karen Xie Adds support for Chelsio T5 adapter. Signed-off-by: Karen Xie --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 159 +--- 1 files changed, 128 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 3fecf35..e659feb 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -20,6 +20,7 @@ #include #include +#include "t4_regs.h" #include "t4_msg.h" #include "cxgb4.h" #include "cxgb4_uld.h" @@ -32,13 +33,12 @@ static unsigned int dbg_level; #include "../libcxgbi.h" #defineDRV_MODULE_NAME "cxgb4i" -#define DRV_MODULE_DESC"Chelsio T4 iSCSI Driver" -#defineDRV_MODULE_VERSION "0.9.1" -#defineDRV_MODULE_RELDATE "Aug. 2010" +#define DRV_MODULE_DESC"Chelsio T4/T5 iSCSI Driver" +#defineDRV_MODULE_VERSION "0.9.4" static char version[] = DRV_MODULE_DESC " " DRV_MODULE_NAME - " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; + " v" DRV_MODULE_VERSION "\n"; MODULE_AUTHOR("Chelsio Communications, Inc."); MODULE_DESCRIPTION(DRV_MODULE_DESC); @@ -175,10 +175,56 @@ static inline int is_ofld_imm(const struct sk_buff *skb) sizeof(struct fw_ofld_tx_data_wr)); } + +#define VLAN_NONE 0xfff +#define FILTER_SEL_VLAN_NONE 0x +#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */ +#define FILTER_SEL_WIDTH_VIN_P_FC \ + (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/ +#define FILTER_SEL_WIDTH_TAG_P_FC \ + (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */ +#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC) + +static unsigned int select_ntuple(struct cxgbi_device *cdev, + struct l2t_entry *l2t) +{ + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev); + unsigned int ntuple = 0; + u32 viid; + + switch (lldi->filt_mode) { + + /* default filter mode */ + case HW_TPL_FR_MT_PR_IV_P_FC: + if (l2t->vlan == VLAN_NONE) + ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC; + else { + ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC; + ntuple |= 1 << FILTER_SEL_WIDTH_VLD_TAG_P_FC; + } + ntuple |= l2t->lport << S_PORT | IPPROTO_TCP << + FILTER_SEL_WIDTH_VLD_TAG_P_FC; + break; + case HW_TPL_FR_MT_PR_OV_P_FC: { + viid = cxgb4_port_viid(l2t->neigh->dev); + + ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC; + ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC; + ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC; + ntuple |= l2t->lport << S_PORT | IPPROTO_TCP << + FILTER_SEL_WIDTH_VLD_TAG_P_FC; + break; + } + default: + break; + } + return ntuple; +} + static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, struct l2t_entry *e) { - struct cpl_act_open_req *req; + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev); int wscale = cxgbi_sock_compute_wscale(csk->mss_idx); unsigned long long opt0; unsigned int opt2; @@ -195,29 +241,58 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, RCV_BUFSIZ(cxgb4i_rcv_win >> 10); opt2 = RX_CHANNEL(0) | RSS_QUEUE_VALID | - (1 << 20) | (1 << 22) | + (1 << 20) | RSS_QUEUE(csk->rss_qid); - set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id); - req = (struct cpl_act_open_req *)skb->head; + if (is_t4(lldi->adapter_type)) { + struct cpl_act_open_req *req = + (struct cpl_act_open_req *)skb->head; - INIT_TP_WR(req, 0); - OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, + req = (struct cpl_act_open_req *)skb->head; + + INIT_TP_WR(req, 0); + OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_atid)); - req->local_port = csk->saddr.sin_port; - req->peer_port = csk->daddr.sin_port; - req->local_ip = csk->saddr.sin_addr.s_addr; - req->peer_ip = csk->daddr.sin_addr.s_addr; - req->opt0 = cpu_to_be64(opt0); - req->params = 0; - req->opt2 = cpu_to_be32(opt2); + req->local_port = csk->saddr.sin_port; + req->peer_port = csk->daddr.sin_port; + req->local_ip = csk->saddr.sin_addr.s_addr; + req->peer_ip = csk->daddr.sin_addr.s_addr; +