Merge patch series "Introduce functionality for NVMe initiator"

Karan Tilak Kumar <kartilak@cisco.com> says:

Hi Martin, reviewers,

This series adds functionality for NVMe initiator to the fnic driver.

The changes enable the fnic driver to act as an NVMe initiator over
Fibre Channel (FC-NVMe), allowing the host to discover and communicate
with NVMe targets using the existing fnic infrastructure. The patches
prepare the driver for full FC-NVMe initiator operation while
maintaining existing SCSI/FC functionality.

These are some of the salient patches:

o. Make fnic debug logging usable by SCSI and NVMe initiator roles.
o. Use fnic instance numbers for non-SCSI-facing identifiers.
o. Decode firmware roles for FCP, NVMe, and unsupported targets.
o. Advertise NVMe initiator service parameters during FC discovery.
o. Add FDLS role handling for NVMe initiator discovery flows.
o. Add the NVMe/FC transport path and port registration.
o. Route completions, resets, and LS frames by initiator role.
o. Add NVMe LS timeouts, statistics, and debugfs state reporting.

Even though the patches have been made into a series, some patches are
heavier than others. But, every effort has been made to keep the
purpose of each patch as a single-purpose, and to compile cleanly.
All the individual patches compile cleanly. The compiler used is GCC
14.2.

This patch set has been tested as a whole. Therefore, the tested-by
fields have been added only to one patch in the set.
I've refrained from adding tested-by to most of the patches, so as to
not mislead the reviewer/reader.

A brief note on the unit tests:

o. Configure multipathing, and run link flaps on single link. IOs drop
   briefly, but pick up as expected.
o. Configure multipathing, and run link flaps on two links, with a 30
   second delay in between. IOs drop briefly, but pick up as expected.
o. Repeat the above tests with 1 queue and 64 queues.
o. Perform tests with Netapp and Pure targets.

All tests were successful.

This set of patches was reviewed before submitting upstream,
and the following review comments were incorporated.

Incorporate review comments from Hannes Reinecke:

Decode target roles explicitly and report unsupported roles.
Remove the empty line before the FLOGI completion else block.
Add a short comment for the NVMe ERSP completion case.

Incorporate review comments from Lee Duncan:

Replace the NVMe LS OXID switch with a direct frame-type check.
Rename the NVMe frame helper to follow fnic function naming style.
Convert the NVMe opcode stats helper to a switch statement.
Share NVMe completion stats accounting and compute duration once.

Link: https://patch.msgid.link/20260724174811.5118-1-kartilak@cisco.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Martin K. Petersen 2026-07-28 22:24:19 -04:00
commit b98a500956
21 changed files with 3901 additions and 774 deletions

View File

@ -6,6 +6,7 @@ fnic-y := \
fnic_attrs.o \
fnic_isr.o \
fnic_main.o \
fnic_nvme.o \
fnic_res.o \
fnic_fcs.o \
fdls_disc.o \

View File

@ -21,6 +21,18 @@
#define FCPIO_HOST_SEQ_ID_RANGE_START 0x80
#define FCPIO_HOST_SEQ_ID_RANGE_END 0xff
struct fnic_nvme_io_event {
struct list_head links;
struct work_struct io_work;
void *arg1;
};
struct fnic_io_event_s {
struct list_head links;
struct work_struct io_work;
void *arg1;
};
/*
* Command entry type
*/
@ -33,6 +45,9 @@ enum fcpio_type {
FCPIO_ICMND_CMPL,
FCPIO_ITMF,
FCPIO_ITMF_CMPL,
FCPIO_NVME_CMD,
FCPIO_NVME_ERSP_HW_CMPL,
FCPIO_NVME_ERSP_FW_CMPL,
/*
* Target request types
@ -179,10 +194,22 @@ fcpio_header_dec(struct fcpio_header *hdr,
*tag = hdr->tag;
}
#define NVME_CMD_SZ 96
#define CDB_16 16
#define CDB_32 32
#define LUN_ADDRESS 8
struct fcpio_nvme_cmnd {
uint8_t d_id[3];
u_int8_t flags; /* command flags */
u_int32_t sgl_cnt; /* scatter-gather list count */
u_int64_t sgl_addr; /* scatter-gather list addr */
u_int16_t cmd_len;
u_int16_t _resvd1; /* reserved: should be 0 */
u_int32_t data_len; /* length of data expected */
u_int8_t nvme_cmnd[NVME_CMD_SZ]; /* NVME command */
};
/*
* fcpio_icmnd_16: host -> firmware request
*
@ -458,6 +485,7 @@ struct fcpio_host_req {
/*
* Initiator host requests
*/
struct fcpio_nvme_cmnd nvcmnd;
struct fcpio_icmnd_16 icmnd_16;
struct fcpio_icmnd_32 icmnd_32;
struct fcpio_itmf itmf;
@ -482,6 +510,12 @@ struct fcpio_host_req {
} u;
};
struct fcpio_nvme_cmpl {
uint8_t resp_size;
uint8_t resvd[3];
uint8_t resp_bytes[32];
};
/*
* fcpio_icmnd_cmpl: firmware -> host response
*
@ -682,6 +716,7 @@ struct fcpio_fw_req {
* Initiator firmware responses
*/
struct fcpio_icmnd_cmpl icmnd_cmpl;
struct fcpio_nvme_cmpl nvme_cmpl;
struct fcpio_itmf_cmpl itmf_cmpl;
/*

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,9 @@
#include <linux/if_ether.h>
#include <scsi/fc/fc_encaps.h>
#include <scsi/fc/fc_fcoe.h>
#include <linux/nvme.h>
#include <linux/nvme-fc.h>
#include <linux/nvme-fc-driver.h>
#define FDLS_MIN_FRAMES (32)
#define FDLS_MIN_FRAME_ELEM (4)
@ -39,6 +42,9 @@
#define FNIC_FCP_SP_CONF_CMPL 0x00000080
#define FNIC_FCP_SP_RETRY 0x00000100
#define FNIC_NVME_SP_INITIATOR 0x00000020
#define FNIC_NVME_SP_SLER 0x00000100
#define FNIC_FC_CONCUR_SEQS (0xFF)
#define FNIC_FC_RO_INFO (0x1F)
@ -50,6 +56,7 @@
#define FNIC_FCP_RSP_FCTL (0x000099)
#define FNIC_REQ_ABTS_FCTL (0x000009)
#define FNIC_NVME_LS_REQ_FCTL (0x000029)
#define FNIC_FC_PH_VER_HI (0x20)
#define FNIC_FC_PH_VER_LO (0x20)

View File

@ -27,7 +27,7 @@ void fnic_fcoe_reset_vlans(struct fnic *fnic)
}
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Reset vlan complete\n");
}
@ -46,7 +46,7 @@ void fnic_fcoe_send_vlan_req(struct fnic *fnic)
frame = fdls_alloc_frame(iport);
if (frame == NULL) {
FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_ERR, fnic,
"Failed to allocate frame to send VLAN req");
return;
}
@ -54,10 +54,10 @@ void fnic_fcoe_send_vlan_req(struct fnic *fnic)
fnic_fcoe_reset_vlans(fnic);
fnic->set_vlan(fnic, 0);
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"set vlan done\n");
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"got MAC 0x%x:%x:%x:%x:%x:%x\n", iport->hwmac[0],
iport->hwmac[1], iport->hwmac[2], iport->hwmac[3],
iport->hwmac[4], iport->hwmac[5]);
@ -81,13 +81,13 @@ void fnic_fcoe_send_vlan_req(struct fnic *fnic)
iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Send VLAN req\n");
fnic_send_fip_frame(iport, frame, frame_size);
vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV);
mod_timer(&fnic->retry_fip_timer, round_jiffies(vlan_tov));
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fip timer set\n");
}
@ -111,11 +111,11 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct fip_header *fiph)
struct fip_vlan_desc *vlan_desc;
unsigned long flags;
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p got vlan resp\n", fnic);
desc_len = be16_to_cpu(vlan_notif->fip.fip_dl_len);
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"desc_len %d\n", desc_len);
spin_lock_irqsave(&fnic->vlans_lock, flags);
@ -128,23 +128,20 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct fip_header *fiph)
if (vlan_desc->fd_desc.fip_dtype == FIP_DT_VLAN) {
if (vlan_desc->fd_desc.fip_dlen != 1) {
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Invalid descriptor length(%x) in VLan response\n",
vlan_desc->fd_desc.fip_dlen);
}
num_vlan++;
vid = be16_to_cpu(vlan_desc->fd_vlan);
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"process_vlan_resp: FIP VLAN %d\n", vid);
vlan = kzalloc_obj(*vlan);
if (!vlan) {
/* retry from timer */
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Mem Alloc failure\n");
spin_unlock_irqrestore(&fnic->vlans_lock,
flags);
@ -155,14 +152,14 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct fip_header *fiph)
list_add_tail(&vlan->list, &fnic->vlan_list);
break;
}
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
"Invalid descriptor type(%x) in VLan response\n",
vlan_desc->fd_desc.fip_dtype);
/*
* Note : received a type=2 descriptor here i.e. FIP
* MAC Address Descriptor
* Note : skip any type=2 descriptor here
* (i.e. FIP MAC Address Descriptor)
*/
if (vlan_desc->fd_desc.fip_dtype != FIP_DT_MAC)
FNIC_FIP_DBG(KERN_INFO, fnic,
"Invalid descriptor type(0x%x) in vlan response\n",
vlan_desc->fd_desc.fip_dtype);
cur_desc += vlan_desc->fd_desc.fip_dlen;
desc_len -= vlan_desc->fd_desc.fip_dlen;
}
@ -170,7 +167,7 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct fip_header *fiph)
/* any VLAN descriptors present ? */
if (num_vlan == 0) {
atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p No VLAN descriptors in FIP VLAN response\n",
fnic);
}
@ -195,7 +192,7 @@ void fnic_fcoe_start_fcf_discovery(struct fnic *fnic)
frame = fdls_alloc_frame(iport);
if (frame == NULL) {
FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_ERR, fnic,
"Failed to allocate frame to start FCF discovery");
return;
}
@ -222,7 +219,7 @@ void fnic_fcoe_start_fcf_discovery(struct fnic *fnic)
FNIC_STD_SET_NODE_NAME(&pdisc_sol->name_desc.fd_wwn, iport->wwnn);
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Start FCF discovery\n");
fnic_send_fip_frame(iport, frame, frame_size);
@ -257,16 +254,14 @@ void fnic_fcoe_fip_discovery_resp(struct fnic *fnic, struct fip_header *fiph)
switch (iport->fip.state) {
case FDLS_FIP_FCF_DISCOVERY_STARTED:
if (be16_to_cpu(disc_adv->fip.fip_flags) & FIP_FL_SOL) {
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p Solicited adv\n", fnic);
if ((disc_adv->prio_desc.fd_pri <
iport->selected_fcf.fcf_priority)
&& (be16_to_cpu(disc_adv->fip.fip_flags) & FIP_FL_AVAIL)) {
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p FCF Available\n", fnic);
memcpy(iport->selected_fcf.fcf_mac,
disc_adv->mac_desc.fd_mac, ETH_ALEN);
@ -274,8 +269,8 @@ void fnic_fcoe_fip_discovery_resp(struct fnic *fnic, struct fip_header *fiph)
disc_adv->prio_desc.fd_pri;
iport->selected_fcf.fka_adv_period =
be32_to_cpu(disc_adv->fka_adv_desc.fd_fka_period);
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num, "adv time %d",
FNIC_FIP_DBG(KERN_INFO, fnic,
"adv time %d",
iport->selected_fcf.fka_adv_period);
iport->selected_fcf.ka_disabled =
(disc_adv->fka_adv_desc.fd_flags & 1);
@ -294,8 +289,7 @@ void fnic_fcoe_fip_discovery_resp(struct fnic *fnic, struct fip_header *fiph)
iport->selected_fcf.fka_adv_period =
be32_to_cpu(disc_adv->fka_adv_desc.fd_fka_period);
FNIC_FIP_DBG(KERN_INFO,
fnic->host,
fnic->fnic_num,
fnic,
"change fka to %d",
iport->selected_fcf.fka_adv_period);
}
@ -362,7 +356,7 @@ void fnic_fcoe_start_flogi(struct fnic *fnic)
frame = fdls_alloc_frame(iport);
if (frame == NULL) {
FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_ERR, fnic,
"Failed to allocate frame to start FIP FLOGI");
return;
}
@ -415,7 +409,7 @@ void fnic_fcoe_start_flogi(struct fnic *fnic)
oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_FLOGI,
&iport->active_oxid_fabric_req);
if (oxid == FNIC_UNASSIGNED_OXID) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Failed to allocate OXID to send FIP FLOGI");
mempool_free(frame, fnic->frame_pool);
return;
@ -427,7 +421,7 @@ void fnic_fcoe_start_flogi(struct fnic *fnic)
FNIC_STD_SET_NODE_NAME(&pflogi_req->flogi_desc.flogi.els.fl_wwnn,
iport->wwnn);
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"FIP start FLOGI\n");
fnic_send_fip_frame(iport, frame, frame_size);
iport->fip.flogi_retry++;
@ -457,11 +451,11 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
struct fc_frame_header *fchdr = &flogi_rsp->rsp_desc.flogi.fchdr;
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p FIP FLOGI rsp\n", fnic);
desc_len = be16_to_cpu(flogi_rsp->fip.fip_dl_len);
if (desc_len != 38) {
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Invalid Descriptor List len (%x). Dropping frame\n",
desc_len);
return;
@ -471,7 +465,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
&& (flogi_rsp->rsp_desc.fd_desc.fip_dlen == 36))
|| !((flogi_rsp->mac_desc.fd_desc.fip_dtype == 2)
&& (flogi_rsp->mac_desc.fd_desc.fip_dlen == 2))) {
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Dropping frame invalid type and len mix\n");
return;
}
@ -484,7 +478,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
|| (s_id != FC_FID_FLOGI)
|| (frame_type != FNIC_FABRIC_FLOGI_RSP)
|| (fchdr->fh_type != 0x01)) {
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Dropping invalid frame: s_id %x F %x R %x t %x OX_ID %x\n",
s_id, fchdr->fh_f_ctl[0], fchdr->fh_r_ctl,
fchdr->fh_type, FNIC_STD_GET_OX_ID(fchdr));
@ -492,7 +486,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
}
if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p rsp for pending FLOGI\n", fnic);
oxid = FNIC_STD_GET_OX_ID(fchdr);
@ -502,8 +496,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
if ((be16_to_cpu(flogi_rsp->fip.fip_dl_len) == FIP_FLOGI_LEN)
&& (flogi_rsp->rsp_desc.flogi.els.fl_cmd == ELS_LS_ACC)) {
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p FLOGI success\n", fnic);
memcpy(iport->fpma, flogi_rsp->mac_desc.fd_mac, ETH_ALEN);
iport->fcid =
@ -519,8 +512,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
if (fnic_fdls_register_portid(iport, iport->fcid, NULL)
!= 0) {
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p flogi registration failed\n",
fnic);
return;
@ -528,8 +520,8 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
iport->fip.state = FDLS_FIP_FLOGI_COMPLETE;
iport->state = FNIC_IPORT_STATE_FABRIC_DISC;
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num, "iport->state:%d\n",
FNIC_FIP_DBG(KERN_INFO, fnic,
"iport->state:%d\n",
iport->state);
fnic_fdls_disc_start(iport);
if (!((iport->selected_fcf.ka_disabled)
@ -575,7 +567,7 @@ void fnic_common_fip_cleanup(struct fnic *fnic)
if (!iport->usefip)
return;
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p fip cleanup\n", fnic);
iport->fip.state = FDLS_FIP_INIT;
@ -617,7 +609,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header *fiph)
int found = false;
int max_count = 0;
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p clear virtual link handler\n", fnic);
if (!((cvl_msg->fcf_mac_desc.fd_desc.fip_dtype == 2)
@ -625,7 +617,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header *fiph)
|| !((cvl_msg->name_desc.fd_desc.fip_dtype == 4)
&& (cvl_msg->name_desc.fd_desc.fip_dlen == 3))) {
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"invalid mix: ft %x fl %x ndt %x ndl %x",
cvl_msg->fcf_mac_desc.fd_desc.fip_dtype,
cvl_msg->fcf_mac_desc.fd_desc.fip_dlen,
@ -640,8 +632,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header *fiph)
if (!((cvl_msg->vn_ports_desc[i].fd_desc.fip_dtype == 11)
&& (cvl_msg->vn_ports_desc[i].fd_desc.fip_dlen == 5))) {
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Invalid type and len mix type: %d len: %d\n",
cvl_msg->vn_ports_desc[i].fd_desc.fip_dtype,
cvl_msg->vn_ports_desc[i].fd_desc.fip_dlen);
@ -664,12 +655,12 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header *fiph)
spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
max_count++;
if (max_count >= FIP_FNIC_RESET_WAIT_COUNT) {
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"Rthr waited too long. Skipping handle link event %p\n",
fnic);
return;
}
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic reset in progress. Link event needs to wait %p",
fnic);
}
@ -714,7 +705,7 @@ int fdls_fip_recv_frame(struct fnic *fnic, void *frame)
return true;
}
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Not a FIP Frame");
return false;
}
@ -724,7 +715,7 @@ void fnic_work_on_fip_timer(struct work_struct *work)
struct fnic *fnic = container_of(work, struct fnic, fip_timer_work);
struct fnic_iport_s *iport = &fnic->iport;
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"FIP timeout\n");
if (iport->fip.state == FDLS_FIP_VLAN_DISCOVERY_STARTED) {
@ -732,7 +723,7 @@ void fnic_work_on_fip_timer(struct work_struct *work)
} else if (iport->fip.state == FDLS_FIP_FCF_DISCOVERY_STARTED) {
u8 zmac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"FCF Discovery timeout\n");
if (memcmp(iport->selected_fcf.fcf_mac, zmac, ETH_ALEN) != 0) {
@ -754,13 +745,13 @@ void fnic_work_on_fip_timer(struct work_struct *work)
round_jiffies(fcf_tov));
}
} else {
FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num, "FCF Discovery timeout\n");
FNIC_FIP_DBG(KERN_INFO, fnic,
"FCF Discovery timeout\n");
fnic_vlan_discovery_timeout(fnic);
}
} else if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"FLOGI timeout\n");
if (iport->fip.flogi_retry < fnic->config.flogi_retries)
fnic_fcoe_start_flogi(fnic);
@ -807,7 +798,7 @@ void fnic_handle_enode_ka_timer(struct timer_list *t)
frame = fdls_alloc_frame(iport);
if (frame == NULL) {
FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_ERR, fnic,
"Failed to allocate frame to send enode ka");
return;
}
@ -828,7 +819,7 @@ void fnic_handle_enode_ka_timer(struct timer_list *t)
memcpy(penode_ka->eth.h_dest, iport->selected_fcf.fcf_mac, ETH_ALEN);
memcpy(penode_ka->mac_desc.fd_mac, iport->hwmac, ETH_ALEN);
FNIC_FIP_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_DEBUG, fnic,
"Handle enode KA timer\n");
fnic_send_fip_frame(iport, frame, frame_size);
enode_ka_tov = jiffies
@ -861,7 +852,7 @@ void fnic_handle_vn_ka_timer(struct timer_list *t)
frame = fdls_alloc_frame(iport);
if (frame == NULL) {
FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_ERR, fnic,
"Failed to allocate frame to send vn ka");
return;
}
@ -887,7 +878,7 @@ void fnic_handle_vn_ka_timer(struct timer_list *t)
memcpy(pvn_port_ka->vn_port_desc.fd_fc_id, fcid, 3);
FNIC_STD_SET_NPORT_NAME(&pvn_port_ka->vn_port_desc.fd_wwpn, iport->wwpn);
FNIC_FIP_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_DEBUG, fnic,
"Handle vnport KA timer\n");
fnic_send_fip_frame(iport, frame, frame_size);
vn_ka_tov = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
@ -977,7 +968,7 @@ void fnic_work_on_fcs_ka_timer(struct work_struct *work)
*fnic = container_of(work, struct fnic, fip_timer_work);
struct fnic_iport_s *iport = &fnic->iport;
FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FIP_DBG(KERN_INFO, fnic,
"fnic 0x%p fcs ka timeout\n", fnic);
fnic_common_fip_cleanup(fnic);

View File

@ -142,7 +142,7 @@ fnic_debug_dump_fip_frame(struct fnic *fnic, struct ethhdr *eth,
u16 op = be16_to_cpu(fiph->fip_op);
u8 sub = fiph->fip_subcode;
FNIC_FCS_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_DEBUG, fnic,
"FIP %s packet contents: op: 0x%x sub: 0x%x (len = %d)",
pfx, op, sub, len);

View File

@ -27,10 +27,11 @@
#include "vnic_stats.h"
#include "vnic_scsi.h"
#include "fnic_fdls.h"
#include "fnic_nvme.h"
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
#define DRV_VERSION "1.8.0.3"
#define DRV_VERSION "1.9.0.0"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
@ -43,6 +44,7 @@
#define FNIC_DFLT_QUEUE_DEPTH 256
#define FNIC_STATS_RATE_LIMIT 4 /* limit rate at which stats are pulled up */
#define LUN0_DELAY_TIME 9
#define FNIC_ROLE_CONFIG_MASK (0xFF0)
/*
* Tag bits used for special requests.
@ -79,6 +81,8 @@
#define FNIC_DEV_RST_ABTS_DONE BIT(19)
#define FNIC_DEV_RST_TERM_DONE BIT(20)
#define FNIC_DEV_RST_ABTS_PENDING BIT(21)
#define FNIC_NVME_ADMIN_IO_TIMER_PENDING BIT(22)
#define FNIC_NVME_ADMIN_IO BIT(23)
#define FNIC_FW_RESET_TIMEOUT 60000 /* mSec */
#define FNIC_FCOE_MAX_CMD_LEN 16
@ -144,6 +148,9 @@
#define PCI_SUBDEVICE_ID_CISCO_HELSINKI 0x02e4 /* VIC 15235 */
#define PCI_SUBDEVICE_ID_CISCO_GOTHENBURG 0x02f2 /* VIC 15425 */
#define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)
#define IS_FNIC_NVME_INITIATOR(fnic) (fnic->role == FNIC_ROLE_NVME_INITIATOR)
struct fnic_pcie_device {
u32 device;
u8 *desc;
@ -234,12 +241,15 @@ extern spinlock_t reset_fnic_list_lock;
extern struct list_head reset_fnic_list;
extern struct workqueue_struct *reset_fnic_work_queue;
extern struct work_struct reset_fnic_work;
extern struct workqueue_struct *fnic_cmpl_queue;
#define FNIC_MAIN_LOGGING 0x01
#define FNIC_FCS_LOGGING 0x02
#define FNIC_SCSI_LOGGING 0x04
#define FNIC_ISR_LOGGING 0x08
#define FNIC_FDLS_LOGGING 0x10
#define FNIC_NVME_LOGGING 0x20
#define FNIC_FIP_LOGGING 0x40
#define FNIC_CHECK_LOGGING(LEVEL, CMD) \
do { \
@ -249,38 +259,39 @@ do { \
} while (0); \
} while (0)
#define FNIC_MAIN_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_MAIN_LOGGING, \
shost_printk(kern_level, host, \
"fnic<%d>: %s: %d: " fmt, fnic_num,\
__func__, __LINE__, ##args);)
#define fnic_printk(kern_level, fnic, fmt, ...) \
(IS_FNIC_FCP_INITIATOR(fnic) ? \
shost_printk(kern_level, fnic->host, "fnic<%d>: %s: %d: " fmt, \
fnic->fnic_num, __func__, __LINE__, ##__VA_ARGS__) : \
printk(kern_level "fnic<%d>: %s: %d: " fmt, fnic->fnic_num, \
__func__, __LINE__, ##__VA_ARGS__))
#define FNIC_FCS_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_FCS_LOGGING, \
shost_printk(kern_level, host, \
"fnic<%d>: %s: %d: " fmt, fnic_num,\
__func__, __LINE__, ##args);)
#define FNIC_MAIN_DBG(kern_level, fnic, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_MAIN_LOGGING, \
fnic_printk(kern_level, fnic, fmt, ##args);)
#define FNIC_FIP_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_FCS_LOGGING, \
shost_printk(kern_level, host, \
"fnic<%d>: %s: %d: " fmt, fnic_num,\
__func__, __LINE__, ##args);)
#define FNIC_FCS_DBG(kern_level, fnic, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_FCS_LOGGING, \
fnic_printk(kern_level, fnic, fmt, ##args);)
#define FNIC_SCSI_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
shost_printk(kern_level, host, \
"fnic<%d>: %s: %d: " fmt, fnic_num,\
__func__, __LINE__, ##args);)
#define FNIC_FIP_DBG(kern_level, fnic, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_FIP_LOGGING, \
fnic_printk(kern_level, fnic, fmt, ##args);)
#define FNIC_ISR_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_ISR_LOGGING, \
shost_printk(kern_level, host, \
"fnic<%d>: %s: %d: " fmt, fnic_num,\
__func__, __LINE__, ##args);)
#define FNIC_SCSI_DBG(kern_level, fnic, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
fnic_printk(kern_level, fnic, fmt, ##args);)
#define FNIC_MAIN_NOTE(kern_level, host, fmt, args...) \
shost_printk(kern_level, host, fmt, ##args)
#define FNIC_ISR_DBG(kern_level, fnic, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_ISR_LOGGING, \
fnic_printk(kern_level, fnic, fmt, ##args);)
#define FNIC_NVME_DBG(kern_level, fnic, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_NVME_LOGGING, \
fnic_printk(kern_level, fnic, fmt, ##args);)
#define FNIC_MAIN_NOTE(kern_level, fnic, fmt, args...) \
fnic_printk(kern_level, fnic, fmt, ##args)
#define FNIC_WQ_COPY_MAX 64
#define FNIC_WQ_MAX 1
@ -325,6 +336,7 @@ enum fnic_state {
enum fnic_role_e {
FNIC_ROLE_FCP_INITIATOR = 0,
FNIC_ROLE_NVME_INITIATOR,
};
enum fnic_evt {
@ -343,6 +355,11 @@ struct fnic_frame_list {
int rx_ethhdr_stripped;
};
struct fnic_tag_t {
struct list_head free_list;
int tag_id;
};
struct fnic_event {
struct list_head list;
struct fnic *fnic;
@ -460,6 +477,15 @@ struct fnic {
struct list_head vlan_list;
/*** FIP related data members -- end ***/
/* NVME data members */
struct dentry *fnic_nvmef_debugfs_host;
struct dentry *fnic_nvmef_debugfs_file;
struct sbitmap nvfnic_tag_map;
struct work_struct nvme_io_cmpl_work;
atomic_t nvme_io_event_queued;
struct llist_head nvme_io_event_llist;
struct completion *nvme_lport_unreg_done;
/* copy work queue cache line section */
____cacheline_aligned struct vnic_wq_copy hw_copy_wq[FNIC_WQ_COPY_MAX];
____cacheline_aligned struct fnic_cpy_wq sw_copy_wq[FNIC_WQ_COPY_MAX];
@ -513,6 +539,7 @@ int fnic_host_reset(struct Scsi_Host *shost);
void fnic_reset(struct Scsi_Host *shost);
int fnic_issue_fc_host_lip(struct Scsi_Host *shost);
void fnic_get_host_port_state(struct Scsi_Host *shost);
void fnic_fcpio_reset(struct fnic *fnic);
int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do, unsigned int cq_index);
int fnic_wq_cmpl_handler(struct fnic *fnic, int);
int fnic_flogi_reg_handler(struct fnic *fnic, u32);
@ -526,6 +553,9 @@ void fnic_log_q_error(struct fnic *fnic);
void fnic_handle_link_event(struct fnic *fnic);
int fnic_stats_debugfs_init(struct fnic *fnic);
void fnic_stats_debugfs_remove(struct fnic *fnic);
void fnic_nvmef_debugfs_init(struct fnic *fnic);
void fnic_nvmef_debugfs_remove(struct fnic *fnic);
int nvfnic_get_nvmef_info(struct fnic *fnic, struct fnic_nvmef_info *info);
int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);
void fnic_handle_fip_frame(struct work_struct *work);
@ -559,6 +589,8 @@ void fnic_scsi_unload(struct fnic *fnic);
void fnic_scsi_unload_cleanup(struct fnic *fnic);
int fnic_get_debug_info(struct stats_debug_info *info,
struct fnic *fnic);
int free_wq_copy_descs(struct fnic *fnic, struct vnic_wq_copy *wq,
unsigned int hwq);
struct fnic_scsi_iter_data {
struct fnic *fnic;
@ -598,7 +630,7 @@ fnic_debug_dump(struct fnic *fnic, uint8_t *u8arr, int len)
int i;
for (i = 0; i < len; i = i+8) {
FNIC_FCS_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"%d: %02x %02x %02x %02x %02x %02x %02x %02x", i / 8,
u8arr[i + 0], u8arr[i + 1], u8arr[i + 2], u8arr[i + 3],
u8arr[i + 4], u8arr[i + 5], u8arr[i + 6], u8arr[i + 7]);
@ -613,7 +645,7 @@ fnic_debug_dump_fc_frame(struct fnic *fnic, struct fc_frame_header *fchdr,
s_id = ntoh24(fchdr->fh_s_id);
d_id = ntoh24(fchdr->fh_d_id);
FNIC_FCS_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"%s packet contents: sid/did/type/oxid = 0x%x/0x%x/0x%x/0x%x (len = %d)\n",
pfx, s_id, d_id, fchdr->fh_type,
FNIC_STD_GET_OX_ID(fchdr), len);

View File

@ -10,10 +10,19 @@
extern int fnic_get_debug_info(struct stats_debug_info *debug_buffer,
struct fnic *fnic);
static int fnic_nvmef_debugfs_open(struct inode *inode,
struct file *file);
static ssize_t fnic_nvmef_debugfs_read(struct file *file,
char __user *ubuf,
size_t nbytes, loff_t *pos);
static int fnic_nvmef_debugfs_release(struct inode *inode,
struct file *file);
static struct dentry *fnic_trace_debugfs_root;
static struct dentry *fnic_trace_debugfs_file;
static struct dentry *fnic_trace_enable;
static struct dentry *fnic_stats_debugfs_root;
static struct dentry *fnic_nvmef_debugfs_root;
static struct dentry *fnic_fc_trace_debugfs_file;
static struct dentry *fnic_fc_rdata_trace_debugfs_file;
@ -46,6 +55,9 @@ int fnic_debugfs_init(void)
fnic_stats_debugfs_root = debugfs_create_dir("statistics",
fnic_trace_debugfs_root);
fnic_nvmef_debugfs_root = debugfs_create_dir("nvme_info",
fnic_trace_debugfs_root);
/* Allocate memory to structure */
fc_trc_flag = vmalloc(sizeof(struct fc_trace_flag_type));
@ -70,6 +82,9 @@ int fnic_debugfs_init(void)
*/
void fnic_debugfs_terminate(void)
{
debugfs_remove(fnic_nvmef_debugfs_root);
fnic_nvmef_debugfs_root = NULL;
debugfs_remove(fnic_stats_debugfs_root);
fnic_stats_debugfs_root = NULL;
@ -669,6 +684,13 @@ static const struct file_operations fnic_reset_debugfs_fops = {
.release = fnic_reset_stats_release,
};
static const struct file_operations fnic_nvmef_debugfs_fops = {
.owner = THIS_MODULE,
.open = fnic_nvmef_debugfs_open,
.read = fnic_nvmef_debugfs_read,
.release = fnic_nvmef_debugfs_release,
};
/*
* fnic_stats_init - Initialize stats struct and create stats file per fnic
*
@ -681,7 +703,10 @@ int fnic_stats_debugfs_init(struct fnic *fnic)
{
char name[16];
snprintf(name, sizeof(name), "host%d", fnic->host->host_no);
if (IS_FNIC_FCP_INITIATOR(fnic))
snprintf(name, sizeof(name), "host%d", fnic->host->host_no);
else if (IS_FNIC_NVME_INITIATOR(fnic))
snprintf(name, sizeof(name), "nvfnic%d", fnic->fnic_num);
fnic->fnic_stats_debugfs_host = debugfs_create_dir(name,
fnic_stats_debugfs_root);
@ -719,3 +744,75 @@ void fnic_stats_debugfs_remove(struct fnic *fnic)
debugfs_remove(fnic->fnic_stats_debugfs_host);
fnic->fnic_stats_debugfs_host = NULL;
}
void fnic_nvmef_debugfs_init(struct fnic *fnic)
{
char name[16];
snprintf(name, sizeof(name), "host%d", fnic->fnic_num);
fnic->fnic_nvmef_debugfs_host = debugfs_create_dir(name,
fnic_nvmef_debugfs_root);
fnic->fnic_nvmef_debugfs_file = debugfs_create_file("nvmef_info",
S_IFREG | 0444,
fnic->fnic_nvmef_debugfs_host,
fnic,
&fnic_nvmef_debugfs_fops);
}
static int fnic_nvmef_debugfs_open(struct inode *inode, struct file *file)
{
struct fnic *fnic = inode->i_private;
struct fnic_nvmef_info *info;
int buf_size = 2 * PAGE_SIZE;
info = kzalloc_obj(struct fnic_nvmef_info, GFP_KERNEL);
if (!info)
return -ENOMEM;
info->info_buffer = vmalloc(buf_size);
if (!info->info_buffer) {
kfree(info);
return -ENOMEM;
}
info->buf_size = buf_size;
memset((void *)info->info_buffer, 0, buf_size);
info->buffer_len = nvfnic_get_nvmef_info(fnic, info);
file->private_data = info;
return 0;
}
static ssize_t fnic_nvmef_debugfs_read(struct file *file,
char __user *ubuf,
size_t nbytes, loff_t *pos)
{
struct fnic_nvmef_info *info = file->private_data;
return simple_read_from_buffer(ubuf, nbytes, pos,
info->info_buffer, info->buffer_len);
}
static int fnic_nvmef_debugfs_release(struct inode *inode, struct file *file)
{
struct fnic_nvmef_info *info = file->private_data;
vfree(info->info_buffer);
kfree(info);
return 0;
}
void fnic_nvmef_debugfs_remove(struct fnic *fnic)
{
if (!fnic)
return;
debugfs_remove(fnic->fnic_nvmef_debugfs_file);
fnic->fnic_nvmef_debugfs_file = NULL;
debugfs_remove(fnic->fnic_nvmef_debugfs_host);
fnic->fnic_nvmef_debugfs_host = NULL;
}

View File

@ -31,6 +31,11 @@ struct workqueue_struct *fnic_event_queue;
static uint8_t FCOE_ALL_FCF_MAC[6] = FC_FCOE_FLOGI_MAC;
static inline bool fnic_is_nvme_frame(struct fc_frame_header *fchdr)
{
return (fchdr->fh_type == FC_TYPE_NVME);
}
/*
* Internal Functions
* This function will initialize the src_mac address to be
@ -39,7 +44,7 @@ static uint8_t FCOE_ALL_FCF_MAC[6] = FC_FCOE_FLOGI_MAC;
static inline void fnic_fdls_set_fcoe_srcmac(struct fnic *fnic,
uint8_t *src_mac)
{
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Setting src mac: %02x:%02x:%02x:%02x:%02x:%02x",
src_mac[0], src_mac[1], src_mac[2], src_mac[3],
src_mac[4], src_mac[5]);
@ -54,7 +59,7 @@ static inline void fnic_fdls_set_fcoe_srcmac(struct fnic *fnic,
static inline void fnic_fdls_set_fcoe_dstmac(struct fnic *fnic,
uint8_t *dst_mac)
{
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Setting dst mac: %02x:%02x:%02x:%02x:%02x:%02x",
dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3],
dst_mac[4], dst_mac[5]);
@ -82,7 +87,7 @@ void fnic_fdls_link_status_change(struct fnic *fnic, int linkup)
{
struct fnic_iport_s *iport = &fnic->iport;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"link up: %d, usefip: %d", linkup, iport->usefip);
spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
@ -90,12 +95,12 @@ void fnic_fdls_link_status_change(struct fnic *fnic, int linkup)
if (linkup) {
if (iport->usefip) {
iport->state = FNIC_IPORT_STATE_FIP;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"link up: %d, usefip: %d", linkup, iport->usefip);
fnic_fcoe_send_vlan_req(fnic);
} else {
iport->state = FNIC_IPORT_STATE_FABRIC_DISC;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"iport->state: %d", iport->state);
fnic_fdls_disc_start(iport);
}
@ -125,13 +130,13 @@ void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
memcpy(&fcmac[3], fcid, 3);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"learn fcoe: dst_mac: %02x:%02x:%02x:%02x:%02x:%02x",
ethhdr->h_dest[0], ethhdr->h_dest[1],
ethhdr->h_dest[2], ethhdr->h_dest[3],
ethhdr->h_dest[4], ethhdr->h_dest[5]);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"learn fcoe: fc_mac: %02x:%02x:%02x:%02x:%02x:%02x",
fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
fcmac[5]);
@ -149,13 +154,12 @@ void fnic_fdls_init(struct fnic *fnic, int usefip)
iport->fnic = fnic;
iport->usefip = usefip;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"iportsrcmac: %02x:%02x:%02x:%02x:%02x:%02x",
iport->hwmac[0], iport->hwmac[1], iport->hwmac[2],
iport->hwmac[3], iport->hwmac[4], iport->hwmac[5]);
INIT_LIST_HEAD(&iport->tport_list);
INIT_LIST_HEAD(&iport->tport_list_pending_del);
fnic_fdls_disc_init(iport);
}
@ -168,14 +172,14 @@ void fnic_handle_link(struct work_struct *work)
int max_count = 0;
if (vnic_dev_get_intr_mode(fnic->vdev) != VNIC_DEV_INTR_MODE_MSI)
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Interrupt mode is not MSI\n");
spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
if (fnic->stop_rx_link_events) {
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Stop link rx events\n");
return;
}
@ -184,10 +188,10 @@ void fnic_handle_link(struct work_struct *work)
if ((fnic->state != FNIC_IN_ETH_MODE)
&& (fnic->state != FNIC_IN_FC_MODE)) {
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fnic in transitional state: %d. link up: %d ignored",
fnic->state, vnic_dev_link_status(fnic->vdev));
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Current link status: %d iport state: %d\n",
fnic->link_status, fnic->iport.state);
return;
@ -199,36 +203,36 @@ void fnic_handle_link(struct work_struct *work)
fnic->link_down_cnt = vnic_dev_link_down_cnt(fnic->vdev);
while (fnic->reset_in_progress == IN_PROGRESS) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fnic reset in progress. Link event needs to wait\n");
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"waiting for reset completion\n");
wait_for_completion_timeout(&fnic->reset_completion_wait,
msecs_to_jiffies(5000));
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"woken up from reset completion wait\n");
spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
max_count++;
if (max_count >= MAX_RESET_WAIT_COUNT) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Rstth waited for too long. Skipping handle link event\n");
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
return;
}
}
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Marking fnic reset in progress\n");
fnic->reset_in_progress = IN_PROGRESS;
if ((vnic_dev_get_intr_mode(fnic->vdev) != VNIC_DEV_INTR_MODE_MSI) ||
(fnic->link_status != old_link_status)) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"old link status: %d link status: %d\n",
old_link_status, (int) fnic->link_status);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"old down count %d down count: %d\n",
old_link_down_cnt, (int) fnic->link_down_cnt);
}
@ -237,36 +241,36 @@ void fnic_handle_link(struct work_struct *work)
if (!fnic->link_status) {
/* DOWN -> DOWN */
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"down->down\n");
} else {
if (old_link_down_cnt != fnic->link_down_cnt) {
/* UP -> DOWN -> UP */
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"up->down. Link down\n");
fnic_fdls_link_status_change(fnic, 0);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"down->up. Link up\n");
fnic_fdls_link_status_change(fnic, 1);
} else {
/* UP -> UP */
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"up->up\n");
}
}
} else if (fnic->link_status) {
/* DOWN -> UP */
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"down->up. Link up\n");
fnic_fdls_link_status_change(fnic, 1);
} else {
/* UP -> DOWN */
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"up->down. Link down\n");
fnic_fdls_link_status_change(fnic, 0);
}
@ -275,7 +279,7 @@ void fnic_handle_link(struct work_struct *work)
fnic->reset_in_progress = NOT_IN_PROGRESS;
complete(&fnic->reset_completion_wait);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Marking fnic reset completion\n");
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
}
@ -285,6 +289,7 @@ void fnic_handle_frame(struct work_struct *work)
struct fnic *fnic = container_of(work, struct fnic, frame_work);
struct fnic_frame_list *cur_frame, *next;
int fchdr_offset = 0;
struct fc_frame_header *fchdr;
spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
list_for_each_entry_safe(cur_frame, next, &fnic->frame_queue, links) {
@ -302,7 +307,7 @@ void fnic_handle_frame(struct work_struct *work)
*/
if (fnic->state != FNIC_IN_FC_MODE &&
fnic->state != FNIC_IN_ETH_MODE) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Cannot process frame in transitional state\n");
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
return;
@ -314,8 +319,14 @@ void fnic_handle_frame(struct work_struct *work)
fchdr_offset = (cur_frame->rx_ethhdr_stripped) ?
0 : FNIC_ETH_FCOE_HDRS_OFFSET;
fnic_fdls_recv_frame(&fnic->iport, cur_frame->fp,
cur_frame->frame_len, fchdr_offset);
fchdr = (struct fc_frame_header *)((u8 *)cur_frame->fp + fchdr_offset);
if (IS_FNIC_NVME_INITIATOR(fnic) && fnic_is_nvme_frame(fchdr)) {
nvfnic_ls_rsp_recv(&fnic->iport, fchdr,
cur_frame->frame_len - fchdr_offset);
} else {
fnic_fdls_recv_frame(&fnic->iport, cur_frame->fp,
cur_frame->frame_len, fchdr_offset);
}
mempool_free(cur_frame->fp, fnic->frame_recv_pool);
mempool_free(cur_frame, fnic->frame_elem_pool);
@ -328,7 +339,7 @@ void fnic_handle_fip_frame(struct work_struct *work)
struct fnic_frame_list *cur_frame, *next;
struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Processing FIP frame\n");
spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
@ -407,7 +418,7 @@ void fnic_update_mac_locked(struct fnic *fnic, u8 *new)
if (ether_addr_equal(data, new))
return;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Update MAC: %u\n", *new);
if (!is_zero_ether_addr(data) && !ether_addr_equal(data, ctl))
@ -477,7 +488,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
if (!fcs_ok) {
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fnic 0x%p fcs error. Dropping packet.\n", fnic);
goto drop;
}
@ -487,21 +498,21 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
if (fnic_import_rq_eth_pkt(fnic, fp))
return;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Dropping h_proto 0x%x",
be16_to_cpu(eh->h_proto));
goto drop;
}
} else {
/* wrong CQ type */
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fnic rq_cmpl wrong cq type x%x\n", type);
goto drop;
}
if (!fcs_ok || packet_error || !fcoe_fnic_crc_ok || fcoe_enc_error) {
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fcoe %x fcsok %x pkterr %x ffco %x fee %x\n",
fcoe, fcs_ok, packet_error,
fcoe_fnic_crc_ok, fcoe_enc_error);
@ -511,7 +522,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
spin_lock_irqsave(&fnic->fnic_lock, flags);
if (fnic->stop_rx_link_events) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fnic->stop_rx_link_events: %d\n",
fnic->stop_rx_link_events);
goto drop;
@ -521,7 +532,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
frame_elem = mempool_alloc(fnic->frame_elem_pool, GFP_ATOMIC);
if (!frame_elem) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Failed to allocate memory for frame elem");
goto drop;
}
@ -567,7 +578,7 @@ int fnic_rq_cmpl_handler(struct fnic *fnic, int rq_work_to_do)
if (cur_work_done && fnic->stop_rx_link_events != 1) {
err = vnic_rq_fill(&fnic->rq[i], fnic_alloc_rq_frame);
if (err)
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"fnic_alloc_rq_frame can't alloc"
" frame\n");
}
@ -593,7 +604,7 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
len = FNIC_FRAME_HT_ROOM;
buf = mempool_alloc(fnic->frame_recv_pool, GFP_ATOMIC);
if (!buf) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Unable to allocate RQ buffer of size: %d\n", len);
return -ENOMEM;
}
@ -601,7 +612,7 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
pa = dma_map_single(&fnic->pdev->dev, buf, len, DMA_FROM_DEVICE);
if (dma_mapping_error(&fnic->pdev->dev, pa)) {
ret = -ENOMEM;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"PCI mapping failed with error %d\n", ret);
goto free_buf;
}
@ -615,9 +626,13 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
{
void *rq_buf = buf->os_buf;
void *rq_buf;
struct fnic *fnic = vnic_dev_priv(rq->vdev);
if (WARN_ON(!buf))
return;
rq_buf = buf->os_buf;
dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
DMA_FROM_DEVICE);
@ -642,7 +657,7 @@ static int fnic_send_frame(struct fnic *fnic, void *frame, int frame_len)
if ((fnic_fc_trace_set_data(fnic->fnic_num,
FNIC_FC_SEND | 0x80, (char *) frame,
frame_len)) != 0) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fnic ctlr frame trace error");
}
@ -650,9 +665,9 @@ static int fnic_send_frame(struct fnic *fnic, void *frame, int frame_len)
if (!vnic_wq_desc_avail(wq)) {
dma_unmap_single(&fnic->pdev->dev, pa, frame_len, DMA_TO_DEVICE);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"vnic work queue descriptor is not available");
ret = -1;
ret = -ENXIO;
goto fnic_send_frame_end;
}
@ -686,7 +701,6 @@ fdls_send_fcoe_frame(struct fnic *fnic, void *frame, int frame_size,
struct fcoe_hdr *pfcoe_hdr;
struct fnic_frame_list *frame_elem;
int len = frame_size;
int ret;
struct fc_frame_header *fchdr = (struct fc_frame_header *) (frame +
FNIC_ETH_FCOE_HDRS_OFFSET);
@ -706,13 +720,13 @@ fdls_send_fcoe_frame(struct fnic *fnic, void *frame, int frame_size,
&& (fnic->state != FNIC_IN_ETH_MODE)) {
frame_elem = mempool_alloc(fnic->frame_elem_pool, GFP_ATOMIC);
if (!frame_elem) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Failed to allocate memory for frame elem");
return -ENOMEM;
}
memset(frame_elem, 0, sizeof(struct fnic_frame_list));
FNIC_FCS_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Queueing FC frame: sid/did/type/oxid = 0x%x/0x%x/0x%x/0x%x\n",
ntoh24(fchdr->fh_s_id), ntoh24(fchdr->fh_d_id),
fchdr->fh_type, FNIC_STD_GET_OX_ID(fchdr));
@ -724,11 +738,10 @@ fdls_send_fcoe_frame(struct fnic *fnic, void *frame, int frame_size,
fnic_debug_dump_fc_frame(fnic, fchdr, frame_size, "Outgoing");
ret = fnic_send_frame(fnic, frame, len);
return ret;
return fnic_send_frame(fnic, frame, len);
}
void fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame,
int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame,
int frame_size)
{
struct fnic *fnic = iport->fnic;
@ -736,7 +749,7 @@ void fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame,
/* If module unload is in-progress, don't send */
if (fnic->in_remove)
return;
return -ESHUTDOWN;
if (iport->fabric.flags & FNIC_FDLS_FPMA_LEARNT) {
srcmac = iport->fpma;
@ -746,7 +759,7 @@ void fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame,
dstmac = FCOE_ALL_FCF_MAC;
}
fdls_send_fcoe_frame(fnic, frame, frame_size, srcmac, dstmac);
return fdls_send_fcoe_frame(fnic, frame, frame_size, srcmac, dstmac);
}
int
@ -778,7 +791,7 @@ void fnic_flush_tx(struct work_struct *work)
struct fc_frame *fp;
struct fnic_frame_list *cur_frame, *next;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Flush queued frames");
list_for_each_entry_safe(cur_frame, next, &fnic->tx_queue, links) {
@ -797,7 +810,7 @@ fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
struct ethhdr *ethhdr;
int ret;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Setting port id: 0x%x fp: 0x%p fnic state: %d", port_id,
fp, fnic->state);
@ -810,7 +823,7 @@ fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
if (fnic->state == FNIC_IN_ETH_MODE || fnic->state == FNIC_IN_FC_MODE)
fnic->state = FNIC_IN_ETH_TRANS_FC_MODE;
else {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Unexpected fnic state while processing FLOGI response\n");
return -1;
}
@ -821,7 +834,7 @@ fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
*/
ret = fnic_flogi_reg_handler(fnic, port_id);
if (ret < 0) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"FLOGI registration error ret: %d fnic state: %d\n",
ret, fnic->state);
if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE)
@ -831,7 +844,7 @@ fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
}
iport->fabric.flags |= FNIC_FDLS_FPMA_LEARNT;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"FLOGI registration success\n");
return 0;
}
@ -873,6 +886,9 @@ static void fnic_wq_complete_frame_send(struct vnic_wq *wq,
{
struct fnic *fnic = vnic_dev_priv(wq->vdev);
if (WARN_ON(!buf))
return;
dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);
mempool_free(buf->os_buf, fnic->frame_pool);
@ -915,6 +931,9 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
{
struct fnic *fnic = vnic_dev_priv(wq->vdev);
if (WARN_ON(!buf))
return;
dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);
@ -931,7 +950,7 @@ fnic_fdls_add_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport,
struct fc_rport_identifiers ids;
struct rport_dd_data_s *rdd_data;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Adding rport fcid: 0x%x", tport->fcid);
ids.node_name = tport->wwnn;
@ -943,12 +962,12 @@ fnic_fdls_add_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport,
rport = fc_remote_port_add(fnic->host, 0, &ids);
spin_lock_irqsave(&fnic->fnic_lock, flags);
if (!rport) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Failed to add rport for tport: 0x%x", tport->fcid);
return;
}
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Added rport fcid: 0x%x", tport->fcid);
/* Mimic these assignments in queuecommand to avoid timing issues */
@ -987,7 +1006,7 @@ fnic_fdls_remove_tport(struct fnic_iport_s *iport,
fc_remote_port_delete(rport);
spin_lock_irqsave(&fnic->fnic_lock, flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Deregistered and freed tport fcid: 0x%x from scsi transport fc",
tport->fcid);
@ -1014,11 +1033,14 @@ void fnic_delete_fcp_tports(struct fnic *fnic)
spin_lock_irqsave(&fnic->fnic_lock, flags);
list_for_each_entry_safe(tport, next, &fnic->iport.tport_list, links) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"removing fcp rport fcid: 0x%x", tport->fcid);
fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINING);
fnic_del_tport_timer_sync(fnic, tport);
fnic_fdls_remove_tport(&fnic->iport, tport, flags);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_fdls_remove_tport(&fnic->iport, tport, flags);
else if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_delete_tport(&fnic->iport, tport, flags);
}
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
}
@ -1041,36 +1063,40 @@ void fnic_tport_event_handler(struct work_struct *work)
tport = cur_evt->arg1;
switch (cur_evt->event) {
case TGT_EV_RPORT_ADD:
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Add rport event");
if (tport->state == FDLS_TGT_STATE_READY) {
fnic_fdls_add_tport(&fnic->iport,
(struct fnic_tport_s *) cur_evt->arg1, flags);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_fdls_add_tport(&fnic->iport, tport, flags);
else if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_add_tport(fnic, tport, flags);
} else {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Target not ready. Add rport event dropped: 0x%x",
tport->fcid);
}
break;
case TGT_EV_RPORT_DEL:
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Remove rport event");
if (tport->state == FDLS_TGT_STATE_OFFLINING) {
fnic_fdls_remove_tport(&fnic->iport,
(struct fnic_tport_s *) cur_evt->arg1, flags);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_fdls_remove_tport(&fnic->iport, tport, flags);
else if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_delete_tport(&fnic->iport, tport, flags);
} else {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"remove rport event dropped tport fcid: 0x%x",
tport->fcid);
}
break;
case TGT_EV_TPORT_DELETE:
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Delete tport event");
fdls_delete_tport(tport->iport, tport);
break;
default:
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Unknown tport event");
break;
}
@ -1110,12 +1136,15 @@ void fnic_reset_work_handler(struct work_struct *work)
spin_unlock_irqrestore(&reset_fnic_list_lock,
reset_fnic_list_lock_flags);
dev_err(&cur_fnic->pdev->dev, "fnic: <%d>: issuing a host reset\n",
cur_fnic->fnic_num);
host_reset_ret_code = fnic_host_reset(cur_fnic->host);
dev_err(&cur_fnic->pdev->dev,
"fnic: <%d>: returned from host reset with status: %d\n",
cur_fnic->fnic_num, host_reset_ret_code);
if (IS_FNIC_FCP_INITIATOR(cur_fnic)) {
dev_err(&cur_fnic->pdev->dev,
"fnic: <%d>: issuing a host reset\n",
cur_fnic->fnic_num);
host_reset_ret_code = fnic_host_reset(cur_fnic->host);
dev_err(&cur_fnic->pdev->dev,
"fnic: <%d>: returned from host reset with status: %d\n",
cur_fnic->fnic_num, host_reset_ret_code);
}
spin_lock_irqsave(&cur_fnic->fnic_lock, cur_fnic->lock_flags);
cur_fnic->pc_rscn_handling_status =
@ -1142,7 +1171,7 @@ void fnic_fcpio_reset(struct fnic *fnic)
if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)) {
/* fw reset is in progress, poll for its completion */
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"fnic is in unexpected state: %d for fw_reset\n",
fnic->state);
return;
@ -1155,7 +1184,7 @@ void fnic_fcpio_reset(struct fnic *fnic)
fnic->fw_reset_done = &fw_reset_done;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Issuing fw reset\n");
if (fnic_fw_reset_handler(fnic)) {
spin_lock_irqsave(&fnic->fnic_lock, flags);
@ -1163,14 +1192,14 @@ void fnic_fcpio_reset(struct fnic *fnic)
fnic->state = old_state;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
} else {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Waiting for fw completion\n");
time_remain = wait_for_completion_timeout(&fw_reset_done,
msecs_to_jiffies(FNIC_FW_RESET_TIMEOUT));
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"Woken up after fw completion timeout\n");
if (time_remain == 0) {
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_FCS_DBG(KERN_INFO, fnic,
"FW reset completion timed out after %d ms\n",
FNIC_FW_RESET_TIMEOUT);
}

View File

@ -78,14 +78,17 @@
#define FNIC_FDLS_FPMA_LEARNT 0x2
/* tport flags */
#define FNIC_FDLS_TPORT_IN_GPN_FT_LIST 0x1
#define FNIC_FDLS_TGT_ABORT_ISSUED 0x2
#define FNIC_FDLS_TPORT_SEND_ADISC 0x4
#define FNIC_FDLS_RETRY_FRAME 0x8
#define FNIC_FDLS_TPORT_BUSY 0x10
#define FNIC_FDLS_TPORT_TERMINATING 0x20
#define FNIC_FDLS_TPORT_DELETED 0x40
#define FNIC_FDLS_SCSI_REGISTERED 0x200
#define FNIC_FDLS_TPORT_IN_GPN_FT_LIST 0x1
#define FNIC_FDLS_TGT_ABORT_ISSUED 0x2
#define FNIC_FDLS_TPORT_SEND_ADISC 0x4
#define FNIC_FDLS_RETRY_FRAME 0x8
#define FNIC_FDLS_TPORT_BUSY 0x10
#define FNIC_FDLS_TPORT_TERMINATING 0x20
#define FNIC_FDLS_TPORT_DELETED 0x40
#define FNIC_FDLS_NVME_REGISTERED 0x80
#define FNIC_FDLS_NVME_TPORT_CLEANUP_PENDING 0x100
#define FNIC_FDLS_SCSI_REGISTERED 0x200
#define FNIC_TPORT_CAN_BE_FREED 0x400
/* Retry supported by rport(returned by prli service parameters) */
#define FDLS_FC_RP_FLAGS_RETRY 0x1
@ -94,6 +97,7 @@
#define fdls_get_state(_fdls_fabric) ((_fdls_fabric)->state)
#define FNIC_FDMI_ACTIVE 0x8
#define FNIC_LPORT_NVME_REGISTERED 0x4
#define FNIC_FIRST_LINK_UP 0x2
#define fdls_set_tport_state(_tport, _state) (_tport->state = _state)
@ -119,6 +123,13 @@
#define FNIC_FRAME_TYPE_TGT_PRLI 0x2800
#define FNIC_FRAME_TYPE_TGT_ADISC 0x2A00
#define FNIC_FRAME_TYPE_TGT_LOGO 0x2C00
#define FNIC_FRAME_TYPE_NVME_LS 0x3000
#define NVFNIC_FCPIO_TAG_POOL_SZ (2048)
#define NVFNIC_LS_REQ_OXID_POOL_SZ (64)
#define NVFNIC_LS_REQ_OXID_BASE (0x2500)
#define FNIC_LPORT_NVME_REGISTERED 0x4
struct fnic_fip_fcf_s {
uint16_t vlan_id;
@ -220,6 +231,8 @@ struct fnic_tport_s {
struct fc_rport *rport;
char str_wwpn[20];
char str_wwnn[20];
struct list_head ls_req_list;
struct nvme_fc_remote_port *nv_rport;
};
/* OXID pool related structures */
@ -288,7 +301,6 @@ struct fnic_iport_s {
struct fnic_fdls_fip_s fip;
struct fnic_fdls_fabric_s fabric;
struct list_head tport_list;
struct list_head tport_list_pending_del;
/* list of tports for which we are yet to send PLOGO */
struct list_head inprocess_tport_list;
struct list_head deleted_tport_list;
@ -308,6 +320,13 @@ struct fnic_iport_s {
struct fnic_iport_stats iport_stats;
char str_wwpn[20];
char str_wwnn[20];
/* nvme */;
void *nvfnic_fcpio_tag[NVFNIC_FCPIO_TAG_POOL_SZ];
struct nvme_fc_local_port *nv_lport;
struct nvme_fc_port_template *nv_tmpl;
struct fnic_oxid_pool_s ls_req_oxid_pool;
struct list_head fcpio_list;
};
struct rport_dd_data_s {
@ -336,6 +355,7 @@ enum fnic_recv_frame_type_e {
FNIC_TPORT_ADISC_RSP,
FNIC_TPORT_BLS_ABTS_RSP,
FNIC_TPORT_LOGO_RSP,
FNIC_LS_REQ_ABTS_RSP,
/* unsolicited requests */
FNIC_BLS_ABTS_REQ,
@ -368,6 +388,12 @@ enum fnic_port_speeds {
DCEM_PORTSPEED_128G = 128000,
};
static inline bool fdls_tport_is_offline(struct fnic_tport_s *tport)
{
return (tport->state == FDLS_TGT_STATE_OFFLINING ||
tport->state == FDLS_TGT_STATE_OFFLINE);
}
/* Function Declarations */
/* fdls_disc.c */
void fnic_fdls_disc_init(struct fnic_iport_s *iport);
@ -381,6 +407,8 @@ uint16_t fdls_alloc_oxid(struct fnic_iport_s *iport, int oxid_frame_type,
uint16_t *active_oxid);
void fdls_free_oxid(struct fnic_iport_s *iport,
uint16_t oxid, uint16_t *active_oxid);
int fdls_send_ls_req_abts(struct fnic_iport_s *iport,
struct fnic_tport_s *tport, unsigned int oxid);
void fdls_tgt_logout(struct fnic_iport_s *iport,
struct fnic_tport_s *tport);
void fnic_del_fabric_timer_sync(struct fnic *fnic);
@ -398,7 +426,7 @@ void fdls_fdmi_retry_plogi(struct fnic_iport_s *iport);
/* fnic_fcs.c */
void fnic_fdls_init(struct fnic *fnic, int usefip);
void fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame,
int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame,
int frame_size);
void fnic_fcoe_send_vlan_req(struct fnic *fnic);
int fnic_send_fip_frame(struct fnic_iport_s *iport,

View File

@ -6,13 +6,19 @@
#ifndef _FNIC_IO_H_
#define _FNIC_IO_H_
#include <scsi/fc/fc_fs.h>
#include <scsi/fc/fc_fcp.h>
#include "fnic_fdls.h"
#include "fcpio.h"
#include <linux/nvme-fc-driver.h>
#define FNIC_DFLT_SG_DESC_CNT 32
#define FNIC_MAX_SG_DESC_CNT 256 /* Maximum descriptors per sgl */
#define FNIC_SG_DESC_ALIGN 16 /* Descriptor address alignment */
#define NVME_STAT_ERROR 0x2
#define NVME_STAT_TASK_SET_FULL 0x3
struct host_sg_desc {
__le64 addr;
__le32 len;
@ -39,6 +45,7 @@ enum fnic_ioreq_state {
FNIC_IOREQ_ABTS_PENDING,
FNIC_IOREQ_ABTS_COMPLETE,
FNIC_IOREQ_CMD_COMPLETE,
FNIC_IOREQ_RESET_TERM,
};
struct fnic_io_req {
@ -50,12 +57,27 @@ struct fnic_io_req {
dma_addr_t sgl_list_pa; /* dma address for sgl list */
u16 sgl_cnt;
u8 sgl_type; /* device DMA descriptor list type */
u8 sgl_mapped:1; /* set when sgl_list_pa is a valid DMA mapping */
u8 io_completed:1; /* set to 1 when fw completes IO */
u32 port_id; /* remote port DID */
unsigned long start_time; /* in jiffies */
u32 tag;
enum fnic_ioreq_state cmd_state;
u32 cmd_flags;
u32 abts_state;
struct completion *abts_done; /* completion for abts */
struct completion *dr_done; /* completion for device reset */
unsigned int tag;
struct scsi_cmnd *sc; /* midlayer's cmd pointer */
struct vnic_wq_copy *wq;
struct llist_node nvfnic_io_cmpl;
struct nvmefc_fcp_req *fcp_req;
void (*done)(struct fnic_io_req *io_req);
unsigned long waitq_start_time; /* in jiffies */
struct timer_list admin_io_timer;
uint32_t status;
struct fnic_tag_t *tag_data;
struct fnic_io_event_s io_evt;
};
#endif /* _FNIC_IO_H_ */

View File

@ -222,7 +222,7 @@ int fnic_request_intr(struct fnic *fnic)
fnic->msix[i].devname,
fnic->msix[i].devid);
if (err) {
FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_ERR, fnic,
"request_irq failed with error: %d\n",
err);
fnic_free_intr(fnic);
@ -250,10 +250,10 @@ int fnic_set_intr_mode_msix(struct fnic *fnic)
* We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
* (last INTR is used for WQ/RQ errors and notification area)
*/
FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_INFO, fnic,
"rq-array size: %d wq-array size: %d copy-wq array size: %d\n",
n, m, o);
FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_INFO, fnic,
"rq_count: %d raw_wq_count: %d wq_copy_count: %d cq_count: %d\n",
fnic->rq_count, fnic->raw_wq_count,
fnic->wq_copy_count, fnic->cq_count);
@ -265,17 +265,17 @@ int fnic_set_intr_mode_msix(struct fnic *fnic)
vec_count = pci_alloc_irq_vectors(fnic->pdev, min_irqs, vecs,
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_INFO, fnic,
"allocated %d MSI-X vectors\n",
vec_count);
if (vec_count > 0) {
if (vec_count < vecs) {
FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_ERR, fnic,
"interrupts number mismatch: vec_count: %d vecs: %d\n",
vec_count, vecs);
if (vec_count < min_irqs) {
FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_ERR, fnic,
"no interrupts for copy wq\n");
return 1;
}
@ -287,7 +287,7 @@ int fnic_set_intr_mode_msix(struct fnic *fnic)
fnic->wq_copy_count = vec_count - n - m - 1;
fnic->wq_count = fnic->raw_wq_count + fnic->wq_copy_count;
if (fnic->cq_count != vec_count - 1) {
FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_ERR, fnic,
"CQ count: %d does not match MSI-X vector count: %d\n",
fnic->cq_count, vec_count);
fnic->cq_count = vec_count - 1;
@ -295,23 +295,23 @@ int fnic_set_intr_mode_msix(struct fnic *fnic)
fnic->intr_count = vec_count;
fnic->err_intr_offset = fnic->rq_count + fnic->wq_count;
FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_INFO, fnic,
"rq_count: %d raw_wq_count: %d copy_wq_base: %d\n",
fnic->rq_count,
fnic->raw_wq_count, fnic->copy_wq_base);
FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_INFO, fnic,
"wq_copy_count: %d wq_count: %d cq_count: %d\n",
fnic->wq_copy_count,
fnic->wq_count, fnic->cq_count);
FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"intr_count: %d err_intr_offset: %u",
FNIC_ISR_DBG(KERN_INFO, fnic,
"intr_count: %d err_intr_offset: %u\n",
fnic->intr_count,
fnic->err_intr_offset);
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSIX);
FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_INFO, fnic,
"fnic using MSI-X\n");
return 0;
}
@ -351,7 +351,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
fnic->intr_count = 1;
fnic->err_intr_offset = 0;
FNIC_ISR_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_DEBUG, fnic,
"Using MSI Interrupts\n");
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSI);
@ -377,7 +377,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
fnic->cq_count = 3;
fnic->intr_count = 3;
FNIC_ISR_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_ISR_DBG(KERN_DEBUG, fnic,
"Using Legacy Interrupts\n");
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);

View File

@ -42,12 +42,12 @@ static struct kmem_cache *fdls_frame_cache;
static struct kmem_cache *fdls_frame_elem_cache;
static struct kmem_cache *fdls_frame_recv_cache;
static LIST_HEAD(fnic_list);
static DEFINE_SPINLOCK(fnic_list_lock);
static DEFINE_IDA(fnic_ida);
struct work_struct reset_fnic_work;
LIST_HEAD(reset_fnic_list);
DEFINE_SPINLOCK(reset_fnic_list_lock);
DEFINE_SPINLOCK(fnic_list_lock);
/* Supported devices by fnic module */
static const struct pci_device_id fnic_id_table[] = {
@ -89,6 +89,15 @@ module_param(fnic_fc_trace_max_pages, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(fnic_fc_trace_max_pages,
"Total allocated memory pages for fc trace buffer");
unsigned int nvme_dev_loss_tmo = 30;
module_param_named(nvme_dev_loss_tmo, nvme_dev_loss_tmo, uint, 0644);
MODULE_PARM_DESC(nvme_dev_loss_tmo, "configurable NVME dev loss timeout");
unsigned int nvme_max_ios_to_process = 16;
module_param(nvme_max_ios_to_process, uint, 0644);
MODULE_PARM_DESC(nvme_max_ios_to_process,
"Maximum number of NVME IOs to process per work queue");
static unsigned int fnic_max_qdepth = FNIC_DFLT_QUEUE_DEPTH;
module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN");
@ -100,6 +109,7 @@ MODULE_PARM_DESC(pc_rscn_handling_feature_flag,
struct workqueue_struct *reset_fnic_work_queue;
struct workqueue_struct *fnic_fip_queue;
struct workqueue_struct *fnic_cmpl_queue;
static int fnic_sdev_init(struct scsi_device *sdev)
{
@ -185,7 +195,7 @@ static void fnic_get_host_speed(struct Scsi_Host *shost)
u32 port_speed = vnic_dev_port_speed(fnic->vdev);
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
FNIC_MAIN_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_MAIN_DBG(KERN_INFO, fnic,
"port_speed: %d Mbps", port_speed);
atomic64_set(&fnic_stats->misc_stats.port_speed_in_mbps, port_speed);
@ -235,7 +245,7 @@ static void fnic_get_host_speed(struct Scsi_Host *shost)
fc_host_speed(shost) = FC_PORTSPEED_128GBIT;
break;
default:
FNIC_MAIN_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_MAIN_DBG(KERN_INFO, fnic,
"Unknown FC speed: %d Mbps", port_speed);
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
@ -261,7 +271,7 @@ static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *host)
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
if (ret) {
FNIC_MAIN_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_MAIN_DBG(KERN_DEBUG, fnic,
"fnic: Get vnic stats failed: 0x%x", ret);
return stats;
}
@ -287,64 +297,66 @@ static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *host)
void fnic_dump_fchost_stats(struct Scsi_Host *host,
struct fc_host_statistics *stats)
{
FNIC_MAIN_NOTE(KERN_NOTICE, host,
struct fnic *fnic = *((struct fnic **) shost_priv(host));
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: seconds since last reset = %llu\n",
stats->seconds_since_last_reset);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: tx frames = %llu\n",
stats->tx_frames);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: tx words = %llu\n",
stats->tx_words);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: rx frames = %llu\n",
stats->rx_frames);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: rx words = %llu\n",
stats->rx_words);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: lip count = %llu\n",
stats->lip_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: nos count = %llu\n",
stats->nos_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: error frames = %llu\n",
stats->error_frames);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: dumped frames = %llu\n",
stats->dumped_frames);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: link failure count = %llu\n",
stats->link_failure_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: loss of sync count = %llu\n",
stats->loss_of_sync_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: loss of signal count = %llu\n",
stats->loss_of_signal_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: prim seq protocol err count = %llu\n",
stats->prim_seq_protocol_err_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: invalid tx word count= %llu\n",
stats->invalid_tx_word_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: invalid crc count = %llu\n",
stats->invalid_crc_count);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: fcp input requests = %llu\n",
stats->fcp_input_requests);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: fcp output requests = %llu\n",
stats->fcp_output_requests);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: fcp control requests = %llu\n",
stats->fcp_control_requests);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: fcp input megabytes = %llu\n",
stats->fcp_input_megabytes);
FNIC_MAIN_NOTE(KERN_NOTICE, host,
FNIC_MAIN_NOTE(KERN_NOTICE, fnic,
"fnic: fcp output megabytes = %llu\n",
stats->fcp_output_megabytes);
return;
@ -370,7 +382,7 @@ static void fnic_reset_host_stats(struct Scsi_Host *host)
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
if (ret) {
FNIC_MAIN_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_MAIN_DBG(KERN_DEBUG, fnic,
"fnic: Reset vnic stats failed"
" 0x%x", ret);
return;
@ -547,6 +559,9 @@ static int fnic_cleanup(struct fnic *fnic)
vnic_wq_copy_clean(&fnic->hw_copy_wq[i],
fnic_wq_copy_cleanup_handler);
if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_flush_nvme_io_list(fnic);
for (i = 0; i < fnic->cq_count; i++)
vnic_cq_clean(&fnic->cq[i]);
for (i = 0; i < fnic->intr_count; i++)
@ -676,6 +691,59 @@ static int fnic_scsi_drv_init(struct fnic *fnic)
return 0;
}
static int fnic_nvme_drv_init(struct fnic *fnic)
{
int ret;
int hwq;
fnic->fnic_max_tag_id = NVFNIC_FCPIO_TAG_POOL_SZ;
for (hwq = 0; hwq < fnic->wq_copy_count; hwq++) {
fnic->sw_copy_wq[hwq].ioreq_table_size = fnic->fnic_max_tag_id;
fnic->sw_copy_wq[hwq].io_req_table =
kzalloc((fnic->sw_copy_wq[hwq].ioreq_table_size + 1) *
sizeof(struct fnic_io_req *), GFP_KERNEL);
if (!fnic->sw_copy_wq[hwq].io_req_table) {
fnic_free_ioreq_tables_mq(fnic);
return -ENOMEM;
}
}
dev_info(&fnic->pdev->dev, "fnic copy wqs: %d, Q0 ioreq table size: %d\n",
fnic->wq_copy_count, fnic->sw_copy_wq[0].ioreq_table_size);
if (sbitmap_init_node(&fnic->nvfnic_tag_map, NVFNIC_FCPIO_TAG_POOL_SZ,
-1, GFP_KERNEL, NUMA_NO_NODE, false, true)) {
dev_err(&fnic->pdev->dev,
"Unable to allocate tag pool\n");
ret = -ENOMEM;
goto out_free_ioreq_tables;
}
fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
if (!fnic->io_req_pool) {
ret = -ENOMEM;
goto out_free_sbitmap;
}
init_llist_head(&fnic->nvme_io_event_llist);
INIT_WORK(&fnic->nvme_io_cmpl_work, nvfnic_nvme_iodone_work);
ret = nvfnic_add_lport(fnic);
if (ret)
goto out_free_req_pool;
return 0;
out_free_req_pool:
mempool_destroy(fnic->io_req_pool);
out_free_sbitmap:
sbitmap_free(&fnic->nvfnic_tag_map);
out_free_ioreq_tables:
fnic_free_ioreq_tables_mq(fnic);
return ret;
}
void fnic_mq_map_queues_cpus(struct Scsi_Host *host)
{
struct fnic *fnic = *((struct fnic **) shost_priv(host));
@ -684,16 +752,16 @@ void fnic_mq_map_queues_cpus(struct Scsi_Host *host)
struct blk_mq_queue_map *qmap = &host->tag_set.map[HCTX_TYPE_DEFAULT];
if (intr_mode == VNIC_DEV_INTR_MODE_MSI || intr_mode == VNIC_DEV_INTR_MODE_INTX) {
FNIC_MAIN_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_MAIN_DBG(KERN_ERR, fnic,
"intr_mode is not msix\n");
return;
}
FNIC_MAIN_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_MAIN_DBG(KERN_INFO, fnic,
"qmap->nr_queues: %d\n", qmap->nr_queues);
if (l_pdev == NULL) {
FNIC_MAIN_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_MAIN_DBG(KERN_ERR, fnic,
"l_pdev is null\n");
return;
}
@ -842,7 +910,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_fnic_get_config;
}
switch (fnic->config.flags & 0xff0) {
switch (fnic->config.flags & FNIC_ROLE_CONFIG_MASK) {
case VFCF_FC_INITIATOR:
{
host =
@ -861,8 +929,28 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fnic->fnic_num);
}
break;
case VFCF_FC_TARGET:
dev_info(&fnic->pdev->dev,
"fnic: %d is scsi target\n",
fnic->fnic_num);
err = -EOPNOTSUPP;
goto err_out_fnic_role;
case VFCF_FC_NVME_INITIATOR:
fnic_nvmef_debugfs_init(fnic);
fnic->role = FNIC_ROLE_NVME_INITIATOR;
dev_info(&fnic->pdev->dev, "fnic: %d is NVME initiator\n",
fnic->fnic_num);
break;
case VFCF_FC_NVME_TARGET:
dev_info(&fnic->pdev->dev,
"fnic: %d is NVME target\n",
fnic->fnic_num);
err = -EOPNOTSUPP;
goto err_out_fnic_role;
default:
dev_info(&fnic->pdev->dev, "fnic: %d has no role defined\n", fnic->fnic_num);
dev_info(&fnic->pdev->dev,
"fnic: %d has no role defined (0x%x)\n",
fnic->fnic_num, fnic->config.flags & FNIC_ROLE_CONFIG_MASK);
err = -EINVAL;
goto err_out_fnic_role;
}
@ -995,11 +1083,16 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iport->max_flogi_retries = fnic->config.flogi_retries;
iport->max_plogi_retries = fnic->config.plogi_retries;
iport->plogi_timeout = fnic->config.plogi_timeout;
iport->service_params =
(FNIC_FCP_SP_INITIATOR | FNIC_FCP_SP_RD_XRDY_DIS |
FNIC_FCP_SP_CONF_CMPL);
if (fnic->config.flags & VFCF_FCP_SEQ_LVL_ERR)
iport->service_params |= FNIC_FCP_SP_RETRY;
if (IS_FNIC_FCP_INITIATOR(fnic)) {
iport->service_params = (FNIC_FCP_SP_INITIATOR |
FNIC_FCP_SP_RD_XRDY_DIS | FNIC_FCP_SP_CONF_CMPL);
if (fnic->config.flags & VFCF_FCP_SEQ_LVL_ERR)
iport->service_params |= FNIC_FCP_SP_RETRY;
} else if (IS_FNIC_NVME_INITIATOR(fnic)) {
iport->service_params = (FNIC_NVME_SP_INITIATOR);
if (fnic->config.flags & VFCF_FCP_SEQ_LVL_ERR)
iport->service_params |= FNIC_NVME_SP_SLER;
}
iport->boot_time = jiffies;
iport->e_d_tov = fnic->config.ed_tov;
@ -1031,6 +1124,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_LIST_HEAD(&fnic->frame_queue);
INIT_LIST_HEAD(&fnic->tx_queue);
INIT_LIST_HEAD(&fnic->tport_event_list);
init_llist_head(&fnic->nvme_io_event_llist);
INIT_DELAYED_WORK(&iport->oxid_pool.schedule_oxid_free_retry,
fdls_schedule_oxid_free_retry_work);
@ -1061,9 +1155,15 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fnic_fdls_init(fnic, (fnic->config.flags & VFCF_FIP_CAPABLE));
err = fnic_scsi_drv_init(fnic);
if (err)
goto err_out_scsi_drv_init;
if (IS_FNIC_FCP_INITIATOR(fnic)) {
err = fnic_scsi_drv_init(fnic);
if (err)
goto err_out_scsi_drv_init;
} else if (IS_FNIC_NVME_INITIATOR(fnic)) {
err = fnic_nvme_drv_init(fnic);
if (err)
goto err_out_nvme_drv_init;
}
err = fnic_stats_debugfs_init(fnic);
if (err) {
@ -1083,7 +1183,9 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_free_stats_debugfs:
fnic_stats_debugfs_remove(fnic);
fnic_free_ioreq_tables_mq(fnic);
scsi_remove_host(fnic->host);
if (IS_FNIC_FCP_INITIATOR(fnic))
scsi_remove_host(fnic->host);
err_out_nvme_drv_init:
err_out_scsi_drv_init:
fnic_free_intr(fnic);
err_out_fnic_request_intr:
@ -1109,7 +1211,10 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_fnic_alloc_vnic_res:
fnic_clear_intr_mode(fnic);
err_out_fnic_set_intr_mode:
scsi_host_put(fnic->host);
if (IS_FNIC_NVME_INITIATOR(fnic))
fnic_nvmef_debugfs_remove(fnic);
if (IS_FNIC_FCP_INITIATOR(fnic))
scsi_host_put(fnic->host);
err_out_fnic_role:
err_out_scsi_host_alloc:
err_out_fnic_get_config:
@ -1158,7 +1263,10 @@ static void fnic_remove(struct pci_dev *pdev)
*/
flush_workqueue(fnic_event_queue);
fnic_scsi_unload(fnic);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_scsi_unload(fnic);
else if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_nvme_unload(fnic);
if (vnic_dev_get_intr_mode(fnic->vdev) == VNIC_DEV_INTR_MODE_MSI)
timer_delete_sync(&fnic->notify_timer);
@ -1175,6 +1283,7 @@ static void fnic_remove(struct pci_dev *pdev)
if ((fnic_fdmi_support == 1) && (fnic->iport.fabric.fdmi_pending > 0))
timer_delete_sync(&fnic->iport.fabric.fdmi_timer);
fnic_nvmef_debugfs_remove(fnic);
fnic_stats_debugfs_remove(fnic);
/*
@ -1184,6 +1293,11 @@ static void fnic_remove(struct pci_dev *pdev)
*/
fnic_cleanup(fnic);
if (IS_FNIC_NVME_INITIATOR(fnic)) {
sbitmap_free(&fnic->nvfnic_tag_map);
fnic_free_ioreq_tables_mq(fnic);
}
spin_lock_irqsave(&fnic_list_lock, flags);
list_del(&fnic->list);
spin_unlock_irqrestore(&fnic_list_lock, flags);
@ -1202,8 +1316,10 @@ static void fnic_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
ida_free(&fnic_ida, fnic->fnic_num);
fnic_scsi_unload_cleanup(fnic);
scsi_host_put(fnic->host);
if (IS_FNIC_FCP_INITIATOR(fnic)) {
fnic_scsi_unload_cleanup(fnic);
scsi_host_put(fnic->host);
}
kfree(fnic);
}
@ -1323,6 +1439,15 @@ static int __init fnic_init_module(void)
goto err_create_fip_workq;
}
fnic_cmpl_queue =
alloc_workqueue("fnic_cmpl_wq",
WQ_PERCPU | WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
if (!fnic_cmpl_queue) {
pr_err("fnic completion work queue create failed\n");
err = -ENOMEM;
goto err_create_cmpl_workq;
}
if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON) {
reset_fnic_work_queue =
create_singlethread_workqueue("reset_fnic_work_queue");
@ -1354,6 +1479,8 @@ static int __init fnic_init_module(void)
err_pci_register:
fc_release_transport(fnic_fc_transport);
err_fc_transport:
destroy_workqueue(fnic_cmpl_queue);
err_create_cmpl_workq:
destroy_workqueue(fnic_fip_queue);
err_create_fip_workq:
if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON)
@ -1382,6 +1509,7 @@ static int __init fnic_init_module(void)
static void __exit fnic_cleanup_module(void)
{
pci_unregister_driver(&fnic_driver);
destroy_workqueue(fnic_cmpl_queue);
destroy_workqueue(fnic_event_queue);
if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2008 Cisco Systems, Inc. All rights reserved.
* Copyright 2007 Nuova Systems, Inc. All rights reserved.
*/
#ifndef _FNIC_NVME_H
#define _FNIC_NVME_H
#include "fdls_fc.h"
#include "fnic_fdls.h"
#define FNIC_NVME_TPORT_REMOVE_WAIT (5 * 1000)
#define FNIC_NVME_TPORT_LIST_EMPTY_WAIT (FNIC_NVME_TPORT_REMOVE_WAIT * 2)
#define FNIC_TPORT_CLEANUP_WAIT_COUNT 8
#define FNIC_NVME_LPORT_REMOVE_WAIT (2 * 60 * 1000)
#define FNIC_LS_REQ_FLAGS_NONE 0x0
#define FNIC_LS_REQ_FLAGS_ABORTED 0x1
#define FNIC_LS_REQ_FLAGS_DONE 0x2
#define FNIC_LS_REQ_ABORT_COMPLETED 0x4
#define FNIC_STATUS_LS_REQ_ABORTED 0x1
#define FNIC_LS_REQ_MIN_TMO_SECS (2)
#define FNIC_LS_REQ_MAX_TMO_SECS (5)
#define FNIC_NVME_ADMIN_IO_TIMEOUT 30000 /* mSec */
#define FNIC_NVME_NO_FREE_TAG (0xFFFF)
#define FNIC_LS_REQ_TMO_MSECS(tmo) (((tmo >= FNIC_LS_REQ_MIN_TMO_SECS) && \
(tmo <= FNIC_LS_REQ_MAX_TMO_SECS)) ? \
(tmo * 1000) : (FNIC_LS_REQ_MIN_TMO_SECS * 1000))
#define IS_ADMIN_IO(_io_req) \
(NVME_CMD_FLAGS(_io_req) & FNIC_NVME_ADMIN_IO_TIMER_PENDING)
extern unsigned int nvme_max_ios_to_process;
extern unsigned int nvme_dev_loss_tmo;
extern spinlock_t fnic_list_lock;
enum nvfnic_lsreq_state_e {
FNIC_LS_REQ_CMD_INIT = 0,
FNIC_LS_REQ_CMD_PENDING,
FNIC_LS_REQ_CMD_ABTS_PENDING,
FNIC_LS_REQ_CMD_COMPLETE,
FNIC_LS_REQ_ABTS_COMPLETE,
FNIC_LS_REQ_CMD_ABTS_STARTED,
};
struct fnic_nvme_tag {
struct list_head free_list;
int tag_id;
};
struct nvfnic_ls_req {
struct list_head list;
struct nvmefc_ls_req *ls_req;
uint16_t oxid;
struct timer_list ls_req_timer;
struct fnic *fnic;
struct fnic_tport_s *tport;
int state;
unsigned int flags;
};
#if IS_ENABLED(CONFIG_NVME_FC)
int nvfnic_nvme_io_done_handler(void *arg);
struct fnic_io_req *nvfnic_find_io_req_by_tag(struct fnic *fnic, uint16_t tag);
void nvfnic_reset_fcpio_tag_pool(struct fnic_iport_s *iport);
int nvfnic_add_lport(struct fnic *fnic);
void nvfnic_fcpio_abort(struct nvme_fc_local_port *lport,
struct nvme_fc_remote_port *rport,
void *hw_queue_handle, struct nvmefc_fcp_req *fcp_req);
void nvfnic_remote_port_delete(struct nvme_fc_remote_port *rport);
void nvfnic_local_port_delete(struct nvme_fc_local_port *lport);
int nvfnic_dma_map_sgl(struct fnic *fnic, struct fnic_io_req *io_req,
int sg_count);
void nvfnic_dma_unmap_sgl(struct fnic *fnic, struct fnic_io_req *io_req);
int nvfnic_get_sg_count(struct fnic_io_req *io_req);
void nvfnic_release_nvme_ioreq_buf(struct fnic_iport_s *iport,
struct fnic_io_req *io_req);
void nvfnic_dump_nvcmd(struct fnic_io_req *io_req, uint8_t flags);
bool _cleanup_tport_io(struct sbitmap *map, unsigned int tag, void *data);
void nvfnic_flush_nvme_io_list(struct fnic *fnic);
void nvfnic_fcpio_cmpl(struct fnic_io_req *io_req);
bool nvfnic_transport_ready(struct fnic_iport_s *iport,
struct fnic_tport_s *tport);
int nvfnic_alloc_fcpio_tag(struct fnic_iport_s *iport,
struct fnic_io_req *io_req);
int nvfnic_queuecommand(struct fnic_io_req *io_req);
void nvfnic_free_fcpio_tag(struct fnic_iport_s *iport,
struct fnic_io_req *io_req);
void nvfnic_delete_lport(struct fnic_iport_s *iport);
int nvfnic_add_tport(struct fnic *fnic, struct fnic_tport_s *tport,
unsigned long flags);
void nvfnic_cleanup_all_nvme_ios(struct fnic *fnic);
void nvfnic_delete_tport_work(struct work_struct *work);
void nvfnic_delete_tport(struct fnic_iport_s *iport,
struct fnic_tport_s *tport, unsigned long flags);
void nvfnic_fcpio_nvme_fast_cmpl_handler(struct fnic *fnic,
struct fcpio_fw_req *desc);
void nvfnic_ls_rsp_recv(struct fnic_iport_s *iport,
struct fc_frame_header *fchdr, int len);
void nvfnic_process_ls_abts_rsp(struct fnic_iport_s *iport,
struct fc_frame_header *fchdr);
void nvfnic_admin_io_timeout(struct timer_list *t);
void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
struct fcpio_fw_req *desc);
void nvfnic_nvme_zero_devloss_tports(struct fnic *fnic);
bool nvfnic_queue_abort_io_req(struct fnic *fnic, int tag, u32 task_req,
struct fnic_io_req *io_req);
void nvfnic_ls_req_abort(struct nvme_fc_local_port *lport,
struct nvme_fc_remote_port *rport,
struct nvmefc_ls_req *lsreq);
int nvfnic_create_queue(struct nvme_fc_local_port *lport, unsigned int idx,
u16 size, void **handle);
int nvfnic_ls_req_send(struct nvme_fc_local_port *lport,
struct nvme_fc_remote_port *rport,
struct nvmefc_ls_req *ls_req);
void nvfnic_ls_req_timeout(struct timer_list *t);
uint16_t nvfnic_alloc_ls_req_oxid(struct fnic_iport_s *iport);
struct nvfnic_ls_req *nvfnic_find_ls_req(struct fnic_tport_s *tport,
uint16_t oxid);
void nvfnic_terminate_tport_ios(struct fnic *fnic, struct fnic_tport_s *tport);
bool _terminate_tport_ios(struct sbitmap *map, unsigned int tag, void *data);
bool _cleanup_all_nvme_io(struct sbitmap *map, unsigned int tag, void *data);
void nvfnic_cleanup_all_nvme_ios(struct fnic *fnic);
int nvfnic_fcpio_send(struct nvme_fc_local_port *lport,
struct nvme_fc_remote_port *rport, void *hw_queue_handle,
struct nvmefc_fcp_req *fcp_req);
void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic,
struct fcpio_fw_req *desc, int sw_flag);
void nvfnic_terminate_tport_ls_reqs(struct fnic *fnic,
struct fnic_tport_s *tport);
void nvfnic_terminate_tport_admin_ios(struct fnic *fnic,
struct fnic_tport_s *tport);
void nvfnic_cleanup_tport_io(struct fnic *fnic, struct fnic_tport_s *tport);
void nvfnic_nvme_unload(struct fnic *fnic);
int nvfnic_get_nvmef_info(struct fnic *fnic, struct fnic_nvmef_info *info);
void nvfnic_exch_reset(struct fnic_iport_s *iport, struct fnic_tport_s *tport);
void nvfnic_nvme_iodone_work(struct work_struct *work);
#else
static inline int nvfnic_add_lport(struct fnic *fnic)
{
return -EOPNOTSUPP;
}
static inline void nvfnic_nvme_unload(struct fnic *fnic)
{
}
static inline void nvfnic_flush_nvme_io_list(struct fnic *fnic)
{
}
static inline void nvfnic_nvme_iodone_work(struct work_struct *work)
{
}
static inline void nvfnic_exch_reset(struct fnic_iport_s *iport,
struct fnic_tport_s *tport)
{
}
static inline void nvfnic_process_ls_abts_rsp(struct fnic_iport_s *iport,
struct fc_frame_header *fchdr)
{
}
static inline void nvfnic_ls_rsp_recv(struct fnic_iport_s *iport,
struct fc_frame_header *fchdr, int len)
{
}
static inline int nvfnic_add_tport(struct fnic *fnic,
struct fnic_tport_s *tport,
unsigned long flags)
{
return 0;
}
static inline void nvfnic_delete_tport(struct fnic_iport_s *iport,
struct fnic_tport_s *tport,
unsigned long flags)
{
}
static inline void nvfnic_cleanup_all_nvme_ios(struct fnic *fnic)
{
}
static inline void nvfnic_fcpio_nvme_fast_cmpl_handler(struct fnic *fnic,
struct fcpio_fw_req *desc)
{
}
static inline void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic,
struct fcpio_fw_req *desc,
int sw_flag)
{
}
static inline void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
struct fcpio_fw_req *desc)
{
}
static inline int nvfnic_get_nvmef_info(struct fnic *fnic,
struct fnic_nvmef_info *info)
{
return 0;
}
#endif
extern const char *fnic_fcpio_status_to_str(unsigned int status);
#endif /* _FNIC_NVME_H */

View File

@ -22,6 +22,7 @@
int fnic_get_vnic_config(struct fnic *fnic)
{
struct vnic_fc_config *c = &fnic->config;
u32 role;
int err;
#define GET_CONFIG(m) \
@ -56,11 +57,35 @@ int fnic_get_vnic_config(struct fnic *fnic)
GET_CONFIG(port_down_io_retries);
GET_CONFIG(luns_per_tgt);
GET_CONFIG(intr_mode);
GET_CONFIG(lun_queue_depth);
GET_CONFIG(io_timeout_retry);
GET_CONFIG(wq_copy_count);
if ((c->flags & (VFCF_FC_INITIATOR)) == 0) {
dev_info(&fnic->pdev->dev, "vNIC role not defined (def role: FC Init)\n");
role = c->flags & FNIC_ROLE_CONFIG_MASK;
switch (role) {
case 0:
dev_info(&fnic->pdev->dev,
"vNIC role not defined (def role: FC Init)\n");
c->flags |= VFCF_FC_INITIATOR;
break;
case VFCF_FC_INITIATOR:
case VFCF_FC_NVME_INITIATOR:
break;
case VFCF_FC_TARGET:
dev_info(&fnic->pdev->dev,
"vNIC role is FC Target (unsupported)\n");
break;
case VFCF_FC_NVME_TARGET:
dev_info(&fnic->pdev->dev,
"vNIC role is FC-NVMe Target (unsupported)\n");
break;
default:
dev_info(&fnic->pdev->dev,
"vNIC role not supported (0x%x), defaulting to FC Init\n",
role);
c->flags &= ~FNIC_ROLE_CONFIG_MASK;
c->flags |= VFCF_FC_INITIATOR;
break;
}
c->wq_enet_desc_count =
@ -163,6 +188,8 @@ int fnic_get_vnic_config(struct fnic *fnic)
c->port_down_io_retries, c->port_down_timeout);
dev_info(&fnic->pdev->dev, "fNIC wq_copy_count: %d\n", c->wq_copy_count);
dev_info(&fnic->pdev->dev, "fNIC intr mode: %d\n", c->intr_mode);
dev_info(&fnic->pdev->dev, "fNIC role flags: 0x%x\n",
(c->flags & FNIC_ROLE_CONFIG_MASK));
return 0;
}

View File

@ -126,7 +126,8 @@ static inline void fnic_queue_wq_copy_desc_itmf(struct vnic_wq_copy *wq,
desc->u.itmf.tm_req = tm_req; /* SCSI Task Management request */
desc->u.itmf.t_tag = tm_id; /* tag of fcpio to be aborted */
desc->u.itmf._resvd = 0;
memcpy(desc->u.itmf.lun, lun, LUN_ADDRESS); /* LUN address */
if (lun)
memcpy(desc->u.itmf.lun, lun, LUN_ADDRESS); /* LUN address */
desc->u.itmf._resvd1 = 0;
hton24(desc->u.itmf.d_id, d_id); /* FC vNIC only: Target D_ID */
desc->u.itmf.r_a_tov = r_a_tov; /* FC vNIC only: R_A_TOV in msec */
@ -222,6 +223,35 @@ static inline void fnic_queue_rq_desc(struct vnic_rq *rq,
vnic_rq_post(rq, os_buf, 0, dma_addr, len);
}
static inline void fnic_queue_wq_copy_desc_nvme_io(struct vnic_wq_copy *wq,
u32 req_id,
u8 spl_flags,
u32 sgl_cnt,
u64 sgl_addr,
u8 flags, u8 *nvme_cmd_iu,
u16 cmd_len,
u32 data_len,
u32 d_id, u32 mss,
u32 ratov, u32 edtov)
{
struct fcpio_host_req *desc = vnic_wq_copy_next_desc(wq);
desc->hdr.type = FCPIO_NVME_CMD; /* enum fcpio_type */
desc->hdr.status = 0; /* header status entry */
desc->hdr._resvd = 0; /* reserved */
desc->hdr.tag.u.req_id = req_id; /* id for this request */
desc->u.nvcmnd.sgl_cnt = sgl_cnt; /* scatter-gather list count */
desc->u.nvcmnd.sgl_addr = sgl_addr; /* scatter-gather list addr */
desc->u.nvcmnd._resvd1 = 0; /* reserved: should be 0 */
desc->u.nvcmnd.flags = flags; /* command flags */
memset(desc->u.nvcmnd.nvme_cmnd, 0, NVME_CMD_SZ);
memcpy(desc->u.nvcmnd.nvme_cmnd, nvme_cmd_iu, cmd_len); /* SCSI CDB */
desc->u.nvcmnd.cmd_len = cmd_len;
desc->u.nvcmnd.data_len = data_len; /* length of data expected */
hton24(desc->u.nvcmnd.d_id, d_id); /* FC vNIC only: Target D_ID */
vnic_wq_copy_post(wq);
}
struct fnic;

View File

@ -96,7 +96,7 @@ static const char *fnic_ioreq_state_to_str(unsigned int state)
return fnic_ioreq_state_str[state];
}
static const char *fnic_fcpio_status_to_str(unsigned int status)
const char *fnic_fcpio_status_to_str(unsigned int status)
{
if (status >= ARRAY_SIZE(fcpio_status_str) || !fcpio_status_str[status])
return "unknown";
@ -145,10 +145,11 @@ unsigned int fnic_count_ioreqs(struct fnic *fnic, u32 portid)
{
unsigned int count = 0;
fnic_scsi_io_iter(fnic, fnic_count_portid_ioreqs_iter,
&portid, &count);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_scsi_io_iter(fnic, fnic_count_portid_ioreqs_iter,
&portid, &count);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"portid = 0x%x count = %u\n", portid, count);
return count;
}
@ -180,13 +181,13 @@ fnic_count_lun_ioreqs(struct fnic *fnic, struct scsi_device *scsi_device)
fnic_scsi_io_iter(fnic, fnic_count_lun_ioreqs_iter,
scsi_device, &count);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"lun = %p count = %u\n", scsi_device, count);
return count;
}
/* Free up Copy Wq descriptors. Called with copy_wq lock held */
static int free_wq_copy_descs(struct fnic *fnic, struct vnic_wq_copy *wq, unsigned int hwq)
int free_wq_copy_descs(struct fnic *fnic, struct vnic_wq_copy *wq, unsigned int hwq)
{
/* if no Ack received from firmware, then nothing to clean */
if (!fnic->fw_ack_recd[hwq])
@ -268,7 +269,7 @@ int fnic_fw_reset_handler(struct fnic *fnic)
if (!vnic_wq_copy_desc_avail(wq))
ret = -EAGAIN;
else {
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"ioreq_count: %u\n", ioreq_count);
fnic_queue_wq_copy_desc_fw_reset(wq, SCSI_NO_TAG);
atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs);
@ -283,11 +284,11 @@ int fnic_fw_reset_handler(struct fnic *fnic)
if (!ret) {
atomic64_inc(&fnic->fnic_stats.reset_stats.fw_resets);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"Issued fw reset\n");
} else {
fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"Failed to issue fw reset\n");
}
@ -326,13 +327,13 @@ int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id)
fc_id, gw_mac,
fnic->iport.fpma,
iport->r_a_tov, iport->e_d_tov);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"FLOGI FIP reg issued fcid: 0x%x src %p dest %p\n",
fc_id, fnic->iport.fpma, gw_mac);
} else {
fnic_queue_wq_copy_desc_flogi_reg(wq, SCSI_NO_TAG,
format, fc_id, gw_mac);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"FLOGI reg issued fcid 0x%x dest %p\n",
fc_id, gw_mac);
}
@ -413,7 +414,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
free_wq_copy_descs(fnic, wq, hwq);
if (unlikely(!vnic_wq_copy_desc_avail(wq))) {
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"fnic_queue_wq_copy_desc failure - no descriptors\n");
atomic64_inc(&misc_stats->io_cpwq_alloc_failures);
return SCSI_MLQUEUE_HOST_BUSY;
@ -478,7 +479,7 @@ enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
rport = starget_to_rport(scsi_target(sc->device));
if (!rport) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"returning DID_NO_CONNECT for IO as rport is NULL\n");
sc->result = DID_NO_CONNECT << 16;
done(sc);
@ -487,7 +488,7 @@ enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
ret = fc_remote_port_chkready(rport);
if (ret) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"rport is not ready\n");
atomic64_inc(&fnic_stats->misc_stats.tport_not_ready);
sc->result = ret;
@ -501,7 +502,7 @@ enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
if (iport->state != FNIC_IPORT_STATE_READY) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"returning DID_NO_CONNECT for IO as iport state: %d\n",
iport->state);
sc->result = DID_NO_CONNECT << 16;
@ -515,13 +516,13 @@ enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
rdd_data = rport->dd_data;
tport = rdd_data->tport;
if (!tport || (rdd_data->iport != iport)) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"dd_data not yet set in SCSI for rport portid: 0x%x\n",
rport->port_id);
tport = fnic_find_tport_by_fcid(iport, rport->port_id);
if (!tport) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"returning DID_BUS_BUSY for IO as tport not found for: 0x%x\n",
rport->port_id);
sc->result = DID_BUS_BUSY << 16;
@ -544,7 +545,7 @@ enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
if ((tport->state != FDLS_TGT_STATE_READY)
&& (tport->state != FDLS_TGT_STATE_ADISC)) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"returning DID_NO_CONNECT for IO as tport state: %d\n",
tport->state);
sc->result = DID_NO_CONNECT << 16;
@ -564,7 +565,7 @@ enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET))) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"fnic flags FW reset: 0x%lx. Returning SCSI_MLQUEUE_HOST_BUSY\n",
fnic->state_flags);
return SCSI_MLQUEUE_HOST_BUSY;
@ -704,7 +705,7 @@ enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
atomic_dec(&tport->in_flight);
if (lun0_delay) {
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"LUN0 delay\n");
mdelay(LUN0_DELAY_TIME);
}
@ -732,7 +733,10 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
atomic64_inc(&reset_stats->fw_reset_completions);
/* Clean up all outstanding io requests */
fnic_cleanup_io(fnic, SCSI_NO_TAG);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_cleanup_io(fnic, SCSI_NO_TAG);
else if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_cleanup_all_nvme_ios(fnic);
atomic64_set(&fnic->fnic_stats.fw_stats.active_fw_reqs, 0);
atomic64_set(&fnic->fnic_stats.io_stats.active_ios, 0);
@ -744,12 +748,12 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) {
/* Check status of reset completion */
if (!hdr_status) {
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"reset cmpl success\n");
/* Ready to send flogi out */
fnic->state = FNIC_IN_ETH_MODE;
} else {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"reset failed with header status: %s\n",
fnic_fcpio_status_to_str(hdr_status));
@ -758,7 +762,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
ret = -1;
}
} else {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"Unexpected state while processing reset completion: %s\n",
fnic_state_to_str(fnic->state));
atomic64_inc(&reset_stats->fw_reset_failures);
@ -810,19 +814,18 @@ static int fnic_fcpio_flogi_reg_cmpl_handler(struct fnic *fnic,
/* Check flogi registration completion status */
if (!hdr_status) {
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"FLOGI reg succeeded\n");
fnic->state = FNIC_IN_FC_MODE;
} else {
FNIC_SCSI_DBG(KERN_DEBUG,
fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"fnic flogi reg failed: %s\n",
fnic_fcpio_status_to_str(hdr_status));
fnic->state = FNIC_IN_ETH_MODE;
ret = -1;
}
} else {
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Unexpected fnic state %s while"
" processing flogi reg completion\n",
fnic_state_to_str(fnic->state));
@ -895,7 +898,7 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic,
spin_unlock_irqrestore(&fnic->wq_copy_lock[wq_index], flags);
FNIC_TRACE(fnic_fcpio_ack_handler,
fnic->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3],
fnic->fnic_num, 0, 0, ox_id_tag[2], ox_id_tag[3],
ox_id_tag[4], ox_id_tag[5]);
}
@ -933,19 +936,19 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
hwq = blk_mq_unique_tag_to_hwq(mqtag);
if (hwq != cq_index) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hdr status: %s icmnd completion on the wrong queue\n",
fnic_fcpio_status_to_str(hdr_status));
}
if (tag >= fnic->fnic_max_tag_id) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hdr status: %s Out of range tag\n",
fnic_fcpio_status_to_str(hdr_status));
return;
@ -957,7 +960,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
if (!sc) {
atomic64_inc(&fnic_stats->io_stats.sc_null);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"icmnd_cmpl sc is null - "
"hdr status = %s tag = 0x%x desc = 0x%p\n",
fnic_fcpio_status_to_str(hdr_status), id, desc);
@ -985,7 +988,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
atomic64_inc(&fnic_stats->io_stats.ioreq_null);
fnic_priv(sc)->flags |= FNIC_IO_REQ_NULL;
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"icmnd_cmpl io_req is null - "
"hdr status = %s tag = 0x%x sc 0x%p\n",
fnic_fcpio_status_to_str(hdr_status), id, sc);
@ -1012,7 +1015,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
if(FCPIO_ABORTED == hdr_status)
fnic_priv(sc)->flags |= FNIC_IO_ABORTED;
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"icmnd_cmpl abts pending "
"hdr status = %s tag = 0x%x sc = 0x%p "
"scsi_status = %x residual = %d\n",
@ -1044,7 +1047,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
if (icmnd_cmpl->scsi_status == SAM_STAT_TASK_SET_FULL)
atomic64_inc(&fnic_stats->misc_stats.queue_fulls);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"xfer_len: %llu", xfer_len);
break;
@ -1107,7 +1110,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
if (hdr_status != FCPIO_SUCCESS) {
atomic64_inc(&fnic_stats->io_stats.io_failures);
shost_printk(KERN_ERR, fnic->host, "hdr status = %s\n",
fnic_printk(KERN_ERR, fnic, "hdr status = %s\n",
fnic_fcpio_status_to_str(hdr_status));
}
@ -1200,27 +1203,27 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
hwq = blk_mq_unique_tag_to_hwq(id & FNIC_TAG_MASK);
if (hwq != cq_index) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hdr status: %s ITMF completion on the wrong queue\n",
fnic_fcpio_status_to_str(hdr_status));
}
if (tag > fnic->fnic_max_tag_id) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hdr status: %s Tag out of range\n",
fnic_fcpio_status_to_str(hdr_status));
return;
} else if ((tag == fnic->fnic_max_tag_id) && !(id & FNIC_TAG_DEV_RST)) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hdr status: %s Tag out of range\n",
fnic_fcpio_status_to_str(hdr_status));
return;
@ -1243,7 +1246,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
if (!sc) {
atomic64_inc(&fnic_stats->io_stats.sc_null);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n",
fnic_fcpio_status_to_str(hdr_status), tag);
return;
@ -1255,7 +1258,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
atomic64_inc(&fnic_stats->io_stats.ioreq_null);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
fnic_priv(sc)->flags |= FNIC_IO_ABT_TERM_REQ_NULL;
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"itmf_cmpl io_req is null - "
"hdr status = %s tag = 0x%x sc 0x%p\n",
fnic_fcpio_status_to_str(hdr_status), tag, sc);
@ -1266,7 +1269,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
if ((id & FNIC_TAG_ABORT) && (id & FNIC_TAG_DEV_RST)) {
/* Abort and terminate completion of device reset req */
/* REVISIT : Add asserts about various flags */
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Abt/term completion received\n",
hwq, mqtag, tag,
fnic_fcpio_status_to_str(hdr_status));
@ -1278,7 +1281,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
} else if (id & FNIC_TAG_ABORT) {
/* Completion of abort cmd */
shost_printk(KERN_DEBUG, fnic->host,
fnic_printk(KERN_DEBUG, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x Abort header status: %s\n",
hwq, mqtag, tag,
fnic_fcpio_status_to_str(hdr_status));
@ -1293,7 +1296,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
&term_stats->terminate_fw_timeouts);
break;
case FCPIO_ITMF_REJECTED:
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"abort reject recd. id %d\n",
(int)(id & FNIC_TAG_MASK));
break;
@ -1328,7 +1331,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
if (!(fnic_priv(sc)->flags & (FNIC_IO_ABORTED | FNIC_IO_DONE)))
atomic64_inc(&misc_stats->no_icmnd_itmf_cmpls);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"abts cmpl recd. id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
fnic_fcpio_status_to_str(hdr_status));
@ -1341,11 +1344,11 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
if (io_req->abts_done) {
complete(io_req->abts_done);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
shost_printk(KERN_INFO, fnic->host,
fnic_printk(KERN_INFO, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x Waking up abort thread\n",
hwq, mqtag, tag);
} else {
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Completing IO\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@ -1376,7 +1379,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
}
} else if (id & FNIC_TAG_DEV_RST) {
/* Completion of device reset */
shost_printk(KERN_INFO, fnic->host,
fnic_printk(KERN_INFO, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x DR hst: %s\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@ -1388,7 +1391,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
sc->device->host->host_no, id, sc,
jiffies_to_msecs(jiffies - start_time),
desc, 0, fnic_flags_and_state(sc));
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Terminate pending\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@ -1401,7 +1404,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
sc->device->host->host_no, id, sc,
jiffies_to_msecs(jiffies - start_time),
desc, 0, fnic_flags_and_state(sc));
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"dev reset cmpl recd after time out. "
"id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
@ -1410,7 +1413,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
}
fnic_priv(sc)->state = FNIC_IOREQ_CMD_COMPLETE;
fnic_priv(sc)->flags |= FNIC_DEV_RST_DONE;
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x hst: %s DR completion received\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@ -1419,7 +1422,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
} else {
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"%s: Unexpected itmf io state: hwq: %d tag 0x%x %s\n",
__func__, hwq, id, fnic_ioreq_state_to_str(fnic_priv(sc)->state));
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
@ -1443,6 +1446,7 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */
case FCPIO_FLOGI_FIP_REG_CMPL: /* fw completed flogi_fip_reg */
case FCPIO_RESET_CMPL: /* fw completed reset */
case FCPIO_NVME_ERSP_HW_CMPL: /* fw completed NVMe ERSP */
atomic64_dec(&fnic->fnic_stats.fw_stats.active_fw_reqs);
break;
default:
@ -1457,11 +1461,22 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
break;
case FCPIO_ICMND_CMPL: /* fw completed a command */
fnic_fcpio_icmnd_cmpl_handler(fnic, cq_index, desc);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_fcpio_icmnd_cmpl_handler(fnic, cq_index, desc);
else if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_fcpio_nvme_fast_cmpl_handler(fnic, desc);
break;
case FCPIO_NVME_ERSP_HW_CMPL: /* fw completed NVMe ERSP */
if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_fcpio_ersp_cmpl_handler(fnic, desc, 1);
break;
case FCPIO_ITMF_CMPL: /* fw completed itmf (abort cmd, lun reset)*/
fnic_fcpio_itmf_cmpl_handler(fnic, cq_index, desc);
if (IS_FNIC_FCP_INITIATOR(fnic))
fnic_fcpio_itmf_cmpl_handler(fnic, cq_index, desc);
else if (IS_FNIC_NVME_INITIATOR(fnic))
nvfnic_fcpio_nvme_itmf_cmpl_handler(fnic, desc);
break;
case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */
@ -1474,7 +1489,7 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
break;
default:
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"firmware completion type %d\n",
desc->hdr.type);
break;
@ -1535,7 +1550,7 @@ static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d mqtag: 0x%x tag: 0x%x flags: 0x%x No ioreq. Returning\n",
hwq, mqtag, tag, fnic_priv(sc)->flags);
return true;
@ -1573,7 +1588,7 @@ static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
mempool_free(io_req, fnic->io_req_pool);
sc->result = DID_TRANSPORT_DISRUPTED << 16;
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"mqtag: 0x%x tag: 0x%x sc: 0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
mqtag, tag, sc, (jiffies - start_time));
@ -1605,7 +1620,7 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
struct scsi_cmnd *sc = NULL;
io_count = fnic_count_all_ioreqs(fnic);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Outstanding ioreq count: %d active io count: %lld Waiting\n",
io_count,
atomic64_read(&fnic->fnic_stats.io_stats.active_ios));
@ -1630,7 +1645,7 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
while ((io_count = fnic_count_all_ioreqs(fnic))) {
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Outstanding ioreq count: %d active io count: %lld Waiting\n",
io_count,
atomic64_read(&fnic->fnic_stats.io_stats.active_ios));
@ -1650,6 +1665,15 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
unsigned long start_time = 0;
uint16_t hwq;
/*
* Clean up outstanding NVMe requests if firmware reset did not
* complete them before WQ copy cleanup.
*/
if (IS_FNIC_NVME_INITIATOR(fnic)) {
nvfnic_cleanup_all_nvme_ios(fnic);
return;
}
/* get the tag reference */
fcpio_tag_id_dec(&desc->hdr.tag, &id);
id &= FNIC_TAG_MASK;
@ -1686,7 +1710,7 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
wq_copy_cleanup_scsi_cmd:
sc->result = DID_NO_CONNECT << 16;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num, "wq_copy_cleanup_handler:"
FNIC_SCSI_DBG(KERN_DEBUG, fnic, "wq_copy_cleanup_handler:"
" DID_NO_CONNECT\n");
FNIC_TRACE(fnic_wq_copy_cleanup_handler,
@ -1730,7 +1754,7 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic_dec(&fnic->in_flight);
atomic_dec(&tport->in_flight);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"fnic_queue_abort_io_req: failure: no descriptors\n");
atomic64_inc(&misc_stats->abts_cpwq_alloc_failures);
return 1;
@ -1775,7 +1799,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
hwq = blk_mq_unique_tag_to_hwq(abt_tag);
if (!sc) {
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"sc is NULL abt_tag: 0x%x hwq: %d\n", abt_tag, hwq);
return true;
}
@ -1789,7 +1813,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
!(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED)) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d abt_tag: 0x%x flags: 0x%x Device reset is not pending\n",
hwq, abt_tag, fnic_priv(sc)->flags);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
@ -1806,16 +1830,16 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
}
if (io_req->abts_done) {
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"fnic_rport_exch_reset: io_req->abts_done is set state is %s\n",
fnic_ioreq_state_to_str(fnic_priv(sc)->state));
}
if (!(fnic_priv(sc)->flags & FNIC_IO_ISSUED)) {
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"rport_exch_reset IO not yet issued %p abt_tag 0x%x",
sc, abt_tag);
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"flags %x state %d\n", fnic_priv(sc)->flags,
fnic_priv(sc)->state);
}
@ -1826,13 +1850,13 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
atomic64_inc(&reset_stats->device_reset_terminates);
abt_tag |= FNIC_TAG_DEV_RST;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"dev reset sc 0x%p\n", sc);
}
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"fnic_rport_exch_reset: dev rst sc 0x%p\n", sc);
WARN_ON_ONCE(io_req->abts_done);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"fnic_rport_reset_exch: Issuing abts\n");
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
@ -1850,7 +1874,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
* lun reset
*/
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d abt_tag: 0x%x flags: 0x%x Queuing abort failed\n",
hwq, abt_tag, fnic_priv(sc)->flags);
if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING)
@ -1881,7 +1905,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
.term_cnt = 0,
};
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"fnic rport exchange reset for tport: 0x%06x\n",
port_id);
@ -1889,7 +1913,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
return;
io_count = fnic_count_ioreqs(fnic, port_id);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Starting terminates: rport:0x%x portid-io-count: %d active-io-count: %lld\n",
port_id, io_count,
atomic64_read(&fnic->fnic_stats.io_stats.active_ios));
@ -1915,7 +1939,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
while ((io_count = fnic_count_ioreqs(fnic, port_id)))
schedule_timeout(msecs_to_jiffies(1000));
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"rport: 0x%x remaining portid-io-count: %d ",
port_id, io_count);
}
@ -2040,10 +2064,10 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
tport = rdd_data->tport;
if (!tport) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"Abort cmd called after tport delete! rport fcid: 0x%x",
rport->port_id);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"lun: %llu hwq: 0x%x mqtag: 0x%x Op: 0x%x flags: 0x%x\n",
sc->device->lun, hwq, mqtag,
sc->cmnd[0], fnic_priv(sc)->flags);
@ -2052,18 +2076,18 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
goto fnic_abort_cmd_end;
}
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"Abort cmd called rport fcid: 0x%x lun: %llu hwq: 0x%x mqtag: 0x%x",
rport->port_id, sc->device->lun, hwq, mqtag);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"Op: 0x%x flags: 0x%x\n",
sc->cmnd[0],
fnic_priv(sc)->flags);
if (iport->state != FNIC_IPORT_STATE_READY) {
atomic64_inc(&fnic_stats->misc_stats.iport_not_ready);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"iport NOT in READY state");
ret = FAILED;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
@ -2072,7 +2096,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
if ((tport->state != FDLS_TGT_STATE_READY) &&
(tport->state != FDLS_TGT_STATE_ADISC)) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"tport state: %d\n", tport->state);
ret = FAILED;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
@ -2123,7 +2147,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
else
atomic64_inc(&abts_stats->abort_issued_greater_than_60_sec);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"CDB Opcode: 0x%02x Abort issued time: %lu msec\n",
sc->cmnd[0], abt_issued_time);
/*
@ -2214,7 +2238,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
if (!(fnic_priv(sc)->flags & (FNIC_IO_ABORTED | FNIC_IO_DONE))) {
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"Issuing host reset due to out of order IO\n");
ret = FAILED;
@ -2262,7 +2286,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
(u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
fnic_flags_and_state(sc));
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Returning from abort cmd type %x %s\n", task_req,
(ret == SUCCESS) ?
"SUCCESS" : "FAILED");
@ -2303,7 +2327,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
free_wq_copy_descs(fnic, wq, hwq);
if (!vnic_wq_copy_desc_avail(wq)) {
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"queue_dr_io_req failure - no descriptors\n");
atomic64_inc(&misc_stats->devrst_cpwq_alloc_failures);
ret = -EAGAIN;
@ -2371,7 +2395,7 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
* Found IO that is still pending with firmware and
* belongs to the LUN that we are resetting
*/
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Found IO in %s on lun\n",
fnic_ioreq_state_to_str(fnic_priv(sc)->state));
@ -2381,14 +2405,14 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
}
if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
(!(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED))) {
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"dev rst not pending sc 0x%p\n", sc);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
return true;
}
if (io_req->abts_done)
shost_printk(KERN_ERR, fnic->host,
fnic_printk(KERN_ERR, fnic,
"%s: io_req->abts_done is set state is %s\n",
__func__, fnic_ioreq_state_to_str(fnic_priv(sc)->state));
old_ioreq_state = fnic_priv(sc)->state;
@ -2404,7 +2428,7 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
BUG_ON(io_req->abts_done);
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"dev rst sc 0x%p\n", sc);
}
@ -2426,7 +2450,7 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc, void *data)
fnic_priv(sc)->state = old_ioreq_state;
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
iter_data->ret = FAILED;
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"hwq: %d abt_tag: 0x%lx Abort could not be queued\n",
hwq, abt_tag);
return false;
@ -2518,7 +2542,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
ret = 1;
clean_pending_aborts_end:
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"exit status: %d\n", ret);
return ret;
}
@ -2568,7 +2592,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
rport = starget_to_rport(scsi_target(sc->device));
spin_lock_irqsave(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"fcid: 0x%x lun: %llu hwq: %d mqtag: 0x%x flags: 0x%x Device reset\n",
rport->port_id, sc->device->lun, hwq, mqtag,
fnic_priv(sc)->flags);
@ -2576,7 +2600,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
rdd_data = rport->dd_data;
tport = rdd_data->tport;
if (!tport) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"Dev rst called after tport delete! rport fcid: 0x%x lun: %llu\n",
rport->port_id, sc->device->lun);
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
@ -2585,7 +2609,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
if (iport->state != FNIC_IPORT_STATE_READY) {
atomic64_inc(&fnic_stats->misc_stats.iport_not_ready);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"iport NOT in READY state");
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
goto fnic_device_reset_end;
@ -2593,7 +2617,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
if ((tport->state != FDLS_TGT_STATE_READY) &&
(tport->state != FDLS_TGT_STATE_ADISC)) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"tport state: %d\n", tport->state);
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
goto fnic_device_reset_end;
@ -2656,7 +2680,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
fnic_priv(sc)->lr_status = FCPIO_INVALID_CODE;
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num, "TAG %x\n", mqtag);
FNIC_SCSI_DBG(KERN_DEBUG, fnic, "TAG %x\n", mqtag);
/*
* issue the device reset, if enqueue failed, clean up the ioreq
@ -2707,13 +2731,13 @@ int fnic_device_reset(struct scsi_cmnd *sc)
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"io_req is null mqtag 0x%x sc 0x%p\n", mqtag, sc);
goto fnic_device_reset_end;
}
if (exit_dr) {
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"Host reset called for fnic. Exit device reset\n");
io_req->dr_done = NULL;
goto fnic_device_reset_clean;
@ -2728,7 +2752,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
*/
if (status == FCPIO_INVALID_CODE) {
atomic64_inc(&reset_stats->device_reset_timeouts);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Device reset timed out\n");
fnic_priv(sc)->flags |= FNIC_DEV_RST_TIMED_OUT;
int_to_scsilun(sc->device->lun, &fc_lun);
@ -2740,8 +2764,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
/* Completed, but not successful, clean up the io_req, return fail */
if (status != FCPIO_SUCCESS) {
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_DEBUG,
fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Device reset completed - failed\n");
io_req = fnic_priv(sc)->io_req;
goto fnic_device_reset_clean;
@ -2757,7 +2780,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
if (fnic_clean_pending_aborts(fnic, sc, new_sc)) {
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Device reset failed: Cannot abort all IOs\n");
goto fnic_device_reset_clean;
}
@ -2811,13 +2834,13 @@ int fnic_device_reset(struct scsi_cmnd *sc)
ret = FAILED;
break;
}
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"Cannot clean up all IOs for the LUN\n");
schedule_timeout(msecs_to_jiffies(1000));
count++;
}
FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_DEBUG, fnic,
"Returning from device reset %s\n",
(ret == SUCCESS) ?
"SUCCESS" : "FAILED");
@ -2852,13 +2875,13 @@ void fnic_reset(struct Scsi_Host *shost)
fnic = *((struct fnic **) shost_priv(shost));
reset_stats = &fnic->fnic_stats.reset_stats;
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"Issuing fnic reset\n");
atomic64_inc(&reset_stats->fnic_resets);
fnic_post_flogo_linkflap(fnic);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"Returning from fnic reset");
atomic64_inc(&reset_stats->fnic_reset_completions);
@ -2869,7 +2892,7 @@ int fnic_issue_fc_host_lip(struct Scsi_Host *shost)
int ret = 0;
struct fnic *fnic = *((struct fnic **) shost_priv(shost));
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"FC host lip issued");
ret = fnic_host_reset(shost);
@ -2895,7 +2918,7 @@ int fnic_host_reset(struct Scsi_Host *shost)
spin_lock_irqsave(&fnic->fnic_lock, flags);
if (fnic->reset_in_progress == IN_PROGRESS) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_WARNING, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_WARNING, fnic,
"Firmware reset in progress. Skipping another host reset\n");
return SUCCESS;
}
@ -2933,7 +2956,7 @@ int fnic_host_reset(struct Scsi_Host *shost)
}
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"host reset return status: %d\n", ret);
return ret;
}
@ -2973,7 +2996,7 @@ static bool fnic_abts_pending_iter(struct scsi_cmnd *sc, void *data)
* Found IO that is still pending with firmware and
* belongs to the LUN that we are resetting
*/
FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_INFO, fnic,
"hwq: %d tag: 0x%x Found IO in state: %s on lun\n",
hwq, tag,
fnic_ioreq_state_to_str(fnic_priv(sc)->state));
@ -3027,7 +3050,7 @@ int fnic_eh_host_reset_handler(struct scsi_cmnd *sc)
struct Scsi_Host *shost = sc->device->host;
struct fnic *fnic = *((struct fnic **) shost_priv(shost));
FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
FNIC_SCSI_DBG(KERN_ERR, fnic,
"SCSI error handling: fnic host reset");
ret = fnic_host_reset(shost);

View File

@ -29,6 +29,15 @@ struct io_path_stats {
atomic64_t io_greater_than_30000_msec;
atomic64_t current_max_io_time;
atomic64_t ios[FNIC_MQ_MAX_QUEUES];
atomic64_t nvme_io_reqs_rcvd;
atomic64_t nvme_ios_queued_for_rsp;
atomic64_t nvme_io_rsps_unqueued;
atomic64_t nvme_io_rsps_sending;
atomic64_t nvme_io_rsps_sent;
atomic64_t nvme_num_ios_in_waitq;
atomic64_t nvme_ios_in_waitq_3000_msec;
atomic64_t nvme_ios_in_waitq_max_time;
};
struct abort_stats {
@ -151,6 +160,17 @@ struct fnic_iport_stats {
atomic64_t unsupported_frames_dropped;
};
struct nvme_host_statistics {
atomic64_t nvme_input_requests;
atomic64_t nvme_output_requests;
atomic64_t nvme_control_requests;
atomic64_t nvme_ersps;
atomic64_t nvme_ls_requests;
atomic64_t nvme_ls_responses;
atomic64_t nvme_ls_aborts;
atomic64_t nvme_ls_abort_responses;
};
struct fnic_stats {
struct stats_timestamps stats_timestamps;
struct io_path_stats io_stats;
@ -161,6 +181,7 @@ struct fnic_stats {
struct vlan_stats vlan_stats;
struct fc_host_statistics host_stats;
struct misc_stats misc_stats;
struct nvme_host_statistics nvme_stats;
};
struct stats_debug_info {
@ -170,6 +191,13 @@ struct stats_debug_info {
int buffer_len;
};
struct fnic_nvmef_info {
char *info_buffer;
void *i_private;
int buf_size;
int buffer_len;
};
int fnic_get_stats_data(struct stats_debug_info *, struct fnic_stats *);
const char *fnic_role_to_str(unsigned int role);
#endif /* _FNIC_STATS_H_ */

View File

@ -31,7 +31,8 @@ int fnic_fc_trace_cleared = 1;
static DEFINE_SPINLOCK(fnic_fc_trace_lock);
static const char * const fnic_role_str[] = {
[FNIC_ROLE_FCP_INITIATOR] = "FCP_Initiator",
[FNIC_ROLE_FCP_INITIATOR] = "FCP_Initiator",
[FNIC_ROLE_NVME_INITIATOR] = "NVMeF_Initiator",
};
const char *fnic_role_to_str(unsigned int role)

View File

@ -430,7 +430,7 @@ struct vnic_devcmd_notify {
struct vnic_devcmd_provinfo {
u8 oui[3];
u8 type;
u8 data[];
u8 data[0];
};
/*