Skip to content

Commit c3d98b1

Browse files
Quinn Tranmartinkpetersen
authored andcommitted
scsi: qla2xxx: Unable to act on RSCN for port online
The device does not come online when the target port is online. There were multiple RSCNs indicating multiple devices were affected. Driver is in the process of finishing a fabric scan. A new RSCN (device up) arrived at the tail end of the last fabric scan. Driver mistakenly thinks the new RSCN is being taken care of by the previous fabric scan, where this notification is cleared and not acted on. The laser needs to be blinked again to get the device to show up. To prevent driver from accidentally clearing the RSCN notification, each RSCN is given a generation value. A fabric scan will scan for that generation(s). Any new RSCN arrive after the scan start will have a new generation value. This will trigger another scan to get latest data. The RSCN notification flag will be cleared when the scan is associate to that generation. Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/ Fixes: bb2ca6b ("scsi: qla2xxx: Relogin during fabric disturbance") Cc: [email protected] Signed-off-by: Quinn Tran <[email protected]> Signed-off-by: Nilesh Javali <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Himanshu Madhani <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 1613e60 commit c3d98b1

File tree

4 files changed

+60
-8
lines changed

4 files changed

+60
-8
lines changed

drivers/scsi/qla2xxx/qla_def.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,6 +3312,8 @@ struct fab_scan_rp {
33123312
struct fab_scan {
33133313
struct fab_scan_rp *l;
33143314
u32 size;
3315+
u32 rscn_gen_start;
3316+
u32 rscn_gen_end;
33153317
u16 scan_retry;
33163318
#define MAX_SCAN_RETRIES 5
33173319
enum scan_flags_t scan_flags;
@@ -5030,6 +5032,7 @@ typedef struct scsi_qla_host {
50305032

50315033
/* Counter to detect races between ELS and RSCN events */
50325034
atomic_t generation_tick;
5035+
atomic_t rscn_gen;
50335036
/* Time when global fcport update has been scheduled */
50345037
int total_fcport_update_gen;
50355038
/* List of pending LOGOs, protected by tgt_mutex */

drivers/scsi/qla2xxx/qla_gs.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3168,6 +3168,29 @@ static int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn)
31683168
return rc;
31693169
}
31703170

3171+
static bool qla_ok_to_clear_rscn(scsi_qla_host_t *vha, fc_port_t *fcport)
3172+
{
3173+
u32 rscn_gen;
3174+
3175+
rscn_gen = atomic_read(&vha->rscn_gen);
3176+
ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2017,
3177+
"%s %d %8phC rscn_gen %x start %x end %x current %x\n",
3178+
__func__, __LINE__, fcport->port_name, fcport->rscn_gen,
3179+
vha->scan.rscn_gen_start, vha->scan.rscn_gen_end, rscn_gen);
3180+
3181+
if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_start,
3182+
vha->scan.rscn_gen_end))
3183+
/* rscn came in before fabric scan */
3184+
return true;
3185+
3186+
if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_end, rscn_gen))
3187+
/* rscn came in after fabric scan */
3188+
return false;
3189+
3190+
/* rare: fcport's scan_needed + rscn_gen must be stale */
3191+
return true;
3192+
}
3193+
31713194
void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
31723195
{
31733196
fc_port_t *fcport;
@@ -3281,10 +3304,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
32813304
(fcport->scan_needed &&
32823305
fcport->port_type != FCT_INITIATOR &&
32833306
fcport->port_type != FCT_NVME_INITIATOR)) {
3307+
fcport->scan_needed = 0;
32843308
qlt_schedule_sess_for_deletion(fcport);
32853309
}
32863310
fcport->d_id.b24 = rp->id.b24;
3287-
fcport->scan_needed = 0;
32883311
break;
32893312
}
32903313

@@ -3325,7 +3348,9 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
33253348
do_delete = true;
33263349
}
33273350

3328-
fcport->scan_needed = 0;
3351+
if (qla_ok_to_clear_rscn(vha, fcport))
3352+
fcport->scan_needed = 0;
3353+
33293354
if (((qla_dual_mode_enabled(vha) ||
33303355
qla_ini_mode_enabled(vha)) &&
33313356
atomic_read(&fcport->state) == FCS_ONLINE) ||
@@ -3355,7 +3380,9 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
33553380
fcport->port_name, fcport->loop_id,
33563381
fcport->login_retry);
33573382
}
3358-
fcport->scan_needed = 0;
3383+
3384+
if (qla_ok_to_clear_rscn(vha, fcport))
3385+
fcport->scan_needed = 0;
33593386
qla24xx_fcport_handle_login(vha, fcport);
33603387
}
33613388
}

drivers/scsi/qla2xxx/qla_init.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,10 +1842,18 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
18421842
return qla2x00_post_work(vha, e);
18431843
}
18441844

1845+
static void qla_rscn_gen_tick(scsi_qla_host_t *vha, u32 *ret_rscn_gen)
1846+
{
1847+
*ret_rscn_gen = atomic_inc_return(&vha->rscn_gen);
1848+
/* memory barrier */
1849+
wmb();
1850+
}
1851+
18451852
void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
18461853
{
18471854
fc_port_t *fcport;
18481855
unsigned long flags;
1856+
u32 rscn_gen;
18491857

18501858
switch (ea->id.b.rsvd_1) {
18511859
case RSCN_PORT_ADDR:
@@ -1875,47 +1883,50 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
18751883
* Otherwise we're already in the middle of a relogin
18761884
*/
18771885
fcport->scan_needed = 1;
1878-
fcport->rscn_gen++;
1886+
qla_rscn_gen_tick(vha, &fcport->rscn_gen);
18791887
}
18801888
} else {
18811889
fcport->scan_needed = 1;
1882-
fcport->rscn_gen++;
1890+
qla_rscn_gen_tick(vha, &fcport->rscn_gen);
18831891
}
18841892
}
18851893
break;
18861894
case RSCN_AREA_ADDR:
1895+
qla_rscn_gen_tick(vha, &rscn_gen);
18871896
list_for_each_entry(fcport, &vha->vp_fcports, list) {
18881897
if (fcport->flags & FCF_FCP2_DEVICE &&
18891898
atomic_read(&fcport->state) == FCS_ONLINE)
18901899
continue;
18911900

18921901
if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) {
18931902
fcport->scan_needed = 1;
1894-
fcport->rscn_gen++;
1903+
fcport->rscn_gen = rscn_gen;
18951904
}
18961905
}
18971906
break;
18981907
case RSCN_DOM_ADDR:
1908+
qla_rscn_gen_tick(vha, &rscn_gen);
18991909
list_for_each_entry(fcport, &vha->vp_fcports, list) {
19001910
if (fcport->flags & FCF_FCP2_DEVICE &&
19011911
atomic_read(&fcport->state) == FCS_ONLINE)
19021912
continue;
19031913

19041914
if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) {
19051915
fcport->scan_needed = 1;
1906-
fcport->rscn_gen++;
1916+
fcport->rscn_gen = rscn_gen;
19071917
}
19081918
}
19091919
break;
19101920
case RSCN_FAB_ADDR:
19111921
default:
1922+
qla_rscn_gen_tick(vha, &rscn_gen);
19121923
list_for_each_entry(fcport, &vha->vp_fcports, list) {
19131924
if (fcport->flags & FCF_FCP2_DEVICE &&
19141925
atomic_read(&fcport->state) == FCS_ONLINE)
19151926
continue;
19161927

19171928
fcport->scan_needed = 1;
1918-
fcport->rscn_gen++;
1929+
fcport->rscn_gen = rscn_gen;
19191930
}
19201931
break;
19211932
}
@@ -1924,6 +1935,7 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
19241935
if (vha->scan.scan_flags == 0) {
19251936
ql_dbg(ql_dbg_disc, vha, 0xffff, "%s: schedule\n", __func__);
19261937
vha->scan.scan_flags |= SF_QUEUED;
1938+
vha->scan.rscn_gen_start = atomic_read(&vha->rscn_gen);
19271939
schedule_delayed_work(&vha->scan.scan_work, 5);
19281940
}
19291941
spin_unlock_irqrestore(&vha->work_lock, flags);
@@ -6393,6 +6405,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
63936405
qlt_do_generation_tick(vha, &discovery_gen);
63946406

63956407
if (USE_ASYNC_SCAN(ha)) {
6408+
/* start of scan begins here */
6409+
vha->scan.rscn_gen_end = atomic_read(&vha->rscn_gen);
63966410
rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI,
63976411
NULL);
63986412
if (rval)

drivers/scsi/qla2xxx/qla_inline.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,3 +631,11 @@ static inline int qla_mapq_alloc_qp_cpu_map(struct qla_hw_data *ha)
631631
}
632632
return 0;
633633
}
634+
635+
static inline bool val_is_in_range(u32 val, u32 start, u32 end)
636+
{
637+
if (val >= start && val <= end)
638+
return true;
639+
else
640+
return false;
641+
}

0 commit comments

Comments
 (0)