Skip to content

Commit

Permalink
scsi: qla2xxx: Dual FCP-NVMe target port support
Browse files Browse the repository at this point in the history
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/20190912180918.6436-9-hmadhani@marvell.com
Signed-off-by: Michael Hernandez <mhernandez@marvell.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Michael Hernandez authored and Martin K. Petersen committed Oct 10, 2019
1 parent a3a8d13 commit 84ed362
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 60 deletions.
26 changes: 24 additions & 2 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -2277,7 +2277,7 @@ typedef struct {
uint8_t fabric_port_name[WWN_SIZE];
uint16_t fp_speed;
uint8_t fc4_type;
uint8_t fc4f_nvme; /* nvme fc4 feature bits */
uint8_t fc4_features;
} sw_info_t;

/* FCP-4 types */
Expand Down Expand Up @@ -2445,7 +2445,7 @@ typedef struct fc_port {
u32 supported_classes;

uint8_t fc4_type;
uint8_t fc4f_nvme;
uint8_t fc4_features;
uint8_t scan_state;

unsigned long last_queue_full;
Expand Down Expand Up @@ -2476,6 +2476,9 @@ typedef struct fc_port {
u16 n2n_chip_reset;
} fc_port_t;

#define FC4_PRIORITY_NVME 0
#define FC4_PRIORITY_FCP 1

#define QLA_FCPORT_SCAN 1
#define QLA_FCPORT_FOUND 2

Expand Down Expand Up @@ -4291,6 +4294,8 @@ struct qla_hw_data {
atomic_t nvme_active_aen_cnt;
uint16_t nvme_last_rptd_aen; /* Last recorded aen count */

uint8_t fc4_type_priority;

atomic_t zio_threshold;
uint16_t last_zio_threshold;

Expand Down Expand Up @@ -4816,6 +4821,23 @@ struct sff_8247_a0 {
ha->current_topology == ISP_CFG_N || \
!ha->current_topology)

#define NVME_TYPE(fcport) \
(fcport->fc4_type & FS_FC4TYPE_NVME) \

#define FCP_TYPE(fcport) \
(fcport->fc4_type & FS_FC4TYPE_FCP) \

#define NVME_ONLY_TARGET(fcport) \
(NVME_TYPE(fcport) && !FCP_TYPE(fcport)) \

#define NVME_FCP_TARGET(fcport) \
(FCP_TYPE(fcport) && NVME_TYPE(fcport)) \

#define NVME_TARGET(ha, fcport) \
((NVME_FCP_TARGET(fcport) && \
(ha->fc4_type_priority == FC4_PRIORITY_NVME)) || \
NVME_ONLY_TARGET(fcport)) \

#include "qla_target.h"
#include "qla_gbl.h"
#include "qla_dbg.h"
Expand Down
2 changes: 2 additions & 0 deletions drivers/scsi/qla2xxx/qla_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -2101,4 +2101,6 @@ struct qla_fcp_prio_cfg {
#define FA_FLASH_LAYOUT_ADDR_83 (0x3F1000/4)
#define FA_FLASH_LAYOUT_ADDR_28 (0x11000/4)

#define NVRAM_DUAL_FCP_NVME_FLAG_OFFSET 0x196

#endif
42 changes: 25 additions & 17 deletions drivers/scsi/qla2xxx/qla_gs.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
WWN_SIZE);

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

if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
Expand Down Expand Up @@ -2887,7 +2887,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct qla_hw_data *ha = vha->hw;
uint8_t fcp_scsi_features = 0;
uint8_t fcp_scsi_features = 0, nvme_features = 0;
struct ct_arg arg;

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

if (fcp_scsi_features)
list[i].fc4_type = FC4_TYPE_FCP_SCSI;
else
list[i].fc4_type = FC4_TYPE_OTHER;
if (fcp_scsi_features) {
list[i].fc4_type = FS_FC4TYPE_FCP;
list[i].fc4_features = fcp_scsi_features;
}

list[i].fc4f_nvme =
nvme_features =
ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
list[i].fc4f_nvme &= 0xf;
nvme_features &= 0xf;

if (nvme_features) {
list[i].fc4_type |= FS_FC4TYPE_NVME;
list[i].fc4_features = nvme_features;
}
}

/* Last device exit. */
Expand Down Expand Up @@ -3435,31 +3440,34 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
fc_port_t *fcport = sp->fcport;
struct ct_sns_rsp *ct_rsp;
struct event_arg ea;
uint8_t fc4_scsi_feat;
uint8_t fc4_nvme_feat;

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

fcport->flags &= ~FCF_ASYNC_SENT;
ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
fc4_scsi_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
fc4_nvme_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];

/*
* FC-GS-7, 5.2.3.12 FC-4 Features - format
* The format of the FC-4 Features object, as defined by the FC-4,
* Shall be an array of 4-bit values, one for each type code value
*/
if (!res) {
if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) {
if (fc4_scsi_feat & 0xf) {
/* w1 b00:03 */
fcport->fc4_type =
ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
fcport->fc4_type &= 0xf;
}
fcport->fc4_type = FS_FC4TYPE_FCP;
fcport->fc4_features = fc4_scsi_feat & 0xf;
}

if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) {
if (fc4_nvme_feat & 0xf) {
/* w5 [00:03]/28h */
fcport->fc4f_nvme =
ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
fcport->fc4f_nvme &= 0xf;
fcport->fc4_type |= FS_FC4TYPE_NVME;
fcport->fc4_features = fc4_nvme_feat & 0xf;
}
}

Expand Down
64 changes: 37 additions & 27 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
else
lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;

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

ql_dbg(ql_dbg_disc, vha, 0x2072,
Expand Down Expand Up @@ -726,19 +726,17 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,

loop_id = le16_to_cpu(e->nport_handle);
loop_id = (loop_id & 0x7fff);
if (fcport->fc4f_nvme)
if (NVME_TARGET(vha->hw, fcport))
current_login_state = e->current_login_state >> 4;
else
current_login_state = e->current_login_state & 0xf;


ql_dbg(ql_dbg_disc, vha, 0x20e2,
"%s found %8phC CLS [%x|%x] nvme %d ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
"%s found %8phC CLS [%x|%x] fc4_type %d ID[%06x|%06x] lid[%d|%d]\n",
__func__, fcport->port_name,
e->current_login_state, fcport->fw_login_state,
fcport->fc4f_nvme, id.b.domain, id.b.area, id.b.al_pa,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
fcport->fc4_type, id.b24, fcport->d_id.b24,
loop_id, fcport->loop_id);

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

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

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

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

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

if (fcport->disc_state == DSC_DELETE_PEND)
return;

if (fcport->fc4f_nvme)
if (NVME_TARGET(vha->hw, fcport))
ls = pd->current_login_state >> 4;
else
ls = pd->current_login_state & 0xf;
Expand Down Expand Up @@ -1578,7 +1576,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post %s PRLI\n",
__func__, __LINE__, fcport->port_name,
fcport->fc4f_nvme ? "NVME" : "FC");
NVME_TARGET(vha->hw, fcport) ? "NVME" :
"FC");
qla24xx_post_prli_work(vha, fcport);
}
break;
Expand Down Expand Up @@ -1860,13 +1859,22 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
break;
}

if (ea->fcport->fc4f_nvme) {
/*
* Retry PRLI with other FC-4 type if failure occurred on dual
* FCP/NVMe port
*/
if (NVME_FCP_TARGET(ea->fcport)) {
if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME)
ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME;
else
ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP;
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post fc4 prli\n",
__func__, __LINE__, ea->fcport->port_name);
ea->fcport->fc4f_nvme = 0;
"%s %d %8phC post %s prli\n",
__func__, __LINE__, ea->fcport->port_name,
(ea->fcport->fc4_type & FS_FC4TYPE_NVME) ?
"NVMe" : "FCP");
qla24xx_post_prli_work(vha, ea->fcport);
return;
break;
}

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

qla2x00_iidma_fcport(vha, fcport);

if (fcport->fc4f_nvme) {
if (NVME_TARGET(vha->hw, fcport)) {
qla_nvme_register_remote(vha, fcport);
fcport->disc_state = DSC_LOGIN_COMPLETE;
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
Expand Down Expand Up @@ -5710,11 +5718,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
new_fcport->fc4_type = swl[swl_idx].fc4_type;

new_fcport->nvme_flag = 0;
new_fcport->fc4f_nvme = 0;
if (vha->flags.nvme_enabled &&
swl[swl_idx].fc4f_nvme) {
new_fcport->fc4f_nvme =
swl[swl_idx].fc4f_nvme;
swl[swl_idx].fc4_type & FS_FC4TYPE_NVME) {
ql_log(ql_log_info, vha, 0x2131,
"FOUND: NVME port %8phC as FC Type 28h\n",
new_fcport->port_name);
Expand Down Expand Up @@ -5770,7 +5775,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)

/* Bypass ports whose FCP-4 type is not FCP_SCSI */
if (ql2xgffidenable &&
(new_fcport->fc4_type != FC4_TYPE_FCP_SCSI &&
(!(new_fcport->fc4_type & FS_FC4TYPE_FCP) &&
new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
continue;

Expand Down Expand Up @@ -5839,7 +5844,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
break;
}

if (fcport->fc4f_nvme) {
if (NVME_TARGET(vha->hw, fcport)) {
if (fcport->disc_state == DSC_DELETE_PEND) {
fcport->disc_state = DSC_GNL;
vha->fcport_count--;
Expand Down Expand Up @@ -8514,6 +8519,11 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
/* N2N: driver will initiate Login instead of FW */
icb->firmware_options_3 |= BIT_8;

/* Determine NVMe/FCP priority for target ports */
ha->fc4_type_priority = qla2xxx_get_fc4_priority(vha);
ql_log(ql_log_info, vha, 0xffff, "FC4 priority set to %s\n",
ha->fc4_type_priority & BIT_0 ? "FCP" : "NVMe");

if (rval) {
ql_log(ql_log_warn, vha, 0x0076,
"NVRAM configuration failed.\n");
Expand Down
12 changes: 12 additions & 0 deletions drivers/scsi/qla2xxx/qla_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,15 @@ qla_83xx_start_iocbs(struct qla_qpair *qpair)

WRT_REG_DWORD(req->req_q_in, req->ring_index);
}

static inline int
qla2xxx_get_fc4_priority(struct scsi_qla_host *vha)
{
uint32_t data;

data =
((uint8_t *)vha->hw->nvram)[NVRAM_DUAL_FCP_NVME_FLAG_OFFSET];


return ((data >> 6) & BIT_0);
}
11 changes: 6 additions & 5 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1931,7 +1931,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
pd24 = (struct port_database_24xx *) pd;

/* Check for logged in state. */
if (fcport->fc4f_nvme) {
if (NVME_TARGET(ha, fcport)) {
current_login_state = pd24->current_login_state >> 4;
last_login_state = pd24->last_login_state >> 4;
} else {
Expand Down Expand Up @@ -3898,8 +3898,9 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->n2n_flag = 1;
fcport->keep_nport_handle = 1;
fcport->fc4_type = FS_FC4TYPE_FCP;
if (vha->flags.nvme_enabled)
fcport->fc4f_nvme = 1;
fcport->fc4_type |= FS_FC4TYPE_NVME;

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

if (fcport->fc4f_nvme) {
if (NVME_TARGET(vha->hw, fcport)) {
current_login_state = pd->current_login_state >> 4;
last_login_state = pd->last_login_state >> 4;
} else {
Expand Down Expand Up @@ -6396,8 +6397,8 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
fcport->d_id.b.al_pa = pd->port_id[2];
fcport->d_id.b.rsvd_1 = 0;

if (fcport->fc4f_nvme) {
fcport->port_type = 0;
if (NVME_TARGET(vha->hw, fcport)) {
fcport->port_type = FCT_NVME;
if ((pd->prli_svc_param_word_3[0] & BIT_5) == 0)
fcport->port_type |= FCT_NVME_INITIATOR;
if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
Expand Down
Loading

0 comments on commit 84ed362

Please sign in to comment.