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 &&
return -ENOMEM;
}
+ skb_get(tdata->skb);
skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
task->hdr = (struct iscsi_hdr *)tdata->skb->data;
task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
unsigned int datalen;
int err;
- if (!skb) {
+ if (!skb || cxgbi_skcb_test_flag(skb, SKCBF_TX_DONE)) {
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
- "task 0x%p, skb NULL.\n", task);
+ "task 0x%p, skb 0x%p\n", task, skb);
return 0;
}
}
datalen = skb->data_len;
- tdata->skb = NULL;
/* write ppod first if using ofldq to write ppod */
if (ttinfo->flags & CXGBI_PPOD_INFO_FLAG_VALID) {
pdulen += ISCSI_DIGEST_SIZE;
task->conn->txdata_octets += pdulen;
+ cxgbi_skcb_set_flag(skb, SKCBF_TX_DONE);
return 0;
}
"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;
}
"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);
+ __kfree_skb(tdata->skb);
+ tdata->skb = NULL;
iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
tcp_task->dd_data = NULL;
/* never reached the xmit task callout */
- if (tdata->skb)
- __kfree_skb(tdata->skb);
+ if (tdata->skb) {
+ kfree_skb(tdata->skb);
+ tdata->skb = NULL;
+ }
task_release_itt(task, task->hdr_itt);
memset(tdata, 0, sizeof(*tdata));
static int __init libcxgbi_init_module(void)
{
pr_info("%s", version);
+
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+ sizeof(struct cxgbi_skb_cb));
return 0;
}
};
struct cxgbi_skb_tx_cb {
- void *l2t;
+ void *handle;
+ void *arp_err_handler;
struct sk_buff *wr_next;
};
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 */
};
struct cxgbi_skb_cb {
- unsigned char ulp_mode;
- unsigned long flags;
- unsigned int seq;
union {
struct cxgbi_skb_rx_cb rx;
struct cxgbi_skb_tx_cb tx;
};
+ unsigned char ulp_mode;
+ unsigned long flags;
+ unsigned int seq;
};
#define CXGBI_SKB_CB(skb) ((struct cxgbi_skb_cb *)&((skb)->cb[0]))
cxgbi_skcb_tx_wr_next(skb) = NULL;
/*
* We want to take an extra reference since both us and the driver
- * need to free the packet before it's really freed. We know there's
- * just one user currently so we use atomic_set rather than skb_get
- * to avoid the atomic op.
+ * need to free the packet before it's really freed.
*/
- atomic_set(&skb->users, 2);
+ skb_get(skb);
if (!csk->wr_pending_head)
csk->wr_pending_head = skb;
struct list_head *list,
unsigned char *cdb)
{
- struct scsi_device *sdev = ctlr->ms_sdev;
- struct rdac_dh_data *h = sdev->handler_data;
struct rdac_mode_common *common;
unsigned data_size;
struct rdac_queue_data *qdata;
u8 *lun_table;
- if (h->ctlr->use_ms10) {
+ if (ctlr->use_ms10) {
struct rdac_pg_expanded *rdac_pg;
data_size = sizeof(struct rdac_pg_expanded);
- rdac_pg = &h->ctlr->mode_select.expanded;
+ rdac_pg = &ctlr->mode_select.expanded;
memset(rdac_pg, 0, data_size);
common = &rdac_pg->common;
rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;
struct rdac_pg_legacy *rdac_pg;
data_size = sizeof(struct rdac_pg_legacy);
- rdac_pg = &h->ctlr->mode_select.legacy;
+ rdac_pg = &ctlr->mode_select.legacy;
memset(rdac_pg, 0, data_size);
common = &rdac_pg->common;
rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
}
/* Prepare the command. */
- if (h->ctlr->use_ms10) {
+ if (ctlr->use_ms10) {
cdb[0] = MODE_SELECT_10;
cdb[7] = data_size >> 8;
cdb[8] = data_size & 0xff;
#define QEDI_MAX_ISCSI_TASK 4096
#define QEDI_MAX_TASK_NUM 0x0FFF
#define QEDI_MAX_ISCSI_CONNS_PER_HBA 1024
-#define QEDI_ISCSI_MAX_BDS_PER_CMD 256 /* Firmware max BDs is 256 */
+#define QEDI_ISCSI_MAX_BDS_PER_CMD 255 /* Firmware max BDs is 255 */
#define MAX_OUSTANDING_TASKS_PER_CON 1024
#define QEDI_MAX_BD_LEN 0xffff
#define QEDI_PAGE_MASK (~((QEDI_PAGE_SIZE) - 1))
#define QEDI_PAGE_SIZE 4096
+#define QEDI_HW_DMA_BOUNDARY 0xfff
#define QEDI_PATH_HANDLE 0xFE0000000UL
struct qedi_uio_ctrl {
tmf_hdr = (struct iscsi_tm *)mtask->hdr;
qedi_cmd = (struct qedi_cmd *)mtask->dd_data;
ep = qedi_conn->ep;
+ if (!ep)
+ return -ENODEV;
tid = qedi_get_task_idx(qedi);
if (tid == -1)
.this_id = -1,
.sg_tablesize = QEDI_ISCSI_MAX_BDS_PER_CMD,
.max_sectors = 0xffff,
+ .dma_boundary = QEDI_HW_DMA_BOUNDARY,
.cmd_per_lun = 128,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = qedi_shost_attrs,
iscsi_cid = (u32)path_data->handle;
qedi_ep = qedi->ep_tbl[iscsi_cid];
- QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_CONN,
+ QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
"iscsi_cid=0x%x, qedi_ep=%p\n", iscsi_cid, qedi_ep);
+ if (!qedi_ep) {
+ ret = -EINVAL;
+ goto set_path_exit;
+ }
if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
static void __qedi_free_uio_rings(struct qedi_uio_dev *udev)
{
+ if (udev->uctrl) {
+ free_page((unsigned long)udev->uctrl);
+ udev->uctrl = NULL;
+ }
+
if (udev->ll2_ring) {
free_page((unsigned long)udev->ll2_ring);
udev->ll2_ring = NULL;
__qedi_free_uio_rings(udev);
pci_dev_put(udev->pdev);
- kfree(udev->uctrl);
kfree(udev);
}
if (udev->ll2_ring || udev->ll2_buf)
return rc;
+ /* Memory for control area. */
+ udev->uctrl = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!udev->uctrl)
+ return -ENOMEM;
+
/* Allocating memory for LL2 ring */
udev->ll2_ring_size = QEDI_PAGE_SIZE;
udev->ll2_ring = (void *)get_zeroed_page(GFP_KERNEL | __GFP_COMP);
static int qedi_alloc_uio_rings(struct qedi_ctx *qedi)
{
struct qedi_uio_dev *udev = NULL;
- struct qedi_uio_ctrl *uctrl = NULL;
int rc = 0;
list_for_each_entry(udev, &qedi_udev_list, list) {
goto err_udev;
}
- uctrl = kzalloc(sizeof(*uctrl), GFP_KERNEL);
- if (!uctrl) {
- rc = -ENOMEM;
- goto err_uctrl;
- }
-
udev->uio_dev = -1;
udev->qedi = qedi;
udev->pdev = qedi->pdev;
- udev->uctrl = uctrl;
rc = __qedi_alloc_uio_rings(udev);
if (rc)
- goto err_uio_rings;
+ goto err_uctrl;
list_add(&udev->list, &qedi_udev_list);
udev->rx_pkt = udev->ll2_buf + LL2_SINGLE_BUF_SIZE;
return 0;
- err_uio_rings:
- kfree(uctrl);
err_uctrl:
kfree(udev);
err_udev:
qedi->pf_params.iscsi_pf_params.num_uhq_pages_in_ring = num_sq_pages;
qedi->pf_params.iscsi_pf_params.num_queues = qedi->num_queues;
qedi->pf_params.iscsi_pf_params.debug_mode = qedi_fw_debug;
+ qedi->pf_params.iscsi_pf_params.two_msl_timer = 4000;
+ qedi->pf_params.iscsi_pf_params.max_fin_rt = 2;
for (log_page_size = 0 ; log_page_size < 32 ; log_page_size++) {
if ((1 << log_page_size) == PAGE_SIZE)