summaryrefslogtreecommitdiff
path: root/drivers/scsi/be2iscsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c4
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h12
-rw-r--r--drivers/scsi/be2iscsi/be_main.c76
-rw-r--r--drivers/scsi/be2iscsi/be_main.h6
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c69
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h3
6 files changed, 153 insertions, 17 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 447cf7ce6..185391a64 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -452,6 +452,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
(evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) {
phba->state = BE_ADAPTER_LINK_UP | BE_ADAPTER_CHECK_BOOT;
+ phba->get_boot = BE_GET_BOOT_RETRIES;
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
@@ -480,6 +481,7 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
case ASYNC_EVENT_NEW_ISCSI_CONN:
case ASYNC_EVENT_NEW_TCP_CONN:
phba->state |= BE_ADAPTER_CHECK_BOOT;
+ phba->get_boot = BE_GET_BOOT_RETRIES;
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG |
BEISCSI_LOG_MBOX,
@@ -488,6 +490,8 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
compl->flags);
break;
default:
+ phba->state |= BE_ADAPTER_CHECK_BOOT;
+ phba->get_boot = BE_GET_BOOT_RETRIES;
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG |
BEISCSI_LOG_MBOX,
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index f11d325fe..cdfbc5c19 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -304,6 +304,17 @@ struct mgmt_auth_method_format {
struct mgmt_chap_format chap;
} __packed;
+struct be_cmd_req_logout_fw_sess {
+ struct be_cmd_req_hdr hdr; /* dw[4] */
+ uint32_t session_handle;
+} __packed;
+
+struct be_cmd_resp_logout_fw_sess {
+ struct be_cmd_resp_hdr hdr; /* dw[4] */
+#define BEISCSI_MGMT_SESSION_CLOSE 0x20
+ uint32_t session_status;
+} __packed;
+
struct mgmt_conn_login_options {
u8 flags;
u8 header_digest;
@@ -1136,6 +1147,7 @@ struct be_cmd_get_all_if_id_req {
#define OPCODE_ISCSI_INI_CFG_GET_HBA_NAME 6
#define OPCODE_ISCSI_INI_CFG_SET_HBA_NAME 7
#define OPCODE_ISCSI_INI_SESSION_GET_A_SESSION 14
+#define OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET 24
#define OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS 36
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 1f74760ce..7a6dbfbcc 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -668,14 +668,20 @@ static int beiscsi_enable_pci(struct pci_dev *pcidev)
return ret;
}
+ ret = pci_request_regions(pcidev, DRV_NAME);
+ if (ret) {
+ dev_err(&pcidev->dev,
+ "beiscsi_enable_pci - request region failed\n");
+ goto pci_dev_disable;
+ }
+
pci_set_master(pcidev);
ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64));
if (ret) {
ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n");
- pci_disable_device(pcidev);
- return ret;
+ goto pci_region_release;
} else {
ret = pci_set_consistent_dma_mask(pcidev,
DMA_BIT_MASK(32));
@@ -684,11 +690,17 @@ static int beiscsi_enable_pci(struct pci_dev *pcidev)
ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));
if (ret) {
dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n");
- pci_disable_device(pcidev);
- return ret;
+ goto pci_region_release;
}
}
return 0;
+
+pci_region_release:
+ pci_release_regions(pcidev);
+pci_dev_disable:
+ pci_disable_device(pcidev);
+
+ return ret;
}
static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
@@ -1356,8 +1368,10 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ)
conn->rxdata_octets += resid;
unmap:
- scsi_dma_unmap(io_task->scsi_cmnd);
- io_task->scsi_cmnd = NULL;
+ if (io_task->scsi_cmnd) {
+ scsi_dma_unmap(io_task->scsi_cmnd);
+ io_task->scsi_cmnd = NULL;
+ }
iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
}
@@ -2037,11 +2051,16 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
/* Interpret compl as a async link evt */
beiscsi_async_link_state_process(phba,
(struct be_async_event_link_state *) mcc_compl);
- else
+ else {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX,
"BM_%d : Unsupported Async Event, flags"
" = 0x%08x\n",
mcc_compl->flags);
+ if (phba->state & BE_ADAPTER_LINK_UP) {
+ phba->state |= BE_ADAPTER_CHECK_BOOT;
+ phba->get_boot = BE_GET_BOOT_RETRIES;
+ }
+ }
} else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) {
be_mcc_compl_process_isr(&phba->ctrl, mcc_compl);
atomic_dec(&phba->ctrl.mcc_obj.q.used);
@@ -3678,14 +3697,16 @@ static void be_mcc_queues_destroy(struct beiscsi_hba *phba)
struct be_ctrl_info *ctrl = &phba->ctrl;
q = &phba->ctrl.mcc_obj.q;
- if (q->created)
+ if (q->created) {
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ);
- be_queue_free(phba, q);
+ be_queue_free(phba, q);
+ }
q = &phba->ctrl.mcc_obj.cq;
- if (q->created)
+ if (q->created) {
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
- be_queue_free(phba, q);
+ be_queue_free(phba, q);
+ }
}
static void hwi_cleanup(struct beiscsi_hba *phba)
@@ -3729,8 +3750,10 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
for (i = 0; i < (phba->num_cpus); i++) {
q = &phwi_context->be_cq[i];
- if (q->created)
+ if (q->created) {
+ be_queue_free(phba, q);
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+ }
}
be_mcc_queues_destroy(phba);
@@ -3740,8 +3763,10 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
eq_for_mcc = 0;
for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {
q = &phwi_context->be_eq[i].q;
- if (q->created)
+ if (q->created) {
+ be_queue_free(phba, q);
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
+ }
}
be_cmd_fw_uninit(ctrl);
}
@@ -4328,8 +4353,14 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
"BM_%d : No boot session\n");
+
+ if (ret == -ENXIO)
+ phba->get_boot = 0;
+
+
return ret;
}
+ phba->get_boot = 0;
nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev,
sizeof(*session_resp),
&nonemb_cmd.dma);
@@ -4369,6 +4400,9 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
memcpy(&phba->boot_sess, &session_resp->session_info,
sizeof(struct mgmt_session_info));
+
+ beiscsi_logout_fw_sess(phba,
+ phba->boot_sess.session_handle);
ret = 0;
boot_freemem:
@@ -4580,11 +4614,13 @@ beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
spin_unlock_bh(&phba->mgmt_sgl_lock);
}
- if (io_task->mtask_addr)
+ if (io_task->mtask_addr) {
pci_unmap_single(phba->pcidev,
io_task->mtask_addr,
io_task->mtask_data_count,
PCI_DMA_TODEVICE);
+ io_task->mtask_addr = 0;
+ }
}
/**
@@ -5264,6 +5300,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
iscsi_host_free(phba->shost);
pci_disable_pcie_error_reporting(pcidev);
pci_set_drvdata(pcidev, NULL);
+ pci_release_regions(pcidev);
pci_disable_device(pcidev);
}
@@ -5374,8 +5411,14 @@ beiscsi_hw_health_check(struct work_struct *work)
be_eqd_update(phba);
if (phba->state & BE_ADAPTER_CHECK_BOOT) {
- phba->state &= ~BE_ADAPTER_CHECK_BOOT;
- be_check_boot_session(phba);
+ if ((phba->get_boot > 0) && (!phba->boot_kset)) {
+ phba->get_boot--;
+ if (!(phba->get_boot % BE_GET_BOOT_TO))
+ be_check_boot_session(phba);
+ } else {
+ phba->state &= ~BE_ADAPTER_CHECK_BOOT;
+ phba->get_boot = 0;
+ }
}
beiscsi_ue_detect(phba);
@@ -5738,6 +5781,7 @@ hba_free:
iscsi_host_free(phba->shost);
pci_set_drvdata(pcidev, NULL);
disable_pci:
+ pci_release_regions(pcidev);
pci_disable_device(pcidev);
return ret;
}
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index e70ea26bb..b8c0c7819 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -36,7 +36,7 @@
#include <scsi/scsi_transport_iscsi.h>
#define DRV_NAME "be2iscsi"
-#define BUILD_STR "10.4.114.0"
+#define BUILD_STR "10.6.0.0"
#define BE_NAME "Avago Technologies OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@@ -109,6 +109,9 @@
#define BEISCSI_CLEAN_UNLOAD 0x01
#define BEISCSI_EEH_UNLOAD 0x02
+
+#define BE_GET_BOOT_RETRIES 45
+#define BE_GET_BOOT_TO 20
/**
* hardware needs the async PDU buffers to be posted in multiples of 8
* So have atleast 8 of them by default
@@ -413,6 +416,7 @@ struct beiscsi_hba {
} fw_config;
unsigned int state;
+ int get_boot;
bool fw_timeout;
bool ue_detected;
struct delayed_work beiscsi_hw_check_task;
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index c2c4d6975..ca4016f20 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -1707,3 +1707,72 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
(params->dw[offsetof(struct amap_beiscsi_offload_params,
exp_statsn) / 32] + 1));
}
+
+/**
+ * beiscsi_logout_fw_sess()- Firmware Session Logout
+ * @phba: Device priv structure instance
+ * @fw_sess_handle: FW session handle
+ *
+ * Logout from the FW established sessions.
+ * returns
+ * Success: 0
+ * Failure: Non-Zero Value
+ *
+ */
+int beiscsi_logout_fw_sess(struct beiscsi_hba *phba,
+ uint32_t fw_sess_handle)
+{
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_logout_fw_sess *req;
+ struct be_cmd_resp_logout_fw_sess *resp;
+ unsigned int tag;
+ int rc;
+
+ beiscsi_log(phba, KERN_INFO,
+ BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
+ "BG_%d : In bescsi_logout_fwboot_sess\n");
+
+ spin_lock(&ctrl->mbox_lock);
+ tag = alloc_mcc_tag(phba);
+ if (!tag) {
+ spin_unlock(&ctrl->mbox_lock);
+ beiscsi_log(phba, KERN_INFO,
+ BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
+ "BG_%d : MBX Tag Failure\n");
+ return -EINVAL;
+ }
+
+ wrb = wrb_from_mccq(phba);
+ req = embedded_payload(wrb);
+ wrb->tag0 |= tag;
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
+ OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET,
+ sizeof(struct be_cmd_req_logout_fw_sess));
+
+ /* Set the session handle */
+ req->session_handle = fw_sess_handle;
+ be_mcc_notify(phba);
+ spin_unlock(&ctrl->mbox_lock);
+
+ rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+ if (rc) {
+ beiscsi_log(phba, KERN_ERR,
+ BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
+ "BG_%d : MBX CMD FW_SESSION_LOGOUT_TARGET Failed\n");
+ return -EBUSY;
+ }
+
+ resp = embedded_payload(wrb);
+ if (resp->session_status !=
+ BEISCSI_MGMT_SESSION_CLOSE) {
+ beiscsi_log(phba, KERN_ERR,
+ BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
+ "BG_%d : FW_SESSION_LOGOUT_TARGET resp : 0x%x\n",
+ resp->session_status);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index 9356b9a86..b58a7decb 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -338,4 +338,7 @@ void beiscsi_ue_detect(struct beiscsi_hba *phba);
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *, int num);
+int beiscsi_logout_fw_sess(struct beiscsi_hba *phba,
+ uint32_t fw_sess_handle);
+
#endif