diff options
Diffstat (limited to 'drivers/scsi/cxgbi')
-rw-r--r-- | drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 1 | ||||
-rw-r--r-- | drivers/scsi/cxgbi/libcxgbi.c | 50 | ||||
-rw-r--r-- | drivers/scsi/cxgbi/libcxgbi.h | 1 |
3 files changed, 33 insertions, 19 deletions
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 1bef2724eb78..266eddf17a99 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -1575,6 +1575,7 @@ static void release_offload_resources(struct cxgbi_sock *csk) csk, csk->state, csk->flags, csk->tid); cxgbi_sock_free_cpl_skbs(csk); + cxgbi_sock_purge_write_queue(csk); if (csk->wr_cred != csk->wr_max_cred) { cxgbi_sock_purge_wr_queue(csk); cxgbi_sock_reset_wr_list(csk); diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index a61a152136a3..ce1336414e0a 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -688,8 +688,6 @@ rel_neigh: rel_rt: ip_rt_put(rt); - if (csk) - cxgbi_sock_closed(csk); err_out: return ERR_PTR(err); } @@ -1889,16 +1887,13 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) struct iscsi_tcp_task *tcp_task = task->dd_data; struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); struct scsi_cmnd *sc = task->sc; + struct cxgbi_sock *csk = cconn->cep->csk; + struct net_device *ndev = cdev->ports[csk->port_id]; int headroom = SKB_TX_ISCSI_PDU_HEADER_MAX; tcp_task->dd_data = tdata; task->hdr = NULL; - if (tdata->skb) { - kfree_skb(tdata->skb); - tdata->skb = NULL; - } - if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) && (opcode == ISCSI_OP_SCSI_DATA_OUT || (opcode == ISCSI_OP_SCSI_CMD && @@ -1910,15 +1905,23 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC); if (!tdata->skb) { - struct cxgbi_sock *csk = cconn->cep->csk; - struct net_device *ndev = cdev->ports[csk->port_id]; ndev->stats.tx_dropped++; return -ENOMEM; } - skb_get(tdata->skb); skb_reserve(tdata->skb, cdev->skb_tx_rsvd); - task->hdr = (struct iscsi_hdr *)tdata->skb->data; + + if (task->sc) { + task->hdr = (struct iscsi_hdr *)tdata->skb->data; + } else { + task->hdr = kzalloc(SKB_TX_ISCSI_PDU_HEADER_MAX, GFP_KERNEL); + if (!task->hdr) { + __kfree_skb(tdata->skb); + tdata->skb = NULL; + ndev->stats.tx_dropped++; + return -ENOMEM; + } + } task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */ /* data_out uses scsi_cmd's itt */ @@ -2062,9 +2065,9 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) unsigned int datalen; int err; - if (!skb || cxgbi_skcb_test_flag(skb, SKCBF_TX_DONE)) { + if (!skb) { log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, - "task 0x%p, skb 0x%p\n", task, skb); + "task 0x%p\n", task); return 0; } @@ -2076,6 +2079,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) return -EPIPE; } + tdata->skb = NULL; datalen = skb->data_len; /* write ppod first if using ofldq to write ppod */ @@ -2089,6 +2093,9 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) /* continue. Let fl get the data */ } + if (!task->sc) + memcpy(skb->data, task->hdr, SKB_TX_ISCSI_PDU_HEADER_MAX); + err = cxgbi_sock_send_pdus(cconn->cep->csk, skb); if (err > 0) { int pdulen = err; @@ -2104,7 +2111,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) pdulen += ISCSI_DIGEST_SIZE; task->conn->txdata_octets += pdulen; - cxgbi_skcb_set_flag(skb, SKCBF_TX_DONE); return 0; } @@ -2113,6 +2119,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n", task, skb, skb->len, skb->data_len, err); /* reset skb to send when we are called again */ + tdata->skb = skb; return err; } @@ -2120,8 +2127,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", task->itt, skb, skb->len, skb->data_len, err); - __kfree_skb(tdata->skb); - tdata->skb = NULL; + __kfree_skb(skb); iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err); iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED); @@ -2146,9 +2152,14 @@ void cxgbi_cleanup_task(struct iscsi_task *task) task, tdata->skb, task->hdr_itt); tcp_task->dd_data = NULL; + + if (!task->sc) + kfree(task->hdr); + task->hdr = NULL; + /* never reached the xmit task callout */ if (tdata->skb) { - kfree_skb(tdata->skb); + __kfree_skb(tdata->skb); tdata->skb = NULL; } @@ -2556,7 +2567,10 @@ struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost, goto err_out; } - ifindex = hba->ndev->ifindex; + rtnl_lock(); + if (!vlan_uses_dev(hba->ndev)) + ifindex = hba->ndev->ifindex; + rtnl_unlock(); } if (dst_addr->sa_family == AF_INET) { diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 31a5816c2e8d..dcb190e75343 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -205,7 +205,6 @@ enum cxgbi_skcb_flags { SKCBF_TX_NEED_HDR, /* packet needs a header */ SKCBF_TX_MEM_WRITE, /* memory write */ SKCBF_TX_FLAG_COMPL, /* wr completion flag */ - SKCBF_TX_DONE, /* skb tx done */ SKCBF_RX_COALESCED, /* received whole pdu */ SKCBF_RX_HDR, /* received pdu header */ SKCBF_RX_DATA, /* received pdu payload */ |