Skip to content

Commit 84ed362

Browse files
Michael Hernandezmartinkpetersen
authored andcommitted
scsi: qla2xxx: Dual FCP-NVMe target port support
Some storage arrays advertise FCP LUNs and NVMe namespaces behind the same WWN. The driver now offers a user option by way of NVRAM parameter to allow users to choose, on a per port basis, the kind of FC-4 type they would like to prioritize for login. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael Hernandez <[email protected]> Signed-off-by: Himanshu Madhani <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent a3a8d13 commit 84ed362

7 files changed

Lines changed: 114 additions & 60 deletions

File tree

drivers/scsi/qla2xxx/qla_def.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,7 +2277,7 @@ typedef struct {
22772277
uint8_t fabric_port_name[WWN_SIZE];
22782278
uint16_t fp_speed;
22792279
uint8_t fc4_type;
2280-
uint8_t fc4f_nvme; /* nvme fc4 feature bits */
2280+
uint8_t fc4_features;
22812281
} sw_info_t;
22822282

22832283
/* FCP-4 types */
@@ -2445,7 +2445,7 @@ typedef struct fc_port {
24452445
u32 supported_classes;
24462446

24472447
uint8_t fc4_type;
2448-
uint8_t fc4f_nvme;
2448+
uint8_t fc4_features;
24492449
uint8_t scan_state;
24502450

24512451
unsigned long last_queue_full;
@@ -2476,6 +2476,9 @@ typedef struct fc_port {
24762476
u16 n2n_chip_reset;
24772477
} fc_port_t;
24782478

2479+
#define FC4_PRIORITY_NVME 0
2480+
#define FC4_PRIORITY_FCP 1
2481+
24792482
#define QLA_FCPORT_SCAN 1
24802483
#define QLA_FCPORT_FOUND 2
24812484

@@ -4291,6 +4294,8 @@ struct qla_hw_data {
42914294
atomic_t nvme_active_aen_cnt;
42924295
uint16_t nvme_last_rptd_aen; /* Last recorded aen count */
42934296

4297+
uint8_t fc4_type_priority;
4298+
42944299
atomic_t zio_threshold;
42954300
uint16_t last_zio_threshold;
42964301

@@ -4816,6 +4821,23 @@ struct sff_8247_a0 {
48164821
ha->current_topology == ISP_CFG_N || \
48174822
!ha->current_topology)
48184823

4824+
#define NVME_TYPE(fcport) \
4825+
(fcport->fc4_type & FS_FC4TYPE_NVME) \
4826+
4827+
#define FCP_TYPE(fcport) \
4828+
(fcport->fc4_type & FS_FC4TYPE_FCP) \
4829+
4830+
#define NVME_ONLY_TARGET(fcport) \
4831+
(NVME_TYPE(fcport) && !FCP_TYPE(fcport)) \
4832+
4833+
#define NVME_FCP_TARGET(fcport) \
4834+
(FCP_TYPE(fcport) && NVME_TYPE(fcport)) \
4835+
4836+
#define NVME_TARGET(ha, fcport) \
4837+
((NVME_FCP_TARGET(fcport) && \
4838+
(ha->fc4_type_priority == FC4_PRIORITY_NVME)) || \
4839+
NVME_ONLY_TARGET(fcport)) \
4840+
48194841
#include "qla_target.h"
48204842
#include "qla_gbl.h"
48214843
#include "qla_dbg.h"

drivers/scsi/qla2xxx/qla_fw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,4 +2101,6 @@ struct qla_fcp_prio_cfg {
21012101
#define FA_FLASH_LAYOUT_ADDR_83 (0x3F1000/4)
21022102
#define FA_FLASH_LAYOUT_ADDR_28 (0x11000/4)
21032103

2104+
#define NVRAM_DUAL_FCP_NVME_FLAG_OFFSET 0x196
2105+
21042106
#endif

drivers/scsi/qla2xxx/qla_gs.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
248248
WWN_SIZE);
249249

250250
fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
251-
FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER;
251+
FS_FC4TYPE_FCP : FC4_TYPE_OTHER;
252252

253253
if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
254254
ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
@@ -2887,7 +2887,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
28872887
struct ct_sns_req *ct_req;
28882888
struct ct_sns_rsp *ct_rsp;
28892889
struct qla_hw_data *ha = vha->hw;
2890-
uint8_t fcp_scsi_features = 0;
2890+
uint8_t fcp_scsi_features = 0, nvme_features = 0;
28912891
struct ct_arg arg;
28922892

28932893
for (i = 0; i < ha->max_fibre_devices; i++) {
@@ -2933,14 +2933,19 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
29332933
ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
29342934
fcp_scsi_features &= 0x0f;
29352935

2936-
if (fcp_scsi_features)
2937-
list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2938-
else
2939-
list[i].fc4_type = FC4_TYPE_OTHER;
2936+
if (fcp_scsi_features) {
2937+
list[i].fc4_type = FS_FC4TYPE_FCP;
2938+
list[i].fc4_features = fcp_scsi_features;
2939+
}
29402940

2941-
list[i].fc4f_nvme =
2941+
nvme_features =
29422942
ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
2943-
list[i].fc4f_nvme &= 0xf;
2943+
nvme_features &= 0xf;
2944+
2945+
if (nvme_features) {
2946+
list[i].fc4_type |= FS_FC4TYPE_NVME;
2947+
list[i].fc4_features = nvme_features;
2948+
}
29442949
}
29452950

29462951
/* Last device exit. */
@@ -3435,31 +3440,34 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
34353440
fc_port_t *fcport = sp->fcport;
34363441
struct ct_sns_rsp *ct_rsp;
34373442
struct event_arg ea;
3443+
uint8_t fc4_scsi_feat;
3444+
uint8_t fc4_nvme_feat;
34383445

34393446
ql_dbg(ql_dbg_disc, vha, 0x2133,
34403447
"Async done-%s res %x ID %x. %8phC\n",
34413448
sp->name, res, fcport->d_id.b24, fcport->port_name);
34423449

34433450
fcport->flags &= ~FCF_ASYNC_SENT;
34443451
ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
3452+
fc4_scsi_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
3453+
fc4_nvme_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
3454+
34453455
/*
34463456
* FC-GS-7, 5.2.3.12 FC-4 Features - format
34473457
* The format of the FC-4 Features object, as defined by the FC-4,
34483458
* Shall be an array of 4-bit values, one for each type code value
34493459
*/
34503460
if (!res) {
3451-
if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) {
3461+
if (fc4_scsi_feat & 0xf) {
34523462
/* w1 b00:03 */
3453-
fcport->fc4_type =
3454-
ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
3455-
fcport->fc4_type &= 0xf;
3456-
}
3463+
fcport->fc4_type = FS_FC4TYPE_FCP;
3464+
fcport->fc4_features = fc4_scsi_feat & 0xf;
3465+
}
34573466

3458-
if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) {
3467+
if (fc4_nvme_feat & 0xf) {
34593468
/* w5 [00:03]/28h */
3460-
fcport->fc4f_nvme =
3461-
ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
3462-
fcport->fc4f_nvme &= 0xf;
3469+
fcport->fc4_type |= FS_FC4TYPE_NVME;
3470+
fcport->fc4_features = fc4_nvme_feat & 0xf;
34633471
}
34643472
}
34653473

drivers/scsi/qla2xxx/qla_init.c

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
328328
else
329329
lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
330330

331-
if (fcport->fc4f_nvme)
331+
if (NVME_TARGET(vha->hw, fcport))
332332
lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
333333

334334
ql_dbg(ql_dbg_disc, vha, 0x2072,
@@ -726,19 +726,17 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
726726

727727
loop_id = le16_to_cpu(e->nport_handle);
728728
loop_id = (loop_id & 0x7fff);
729-
if (fcport->fc4f_nvme)
729+
if (NVME_TARGET(vha->hw, fcport))
730730
current_login_state = e->current_login_state >> 4;
731731
else
732732
current_login_state = e->current_login_state & 0xf;
733733

734-
735734
ql_dbg(ql_dbg_disc, vha, 0x20e2,
736-
"%s found %8phC CLS [%x|%x] nvme %d ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
735+
"%s found %8phC CLS [%x|%x] fc4_type %d ID[%06x|%06x] lid[%d|%d]\n",
737736
__func__, fcport->port_name,
738737
e->current_login_state, fcport->fw_login_state,
739-
fcport->fc4f_nvme, id.b.domain, id.b.area, id.b.al_pa,
740-
fcport->d_id.b.domain, fcport->d_id.b.area,
741-
fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
738+
fcport->fc4_type, id.b24, fcport->d_id.b24,
739+
loop_id, fcport->loop_id);
742740

743741
switch (fcport->disc_state) {
744742
case DSC_DELETE_PEND:
@@ -1225,13 +1223,13 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
12251223
sp->done = qla2x00_async_prli_sp_done;
12261224
lio->u.logio.flags = 0;
12271225

1228-
if (fcport->fc4f_nvme)
1226+
if (NVME_TARGET(vha->hw, fcport))
12291227
lio->u.logio.flags |= SRB_LOGIN_NVME_PRLI;
12301228

12311229
ql_dbg(ql_dbg_disc, vha, 0x211b,
12321230
"Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d %s.\n",
12331231
fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24,
1234-
fcport->login_retry, fcport->fc4f_nvme ? "nvme" : "fc");
1232+
fcport->login_retry, NVME_TARGET(vha->hw, fcport) ? "nvme" : "fc");
12351233

12361234
rval = qla2x00_start_sp(sp);
12371235
if (rval != QLA_SUCCESS) {
@@ -1382,14 +1380,14 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
13821380
fcport->flags &= ~FCF_ASYNC_SENT;
13831381

13841382
ql_dbg(ql_dbg_disc, vha, 0x20d2,
1385-
"%s %8phC DS %d LS %d nvme %x rc %d\n", __func__, fcport->port_name,
1386-
fcport->disc_state, pd->current_login_state, fcport->fc4f_nvme,
1387-
ea->rc);
1383+
"%s %8phC DS %d LS %d fc4_type %x rc %d\n", __func__,
1384+
fcport->port_name, fcport->disc_state, pd->current_login_state,
1385+
fcport->fc4_type, ea->rc);
13881386

13891387
if (fcport->disc_state == DSC_DELETE_PEND)
13901388
return;
13911389

1392-
if (fcport->fc4f_nvme)
1390+
if (NVME_TARGET(vha->hw, fcport))
13931391
ls = pd->current_login_state >> 4;
13941392
else
13951393
ls = pd->current_login_state & 0xf;
@@ -1578,7 +1576,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
15781576
ql_dbg(ql_dbg_disc, vha, 0x2118,
15791577
"%s %d %8phC post %s PRLI\n",
15801578
__func__, __LINE__, fcport->port_name,
1581-
fcport->fc4f_nvme ? "NVME" : "FC");
1579+
NVME_TARGET(vha->hw, fcport) ? "NVME" :
1580+
"FC");
15821581
qla24xx_post_prli_work(vha, fcport);
15831582
}
15841583
break;
@@ -1860,13 +1859,22 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
18601859
break;
18611860
}
18621861

1863-
if (ea->fcport->fc4f_nvme) {
1862+
/*
1863+
* Retry PRLI with other FC-4 type if failure occurred on dual
1864+
* FCP/NVMe port
1865+
*/
1866+
if (NVME_FCP_TARGET(ea->fcport)) {
1867+
if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME)
1868+
ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME;
1869+
else
1870+
ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP;
18641871
ql_dbg(ql_dbg_disc, vha, 0x2118,
1865-
"%s %d %8phC post fc4 prli\n",
1866-
__func__, __LINE__, ea->fcport->port_name);
1867-
ea->fcport->fc4f_nvme = 0;
1872+
"%s %d %8phC post %s prli\n",
1873+
__func__, __LINE__, ea->fcport->port_name,
1874+
(ea->fcport->fc4_type & FS_FC4TYPE_NVME) ?
1875+
"NVMe" : "FCP");
18681876
qla24xx_post_prli_work(vha, ea->fcport);
1869-
return;
1877+
break;
18701878
}
18711879

18721880
/* at this point both PRLI NVME & PRLI FCP failed */
@@ -1952,7 +1960,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
19521960
* force a relogin attempt via implicit LOGO, PLOGI, and PRLI
19531961
* requests.
19541962
*/
1955-
if (ea->fcport->fc4f_nvme) {
1963+
if (NVME_TARGET(vha->hw, ea->fcport)) {
19561964
ql_dbg(ql_dbg_disc, vha, 0x2117,
19571965
"%s %d %8phC post prli\n",
19581966
__func__, __LINE__, ea->fcport->port_name);
@@ -5382,7 +5390,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
53825390

53835391
qla2x00_iidma_fcport(vha, fcport);
53845392

5385-
if (fcport->fc4f_nvme) {
5393+
if (NVME_TARGET(vha->hw, fcport)) {
53865394
qla_nvme_register_remote(vha, fcport);
53875395
fcport->disc_state = DSC_LOGIN_COMPLETE;
53885396
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
@@ -5710,11 +5718,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
57105718
new_fcport->fc4_type = swl[swl_idx].fc4_type;
57115719

57125720
new_fcport->nvme_flag = 0;
5713-
new_fcport->fc4f_nvme = 0;
57145721
if (vha->flags.nvme_enabled &&
5715-
swl[swl_idx].fc4f_nvme) {
5716-
new_fcport->fc4f_nvme =
5717-
swl[swl_idx].fc4f_nvme;
5722+
swl[swl_idx].fc4_type & FS_FC4TYPE_NVME) {
57185723
ql_log(ql_log_info, vha, 0x2131,
57195724
"FOUND: NVME port %8phC as FC Type 28h\n",
57205725
new_fcport->port_name);
@@ -5770,7 +5775,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
57705775

57715776
/* Bypass ports whose FCP-4 type is not FCP_SCSI */
57725777
if (ql2xgffidenable &&
5773-
(new_fcport->fc4_type != FC4_TYPE_FCP_SCSI &&
5778+
(!(new_fcport->fc4_type & FS_FC4TYPE_FCP) &&
57745779
new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
57755780
continue;
57765781

@@ -5839,7 +5844,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
58395844
break;
58405845
}
58415846

5842-
if (fcport->fc4f_nvme) {
5847+
if (NVME_TARGET(vha->hw, fcport)) {
58435848
if (fcport->disc_state == DSC_DELETE_PEND) {
58445849
fcport->disc_state = DSC_GNL;
58455850
vha->fcport_count--;
@@ -8514,6 +8519,11 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
85148519
/* N2N: driver will initiate Login instead of FW */
85158520
icb->firmware_options_3 |= BIT_8;
85168521

8522+
/* Determine NVMe/FCP priority for target ports */
8523+
ha->fc4_type_priority = qla2xxx_get_fc4_priority(vha);
8524+
ql_log(ql_log_info, vha, 0xffff, "FC4 priority set to %s\n",
8525+
ha->fc4_type_priority & BIT_0 ? "FCP" : "NVMe");
8526+
85178527
if (rval) {
85188528
ql_log(ql_log_warn, vha, 0x0076,
85198529
"NVRAM configuration failed.\n");

drivers/scsi/qla2xxx/qla_inline.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,15 @@ qla_83xx_start_iocbs(struct qla_qpair *qpair)
307307

308308
WRT_REG_DWORD(req->req_q_in, req->ring_index);
309309
}
310+
311+
static inline int
312+
qla2xxx_get_fc4_priority(struct scsi_qla_host *vha)
313+
{
314+
uint32_t data;
315+
316+
data =
317+
((uint8_t *)vha->hw->nvram)[NVRAM_DUAL_FCP_NVME_FLAG_OFFSET];
318+
319+
320+
return ((data >> 6) & BIT_0);
321+
}

drivers/scsi/qla2xxx/qla_mbx.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,7 +1931,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
19311931
pd24 = (struct port_database_24xx *) pd;
19321932

19331933
/* Check for logged in state. */
1934-
if (fcport->fc4f_nvme) {
1934+
if (NVME_TARGET(ha, fcport)) {
19351935
current_login_state = pd24->current_login_state >> 4;
19361936
last_login_state = pd24->last_login_state >> 4;
19371937
} else {
@@ -3898,8 +3898,9 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
38983898
fcport->scan_state = QLA_FCPORT_FOUND;
38993899
fcport->n2n_flag = 1;
39003900
fcport->keep_nport_handle = 1;
3901+
fcport->fc4_type = FS_FC4TYPE_FCP;
39013902
if (vha->flags.nvme_enabled)
3902-
fcport->fc4f_nvme = 1;
3903+
fcport->fc4_type |= FS_FC4TYPE_NVME;
39033904

39043905
switch (fcport->disc_state) {
39053906
case DSC_DELETED:
@@ -6361,7 +6362,7 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
63616362
uint64_t zero = 0;
63626363
u8 current_login_state, last_login_state;
63636364

6364-
if (fcport->fc4f_nvme) {
6365+
if (NVME_TARGET(vha->hw, fcport)) {
63656366
current_login_state = pd->current_login_state >> 4;
63666367
last_login_state = pd->last_login_state >> 4;
63676368
} else {
@@ -6396,8 +6397,8 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
63966397
fcport->d_id.b.al_pa = pd->port_id[2];
63976398
fcport->d_id.b.rsvd_1 = 0;
63986399

6399-
if (fcport->fc4f_nvme) {
6400-
fcport->port_type = 0;
6400+
if (NVME_TARGET(vha->hw, fcport)) {
6401+
fcport->port_type = FCT_NVME;
64016402
if ((pd->prli_svc_param_word_3[0] & BIT_5) == 0)
64026403
fcport->port_type |= FCT_NVME_INITIATOR;
64036404
if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)

0 commit comments

Comments
 (0)