summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/be2iscsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r--drivers/scsi/be2iscsi/be.h12
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c17
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h74
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c111
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.h13
-rw-r--r--drivers/scsi/be2iscsi/be_main.c397
-rw-r--r--drivers/scsi/be2iscsi/be_main.h30
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c140
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h43
9 files changed, 360 insertions, 477 deletions
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
index ca9440fb2325..55e3f8b40eb3 100644
--- a/drivers/scsi/be2iscsi/be.h
+++ b/drivers/scsi/be2iscsi/be.h
@@ -1,18 +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.
*
* Contact Information:
* linux-drivers@broadcom.com
*
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
*/
#ifndef BEISCSI_H
@@ -154,7 +151,6 @@ struct be_ctrl_info {
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
#define mcc_timeout 120000 /* 12s timeout */
-#define BEISCSI_LOGOUT_SYNC_DELAY 250
/* Returns number of pages spanned by the data starting at the given addr */
#define PAGES_4K_SPANNED(_address, size) \
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 5d59e2630ce6..a79a5e72c777 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -1,18 +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.
*
* Contact Information:
* linux-drivers@broadcom.com
*
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
*/
#include <scsi/iscsi_proto.h>
@@ -246,6 +243,12 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba,
{
int rc = 0;
+ if (!tag || tag > MAX_MCC_CMD) {
+ __beiscsi_log(phba, KERN_ERR,
+ "BC_%d : invalid tag %u\n", tag);
+ return -EINVAL;
+ }
+
if (beiscsi_hba_in_error(phba)) {
clear_bit(MCC_TAG_STATE_RUNNING,
&phba->ctrl.ptag_state[tag].tag_state);
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 1d40e83b0790..d9b6773facdb 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -1,18 +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.
*
* Contact Information:
* linux-drivers@broadcom.com
*
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
*/
#ifndef BEISCSI_CMDS_H
@@ -1145,24 +1142,49 @@ struct tcp_connect_and_offload_out {
#define DB_DEF_PDU_EVENT_SHIFT 15
#define DB_DEF_PDU_CQPROC_SHIFT 16
-struct dmsg_cqe {
- u32 dw[4];
+struct be_invalidate_connection_params_in {
+ struct be_cmd_req_hdr hdr;
+ u32 session_handle;
+ u16 cid;
+ u16 unused;
+#define BE_CLEANUP_TYPE_INVALIDATE 0x8001
+#define BE_CLEANUP_TYPE_ISSUE_TCP_RST 0x8002
+ u16 cleanup_type;
+ u16 save_cfg;
+} __packed;
+
+struct be_invalidate_connection_params_out {
+ u32 session_handle;
+ u16 cid;
+ u16 unused;
+} __packed;
+
+union be_invalidate_connection_params {
+ struct be_invalidate_connection_params_in req;
+ struct be_invalidate_connection_params_out resp;
} __packed;
-struct tcp_upload_params_in {
+struct be_tcp_upload_params_in {
struct be_cmd_req_hdr hdr;
u16 id;
+#define BE_UPLOAD_TYPE_GRACEFUL 1
+/* abortive upload with reset */
+#define BE_UPLOAD_TYPE_ABORT_RESET 2
+/* abortive upload without reset */
+#define BE_UPLOAD_TYPE_ABORT 3
+/* abortive upload with reset, sequence number by driver */
+#define BE_UPLOAD_TYPE_ABORT_WITH_SEQ 4
u16 upload_type;
u32 reset_seq;
} __packed;
-struct tcp_upload_params_out {
+struct be_tcp_upload_params_out {
u32 dw[32];
} __packed;
-union tcp_upload_params {
- struct tcp_upload_params_in request;
- struct tcp_upload_params_out response;
+union be_tcp_upload_params {
+ struct be_tcp_upload_params_in request;
+ struct be_tcp_upload_params_out response;
} __packed;
struct be_ulp_fw_cfg {
@@ -1243,10 +1265,7 @@ struct be_cmd_get_port_name {
#define OPCODE_COMMON_WRITE_FLASH 96
#define OPCODE_COMMON_READ_FLASH 97
-/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
#define CMD_ISCSI_COMMAND_INVALIDATE 1
-#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001
-#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002
#define INI_WR_CMD 1 /* Initiator write command */
#define INI_TMF_CMD 2 /* Initiator TMF command */
@@ -1269,27 +1288,6 @@ struct be_cmd_get_port_name {
* preparedby
* driver should not be touched
*/
-/* --- CMD_CHUTE_TYPE --- */
-#define CMD_CONNECTION_CHUTE_0 1
-#define CMD_CONNECTION_CHUTE_1 2
-#define CMD_CONNECTION_CHUTE_2 3
-
-#define EQ_MAJOR_CODE_COMPLETION 0
-
-#define CMD_ISCSI_SESSION_DEL_CFG_FROM_FLASH 0
-#define CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH 1
-
-/* --- CONNECTION_UPLOAD_PARAMS --- */
-/* These parameters are used to define the type of upload desired. */
-#define CONNECTION_UPLOAD_GRACEFUL 1 /* Graceful upload */
-#define CONNECTION_UPLOAD_ABORT_RESET 2 /* Abortive upload with
- * reset
- */
-#define CONNECTION_UPLOAD_ABORT 3 /* Abortive upload without
- * reset
- */
-#define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4 /* Abortive upload with reset,
- * sequence number by driver */
/* Returns the number of items in the field array. */
#define BE_NUMBER_OF_FIELD(_type_, _field_) \
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index a4844578e357..97dca4681784 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.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 <scsi/libiscsi.h>
@@ -1263,31 +1258,58 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba)
}
/**
- * beiscsi_close_conn - Upload the connection
+ * beiscsi_conn_close - Invalidate and upload connection
* @ep: The iscsi endpoint
- * @flag: The type of connection closure
+ *
+ * Returns 0 on success, -1 on failure.
*/
-static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
+static int beiscsi_conn_close(struct beiscsi_endpoint *beiscsi_ep)
{
- int ret = 0;
- unsigned int tag;
struct beiscsi_hba *phba = beiscsi_ep->phba;
+ unsigned int tag, attempts;
+ int ret;
- tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag);
- if (!tag) {
- beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
- "BS_%d : upload failed for cid 0x%x\n",
- beiscsi_ep->ep_cid);
-
- ret = -EAGAIN;
+ /**
+ * Without successfully invalidating and uploading connection
+ * driver can't reuse the CID so attempt more than once.
+ */
+ attempts = 0;
+ while (attempts++ < 3) {
+ tag = beiscsi_invalidate_cxn(phba, beiscsi_ep);
+ if (tag) {
+ ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
+ if (!ret)
+ break;
+ beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
+ "BS_%d : invalidate conn failed cid %d\n",
+ beiscsi_ep->ep_cid);
+ }
}
- ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
-
- /* Flush the CQ entries */
+ /* wait for all completions to arrive, then process them */
+ msleep(250);
+ /* flush CQ entries */
beiscsi_flush_cq(phba);
- return ret;
+ if (attempts > 3)
+ return -1;
+
+ attempts = 0;
+ while (attempts++ < 3) {
+ tag = beiscsi_upload_cxn(phba, beiscsi_ep);
+ if (tag) {
+ ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
+ if (!ret)
+ break;
+ beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
+ "BS_%d : upload conn failed cid %d\n",
+ beiscsi_ep->ep_cid);
+ }
+ }
+ if (attempts > 3)
+ return -1;
+
+ return 0;
}
/**
@@ -1298,12 +1320,9 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
*/
void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
{
- struct beiscsi_conn *beiscsi_conn;
struct beiscsi_endpoint *beiscsi_ep;
+ struct beiscsi_conn *beiscsi_conn;
struct beiscsi_hba *phba;
- unsigned int tag;
- uint8_t mgmt_invalidate_flag, tcp_upload_flag;
- unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
uint16_t cri_index;
beiscsi_ep = ep->dd_data;
@@ -1324,39 +1343,27 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
if (beiscsi_ep->conn) {
beiscsi_conn = beiscsi_ep->conn;
iscsi_suspend_queue(beiscsi_conn->conn);
- mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE;
- tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL;
- } else {
- mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE;
- tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
}
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
- goto free_ep;
- }
-
- tag = mgmt_invalidate_connection(phba, beiscsi_ep,
- beiscsi_ep->ep_cid,
- mgmt_invalidate_flag,
- savecfg_flag);
- if (!tag) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
- "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
- beiscsi_ep->ep_cid);
+ } else {
+ /**
+ * Make CID available even if close fails.
+ * If not freed, FW might fail open using the CID.
+ */
+ if (beiscsi_conn_close(beiscsi_ep) < 0)
+ __beiscsi_log(phba, KERN_ERR,
+ "BS_%d : close conn failed cid %d\n",
+ beiscsi_ep->ep_cid);
}
- beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
- beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
-free_ep:
- msleep(BEISCSI_LOGOUT_SYNC_DELAY);
beiscsi_free_ep(beiscsi_ep);
if (!phba->conn_table[cri_index])
__beiscsi_log(phba, KERN_ERR,
- "BS_%d : conn_table empty at %u: cid %u\n",
- cri_index,
- beiscsi_ep->ep_cid);
+ "BS_%d : conn_table empty at %u: cid %u\n",
+ cri_index, beiscsi_ep->ep_cid);
phba->conn_table[cri_index] = NULL;
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
index e4d67dfea4cb..b9d459a21f25 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.h
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -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
*
- * Avago Technologies
- * 3333 Susan Street
- * Costa Mesa, CA 92626
*/
#ifndef _BE_ISCSI_
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);
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index 218857926566..338dbe0800c1 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -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
*/
#ifndef _BEISCSI_MAIN_
@@ -36,7 +31,7 @@
#include <scsi/scsi_transport_iscsi.h>
#define DRV_NAME "be2iscsi"
-#define BUILD_STR "11.2.1.0"
+#define BUILD_STR "11.4.0.0"
#define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@@ -235,7 +230,6 @@ struct sgl_handle {
struct hba_parameters {
unsigned int ios_per_ctrl;
unsigned int cxns_per_ctrl;
- unsigned int asyncpdus_per_ctrl;
unsigned int icds_per_ctrl;
unsigned int num_sge_per_io;
unsigned int defpdu_hdr_sz;
@@ -323,9 +317,7 @@ struct beiscsi_hba {
struct pci_dev *pcidev;
unsigned int num_cpus;
unsigned int nxt_cqid;
- struct msix_entry msix_entries[MAX_CPUS];
char *msi_name[MAX_CPUS];
- bool msix_enabled;
struct be_mem_descriptor *init_mem;
unsigned short io_sgl_alloc_index;
@@ -597,8 +589,12 @@ struct hd_async_handle {
u16 cri;
u8 is_header;
u8 is_final;
+ u8 in_use;
};
+#define BEISCSI_ASYNC_HDQ_SIZE(phba, ulp) \
+ (BEISCSI_GET_CID_COUNT((phba), (ulp)) * 2)
+
/**
* This has list of async PDUs that are waiting to be processed.
* Buffers live in this list for a brief duration before they get
@@ -624,14 +620,8 @@ struct hd_async_buf_context {
void *va_base;
void *ring_base;
struct hd_async_handle *handle_base;
- u16 free_entries;
u32 buffer_size;
- /**
- * Once iSCSI layer finishes processing an async PDU, the
- * handles used for the PDU are added to this list.
- * They are posted back to FW in groups of 8.
- */
- struct list_head free_list;
+ u16 pi;
};
/**
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 2f6d5c2ac329..c73775368d09 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.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/bsg-lib.h>
@@ -126,67 +121,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
return tag;
}
-unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
- struct beiscsi_endpoint *beiscsi_ep,
- unsigned short cid,
- unsigned short issue_reset,
- unsigned short savecfg_flag)
-{
- struct be_ctrl_info *ctrl = &phba->ctrl;
- struct be_mcc_wrb *wrb;
- struct iscsi_invalidate_connection_params_in *req;
- unsigned int tag = 0;
-
- mutex_lock(&ctrl->mbox_lock);
- wrb = alloc_mcc_wrb(phba, &tag);
- if (!wrb) {
- mutex_unlock(&ctrl->mbox_lock);
- return 0;
- }
-
- req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
- OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
- sizeof(*req));
- req->session_handle = beiscsi_ep->fw_handle;
- req->cid = cid;
- if (issue_reset)
- req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST;
- else
- req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
- req->save_cfg = savecfg_flag;
- be_mcc_notify(phba, tag);
- mutex_unlock(&ctrl->mbox_lock);
- return tag;
-}
-
-unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
- unsigned short cid, unsigned int upload_flag)
-{
- struct be_ctrl_info *ctrl = &phba->ctrl;
- struct be_mcc_wrb *wrb;
- struct tcp_upload_params_in *req;
- unsigned int tag;
-
- mutex_lock(&ctrl->mbox_lock);
- wrb = alloc_mcc_wrb(phba, &tag);
- if (!wrb) {
- mutex_unlock(&ctrl->mbox_lock);
- return 0;
- }
-
- req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
- be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
- OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
- req->id = (unsigned short)cid;
- req->upload_type = (unsigned char)upload_flag;
- be_mcc_notify(phba, tag);
- mutex_unlock(&ctrl->mbox_lock);
- return tag;
-}
-
/**
* mgmt_open_connection()- Establish a TCP CXN
* @dst_addr: Destination Address
@@ -1449,6 +1383,72 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
exp_statsn) / 32] + 1));
}
+unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba,
+ struct beiscsi_endpoint *beiscsi_ep)
+{
+ struct be_invalidate_connection_params_in *req;
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+ struct be_mcc_wrb *wrb;
+ unsigned int tag = 0;
+
+ mutex_lock(&ctrl->mbox_lock);
+ wrb = alloc_mcc_wrb(phba, &tag);
+ if (!wrb) {
+ mutex_unlock(&ctrl->mbox_lock);
+ return 0;
+ }
+
+ req = embedded_payload(wrb);
+ be_wrb_hdr_prepare(wrb, sizeof(union be_invalidate_connection_params),
+ true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
+ OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
+ sizeof(*req));
+ req->session_handle = beiscsi_ep->fw_handle;
+ req->cid = beiscsi_ep->ep_cid;
+ if (beiscsi_ep->conn)
+ req->cleanup_type = BE_CLEANUP_TYPE_INVALIDATE;
+ else
+ req->cleanup_type = BE_CLEANUP_TYPE_ISSUE_TCP_RST;
+ /**
+ * 0 - non-persistent targets
+ * 1 - save session info on flash
+ */
+ req->save_cfg = 0;
+ be_mcc_notify(phba, tag);
+ mutex_unlock(&ctrl->mbox_lock);
+ return tag;
+}
+
+unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba,
+ struct beiscsi_endpoint *beiscsi_ep)
+{
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+ struct be_mcc_wrb *wrb;
+ struct be_tcp_upload_params_in *req;
+ unsigned int tag;
+
+ mutex_lock(&ctrl->mbox_lock);
+ wrb = alloc_mcc_wrb(phba, &tag);
+ if (!wrb) {
+ mutex_unlock(&ctrl->mbox_lock);
+ return 0;
+ }
+
+ req = embedded_payload(wrb);
+ be_wrb_hdr_prepare(wrb, sizeof(union be_tcp_upload_params), true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
+ OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
+ req->id = beiscsi_ep->ep_cid;
+ if (beiscsi_ep->conn)
+ req->upload_type = BE_UPLOAD_TYPE_GRACEFUL;
+ else
+ req->upload_type = BE_UPLOAD_TYPE_ABORT;
+ be_mcc_notify(phba, tag);
+ mutex_unlock(&ctrl->mbox_lock);
+ return tag;
+}
+
int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invldt_cmd_tbl *inv_tbl,
unsigned int nents)
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index 308f1472f98a..06ddc5ad6874 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -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
*/
#ifndef _BEISCSI_MGMT_
@@ -41,35 +36,11 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
struct beiscsi_endpoint *beiscsi_ep,
struct be_dma_mem *nonemb_cmd);
-unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
- unsigned short cid,
- unsigned int upload_flag);
unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba,
struct bsg_job *job,
struct be_dma_mem *nonemb_cmd);
-#define BEISCSI_NO_RST_ISSUE 0
-struct iscsi_invalidate_connection_params_in {
- struct be_cmd_req_hdr hdr;
- unsigned int session_handle;
- unsigned short cid;
- unsigned short unused;
- unsigned short cleanup_type;
- unsigned short save_cfg;
-} __packed;
-
-struct iscsi_invalidate_connection_params_out {
- unsigned int session_handle;
- unsigned short cid;
- unsigned short unused;
-} __packed;
-
-union iscsi_invalidate_connection_params {
- struct iscsi_invalidate_connection_params_in request;
- struct iscsi_invalidate_connection_params_out response;
-} __packed;
-
#define BE_INVLDT_CMD_TBL_SZ 128
struct invldt_cmd_tbl {
unsigned short icd;
@@ -265,6 +236,12 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle,
struct hwi_wrb_context *pwrb_context);
+unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba,
+ struct beiscsi_endpoint *beiscsi_ep);
+
+unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba,
+ struct beiscsi_endpoint *beiscsi_ep);
+
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *, int num);