From: Greg Kroah-Hartman Date: Thu, 17 Sep 2020 14:43:36 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.4.237~54 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=65bb92097ef1f3604ab84850051769f92b590d59;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: dsa-allow-forwarding-of-redirected-igmp-traffic.patch scsi-qla2xxx-move-rport-registration-out-of-internal-work_list.patch scsi-qla2xxx-reduce-holding-sess_lock-to-prevent-cpu-lock-up.patch scsi-qla2xxx-update-rscn_rcvd-field-to-more-meaningful-scan_needed.patch --- diff --git a/queue-4.19/dsa-allow-forwarding-of-redirected-igmp-traffic.patch b/queue-4.19/dsa-allow-forwarding-of-redirected-igmp-traffic.patch new file mode 100644 index 00000000000..0bfeca76913 --- /dev/null +++ b/queue-4.19/dsa-allow-forwarding-of-redirected-igmp-traffic.patch @@ -0,0 +1,113 @@ +From 1ed9ec9b08addbd8d3e36d5f4a652d8590a6ddb7 Mon Sep 17 00:00:00 2001 +From: Daniel Mack +Date: Sat, 20 Jun 2020 21:39:25 +0200 +Subject: dsa: Allow forwarding of redirected IGMP traffic + +From: Daniel Mack + +commit 1ed9ec9b08addbd8d3e36d5f4a652d8590a6ddb7 upstream. + +The driver for Marvell switches puts all ports in IGMP snooping mode +which results in all IGMP/MLD frames that ingress on the ports to be +forwarded to the CPU only. + +The bridge code in the kernel can then interpret these frames and act +upon them, for instance by updating the mdb in the switch to reflect +multicast memberships of stations connected to the ports. However, +the IGMP/MLD frames must then also be forwarded to other ports of the +bridge so external IGMP queriers can track membership reports, and +external multicast clients can receive query reports from foreign IGMP +queriers. + +Currently, this is impossible as the EDSA tagger sets offload_fwd_mark +on the skb when it unwraps the tagged frames, and that will make the +switchdev layer prevent the skb from egressing on any other port of +the same switch. + +To fix that, look at the To_CPU code in the DSA header and make +forwarding of the frame possible for trapped IGMP packets. + +Introduce some #defines for the frame types to make the code a bit more +comprehensive. + +This was tested on a Marvell 88E6352 variant. + +Signed-off-by: Daniel Mack +Reviewed-by: Andrew Lunn +Tested-by: Andrew Lunn +Signed-off-by: David S. Miller +Cc: DENG Qingfang +Signed-off-by: Greg Kroah-Hartman + +--- + net/dsa/tag_edsa.c | 37 ++++++++++++++++++++++++++++++++++--- + 1 file changed, 34 insertions(+), 3 deletions(-) + +--- a/net/dsa/tag_edsa.c ++++ b/net/dsa/tag_edsa.c +@@ -17,6 +17,16 @@ + #define DSA_HLEN 4 + #define EDSA_HLEN 8 + ++#define FRAME_TYPE_TO_CPU 0x00 ++#define FRAME_TYPE_FORWARD 0x03 ++ ++#define TO_CPU_CODE_MGMT_TRAP 0x00 ++#define TO_CPU_CODE_FRAME2REG 0x01 ++#define TO_CPU_CODE_IGMP_MLD_TRAP 0x02 ++#define TO_CPU_CODE_POLICY_TRAP 0x03 ++#define TO_CPU_CODE_ARP_MIRROR 0x04 ++#define TO_CPU_CODE_POLICY_MIRROR 0x05 ++ + static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); +@@ -81,6 +91,8 @@ static struct sk_buff *edsa_rcv(struct s + struct packet_type *pt) + { + u8 *edsa_header; ++ int frame_type; ++ int code; + int source_device; + int source_port; + +@@ -95,8 +107,29 @@ static struct sk_buff *edsa_rcv(struct s + /* + * Check that frame type is either TO_CPU or FORWARD. + */ +- if ((edsa_header[0] & 0xc0) != 0x00 && (edsa_header[0] & 0xc0) != 0xc0) ++ frame_type = edsa_header[0] >> 6; ++ ++ switch (frame_type) { ++ case FRAME_TYPE_TO_CPU: ++ code = (edsa_header[1] & 0x6) | ((edsa_header[2] >> 4) & 1); ++ ++ /* ++ * Mark the frame to never egress on any port of the same switch ++ * unless it's a trapped IGMP/MLD packet, in which case the ++ * bridge might want to forward it. ++ */ ++ if (code != TO_CPU_CODE_IGMP_MLD_TRAP) ++ skb->offload_fwd_mark = 1; ++ ++ break; ++ ++ case FRAME_TYPE_FORWARD: ++ skb->offload_fwd_mark = 1; ++ break; ++ ++ default: + return NULL; ++ } + + /* + * Determine source device and port. +@@ -160,8 +193,6 @@ static struct sk_buff *edsa_rcv(struct s + 2 * ETH_ALEN); + } + +- skb->offload_fwd_mark = 1; +- + return skb; + } + diff --git a/queue-4.19/scsi-qla2xxx-move-rport-registration-out-of-internal-work_list.patch b/queue-4.19/scsi-qla2xxx-move-rport-registration-out-of-internal-work_list.patch new file mode 100644 index 00000000000..0525a8d76e3 --- /dev/null +++ b/queue-4.19/scsi-qla2xxx-move-rport-registration-out-of-internal-work_list.patch @@ -0,0 +1,401 @@ +From cd4ed6b470f1569692b5d0d295b207f870570829 Mon Sep 17 00:00:00 2001 +From: Quinn Tran +Date: Fri, 31 Aug 2018 11:24:31 -0700 +Subject: scsi: qla2xxx: Move rport registration out of internal work_list + +From: Quinn Tran + +commit cd4ed6b470f1569692b5d0d295b207f870570829 upstream. + +Currently, the rport registration is being called from a single work element +that is used to process QLA internal "work_list". This work_list is meant for +quick and simple task (ie no sleep). The Rport registration process sometime +can be delayed by upper layer. This causes back pressure with the internal +queue where other jobs are unable to move forward. + +This patch will schedule the registration process with a new work element +(fc_port.reg_work). While the RPort is being registered, the current state of +the fcport will not move forward until the registration is done. If the state +of the fabric has changed, a new field/next_disc_state will record the next +action on whether to 'DELETE' or 'Reverify the session/ADISC'. + +Signed-off-by: Quinn Tran +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Signed-off-by: Zhengyuan Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_def.h | 6 +- + drivers/scsi/qla2xxx/qla_gbl.h | 5 +- + drivers/scsi/qla2xxx/qla_init.c | 66 ++++++++++++++++++++++++++---- + drivers/scsi/qla2xxx/qla_os.c | 26 +++++++---- + drivers/scsi/qla2xxx/qla_target.c | 83 ++++++++++++++++++++++++++++++-------- + 5 files changed, 147 insertions(+), 39 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2375,11 +2375,13 @@ typedef struct fc_port { + unsigned long expires; + struct list_head del_list_entry; + struct work_struct free_work; +- ++ struct work_struct reg_work; ++ uint64_t jiffies_at_registration; + struct qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX]; + + uint16_t tgt_id; + uint16_t old_tgt_id; ++ uint16_t sec_since_registration; + + uint8_t fcp_prio; + +@@ -2412,6 +2414,7 @@ typedef struct fc_port { + struct qla_tgt_sess *tgt_session; + struct ct_sns_desc ct_desc; + enum discovery_state disc_state; ++ enum discovery_state next_disc_state; + enum login_state fw_login_state; + unsigned long dm_login_expire; + unsigned long plogi_nack_done_deadline; +@@ -3222,7 +3225,6 @@ enum qla_work_type { + QLA_EVT_GPDB, + QLA_EVT_PRLI, + QLA_EVT_GPSC, +- QLA_EVT_UPD_FCPORT, + QLA_EVT_GNL, + QLA_EVT_NACK, + QLA_EVT_RELOGIN, +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -54,7 +54,7 @@ extern void qla2x00_abort_isp_cleanup(sc + extern void qla2x00_quiesce_io(scsi_qla_host_t *); + + extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); +- ++void qla_register_fcport_fn(struct work_struct *); + extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *); + extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *); + +@@ -109,6 +109,7 @@ int qla24xx_post_newsess_work(struct scs + int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); + int qla24xx_detect_sfp(scsi_qla_host_t *vha); + int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); ++ + void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *, + uint16_t *); + extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *, +@@ -208,7 +209,7 @@ extern void qla2x00_disable_board_on_pci + extern void qla2x00_sp_compl(void *, int); + extern void qla2xxx_qpair_sp_free_dma(void *); + extern void qla2xxx_qpair_sp_compl(void *, int); +-extern int qla24xx_post_upd_fcport_work(struct scsi_qla_host *, fc_port_t *); ++extern void qla24xx_sched_upd_fcport(fc_port_t *); + void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, + uint16_t *); + int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -1204,11 +1204,7 @@ void __qla24xx_handle_gpdb_event(scsi_ql + vha->fcport_count++; + ea->fcport->login_succ = 1; + +- ql_dbg(ql_dbg_disc, vha, 0x20d6, +- "%s %d %8phC post upd_fcport fcp_cnt %d\n", +- __func__, __LINE__, ea->fcport->port_name, +- vha->fcport_count); +- qla24xx_post_upd_fcport_work(vha, ea->fcport); ++ qla24xx_sched_upd_fcport(ea->fcport); + } else if (ea->fcport->login_succ) { + /* + * We have an existing session. A late RSCN delivery +@@ -1326,6 +1322,7 @@ int qla24xx_fcport_handle_login(struct s + { + u16 data[2]; + u64 wwn; ++ u16 sec; + + ql_dbg(ql_dbg_disc, vha, 0x20d8, + "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d retry %d lid %d scan %d\n", +@@ -1457,6 +1454,22 @@ int qla24xx_fcport_handle_login(struct s + qla24xx_post_prli_work(vha, fcport); + break; + ++ case DSC_UPD_FCPORT: ++ sec = jiffies_to_msecs(jiffies - ++ fcport->jiffies_at_registration)/1000; ++ if (fcport->sec_since_registration < sec && sec && ++ !(sec % 60)) { ++ fcport->sec_since_registration = sec; ++ ql_dbg(ql_dbg_disc, fcport->vha, 0xffff, ++ "%s %8phC - Slow Rport registration(%d Sec)\n", ++ __func__, fcport->port_name, sec); ++ } ++ ++ if (fcport->next_disc_state != DSC_DELETE_PEND) ++ fcport->next_disc_state = DSC_ADISC; ++ set_bit(RELOGIN_NEEDED, &vha->dpc_flags); ++ break; ++ + default: + break; + } +@@ -1572,8 +1585,10 @@ void qla2x00_fcport_event_handler(scsi_q + case RSCN_PORT_ADDR: + fcport = qla2x00_find_fcport_by_nportid + (vha, &ea->id, 1); +- if (fcport) ++ if (fcport) { + fcport->scan_needed = 1; ++ fcport->rscn_gen++; ++ } + + spin_lock_irqsave(&vha->work_lock, flags); + if (vha->scan.scan_flags == 0) { +@@ -4741,6 +4756,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vh + return NULL; + } + INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn); ++ INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); + INIT_LIST_HEAD(&fcport->gnl_entry); + INIT_LIST_HEAD(&fcport->list); + +@@ -5221,13 +5237,15 @@ qla2x00_reg_remote_port(scsi_qla_host_t + void + qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) + { +- fcport->vha = vha; +- + if (IS_SW_RESV_ADDR(fcport->d_id)) + return; + ++ ql_dbg(ql_dbg_disc, vha, 0x20ef, "%s %8phC\n", ++ __func__, fcport->port_name); ++ ++ fcport->disc_state = DSC_UPD_FCPORT; ++ fcport->login_retry = vha->hw->login_retry_count; + fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); +- fcport->disc_state = DSC_LOGIN_COMPLETE; + fcport->deleted = 0; + fcport->logout_on_delete = 1; + fcport->login_retry = vha->hw->login_retry_count; +@@ -5289,6 +5307,36 @@ qla2x00_update_fcport(scsi_qla_host_t *v + } + } + qla2x00_set_fcport_state(fcport, FCS_ONLINE); ++ ++ fcport->disc_state = DSC_LOGIN_COMPLETE; ++} ++ ++void qla_register_fcport_fn(struct work_struct *work) ++{ ++ fc_port_t *fcport = container_of(work, struct fc_port, reg_work); ++ u32 rscn_gen = fcport->rscn_gen; ++ u16 data[2]; ++ ++ if (IS_SW_RESV_ADDR(fcport->d_id)) ++ return; ++ ++ qla2x00_update_fcport(fcport->vha, fcport); ++ ++ if (rscn_gen != fcport->rscn_gen) { ++ /* RSCN(s) came in while registration */ ++ switch (fcport->next_disc_state) { ++ case DSC_DELETE_PEND: ++ qlt_schedule_sess_for_deletion(fcport); ++ break; ++ case DSC_ADISC: ++ data[0] = data[1] = 0; ++ qla2x00_post_async_adisc_work(fcport->vha, fcport, ++ data); ++ break; ++ default: ++ break; ++ } ++ } + } + + /* +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -4792,16 +4792,25 @@ qlafx00_post_aenfx_work(struct scsi_qla_ + return qla2x00_post_work(vha, e); + } + +-int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport) ++void qla24xx_sched_upd_fcport(fc_port_t *fcport) + { +- struct qla_work_evt *e; ++ unsigned long flags; + +- e = qla2x00_alloc_work(vha, QLA_EVT_UPD_FCPORT); +- if (!e) +- return QLA_FUNCTION_FAILED; ++ if (IS_SW_RESV_ADDR(fcport->d_id)) ++ return; + +- e->u.fcport.fcport = fcport; +- return qla2x00_post_work(vha, e); ++ spin_lock_irqsave(&fcport->vha->work_lock, flags); ++ if (fcport->disc_state == DSC_UPD_FCPORT) { ++ spin_unlock_irqrestore(&fcport->vha->work_lock, flags); ++ return; ++ } ++ fcport->jiffies_at_registration = jiffies; ++ fcport->sec_since_registration = 0; ++ fcport->next_disc_state = DSC_DELETED; ++ fcport->disc_state = DSC_UPD_FCPORT; ++ spin_unlock_irqrestore(&fcport->vha->work_lock, flags); ++ ++ queue_work(system_unbound_wq, &fcport->reg_work); + } + + static +@@ -5057,9 +5066,6 @@ qla2x00_do_work(struct scsi_qla_host *vh + case QLA_EVT_GPSC: + qla24xx_async_gpsc(vha, e->u.fcport.fcport); + break; +- case QLA_EVT_UPD_FCPORT: +- qla2x00_update_fcport(vha, e->u.fcport.fcport); +- break; + case QLA_EVT_GNL: + qla24xx_async_gnl(vha, e->u.fcport.fcport); + break; +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -600,14 +600,7 @@ void qla2x00_async_nack_sp_done(void *s, + sp->fcport->login_succ = 1; + + vha->fcport_count++; +- +- ql_dbg(ql_dbg_disc, vha, 0x20f3, +- "%s %d %8phC post upd_fcport fcp_cnt %d\n", +- __func__, __LINE__, +- sp->fcport->port_name, +- vha->fcport_count); +- sp->fcport->disc_state = DSC_UPD_FCPORT; +- qla24xx_post_upd_fcport_work(vha, sp->fcport); ++ qla24xx_sched_upd_fcport(sp->fcport); + } else { + sp->fcport->login_retry = 0; + sp->fcport->disc_state = DSC_LOGIN_COMPLETE; +@@ -1227,11 +1220,12 @@ void qlt_schedule_sess_for_deletion(stru + { + struct qla_tgt *tgt = sess->tgt; + unsigned long flags; ++ u16 sec; + +- if (sess->disc_state == DSC_DELETE_PEND) ++ switch (sess->disc_state) { ++ case DSC_DELETE_PEND: + return; +- +- if (sess->disc_state == DSC_DELETED) { ++ case DSC_DELETED: + if (tgt && tgt->tgt_stop && (tgt->sess_count == 0)) + wake_up_all(&tgt->waitQ); + if (sess->vha->fcport_count == 0) +@@ -1240,6 +1234,24 @@ void qlt_schedule_sess_for_deletion(stru + if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] && + !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]) + return; ++ break; ++ case DSC_UPD_FCPORT: ++ /* ++ * This port is not done reporting to upper layer. ++ * let it finish ++ */ ++ sess->next_disc_state = DSC_DELETE_PEND; ++ sec = jiffies_to_msecs(jiffies - ++ sess->jiffies_at_registration)/1000; ++ if (sess->sec_since_registration < sec && sec && !(sec % 5)) { ++ sess->sec_since_registration = sec; ++ ql_dbg(ql_dbg_disc, sess->vha, 0xffff, ++ "%s %8phC : Slow Rport registration(%d Sec)\n", ++ __func__, sess->port_name, sec); ++ } ++ return; ++ default: ++ break; + } + + if (sess->deleted == QLA_SESS_DELETED) +@@ -4749,6 +4761,32 @@ static int qlt_handle_login(struct scsi_ + goto out; + } + ++ if (sess->disc_state == DSC_UPD_FCPORT) { ++ u16 sec; ++ ++ /* ++ * Remote port registration is still going on from ++ * previous login. Allow it to finish before we ++ * accept the new login. ++ */ ++ sess->next_disc_state = DSC_DELETE_PEND; ++ sec = jiffies_to_msecs(jiffies - ++ sess->jiffies_at_registration) / 1000; ++ if (sess->sec_since_registration < sec && sec && ++ !(sec % 5)) { ++ sess->sec_since_registration = sec; ++ ql_dbg(ql_dbg_disc, vha, 0xffff, ++ "%s %8phC - Slow Rport registration (%d Sec)\n", ++ __func__, sess->port_name, sec); ++ } ++ ++ if (!conflict_sess) ++ kmem_cache_free(qla_tgt_plogi_cachep, pla); ++ ++ qlt_send_term_imm_notif(vha, iocb, 1); ++ goto out; ++ } ++ + qlt_plogi_ack_link(vha, pla, sess, QLT_PLOGI_LINK_SAME_WWN); + sess->d_id = port_id; + sess->login_gen++; +@@ -4908,6 +4946,7 @@ static int qlt_24xx_handle_els(struct sc + + if (sess != NULL) { + bool delete = false; ++ int sec; + spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags); + switch (sess->fw_login_state) { + case DSC_LS_PLOGI_PEND: +@@ -4920,9 +4959,24 @@ static int qlt_24xx_handle_els(struct sc + } + + switch (sess->disc_state) { ++ case DSC_UPD_FCPORT: ++ spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, ++ flags); ++ ++ sec = jiffies_to_msecs(jiffies - ++ sess->jiffies_at_registration)/1000; ++ if (sess->sec_since_registration < sec && sec && ++ !(sec % 5)) { ++ sess->sec_since_registration = sec; ++ ql_dbg(ql_dbg_disc, sess->vha, 0xffff, ++ "%s %8phC : Slow Rport registration(%d Sec)\n", ++ __func__, sess->port_name, sec); ++ } ++ qlt_send_term_imm_notif(vha, iocb, 1); ++ return 0; ++ + case DSC_LOGIN_PEND: + case DSC_GPDB: +- case DSC_UPD_FCPORT: + case DSC_LOGIN_COMPLETE: + case DSC_ADISC: + delete = false; +@@ -5959,10 +6013,7 @@ static fc_port_t *qlt_get_port_database( + case MODE_DUAL: + if (newfcport) { + if (!IS_IIDMA_CAPABLE(vha->hw) || !vha->hw->flags.gpsc_supported) { +- ql_dbg(ql_dbg_disc, vha, 0x20fe, +- "%s %d %8phC post upd_fcport fcp_cnt %d\n", +- __func__, __LINE__, fcport->port_name, vha->fcport_count); +- qla24xx_post_upd_fcport_work(vha, fcport); ++ qla24xx_sched_upd_fcport(fcport); + } else { + ql_dbg(ql_dbg_disc, vha, 0x20ff, + "%s %d %8phC post gpsc fcp_cnt %d\n", diff --git a/queue-4.19/scsi-qla2xxx-reduce-holding-sess_lock-to-prevent-cpu-lock-up.patch b/queue-4.19/scsi-qla2xxx-reduce-holding-sess_lock-to-prevent-cpu-lock-up.patch new file mode 100644 index 00000000000..a4a3e081889 --- /dev/null +++ b/queue-4.19/scsi-qla2xxx-reduce-holding-sess_lock-to-prevent-cpu-lock-up.patch @@ -0,0 +1,226 @@ +From 0aca77843e2803bf4fab1598b7891c56c16be979 Mon Sep 17 00:00:00 2001 +From: Quinn Tran +Date: Tue, 4 Sep 2018 14:19:16 -0700 +Subject: scsi: qla2xxx: Reduce holding sess_lock to prevent CPU lock-up + +From: Quinn Tran + +commit 0aca77843e2803bf4fab1598b7891c56c16be979 upstream. + +- Reduce sess_lock holding to prevent CPU Lock up. sess_lock was held across + fc_port registration and deletion. These calls can be blocked by upper + layer. Sess_lock is also being accessed by interrupt thread. + +- Reduce number of loops in processing work_list to prevent kernel complaint + of CPU lockup or holding sess_lock. + +Reported-by: Zhengyuan Liu +Tested-by: Zhengyuan Liu +Fixes: 9ba1cb25c151 ("scsi: qla2xxx: Remove all rports if fabric scan retry fails") +Link: https://lore.kernel.org/linux-scsi/D01377DD-2E86-427B-BA0C-8D7649E37870@oracle.com/T/#t +Signed-off-by: Quinn Tran +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_def.h | 2 +- + drivers/scsi/qla2xxx/qla_gs.c | 18 ++++++++++++------ + drivers/scsi/qla2xxx/qla_init.c | 33 +++++++++++++++++---------------- + drivers/scsi/qla2xxx/qla_os.c | 3 +-- + drivers/scsi/qla2xxx/qla_target.c | 2 ++ + 5 files changed, 33 insertions(+), 25 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -262,8 +262,8 @@ struct name_list_extended { + struct get_name_list_extended *l; + dma_addr_t ldma; + struct list_head fcports; +- spinlock_t fcports_lock; + u32 size; ++ u8 sent; + }; + /* + * Timeout timer counts in seconds +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -4018,11 +4018,10 @@ void qla24xx_async_gnnft_done(scsi_qla_h + if ((qla_dual_mode_enabled(vha) || + qla_ini_mode_enabled(vha)) && + atomic_read(&fcport->state) == FCS_ONLINE) { +- qla2x00_mark_device_lost(vha, fcport, +- ql2xplogiabsentdevice, 0); ++ if (fcport->loop_id != FC_NO_LOOP_ID) { ++ if (fcport->flags & FCF_FCP2_DEVICE) ++ fcport->logout_on_delete = 0; + +- if (fcport->loop_id != FC_NO_LOOP_ID && +- (fcport->flags & FCF_FCP2_DEVICE) == 0) { + ql_dbg(ql_dbg_disc, vha, 0x20f0, + "%s %d %8phC post del sess\n", + __func__, __LINE__, +@@ -4261,12 +4260,13 @@ static void qla2x00_async_gpnft_gnnft_sp + + sp->rc = res; + rc = qla2x00_post_nvme_gpnft_done_work(vha, sp, QLA_EVT_GPNFT); +- if (!rc) { ++ if (rc) { + qla24xx_sp_unmap(vha, sp); + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + return; + } ++ return; + } + + if (cmd == GPN_FT_CMD) { +@@ -4316,6 +4316,8 @@ static int qla24xx_async_gnnft(scsi_qla_ + vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); + WARN_ON(1); ++ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); ++ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + goto done_free_sp; + } + +@@ -4349,8 +4351,12 @@ static int qla24xx_async_gnnft(scsi_qla_ + sp->done = qla2x00_async_gpnft_gnnft_sp_done; + + rval = qla2x00_start_sp(sp); +- if (rval != QLA_SUCCESS) ++ if (rval != QLA_SUCCESS) { ++ spin_lock_irqsave(&vha->work_lock, flags); ++ vha->scan.scan_flags &= ~SF_SCANNING; ++ spin_unlock_irqrestore(&vha->work_lock, flags); + goto done_free_sp; ++ } + + ql_dbg(ql_dbg_disc, vha, 0xffff, + "Async-%s hdl=%x FC4Type %x.\n", sp->name, +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -800,6 +800,7 @@ qla24xx_async_gnl_sp_done(void *s, int r + if (res == QLA_FUNCTION_TIMEOUT) + return; + ++ sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE); + memset(&ea, 0, sizeof(ea)); + ea.sp = sp; + ea.rc = res; +@@ -827,25 +828,24 @@ qla24xx_async_gnl_sp_done(void *s, int r + (loop_id & 0x7fff)); + } + +- spin_lock_irqsave(&vha->gnl.fcports_lock, flags); ++ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + + INIT_LIST_HEAD(&h); + fcport = tf = NULL; + if (!list_empty(&vha->gnl.fcports)) + list_splice_init(&vha->gnl.fcports, &h); ++ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + + list_for_each_entry_safe(fcport, tf, &h, gnl_entry) { + list_del_init(&fcport->gnl_entry); +- spin_lock(&vha->hw->tgt.sess_lock); ++ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); +- spin_unlock(&vha->hw->tgt.sess_lock); ++ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + ea.fcport = fcport; + + qla2x00_fcport_event_handler(vha, &ea); + } +- spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags); + +- spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + /* create new fcport if fw has knowledge of new sessions */ + for (i = 0; i < n; i++) { + port_id_t id; +@@ -878,6 +878,8 @@ qla24xx_async_gnl_sp_done(void *s, int r + } + } + ++ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); ++ vha->gnl.sent = 0; + spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + + sp->free(sp); +@@ -897,27 +899,24 @@ int qla24xx_async_gnl(struct scsi_qla_ho + ql_dbg(ql_dbg_disc, vha, 0x20d9, + "Async-gnlist WWPN %8phC \n", fcport->port_name); + +- spin_lock_irqsave(&vha->gnl.fcports_lock, flags); +- if (!list_empty(&fcport->gnl_entry)) { +- spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags); +- rval = QLA_SUCCESS; +- goto done; +- } +- +- spin_lock(&vha->hw->tgt.sess_lock); ++ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); ++ fcport->flags |= FCF_ASYNC_SENT; + fcport->disc_state = DSC_GNL; + fcport->last_rscn_gen = fcport->rscn_gen; + fcport->last_login_gen = fcport->login_gen; +- spin_unlock(&vha->hw->tgt.sess_lock); + + list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports); +- spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags); ++ if (vha->gnl.sent) { ++ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); ++ return QLA_SUCCESS; ++ } ++ vha->gnl.sent = 1; ++ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + + sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + if (!sp) + goto done; + +- fcport->flags |= FCF_ASYNC_SENT; + sp->type = SRB_MB_IOCB; + sp->name = "gnlist"; + sp->gen1 = fcport->rscn_gen; +@@ -1204,7 +1203,9 @@ void __qla24xx_handle_gpdb_event(scsi_ql + vha->fcport_count++; + ea->fcport->login_succ = 1; + ++ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + qla24xx_sched_upd_fcport(ea->fcport); ++ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + } else if (ea->fcport->login_succ) { + /* + * We have an existing session. A late RSCN delivery +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -2719,7 +2719,7 @@ static void qla2x00_iocb_work_fn(struct + struct scsi_qla_host, iocb_work); + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); +- int i = 20; ++ int i = 2; + unsigned long flags; + + if (test_bit(UNLOADING, &base_vha->dpc_flags)) +@@ -4606,7 +4606,6 @@ struct scsi_qla_host *qla2x00_create_hos + + spin_lock_init(&vha->work_lock); + spin_lock_init(&vha->cmd_list_lock); +- spin_lock_init(&vha->gnl.fcports_lock); + init_waitqueue_head(&vha->fcport_waitQ); + init_waitqueue_head(&vha->vref_waitq); + +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -600,7 +600,9 @@ void qla2x00_async_nack_sp_done(void *s, + sp->fcport->login_succ = 1; + + vha->fcport_count++; ++ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + qla24xx_sched_upd_fcport(sp->fcport); ++ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + } else { + sp->fcport->login_retry = 0; + sp->fcport->disc_state = DSC_LOGIN_COMPLETE; diff --git a/queue-4.19/scsi-qla2xxx-update-rscn_rcvd-field-to-more-meaningful-scan_needed.patch b/queue-4.19/scsi-qla2xxx-update-rscn_rcvd-field-to-more-meaningful-scan_needed.patch new file mode 100644 index 00000000000..40faf541961 --- /dev/null +++ b/queue-4.19/scsi-qla2xxx-update-rscn_rcvd-field-to-more-meaningful-scan_needed.patch @@ -0,0 +1,98 @@ +From cb873ba4002095d1e2fc60521bc4d860c7b72b92 Mon Sep 17 00:00:00 2001 +From: Quinn Tran +Date: Fri, 31 Aug 2018 11:24:29 -0700 +Subject: scsi: qla2xxx: Update rscn_rcvd field to more meaningful scan_needed + +From: Quinn Tran + +commit cb873ba4002095d1e2fc60521bc4d860c7b72b92 upstream. + +Rename rscn_rcvd field to scan_needed to be more meaningful. + +Signed-off-by: Quinn Tran +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Signed-off-by: Zhengyuan Liu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_def.h | 2 +- + drivers/scsi/qla2xxx/qla_gs.c | 12 ++++++------ + drivers/scsi/qla2xxx/qla_init.c | 2 +- + 3 files changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2351,7 +2351,7 @@ typedef struct fc_port { + unsigned int login_succ:1; + unsigned int query:1; + unsigned int id_changed:1; +- unsigned int rscn_rcvd:1; ++ unsigned int scan_needed:1; + + struct work_struct nvme_del_work; + struct completion nvme_del_done; +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -3973,7 +3973,7 @@ void qla24xx_async_gnnft_done(scsi_qla_h + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE)) + continue; +- fcport->rscn_rcvd = 0; ++ fcport->scan_needed = 0; + fcport->scan_state = QLA_FCPORT_FOUND; + found = true; + /* +@@ -4009,12 +4009,12 @@ void qla24xx_async_gnnft_done(scsi_qla_h + */ + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) { +- fcport->rscn_rcvd = 0; ++ fcport->scan_needed = 0; + continue; + } + + if (fcport->scan_state != QLA_FCPORT_FOUND) { +- fcport->rscn_rcvd = 0; ++ fcport->scan_needed = 0; + if ((qla_dual_mode_enabled(vha) || + qla_ini_mode_enabled(vha)) && + atomic_read(&fcport->state) == FCS_ONLINE) { +@@ -4033,7 +4033,7 @@ void qla24xx_async_gnnft_done(scsi_qla_h + } + } + } else { +- if (fcport->rscn_rcvd || ++ if (fcport->scan_needed || + fcport->disc_state != DSC_LOGIN_COMPLETE) { + if (fcport->login_retry == 0) { + fcport->login_retry = +@@ -4043,7 +4043,7 @@ void qla24xx_async_gnnft_done(scsi_qla_h + fcport->port_name, fcport->loop_id, + fcport->login_retry); + } +- fcport->rscn_rcvd = 0; ++ fcport->scan_needed = 0; + qla24xx_fcport_handle_login(vha, fcport); + } + } +@@ -4058,7 +4058,7 @@ out: + + if (recheck) { + list_for_each_entry(fcport, &vha->vp_fcports, list) { +- if (fcport->rscn_rcvd) { ++ if (fcport->scan_needed) { + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + break; +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -1573,7 +1573,7 @@ void qla2x00_fcport_event_handler(scsi_q + fcport = qla2x00_find_fcport_by_nportid + (vha, &ea->id, 1); + if (fcport) +- fcport->rscn_rcvd = 1; ++ fcport->scan_needed = 1; + + spin_lock_irqsave(&vha->work_lock, flags); + if (vha->scan.scan_flags == 0) { diff --git a/queue-4.19/series b/queue-4.19/series new file mode 100644 index 00000000000..fa17740383b --- /dev/null +++ b/queue-4.19/series @@ -0,0 +1,4 @@ +dsa-allow-forwarding-of-redirected-igmp-traffic.patch +scsi-qla2xxx-update-rscn_rcvd-field-to-more-meaningful-scan_needed.patch +scsi-qla2xxx-move-rport-registration-out-of-internal-work_list.patch +scsi-qla2xxx-reduce-holding-sess_lock-to-prevent-cpu-lock-up.patch