]> git.karo-electronics.de Git - linux-beck.git/commitdiff
[SCSI] qla2xxx: Handle device mapping changes due to device logout.
authorArun Easi <arun.easi@qlogic.com>
Thu, 9 Feb 2012 19:15:58 +0000 (11:15 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Sun, 19 Feb 2012 14:33:48 +0000 (08:33 -0600)
A device logout sent in the delete path of a fcport would clear the
port handle binding inside the firmware. This could lead to queued
work items for the fcport, if any, getting incorrect results. This
patch fixes the issue by checking for device name changes after a
call to get port database.

Signed-off-by: Arun Easi <arun.easi@qlogic.com>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c

index 2627c87a4a34e71a4ea056c2d9d9c245f46a346c..b9465643396b0c40e7fb7fbab19249f5c5cbded6 100644 (file)
@@ -350,6 +350,13 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
                 * requests.
                 */
                rval = qla2x00_get_port_database(vha, fcport, 0);
+               if (rval == QLA_NOT_LOGGED_IN) {
+                       fcport->flags &= ~FCF_ASYNC_SENT;
+                       fcport->flags |= FCF_LOGIN_NEEDED;
+                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+                       break;
+               }
+
                if (rval != QLA_SUCCESS) {
                        qla2x00_post_async_logout_work(vha, fcport, NULL);
                        qla2x00_post_async_login_work(vha, fcport, NULL);
@@ -3318,6 +3325,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                        fcport->flags |= FCF_LOGIN_NEEDED;
                        if (fcport->loop_id != FC_NO_LOOP_ID &&
                            (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
+                           (fcport->flags & FCF_ASYNC_SENT) == 0 &&
                            fcport->port_type != FCT_INITIATOR &&
                            fcport->port_type != FCT_BROADCAST) {
                                ha->isp_ops->fabric_logout(vha, fcport->loop_id,
index adc2b14b03f5ea53122a144f1cc6f14a469bb992..b4a23394a7bd8f9a225ba2acd77ee19fb018f691 100644 (file)
@@ -1289,6 +1289,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
                goto gpd_error_out;
 
        if (IS_FWI2_CAPABLE(ha)) {
+               uint64_t zero = 0;
                pd24 = (struct port_database_24xx *) pd;
 
                /* Check for logged in state. */
@@ -1302,6 +1303,14 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
                        goto gpd_error_out;
                }
 
+               if (fcport->loop_id == FC_NO_LOOP_ID ||
+                   (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
+                    memcmp(fcport->port_name, pd24->port_name, 8))) {
+                       /* We lost the device mid way. */
+                       rval = QLA_NOT_LOGGED_IN;
+                       goto gpd_error_out;
+               }
+
                /* Names are little-endian. */
                memcpy(fcport->node_name, pd24->node_name, WWN_SIZE);
                memcpy(fcport->port_name, pd24->port_name, WWN_SIZE);
@@ -1318,6 +1327,8 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
                else
                        fcport->port_type = FCT_TARGET;
        } else {
+               uint64_t zero = 0;
+
                /* Check for logged in state. */
                if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&
                    pd->slave_state != PD_STATE_PORT_LOGGED_IN) {
@@ -1330,6 +1341,14 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
                        goto gpd_error_out;
                }
 
+               if (fcport->loop_id == FC_NO_LOOP_ID ||
+                   (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
+                    memcmp(fcport->port_name, pd->port_name, 8))) {
+                       /* We lost the device mid way. */
+                       rval = QLA_NOT_LOGGED_IN;
+                       goto gpd_error_out;
+               }
+
                /* Names are little-endian. */
                memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
                memcpy(fcport->port_name, pd->port_name, WWN_SIZE);