diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 151 |
1 files changed, 102 insertions, 49 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 34ee8c755655..c671852131ef 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -181,11 +181,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, if (!vha->flags.online) goto done; - if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) || - (fcport->fw_login_state == DSC_LS_PLOGI_COMP) || - (fcport->fw_login_state == DSC_LS_PRLI_PEND)) - goto done; - sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) goto done; @@ -1013,6 +1008,43 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); } /* gpdb event */ + +static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) +{ + u8 login = 0; + + if (qla_tgt_mode_enabled(vha)) + return; + + if (qla_dual_mode_enabled(vha)) { + if (N2N_TOPO(vha->hw)) { + u64 mywwn, wwn; + + mywwn = wwn_to_u64(vha->port_name); + wwn = wwn_to_u64(fcport->port_name); + if (mywwn > wwn) + login = 1; + else if ((fcport->fw_login_state == DSC_LS_PLOGI_COMP) + && time_after_eq(jiffies, + fcport->plogi_nack_done_deadline)) + login = 1; + } else { + login = 1; + } + } else { + /* initiator mode */ + login = 1; + } + + if (login) { + ql_dbg(ql_dbg_disc, vha, 0x20bf, + "%s %d %8phC post login\n", + __func__, __LINE__, fcport->port_name); + fcport->disc_state = DSC_LOGIN_PEND; + qla2x00_post_async_login_work(vha, fcport, NULL); + } +} + int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) { u16 data[2]; @@ -1037,8 +1069,10 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) return 0; if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) { - if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) + if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) { + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); return 0; + } } /* for pure Target Mode. Login will not be initiated */ @@ -1058,11 +1092,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) __func__, __LINE__, fcport->port_name); qla24xx_post_gnl_work(vha, fcport); } else { - ql_dbg(ql_dbg_disc, vha, 0x20bf, - "%s %d %8phC post login\n", - __func__, __LINE__, fcport->port_name); - fcport->disc_state = DSC_LOGIN_PEND; - qla2x00_post_async_login_work(vha, fcport, NULL); + qla_chk_n2n_b4_login(vha, fcport); } break; @@ -1074,19 +1104,17 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) break; } - ql_dbg(ql_dbg_disc, vha, 0x20cf, - "%s %d %8phC post login\n", - __func__, __LINE__, fcport->port_name); - fcport->disc_state = DSC_LOGIN_PEND; - qla2x00_post_async_login_work(vha, fcport, NULL); + qla_chk_n2n_b4_login(vha, fcport); break; case DSC_LOGIN_FAILED: ql_dbg(ql_dbg_disc, vha, 0x20d0, "%s %d %8phC post gidpn\n", __func__, __LINE__, fcport->port_name); - - qla24xx_post_gidpn_work(vha, fcport); + if (N2N_TOPO(vha->hw)) + qla_chk_n2n_b4_login(vha, fcport); + else + qla24xx_post_gidpn_work(vha, fcport); break; case DSC_LOGIN_COMPLETE: @@ -1193,8 +1221,10 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, return; if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) { - if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) + if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) { + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); return; + } } if (fcport->flags & FCF_ASYNC_SENT) { @@ -4434,6 +4464,21 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) } else if (ha->current_topology == ISP_CFG_N) { clear_bit(RSCN_UPDATE, &flags); + if (ha->flags.rida_fmt2) { + /* With Rida Format 2, the login is already triggered. + * We know who is on the other side of the wire. + * No need to login to do login to find out or drop into + * qla2x00_configure_local_loop(). + */ + clear_bit(LOCAL_LOOP_UPDATE, &flags); + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + } else { + if (qla_tgt_mode_enabled(vha)) { + /* allow the other side to start the login */ + clear_bit(LOCAL_LOOP_UPDATE, &flags); + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + } + } } else if (ha->current_topology == ISP_CFG_NL) { clear_bit(RSCN_UPDATE, &flags); set_bit(LOCAL_LOOP_UPDATE, &flags); @@ -4662,6 +4707,10 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) (uint8_t *)ha->gid_list, entries * sizeof(struct gid_list_info)); + list_for_each_entry(fcport, &vha->vp_fcports, list) { + fcport->scan_state = QLA_FCPORT_SCAN; + } + /* Allocate temporary fcport for any new fcports discovered. */ new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (new_fcport == NULL) { @@ -4672,22 +4721,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) } new_fcport->flags &= ~FCF_FABRIC_DEVICE; - /* - * Mark local devices that were present with FCF_DEVICE_LOST for now. - */ - list_for_each_entry(fcport, &vha->vp_fcports, list) { - if (atomic_read(&fcport->state) == FCS_ONLINE && - fcport->port_type != FCT_BROADCAST && - (fcport->flags & FCF_FABRIC_DEVICE) == 0) { - - ql_dbg(ql_dbg_disc, vha, 0x2096, - "Marking port lost loop_id=0x%04x.\n", - fcport->loop_id); - - qla2x00_mark_device_lost(vha, fcport, 0, 0); - } - } - /* Inititae N2N login. */ if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { rval = qla24xx_n2n_handle_login(vha, new_fcport); @@ -4730,6 +4763,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) new_fcport->d_id.b.area = area; new_fcport->d_id.b.al_pa = al_pa; new_fcport->loop_id = loop_id; + new_fcport->scan_state = QLA_FCPORT_FOUND; rval2 = qla2x00_get_port_database(vha, new_fcport, 0); if (rval2 != QLA_SUCCESS) { @@ -4761,13 +4795,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) fcport->d_id.b24 = new_fcport->d_id.b24; memcpy(fcport->node_name, new_fcport->node_name, WWN_SIZE); - - if (!fcport->login_succ) { - vha->fcport_count++; - fcport->login_succ = 1; - fcport->disc_state = DSC_LOGIN_COMPLETE; - } - + fcport->scan_state = QLA_FCPORT_FOUND; found++; break; } @@ -4778,11 +4806,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) /* Allocate a new replacement fcport. */ fcport = new_fcport; - if (!fcport->login_succ) { - vha->fcport_count++; - fcport->login_succ = 1; - fcport->disc_state = DSC_LOGIN_COMPLETE; - } spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); @@ -4803,11 +4826,39 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) /* Base iIDMA settings on HBA port speed. */ fcport->fp_speed = ha->link_data_rate; - qla2x00_update_fcport(vha, fcport); - found_devs++; } + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) + break; + + if (fcport->scan_state == QLA_FCPORT_SCAN) { + if ((qla_dual_mode_enabled(vha) || + qla_ini_mode_enabled(vha)) && + atomic_read(&fcport->state) == FCS_ONLINE) { + qla2x00_mark_device_lost(vha, fcport, + ql2xplogiabsentdevice, 0); + if (fcport->loop_id != FC_NO_LOOP_ID && + (fcport->flags & FCF_FCP2_DEVICE) == 0 && + fcport->port_type != FCT_INITIATOR && + fcport->port_type != FCT_BROADCAST) { + ql_dbg(ql_dbg_disc, vha, 0x20f0, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + fcport->port_name); + + qlt_schedule_sess_for_deletion_lock + (fcport); + continue; + } + } + } + + if (fcport->scan_state == QLA_FCPORT_FOUND) + qla24xx_fcport_handle_login(vha, fcport); + } + cleanup_allocation: kfree(new_fcport); @@ -6115,6 +6166,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) if (!(IS_P3P_TYPE(ha))) ha->isp_ops->reset_chip(vha); + SAVE_TOPO(ha); + ha->flags.rida_fmt2 = 0; ha->flags.n2n_ae = 0; ha->flags.lip_ae = 0; ha->current_topology = 0; |