aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/scsi/be2iscsi/be_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/be2iscsi/be_main.c')
-rw-r--r--drivers/scsi/be2iscsi/be_main.c397
1 files changed, 157 insertions, 240 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 32b2713cec93..f862332261f8 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -1,20 +1,15 @@
-/**
- * Copyright (C) 2005 - 2016 Broadcom
- * All rights reserved.
+/*
+ * Copyright 2017 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation. The full GNU General
+ * as published by the Free Software Foundation. The full GNU General
* Public License is included in this distribution in the file called COPYING.
*
- * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
- *
* Contact Information:
* linux-drivers@broadcom.com
*
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
*/
#include <linux/reboot.h>
@@ -337,7 +332,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
inv_tbl->task[nents] = task;
nents++;
}
- spin_unlock_bh(&session->back_lock);
+ spin_unlock(&session->back_lock);
spin_unlock_bh(&session->frwd_lock);
rc = SUCCESS;
@@ -636,7 +631,6 @@ static void beiscsi_get_params(struct beiscsi_hba *phba)
(total_cid_count +
BE2_TMFS + BE2_NOPOUT_REQ));
phba->params.cxns_per_ctrl = total_cid_count;
- phba->params.asyncpdus_per_ctrl = total_cid_count;
phba->params.icds_per_ctrl = total_icd_count;
phba->params.num_sge_per_io = BE2_SGE;
phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
@@ -802,12 +796,12 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
struct pci_dev *pcidev = phba->pcidev;
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context;
- int ret, msix_vec, i, j;
+ int ret, i, j;
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
- if (phba->msix_enabled) {
+ if (pcidev->msix_enabled) {
for (i = 0; i < phba->num_cpus; i++) {
phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME,
GFP_KERNEL);
@@ -818,9 +812,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
sprintf(phba->msi_name[i], "beiscsi_%02x_%02x",
phba->shost->host_no, i);
- msix_vec = phba->msix_entries[i].vector;
- ret = request_irq(msix_vec, be_isr_msix, 0,
- phba->msi_name[i],
+ ret = request_irq(pci_irq_vector(pcidev, i),
+ be_isr_msix, 0, phba->msi_name[i],
&phwi_context->be_eq[i]);
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
@@ -838,9 +831,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
}
sprintf(phba->msi_name[i], "beiscsi_mcc_%02x",
phba->shost->host_no);
- msix_vec = phba->msix_entries[i].vector;
- ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i],
- &phwi_context->be_eq[i]);
+ ret = request_irq(pci_irq_vector(pcidev, i), be_isr_mcc, 0,
+ phba->msi_name[i], &phwi_context->be_eq[i]);
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT ,
"BM_%d : beiscsi_init_irqs-"
@@ -862,9 +854,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
return 0;
free_msix_irqs:
for (j = i - 1; j >= 0; j--) {
+ free_irq(pci_irq_vector(pcidev, i), &phwi_context->be_eq[j]);
kfree(phba->msi_name[j]);
- msix_vec = phba->msix_entries[j].vector;
- free_irq(msix_vec, &phwi_context->be_eq[j]);
}
return ret;
}
@@ -1454,30 +1445,45 @@ static inline void
beiscsi_hdl_put_handle(struct hd_async_context *pasync_ctx,
struct hd_async_handle *pasync_handle)
{
- if (pasync_handle->is_header) {
- list_add_tail(&pasync_handle->link,
- &pasync_ctx->async_header.free_list);
- pasync_ctx->async_header.free_entries++;
- } else {
- list_add_tail(&pasync_handle->link,
- &pasync_ctx->async_data.free_list);
- pasync_ctx->async_data.free_entries++;
- }
+ pasync_handle->is_final = 0;
+ pasync_handle->buffer_len = 0;
+ pasync_handle->in_use = 0;
+ list_del_init(&pasync_handle->link);
+}
+
+static void
+beiscsi_hdl_purge_handles(struct beiscsi_hba *phba,
+ struct hd_async_context *pasync_ctx,
+ u16 cri)
+{
+ struct hd_async_handle *pasync_handle, *tmp_handle;
+ struct list_head *plist;
+
+ plist = &pasync_ctx->async_entry[cri].wq.list;
+ list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link)
+ beiscsi_hdl_put_handle(pasync_ctx, pasync_handle);
+
+ INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list);
+ pasync_ctx->async_entry[cri].wq.hdr_len = 0;
+ pasync_ctx->async_entry[cri].wq.bytes_received = 0;
+ pasync_ctx->async_entry[cri].wq.bytes_needed = 0;
}
static struct hd_async_handle *
beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
struct hd_async_context *pasync_ctx,
- struct i_t_dpdu_cqe *pdpdu_cqe)
+ struct i_t_dpdu_cqe *pdpdu_cqe,
+ u8 *header)
{
struct beiscsi_hba *phba = beiscsi_conn->phba;
struct hd_async_handle *pasync_handle;
struct be_bus_address phys_addr;
+ u16 cid, code, ci, cri;
u8 final, error = 0;
- u16 cid, code, ci;
u32 dpl;
cid = beiscsi_conn->beiscsi_conn_cid;
+ cri = BE_GET_ASYNC_CRI_FROM_CID(cid);
/**
* This function is invoked to get the right async_handle structure
* from a given DEF PDU CQ entry.
@@ -1516,6 +1522,7 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
switch (code) {
case UNSOL_HDR_NOTIFY:
pasync_handle = pasync_ctx->async_entry[ci].header;
+ *header = 1;
break;
case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
error = 1;
@@ -1524,15 +1531,7 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
break;
/* called only for above codes */
default:
- pasync_handle = NULL;
- break;
- }
-
- if (!pasync_handle) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
- "BM_%d : cid %d async PDU handle not found - code %d ci %d addr %llx\n",
- cid, code, ci, phys_addr.u.a64.address);
- return pasync_handle;
+ return NULL;
}
if (pasync_handle->pa.u.a64.address != phys_addr.u.a64.address ||
@@ -1549,47 +1548,32 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
}
/**
- * Each CID is associated with unique CRI.
- * ASYNC_CRI_FROM_CID mapping and CRI_FROM_CID are totaly different.
- **/
- pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID(cid);
- pasync_handle->is_final = final;
- pasync_handle->buffer_len = dpl;
- /* empty the slot */
- if (pasync_handle->is_header)
- pasync_ctx->async_entry[ci].header = NULL;
- else
- pasync_ctx->async_entry[ci].data = NULL;
-
- /**
* DEF PDU header and data buffers with errors should be simply
* dropped as there are no consumers for it.
*/
if (error) {
beiscsi_hdl_put_handle(pasync_ctx, pasync_handle);
- pasync_handle = NULL;
+ return NULL;
}
- return pasync_handle;
-}
-
-static void
-beiscsi_hdl_purge_handles(struct beiscsi_hba *phba,
- struct hd_async_context *pasync_ctx,
- u16 cri)
-{
- struct hd_async_handle *pasync_handle, *tmp_handle;
- struct list_head *plist;
- plist = &pasync_ctx->async_entry[cri].wq.list;
- list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) {
- list_del(&pasync_handle->link);
- beiscsi_hdl_put_handle(pasync_ctx, pasync_handle);
+ if (pasync_handle->in_use || !list_empty(&pasync_handle->link)) {
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
+ "BM_%d : cid %d async PDU handle in use - code %d ci %d addr %llx\n",
+ cid, code, ci, phys_addr.u.a64.address);
+ beiscsi_hdl_purge_handles(phba, pasync_ctx, cri);
}
- INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list);
- pasync_ctx->async_entry[cri].wq.hdr_len = 0;
- pasync_ctx->async_entry[cri].wq.bytes_received = 0;
- pasync_ctx->async_entry[cri].wq.bytes_needed = 0;
+ list_del_init(&pasync_handle->link);
+ /**
+ * Each CID is associated with unique CRI.
+ * ASYNC_CRI_FROM_CID mapping and CRI_FROM_CID are totaly different.
+ **/
+ pasync_handle->cri = cri;
+ pasync_handle->is_final = final;
+ pasync_handle->buffer_len = dpl;
+ pasync_handle->in_use = 1;
+
+ return pasync_handle;
}
static unsigned int
@@ -1619,6 +1603,10 @@ beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn,
dlen = pasync_handle->buffer_len;
continue;
}
+ if (!pasync_handle->buffer_len ||
+ (dlen + pasync_handle->buffer_len) >
+ pasync_ctx->async_data.buffer_size)
+ break;
memcpy(pdata + dlen, pasync_handle->pbuffer,
pasync_handle->buffer_len);
dlen += pasync_handle->buffer_len;
@@ -1627,8 +1615,9 @@ beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn,
if (!plast_handle->is_final) {
/* last handle should have final PDU notification from FW */
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
- "BM_%d : cid %u %p fwd async PDU with last handle missing - HL%u:DN%u:DR%u\n",
+ "BM_%d : cid %u %p fwd async PDU opcode %x with last handle missing - HL%u:DN%u:DR%u\n",
beiscsi_conn->beiscsi_conn_cid, plast_handle,
+ AMAP_GET_BITS(struct amap_pdu_base, opcode, phdr),
pasync_ctx->async_entry[cri].wq.hdr_len,
pasync_ctx->async_entry[cri].wq.bytes_needed,
pasync_ctx->async_entry[cri].wq.bytes_received);
@@ -1709,85 +1698,53 @@ drop_pdu:
static void
beiscsi_hdq_post_handles(struct beiscsi_hba *phba,
- u8 header, u8 ulp_num)
+ u8 header, u8 ulp_num, u16 nbuf)
{
- struct hd_async_handle *pasync_handle, *tmp, **slot;
+ struct hd_async_handle *pasync_handle;
struct hd_async_context *pasync_ctx;
struct hwi_controller *phwi_ctrlr;
- struct list_head *hfree_list;
struct phys_addr *pasync_sge;
u32 ring_id, doorbell = 0;
u32 doorbell_offset;
- u16 prod = 0, cons;
- u16 index;
+ u16 prod, pi;
phwi_ctrlr = phba->phwi_ctrlr;
pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num);
if (header) {
- cons = pasync_ctx->async_header.free_entries;
- hfree_list = &pasync_ctx->async_header.free_list;
+ pasync_sge = pasync_ctx->async_header.ring_base;
+ pi = pasync_ctx->async_header.pi;
ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id;
doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num].
doorbell_offset;
} else {
- cons = pasync_ctx->async_data.free_entries;
- hfree_list = &pasync_ctx->async_data.free_list;
+ pasync_sge = pasync_ctx->async_data.ring_base;
+ pi = pasync_ctx->async_data.pi;
ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id;
doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num].
doorbell_offset;
}
- /* number of entries posted must be in multiples of 8 */
- if (cons % 8)
- return;
-
- list_for_each_entry_safe(pasync_handle, tmp, hfree_list, link) {
- list_del_init(&pasync_handle->link);
- pasync_handle->is_final = 0;
- pasync_handle->buffer_len = 0;
- /* handles can be consumed out of order, use index in handle */
- index = pasync_handle->index;
- WARN_ON(pasync_handle->is_header != header);
+ for (prod = 0; prod < nbuf; prod++) {
if (header)
- slot = &pasync_ctx->async_entry[index].header;
+ pasync_handle = pasync_ctx->async_entry[pi].header;
else
- slot = &pasync_ctx->async_entry[index].data;
- /**
- * The slot just tracks handle's hold and release, so
- * overwriting at the same index won't do any harm but
- * needs to be caught.
- */
- if (*slot != NULL) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
- "BM_%d : async PDU %s slot at %u not empty\n",
- header ? "header" : "data", index);
+ pasync_handle = pasync_ctx->async_entry[pi].data;
+ WARN_ON(pasync_handle->is_header != header);
+ WARN_ON(pasync_handle->index != pi);
+ /* setup the ring only once */
+ if (nbuf == pasync_ctx->num_entries) {
+ /* note hi is lo */
+ pasync_sge[pi].hi = pasync_handle->pa.u.a32.address_lo;
+ pasync_sge[pi].lo = pasync_handle->pa.u.a32.address_hi;
}
- /**
- * We use same freed index as in completion to post so this
- * operation is not required for refills. Its required only
- * for ring creation.
- */
- if (header)
- pasync_sge = pasync_ctx->async_header.ring_base;
- else
- pasync_sge = pasync_ctx->async_data.ring_base;
- pasync_sge += index;
- /* if its a refill then address is same; hi is lo */
- WARN_ON(pasync_sge->hi &&
- pasync_sge->hi != pasync_handle->pa.u.a32.address_lo);
- WARN_ON(pasync_sge->lo &&
- pasync_sge->lo != pasync_handle->pa.u.a32.address_hi);
- pasync_sge->hi = pasync_handle->pa.u.a32.address_lo;
- pasync_sge->lo = pasync_handle->pa.u.a32.address_hi;
-
- *slot = pasync_handle;
- if (++prod == cons)
- break;
+ if (++pi == pasync_ctx->num_entries)
+ pi = 0;
}
+
if (header)
- pasync_ctx->async_header.free_entries -= prod;
+ pasync_ctx->async_header.pi = pi;
else
- pasync_ctx->async_data.free_entries -= prod;
+ pasync_ctx->async_data.pi = pi;
doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK;
doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT;
@@ -1804,20 +1761,26 @@ beiscsi_hdq_process_compl(struct beiscsi_conn *beiscsi_conn,
struct hd_async_handle *pasync_handle = NULL;
struct hd_async_context *pasync_ctx;
struct hwi_controller *phwi_ctrlr;
+ u8 ulp_num, consumed, header = 0;
u16 cid_cri;
- u8 ulp_num;
phwi_ctrlr = phba->phwi_ctrlr;
cid_cri = BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid);
ulp_num = BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cid_cri);
pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num);
pasync_handle = beiscsi_hdl_get_handle(beiscsi_conn, pasync_ctx,
- pdpdu_cqe);
- if (!pasync_handle)
- return;
-
- beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle);
- beiscsi_hdq_post_handles(phba, pasync_handle->is_header, ulp_num);
+ pdpdu_cqe, &header);
+ if (is_chip_be2_be3r(phba))
+ consumed = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+ num_cons, pdpdu_cqe);
+ else
+ consumed = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+ num_cons, pdpdu_cqe);
+ if (pasync_handle)
+ beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle);
+ /* num_cons indicates number of 8 RQEs consumed */
+ if (consumed)
+ beiscsi_hdq_post_handles(phba, header, ulp_num, 8 * consumed);
}
void beiscsi_process_mcc_cq(struct beiscsi_hba *phba)
@@ -2407,22 +2370,22 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
num_async_pdu_buf_sgl_pages =
- PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
+ PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
phba, ulp_num) *
sizeof(struct phys_addr));
num_async_pdu_buf_pages =
- PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
+ PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
phba, ulp_num) *
phba->params.defpdu_hdr_sz);
num_async_pdu_data_pages =
- PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
+ PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
phba, ulp_num) *
phba->params.defpdu_data_sz);
num_async_pdu_data_sgl_pages =
- PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
+ PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
phba, ulp_num) *
sizeof(struct phys_addr));
@@ -2459,21 +2422,21 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
mem_descr_index = (HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 +
(ulp_num * MEM_DESCR_OFFSET));
phba->mem_req[mem_descr_index] =
- BEISCSI_GET_CID_COUNT(phba, ulp_num) *
- sizeof(struct hd_async_handle);
+ BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) *
+ sizeof(struct hd_async_handle);
mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 +
(ulp_num * MEM_DESCR_OFFSET));
phba->mem_req[mem_descr_index] =
- BEISCSI_GET_CID_COUNT(phba, ulp_num) *
- sizeof(struct hd_async_handle);
+ BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) *
+ sizeof(struct hd_async_handle);
mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 +
(ulp_num * MEM_DESCR_OFFSET));
phba->mem_req[mem_descr_index] =
- sizeof(struct hd_async_context) +
- (BEISCSI_GET_CID_COUNT(phba, ulp_num) *
- sizeof(struct hd_async_entry));
+ sizeof(struct hd_async_context) +
+ (BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) *
+ sizeof(struct hd_async_entry));
}
}
}
@@ -2757,7 +2720,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
((long unsigned int)pasync_ctx +
sizeof(struct hd_async_context));
- pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba,
+ pasync_ctx->num_entries = BEISCSI_ASYNC_HDQ_SIZE(phba,
ulp_num);
/* setup header buffers */
mem_descr = (struct be_mem_descriptor *)phba->init_mem;
@@ -2776,6 +2739,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
"BM_%d : No Virtual address for ULP : %d\n",
ulp_num);
+ pasync_ctx->async_header.pi = 0;
pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz;
pasync_ctx->async_header.va_base =
mem_descr->mem_array[0].virtual_address;
@@ -2823,7 +2787,6 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_ctx->async_header.handle_base =
mem_descr->mem_array[0].virtual_address;
- INIT_LIST_HEAD(&pasync_ctx->async_header.free_list);
/* setup data buffer sgls */
mem_descr = (struct be_mem_descriptor *)phba->init_mem;
@@ -2857,7 +2820,6 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_ctx->async_data.handle_base =
mem_descr->mem_array[0].virtual_address;
- INIT_LIST_HEAD(&pasync_ctx->async_data.free_list);
pasync_header_h =
(struct hd_async_handle *)
@@ -2884,6 +2846,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
ulp_num);
idx = 0;
+ pasync_ctx->async_data.pi = 0;
pasync_ctx->async_data.buffer_size = p->defpdu_data_sz;
pasync_ctx->async_data.va_base =
mem_descr->mem_array[idx].virtual_address;
@@ -2895,7 +2858,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
phba->params.defpdu_data_sz);
num_per_mem = 0;
- for (index = 0; index < BEISCSI_GET_CID_COUNT
+ for (index = 0; index < BEISCSI_ASYNC_HDQ_SIZE
(phba, ulp_num); index++) {
pasync_header_h->cri = -1;
pasync_header_h->is_header = 1;
@@ -2911,14 +2874,11 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_ctx->async_header.pa_base.u.a64.
address + (p->defpdu_hdr_sz * index);
- list_add_tail(&pasync_header_h->link,
- &pasync_ctx->async_header.
- free_list);
+ pasync_ctx->async_entry[index].header =
+ pasync_header_h;
pasync_header_h++;
- pasync_ctx->async_header.free_entries++;
INIT_LIST_HEAD(&pasync_ctx->async_entry[index].
wq.list);
- pasync_ctx->async_entry[index].header = NULL;
pasync_data_h->cri = -1;
pasync_data_h->is_header = 0;
@@ -2952,12 +2912,9 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
num_per_mem++;
num_async_data--;
- list_add_tail(&pasync_data_h->link,
- &pasync_ctx->async_data.
- free_list);
+ pasync_ctx->async_entry[index].data =
+ pasync_data_h;
pasync_data_h++;
- pasync_ctx->async_data.free_entries++;
- pasync_ctx->async_entry[index].data = NULL;
}
}
}
@@ -3040,7 +2997,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \
sizeof(struct be_eq_entry));
- if (phba->msix_enabled)
+ if (phba->pcidev->msix_enabled)
eq_for_mcc = 1;
else
eq_for_mcc = 0;
@@ -3550,7 +3507,7 @@ static int be_mcc_queues_create(struct beiscsi_hba *phba,
sizeof(struct be_mcc_compl)))
goto err;
/* Ask BE to create MCC compl queue; */
- if (phba->msix_enabled) {
+ if (phba->pcidev->msix_enabled) {
if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq
[phba->num_cpus].q, false, true, 0))
goto mcc_cq_free;
@@ -3581,42 +3538,35 @@ err:
return -ENOMEM;
}
-/**
- * find_num_cpus()- Get the CPU online count
- * @phba: ptr to priv structure
- *
- * CPU count is used for creating EQ.
- **/
-static void find_num_cpus(struct beiscsi_hba *phba)
+static void be2iscsi_enable_msix(struct beiscsi_hba *phba)
{
- int num_cpus = 0;
-
- num_cpus = num_online_cpus();
+ int nvec = 1;
switch (phba->generation) {
case BE_GEN2:
case BE_GEN3:
- phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ?
- BEISCSI_MAX_NUM_CPUS : num_cpus;
+ nvec = BEISCSI_MAX_NUM_CPUS + 1;
break;
case BE_GEN4:
- /*
- * If eqid_count == 1 fall back to
- * INTX mechanism
- **/
- if (phba->fw_config.eqid_count == 1) {
- enable_msix = 0;
- phba->num_cpus = 1;
- return;
- }
-
- phba->num_cpus =
- (num_cpus > (phba->fw_config.eqid_count - 1)) ?
- (phba->fw_config.eqid_count - 1) : num_cpus;
+ nvec = phba->fw_config.eqid_count;
break;
default:
- phba->num_cpus = 1;
+ nvec = 2;
+ break;
}
+
+ /* if eqid_count == 1 fall back to INTX */
+ if (enable_msix && nvec > 1) {
+ const struct irq_affinity desc = { .post_vectors = 1 };
+
+ if (pci_alloc_irq_vectors_affinity(phba->pcidev, 2, nvec,
+ PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc) < 0) {
+ phba->num_cpus = nvec - 1;
+ return;
+ }
+ }
+
+ phba->num_cpus = 1;
}
static void hwi_purge_eq(struct beiscsi_hba *phba)
@@ -3633,7 +3583,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
- if (phba->msix_enabled)
+ if (phba->pcidev->msix_enabled)
eq_msix = 1;
else
eq_msix = 0;
@@ -3711,7 +3661,7 @@ static void hwi_cleanup_port(struct beiscsi_hba *phba)
}
be_mcc_queues_destroy(phba);
- if (phba->msix_enabled)
+ if (phba->pcidev->msix_enabled)
eq_for_mcc = 1;
else
eq_for_mcc = 0;
@@ -3735,6 +3685,7 @@ static int hwi_init_port(struct beiscsi_hba *phba)
unsigned int def_pdu_ring_sz;
struct be_ctrl_info *ctrl = &phba->ctrl;
int status, ulp_num;
+ u16 nbufs;
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -3771,9 +3722,8 @@ static int hwi_init_port(struct beiscsi_hba *phba)
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
- def_pdu_ring_sz =
- BEISCSI_GET_CID_COUNT(phba, ulp_num) *
- sizeof(struct phys_addr);
+ nbufs = phwi_context->pasync_ctx[ulp_num]->num_entries;
+ def_pdu_ring_sz = nbufs * sizeof(struct phys_addr);
status = beiscsi_create_def_hdr(phba, phwi_context,
phwi_ctrlr,
@@ -3801,9 +3751,9 @@ static int hwi_init_port(struct beiscsi_hba *phba)
* let EP know about it.
*/
beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR,
- ulp_num);
+ ulp_num, nbufs);
beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_DATA,
- ulp_num);
+ ulp_num, nbufs);
}
}
@@ -4157,7 +4107,7 @@ static void hwi_enable_intr(struct beiscsi_hba *phba)
iowrite32(reg, addr);
}
- if (!phba->msix_enabled) {
+ if (!phba->pcidev->msix_enabled) {
eq = &phwi_context->be_eq[0].q;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BM_%d : eq->id=%d\n", eq->id);
@@ -5280,19 +5230,6 @@ static void beiscsi_eqd_update_work(struct work_struct *work)
msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL));
}
-static void beiscsi_msix_enable(struct beiscsi_hba *phba)
-{
- int i, status;
-
- for (i = 0; i <= phba->num_cpus; i++)
- phba->msix_entries[i].entry = i;
-
- status = pci_enable_msix_range(phba->pcidev, phba->msix_entries,
- phba->num_cpus + 1, phba->num_cpus + 1);
- if (status > 0)
- phba->msix_enabled = true;
-}
-
static void beiscsi_hw_tpe_check(unsigned long ptr)
{
struct beiscsi_hba *phba;
@@ -5360,15 +5297,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba)
if (ret)
return ret;
- if (enable_msix)
- find_num_cpus(phba);
- else
- phba->num_cpus = 1;
- if (enable_msix) {
- beiscsi_msix_enable(phba);
- if (!phba->msix_enabled)
- phba->num_cpus = 1;
- }
+ be2iscsi_enable_msix(phba);
beiscsi_get_params(phba);
/* Re-enable UER. If different TPE occurs then it is recoverable. */
@@ -5397,7 +5326,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba)
irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll);
}
- i = (phba->msix_enabled) ? i : 0;
+ i = (phba->pcidev->msix_enabled) ? i : 0;
/* Work item for MCC handling */
pbe_eq = &phwi_context->be_eq[i];
INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work);
@@ -5435,9 +5364,7 @@ cleanup_port:
hwi_cleanup_port(phba);
disable_msix:
- if (phba->msix_enabled)
- pci_disable_msix(phba->pcidev);
-
+ pci_free_irq_vectors(phba->pcidev);
return ret;
}
@@ -5454,7 +5381,7 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload)
struct hwi_context_memory *phwi_context;
struct hwi_controller *phwi_ctrlr;
struct be_eq_obj *pbe_eq;
- unsigned int i, msix_vec;
+ unsigned int i;
if (!test_and_clear_bit(BEISCSI_HBA_ONLINE, &phba->state))
return;
@@ -5462,16 +5389,16 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload)
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
hwi_disable_intr(phba);
- if (phba->msix_enabled) {
+ if (phba->pcidev->msix_enabled) {
for (i = 0; i <= phba->num_cpus; i++) {
- msix_vec = phba->msix_entries[i].vector;
- free_irq(msix_vec, &phwi_context->be_eq[i]);
+ free_irq(pci_irq_vector(phba->pcidev, i),
+ &phwi_context->be_eq[i]);
kfree(phba->msi_name[i]);
}
} else
if (phba->pcidev->irq)
free_irq(phba->pcidev->irq, phba);
- pci_disable_msix(phba->pcidev);
+ pci_free_irq_vectors(phba->pcidev);
for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i];
@@ -5681,21 +5608,12 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
beiscsi_get_params(phba);
beiscsi_set_uer_feature(phba);
- if (enable_msix)
- find_num_cpus(phba);
- else
- phba->num_cpus = 1;
+ be2iscsi_enable_msix(phba);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BM_%d : num_cpus = %d\n",
phba->num_cpus);
- if (enable_msix) {
- beiscsi_msix_enable(phba);
- if (!phba->msix_enabled)
- phba->num_cpus = 1;
- }
-
phba->shost->max_id = phba->params.cxns_per_ctrl;
phba->shost->can_queue = phba->params.ios_per_ctrl;
ret = beiscsi_get_memory(phba);
@@ -5745,7 +5663,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll);
}
- i = (phba->msix_enabled) ? i : 0;
+ i = (phba->pcidev->msix_enabled) ? i : 0;
/* Work item for MCC handling */
pbe_eq = &phwi_context->be_eq[i];
INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work);
@@ -5816,8 +5734,7 @@ free_port:
phba->ctrl.mbox_mem_alloced.dma);
beiscsi_unmap_pci_function(phba);
hba_free:
- if (phba->msix_enabled)
- pci_disable_msix(phba->pcidev);
+ pci_disable_msix(phba->pcidev);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);
pci_set_drvdata(pcidev, NULL);