[PATCH net v2 0/5] cxgb4/cxgbi: misc. fixes for cxgb4i

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-12-08 Thread kxie
[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

2014-01-28 Thread kxie
[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

2013-05-29 Thread kxie
[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;
+