diff options
author | Quinn Tran <qutran@marvell.com> | 2019-09-12 14:09:09 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-09-23 23:09:43 -0400 |
commit | 7f2a398d59d658818f3d219645164676fbbc88e8 (patch) | |
tree | 07f6ab0695c0cc594eec8567aa63a988d1dadfb4 | |
parent | f5187b7d1ac66b61676f896751d3af9fcf8dd592 (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.h | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 107 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 23 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 4 |
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 { | |||
3036 | enum fc4type_t { | 3036 | enum 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 | ||
3041 | struct fab_scan_rp { | 3042 | struct 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 | } | ||
5063 | skip_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", |