[SCSI] be2iscsi: Issue MBX Cmd for login to boot target in crashdump mode
authorJohn Soni Jose <sony.john-n@emulex.com>
Mon, 20 Aug 2012 17:30:08 +0000 (23:00 +0530)
committerJames Bottomley <JBottomley@Parallels.com>
Fri, 14 Sep 2012 16:59:26 +0000 (17:59 +0100)
When the driver comes up in crashdump mode, it has to explicitly
issue command to FW for logging to the boot target. This fix issues
MBX Cmd to login to boot target in crashdump mode.

Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/be2iscsi/be_mgmt.h

index b0b36c6a145f77f0fb3ce38d9c2b45964dc4b99d..953c354c4d9783c404f3e860c93e4dfd7d17b31b 100644 (file)
@@ -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
index 2cdae0833996427ca49642d4c3585962b368430d..4b283a25d02530e6ac073f06d9c96f4c156f6601 100644 (file)
@@ -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"
index 40fea6ec879c2df00432f826e8f425dfecc69c48..8b2ce610b06de1c7b5042d465cf7100a05a3b4df 100644 (file)
@@ -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
index 2a096795b9aa86768ef18561872d948800eb6402..e294b0ae324f087c5f9b3bd65aa290303b3223d1 100644 (file)
 #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;
+}
index 5c2e37693ca82a863c0b459a1b58df342d80d6be..63b8e81f325018a16fcfe73b48dba2c6c0b3db9f 100644 (file)
@@ -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