[PATCH 01/12] qla2xxx: Fix N2N link re-connect
From: Quinn Tran In case of N2N connect, when sg_regset for bus/device/host was causing driver and firmware state to go out of sync. This patch fixes this link instablity when reconnect is attempted after link flap. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 3 +- drivers/scsi/qla2xxx/qla_init.c | 229 +- drivers/scsi/qla2xxx/qla_iocb.c | 15 ++- drivers/scsi/qla2xxx/qla_isr.c| 3 +- drivers/scsi/qla2xxx/qla_mbx.c| 27 + drivers/scsi/qla2xxx/qla_os.c | 5 + drivers/scsi/qla2xxx/qla_target.c | 9 ++ 7 files changed, 183 insertions(+), 108 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 9442e18aef6f..ee4d1f4fdf95 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -377,6 +377,7 @@ struct srb_iocb { #define SRB_LOGIN_COND_PLOGI BIT_1 #define SRB_LOGIN_SKIP_PRLIBIT_2 #define SRB_LOGIN_NVME_PRLIBIT_3 +#define SRB_LOGIN_PRLI_ONLYBIT_4 uint16_t data[2]; u32 iop[2]; } logio; @@ -4236,7 +4237,7 @@ typedef struct scsi_qla_host { #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ #define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ -#define FREE_BIT 21 +#define N2N_LINK_RESET 21 #define PORT_UPDATE_NEEDED 22 #define FX00_RESET_RECOVERY23 #define FX00_TARGET_SCAN 24 diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b0430a280ce6..b85c7d311376 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -160,6 +160,22 @@ qla2x00_async_login_sp_done(void *ptr, int res) sp->free(sp); } +static inline bool +fcport_is_smaller(fc_port_t *fcport) +{ + if (wwn_to_u64(fcport->port_name) < + wwn_to_u64(fcport->vha->port_name)) + return true; + else + return false; +} + +static inline bool +fcport_is_bigger(fc_port_t *fcport) +{ + return !fcport_is_smaller(fcport); +} + int qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, uint16_t *data) @@ -189,13 +205,18 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); sp->done = qla2x00_async_login_sp_done; - lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; + if (N2N_TOPO(fcport->vha->hw) && fcport_is_bigger(fcport)) { + lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY; + } else { + lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; - if (fcport->fc4f_nvme) - lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI; + if (fcport->fc4f_nvme) + lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI; + + if (data[1] & QLA_LOGIO_LOGIN_RETRIED) + lio->u.logio.flags |= SRB_LOGIN_RETRIED; + } - if (data[1] & QLA_LOGIO_LOGIN_RETRIED) - lio->u.logio.flags |= SRB_LOGIN_RETRIED; rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { fcport->flags |= FCF_LOGIN_NEEDED; @@ -497,15 +518,18 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, for (i = 0; i < n; i++) { e = >gnl.l[i]; wwn = wwn_to_u64(e->port_name); + id.b.domain = e->port_id[2]; + id.b.area = e->port_id[1]; + id.b.al_pa = e->port_id[0]; + id.b.rsvd_1 = 0; if (memcmp((u8 *), fcport->port_name, WWN_SIZE)) continue; + if (IS_SW_RESV_ADDR(id)) + continue; + found = 1; - id.b.domain = e->port_id[2]; - id.b.area = e->port_id[1]; - id.b.al_pa = e->port_id[0]; - id.b.rsvd_1 = 0; loop_id = le16_to_cpu(e->nport_handle); loop_id = (loop_id & 0x7fff); @@ -518,14 +542,18 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, loop_id, fcport->loop_id); - if ((id.b24 != fcport->d_id.b24) || - ((fcport->loop_id != FC_NO_LOOP_ID) && - (fcport->loop_id != loop_id))) { - ql_dbg(ql_dbg_disc, vha, 0x20e3, - "%s %d %8phC post del sess\n", - __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion(fcport); - return; + switch (fcport->disc_state) { + case DSC_DELETE_PEND: + case DSC_DELETED: +
[PATCH 01/12] qla2xxx: Fix N2N link re-connect
From: Quinn Tran In case of N2N connect, when sg_regset for bus/device/host was causing driver and firmware state to go out of sync. This patch fixes this link instablity when reconnect is attempted after link flap. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 3 +- drivers/scsi/qla2xxx/qla_init.c | 229 +- drivers/scsi/qla2xxx/qla_iocb.c | 15 ++- drivers/scsi/qla2xxx/qla_isr.c| 3 +- drivers/scsi/qla2xxx/qla_mbx.c| 27 + drivers/scsi/qla2xxx/qla_os.c | 5 + drivers/scsi/qla2xxx/qla_target.c | 9 ++ 7 files changed, 183 insertions(+), 108 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 9442e18aef6f..ee4d1f4fdf95 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -377,6 +377,7 @@ struct srb_iocb { #define SRB_LOGIN_COND_PLOGI BIT_1 #define SRB_LOGIN_SKIP_PRLIBIT_2 #define SRB_LOGIN_NVME_PRLIBIT_3 +#define SRB_LOGIN_PRLI_ONLYBIT_4 uint16_t data[2]; u32 iop[2]; } logio; @@ -4236,7 +4237,7 @@ typedef struct scsi_qla_host { #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ #define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ -#define FREE_BIT 21 +#define N2N_LINK_RESET 21 #define PORT_UPDATE_NEEDED 22 #define FX00_RESET_RECOVERY23 #define FX00_TARGET_SCAN 24 diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b0430a280ce6..b85c7d311376 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -160,6 +160,22 @@ qla2x00_async_login_sp_done(void *ptr, int res) sp->free(sp); } +static inline bool +fcport_is_smaller(fc_port_t *fcport) +{ + if (wwn_to_u64(fcport->port_name) < + wwn_to_u64(fcport->vha->port_name)) + return true; + else + return false; +} + +static inline bool +fcport_is_bigger(fc_port_t *fcport) +{ + return !fcport_is_smaller(fcport); +} + int qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, uint16_t *data) @@ -189,13 +205,18 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); sp->done = qla2x00_async_login_sp_done; - lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; + if (N2N_TOPO(fcport->vha->hw) && fcport_is_bigger(fcport)) { + lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY; + } else { + lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; - if (fcport->fc4f_nvme) - lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI; + if (fcport->fc4f_nvme) + lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI; + + if (data[1] & QLA_LOGIO_LOGIN_RETRIED) + lio->u.logio.flags |= SRB_LOGIN_RETRIED; + } - if (data[1] & QLA_LOGIO_LOGIN_RETRIED) - lio->u.logio.flags |= SRB_LOGIN_RETRIED; rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { fcport->flags |= FCF_LOGIN_NEEDED; @@ -497,15 +518,18 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, for (i = 0; i < n; i++) { e = >gnl.l[i]; wwn = wwn_to_u64(e->port_name); + id.b.domain = e->port_id[2]; + id.b.area = e->port_id[1]; + id.b.al_pa = e->port_id[0]; + id.b.rsvd_1 = 0; if (memcmp((u8 *), fcport->port_name, WWN_SIZE)) continue; + if (IS_SW_RESV_ADDR(id)) + continue; + found = 1; - id.b.domain = e->port_id[2]; - id.b.area = e->port_id[1]; - id.b.al_pa = e->port_id[0]; - id.b.rsvd_1 = 0; loop_id = le16_to_cpu(e->nport_handle); loop_id = (loop_id & 0x7fff); @@ -518,14 +542,18 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, loop_id, fcport->loop_id); - if ((id.b24 != fcport->d_id.b24) || - ((fcport->loop_id != FC_NO_LOOP_ID) && - (fcport->loop_id != loop_id))) { - ql_dbg(ql_dbg_disc, vha, 0x20e3, - "%s %d %8phC post del sess\n", - __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion(fcport); - return; + switch (fcport->disc_state) { + case DSC_DELETE_PEND: + case DSC_DELETED: +