diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.h | 18 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 45 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 1 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 133 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 6 |
5 files changed, 175 insertions, 28 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index b0b36c6a145f..953c354c4d97 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -348,6 +348,23 @@ struct be_cmd_get_boot_target_resp { int boot_session_handle; }; +struct be_cmd_reopen_session_req { + struct be_cmd_req_hdr hdr; +#define BE_REOPEN_ALL_SESSIONS 0x00 +#define BE_REOPEN_BOOT_SESSIONS 0x01 +#define BE_REOPEN_A_SESSION 0x02 + u16 reopen_type; + u16 rsvd; + u32 session_handle; +} __packed; + +struct be_cmd_reopen_session_resp { + struct be_cmd_resp_hdr hdr; + u32 rsvd; + u32 session_handle; +} __packed; + + struct be_cmd_mac_query_req { struct be_cmd_req_hdr hdr; u8 type; @@ -911,6 +928,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_DRIVER_REOPEN_ALL_SESSIONS 36 #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 #define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 2cdae0833996..4b283a25d025 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3466,44 +3466,33 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) "In hwi_disable_intr, Already Disabled\n"); } +/** + * beiscsi_get_boot_info()- Get the boot session info + * @phba: The device priv structure instance + * + * Get the boot target info and store in driver priv structure + * + * return values + * Success: 0 + * Failure: Non-Zero Value + **/ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) { - struct be_cmd_get_boot_target_resp *boot_resp; struct be_cmd_get_session_resp *session_resp; struct be_mcc_wrb *wrb; struct be_dma_mem nonemb_cmd; unsigned int tag, wrb_num; unsigned short status, extd_status; + unsigned int s_handle; struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; int ret = -ENOMEM; - tag = mgmt_get_boot_target(phba); - if (!tag) { - SE_DEBUG(DBG_LVL_1, "beiscsi_get_boot_info Failed\n"); - return -EAGAIN; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { - SE_DEBUG(DBG_LVL_1, "beiscsi_get_boot_info Failed" - " status = %d extd_status = %d\n", - status, extd_status); - free_mcc_tag(&phba->ctrl, tag); - return -EBUSY; - } - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); - boot_resp = embedded_payload(wrb); - - if (boot_resp->boot_session_handle < 0) { - shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n"); - return -ENXIO; + /* Get the session handle of the boot target */ + ret = be_mgmt_get_boot_shandle(phba, &s_handle); + if (ret) { + SE_DEBUG(DBG_LVL_1, "No boot session\n"); + return ret; } - nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, sizeof(*session_resp), &nonemb_cmd.dma); @@ -3515,7 +3504,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) } memset(nonemb_cmd.va, 0, sizeof(*session_resp)); - tag = mgmt_get_session_info(phba, boot_resp->boot_session_handle, + tag = mgmt_get_session_info(phba, s_handle, &nonemb_cmd); if (!tag) { SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info" diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 40fea6ec879c..8b2ce610b06d 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -84,6 +84,7 @@ #define MAX_CMD_SZ 65536 #define IIOC_SCSI_DATA 0x05 /* Write Operation */ +#define INVALID_SESS_HANDLE 0xFFFFFFFF #define DBG_LVL 0x00000001 #define DBG_LVL_1 0x00000001 #define DBG_LVL_2 0x00000002 diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 2a096795b9aa..e294b0ae324f 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -23,6 +23,50 @@ #include "be_mgmt.h" #include "be_iscsi.h" +/** + * mgmt_reopen_session()- Reopen a session based on reopen_type + * @phba: Device priv structure instance + * @reopen_type: Type of reopen_session FW should do. + * @sess_handle: Session Handle of the session to be re-opened + * + * return + * the TAG used for MBOX Command + * + **/ +unsigned int mgmt_reopen_session(struct beiscsi_hba *phba, + unsigned int reopen_type, + unsigned int sess_handle) +{ + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb; + struct be_cmd_reopen_session_req *req; + unsigned int tag = 0; + + SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n"); + spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); + return tag; + } + + 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_DRIVER_REOPEN_ALL_SESSIONS, + sizeof(struct be_cmd_reopen_session_resp)); + + /* set the reopen_type,sess_handle */ + req->reopen_type = reopen_type; + req->session_handle = sess_handle; + + be_mcc_notify(phba); + spin_unlock(&ctrl->mbox_lock); + return tag; +} + unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba) { struct be_ctrl_info *ctrl = &phba->ctrl; @@ -924,3 +968,92 @@ unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba) spin_unlock(&ctrl->mbox_lock); return tag; } + +/** + * be_mgmt_get_boot_shandle()- Get the session handle + * @phba: device priv structure instance + * @s_handle: session handle returned for boot session. + * + * Get the boot target session handle. In case of + * crashdump mode driver has to issue and MBX Cmd + * for FW to login to boot target + * + * return + * Success: 0 + * Failure: Non-Zero value + * + **/ +int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, + unsigned int *s_handle) +{ + struct be_cmd_get_boot_target_resp *boot_resp; + struct be_mcc_wrb *wrb; + unsigned int tag, wrb_num; + uint8_t boot_retry = 3; + unsigned short status, extd_status; + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + + do { + /* Get the Boot Target Session Handle and Count*/ + tag = mgmt_get_boot_target(phba); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "mgmt_get_boot_target Failed\n"); + return -EAGAIN; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "mgmt_get_boot_target Failed" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + return -EBUSY; + } + wrb = queue_get_wrb(mccq, wrb_num); + free_mcc_tag(&phba->ctrl, tag); + boot_resp = embedded_payload(wrb); + + /* Check if the there are any Boot targets configured */ + if (!boot_resp->boot_session_count) { + SE_DEBUG(DBG_LVL_8, "No boot targets configured\n"); + return -ENXIO; + } + + /* FW returns the session handle of the boot session */ + if (boot_resp->boot_session_handle != INVALID_SESS_HANDLE) { + *s_handle = boot_resp->boot_session_handle; + return 0; + } + + /* Issue MBX Cmd to FW to login to the boot target */ + tag = mgmt_reopen_session(phba, BE_REOPEN_BOOT_SESSIONS, + INVALID_SESS_HANDLE); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "mgmt_reopen_session Failed\n"); + return -EAGAIN; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "mgmt_reopen_session Failed" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + return -EBUSY; + } + free_mcc_tag(&phba->ctrl, tag); + + } while (--boot_retry); + + /* Couldn't log into the boot target */ + SE_DEBUG(DBG_LVL_1, "Login to Boot Target Failed\n"); + return -ENXIO; +} diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 5c2e37693ca8..63b8e81f3250 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h @@ -274,6 +274,10 @@ int mgmt_set_ip(struct beiscsi_hba *phba, unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba); +unsigned int mgmt_reopen_session(struct beiscsi_hba *phba, + unsigned int reopen_type, + unsigned sess_handle); + unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, u32 boot_session_handle, struct be_dma_mem *nonemb_cmd); @@ -290,4 +294,6 @@ int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, int mgmt_set_gateway(struct beiscsi_hba *phba, struct iscsi_iface_param_info *gateway_param); +int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, + unsigned int *s_handle); #endif |