summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuinn Tran <qutran@marvell.com>2019-09-12 14:09:09 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2019-09-23 23:09:43 -0400
commit7f2a398d59d658818f3d219645164676fbbc88e8 (patch)
tree07f6ab0695c0cc594eec8567aa63a988d1dadfb4
parentf5187b7d1ac66b61676f896751d3af9fcf8dd592 (diff)
scsi: qla2xxx: Fix N2N link reset
Fix stalled link recovery for N2N with FC-NVMe connection. Link: https://lore.kernel.org/r/20190912180918.6436-6-hmadhani@marvell.com Signed-off-by: Quinn Tran <qutran@marvell.com> Signed-off-by: Himanshu Madhani <hmadhani@marvell.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c107
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c23
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c4
4 files changed, 103 insertions, 34 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index fa038568beb6..6ffa9877c28b 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2396,6 +2396,7 @@ typedef struct fc_port {
2396 unsigned int query:1; 2396 unsigned int query:1;
2397 unsigned int id_changed:1; 2397 unsigned int id_changed:1;
2398 unsigned int scan_needed:1; 2398 unsigned int scan_needed:1;
2399 unsigned int n2n_flag:1;
2399 2400
2400 struct completion nvme_del_done; 2401 struct completion nvme_del_done;
2401 uint32_t nvme_prli_service_param; 2402 uint32_t nvme_prli_service_param;
@@ -2446,7 +2447,6 @@ typedef struct fc_port {
2446 uint8_t fc4_type; 2447 uint8_t fc4_type;
2447 uint8_t fc4f_nvme; 2448 uint8_t fc4f_nvme;
2448 uint8_t scan_state; 2449 uint8_t scan_state;
2449 uint8_t n2n_flag;
2450 2450
2451 unsigned long last_queue_full; 2451 unsigned long last_queue_full;
2452 unsigned long last_ramp_up; 2452 unsigned long last_ramp_up;
@@ -3036,6 +3036,7 @@ enum scan_flags_t {
3036enum fc4type_t { 3036enum fc4type_t {
3037 FS_FC4TYPE_FCP = BIT_0, 3037 FS_FC4TYPE_FCP = BIT_0,
3038 FS_FC4TYPE_NVME = BIT_1, 3038 FS_FC4TYPE_NVME = BIT_1,
3039 FS_FCP_IS_N2N = BIT_7,
3039}; 3040};
3040 3041
3041struct fab_scan_rp { 3042struct fab_scan_rp {
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f6a5d78f93c9..67f522a8a9d4 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -746,12 +746,15 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
746 break; 746 break;
747 default: 747 default:
748 if ((id.b24 != fcport->d_id.b24 && 748 if ((id.b24 != fcport->d_id.b24 &&
749 fcport->d_id.b24) || 749 fcport->d_id.b24 &&
750 fcport->loop_id != FC_NO_LOOP_ID) ||
750 (fcport->loop_id != FC_NO_LOOP_ID && 751 (fcport->loop_id != FC_NO_LOOP_ID &&
751 fcport->loop_id != loop_id)) { 752 fcport->loop_id != loop_id)) {
752 ql_dbg(ql_dbg_disc, vha, 0x20e3, 753 ql_dbg(ql_dbg_disc, vha, 0x20e3,
753 "%s %d %8phC post del sess\n", 754 "%s %d %8phC post del sess\n",
754 __func__, __LINE__, fcport->port_name); 755 __func__, __LINE__, fcport->port_name);
756 if (fcport->n2n_flag)
757 fcport->d_id.b24 = 0;
755 qlt_schedule_sess_for_deletion(fcport); 758 qlt_schedule_sess_for_deletion(fcport);
756 return; 759 return;
757 } 760 }
@@ -759,6 +762,8 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
759 } 762 }
760 763
761 fcport->loop_id = loop_id; 764 fcport->loop_id = loop_id;
765 if (fcport->n2n_flag)
766 fcport->d_id.b24 = id.b24;
762 767
763 wwn = wwn_to_u64(fcport->port_name); 768 wwn = wwn_to_u64(fcport->port_name);
764 qlt_find_sess_invalidate_other(vha, wwn, 769 qlt_find_sess_invalidate_other(vha, wwn,
@@ -972,7 +977,7 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
972 wwn = wwn_to_u64(e->port_name); 977 wwn = wwn_to_u64(e->port_name);
973 978
974 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20e8, 979 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20e8,
975 "%s %8phC %02x:%02x:%02x state %d/%d lid %x \n", 980 "%s %8phC %02x:%02x:%02x CLS %x/%x lid %x \n",
976 __func__, (void *)&wwn, e->port_id[2], e->port_id[1], 981 __func__, (void *)&wwn, e->port_id[2], e->port_id[1],
977 e->port_id[0], e->current_login_state, e->last_login_state, 982 e->port_id[0], e->current_login_state, e->last_login_state,
978 (loop_id & 0x7fff)); 983 (loop_id & 0x7fff));
@@ -1499,7 +1504,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
1499 (fcport->fw_login_state == DSC_LS_PRLI_PEND))) 1504 (fcport->fw_login_state == DSC_LS_PRLI_PEND)))
1500 return 0; 1505 return 0;
1501 1506
1502 if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) { 1507 if (fcport->fw_login_state == DSC_LS_PLOGI_COMP &&
1508 !N2N_TOPO(vha->hw)) {
1503 if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) { 1509 if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) {
1504 set_bit(RELOGIN_NEEDED, &vha->dpc_flags); 1510 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1505 return 0; 1511 return 0;
@@ -1570,8 +1576,9 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
1570 qla24xx_post_gpdb_work(vha, fcport, 0); 1576 qla24xx_post_gpdb_work(vha, fcport, 0);
1571 } else { 1577 } else {
1572 ql_dbg(ql_dbg_disc, vha, 0x2118, 1578 ql_dbg(ql_dbg_disc, vha, 0x2118,
1573 "%s %d %8phC post NVMe PRLI\n", 1579 "%s %d %8phC post %s PRLI\n",
1574 __func__, __LINE__, fcport->port_name); 1580 __func__, __LINE__, fcport->port_name,
1581 fcport->fc4f_nvme ? "NVME" : "FC");
1575 qla24xx_post_prli_work(vha, fcport); 1582 qla24xx_post_prli_work(vha, fcport);
1576 } 1583 }
1577 break; 1584 break;
@@ -1853,17 +1860,38 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
1853 break; 1860 break;
1854 } 1861 }
1855 1862
1856 if (ea->fcport->n2n_flag) { 1863 if (ea->fcport->fc4f_nvme) {
1857 ql_dbg(ql_dbg_disc, vha, 0x2118, 1864 ql_dbg(ql_dbg_disc, vha, 0x2118,
1858 "%s %d %8phC post fc4 prli\n", 1865 "%s %d %8phC post fc4 prli\n",
1859 __func__, __LINE__, ea->fcport->port_name); 1866 __func__, __LINE__, ea->fcport->port_name);
1860 ea->fcport->fc4f_nvme = 0; 1867 ea->fcport->fc4f_nvme = 0;
1861 ea->fcport->n2n_flag = 0;
1862 qla24xx_post_prli_work(vha, ea->fcport); 1868 qla24xx_post_prli_work(vha, ea->fcport);
1869 return;
1870 }
1871
1872 /* at this point both PRLI NVME & PRLI FCP failed */
1873 if (N2N_TOPO(vha->hw)) {
1874 if (ea->fcport->n2n_link_reset_cnt < 3) {
1875 ea->fcport->n2n_link_reset_cnt++;
1876 /*
1877 * remote port is not sending Plogi. Reset
1878 * link to kick start his state machine
1879 */
1880 set_bit(N2N_LINK_RESET, &vha->dpc_flags);
1881 } else {
1882 ql_log(ql_log_warn, vha, 0x2119,
1883 "%s %d %8phC Unable to reconnect\n",
1884 __func__, __LINE__, ea->fcport->port_name);
1885 }
1886 } else {
1887 /*
1888 * switch connect. login failed. Take connection
1889 * down and allow relogin to retrigger
1890 */
1891 ea->fcport->flags &= ~FCF_ASYNC_SENT;
1892 ea->fcport->keep_nport_handle = 0;
1893 qlt_schedule_sess_for_deletion(ea->fcport);
1863 } 1894 }
1864 ql_dbg(ql_dbg_disc, vha, 0x2119,
1865 "%s %d %8phC unhandle event of %x\n",
1866 __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
1867 break; 1895 break;
1868 } 1896 }
1869} 1897}
@@ -5000,28 +5028,47 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
5000 unsigned long flags; 5028 unsigned long flags;
5001 5029
5002 /* Inititae N2N login. */ 5030 /* Inititae N2N login. */
5003 if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { 5031 if (N2N_TOPO(ha)) {
5004 /* borrowing */ 5032 if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
5005 u32 *bp, i, sz; 5033 /* borrowing */
5006 5034 u32 *bp, i, sz;
5007 memset(ha->init_cb, 0, ha->init_cb_size); 5035
5008 sz = min_t(int, sizeof(struct els_plogi_payload), 5036 memset(ha->init_cb, 0, ha->init_cb_size);
5009 ha->init_cb_size); 5037 sz = min_t(int, sizeof(struct els_plogi_payload),
5010 rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, 5038 ha->init_cb_size);
5011 (void *)ha->init_cb, sz); 5039 rval = qla24xx_get_port_login_templ(vha,
5012 if (rval == QLA_SUCCESS) { 5040 ha->init_cb_dma, (void *)ha->init_cb, sz);
5013 bp = (uint32_t *)ha->init_cb; 5041 if (rval == QLA_SUCCESS) {
5014 for (i = 0; i < sz/4 ; i++, bp++) 5042 bp = (uint32_t *)ha->init_cb;
5015 *bp = cpu_to_be32(*bp); 5043 for (i = 0; i < sz/4 ; i++, bp++)
5044 *bp = cpu_to_be32(*bp);
5016 5045
5017 memcpy(&ha->plogi_els_payld.data, (void *)ha->init_cb, 5046 memcpy(&ha->plogi_els_payld.data,
5018 sizeof(ha->plogi_els_payld.data)); 5047 (void *)ha->init_cb,
5019 set_bit(RELOGIN_NEEDED, &vha->dpc_flags); 5048 sizeof(ha->plogi_els_payld.data));
5020 } else { 5049 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
5021 ql_dbg(ql_dbg_init, vha, 0x00d1, 5050 } else {
5022 "PLOGI ELS param read fail.\n"); 5051 ql_dbg(ql_dbg_init, vha, 0x00d1,
5052 "PLOGI ELS param read fail.\n");
5053 goto skip_login;
5054 }
5055 }
5056
5057 list_for_each_entry(fcport, &vha->vp_fcports, list) {
5058 if (fcport->n2n_flag) {
5059 qla24xx_fcport_handle_login(vha, fcport);
5060 return QLA_SUCCESS;
5061 }
5062 }
5063skip_login:
5064 spin_lock_irqsave(&vha->work_lock, flags);
5065 vha->scan.scan_retry++;
5066 spin_unlock_irqrestore(&vha->work_lock, flags);
5067
5068 if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
5069 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
5070 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
5023 } 5071 }
5024 return QLA_SUCCESS;
5025 } 5072 }
5026 5073
5027 found_devs = 0; 5074 found_devs = 0;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 4c858e2d0ea8..6d6e10812b42 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2249,7 +2249,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
2249 mbx_cmd_t mc; 2249 mbx_cmd_t mc;
2250 mbx_cmd_t *mcp = &mc; 2250 mbx_cmd_t *mcp = &mc;
2251 2251
2252 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105a, 2252 ql_dbg(ql_dbg_disc, vha, 0x105a,
2253 "Entered %s.\n", __func__); 2253 "Entered %s.\n", __func__);
2254 2254
2255 if (IS_CNA_CAPABLE(vha->hw)) { 2255 if (IS_CNA_CAPABLE(vha->hw)) {
@@ -3883,14 +3883,23 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
3883 case TOPO_N2N: 3883 case TOPO_N2N:
3884 ha->current_topology = ISP_CFG_N; 3884 ha->current_topology = ISP_CFG_N;
3885 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); 3885 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
3886 list_for_each_entry(fcport, &vha->vp_fcports, list) {
3887 fcport->scan_state = QLA_FCPORT_SCAN;
3888 fcport->n2n_flag = 0;
3889 }
3890
3886 fcport = qla2x00_find_fcport_by_wwpn(vha, 3891 fcport = qla2x00_find_fcport_by_wwpn(vha,
3887 rptid_entry->u.f1.port_name, 1); 3892 rptid_entry->u.f1.port_name, 1);
3888 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); 3893 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
3889 3894
3890 if (fcport) { 3895 if (fcport) {
3891 fcport->plogi_nack_done_deadline = jiffies + HZ; 3896 fcport->plogi_nack_done_deadline = jiffies + HZ;
3892 fcport->dm_login_expire = jiffies + 3*HZ; 3897 fcport->dm_login_expire = jiffies + 2*HZ;
3893 fcport->scan_state = QLA_FCPORT_FOUND; 3898 fcport->scan_state = QLA_FCPORT_FOUND;
3899 fcport->n2n_flag = 1;
3900 if (vha->flags.nvme_enabled)
3901 fcport->fc4f_nvme = 1;
3902
3894 switch (fcport->disc_state) { 3903 switch (fcport->disc_state) {
3895 case DSC_DELETED: 3904 case DSC_DELETED:
3896 set_bit(RELOGIN_NEEDED, 3905 set_bit(RELOGIN_NEEDED,
@@ -3924,7 +3933,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
3924 rptid_entry->u.f1.port_name, 3933 rptid_entry->u.f1.port_name,
3925 rptid_entry->u.f1.node_name, 3934 rptid_entry->u.f1.node_name,
3926 NULL, 3935 NULL,
3927 FC4_TYPE_UNKNOWN); 3936 FS_FCP_IS_N2N);
3928 } 3937 }
3929 3938
3930 /* if our portname is higher then initiate N2N login */ 3939 /* if our portname is higher then initiate N2N login */
@@ -4023,6 +4032,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
4023 4032
4024 list_for_each_entry(fcport, &vha->vp_fcports, list) { 4033 list_for_each_entry(fcport, &vha->vp_fcports, list) {
4025 fcport->scan_state = QLA_FCPORT_SCAN; 4034 fcport->scan_state = QLA_FCPORT_SCAN;
4035 fcport->n2n_flag = 0;
4026 } 4036 }
4027 4037
4028 fcport = qla2x00_find_fcport_by_wwpn(vha, 4038 fcport = qla2x00_find_fcport_by_wwpn(vha,
@@ -4032,6 +4042,13 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
4032 fcport->login_retry = vha->hw->login_retry_count; 4042 fcport->login_retry = vha->hw->login_retry_count;
4033 fcport->plogi_nack_done_deadline = jiffies + HZ; 4043 fcport->plogi_nack_done_deadline = jiffies + HZ;
4034 fcport->scan_state = QLA_FCPORT_FOUND; 4044 fcport->scan_state = QLA_FCPORT_FOUND;
4045 fcport->n2n_flag = 1;
4046 fcport->d_id.b.domain =
4047 rptid_entry->u.f2.remote_nport_id[2];
4048 fcport->d_id.b.area =
4049 rptid_entry->u.f2.remote_nport_id[1];
4050 fcport->d_id.b.al_pa =
4051 rptid_entry->u.f2.remote_nport_id[0];
4035 } 4052 }
4036 } 4053 }
4037} 4054}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 5eda86ff6606..8411dd5acd43 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5033,6 +5033,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
5033 5033
5034 memcpy(fcport->port_name, e->u.new_sess.port_name, 5034 memcpy(fcport->port_name, e->u.new_sess.port_name,
5035 WWN_SIZE); 5035 WWN_SIZE);
5036
5037 if (e->u.new_sess.fc4_type & FS_FCP_IS_N2N)
5038 fcport->n2n_flag = 1;
5039
5036 } else { 5040 } else {
5037 ql_dbg(ql_dbg_disc, vha, 0xffff, 5041 ql_dbg(ql_dbg_disc, vha, 0xffff,
5038 "%s %8phC mem alloc fail.\n", 5042 "%s %8phC mem alloc fail.\n",