]> Pileus Git - ~andy/linux/commitdiff
[SCSI] qla4xxx: wait for boot target login response during probe.
authorManish Rangankar <manish.rangankar@qlogic.com>
Mon, 21 Jan 2013 04:51:03 +0000 (23:51 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Wed, 30 Jan 2013 02:55:50 +0000 (13:55 +1100)
Boot from SAN fails in some cases where boot target login response
is slow. In this case, probe finishes early and triggers init, which
doesn't find remote disk to mount root which leads to BFS failure.

Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_os.c

index ad580625a47772b578437cd0cfe2a915aa835527..129f5dd02822149af1cce4a7309241d87d841e2a 100644 (file)
 #define DISABLE_ACB_TOV                        30
 #define IP_CONFIG_TOV                  30
 #define LOGIN_TOV                      12
+#define BOOT_LOGIN_RESP_TOV            60
 
 #define MAX_RESET_HA_RETRIES           2
 #define FW_ALIVE_WAIT_TOV              3
@@ -315,6 +316,7 @@ struct ql4_tuple_ddb {
  * DDB flags.
  */
 #define DF_RELOGIN             0       /* Relogin to device */
+#define DF_BOOT_TGT            1       /* Boot target entry */
 #define DF_ISNS_DISCOVERED     2       /* Device was discovered via iSNS */
 #define DF_FO_MASKED           3
 
index 2ccbb3bee096a8e36c8efd2a4acd5dc437ecceb9..b8acc40d6f6ce7ffb676f25066da781df79e0ea7 100644 (file)
@@ -4728,7 +4728,8 @@ static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
 }
 
 static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
-                                         struct ddb_entry *ddb_entry)
+                                         struct ddb_entry *ddb_entry,
+                                         uint16_t idx)
 {
        uint16_t def_timeout;
 
@@ -4748,6 +4749,10 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
                def_timeout : LOGIN_TOV;
        ddb_entry->default_time2wait =
                le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
+
+       if (ql4xdisablesysfsboot &&
+           (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx))
+               set_bit(DF_BOOT_TGT, &ddb_entry->flags);
 }
 
 static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
@@ -4884,7 +4889,7 @@ static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
 
 static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
                                   struct dev_db_entry *fw_ddb_entry,
-                                  int is_reset)
+                                  int is_reset, uint16_t idx)
 {
        struct iscsi_cls_session *cls_sess;
        struct iscsi_session *sess;
@@ -4922,7 +4927,7 @@ static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
        memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
               sizeof(struct dev_db_entry));
 
-       qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
+       qla4xxx_setup_flash_ddb_entry(ha, ddb_entry, idx);
 
        cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);
 
@@ -5039,7 +5044,7 @@ static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
                                goto continue_next_nt;
                }
 
-               ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
+               ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx);
                if (ret == QLA_ERROR)
                        goto exit_nt_list;
 
@@ -5118,6 +5123,78 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
        qla4xxx_free_ddb_index(ha);
 }
 
+/**
+ * qla4xxx_wait_login_resp_boot_tgt -  Wait for iSCSI boot target login
+ * response.
+ * @ha: pointer to adapter structure
+ *
+ * When the boot entry is normal iSCSI target then DF_BOOT_TGT flag will be
+ * set in DDB and we will wait for login response of boot targets during
+ * probe.
+ **/
+static void qla4xxx_wait_login_resp_boot_tgt(struct scsi_qla_host *ha)
+{
+       struct ddb_entry *ddb_entry;
+       struct dev_db_entry *fw_ddb_entry = NULL;
+       dma_addr_t fw_ddb_entry_dma;
+       unsigned long wtime;
+       uint32_t ddb_state;
+       int max_ddbs, idx, ret;
+
+       max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+                                    MAX_DEV_DB_ENTRIES;
+
+       fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+                                         &fw_ddb_entry_dma, GFP_KERNEL);
+       if (!fw_ddb_entry) {
+               ql4_printk(KERN_ERR, ha,
+                          "%s: Unable to allocate dma buffer\n", __func__);
+               goto exit_login_resp;
+       }
+
+       wtime = jiffies + (HZ * BOOT_LOGIN_RESP_TOV);
+
+       for (idx = 0; idx < max_ddbs; idx++) {
+               ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
+               if (ddb_entry == NULL)
+                       continue;
+
+               if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) {
+                       DEBUG2(ql4_printk(KERN_INFO, ha,
+                                         "%s: DDB index [%d]\n", __func__,
+                                         ddb_entry->fw_ddb_index));
+                       do {
+                               ret = qla4xxx_get_fwddb_entry(ha,
+                                               ddb_entry->fw_ddb_index,
+                                               fw_ddb_entry, fw_ddb_entry_dma,
+                                               NULL, NULL, &ddb_state, NULL,
+                                               NULL, NULL);
+                               if (ret == QLA_ERROR)
+                                       goto exit_login_resp;
+
+                               if ((ddb_state == DDB_DS_SESSION_ACTIVE) ||
+                                   (ddb_state == DDB_DS_SESSION_FAILED))
+                                       break;
+
+                               schedule_timeout_uninterruptible(HZ);
+
+                       } while ((time_after(wtime, jiffies)));
+
+                       if (!time_after(wtime, jiffies)) {
+                               DEBUG2(ql4_printk(KERN_INFO, ha,
+                                                 "%s: Login response wait timer expired\n",
+                                                 __func__));
+                                goto exit_login_resp;
+                       }
+               }
+       }
+
+exit_login_resp:
+       if (fw_ddb_entry)
+               dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+                                 fw_ddb_entry, fw_ddb_entry_dma);
+}
+
 /**
  * qla4xxx_probe_adapter - callback function to probe HBA
  * @pdev: pointer to pci_dev structure
@@ -5371,6 +5448,7 @@ skip_retry_init:
                /* Perform the build ddb list and login to each */
        qla4xxx_build_ddb_list(ha, INIT_ADAPTER);
        iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb);
+       qla4xxx_wait_login_resp_boot_tgt(ha);
 
        qla4xxx_create_chap_list(ha);