[PATCH 4.15 133/146] scsi: qla2xxx: Relogin to target port on a cable swap
4.15-stable review patch. If anyone has any objections, please let me know. -- From: Quinn Trancommit 5ef696aa9f3ccf999552d924c4e21a348f2bbea9 upstream. If user swaps one target port for another target port for same switch port, the new target port is not being recognized by the driver. Current code assumes that old Target port has recovered from link down. The fix will ask switch what is the WWPN of a specific NportID (GPNID) rather than assuming it's the same Target port which has came back. Fixes: 726b85487067d ("qla2xxx: Add framework for async fabric discovery") Cc: # 4.10+ Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_gs.c | 170 +- drivers/scsi/qla2xxx/qla_init.c |6 - drivers/scsi/qla2xxx/qla_os.c | 35 +++ drivers/scsi/qla2xxx/qla_target.c | 35 ++- 4 files changed, 197 insertions(+), 49 deletions(-) --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3171,43 +3171,136 @@ void qla24xx_async_gpnid_done(scsi_qla_h void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) { - fc_port_t *fcport; - unsigned long flags; + fc_port_t *fcport, *conflict, *t; - spin_lock_irqsave(>hw->tgt.sess_lock, flags); - fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1); - spin_unlock_irqrestore(>hw->tgt.sess_lock, flags); - - if (fcport) { - /* cable moved. just plugged in */ - fcport->rscn_gen++; - fcport->d_id = ea->id; - fcport->scan_state = QLA_FCPORT_FOUND; - fcport->flags |= FCF_FABRIC_DEVICE; - - switch (fcport->disc_state) { - case DSC_DELETED: - ql_dbg(ql_dbg_disc, vha, 0x210d, - "%s %d %8phC login\n", __func__, __LINE__, - fcport->port_name); - qla24xx_fcport_handle_login(vha, fcport); - break; - case DSC_DELETE_PEND: - break; - default: - ql_dbg(ql_dbg_disc, vha, 0x2064, - "%s %d %8phC post del sess\n", - __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion_lock(fcport); - break; + ql_dbg(ql_dbg_disc, vha, 0x, + "%s %d port_id: %06x\n", + __func__, __LINE__, ea->id.b24); + + if (ea->rc) { + /* cable is disconnected */ + list_for_each_entry_safe(fcport, t, >vp_fcports, list) { + if (fcport->d_id.b24 == ea->id.b24) { + ql_dbg(ql_dbg_disc, vha, 0x, + "%s %d %8phC DS %d\n", + __func__, __LINE__, + fcport->port_name, + fcport->disc_state); + fcport->scan_state = QLA_FCPORT_SCAN; + switch (fcport->disc_state) { + case DSC_DELETED: + case DSC_DELETE_PEND: + break; + default: + ql_dbg(ql_dbg_disc, vha, 0x, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + fcport->port_name); + qlt_schedule_sess_for_deletion_lock + (fcport); + break; + } + } } } else { - /* create new fcport */ - ql_dbg(ql_dbg_disc, vha, 0x2065, - "%s %d %8phC post new sess\n", - __func__, __LINE__, ea->port_name); - - qla24xx_post_newsess_work(vha, >id, ea->port_name, NULL); + /* cable is connected */ + fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1); + if (fcport) { + list_for_each_entry_safe(conflict, t, >vp_fcports, + list) { + if ((conflict->d_id.b24 == ea->id.b24) && + (fcport != conflict)) { + /* 2 fcports with conflict Nport ID or +*
[PATCH 4.15 133/146] scsi: qla2xxx: Relogin to target port on a cable swap
4.15-stable review patch. If anyone has any objections, please let me know. -- From: Quinn Tran commit 5ef696aa9f3ccf999552d924c4e21a348f2bbea9 upstream. If user swaps one target port for another target port for same switch port, the new target port is not being recognized by the driver. Current code assumes that old Target port has recovered from link down. The fix will ask switch what is the WWPN of a specific NportID (GPNID) rather than assuming it's the same Target port which has came back. Fixes: 726b85487067d ("qla2xxx: Add framework for async fabric discovery") Cc: # 4.10+ Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_gs.c | 170 +- drivers/scsi/qla2xxx/qla_init.c |6 - drivers/scsi/qla2xxx/qla_os.c | 35 +++ drivers/scsi/qla2xxx/qla_target.c | 35 ++- 4 files changed, 197 insertions(+), 49 deletions(-) --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3171,43 +3171,136 @@ void qla24xx_async_gpnid_done(scsi_qla_h void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) { - fc_port_t *fcport; - unsigned long flags; + fc_port_t *fcport, *conflict, *t; - spin_lock_irqsave(>hw->tgt.sess_lock, flags); - fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1); - spin_unlock_irqrestore(>hw->tgt.sess_lock, flags); - - if (fcport) { - /* cable moved. just plugged in */ - fcport->rscn_gen++; - fcport->d_id = ea->id; - fcport->scan_state = QLA_FCPORT_FOUND; - fcport->flags |= FCF_FABRIC_DEVICE; - - switch (fcport->disc_state) { - case DSC_DELETED: - ql_dbg(ql_dbg_disc, vha, 0x210d, - "%s %d %8phC login\n", __func__, __LINE__, - fcport->port_name); - qla24xx_fcport_handle_login(vha, fcport); - break; - case DSC_DELETE_PEND: - break; - default: - ql_dbg(ql_dbg_disc, vha, 0x2064, - "%s %d %8phC post del sess\n", - __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion_lock(fcport); - break; + ql_dbg(ql_dbg_disc, vha, 0x, + "%s %d port_id: %06x\n", + __func__, __LINE__, ea->id.b24); + + if (ea->rc) { + /* cable is disconnected */ + list_for_each_entry_safe(fcport, t, >vp_fcports, list) { + if (fcport->d_id.b24 == ea->id.b24) { + ql_dbg(ql_dbg_disc, vha, 0x, + "%s %d %8phC DS %d\n", + __func__, __LINE__, + fcport->port_name, + fcport->disc_state); + fcport->scan_state = QLA_FCPORT_SCAN; + switch (fcport->disc_state) { + case DSC_DELETED: + case DSC_DELETE_PEND: + break; + default: + ql_dbg(ql_dbg_disc, vha, 0x, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + fcport->port_name); + qlt_schedule_sess_for_deletion_lock + (fcport); + break; + } + } } } else { - /* create new fcport */ - ql_dbg(ql_dbg_disc, vha, 0x2065, - "%s %d %8phC post new sess\n", - __func__, __LINE__, ea->port_name); - - qla24xx_post_newsess_work(vha, >id, ea->port_name, NULL); + /* cable is connected */ + fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1); + if (fcport) { + list_for_each_entry_safe(conflict, t, >vp_fcports, + list) { + if ((conflict->d_id.b24 == ea->id.b24) && + (fcport != conflict)) { + /* 2 fcports with conflict Nport ID or +* an existing fcport is having nport ID +* conflict with new fcport. +*/ + +