]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
[SCSI] qla2xxx: Wait for IDC complete event to finish loopback operation.
authorChad Dupuis <chad.dupuis@qlogic.com>
Fri, 8 Feb 2013 06:58:04 +0000 (01:58 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Fri, 22 Feb 2013 15:06:24 +0000 (15:06 +0000)
Wait for the IDC complete AEN before returning the loopback operation back to
the application to make sure the port is put back into normal operations.

Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c

index 747f440b1a93208ab9e5f5f6dc2683aa0cbd438a..ad54099cb805a277b206fc1a6adbf3676ad50271 100644 (file)
@@ -535,7 +535,7 @@ done:
 /* Disable loopback mode */
 static inline int
 qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
-                           int wait)
+                           int wait, int wait2)
 {
        int ret = 0;
        int rval = 0;
@@ -556,28 +556,45 @@ qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
                memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
 
                ha->notify_dcbx_comp = wait;
+               ha->notify_lb_portup_comp = wait2;
+
                ret = qla81xx_set_port_config(vha, new_config);
                if (ret != QLA_SUCCESS) {
                        ql_log(ql_log_warn, vha, 0x7025,
                            "Set port config failed.\n");
                        ha->notify_dcbx_comp = 0;
+                       ha->notify_lb_portup_comp = 0;
                        rval = -EINVAL;
                        goto done_reset_internal;
                }
 
                /* Wait for DCBX complete event */
                if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
-                       (20 * HZ))) {
+                       (DCBX_COMP_TIMEOUT * HZ))) {
                        ql_dbg(ql_dbg_user, vha, 0x7026,
-                           "State change notification not received.\n");
+                           "DCBX completion not received.\n");
                        ha->notify_dcbx_comp = 0;
+                       ha->notify_lb_portup_comp = 0;
                        rval = -EINVAL;
                        goto done_reset_internal;
                } else
                        ql_dbg(ql_dbg_user, vha, 0x7027,
-                           "State change received.\n");
+                           "DCBX completion received.\n");
+
+               if (wait2 &&
+                   !wait_for_completion_timeout(&ha->lb_portup_comp,
+                   (LB_PORTUP_COMP_TIMEOUT * HZ))) {
+                       ql_dbg(ql_dbg_user, vha, 0x70c5,
+                           "Port up completion not received.\n");
+                       ha->notify_lb_portup_comp = 0;
+                       rval = -EINVAL;
+                       goto done_reset_internal;
+               } else
+                       ql_dbg(ql_dbg_user, vha, 0x70c6,
+                           "Port up completion received.\n");
 
                ha->notify_dcbx_comp = 0;
+               ha->notify_lb_portup_comp = 0;
        }
 done_reset_internal:
        return rval;
@@ -618,10 +635,11 @@ qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
        }
 
        /* Wait for DCBX complete event */
-       if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) {
+       if (!wait_for_completion_timeout(&ha->dcbx_comp,
+           (DCBX_COMP_TIMEOUT * HZ))) {
                ql_dbg(ql_dbg_user, vha, 0x7022,
-                   "State change notification not received.\n");
-               ret = qla81xx_reset_loopback_mode(vha, new_config, 0);
+                   "DCBX completion not received.\n");
+               ret = qla81xx_reset_loopback_mode(vha, new_config, 0, 0);
                /*
                 * If the reset of the loopback mode doesn't work take a FCoE
                 * dump and reset the chip.
@@ -639,7 +657,7 @@ qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
                        ha->flags.idc_compl_status = 0;
                } else
                        ql_dbg(ql_dbg_user, vha, 0x7023,
-                           "State change received.\n");
+                           "DCBX completion received.\n");
        }
 
        ha->notify_dcbx_comp = 0;
@@ -749,6 +767,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                if (IS_QLA81XX(ha) || IS_QLA8031(ha)) {
                        memset(config, 0, sizeof(config));
                        memset(new_config, 0, sizeof(new_config));
+
                        if (qla81xx_get_port_config(vha, config)) {
                                ql_log(ql_log_warn, vha, 0x701f,
                                    "Get port config failed.\n");
@@ -773,7 +792,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                                            config, new_config, elreq.options);
                                else
                                        rval = qla81xx_reset_loopback_mode(vha,
-                                           config, 1);
+                                           config, 1, 0);
                        else
                                rval = qla81xx_set_loopback_mode(vha, config,
                                    new_config, elreq.options);
@@ -817,7 +836,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                                 * Also clear internal loopback
                                 */
                                ret = qla81xx_reset_loopback_mode(vha,
-                                   new_config, 0);
+                                   new_config, 0, 1);
                                if (ret) {
                                        /*
                                         * If the reset of the loopback mode
index c081882c566dc78dc4c05098dc94e2583336a62d..c6509911772b5569e9de368bca1a995897359b43 100644 (file)
@@ -2882,7 +2882,13 @@ struct qla_hw_data {
        struct completion mbx_cmd_comp; /* Serialize mbx access */
        struct completion mbx_intr_comp;  /* Used for completion notification */
        struct completion dcbx_comp;    /* For set port config notification */
+       struct completion lb_portup_comp; /* Used to wait for link up during
+                                          * loopback */
+#define DCBX_COMP_TIMEOUT      20
+#define LB_PORTUP_COMP_TIMEOUT 10
+
        int notify_dcbx_comp;
+       int notify_lb_portup_comp;
        struct mutex selflogin_lock;
 
        /* Basic firmware related information. */
index cbf6a431fcb5e824ca3633fae32231ce63d53f35..e9dbd74c20d31391b13961b0fea89233398239c8 100644 (file)
@@ -1032,6 +1032,9 @@ skip_rio:
                        }
                }
        case MBA_IDC_COMPLETE:
+               if (ha->notify_lb_portup_comp)
+                       complete(&ha->lb_portup_comp);
+               /* Fallthru */
        case MBA_IDC_TIME_EXT:
                if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw))
                        qla81xx_idc_event(vha, mb[0], mb[1]);
index c484e21c4df07b908348e26de5e561e6c1cc515c..2c6dd3dfe0f4de6d4ff867f873d1697c8dd2afd7 100644 (file)
@@ -2465,6 +2465,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        complete(&ha->mbx_cmd_comp);
        init_completion(&ha->mbx_intr_comp);
        init_completion(&ha->dcbx_comp);
+       init_completion(&ha->lb_portup_comp);
 
        set_bit(0, (unsigned long *) ha->vp_idx_map);