[PATCH 01/12] qla2xxx: Fix N2N link re-connect

2018-07-18 Thread Himanshu Madhani
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

2018-06-06 Thread Himanshu Madhani
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:
+