Subject: [PATCH 00/14] Introduce support for feature Fabric Discovery and

Hi Martin, reviewers,

This cover letter describes the feature: add support for Fabric Discovery
and Login Services (FDLS) to fnic driver.

This functionality is needed to support port channel RSCN (PC-RSCN)
handling and serves as a base to create FC-NVME initiators
(planned later), and eCPU handling (planned later).

It is used to discover the fabric and target ports associated with the
fabric.
It will then login to the target ports that are zoned to it.
The driver uses the tport structure presented by FDLS.

Port channel RSCN is a Cisco vendor specific RSCN
event. It is applicable only to Cisco UCS fabrics.

In cases where the eCPU in the UCS VIC (Unified Computing Services
Virtual Interface Card) hangs, a fabric log out is sent to the fabric.
Upon successful log out from the fabric, the IO path is failed over
to a new path.

Generally from a feature perspective, the code is divided into adding
support for this functionality initially. Then, code has been added to
modify the IO path and interfaces. Finally, support for port channel RSCN
handling has been added.

Here are the headers of some of the salient patches:

o add headers and definitions for FDLS
o add support for fabric based solicited requests and responses
o add support for target based solicited requests and responses
o add support for unsolicited requests and responses
o add support for FDMI
o add support for FIP
o add functionality in fnic to support FDLS
o modify IO path to use FDLS and tport
o modify fnic interfaces to use FDLS
o add support to handle port channel RSCN

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. There are some unused function
warnings, but since the function calls happen in later patches, those
warnings go away.

This patchset 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. Perform zone in zone out testing in a loop: remove a target
port from the zone, add it to the zone in a loop. 1000+ iterations
of this test have been successful.
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. Module load/unload test.
o. Repeat the above tests with 1 queue and 64 queues.
All tests were successful.

Please consider this patch series for the next merge window.

Thanks and regards,
Karan

Karan Tilak Kumar (14):
scsi: fnic: Replace shost_printk with pr_info/pr_err
scsi: fnic: Add headers and definitions for FDLS
scsi: fnic: Add support for fabric based solicited requests and
responses
scsi: fnic: Add support for target based solicited requests and
responses
scsi: fnic: Add support for unsolicited requests and responses
scsi: fnic: Add and integrate support for FDMI
scsi: fnic: Add and integrate support for FIP
scsi: fnic: Add functionality in fnic to support FDLS
scsi: fnic: Modify IO path to use FDLS
scsi: fnic: Modify fnic interfaces to use FDLS
scsi: fnic: Add stats and related functionality
scsi: fnic: Code cleanup
scsi: fnic: Add support to handle port channel RSCN
scsi: fnic: Increment driver version

drivers/scsi/fnic/Makefile | 5 +-
drivers/scsi/fnic/fdls_disc.c | 3942 +++++++++++++++++++++
drivers/scsi/fnic/fdls_fc.h | 548 +++
drivers/scsi/fnic/fip.c | 900 +++++
drivers/scsi/fnic/fip.h | 341 ++
drivers/scsi/fnic/fnic.h | 216 +-
drivers/scsi/fnic/fnic_attrs.c | 12 +-
drivers/scsi/fnic/fnic_debugfs.c | 30 +-
drivers/scsi/fnic/fnic_fcs.c | 1775 ++++------
drivers/scsi/fnic/fnic_fdls.h | 371 ++
drivers/scsi/fnic/fnic_io.h | 14 +-
drivers/scsi/fnic/fnic_isr.c | 28 +-
drivers/scsi/fnic/fnic_main.c | 670 ++--
drivers/scsi/fnic/fnic_pci_subsys_devid.c | 133 +
drivers/scsi/fnic/fnic_res.c | 76 +-
drivers/scsi/fnic/fnic_scsi.c | 1406 +++++---
drivers/scsi/fnic/fnic_stats.h | 48 +-
drivers/scsi/fnic/fnic_trace.c | 83 +-
18 files changed, 8640 insertions(+), 1958 deletions(-)
create mode 100644 drivers/scsi/fnic/fdls_disc.c
create mode 100644 drivers/scsi/fnic/fdls_fc.h
create mode 100644 drivers/scsi/fnic/fip.c
create mode 100644 drivers/scsi/fnic/fip.h
create mode 100644 drivers/scsi/fnic/fnic_fdls.h
create mode 100644 drivers/scsi/fnic/fnic_pci_subsys_devid.c

--
2.31.1



Subject: [PATCH 04/14] scsi: fnic: Add support for target based solicited requests and responses

Add support for target based solicited requests and responses.
Add support for tport definitions and processing.
Add support for restarting the IT nexus.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fdls_disc.c | 1540 +++++++++++++++++++++++++++++++--
drivers/scsi/fnic/fnic.h | 6 +
drivers/scsi/fnic/fnic_fdls.h | 4 +
3 files changed, 1473 insertions(+), 77 deletions(-)

diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
index 22a2d0c1c78f..d920202d413d 100644
--- a/drivers/scsi/fnic/fdls_disc.c
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -11,6 +11,8 @@
#include <scsi/fc/fc_fcp.h>
#include <linux/utsname.h>

+#define FC_FC4_TYPE_SCSI 0x08
+
static void fdls_send_rpn_id(struct fnic_iport_s *iport);

/* Frame initialization */
@@ -59,6 +61,19 @@ struct fc_rpn_id_s fnic_rpn_id_req = {
.command = FC_CT_RPN_CMD}
};

+/*
+ * Variables:
+ * did, sid, oxid
+ */
+struct fc_els_prli_s fnic_prli_req = {
+ .fchdr = {.r_ctl = 0x22, .type = 0x01,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .rx_id = 0xFFFF},
+ .command = FC_ELS_PRLI_REQ,
+ .page_len = 16,
+ .payload_len = 0x1400,
+ .sp = {.type = 0x08, .flags = 0x0020, .csp = 0xA2000000}
+};
+
/*
* Variables:
* fh_s_id, port_id, port_name
@@ -123,11 +138,51 @@ struct fc_logo_req_s fnic_logo_req = {
#define RETRIES_EXHAUSTED(iport) \
(iport->fabric.retry_counter == FABRIC_LOGO_MAX_RETRY)

+#define FNIC_TPORT_MAX_NEXUS_RESTART (8)
+
+/* Private Functions */
static void fdls_process_flogi_rsp(struct fnic_iport_s *iport,
struct fc_hdr_s *fchdr, void *rx_frame);
static void fnic_fdls_start_plogi(struct fnic_iport_s *iport);
+static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
+ uint32_t fcid,
+ uint64_t wwpn);
+static void fdls_target_restart_nexus(struct fnic_tport_s *tport);
+static void fdls_start_tport_timer(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport, int timeout);
+
static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
int timeout);
+static void fdls_tport_timer_callback(struct timer_list *t);
+
+static uint16_t fdls_alloc_tgt_oxid(struct fnic_iport_s *iport,
+ uint16_t base)
+{
+ int i;
+ int start, end;
+
+ start = base - FDLS_PLOGI_OXID_BASE;
+ end = start + FDLS_TGT_OXID_BLOCK_SZ;
+
+ for (i = start; i < end; i++) {
+ if (iport->tgt_oxid_pool[i] == 0) {
+ iport->tgt_oxid_pool[i] = 1;
+ return (i + FDLS_PLOGI_OXID_BASE);
+ }
+ }
+ return 0xFFFF;
+}
+
+static void fdls_free_tgt_oxid(struct fnic_iport_s *iport, uint16_t oxid)
+{
+ struct fnic *fnic = iport->fnic;
+
+ if (iport->tgt_oxid_pool[oxid - FDLS_PLOGI_OXID_BASE] != 1) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Freeing unused OXID: 0x%x", oxid);
+ }
+ iport->tgt_oxid_pool[oxid - FDLS_PLOGI_OXID_BASE] = 0;
+}

static void
fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
@@ -153,6 +208,63 @@ fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
"fabric timer is %d ", timeout);
}

+static void
+fdls_start_tport_timer(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport, int timeout)
+{
+ u64 fabric_tov;
+ struct fnic *fnic = iport->fnic;
+
+ if (tport->timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport fcid 0x%x: Canceling disc timer\n",
+ tport->fcid);
+ fnic_del_tport_timer_sync();
+ tport->timer_pending = 0;
+ }
+
+ if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED))
+ tport->retry_counter++;
+
+ fabric_tov = jiffies + msecs_to_jiffies(timeout);
+ mod_timer(&tport->retry_timer, round_jiffies(fabric_tov));
+ tport->timer_pending = 1;
+}
+
+void
+fdls_send_tport_abts(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport)
+{
+ uint8_t s_id[3];
+ uint8_t d_id[3];
+ struct fnic *fnic = iport->fnic;
+
+ struct fc_hdr_s fc_abts_s = {
+ .r_ctl = 0x81, /* ABTS */
+ .cs_ctl = 0x00, .type = 0x00, .f_ctl = FNIC_REQ_ABTS_FCTL, .seq_id =
+ 0x00, .df_ctl = 0x00, .seq_cnt = 0x0000, .rx_id = 0xFFFF,
+ .param = 0x00000000, /* bit:0 = 0 Abort a exchange */
+ };
+
+ struct fc_hdr_s *pfc_abts = &fc_abts_s;
+
+ hton24(s_id, iport->fcid);
+ hton24(d_id, tport->fcid);
+ FNIC_SET_S_ID(pfc_abts, s_id);
+ FNIC_SET_D_ID(pfc_abts, d_id);
+ tport->flags |= FNIC_FDLS_TGT_ABORT_ISSUED;
+
+ fc_abts_s.ox_id = tport->oxid_used;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS sending tport abts: tport->state: %d ",
+ tport->state);
+
+ fnic_send_fcoe_frame(iport, &fc_abts_s, sizeof(struct fc_hdr_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_tport_timer(iport, tport, 2 * iport->r_a_tov);
+}
+
static void fdls_send_fabric_abts(struct fnic_iport_s *iport)
{
uint8_t fcid[3];
@@ -338,6 +450,169 @@ static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state)
fdls_set_state((&iport->fabric), fdls_state);
}

+static void
+fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
+{
+ struct fc_els_adisc_s adisc;
+ uint8_t s_id[3];
+ uint8_t d_id[3];
+ uint16_t oxid;
+ struct fnic *fnic = iport->fnic;
+
+ memset(&adisc, 0, sizeof(struct fc_els_adisc_s));
+ adisc.fchdr.r_ctl = 0x22;
+ adisc.fchdr.type = 0x01;
+ adisc.fchdr.f_ctl = FNIC_ELS_REQ_FCTL;
+ adisc.fchdr.rx_id = 0xFFFF;
+
+ hton24(s_id, iport->fcid);
+ hton24(d_id, tport->fcid);
+ FNIC_SET_S_ID((&adisc.fchdr), s_id);
+ FNIC_SET_D_ID((&adisc.fchdr), d_id);
+
+ oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_ADISC_OXID_BASE));
+ if (oxid == 0xFFFF) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to allocate OXID to send ADISC %p", iport);
+ return;
+ }
+
+ tport->oxid_used = oxid;
+ tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
+
+ FNIC_SET_OX_ID((&adisc.fchdr), oxid);
+ FNIC_SET_NPORT_NAME(adisc, iport->wwpn);
+ FNIC_SET_NODE_NAME(adisc, iport->wwnn);
+
+ memcpy(adisc.fcid, s_id, 3);
+ adisc.command = FNIC_ELS_ADISC_REQ;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "sending ADISC to tgt fcid: 0x%x", tport->fcid);
+
+ fnic_send_fcoe_frame(iport, &adisc, sizeof(struct fc_els_adisc_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_tport_timer(iport, tport, 2 * iport->e_d_tov);
+}
+
+void fdls_delete_tport(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport)
+{
+ struct fnic_tport_event_s *tport_del_evt;
+ struct fnic *fnic = iport->fnic;
+
+ if ((tport->state == FDLS_TGT_STATE_OFFLINING)
+ || (tport->state == FDLS_TGT_STATE_OFFLINE))
+ return;
+
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINING);
+ /*
+ * By setting this flag, the tport will not be seen in a look-up
+ * in an RSCN. Even if we move to multithreaded model, this tport
+ * will be destroyed and a new RSCN will have to create a new one
+ */
+ tport->flags |= FNIC_FDLS_TPORT_TERMINATING;
+
+ if (tport->timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport fcid 0x%x: Canceling disc timer\n",
+ tport->fcid);
+ fnic_del_tport_timer_sync();
+ tport->timer_pending = 0;
+ }
+
+ if (IS_FNIC_FCP_INITIATOR(fnic)) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ fnic_rport_exch_reset(iport->fnic, tport->fcid);
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+
+ if (tport->flags & FNIC_FDLS_SCSI_REGISTERED) {
+ tport_del_evt =
+ kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
+ if (!tport_del_evt) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to allocate memory for tport fcid: 0x%0x\n",
+ tport->fcid);
+ return;
+ }
+ tport_del_evt->event = TGT_EV_RPORT_DEL;
+ tport_del_evt->arg1 = (void *) tport;
+ list_add_tail(&tport_del_evt->links, &fnic->tport_event_list);
+ queue_work(fnic_event_queue, &fnic->tport_work);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport 0x%x not reg with scsi_transport. Freeing locally",
+ tport->fcid);
+ list_del(&tport->links);
+ kfree(tport);
+ }
+ }
+}
+
+static void
+fdls_send_tgt_plogi(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
+{
+ struct fc_els_s plogi;
+ uint8_t s_id[3];
+ uint8_t d_id[3];
+ uint16_t oxid;
+ struct fnic *fnic = iport->fnic;
+ uint32_t timeout;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Send tgt PLOGI to fcid: 0x%x", tport->fcid);
+
+ memcpy(&plogi, &fnic_plogi_req, sizeof(struct fc_els_s));
+
+ hton24(s_id, iport->fcid);
+ hton24(d_id, tport->fcid);
+
+ FNIC_SET_S_ID((&plogi.fchdr), s_id);
+ FNIC_SET_D_ID((&plogi.fchdr), d_id);
+ FNIC_SET_RDF_SIZE(plogi.u.csp_plogi, iport->max_payload_size);
+
+ oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_PLOGI_OXID_BASE));
+ if (oxid == 0xFFFF) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Failed to allocate oxid to send PLOGI to fcid: 0x%x",
+ iport->fcid, tport->fcid);
+ return;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "send tgt PLOGI: tgt fcid: 0x%x oxid: 0x%x", tport->fcid,
+ ntohs(oxid));
+ tport->oxid_used = oxid;
+ tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
+
+ FNIC_SET_OX_ID((&plogi.fchdr), oxid);
+ FNIC_SET_NPORT_NAME(plogi, iport->wwpn);
+ FNIC_SET_NODE_NAME(plogi, iport->wwnn);
+
+ timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);
+
+ fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_tport_timer(iport, tport, timeout);
+}
+
+static uint16_t
+fnic_fc_plogi_rsp_rdf(struct fnic_iport_s *iport,
+ struct fc_els_s *plogi_rsp)
+{
+ uint16_t b2b_rdf_size = ntohs(plogi_rsp->u.csp_plogi.b2b_rdf_size);
+ uint16_t spc3_rdf_size =
+ ((uint16_t) (plogi_rsp->spc3[6] << 8 | plogi_rsp->spc3[7]) &
+ FNIC_FC_C3_RDF);
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "MFS: b2b_rdf_size: 0x%x spc3_rdf_size: 0x%x",
+ b2b_rdf_size, spc3_rdf_size);
+
+ return MIN(b2b_rdf_size, spc3_rdf_size);
+}
+
static void fdls_send_register_fc4_types(struct fnic_iport_s *iport)
{
struct fc_rft_id rft_id;
@@ -387,6 +662,47 @@ static void fdls_send_register_fc4_features(struct fnic_iport_s *iport)
fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
}

+static void
+fdls_send_tgt_prli(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
+{
+ struct fc_els_prli_s prli;
+ uint8_t s_id[3];
+ uint8_t d_id[3];
+ uint16_t oxid;
+ struct fnic *fnic = iport->fnic;
+ uint32_t timeout;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS sending PRLI to tgt: 0x%x", tport->fcid);
+
+ oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_PRLI_OXID_BASE));
+ if (oxid == 0xFFFF) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to allocate OXID to send PRLI %p", iport);
+ return;
+ }
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS sending PRLI to tgt: 0x%x OXID: 0x%x", tport->fcid,
+ ntohs(oxid));
+
+ tport->oxid_used = oxid;
+ tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
+ memcpy(&prli, &fnic_prli_req, sizeof(struct fc_els_prli_s));
+
+ hton24(s_id, iport->fcid);
+ hton24(d_id, tport->fcid);
+
+ FNIC_SET_S_ID((&prli.fchdr), s_id);
+ FNIC_SET_D_ID((&prli.fchdr), d_id);
+ FNIC_SET_OX_ID((&prli.fchdr), oxid);
+
+ timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);
+
+ fnic_send_fcoe_frame(iport, &prli, sizeof(struct fc_els_prli_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_tport_timer(iport, tport, timeout);
+}
+
/***********************************************************************
* fdls_send_fabric_logo
*
@@ -434,6 +750,208 @@ void fdls_send_fabric_logo(struct fnic_iport_s *iport)
fnic_send_fcoe_frame(iport, &logo, sizeof(struct fc_logo_req_s));
}

+/***********************************************************************
+ * fdls_tgt_logout
+ *
+ * \brief Send plogo to the remote port
+ *
+ * \param[in] iport Handle to fnic iport. remote port
+ *
+ * \retval void
+ *
+ * \note This function does not change or check the fabric/tport state.
+ * It the caller responsibility to set the appropriate tport/fabric
+ * state when this is called. Normall fdls_tgt_state_plogo.
+ * fdls_set_tport_state(tport, fdls_tgt_state_plogo)
+ *
+ *\note This could be used to send plogo to nameserver process
+ * also not just target processes
+ *
+ ***********************************************************************/
+void fdls_tgt_logout(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport)
+{
+ struct fc_logo_req_s logo;
+ uint8_t s_id[3];
+ uint8_t d_id[3];
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Sending logo to tport fcid: 0x%x", tport->fcid);
+ memcpy(&logo, &fnic_logo_req, sizeof(struct fc_logo_req_s));
+
+ hton24(s_id, iport->fcid);
+ hton24(d_id, tport->fcid);
+
+ FNIC_SET_S_ID((&logo.fchdr), s_id);
+ FNIC_SET_D_ID((&logo.fchdr), d_id);
+ FNIC_SET_OX_ID((&logo.fchdr), FNIC_TLOGO_REQ_OXID);
+
+ memcpy(&logo.fcid, s_id, 3);
+ logo.wwpn = htonll(iport->wwpn);
+
+ fnic_send_fcoe_frame(iport, &logo, sizeof(struct fc_logo_req_s));
+}
+
+static void fdls_tgt_discovery_start(struct fnic_iport_s *iport)
+{
+ struct fnic_tport_s *tport, *next;
+ u32 old_link_down_cnt = iport->fnic->link_down_cnt;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Starting FDLS target discovery", iport->fcid);
+
+ list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
+ if ((old_link_down_cnt != iport->fnic->link_down_cnt)
+ || (iport->state != FNIC_IPORT_STATE_READY)) {
+ break;
+ }
+ /* if we marked the tport as deleted due to GPN_FT
+ * We should not send ADISC anymore
+ */
+ if ((tport->state == FDLS_TGT_STATE_OFFLINING) ||
+ (tport->state == FDLS_TGT_STATE_OFFLINE))
+ continue;
+
+ /* For tports which have received RSCN */
+ if (tport->flags & FNIC_FDLS_TPORT_SEND_ADISC) {
+ tport->retry_counter = 0;
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_ADISC);
+ tport->flags &= ~FNIC_FDLS_TPORT_SEND_ADISC;
+ fdls_send_tgt_adisc(iport, tport);
+ continue;
+ }
+ if (fdls_get_tport_state(tport) != FDLS_TGT_STATE_INIT) {
+ /* Not a new port, skip */
+ continue;
+ }
+ tport->retry_counter = 0;
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
+ fdls_send_tgt_plogi(iport, tport);
+ }
+ fdls_set_state((&iport->fabric), FDLS_STATE_TGT_DISCOVERY);
+}
+
+/*
+ * Function to restart the IT nexus if we received any out of
+ * sequence PLOGI/PRLI response from the target.
+ * The memory for the new tport structure is allocated
+ * inside fdls_create_tport and added to the iport's tport list.
+ * This will get freed later during tport_offline/linkdown
+ * or module unload. The new_tport pointer will go out of scope
+ * safely since the memory it is
+ * pointing to it will be freed later
+ */
+static void fdls_target_restart_nexus(struct fnic_tport_s *tport)
+{
+ struct fnic_iport_s *iport = tport->iport;
+ struct fnic_tport_s *new_tport = NULL;
+ uint32_t fcid;
+ uint64_t wwpn;
+ int nexus_restart_count;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport fcid: 0x%x state: %d restart_count: %d",
+ tport->fcid, tport->state, tport->nexus_restart_count);
+
+ fcid = tport->fcid;
+ wwpn = tport->wwpn;
+ nexus_restart_count = tport->nexus_restart_count;
+
+ fdls_delete_tport(iport, tport);
+
+ if (nexus_restart_count >= FNIC_TPORT_MAX_NEXUS_RESTART) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Exceeded nexus restart retries tport: 0x%x", fcid);
+ return;
+ }
+
+ /*
+ * Allocate memory for the new tport and add it to
+ * iport's tport list.
+ * This memory will be freed during tport_offline/linkdown
+ * or module unload. The pointer new_tport is safe to go
+ * out of scope when this function returns, since the memory
+ * it is pointing to is guaranteed to be freed later
+ * as mentioned above.
+ */
+ new_tport = fdls_create_tport(iport, fcid, wwpn);
+ if (!new_tport) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Error creating new tport: 0x%x", fcid);
+ return;
+ }
+
+ new_tport->nexus_restart_count = nexus_restart_count + 1;
+ fdls_send_tgt_plogi(iport, new_tport);
+ fdls_set_tport_state(new_tport, FDLS_TGT_STATE_PLOGI);
+}
+
+struct fnic_tport_s *fnic_find_tport_by_fcid(struct fnic_iport_s *iport,
+ uint32_t fcid)
+{
+ struct fnic_tport_s *tport, *next;
+
+ list_for_each_entry_safe(tport, next, &(iport->tport_list), links) {
+ if ((tport->fcid == fcid)
+ && !(tport->flags & FNIC_FDLS_TPORT_TERMINATING))
+ return tport;
+ }
+ return NULL;
+}
+
+static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
+ uint32_t fcid, uint64_t wwpn)
+{
+ struct fnic_tport_s *tport;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS create tport: fcid: 0x%x wwpn: 0x%llx", fcid, wwpn);
+
+ tport = kzalloc(sizeof(struct fnic_tport_s), GFP_ATOMIC);
+ if (!tport) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Memory allocation failure while creating tport: 0x%x\n",
+ fcid);
+ return NULL;
+ }
+
+ tport->max_payload_size = FNIC_FCOE_MAX_FRAME_SZ;
+ tport->r_a_tov = FNIC_R_A_TOV_DEF;
+ tport->e_d_tov = FNIC_E_D_TOV_DEF;
+ tport->fcid = fcid;
+ tport->wwpn = wwpn;
+ tport->iport = iport;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Need to setup tport timer callback");
+
+ timer_setup(&tport->retry_timer, fdls_tport_timer_callback, 0);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Added tport 0x%x", tport->fcid);
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_INIT);
+ list_add_tail(&tport->links, &iport->tport_list);
+ atomic_set(&tport->in_flight, 0);
+ return tport;
+}
+
+struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport,
+ uint64_t wwpn)
+{
+ struct fnic_tport_s *tport, *next;
+
+ list_for_each_entry_safe(tport, next, &(iport->tport_list), links) {
+ if ((tport->wwpn == wwpn)
+ && !(tport->flags & FNIC_FDLS_TPORT_TERMINATING))
+ return tport;
+ }
+ return NULL;
+}
+
void fdls_fabric_timer_callback(struct timer_list *t)
{
struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, retry_timer);
@@ -548,98 +1066,614 @@ void fdls_fabric_timer_callback(struct timer_list *t)
else {
/* ABTS has timed out (2*ra_tov), we give up */
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "ABTS timed out. Starting PLOGI: %p", iport);
- fnic_fdls_start_plogi(iport);
+ "ABTS timed out. Starting PLOGI: %p", iport);
+ fnic_fdls_start_plogi(iport);
+ }
+ break;
+ case FDLS_STATE_REGISTER_FC4_TYPES:
+ /* scr received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_register_fc4_types(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* RFT_ID timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
+ fdls_send_fabric_abts(iport);
+ } else {
+ /* ABTS has timed out (2*ra_tov), we give up */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ABTS timed out. Starting PLOGI: %p", iport);
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ }
+ break;
+ case FDLS_STATE_REGISTER_FC4_FEATURES:
+ /* scr received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_register_fc4_features(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* scr have timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
+ fdls_send_fabric_abts(iport);
+ else {
+ /* ABTS has timed out (2*ra_tov), we give up */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ABTS timed out. Starting PLOGI %p", iport);
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ }
+ break;
+ case FDLS_STATE_RSCN_GPN_FT:
+ case FDLS_STATE_SEND_GPNFT:
+ case FDLS_STATE_GPN_FT:
+ /* GPN_FT received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_gpn_ft(iport, iport->fabric.state);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* gpn_gt have timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
+ fdls_send_fabric_abts(iport);
+ } else {
+ /*
+ * ABTS has timed out have waited (2*ra_tov) can
+ * retry safely with same exchange id
+ */
+ if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
+ fdls_send_gpn_ft(iport, iport->fabric.state);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ABTS timeout for fabric GPN_FT. Check name server: %p",
+ iport);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+static void fdls_send_delete_tport_msg(struct fnic_tport_s *tport)
+{
+ struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
+ struct fnic *fnic = iport->fnic;
+ struct fnic_tport_event_s *tport_del_evt;
+
+ if (!IS_FNIC_FCP_INITIATOR(fnic))
+ return;
+
+ tport_del_evt = kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
+ if (!tport_del_evt) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to allocate memory for tport event fcid: 0x%x",
+ tport->fcid);
+ return;
+ }
+ tport_del_evt->event = TGT_EV_TPORT_DELETE;
+ tport_del_evt->arg1 = (void *) tport;
+ list_add_tail(&tport_del_evt->links, &fnic->tport_event_list);
+ queue_work(fnic_event_queue, &fnic->tport_work);
+}
+
+static void fdls_tport_timer_callback(struct timer_list *t)
+{
+ struct fnic_tport_s *tport = from_timer(tport, t, retry_timer);
+ struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
+ struct fnic *fnic = iport->fnic;
+ uint16_t oxid;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (!tport->timer_pending) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+
+ if (tport->del_timer_inprogress) {
+ tport->del_timer_inprogress = 0;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport_del_timer inprogress. Skip timer cb tport fcid: 0x%x\n",
+ tport->fcid);
+ return;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport fcid: 0x%x timer pending: %d state: %d retry counter: %d",
+ tport->fcid, tport->timer_pending, tport->state,
+ tport->retry_counter);
+
+ tport->timer_pending = 0;
+ oxid = ntohs(tport->oxid_used);
+
+ /* We retry plogi/prli/adisc frames depending on the tport state */
+ switch (tport->state) {
+ case FDLS_TGT_STATE_PLOGI:
+ /* PLOGI frame received a LS_RJT with busy, we retry from here */
+ if ((tport->flags & FNIC_FDLS_RETRY_FRAME)
+ && (tport->retry_counter < iport->max_plogi_retries)) {
+ fdls_free_tgt_oxid(iport, oxid);
+ tport->flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_tgt_plogi(iport, tport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* Plogi frame has timed out 2*ed_tov send abts */
+ if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
+ fdls_send_tport_abts(iport, tport);
+ } else if (tport->retry_counter < iport->max_plogi_retries) {
+ /*
+ * ABTS has timed out have waited (2*ra_tov)
+ * can retry safely
+ * even if with same exchange id
+ */
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_tgt_plogi(iport, tport);
+ } else {
+ /* exceeded plogi retry count */
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_delete_tport_msg(tport);
+ }
+ break;
+ case FDLS_TGT_STATE_PRLI:
+ /* PRLI received a LS_RJT with busy , hence we retry from here */
+ if ((tport->flags & FNIC_FDLS_RETRY_FRAME)
+ && (tport->retry_counter < FDLS_RETRY_COUNT)) {
+ fdls_free_tgt_oxid(iport, oxid);
+ tport->flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_tgt_prli(iport, tport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* PRLI has time out 2*ed_tov send abts */
+ if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
+ fdls_send_tport_abts(iport, tport);
+ } else {
+ /* ABTS has timed out for prli, we go back to PLOGI */
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_tgt_plogi(iport, tport);
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
+ }
+ break;
+ case FDLS_TGT_STATE_ADISC:
+ /* ADISC timed out send a ABTS */
+ if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
+ fdls_send_tport_abts(iport, tport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ } else if ((tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)
+ && (tport->retry_counter < FDLS_RETRY_COUNT)) {
+ /*
+ * ABTS has timed out have waited (2*ra_tov) can
+ * retry safely even if with same exchange id
+ */
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_tgt_adisc(iport, tport);
+
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* exceeded retry count */
+ fdls_free_tgt_oxid(iport, oxid);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ADISC not responding. Deleting target port: 0x%x",
+ tport->fcid);
+ fdls_send_delete_tport_msg(tport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown tport state: 0x%x", tport->state);
+ break;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
+{
+ iport->fabric.retry_counter = 0;
+ fdls_send_fabric_flogi(iport);
+ fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_FLOGI);
+ iport->fabric.flags = 0;
+}
+
+static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
+{
+ iport->fabric.retry_counter = 0;
+ fdls_send_fabric_plogi(iport);
+ fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
+ iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+}
+
+static void
+fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ uint32_t tgt_fcid;
+ struct fnic_tport_s *tport;
+ uint8_t *fcid;
+ uint64_t frame_wwnn;
+ uint64_t frame_wwpn;
+ uint16_t oxid;
+ struct fc_els_adisc_ls_acc_s *adisc_rsp =
+ (struct fc_els_adisc_ls_acc_s *) fchdr;
+ struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
+ struct fnic *fnic = iport->fnic;
+
+ fcid = FNIC_GET_S_ID(fchdr);
+ tgt_fcid = ntoh24(fcid);
+ tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
+
+ if (!tport) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Tgt ADISC response tport not found: 0x%x", tgt_fcid);
+ return;
+ }
+ if ((iport->state != FNIC_IPORT_STATE_READY)
+ || (tport->state != FDLS_TGT_STATE_ADISC)
+ || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping this ADISC response");
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport state: %d tport state: %d Is abort issued on PRLI? %d",
+ iport->state, tport->state,
+ (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED));
+ return;
+ }
+ if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping frame from target: 0x%x",
+ tgt_fcid);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Reason: Stale ADISC/Aborted ADISC/OOO frame delivery");
+ return;
+ }
+
+ switch (adisc_rsp->command) {
+ case FC_LS_ACC:
+ if (tport->timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport 0x%p Canceling fabric disc timer\n",
+ tport);
+ fnic_del_tport_timer_sync();
+ }
+ tport->timer_pending = 0;
+ tport->retry_counter = 0;
+ oxid = ntohs(fchdr->ox_id);
+ fdls_free_tgt_oxid(iport, oxid);
+ frame_wwnn = htonll(adisc_rsp->node_name);
+ frame_wwpn = htonll(adisc_rsp->nport_name);
+ if ((frame_wwnn == tport->wwnn) && (frame_wwpn == tport->wwpn)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ADISC accepted from target: 0x%x. Target logged in",
+ tgt_fcid);
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_READY);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Error mismatch frame: ADISC");
+ }
+ break;
+
+ case FC_LS_REJ:
+ if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
+ || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
+ && (tport->retry_counter < FDLS_RETRY_COUNT)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ADISC ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
+ tgt_fcid);
+
+ /* Retry ADISC again from the timer routine. */
+ tport->flags |= FNIC_FDLS_RETRY_FRAME;
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ADISC returned FC_LS_REJ from target: 0x%x",
+ tgt_fcid);
+ oxid = ntohs(fchdr->ox_id);
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_delete_tport(iport, tport);
+ }
+ break;
+ }
+}
+
+
+static void
+fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ uint32_t tgt_fcid;
+ struct fnic_tport_s *tport;
+ uint8_t *fcid;
+ uint16_t oxid;
+ struct fc_els_s *plogi_rsp = (struct fc_els_s *) fchdr;
+ struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
+ int max_payload_size;
+ struct fnic *fnic = iport->fnic;
+
+ fcid = FNIC_GET_S_ID(fchdr);
+ tgt_fcid = ntoh24(fcid);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS processing target PLOGI response: tgt_fcid: 0x%x",
+ tgt_fcid);
+
+ tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
+ if (!tport) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport not found: 0x%x", tgt_fcid);
+ return;
+ }
+ if ((iport->state != FNIC_IPORT_STATE_READY)
+ || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping frame! iport state: %d tport state: %d",
+ iport->state, tport->state);
+ return;
+ }
+
+ if (tport->state != FDLS_TGT_STATE_PLOGI) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI rsp recvd in wrong state. Restarting nexus");
+ oxid = ntohs(FNIC_GET_OX_ID(fchdr));
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_target_restart_nexus(tport);
+ return;
+ }
+
+ if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI response from target: 0x%x. Dropping frame",
+ tgt_fcid);
+ return;
+ }
+
+ switch (plogi_rsp->command) {
+ case FC_LS_ACC:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI accepted by target: 0x%x", tgt_fcid);
+ oxid = ntohs(FNIC_GET_OX_ID(fchdr));
+ fdls_free_tgt_oxid(iport, oxid);
+ break;
+
+ case FC_LS_REJ:
+ if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
+ || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
+ && (tport->retry_counter < iport->max_plogi_retries)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
+ tgt_fcid);
+ /* Retry plogi again from the timer routine. */
+ tport->flags |= FNIC_FDLS_RETRY_FRAME;
+ return;
+ }
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI returned FC_LS_REJ from target: 0x%x",
+ tgt_fcid);
+ oxid = ntohs(fchdr->ox_id);
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_delete_tport(iport, tport);
+ return;
+
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI not accepted from target fcid: 0x%x",
+ tgt_fcid);
+ return;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Found the PLOGI target: 0x%x and state: %d",
+ (unsigned int) tgt_fcid, tport->state);
+
+ if (tport->timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport fcid 0x%x: Canceling disc timer\n",
+ tport->fcid);
+ fnic_del_tport_timer_sync();
+ }
+
+ tport->timer_pending = 0;
+ tport->wwpn = htonll(plogi_rsp->nport_name);
+ tport->wwnn = htonll(plogi_rsp->node_name);
+
+ /* Learn the Service Params */
+
+ /* Max frame size - choose the lowest */
+ max_payload_size = fnic_fc_plogi_rsp_rdf(iport, plogi_rsp);
+ tport->max_payload_size =
+ MIN(max_payload_size, iport->max_payload_size);
+
+ if (tport->max_payload_size < FNIC_MIN_DATA_FIELD_SIZE) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "MFS: tport max frame size below spec bounds: %d",
+ tport->max_payload_size);
+ tport->max_payload_size = FNIC_MIN_DATA_FIELD_SIZE;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "MAX frame size: %d iport max_payload_size: %d tport mfs: %d",
+ max_payload_size, iport->max_payload_size,
+ tport->max_payload_size);
+
+ tport->max_concur_seqs = FNIC_FC_PLOGI_RSP_CONCUR_SEQ(plogi_rsp);
+
+ tport->retry_counter = 0;
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_PRLI);
+ fdls_send_tgt_prli(iport, tport);
+}
+
+static void
+fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ uint32_t tgt_fcid;
+ struct fnic_tport_s *tport;
+ uint8_t *fcid;
+ uint16_t oxid;
+ struct fc_els_prli_s *prli_rsp = (struct fc_els_prli_s *) fchdr;
+ struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
+ struct fnic_tport_event_s *tport_add_evt;
+ struct fnic *fnic = iport->fnic;
+ bool mismatched_tgt = false;
+
+ fcid = FNIC_GET_S_ID(fchdr);
+ tgt_fcid = ntoh24(fcid);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS process tgt PRLI response: 0x%x", tgt_fcid);
+
+ tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
+ if (!tport) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport not found: 0x%x", tgt_fcid);
+ /* Handle or just drop? */
+ return;
+ }
+
+ if ((iport->state != FNIC_IPORT_STATE_READY)
+ || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping frame! iport st: %d tport st: %d tport fcid: 0x%x",
+ iport->state, tport->state, tport->fcid);
+ return;
+ }
+
+ if (tport->state != FDLS_TGT_STATE_PRLI) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PRLI rsp recvd in wrong state. Restarting nexus");
+ oxid = ntohs(FNIC_GET_OX_ID(fchdr));
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_target_restart_nexus(tport);
+ return;
+ }
+
+ if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping PRLI response from target: 0x%x ",
+ tgt_fcid);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Reason: Stale PRLI response/Aborted PDISC/OOO frame delivery");
+ return;
+ }
+
+ switch (prli_rsp->command) {
+ case FC_LS_ACC:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PRLI accepted from target: 0x%x", tgt_fcid);
+ oxid = ntohs(FNIC_GET_OX_ID(fchdr));
+ fdls_free_tgt_oxid(iport, oxid);
+
+ if (prli_rsp->sp.type != FC_FC4_TYPE_SCSI) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "mismatched target zoned with FC SCSI initiator: 0x%x",
+ tgt_fcid);
+ mismatched_tgt = true;
}
- break;
- case FDLS_STATE_REGISTER_FC4_TYPES:
- /* scr received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_register_fc4_types(iport);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ if (mismatched_tgt) {
+ fdls_tgt_logout(iport, tport);
+ fdls_delete_tport(iport, tport);
return;
}
- /* RFT_ID timed out send abts */
- if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
- fdls_send_fabric_abts(iport);
- } else {
- /* ABTS has timed out (2*ra_tov), we give up */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "ABTS timed out. Starting PLOGI: %p", iport);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
break;
- case FDLS_STATE_REGISTER_FC4_FEATURES:
- /* scr received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_register_fc4_features(iport);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- /* scr have timed out send abts */
- if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
- fdls_send_fabric_abts(iport);
- else {
- /* ABTS has timed out (2*ra_tov), we give up */
+
+ case FC_LS_REJ:
+ if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
+ || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
+ && (tport->retry_counter < FDLS_RETRY_COUNT)) {
+
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "ABTS timed out. Starting PLOGI %p", iport);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
- break;
- case FDLS_STATE_RSCN_GPN_FT:
- case FDLS_STATE_SEND_GPNFT:
- case FDLS_STATE_GPN_FT:
- /* GPN_FT received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_gpn_ft(iport, iport->fabric.state);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ "PRLI ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
+ tgt_fcid);
+
+ /*Retry Plogi again from the timer routine. */
+ tport->flags |= FNIC_FDLS_RETRY_FRAME;
return;
- }
- /* gpn_gt have timed out send abts */
- if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
- fdls_send_fabric_abts(iport);
} else {
- /*
- * ABTS has timed out have waited (2*ra_tov) can
- * retry safely with same exchange id
- */
- if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
- fdls_send_gpn_ft(iport, iport->fabric.state);
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "ABTS timeout for fabric GPN_FT. Check name server: %p",
- iport);
- }
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PRLI returned FC_LS_REJ from target: 0x%x",
+ tgt_fcid);
+
+ oxid = ntohs(fchdr->ox_id);
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_tgt_logout(iport, tport);
+ fdls_delete_tport(iport, tport);
+ return;
}
break;
+
default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PRLI not accepted from target: 0x%x", tgt_fcid);
+ return;
break;
}
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-}

-static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
-{
- iport->fabric.retry_counter = 0;
- fdls_send_fabric_flogi(iport);
- fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_FLOGI);
- iport->fabric.flags = 0;
-}
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Found the PRLI target: 0x%x and state: %d",
+ (unsigned int) tgt_fcid, tport->state);

-static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
-{
- iport->fabric.retry_counter = 0;
- fdls_send_fabric_plogi(iport);
- fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
- iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+ if (tport->timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport fcid 0x%x: Canceling disc timer\n",
+ tport->fcid);
+ fnic_del_tport_timer_sync();
+ }
+ tport->timer_pending = 0;
+
+ oxid = ntohs(FNIC_GET_OX_ID(fchdr));
+ fdls_free_tgt_oxid(iport, oxid);
+
+ /* Learn Service Params */
+ tport->fcp_csp = ntohl(prli_rsp->sp.csp);
+ tport->retry_counter = 0;
+
+ if (prli_rsp->sp.csp & FCP_SPPF_RETRY)
+ tport->tgt_flags |= FNIC_FC_RP_FLAGS_RETRY;
+
+ /* Check if the device plays Target Mode Function */
+ if (!(tport->fcp_csp & FCP_PRLI_FUNC_TARGET)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Remote port(0x%x): no target support. Deleting it\n",
+ tgt_fcid);
+ fdls_tgt_logout(iport, tport);
+ fdls_delete_tport(iport, tport);
+ return;
+ }
+
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_READY);
+
+ /* Inform the driver about new target added */
+ tport_add_evt = kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
+ if (!tport_add_evt) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport event memory allocation failure: 0x%0x\n",
+ tport->fcid);
+ return;
+ }
+ tport_add_evt->event = TGT_EV_RPORT_ADD;
+ tport_add_evt->arg1 = (void *) tport;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport fcid: 0x%x add tport event fcid: 0x%x\n",
+ tport->fcid, iport->fcid);
+ list_add_tail(&tport_add_evt->links, &fnic->tport_event_list);
+ queue_work(fnic_event_queue, &fnic->tport_work);
}

+
static void
fdls_process_rff_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
{
@@ -884,6 +1918,106 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
}
}

+static void
+fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr, int len)
+{
+ struct fc_gpn_ft_rsp_iu_s *gpn_ft_tgt;
+ struct fc_gpn_ft_rsp_iu_s *gpn_ft_tgt_rem;
+ struct fnic_tport_s *tport, *next;
+ uint32_t fcid;
+ uint64_t wwpn;
+ int rem_len = len;
+ u32 old_link_down_cnt = iport->fnic->link_down_cnt;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS process GPN_FT tgt list", iport->fcid);
+
+ gpn_ft_tgt =
+ (struct fc_gpn_ft_rsp_iu_s *) ((uint8_t *) fchdr +
+ sizeof(struct fc_hdr_s)
+ + sizeof(struct fc_ct_hdr_s));
+ gpn_ft_tgt_rem = gpn_ft_tgt;
+ len -= sizeof(struct fc_hdr_s) + sizeof(struct fc_ct_hdr_s);
+
+ while (rem_len > 0) {
+
+ fcid = ntoh24(gpn_ft_tgt->fcid);
+ wwpn = ntohll(gpn_ft_tgt->wwpn);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tport: 0x%x: ctrl:0x%x", fcid, gpn_ft_tgt->ctrl);
+
+ if (fcid == iport->fcid) {
+ if (gpn_ft_tgt->ctrl & FNIC_FC_GPN_LAST_ENTRY)
+ break;
+ gpn_ft_tgt++;
+ rem_len -= sizeof(struct fc_gpn_ft_rsp_iu_s);
+ continue;
+ }
+
+ tport = fnic_find_tport_by_wwpn(iport, wwpn);
+ if (!tport) {
+ /*
+ * New port registered with the switch or first time query
+ */
+ tport = fdls_create_tport(iport, fcid, wwpn);
+ if (!tport)
+ return;
+ }
+ /*
+ * check if this was an existing tport with same fcid
+ * but whose wwpn has changed now ,then remove it and
+ * create a new one
+ */
+ if (tport->fcid != fcid) {
+ fdls_delete_tport(iport, tport);
+ tport = fdls_create_tport(iport, fcid, wwpn);
+ if (!tport)
+ return;
+ }
+
+ /*
+ * If this GPN_FT rsp is after RSCN then mark the tports which
+ * matches with the new GPN_FT list, if some tport is not
+ * found in GPN_FT we went to delete that tport later.
+ */
+ if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT)
+ tport->flags |= FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
+
+ if (gpn_ft_tgt->ctrl & FNIC_FC_GPN_LAST_ENTRY)
+ break;
+
+ gpn_ft_tgt++;
+ rem_len -= sizeof(struct fc_gpn_ft_rsp_iu_s);
+ }
+ if (rem_len <= 0) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "GPN_FT response: malformed/corrupt frame rxlen: %d remlen: %d",
+ len, rem_len);
+ }
+
+ /*remove those ports which was not listed in GPN_FT */
+ if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT) {
+ list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
+
+ if (!(tport->flags & FNIC_FDLS_TPORT_IN_GPN_FT_LIST)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Remove port: 0x%x not found in GPN_FT list",
+ tport->fcid);
+ fdls_delete_tport(iport, tport);
+ } else {
+ tport->flags &= ~FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
+ }
+ if ((old_link_down_cnt != iport->fnic->link_down_cnt)
+ || (iport->state != FNIC_IPORT_STATE_READY)) {
+ return;
+ }
+ }
+ }
+}
+
static void
fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
int len)
@@ -892,6 +2026,9 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
struct fc_gpn_ft_s *gpn_ft_rsp = (struct fc_gpn_ft_s *) fchdr;
uint16_t rsp;
uint8_t reason_code;
+ int count = 0;
+ struct fnic_tport_s *tport, *next;
+ u32 old_link_down_cnt = iport->fnic->link_down_cnt;
struct fnic *fnic = iport->fnic;

FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
@@ -928,12 +2065,74 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
case FC_CT_ACC:
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"0x%x: GPNFT_RSP accept", iport->fcid);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Canceling fabric disc timer\n",
+ iport->fcid);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ iport->fabric.retry_counter = 0;
+ fdls_process_gpn_ft_tgt_list(iport, fchdr, len);
+
+ /*
+ * iport state can change only if link down event happened
+ * We don't need to undo fdls_process_gpn_ft_tgt_list,
+ * that will be taken care in next link up event
+ */
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Halting target discovery: fab st: %d iport st: %d ",
+ fdls_get_state(fdls), iport->state);
+ break;
+ }
+ fdls_tgt_discovery_start(iport);
break;

case FC_CT_REJ:
reason_code = gpn_ft_rsp->fc_ct_hdr.reason_code;
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"0x%x: GPNFT_RSP Reject", iport->fcid);
+
+ if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
+ || (reason_code == FC_CT_RJT_BUSY))
+ && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: GPNFT_RSP ret REJ/BSY. Retry from timer routine",
+ iport->fcid);
+ /* Retry again from the timer routine */
+ fdls->flags |= FNIC_FDLS_RETRY_FRAME;
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: GPNFT_RSP reject", iport->fcid);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Canceling fabric disc timer\n",
+ iport->fcid);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ iport->fabric.retry_counter = 0;
+ /*
+ * If GPN_FT ls_rjt then we should delete
+ * all existing tports
+ */
+ count = 0;
+ list_for_each_entry_safe(tport, next, &iport->tport_list,
+ links) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "GPN_FT_REJECT: Remove port: 0x%x",
+ tport->fcid);
+ fdls_delete_tport(iport, tport);
+ if ((old_link_down_cnt != iport->fnic->link_down_cnt)
+ || (iport->state != FNIC_IPORT_STATE_READY)) {
+ return;
+ }
+ count++;
+ }
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "GPN_FT_REJECT: Removed (0x%x) ports", count);
+ }
break;

default:
@@ -1342,6 +2541,141 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
}
}

+static void
+fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ uint32_t s_id;
+ struct fnic_tport_s *tport;
+ uint32_t tport_state;
+ struct fc_abts_ba_acc_s *ba_acc;
+ struct fc_abts_ba_rjt_s *ba_rjt;
+ uint16_t oxid;
+ struct fnic *fnic = iport->fnic;
+
+ s_id = ntoh24(fchdr->sid);
+ ba_acc = (struct fc_abts_ba_acc_s *) fchdr;
+ ba_rjt = (struct fc_abts_ba_rjt_s *) fchdr;
+
+ tport = fnic_find_tport_by_fcid(iport, s_id);
+ if (!tport) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Received tgt abts rsp with invalid SID: 0x%x", s_id);
+ return;
+ }
+
+ if (tport->timer_pending) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "tport 0x%p Canceling fabric disc timer\n", tport);
+ fnic_del_tport_timer_sync();
+ }
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Received tgt abts rsp in iport state(%d). Dropping.",
+ iport->state);
+ return;
+ }
+ tport->timer_pending = 0;
+ tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
+ tport_state = tport->state;
+ oxid = ntohs(fchdr->ox_id);
+
+ /*This abort rsp is for ADISC */
+ if ((oxid >= FDLS_ADISC_OXID_BASE) && (oxid < FDLS_TGT_OXID_POOL_END)) {
+ if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Received tgt ADISC abts response BA_ACC for OX_ID: 0x%x tgt_fcid: 0x%x",
+ ba_acc->ox_id, tport->fcid);
+ } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "ADISC BA_RJT rcvd tport_fcid: 0x%x tport_state: %d ",
+ tport->fcid, tport_state);
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "reason code: 0x%x reason code explanation:0x%x ",
+ ba_rjt->reason_code, ba_rjt->reason_explanation);
+ }
+ if ((tport->retry_counter < FDLS_RETRY_COUNT)
+ && (fchdr->r_ctl == FNIC_BA_ACC_RCTL)) {
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_tgt_adisc(iport, tport);
+ return;
+ }
+ fdls_free_tgt_oxid(iport, oxid);
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "ADISC not responding. Deleting target port: 0x%x",
+ tport->fcid);
+ fdls_delete_tport(iport, tport);
+ if ((iport->state == FNIC_IPORT_STATE_READY)
+ && (iport->fabric.state != FDLS_STATE_SEND_GPNFT)
+ && (iport->fabric.state != FDLS_STATE_RSCN_GPN_FT)) {
+ fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
+ }
+ /*Restart a discovery of targets */
+ return;
+ }
+
+ /*This abort rsp is for PLOGI */
+ if ((oxid >= FDLS_PLOGI_OXID_BASE) && (oxid < FDLS_PRLI_OXID_BASE)) {
+ if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Received tgt PLOGI abts response BA_ACC tgt_fcid: 0x%x",
+ tport->fcid);
+ } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x",
+ tport->fcid, fchdr->ox_id);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "reason code: 0x%x reason code explanation: 0x%x",
+ ba_rjt->reason_code, ba_rjt->reason_explanation);
+ }
+ if ((tport->retry_counter < iport->max_plogi_retries)
+ && (fchdr->r_ctl == FNIC_BA_ACC_RCTL)) {
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_tgt_plogi(iport, tport);
+ return;
+ }
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_delete_tport(iport, tport);
+ /*Restart a discovery of targets */
+ if ((iport->state == FNIC_IPORT_STATE_READY)
+ && (iport->fabric.state != FDLS_STATE_SEND_GPNFT)
+ && (iport->fabric.state != FDLS_STATE_RSCN_GPN_FT)) {
+ fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
+ }
+ return;
+ }
+
+ /*This abort rsp is for PRLI */
+ if ((oxid >= FDLS_PRLI_OXID_BASE) && (oxid < FDLS_ADISC_OXID_BASE)) {
+ if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Received tgt PRLI abts response BA_ACC",
+ tport->fcid);
+ } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PRLI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x ",
+ tport->fcid, fchdr->ox_id);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "reason code: 0x%x reason code explanation: 0x%x",
+ ba_rjt->reason_code,
+ ba_rjt->reason_explanation);
+ }
+ if ((tport->retry_counter < FDLS_RETRY_COUNT)
+ && (fchdr->r_ctl == FNIC_BA_ACC_RCTL)) {
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_tgt_prli(iport, tport);
+ return;
+ }
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_send_tgt_plogi(iport, tport); /* go back to plogi */
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
+ return;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received ABTS response for unknown frame %p", iport);
+}
+
/*
* Performs a validation for all FCOE frames and return the frame type
*/
@@ -1434,6 +2768,42 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
}
}

+ /* ELS response from a target */
+ if ((ntohs(oxid) >= FDLS_PLOGI_OXID_BASE)
+ && (ntohs(oxid) < FDLS_PRLI_OXID_BASE)) {
+ if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping Unknown frame in PLOGI exchange range type: 0x%x.",
+ fchdr->type);
+ return -1;
+ }
+ return FNIC_TPORT_PLOGI_RSP;
+ }
+ if ((ntohs(oxid) >= FDLS_PRLI_OXID_BASE)
+ && (ntohs(oxid) < FDLS_ADISC_OXID_BASE)) {
+ if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping Unknown frame in PRLI exchange range type: 0x%x.",
+ fchdr->type);
+ return -1;
+ }
+ return FNIC_TPORT_PRLI_RSP;
+ }
+
+ if ((ntohs(oxid) >= FDLS_ADISC_OXID_BASE)
+ && (ntohs(oxid) < FDLS_TGT_OXID_POOL_END)) {
+ if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping Unknown frame in ADISC exchange range type: 0x%x.",
+ fchdr->type);
+ return -1;
+ }
+ return FNIC_TPORT_ADISC_RSP;
+ }
+ if (ntohs(oxid) == FNIC_TLOGO_REQ_OXID) {
+ return FNIC_TPORT_LOGO_RSP;
+ }
+
/*response from fabric */
switch (oxid) {

@@ -1557,6 +2927,21 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
case FNIC_FABRIC_GPN_FT_RSP:
fdls_process_gpn_ft_rsp(iport, fchdr, len);
break;
+ case FNIC_TPORT_PLOGI_RSP:
+ fdls_process_tgt_plogi_rsp(iport, fchdr);
+ break;
+ case FNIC_TPORT_PRLI_RSP:
+ fdls_process_tgt_prli_rsp(iport, fchdr);
+ break;
+ case FNIC_TPORT_ADISC_RSP:
+ fdls_process_tgt_adisc_rsp(iport, fchdr);
+ break;
+ case FNIC_TPORT_LOGO_RSP:
+ /* Logo response from tgt which we have deleted */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Logo response from tgt: 0x%x",
+ ntoh24(fchdr->sid));
+ break;
case FNIC_FABRIC_LOGO_RSP:
fdls_process_fabric_logo_rsp(iport, fchdr);
break;
@@ -1566,7 +2951,8 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
if ((iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)
&& (oxid >= FNIC_FLOGI_OXID && oxid <= FNIC_RFF_REQ_OXID)) {
fdls_process_fabric_abts_rsp(iport, fchdr);
- }
+ } else
+ fdls_process_tgt_abts_rsp(iport, fchdr);
break;
default:
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 2d5f438f2cc4..92cd17efa40f 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -79,6 +79,9 @@

#define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)

+/* Retry supported by rport (returned by PRLI service parameters) */
+#define FNIC_FC_RP_FLAGS_RETRY 0x1
+
/*
* fnic private data per SCSI command.
* These fields are locked by the hashed io_req_lock.
@@ -133,6 +136,7 @@ static inline u64 fnic_flags_and_state(struct scsi_cmnd *cmd)

extern unsigned int fnic_log_level;
extern unsigned int io_completions;
+extern struct workqueue_struct *fnic_event_queue;

#define FNIC_MAIN_LOGGING 0x01
#define FNIC_FCS_LOGGING 0x02
@@ -329,6 +333,8 @@ struct fnic {
struct work_struct flush_work;
struct sk_buff_head frame_queue;
struct list_head tx_queue;
+ struct work_struct tport_work;
+ struct list_head tport_event_list;

/*** FIP related data members -- start ***/
void (*set_vlan)(struct fnic *, u16 vlan);
diff --git a/drivers/scsi/fnic/fnic_fdls.h b/drivers/scsi/fnic/fnic_fdls.h
index 095275698716..9eb25ed9c19f 100644
--- a/drivers/scsi/fnic/fnic_fdls.h
+++ b/drivers/scsi/fnic/fnic_fdls.h
@@ -325,6 +325,10 @@ void fdls_send_fabric_logo(struct fnic_iport_s *iport);
int fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
void *rx_frame, int len,
int fchdr_offset);
+void fdls_send_tport_abts(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport);
+void fdls_delete_tport(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport);

/* fnic_fcs.c */
void fnic_fdls_init(struct fnic *fnic, int usefip);
--
2.31.1


Subject: [PATCH 03/14] scsi: fnic: Add support for fabric based solicited requests and responses

Add fdls_disc.c to support fabric based solicited requests
and responses.
Clean up obsolete code but keep the function template so
as to not break compilation.
Remove duplicate definitions from header files.
Modify definitions of data members.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/Makefile | 1 +
drivers/scsi/fnic/fdls_disc.c | 1576 +++++++++++++++++++++++++++++++++
drivers/scsi/fnic/fnic.h | 26 +-
drivers/scsi/fnic/fnic_fcs.c | 404 +++++----
drivers/scsi/fnic/fnic_fdls.h | 7 +-
drivers/scsi/fnic/fnic_io.h | 11 -
drivers/scsi/fnic/fnic_main.c | 10 +-
drivers/scsi/fnic/fnic_scsi.c | 6 +-
8 files changed, 1849 insertions(+), 192 deletions(-)
create mode 100644 drivers/scsi/fnic/fdls_disc.c

diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
index 6214a6b2e96d..3bd6b1c8b643 100644
--- a/drivers/scsi/fnic/Makefile
+++ b/drivers/scsi/fnic/Makefile
@@ -7,6 +7,7 @@ fnic-y := \
fnic_main.o \
fnic_res.o \
fnic_fcs.o \
+ fdls_disc.o \
fnic_scsi.o \
fnic_trace.o \
fnic_debugfs.o \
diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
new file mode 100644
index 000000000000..22a2d0c1c78f
--- /dev/null
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -0,0 +1,1576 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ */
+
+#include <linux/workqueue.h>
+#include "fnic.h"
+#include "fdls_fc.h"
+#include "fnic_fdls.h"
+#include <scsi/fc/fc_fcp.h>
+#include <linux/utsname.h>
+
+static void fdls_send_rpn_id(struct fnic_iport_s *iport);
+
+/* Frame initialization */
+/*
+ * Variables:
+ * sid
+ */
+struct fc_els_s fnic_flogi_req = {
+ .fchdr = {.r_ctl = 0x22, .did = {0xFF, 0xFF, 0xFE},
+ .type = 0x01, .f_ctl = FNIC_ELS_REQ_FCTL,
+ .ox_id = FNIC_FLOGI_OXID, .rx_id = 0xFFFF},
+ .command = FC_ELS_FLOGI_REQ,
+ .u.csp_flogi = {.fc_ph_ver = FNIC_FC_PH_VER,
+ .b2b_credits = FNIC_FC_B2B_CREDIT,
+ .b2b_rdf_size = FNIC_FC_B2B_RDF_SZ},
+ .spc3 = {0x88, 0x00}
+};
+
+/*
+ * Variables:
+ * sid, did(nport logins), ox_id(nport logins), nport_name, node_name
+ */
+struct fc_els_s fnic_plogi_req = {
+ .fchdr = {.r_ctl = 0x22, .did = {0xFF, 0xFF, 0xFC}, .type = 0x01,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_PLOGI_FABRIC_OXID,
+ .rx_id = 0xFFFF},
+ .command = FC_ELS_PLOGI_REQ,
+ .u.csp_plogi = {.fc_ph_ver = FNIC_FC_PH_VER,
+ .b2b_credits = FNIC_FC_B2B_CREDIT, .features = 0x0080,
+ .b2b_rdf_size = FNIC_FC_B2B_RDF_SZ,
+ .total_concur_seqs = FNIC_FC_CONCUR_SEQS,
+ .ro_info = FNIC_FC_RO_INFO, .e_d_tov = FNIC_E_D_TOV},
+ .spc3 = {0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xFF,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}
+};
+
+/*
+ * Variables:
+ * sid, port_id, port_name
+ */
+struct fc_rpn_id_s fnic_rpn_id_req = {
+ .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_RPN_REQ_OXID,
+ .rx_id = 0xFFFF},
+ .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
+ .command = FC_CT_RPN_CMD}
+};
+
+/*
+ * Variables:
+ * fh_s_id, port_id, port_name
+ */
+struct fc_rft_id fnic_rft_id_req = {
+ .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_RFT_REQ_OXID,
+ .rx_id = 0xFFFF},
+ .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
+ .command = FC_CT_RFT_CMD}
+};
+
+/*
+ * Variables:
+ * fh_s_id, port_id, port_name
+ */
+struct fc_rff_id fnic_rff_id_req = {
+ .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_RFF_REQ_OXID,
+ .rx_id = 0xFFFF},
+ .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
+ .command = FC_CT_RFF_CMD},
+ .tgt = 0x2,
+ .fc4_type = 0x28
+};
+
+/*
+ * Variables:
+ * sid
+ */
+struct fc_gpn_ft_s fnic_gpn_ft_req = {
+ .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_GPN_FT_OXID,
+ .rx_id = 0xFFFF},
+ .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
+ .command = FC_CT_GPN_FT_CMD},
+ .fc4_type = 0x08
+};
+
+/*
+ * Variables:
+ * sid
+ */
+struct fc_scr_s fnic_scr_req = {
+ .fchdr = {.r_ctl = 0x22, .did = {0xFF, 0xFF, 0xFD}, .type = 0x01,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_SCR_REQ_OXID,
+ .rx_id = 0xFFFF},
+ .command = FC_ELS_SCR,
+ .reg_func = 0x03
+};
+
+/*
+ * Variables:
+ * did, ox_id, rx_id, fcid, wwpn
+ */
+struct fc_logo_req_s fnic_logo_req = {
+ .fchdr = {.r_ctl = 0x22, .type = 0x01,
+ .f_ctl = FNIC_ELS_REQ_FCTL},
+ .command = FC_ELS_LOGO,
+};
+
+#define RETRIES_EXHAUSTED(iport) \
+ (iport->fabric.retry_counter == FABRIC_LOGO_MAX_RETRY)
+
+static void fdls_process_flogi_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr, void *rx_frame);
+static void fnic_fdls_start_plogi(struct fnic_iport_s *iport);
+static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
+ int timeout);
+
+static void
+fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
+{
+ u64 fabric_tov;
+ struct fnic *fnic = iport->fnic;
+
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport fcid: 0x%x: Canceling fabric disc timer\n",
+ iport->fcid);
+ fnic_del_fabric_timer_sync();
+ iport->fabric.timer_pending = 0;
+ }
+
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
+ iport->fabric.retry_counter++;
+
+ fabric_tov = jiffies + msecs_to_jiffies(timeout);
+ mod_timer(&iport->fabric.retry_timer, round_jiffies(fabric_tov));
+ iport->fabric.timer_pending = 1;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fabric timer is %d ", timeout);
+}
+
+static void fdls_send_fabric_abts(struct fnic_iport_s *iport)
+{
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+ struct fc_hdr_s fc_abts_s = {
+ .r_ctl = 0x81, /* ABTS */
+ .did = {0xFF, 0xFF, 0xFF}, .sid = {0x00, 0x00, 0x00}, .cs_ctl =
+ 0x00, .type = 0x00, .f_ctl = FNIC_REQ_ABTS_FCTL, .seq_id =
+ 0x00, .df_ctl = 0x00, .seq_cnt = 0x0000, .rx_id = 0xFFFF,
+ .param = 0x00000000, /* bit:0 = 0 Abort a exchange */
+ };
+
+ struct fc_hdr_s *pfc_abts = &fc_abts_s;
+
+ switch (iport->fabric.state) {
+ case FDLS_STATE_FABRIC_LOGO:
+ fc_abts_s.ox_id = FNIC_FLOGO_REQ_OXID;
+ fc_abts_s.did[2] = 0xFE;
+ break;
+ case FDLS_STATE_FABRIC_FLOGI:
+ fc_abts_s.ox_id = FNIC_FLOGI_OXID;
+ fc_abts_s.did[2] = 0xFE;
+ break;
+
+ case FDLS_STATE_FABRIC_PLOGI:
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID(pfc_abts, fcid);
+ fc_abts_s.ox_id = FNIC_PLOGI_FABRIC_OXID;
+ fc_abts_s.did[2] = 0xFC;
+ break;
+
+ case FDLS_STATE_RPN_ID:
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID(pfc_abts, fcid);
+ fc_abts_s.ox_id = FNIC_RPN_REQ_OXID;
+ fc_abts_s.did[2] = 0xFC;
+ break;
+
+ case FDLS_STATE_SCR:
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID(pfc_abts, fcid);
+ fc_abts_s.ox_id = FNIC_SCR_REQ_OXID;
+ fc_abts_s.did[2] = 0xFD;
+ break;
+
+ case FDLS_STATE_REGISTER_FC4_TYPES:
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID(pfc_abts, fcid);
+ fc_abts_s.ox_id = FNIC_RFT_REQ_OXID;
+ fc_abts_s.did[2] = 0xFC;
+ break;
+
+ case FDLS_STATE_REGISTER_FC4_FEATURES:
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID(pfc_abts, fcid);
+ fc_abts_s.ox_id = FNIC_RFF_REQ_OXID;
+ fc_abts_s.did[2] = 0xFC;
+ break;
+
+ case FDLS_STATE_GPN_FT:
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID(pfc_abts, fcid);
+ fc_abts_s.ox_id = FNIC_GPN_FT_OXID;
+ fc_abts_s.did[2] = 0xFC;
+ break;
+ default:
+ return;
+ }
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS sending fabric abts. iport->fabric.state: %d",
+ iport->fabric.state);
+
+ iport->fabric.flags |= FNIC_FDLS_FABRIC_ABORT_ISSUED;
+ fnic_send_fcoe_frame(iport, &fc_abts_s, sizeof(struct fc_hdr_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+
+ fdls_start_fabric_timer(iport, 2 * iport->r_a_tov);
+ iport->fabric.timer_pending = 1;
+}
+
+static void fdls_send_fabric_flogi(struct fnic_iport_s *iport)
+{
+ struct fc_els_s flogi;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS send fabric FLOGI", iport->fcid);
+
+ memcpy(&flogi, &fnic_flogi_req, sizeof(struct fc_els_s));
+ FNIC_SET_NPORT_NAME(flogi, iport->wwpn);
+ FNIC_SET_NODE_NAME(flogi, iport->wwnn);
+ FNIC_SET_RDF_SIZE(flogi.u.csp_flogi, iport->max_payload_size);
+ FNIC_SET_R_A_TOV(flogi.u.csp_flogi, iport->r_a_tov);
+ FNIC_SET_E_D_TOV(flogi.u.csp_flogi, iport->e_d_tov);
+
+ fnic_send_fcoe_frame(iport, &flogi, sizeof(struct fc_els_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+}
+
+
+static void fdls_send_fabric_plogi(struct fnic_iport_s *iport)
+{
+ struct fc_els_s plogi;
+ struct fc_hdr_s *fchdr = &plogi.fchdr;
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS send fabric PLOGI", iport->fcid);
+
+ memcpy(&plogi, &fnic_plogi_req, sizeof(struct fc_els_s));
+
+ hton24(fcid, iport->fcid);
+
+ FNIC_SET_S_ID(fchdr, fcid);
+ FNIC_SET_NPORT_NAME(plogi, iport->wwpn);
+ FNIC_SET_NODE_NAME(plogi, iport->wwnn);
+ FNIC_SET_RDF_SIZE(plogi.u.csp_plogi, iport->max_payload_size);
+
+ fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+}
+
+static void fdls_send_rpn_id(struct fnic_iport_s *iport)
+{
+ struct fc_rpn_id_s rpn_id;
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS send RPN ID", iport->fcid);
+
+ memcpy(&rpn_id, &fnic_rpn_id_req, sizeof(struct fc_rpn_id_s));
+
+ hton24(fcid, iport->fcid);
+
+ FNIC_SET_S_ID((&rpn_id.fchdr), fcid);
+ FNIC_SET_RPN_PORT_ID((&rpn_id), fcid);
+ FNIC_SET_RPN_PORT_NAME((&rpn_id), iport->wwpn);
+
+ fnic_send_fcoe_frame(iport, &rpn_id, sizeof(struct fc_rpn_id_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+}
+
+static void fdls_send_scr(struct fnic_iport_s *iport)
+{
+ struct fc_scr_s scr_req;
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS send SCR", iport->fcid);
+
+ memcpy(&scr_req, &fnic_scr_req, sizeof(struct fc_scr_s));
+
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID((&scr_req.fchdr), fcid);
+
+ fnic_send_fcoe_frame(iport, &scr_req, sizeof(struct fc_scr_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+}
+
+static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state)
+{
+ struct fc_gpn_ft_s gpn_ft;
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS send GPN FT", iport->fcid);
+
+ memcpy(&gpn_ft, &fnic_gpn_ft_req, sizeof(struct fc_gpn_ft_s));
+
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID((&gpn_ft.fchdr), fcid);
+ fnic_send_fcoe_frame(iport, &gpn_ft, sizeof(struct fc_gpn_ft_s));
+ /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+ fdls_set_state((&iport->fabric), fdls_state);
+}
+
+static void fdls_send_register_fc4_types(struct fnic_iport_s *iport)
+{
+ struct fc_rft_id rft_id;
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS sending FC4 Types", iport->fcid);
+
+ memset(&rft_id, 0, sizeof(struct fc_rft_id));
+ memcpy(&rft_id, &fnic_rft_id_req, sizeof(struct fc_rft_id));
+ hton24(fcid, iport->fcid);
+
+ FNIC_SET_S_ID((&rft_id.fchdr), fcid);
+ FNIC_SET_PORT_ID((&rft_id), fcid);
+ if (IS_FNIC_FCP_INITIATOR(fnic))
+ rft_id.fc4_types[2] = 1;
+
+ rft_id.fc4_types[7] = 1;
+ fnic_send_fcoe_frame(iport, &rft_id, sizeof(struct fc_rft_id));
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+}
+
+static void fdls_send_register_fc4_features(struct fnic_iport_s *iport)
+{
+ struct fc_rff_id rff_id;
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS sending FC4 features", iport->fcid);
+ memcpy(&rff_id, &fnic_rff_id_req, sizeof(struct fc_rff_id));
+
+ hton24(fcid, iport->fcid);
+
+ FNIC_SET_S_ID((&rff_id.fchdr), fcid);
+ FNIC_SET_PORT_ID((&rff_id), fcid);
+
+ if (IS_FNIC_FCP_INITIATOR(fnic)) {
+ rff_id.fc4_type = 0x08;
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Unknown type", iport->fcid);
+ }
+
+ fnic_send_fcoe_frame(iport, &rff_id, sizeof(struct fc_rff_id));
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+}
+
+/***********************************************************************
+ * fdls_send_fabric_logo
+ *
+ * \brief Send flogo to the fcf
+ *
+ * \param[in] iport Handle to fnic iport.
+ *
+ * \param[in] start_timer 1 if we want to start a perodic timer else 0
+ *
+ * \retval void
+ *
+ * \locks Currently this assumes to be called with fnic lock held
+ *
+ * \note This function does not change or check the fabric state.
+ * It the caller responsibility to set the appropriate iport fabric
+ * state when this is called. Normall its FDLS_STATE_FABRIC_LOGO.
+ * fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_LOGO)
+ * \note Locking can be changed and made bit granuler in future
+ *
+ ***********************************************************************/
+void fdls_send_fabric_logo(struct fnic_iport_s *iport)
+{
+ struct fc_logo_req_s logo;
+ uint8_t s_id[3];
+ uint8_t d_id[3] = { 0xFF, 0xFF, 0xFE };
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Sending logo to fabric from iport->fcid: 0x%x",
+ iport->fcid);
+ memcpy(&logo, &fnic_logo_req, sizeof(struct fc_logo_req_s));
+
+ hton24(s_id, iport->fcid);
+
+ FNIC_SET_S_ID((&logo.fchdr), s_id);
+ FNIC_SET_D_ID((&logo.fchdr), d_id);
+ FNIC_SET_OX_ID((&logo.fchdr), FNIC_FLOGO_REQ_OXID);
+
+ memcpy(&logo.fcid, s_id, 3);
+ logo.wwpn = htonll(iport->wwpn);
+
+ fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
+
+ iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+ fnic_send_fcoe_frame(iport, &logo, sizeof(struct fc_logo_req_s));
+}
+
+void fdls_fabric_timer_callback(struct timer_list *t)
+{
+ struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, retry_timer);
+ struct fnic_iport_s *iport =
+ container_of(fabric, struct fnic_iport_s, fabric);
+ struct fnic *fnic = iport->fnic;
+ unsigned long flags;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "tp: %d fab state: %d fab retry counter: %d max_flogi_retries: %d",
+ iport->fabric.timer_pending, iport->fabric.state,
+ iport->fabric.retry_counter, iport->max_flogi_retries);
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+
+ if (!iport->fabric.timer_pending) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+
+ if (iport->fabric.del_timer_inprogress) {
+ iport->fabric.del_timer_inprogress = 0;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fabric_del_timer inprogress(%d). Skip timer cb",
+ iport->fabric.del_timer_inprogress);
+ return;
+ }
+
+ iport->fabric.timer_pending = 0;
+
+ /* The fabric state indicates which frames have time out, and we retry */
+ switch (iport->fabric.state) {
+ case FDLS_STATE_FABRIC_FLOGI:
+ /* Flogi received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < iport->max_flogi_retries)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_fabric_flogi(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* Flogi has time out 2*ed_tov send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
+ fdls_send_fabric_abts(iport);
+ } else {
+ /* Flogi ABTS has timed out and we have waited
+ * (2 * ra_tov), we can retry safely with same
+ * exchange id
+ */
+ if (iport->fabric.retry_counter < iport->max_flogi_retries) {
+ iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+ fdls_send_fabric_flogi(iport);
+ } else
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Exceeded max FLOGI retries");
+ }
+ break;
+ case FDLS_STATE_FABRIC_PLOGI:
+ /* Plogi received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < iport->max_plogi_retries)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_fabric_plogi(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* Plogi has timed out 2*ed_tov send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
+ fdls_send_fabric_abts(iport);
+ } else {
+ /* plogi ABTS has timed out and we have waited
+ * (2 * ra_tov) can retry safely with same
+ * exchange id
+ */
+ if (iport->fabric.retry_counter < iport->max_plogi_retries) {
+ iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+ fdls_send_fabric_plogi(iport);
+ } else
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Exceeded max PLOGI retries");
+ }
+ break;
+ case FDLS_STATE_RPN_ID:
+ /* Rpn_id received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_rpn_id(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* RPN have timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
+ fdls_send_fabric_abts(iport);
+ else
+ /* ABTS has timed out (2*ra_tov) */
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ break;
+ case FDLS_STATE_SCR:
+ /* scr received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_scr(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* scr have timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
+ fdls_send_fabric_abts(iport);
+ else {
+ /* ABTS has timed out (2*ra_tov), we give up */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ABTS timed out. Starting PLOGI: %p", iport);
+ fnic_fdls_start_plogi(iport);
+ }
+ break;
+ case FDLS_STATE_REGISTER_FC4_TYPES:
+ /* scr received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_register_fc4_types(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* RFT_ID timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
+ fdls_send_fabric_abts(iport);
+ } else {
+ /* ABTS has timed out (2*ra_tov), we give up */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ABTS timed out. Starting PLOGI: %p", iport);
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ }
+ break;
+ case FDLS_STATE_REGISTER_FC4_FEATURES:
+ /* scr received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_register_fc4_features(iport);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* scr have timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
+ fdls_send_fabric_abts(iport);
+ else {
+ /* ABTS has timed out (2*ra_tov), we give up */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ABTS timed out. Starting PLOGI %p", iport);
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ }
+ break;
+ case FDLS_STATE_RSCN_GPN_FT:
+ case FDLS_STATE_SEND_GPNFT:
+ case FDLS_STATE_GPN_FT:
+ /* GPN_FT received a LS_RJT with busy we retry from here */
+ if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
+ && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
+ iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
+ fdls_send_gpn_ft(iport, iport->fabric.state);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /* gpn_gt have timed out send abts */
+ if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
+ fdls_send_fabric_abts(iport);
+ } else {
+ /*
+ * ABTS has timed out have waited (2*ra_tov) can
+ * retry safely with same exchange id
+ */
+ if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
+ fdls_send_gpn_ft(iport, iport->fabric.state);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "ABTS timeout for fabric GPN_FT. Check name server: %p",
+ iport);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
+{
+ iport->fabric.retry_counter = 0;
+ fdls_send_fabric_flogi(iport);
+ fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_FLOGI);
+ iport->fabric.flags = 0;
+}
+
+static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
+{
+ iport->fabric.retry_counter = 0;
+ fdls_send_fabric_plogi(iport);
+ fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
+ iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+}
+
+static void
+fdls_process_rff_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fnic *fnic = iport->fnic;
+ struct fnic_fdls_fabric_s *fdls = &iport->fabric;
+ struct fc_rff_id *rff_rsp = (struct fc_rff_id *) fchdr;
+ uint16_t rsp;
+ uint8_t reason_code;
+
+ if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_FEATURES) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RFF_ID resp recvd in state(%d). Dropping.",
+ fdls_get_state(fdls));
+ return;
+ }
+
+ rsp = FNIC_GET_FC_CT_CMD((&rff_rsp->fc_ct_hdr));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS process RFF ID response: 0x%04x", iport->fcid,
+ (uint32_t) rsp);
+
+ switch (rsp) {
+ case FC_CT_ACC:
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ fdls->retry_counter = 0;
+ fdls_set_state((&iport->fabric), FDLS_STATE_SCR);
+ fdls_send_scr(iport);
+ break;
+ case FC_CT_REJ:
+ reason_code = rff_rsp->fc_ct_hdr.reason_code;
+ if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
+ || (reason_code == FC_CT_RJT_BUSY))
+ && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RFF_ID ret FC_LS_REJ BUSY. Retry from timer routine %p",
+ iport);
+
+ /* Retry again from the timer routine */
+ fdls->flags |= FNIC_FDLS_RETRY_FRAME;
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RFF_ID returned FC_LS_REJ. Halting discovery %p", iport);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ fdls->timer_pending = 0;
+ fdls->retry_counter = 0;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+fdls_process_rft_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fnic_fdls_fabric_s *fdls = &iport->fabric;
+ struct fc_rft_id *rft_rsp = (struct fc_rft_id *) fchdr;
+ uint16_t rsp;
+ uint8_t reason_code;
+ struct fnic *fnic = iport->fnic;
+
+ if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_TYPES) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RFT_ID resp recvd in state(%d). Dropping.",
+ fdls_get_state(fdls));
+ return;
+ }
+
+ rsp = FNIC_GET_FC_CT_CMD((&rft_rsp->fc_ct_hdr));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS process RFT ID response: 0x%04x", iport->fcid,
+ (uint32_t) rsp);
+
+ switch (rsp) {
+ case FC_CT_ACC:
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ fdls->retry_counter = 0;
+ fdls_send_register_fc4_features(iport);
+ fdls_set_state((&iport->fabric), FDLS_STATE_REGISTER_FC4_FEATURES);
+ break;
+ case FC_CT_REJ:
+ reason_code = rft_rsp->fc_ct_hdr.reason_code;
+ if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
+ || (reason_code == FC_CT_RJT_BUSY))
+ && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: RFT_ID ret FC_LS_REJ BUSY. Retry from timer routine",
+ iport->fcid);
+
+ /* Retry again from the timer routine */
+ fdls->flags |= FNIC_FDLS_RETRY_FRAME;
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: RFT_ID REJ. Halting discovery reason %d expl %d",
+ iport->fcid, reason_code,
+ rft_rsp->fc_ct_hdr.reason_expl);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ fdls->timer_pending = 0;
+ fdls->retry_counter = 0;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+fdls_process_rpn_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fnic_fdls_fabric_s *fdls = &iport->fabric;
+ struct fc_rpn_id_s *rpn_rsp = (struct fc_rpn_id_s *) fchdr;
+ uint16_t rsp;
+ uint8_t reason_code;
+ struct fnic *fnic = iport->fnic;
+
+ if (fdls_get_state(fdls) != FDLS_STATE_RPN_ID) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RPN_ID resp recvd in state(%d). Dropping.",
+ fdls_get_state(fdls));
+ return;
+ }
+
+ rsp = FNIC_GET_FC_CT_CMD((&rpn_rsp->fc_ct_hdr));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS process RPN ID response: 0x%04x", iport->fcid,
+ (uint32_t) rsp);
+
+ switch (rsp) {
+ case FC_CT_ACC:
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ fdls->retry_counter = 0;
+ fdls_send_register_fc4_types(iport);
+ fdls_set_state((&iport->fabric), FDLS_STATE_REGISTER_FC4_TYPES);
+ break;
+ case FC_CT_REJ:
+ reason_code = rpn_rsp->fc_ct_hdr.reason_code;
+ if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
+ || (reason_code == FC_CT_RJT_BUSY))
+ && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RPN_ID returned REJ BUSY. Retry from timer routine %p",
+ iport);
+
+ /* Retry again from the timer routine */
+ fdls->flags |= FNIC_FDLS_RETRY_FRAME;
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RPN_ID FC_LS_REJ. Halting discovery %p", iport);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ fdls->timer_pending = 0;
+ fdls->retry_counter = 0;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fnic_fdls_fabric_s *fdls = &iport->fabric;
+ struct fc_scr_s *scr_rsp = (struct fc_scr_s *) fchdr;
+ struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS process SCR response: 0x%04x",
+ (uint32_t) scr_rsp->command);
+
+ if (fdls_get_state(fdls) != FDLS_STATE_SCR) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "SCR resp recvd in state(%d). Dropping.",
+ fdls_get_state(fdls));
+ return;
+ }
+
+ switch (scr_rsp->command) {
+ case FC_LS_ACC:
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ iport->fabric.retry_counter = 0;
+ fdls_send_gpn_ft(iport, FDLS_STATE_GPN_FT);
+ break;
+
+ case FC_LS_REJ:
+ if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
+ || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
+ && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "SCR FC_LS_REJ BUSY. Retry from timer routine %p",
+ iport);
+ /* Retry again from the timer routine */
+ fdls->flags |= FNIC_FDLS_RETRY_FRAME;
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "SCR returned FC_LS_REJ. Halting discovery %p",
+ iport);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ fdls->timer_pending = 0;
+ fdls->retry_counter = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
+ int len)
+{
+ struct fnic_fdls_fabric_s *fdls = &iport->fabric;
+ struct fc_gpn_ft_s *gpn_ft_rsp = (struct fc_gpn_ft_s *) fchdr;
+ uint16_t rsp;
+ uint8_t reason_code;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS process GPN_FT response: iport state: %d len: %d",
+ iport->state, len);
+
+ /*
+ * GPNFT response :-
+ * FDLS_STATE_GPN_FT : GPNFT send after SCR state
+ * during fabric discovery(FNIC_IPORT_STATE_FABRIC_DISC)
+ * FDLS_STATE_RSCN_GPN_FT : GPNFT send in response to RSCN
+ * FDLS_STATE_SEND_GPNFT : GPNFT send after deleting a Target,
+ * e.g. after receiving Target LOGO
+ * FDLS_STATE_TGT_DISCOVERY :Target discovery is currently in progress
+ * from previous GPNFT response,a new GPNFT response has come.
+ */
+ if (!(((iport->state == FNIC_IPORT_STATE_FABRIC_DISC)
+ && (fdls_get_state(fdls) == FDLS_STATE_GPN_FT))
+ || ((iport->state == FNIC_IPORT_STATE_READY)
+ && ((fdls_get_state(fdls) == FDLS_STATE_RSCN_GPN_FT)
+ || (fdls_get_state(fdls) == FDLS_STATE_SEND_GPNFT)
+ || (fdls_get_state(fdls) == FDLS_STATE_TGT_DISCOVERY))))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "GPNFT resp recvd in fab state(%d) iport_state(%d). Dropping.",
+ fdls_get_state(fdls), iport->state);
+ return;
+ }
+
+ iport->state = FNIC_IPORT_STATE_READY;
+ rsp = FNIC_GET_FC_CT_CMD((&gpn_ft_rsp->fc_ct_hdr));
+
+ switch (rsp) {
+
+ case FC_CT_ACC:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: GPNFT_RSP accept", iport->fcid);
+ break;
+
+ case FC_CT_REJ:
+ reason_code = gpn_ft_rsp->fc_ct_hdr.reason_code;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: GPNFT_RSP Reject", iport->fcid);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/***********************************************************************
+ * fdls_process_fabric_logo_rsp
+ *
+ * \brief Handles a flogo response from the fcf
+ *
+ * \param[in] iport Handle to fnic iport.
+ *
+ * \param[in] fchdr Incoming frame
+ *
+ * \retval void
+ *
+ *
+ ***********************************************************************/
+static void
+fdls_process_fabric_logo_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ struct fc_els_s *flogo_rsp = (struct fc_els_s *) fchdr;
+ struct fnic *fnic = iport->fnic;
+
+ switch (flogo_rsp->command) {
+ case FC_LS_ACC:
+ if (iport->fabric.state != FDLS_STATE_FABRIC_LOGO) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Flogo response. Fabric not in LOGO state. Dropping! %p",
+ iport);
+ return;
+ }
+
+ iport->fabric.state = FDLS_STATE_FLOGO_DONE;
+ iport->state = FNIC_IPORT_STATE_LINK_WAIT;
+
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "lport 0x%p Canceling fabric disc timer\n",
+ iport);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Flogo response from Fabric for did: 0x%x",
+ ntoh24(fchdr->did));
+ return;
+
+ case FC_LS_REJ:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Flogo response from Fabric for did: 0x%x returned FC_LS_REJ",
+ ntoh24(fchdr->did));
+ return;
+
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGO response not accepted or rejected: 0x%x",
+ flogo_rsp->command);
+ }
+}
+
+static void
+fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
+ void *rx_frame)
+{
+ struct fnic_fdls_fabric_s *fabric = &iport->fabric;
+ struct fc_els_s *flogi_rsp = (struct fc_els_s *) fchdr;
+ uint8_t *fcid;
+ int rdf_size;
+ struct fc_els_reject_s *els_rjt;
+ uint8_t fcmac[6] = { 0x0E, 0XFC, 0x00, 0x00, 0x00, 0x00 };
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS processing FLOGI response", iport->fcid);
+
+ if (fdls_get_state(fabric) != FDLS_STATE_FABRIC_FLOGI) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI response received in state (%d). Dropping frame",
+ fdls_get_state(fabric));
+ return;
+ }
+
+ switch (flogi_rsp->command) {
+ case FC_LS_ACC:
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport fcid: 0x%x Canceling fabric disc timer\n",
+ iport->fcid);
+ fnic_del_fabric_timer_sync();
+ }
+
+ iport->fabric.timer_pending = 0;
+ iport->fabric.retry_counter = 0;
+ fcid = FNIC_GET_D_ID(fchdr);
+ iport->fcid = ntoh24(fcid);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FLOGI response accepted", iport->fcid);
+
+ /* Learn the Service Params */
+ rdf_size = ntohs(flogi_rsp->u.csp_flogi.b2b_rdf_size);
+ if ((rdf_size >= FNIC_MIN_DATA_FIELD_SIZE)
+ && (rdf_size < FNIC_FC_MAX_PAYLOAD_LEN))
+ iport->max_payload_size = MIN(rdf_size,
+ iport->max_payload_size);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "max_payload_size from fabric: %d set: %d", rdf_size,
+ iport->max_payload_size);
+
+ iport->r_a_tov = ntohl(flogi_rsp->u.csp_flogi.r_a_tov);
+ iport->e_d_tov = ntohl(flogi_rsp->u.csp_flogi.e_d_tov);
+
+ if (flogi_rsp->u.csp_flogi.features & FNIC_FC_EDTOV_NSEC)
+ iport->e_d_tov = iport->e_d_tov / FNIC_NSEC_TO_MSEC;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "From fabric: R_A_TOV: %d E_D_TOV: %d",
+ iport->r_a_tov, iport->e_d_tov);
+
+ if (IS_FNIC_FCP_INITIATOR(fnic)) {
+ fc_host_fabric_name(iport->fnic->lport->host) =
+ get_unaligned_be64(&flogi_rsp->node_name);
+ fc_host_port_id(iport->fnic->lport->host) = iport->fcid;
+ }
+
+ fnic_fdls_learn_fcoe_macs(iport, rx_frame, fcid);
+
+ memcpy(&fcmac[3], fcid, 3);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Adding vNIC device MAC addr: %02x:%02x:%02x:%02x:%02x:%02x",
+ fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
+ fcmac[5]);
+ vnic_dev_add_addr(iport->fnic->vdev, fcmac);
+
+ if (fdls_get_state(fabric) == FDLS_STATE_FABRIC_FLOGI) {
+ fnic_fdls_start_plogi(iport);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI response received. Starting PLOGI");
+ } else {
+ /* From FDLS_STATE_FABRIC_FLOGI state fabric can only go to
+ * FDLS_STATE_LINKDOWN
+ * state, hence we don't have to worry about undoing:
+ * the fnic_fdls_register_portid and vnic_dev_add_addr
+ */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI response received in state (%d). Dropping frame",
+ fdls_get_state(fabric));
+ }
+ break;
+
+ case FC_LS_REJ:
+ els_rjt = (struct fc_els_reject_s *) fchdr;
+ if (fabric->retry_counter < iport->max_flogi_retries) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI returned FC_LS_REJ BUSY. Retry from timer routine %p",
+ iport);
+
+ /* Retry Flogi again from the timer routine. */
+ fabric->flags |= FNIC_FDLS_RETRY_FRAME;
+
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI returned FC_LS_REJ. Halting discovery %p", iport);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport 0x%p Canceling fabric disc timer\n",
+ iport);
+ fnic_del_fabric_timer_sync();
+ }
+ fabric->timer_pending = 0;
+ fabric->retry_counter = 0;
+ }
+ break;
+
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI response not accepted: 0x%x",
+ flogi_rsp->command);
+ break;
+ }
+}
+
+static void
+fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ struct fc_els_s *plogi_rsp = (struct fc_els_s *) fchdr;
+ struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
+ struct fnic *fnic = iport->fnic;
+
+ if (fdls_get_state((&iport->fabric)) != FDLS_STATE_FABRIC_PLOGI) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Fabric PLOGI response received in state (%d). Dropping frame",
+ fdls_get_state(&iport->fabric));
+ return;
+ }
+
+ switch (plogi_rsp->command) {
+ case FC_LS_ACC:
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport fcid: 0x%x fabric PLOGI response: Accepted\n",
+ iport->fcid);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ iport->fabric.retry_counter = 0;
+ fdls_set_state(&iport->fabric, FDLS_STATE_RPN_ID);
+ fdls_send_rpn_id(iport);
+ break;
+ case FC_LS_REJ:
+ if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
+ || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
+ && (iport->fabric.retry_counter < iport->max_plogi_retries)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Fabric PLOGI FC_LS_REJ BUSY. Retry from timer routine",
+ iport->fcid);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: Fabric PLOGI FC_LS_REJ. Halting discovery",
+ iport->fcid);
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport fcid: 0x%x Canceling fabric disc timer\n",
+ iport->fcid);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ iport->fabric.retry_counter = 0;
+ return;
+ }
+ break;
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PLOGI response not accepted: 0x%x",
+ plogi_rsp->command);
+ break;
+ }
+}
+
+static void
+fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ uint32_t s_id;
+ struct fc_abts_ba_acc_s *ba_acc = (struct fc_abts_ba_acc_s *) fchdr;
+ struct fc_abts_ba_rjt_s *ba_rjt;
+ uint32_t fabric_state = iport->fabric.state;
+ struct fnic *fnic = iport->fnic;
+
+ s_id = ntoh24(fchdr->sid);
+ ba_rjt = (struct fc_abts_ba_rjt_s *) fchdr;
+
+ if (!((s_id == FC_DIR_SERVER) || (s_id == FC_DOMAIN_CONTR)
+ || (s_id == FC_FABRIC_CONTROLLER))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received abts rsp with invalid SID: 0x%x. Dropping frame",
+ s_id);
+ return;
+ }
+
+ if (iport->fabric.timer_pending) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Canceling fabric disc timer %p\n", iport);
+ fnic_del_fabric_timer_sync();
+ }
+ iport->fabric.timer_pending = 0;
+ iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+
+ if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received abts rsp BA_ACC for fabric_state: %d OX_ID: 0x%x",
+ fabric_state, ba_acc->ox_id);
+ } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "BA_RJT fs: %d OX_ID: 0x%x rc: 0x%x rce: 0x%x",
+ fabric_state, ba_rjt->fchdr.ox_id,
+ ba_rjt->reason_code, ba_rjt->reason_explanation);
+ }
+
+ /* currently error handling/retry logic is same for ABTS BA_ACC & BA_RJT */
+ switch (fabric_state) {
+ case FDLS_STATE_FABRIC_FLOGI:
+ if (fchdr->ox_id == FNIC_FLOGI_OXID) {
+ if (iport->fabric.retry_counter < iport->max_flogi_retries)
+ fdls_send_fabric_flogi(iport);
+ else
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Exceeded max FLOGI retries");
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x FABRIC_FLOGI state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+ case FDLS_STATE_FABRIC_LOGO:
+ if (fchdr->ox_id == FNIC_FLOGO_REQ_OXID) {
+ if (!RETRIES_EXHAUSTED(iport))
+ fdls_send_fabric_logo(iport);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x FABRIC_FLOGI state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+ case FDLS_STATE_FABRIC_PLOGI:
+ if (fchdr->ox_id == FNIC_PLOGI_FABRIC_OXID) {
+ if (iport->fabric.retry_counter < iport->max_plogi_retries)
+ fdls_send_fabric_plogi(iport);
+ else
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Exceeded max PLOGI retries");
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x FABRIC_PLOGI state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+
+ case FDLS_STATE_RPN_ID:
+ if (fchdr->ox_id == FNIC_RPN_REQ_OXID) {
+ if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
+ fdls_send_rpn_id(iport);
+ } else {
+ /* go back to fabric Plogi */
+ fnic_fdls_start_plogi(iport);
+ }
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x RPN_ID state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+
+ case FDLS_STATE_SCR:
+ if (fchdr->ox_id == FNIC_SCR_REQ_OXID) {
+ if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT)
+ fdls_send_scr(iport);
+ else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "abts rsp fab SCR after two tries. Start fabric PLOGI %p",
+ iport);
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ }
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x SCR state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+ case FDLS_STATE_REGISTER_FC4_TYPES:
+ if (fchdr->ox_id == FNIC_RFT_REQ_OXID) {
+ if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT) {
+ fdls_send_register_fc4_types(iport);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "abts rsp fab RFT_ID two tries. Start fabric PLOGI %p",
+ iport);
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ }
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x RFT state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+ case FDLS_STATE_REGISTER_FC4_FEATURES:
+ if (fchdr->ox_id == FNIC_RFF_REQ_OXID) {
+ if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT)
+ fdls_send_register_fc4_features(iport);
+ else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "abts rsp fab SCR after two tries. Start fabric PLOGI %p",
+ iport);
+ fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
+ }
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x RFF state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+
+ case FDLS_STATE_GPN_FT:
+ if (fchdr->ox_id == FNIC_GPN_FT_OXID) {
+ if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT) {
+ fdls_send_gpn_ft(iport, fabric_state);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "abts rsp fab GPN_FT after two tries %p",
+ iport);
+ }
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown abts rsp OX_ID: 0x%x GPN_FT state. Drop frame",
+ fchdr->ox_id);
+ }
+ break;
+
+ default:
+ return;
+ }
+}
+
+/*
+ * Performs a validation for all FCOE frames and return the frame type
+ */
+int
+fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
+ void *rx_frame, int len,
+ int fchdr_offset)
+{
+ struct fc_hdr_s *fchdr;
+ uint8_t type;
+ uint8_t *fc_payload;
+ uint16_t oxid;
+ uint32_t s_id;
+ uint32_t d_id;
+ struct fnic *fnic = iport->fnic;
+ struct fnic_fdls_fabric_s *fabric = &iport->fabric;
+
+ fchdr = (struct fc_hdr_s *) ((uint8_t *) rx_frame + fchdr_offset);
+ oxid = FNIC_GET_OX_ID(fchdr);
+ fc_payload = (uint8_t *) fchdr + sizeof(struct fc_hdr_s);
+ type = *fc_payload;
+ s_id = ntoh24(fchdr->sid);
+ d_id = ntoh24(fchdr->did);
+
+ /* some common validation */
+ if (iport->fcid)
+ if (fdls_get_state(fabric) > FDLS_STATE_FABRIC_FLOGI) {
+ if ((iport->fcid != d_id) || (!FNIC_FC_FRAME_CS_CTL(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "invalid frame received. Dropping frame");
+ return -1;
+ }
+ }
+
+ /* ABTS response */
+ if ((fchdr->r_ctl == FNIC_BA_ACC_RCTL)
+ || (fchdr->r_ctl == FNIC_BA_RJT_RCTL)) {
+ if (!(FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received ABTS invalid frame. Dropping frame");
+ return -1;
+
+ }
+ return FNIC_BLS_ABTS_RSP;
+ }
+ if ((fchdr->r_ctl == FC_ABTS_RCTL) && (FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Receiving Abort Request from s_id: 0x%x", s_id);
+ return FNIC_BLS_ABTS_REQ;
+ }
+
+ /* unsolicited requests frames */
+ if (FNIC_FC_FRAME_UNSOLICITED(fchdr)) {
+ switch (type) {
+ case FC_ELS_LOGO:
+ if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
+ || (!FNIC_FC_FRAME_UNSOLICITED(fchdr))
+ || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received LOGO invalid frame. Dropping frame");
+ return -1;
+ }
+ return FNIC_ELS_LOGO_REQ;
+ case FC_ELS_RSCN:
+ if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
+ || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))
+ || (!FNIC_FC_FRAME_UNSOLICITED(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received RSCN invalid FCTL. Dropping frame");
+ return -1;
+ }
+ if (s_id != FC_FABRIC_CONTROLLER)
+ return FNIC_ELS_RSCN_REQ;
+ break;
+ case FC_ELS_PLOGI_REQ:
+ return FNIC_ELS_PLOGI_REQ;
+ case FC_ELS_ECHO_REQ:
+ return FNIC_ELS_ECHO_REQ;
+ case FNIC_ELS_ADISC_REQ:
+ return FNIC_ELS_ADISC;
+ case FC_ELS_RLS_REQ:
+ return FNIC_ELS_RLS;
+ case FC_ELS_RRQ_REQ:
+ return FNIC_ELS_RRQ;
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unsupported frame (type:0x%02x) from fcid: 0x%x",
+ type, s_id);
+ return FNIC_ELS_UNSUPPORTED_REQ;
+ }
+ }
+
+ /*response from fabric */
+ switch (oxid) {
+
+ case FNIC_FLOGO_REQ_OXID:
+ return FNIC_FABRIC_LOGO_RSP;
+
+ case FNIC_FLOGI_OXID:
+ if (type == FC_LS_ACC) {
+ if ((s_id != FC_DOMAIN_CONTR)
+ || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown frame. Dropping frame");
+ return -1;
+ }
+ }
+ return FNIC_FABRIC_FLOGI_RSP;
+
+ case FNIC_PLOGI_FABRIC_OXID:
+ if (type == FC_LS_ACC) {
+ if ((s_id != FC_DIR_SERVER)
+ || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown frame. Dropping frame");
+ return -1;
+ }
+ }
+ return FNIC_FABRIC_PLOGI_RSP;
+
+ case FNIC_SCR_REQ_OXID:
+ if (type == FC_LS_ACC) {
+ if ((s_id != FC_FABRIC_CONTROLLER)
+ || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown frame. Dropping frame");
+ return -1;
+ }
+ }
+ return FNIC_FABRIC_SCR_RSP;
+
+ case FNIC_RPN_REQ_OXID:
+ if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown frame. Dropping frame");
+ return -1;
+ }
+ return FNIC_FABRIC_RPN_RSP;
+ case FNIC_RFT_REQ_OXID:
+ if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown frame. Dropping frame");
+ return -1;
+ }
+ return FNIC_FABRIC_RFT_RSP;
+ case FNIC_RFF_REQ_OXID:
+ if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown frame. Dropping frame");
+ return -1;
+ }
+ return FNIC_FABRIC_RFF_RSP;
+
+ case FNIC_GPN_FT_OXID:
+ if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown frame. Dropping frame");
+ return -1;
+ }
+ return FNIC_FABRIC_GPN_FT_RSP;
+
+ default:
+ /* Drop the Rx frame and log/stats it */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Solicited response: unknown OXID: 0x%x", oxid);
+ return -1;
+ }
+ return -1;
+}
+
+void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
+ int len, int fchdr_offset)
+{
+ uint16_t oxid;
+ struct fc_hdr_s *fchdr;
+ uint32_t s_id = 0;
+ uint32_t d_id = 0;
+ struct fnic *fnic = iport->fnic;
+ int frame_type;
+
+ fchdr = (struct fc_hdr_s *) ((uint8_t *) rx_frame + fchdr_offset);
+ s_id = ntoh24(fchdr->sid);
+ d_id = ntoh24(fchdr->did);
+
+ frame_type =
+ fnic_fdls_validate_and_get_frame_type(iport, rx_frame, len,
+ fchdr_offset);
+
+ /*if we are in flogo drop everything else */
+ if (iport->fabric.state == FDLS_STATE_FABRIC_LOGO &&
+ frame_type != FNIC_FABRIC_LOGO_RSP)
+ return;
+
+ switch (frame_type) {
+ case FNIC_FABRIC_FLOGI_RSP:
+ fdls_process_flogi_rsp(iport, fchdr, rx_frame);
+ break;
+ case FNIC_FABRIC_PLOGI_RSP:
+ fdls_process_fabric_plogi_rsp(iport, fchdr);
+ break;
+ case FNIC_FABRIC_RPN_RSP:
+ fdls_process_rpn_id_rsp(iport, fchdr);
+ break;
+ case FNIC_FABRIC_RFT_RSP:
+ fdls_process_rft_id_rsp(iport, fchdr);
+ break;
+ case FNIC_FABRIC_RFF_RSP:
+ fdls_process_rff_id_rsp(iport, fchdr);
+ break;
+ case FNIC_FABRIC_SCR_RSP:
+ fdls_process_scr_rsp(iport, fchdr);
+ break;
+ case FNIC_FABRIC_GPN_FT_RSP:
+ fdls_process_gpn_ft_rsp(iport, fchdr, len);
+ break;
+ case FNIC_FABRIC_LOGO_RSP:
+ fdls_process_fabric_logo_rsp(iport, fchdr);
+ break;
+
+ case FNIC_BLS_ABTS_RSP:
+ oxid = FNIC_GET_OX_ID(fchdr);
+ if ((iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)
+ && (oxid >= FNIC_FLOGI_OXID && oxid <= FNIC_RFF_REQ_OXID)) {
+ fdls_process_fabric_abts_rsp(iport, fchdr);
+ }
+ break;
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received unknown FCoE frame of len: %d. Dropping frame", len);
+ break;
+ }
+}
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index ce73f08ee889..2d5f438f2cc4 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -24,6 +24,7 @@
#include "vnic_intr.h"
#include "vnic_stats.h"
#include "vnic_scsi.h"
+#include "fnic_fdls.h"

#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
@@ -31,6 +32,7 @@
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "

+#define FABRIC_LOGO_MAX_RETRY 3
#define DESC_CLEAN_LOW_WATERMARK 8
#define FNIC_UCSM_DFLT_THROTTLE_CNT_BLD 16 /* UCSM default throttle count */
#define FNIC_MIN_IO_REQ 256 /* Min IO throttle count */
@@ -75,6 +77,8 @@
#define FNIC_DEV_RST_TERM_DONE BIT(20)
#define FNIC_DEV_RST_ABTS_PENDING BIT(21)

+#define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)
+
/*
* fnic private data per SCSI command.
* These fields are locked by the hashed io_req_lock.
@@ -213,12 +217,26 @@ enum fnic_state {

struct mempool;

+enum fnic_role_e {
+ FNIC_ROLE_FCP_INITIATOR = 0,
+};
+
enum fnic_evt {
FNIC_EVT_START_VLAN_DISC = 1,
FNIC_EVT_START_FCF_DISC = 2,
FNIC_EVT_MAX,
};

+struct fnic_frame_list {
+ /*
+ * Link to frame lists
+ */
+ struct list_head links;
+ void *fp;
+ int frame_len;
+ int rx_ethhdr_stripped;
+};
+
struct fnic_event {
struct list_head list;
struct fnic *fnic;
@@ -235,6 +253,8 @@ struct fnic_cpy_wq {
/* Per-instance private data structure */
struct fnic {
int fnic_num;
+ enum fnic_role_e role;
+ struct fnic_iport_s iport;
struct fc_lport *lport;
struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
struct vnic_dev_bar bar0;
@@ -278,6 +298,7 @@ struct fnic {
unsigned long state_flags; /* protected by host lock */
enum fnic_state state;
spinlock_t fnic_lock;
+ unsigned long lock_flags;

u16 vlan_id; /* VLAN tag including priority */
u8 data_src_addr[ETH_ALEN];
@@ -307,7 +328,7 @@ struct fnic {
struct work_struct frame_work;
struct work_struct flush_work;
struct sk_buff_head frame_queue;
- struct sk_buff_head tx_queue;
+ struct list_head tx_queue;

/*** FIP related data members -- start ***/
void (*set_vlan)(struct fnic *, u16 vlan);
@@ -397,7 +418,6 @@ void fnic_handle_fip_frame(struct work_struct *work);
void fnic_handle_fip_event(struct fnic *fnic);
void fnic_fcoe_reset_vlans(struct fnic *fnic);
void fnic_fcoe_evlist_free(struct fnic *fnic);
-extern void fnic_handle_fip_timer(struct fnic *fnic);

static inline int
fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
@@ -406,4 +426,6 @@ fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
}
void __fnic_set_state_flags(struct fnic *, unsigned long, unsigned long);
void fnic_dump_fchost_stats(struct Scsi_Host *, struct fc_host_statistics *);
+void fnic_free_txq(struct list_head *head);
+
#endif /* _FNIC_H_ */
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index a08293b2ad9f..90d0c4c8920c 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -20,6 +20,8 @@
#include "fnic_io.h"
#include "fnic.h"
#include "fnic_fip.h"
+#include "fnic_fdls.h"
+#include "fdls_fc.h"
#include "cq_enet_desc.h"
#include "cq_exch_desc.h"

@@ -28,12 +30,90 @@ struct workqueue_struct *fnic_fip_queue;
struct workqueue_struct *fnic_event_queue;

static void fnic_set_eth_mode(struct fnic *);
-static void fnic_fcoe_send_vlan_req(struct fnic *fnic);
static void fnic_fcoe_start_fcf_disc(struct fnic *fnic);
static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *);
static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag);
static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb);

+/* Frame initialization */
+/*
+ * Variables:
+ * dst_mac, src_mac
+ */
+struct fnic_eth_hdr_s fnic_eth_hdr_fcoe = {
+ .ether_type = 0x0689
+};
+
+/*
+ * Variables:
+ * None
+ */
+struct fnic_fcoe_hdr_s fnic_fcoe_hdr = {
+ .sof = 0x2E
+};
+
+uint8_t FCOE_ALL_FCF_MAC[6] = { 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe };
+
+/*
+ * Internal Functions
+ * This function will initialize the src_mac address to be
+ * used in outgoing frames
+ */
+static inline void fnic_fdls_set_fcoe_srcmac(struct fnic *fnic,
+ uint8_t *src_mac)
+{
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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]);
+
+ memcpy(fnic->iport.fpma, src_mac, 6);
+}
+
+/*
+ * This function will initialize the dst_mac address to be
+ * used in outgoing frames
+ */
+static inline void fnic_fdls_set_fcoe_dstmac(struct fnic *fnic,
+ uint8_t *dst_mac)
+{
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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]);
+
+ memcpy(fnic->iport.fcfmac, dst_mac, 6);
+}
+
+/*
+ * FPMA can be either taken from ethhdr(dst_mac) or flogi resp
+ * or derive from FC_MAP and FCID combination. While it should be
+ * same, revisit this if there is any possibility of not-correct.
+ */
+void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
+ uint8_t *fcid)
+{
+ struct fnic *fnic = iport->fnic;
+ struct fnic_eth_hdr_s *ethhdr = (struct fnic_eth_hdr_s *) rx_frame;
+ uint8_t fcmac[6] = { 0x0E, 0xFC, 0x00, 0x00, 0x00, 0x00 };
+
+ memcpy(&fcmac[3], fcid, 3);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "learn fcoe: dst_mac: %02x:%02x:%02x:%02x:%02x:%02x",
+ ethhdr->dst_mac[0], ethhdr->dst_mac[1],
+ ethhdr->dst_mac[2], ethhdr->dst_mac[3],
+ ethhdr->dst_mac[4], ethhdr->dst_mac[5]);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "learn fcoe: fc_mac: %02x:%02x:%02x:%02x:%02x:%02x",
+ fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
+ fcmac[5]);
+
+ fnic_fdls_set_fcoe_srcmac(fnic, fcmac);
+ fnic_fdls_set_fcoe_dstmac(fnic, ethhdr->src_mac);
+}
+
void fnic_handle_link(struct work_struct *work)
{
struct fnic *fnic = container_of(work, struct fnic, link_work);
@@ -363,7 +443,7 @@ static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip,
return 0;
}

-static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
+void fnic_fcoe_send_vlan_req(struct fnic *fnic)
{
struct fcoe_ctlr *fip = &fnic->ctlr;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
@@ -1068,116 +1148,125 @@ void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
/*
* Send FC frame.
*/
-static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
+static int fnic_send_frame(struct fnic *fnic, void *frame, int frame_len)
{
struct vnic_wq *wq = &fnic->wq[0];
- struct sk_buff *skb;
dma_addr_t pa;
- struct ethhdr *eth_hdr;
- struct vlan_ethhdr *vlan_hdr;
- struct fcoe_hdr *fcoe_hdr;
- struct fc_frame_header *fh;
- u32 tot_len, eth_hdr_len;
int ret = 0;
unsigned long flags;

- fh = fc_frame_header_get(fp);
- skb = fp_skb(fp);
+ pa = dma_map_single(&fnic->pdev->dev, frame, frame_len, DMA_TO_DEVICE);

- if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
- fcoe_ctlr_els_send(&fnic->ctlr, fnic->lport, skb))
- return 0;
+ if ((fnic_fc_trace_set_data(fnic->fnic_num,
+ FNIC_FC_SEND | 0x80, (char *) frame,
+ frame_len)) != 0) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic ctlr frame trace error");
+ }

- if (!fnic->vlan_hw_insert) {
- eth_hdr_len = sizeof(*vlan_hdr) + sizeof(*fcoe_hdr);
- vlan_hdr = skb_push(skb, eth_hdr_len);
- eth_hdr = (struct ethhdr *)vlan_hdr;
- vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
- vlan_hdr->h_vlan_encapsulated_proto = htons(ETH_P_FCOE);
- vlan_hdr->h_vlan_TCI = htons(fnic->vlan_id);
- fcoe_hdr = (struct fcoe_hdr *)(vlan_hdr + 1);
- } else {
- eth_hdr_len = sizeof(*eth_hdr) + sizeof(*fcoe_hdr);
- eth_hdr = skb_push(skb, eth_hdr_len);
- eth_hdr->h_proto = htons(ETH_P_FCOE);
- fcoe_hdr = (struct fcoe_hdr *)(eth_hdr + 1);
+ spin_lock_irqsave(&fnic->wq_lock[0], flags);
+
+ if (!vnic_wq_desc_avail(wq)) {
+ dma_unmap_single(&fnic->pdev->dev, pa, frame_len, DMA_TO_DEVICE);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "vnic work queue descriptor is not available");
+ ret = -1;
+ goto fnic_send_frame_end;
}

- if (fnic->ctlr.map_dest)
- fc_fcoe_set_mac(eth_hdr->h_dest, fh->fh_d_id);
- else
- memcpy(eth_hdr->h_dest, fnic->ctlr.dest_addr, ETH_ALEN);
- memcpy(eth_hdr->h_source, fnic->data_src_addr, ETH_ALEN);
+ /* hw inserts cos value */
+ fnic_queue_wq_desc(wq, frame, pa, frame_len, FNIC_FCOE_EOF,
+ 0, fnic->vlan_id, 1, 1, 1);

- tot_len = skb->len;
- BUG_ON(tot_len % 4);
+fnic_send_frame_end:
+ spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
+ return ret;
+}

- memset(fcoe_hdr, 0, sizeof(*fcoe_hdr));
- fcoe_hdr->fcoe_sof = fr_sof(fp);
- if (FC_FCOE_VER)
- FC_FCOE_ENCAPS_VER(fcoe_hdr, FC_FCOE_VER);
+static int
+fdls_send_fcoe_frame(struct fnic *fnic, void *payload, int payload_sz,
+ uint8_t *srcmac, uint8_t *dstmac)
+{
+ uint8_t *frame;
+ struct fnic_eth_hdr_s *ethhdr;
+ struct fnic_frame_list *frame_elem;
+ int max_framesz = FNIC_FCOE_FRAME_MAXSZ;
+ int len = 0;
+ int ret;

- pa = dma_map_single(&fnic->pdev->dev, eth_hdr, tot_len, DMA_TO_DEVICE);
- if (dma_mapping_error(&fnic->pdev->dev, pa)) {
- ret = -ENOMEM;
- printk(KERN_ERR "DMA map failed with error %d\n", ret);
- goto free_skb_on_err;
+ frame = kmalloc(max_framesz, GFP_ATOMIC);
+ if (!frame) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to allocate frame for flogi\n");
+ return -ENOMEM;
}
+ memset(frame, 0, max_framesz);
+ ethhdr = (struct fnic_eth_hdr_s *) frame;

- if ((fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_SEND,
- (char *)eth_hdr, tot_len)) != 0) {
- printk(KERN_ERR "fnic ctlr frame trace error!!!");
- }
+ memcpy(frame, (uint8_t *) &fnic_eth_hdr_fcoe,
+ sizeof(struct fnic_eth_hdr_s));
+ len = sizeof(struct fnic_eth_hdr_s);

- spin_lock_irqsave(&fnic->wq_lock[0], flags);
+ memcpy(ethhdr->src_mac, srcmac, ETH_ALEN);
+ memcpy(ethhdr->dst_mac, dstmac, ETH_ALEN);

- if (!vnic_wq_desc_avail(wq)) {
- dma_unmap_single(&fnic->pdev->dev, pa, tot_len, DMA_TO_DEVICE);
- ret = -1;
- goto irq_restore;
- }
+ memcpy(frame + len, (uint8_t *) &fnic_fcoe_hdr,
+ sizeof(struct fnic_fcoe_hdr_s));
+ len += sizeof(struct fnic_fcoe_hdr_s);

- fnic_queue_wq_desc(wq, skb, pa, tot_len, fr_eof(fp),
- 0 /* hw inserts cos value */,
- fnic->vlan_id, 1, 1, 1);
+ memcpy(frame + len, (uint8_t *) payload, payload_sz);
+ len += payload_sz;

-irq_restore:
- spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
+ /*
+ * Queue frame if in a transitional state.
+ * This occurs while registering the Port_ID / MAC address after FLOGI.
+ */
+ if ((fnic->state != FNIC_IN_FC_MODE)
+ && (fnic->state != FNIC_IN_ETH_MODE)) {
+ frame_elem = kmalloc(sizeof(struct fnic_frame_list), GFP_ATOMIC);
+ if (!frame_elem) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to allocate memory for fnic_frame_list: %ld\n",
+ sizeof(struct fnic_frame_list));
+ return -ENOMEM;
+ }
+ memset(frame_elem, 0, sizeof(struct fnic_frame_list));

-free_skb_on_err:
- if (ret)
- dev_kfree_skb_any(fp_skb(fp));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Queuing frame: 0x%p\n", frame);

+ frame_elem->fp = frame;
+ frame_elem->frame_len = len;
+ list_add_tail(&frame_elem->links, &fnic->tx_queue);
+ return 0;
+ }
+
+ ret = fnic_send_frame(fnic, frame, len);
return ret;
}

-/*
- * fnic_send
- * Routine to send a raw frame
- */
-int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
+int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
+ int payload_sz)
{
- struct fnic *fnic = lport_priv(lp);
- unsigned long flags;
+ struct fnic *fnic = iport->fnic;
+ uint8_t *dstmac, *srcmac;
+ int ret = 0;

+ /* If module unload is in-progress, don't send */
if (fnic->in_remove) {
- dev_kfree_skb(fp_skb(fp));
return -1;
}

- /*
- * Queue frame if in a transitional state.
- * This occurs while registering the Port_ID / MAC address after FLOGI.
- */
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (fnic->state != FNIC_IN_FC_MODE && fnic->state != FNIC_IN_ETH_MODE) {
- skb_queue_tail(&fnic->tx_queue, fp_skb(fp));
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return 0;
+ if (iport->fabric.flags & FNIC_FDLS_FPMA_LEARNT) {
+ srcmac = iport->fpma;
+ dstmac = iport->fcfmac;
+ } else {
+ srcmac = iport->hwmac;
+ dstmac = FCOE_ALL_FCF_MAC;
}
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);

- return fnic_send_frame(fnic, fp);
+ ret = fdls_send_fcoe_frame(fnic, payload, payload_sz, srcmac, dstmac);
+ return ret;
}

/**
@@ -1193,13 +1282,64 @@ int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
void fnic_flush_tx(struct work_struct *work)
{
struct fnic *fnic = container_of(work, struct fnic, flush_work);
- struct sk_buff *skb;
struct fc_frame *fp;
+ struct fnic_frame_list *cur_frame, *next;

- while ((skb = skb_dequeue(&fnic->tx_queue))) {
- fp = (struct fc_frame *)skb;
- fnic_send_frame(fnic, fp);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Flush queued frames");
+
+ list_for_each_entry_safe(cur_frame, next, &fnic->tx_queue, links) {
+ fp = cur_frame->fp;
+ list_del(&cur_frame->links);
+ fnic_send_frame(fnic, fp, cur_frame->frame_len);
+ }
+}
+
+int
+fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
+ void *fp)
+{
+ struct fnic *fnic = iport->fnic;
+ struct fnic_eth_hdr_s *ethhdr;
+ int ret;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Setting port id: 0x%x fp: 0x%p fnic state: %d", port_id,
+ fp, fnic->state);
+
+ if (fp) {
+ ethhdr = (struct fnic_eth_hdr_s *) fp;
+ vnic_dev_add_addr(fnic->vdev, ethhdr->dst_mac);
+ }
+
+ /* Change state to reflect transition to FC mode */
+ 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->lport->host, fnic->fnic_num,
+ "Unexpected fnic state while processing FLOGI response\n");
+ return -1;
}
+
+ /*
+ * Send FLOGI registration to firmware to set up FC mode.
+ * The new address will be set up when registration completes.
+ */
+ ret = fnic_flogi_reg_handler(fnic, port_id);
+ if (ret < 0) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI registration error ret: %d fnic state: %d\n",
+ ret, fnic->state);
+ if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE)
+ fnic->state = FNIC_IN_ETH_MODE;
+
+ return -1;
+ }
+ iport->fabric.flags |= FNIC_FDLS_FPMA_LEARNT;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI registration success\n");
+ return 0;
}

/**
@@ -1240,6 +1380,17 @@ static void fnic_set_eth_mode(struct fnic *fnic)
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
}

+void fnic_free_txq(struct list_head *head)
+{
+ struct fnic_frame_list *cur_frame, *next;
+
+ list_for_each_entry_safe(cur_frame, next, head, links) {
+ list_del(&cur_frame->links);
+ kfree(cur_frame->fp);
+ kfree(cur_frame);
+ }
+}
+
static void fnic_wq_complete_frame_send(struct vnic_wq *wq,
struct cq_desc *cq_desc,
struct vnic_wq_buf *buf, void *opaque)
@@ -1319,88 +1470,3 @@ void fnic_fcoe_reset_vlans(struct fnic *fnic)
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
}

-void fnic_handle_fip_timer(struct fnic *fnic)
-{
- unsigned long flags;
- struct fcoe_vlan *vlan;
- struct fnic_stats *fnic_stats = &fnic->fnic_stats;
- u64 sol_time;
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (fnic->stop_rx_link_events) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
- if (fnic->ctlr.mode == FIP_MODE_NON_FIP)
- return;
-
- spin_lock_irqsave(&fnic->vlans_lock, flags);
- if (list_empty(&fnic->vlans)) {
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- /* no vlans available, try again */
- if (unlikely(fnic_log_level & FNIC_FCS_LOGGING))
- if (printk_ratelimit())
- shost_printk(KERN_DEBUG, fnic->lport->host,
- "Start VLAN Discovery\n");
- fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
- return;
- }
-
- vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fip_timer: vlan %d state %d sol_count %d\n",
- vlan->vid, vlan->state, vlan->sol_count);
- switch (vlan->state) {
- case FIP_VLAN_USED:
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "FIP VLAN is selected for FC transaction\n");
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- break;
- case FIP_VLAN_FAILED:
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- /* if all vlans are in failed state, restart vlan disc */
- if (unlikely(fnic_log_level & FNIC_FCS_LOGGING))
- if (printk_ratelimit())
- shost_printk(KERN_DEBUG, fnic->lport->host,
- "Start VLAN Discovery\n");
- fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
- break;
- case FIP_VLAN_SENT:
- if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
- /*
- * no response on this vlan, remove from the list.
- * Try the next vlan
- */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "Dequeue this VLAN ID %d from list\n",
- vlan->vid);
- list_del(&vlan->list);
- kfree(vlan);
- vlan = NULL;
- if (list_empty(&fnic->vlans)) {
- /* we exhausted all vlans, restart vlan disc */
- spin_unlock_irqrestore(&fnic->vlans_lock,
- flags);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "fip_timer: vlan list empty, "
- "trigger vlan disc\n");
- fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
- return;
- }
- /* check the next vlan */
- vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan,
- list);
- fnic->set_vlan(fnic, vlan->vid);
- vlan->state = FIP_VLAN_SENT; /* sent now */
- }
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- atomic64_inc(&fnic_stats->vlan_stats.sol_expiry_count);
- vlan->sol_count++;
- sol_time = jiffies + msecs_to_jiffies
- (FCOE_CTLR_START_DELAY);
- mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
- break;
- }
-}
diff --git a/drivers/scsi/fnic/fnic_fdls.h b/drivers/scsi/fnic/fnic_fdls.h
index fddb9390d022..095275698716 100644
--- a/drivers/scsi/fnic/fnic_fdls.h
+++ b/drivers/scsi/fnic/fnic_fdls.h
@@ -321,17 +321,20 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame, int len,
void fnic_fdls_link_down(struct fnic_iport_s *iport);
void fdls_init_tgt_oxid_pool(struct fnic_iport_s *iport);
void fdls_tgt_logout(struct fnic_iport_s *iport, struct fnic_tport_s *tport);
+void fdls_send_fabric_logo(struct fnic_iport_s *iport);
+int fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
+ void *rx_frame, int len,
+ int fchdr_offset);

/* fnic_fcs.c */
void fnic_fdls_init(struct fnic *fnic, int usefip);
int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
int payload_sz);
-
+void fnic_fcoe_send_vlan_req(struct fnic *fnic);
int fnic_send_fip_frame(struct fnic_iport_s *iport,
void *payload, int payload_sz);
void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
uint8_t *fcid);
-
void fnic_fdls_add_tport(struct fnic_iport_s *iport,
struct fnic_tport_s *tport, unsigned long flags);
void fnic_fdls_remove_tport(struct fnic_iport_s *iport,
diff --git a/drivers/scsi/fnic/fnic_io.h b/drivers/scsi/fnic/fnic_io.h
index 5895ead20e14..6fe642cb387b 100644
--- a/drivers/scsi/fnic/fnic_io.h
+++ b/drivers/scsi/fnic/fnic_io.h
@@ -55,15 +55,4 @@ struct fnic_io_req {
unsigned int tag;
struct scsi_cmnd *sc; /* midlayer's cmd pointer */
};
-
-enum fnic_port_speeds {
- DCEM_PORTSPEED_NONE = 0,
- DCEM_PORTSPEED_1G = 1000,
- DCEM_PORTSPEED_10G = 10000,
- DCEM_PORTSPEED_20G = 20000,
- DCEM_PORTSPEED_25G = 25000,
- DCEM_PORTSPEED_40G = 40000,
- DCEM_PORTSPEED_4x10G = 41000,
- DCEM_PORTSPEED_100G = 100000,
-};
#endif /* _FNIC_IO_H_ */
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 08730bdf8b03..577048e30c12 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -31,6 +31,8 @@
#include "fnic_io.h"
#include "fnic_fip.h"
#include "fnic.h"
+#include "fnic_fdls.h"
+#include "fdls_fc.h"

#define PCI_DEVICE_ID_CISCO_FNIC 0x0045

@@ -80,7 +82,6 @@ module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN");

static struct libfc_function_template fnic_transport_template = {
- .frame_send = fnic_send,
.lport_set_port_id = fnic_set_port_id,
.fcp_abort_io = fnic_empty_scsi_cleanup,
.fcp_cleanup = fnic_empty_scsi_cleanup,
@@ -413,7 +414,7 @@ static void fnic_fip_notify_timer(struct timer_list *t)
{
struct fnic *fnic = from_timer(fnic, t, fip_timer);

- fnic_handle_fip_timer(fnic);
+ /* Placeholder function */
}

static void fnic_notify_timer_start(struct fnic *fnic)
@@ -921,7 +922,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&fnic->link_work, fnic_handle_link);
INIT_WORK(&fnic->frame_work, fnic_handle_frame);
skb_queue_head_init(&fnic->frame_queue);
- skb_queue_head_init(&fnic->tx_queue);
+ INIT_LIST_HEAD(&fnic->tx_queue);

fc_fabric_login(lp);

@@ -1004,7 +1005,7 @@ static void fnic_remove(struct pci_dev *pdev)
*/
flush_workqueue(fnic_event_queue);
skb_queue_purge(&fnic->frame_queue);
- skb_queue_purge(&fnic->tx_queue);
+ fnic_free_txq(&fnic->tx_queue);

if (fnic->config.flags & VFCF_FIP_CAPABLE) {
del_timer_sync(&fnic->fip_timer);
@@ -1036,7 +1037,6 @@ static void fnic_remove(struct pci_dev *pdev)
fnic_cleanup(fnic);

BUG_ON(!skb_queue_empty(&fnic->frame_queue));
- BUG_ON(!skb_queue_empty(&fnic->tx_queue));

spin_lock_irqsave(&fnic_list_lock, flags);
list_del(&fnic->list);
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 2ba61dba4569..295dcda4ec16 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -184,7 +184,7 @@ int fnic_fw_reset_handler(struct fnic *fnic)
fnic_set_state_flags(fnic, FNIC_FLAGS_FWRESET);

skb_queue_purge(&fnic->frame_queue);
- skb_queue_purge(&fnic->tx_queue);
+ fnic_free_txq(&fnic->tx_queue);

/* wait for io cmpl */
while (atomic_read(&fnic->in_flight))
@@ -674,7 +674,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
*/
if (fnic->remove_wait || ret) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- skb_queue_purge(&fnic->tx_queue);
+ fnic_free_txq(&fnic->tx_queue);
goto reset_cmpl_handler_end;
}

@@ -1717,7 +1717,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
return true;
}

-static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
+void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
{
struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
struct fnic_rport_abort_io_iter_data iter_data = {
--
2.31.1


Subject: [PATCH 06/14] scsi: fnic: Add and integrate support for FDMI

Add support for Fabric-Device Management Interface
(FDMI) by introducing PCI device IDs for Cisco
Hardware.
Introduce a module parameter to enable/disable
FDMI support.
Integrate support for FDMI.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/Makefile | 3 +-
drivers/scsi/fnic/fdls_disc.c | 281 ++++++++++++++++++++++
drivers/scsi/fnic/fnic.h | 72 ++++++
drivers/scsi/fnic/fnic_fdls.h | 2 +-
drivers/scsi/fnic/fnic_main.c | 26 ++
drivers/scsi/fnic/fnic_pci_subsys_devid.c | 133 ++++++++++
6 files changed, 515 insertions(+), 2 deletions(-)
create mode 100644 drivers/scsi/fnic/fnic_pci_subsys_devid.c

diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
index 3bd6b1c8b643..af156c69da0c 100644
--- a/drivers/scsi/fnic/Makefile
+++ b/drivers/scsi/fnic/Makefile
@@ -16,4 +16,5 @@ fnic-y := \
vnic_intr.o \
vnic_rq.o \
vnic_wq_copy.o \
- vnic_wq.o
+ vnic_wq.o \
+ fnic_pci_subsys_devid.o
diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
index ad115de86f15..42127a70c369 100644
--- a/drivers/scsi/fnic/fdls_disc.c
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -14,6 +14,8 @@
#define FC_FC4_TYPE_SCSI 0x08

static void fdls_send_rpn_id(struct fnic_iport_s *iport);
+static void fdls_fdmi_register_hba(struct fnic_iport_s *iport);
+static void fdls_fdmi_register_pa(struct fnic_iport_s *iport);

/* Frame initialization */
/*
@@ -74,6 +76,66 @@ struct fc_els_prli_s fnic_prli_req = {
.sp = {.type = 0x08, .flags = 0x0020, .csp = 0xA2000000}
};

+/*
+ * Variables:
+ * sid, port_id, port_name
+ */
+struct fc_fdmi_rhba_s fnic_fdmi_rhba = {
+ .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0XFF, 0XFA}, .type = 0x20,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_FDMI_REG_HBA_OXID,
+ .rx_id = 0xFFFF},
+ .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFA, .fs_subtype = 0x10,
+ .command = 0x0002},
+ .num_ports = 0x1000000,
+ .num_hba_attributes = 0x9000000,
+ .type_nn = FNIC_FDMI_TYPE_NODE_NAME,
+ .length_nn = 0xc00,
+ .type_manu = FNIC_FDMI_TYPE_MANUFACTURER,
+ .length_manu = 0x1800,
+ .manufacturer = FNIC_FDMI_MANUFACTURER,
+ .type_serial = FNIC_FDMI_TYPE_SERIAL_NUMBER,
+ .length_serial = 0x1400,
+ .type_model = FNIC_FDMI_TYPE_MODEL,
+ .length_model = 0x1000,
+ .type_model_des = FNIC_FDMI_TYPE_MODEL_DES,
+ .length_model_des = 0x3c00,
+ .model_description = FNIC_FDMI_MODEL_DESCRIPTION,
+ .type_hw_ver = FNIC_FDMI_TYPE_HARDWARE_VERSION,
+ .length_hw_ver = 0x1400,
+ .type_dr_ver = FNIC_FDMI_TYPE_DRIVER_VERSION,
+ .length_dr_ver = 0x2000,
+ .type_rom_ver = FNIC_FDMI_TYPE_ROM_VERSION,
+ .length_rom_ver = 0xc00,
+ .type_fw_ver = FNIC_FDMI_TYPE_FIRMWARE_VERSION,
+ .length_fw_ver = 0x1400,
+};
+
+/*
+ * Variables
+ *sid, port_id, port_name
+ */
+struct fc_fdmi_rpa_s fnic_fdmi_rpa = {
+ .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFA}, .type = 0x20,
+ .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_FDMI_RPA_OXID,
+ .rx_id = 0xFFFF},
+ .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFA, .fs_subtype = 0x10,
+ .command = 0x1102},
+ .num_port_attributes = 0x6000000,
+ .type_fc4 = FNIC_FDMI_TYPE_FC4_TYPES,
+ .length_fc4 = 0x2400,
+ .type_supp_speed = FNIC_FDMI_TYPE_SUPPORTED_SPEEDS,
+ .length_supp_speed = 0x800,
+ .type_cur_speed = FNIC_FDMI_TYPE_CURRENT_SPEED,
+ .length_cur_speed = 0x800,
+ .type_max_frame_size = FNIC_FDMI_TYPE_MAX_FRAME_SIZE,
+ .length_max_frame_size = 0x800,
+ .max_frame_size = 0x0080000,
+ .type_os_name = FNIC_FDMI_TYPE_OS_NAME,
+ .length_os_name = 0x1400,
+ .type_host_name = FNIC_FDMI_TYPE_HOST_NAME,
+ .length_host_name = 0x1000,
+};
+
/*
* Variables:
* fh_s_id, port_id, port_name
@@ -172,6 +234,7 @@ static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
static void fdls_target_restart_nexus(struct fnic_tport_s *tport);
static void fdls_start_tport_timer(struct fnic_iport_s *iport,
struct fnic_tport_s *tport, int timeout);
+static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport);
static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
int timeout);
static void fdls_tport_timer_callback(struct timer_list *t);
@@ -453,6 +516,36 @@ static void fdls_send_fabric_plogi(struct fnic_iport_s *iport)
fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
}

+static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport)
+{
+ struct fc_els_s plogi;
+ struct fc_hdr_s *fchdr = &plogi.fchdr;
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+ u64 fdmi_tov;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fcid: 0x%x: FDLS send FDMI PLOGI", iport->fcid);
+
+ memcpy(&plogi, &fnic_plogi_req, sizeof(plogi));
+
+ hton24(fcid, iport->fcid);
+
+ FNIC_SET_S_ID(fchdr, fcid);
+ hton24(fcid, 0XFFFFFA);
+ FNIC_SET_D_ID(fchdr, fcid);
+ FNIC_SET_OX_ID(fchdr, FNIC_PLOGI_FDMI_OXID);
+ FNIC_SET_NPORT_NAME(plogi, iport->wwpn);
+ FNIC_SET_NODE_NAME(plogi, iport->wwnn);
+ FNIC_SET_RDF_SIZE(plogi.u.csp_plogi, iport->max_payload_size);
+
+ fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
+
+ fdmi_tov = jiffies + msecs_to_jiffies(5000);
+ mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov));
+ iport->fabric.fdmi_pending = 1;
+}
+
static void fdls_send_rpn_id(struct fnic_iport_s *iport)
{
struct fc_rpn_id_s rpn_id;
@@ -1015,6 +1108,92 @@ struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport,
return NULL;
}

+static void fdls_fdmi_register_hba(struct fnic_iport_s *iport)
+{
+ struct fc_fdmi_rhba_s fdmi_rhba;
+ uint8_t fcid[3];
+ uint16_t len;
+ int err;
+ struct fnic *fnic = iport->fnic;
+ struct vnic_devcmd_fw_info *fw_info = NULL;
+
+ memcpy(&fdmi_rhba, &fnic_fdmi_rhba, sizeof(struct fc_fdmi_rhba_s));
+
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID((&fdmi_rhba.fchdr), fcid);
+ fdmi_rhba.hba_identifier = htonll(iport->wwpn);
+ fdmi_rhba.port_name = htonll(iport->wwpn);
+ fdmi_rhba.node_name = htonll(iport->wwnn);
+
+ err = vnic_dev_fw_info(fnic->vdev, &fw_info);
+ if (!err) {
+ snprintf(fdmi_rhba.serial_num, sizeof(fdmi_rhba.serial_num) - 1,
+ "%s", fw_info->hw_serial_number);
+ snprintf(fdmi_rhba.hardware_ver,
+ sizeof(fdmi_rhba.hardware_ver) - 1, "%s",
+ fw_info->hw_version);
+ strscpy(fdmi_rhba.firmware_ver, fw_info->fw_version,
+ sizeof(fdmi_rhba.firmware_ver) - 1);
+
+ len = ARRAY_SIZE(fdmi_rhba.model);
+ if (fnic->subsys_desc_len >= len)
+ fnic->subsys_desc_len = len - 1;
+ memcpy(&fdmi_rhba.model, fnic->subsys_desc, fnic->subsys_desc_len);
+ fdmi_rhba.model[fnic->subsys_desc_len] = 0x00;
+ }
+
+ snprintf(fdmi_rhba.driver_ver, sizeof(fdmi_rhba.driver_ver) - 1, "%s",
+ DRV_VERSION);
+ snprintf(fdmi_rhba.rom_ver, sizeof(fdmi_rhba.rom_ver) - 1, "%s",
+ "N/A");
+ fnic_send_fcoe_frame(iport, &fdmi_rhba, sizeof(struct fc_fdmi_rhba_s));
+}
+
+static void fdls_fdmi_register_pa(struct fnic_iport_s *iport)
+{
+ struct fc_fdmi_rpa_s fdmi_rpa;
+
+ uint8_t fcid[3];
+ struct fnic *fnic = iport->fnic;
+ u32 port_speed_bm;
+ u32 port_speed = vnic_dev_port_speed(fnic->vdev);
+
+ memcpy(&fdmi_rpa, &fnic_fdmi_rpa, sizeof(struct fc_fdmi_rpa_s));
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID((&fdmi_rpa.fchdr), fcid);
+ fdmi_rpa.port_name = htonll(iport->wwpn);
+
+ /* MDS does not support GIGE speed */
+ switch (port_speed) {
+ case DCEM_PORTSPEED_10G:
+ case DCEM_PORTSPEED_20G:
+ /* There is no bit for 20G */
+ port_speed_bm = 0x010000;
+ break;
+ case DCEM_PORTSPEED_25G:
+ port_speed_bm = 0x080000;
+ break;
+ case DCEM_PORTSPEED_40G:
+ case DCEM_PORTSPEED_4x10G:
+ port_speed_bm = 0x020000;
+ break;
+ case DCEM_PORTSPEED_100G:
+ port_speed_bm = 0x040000;
+ break;
+ default:
+ port_speed_bm = 0x8000;
+ break;
+ }
+ fdmi_rpa.supported_speed = htonl(port_speed_bm);
+ fdmi_rpa.current_speed = htonl(port_speed_bm);
+ fdmi_rpa.fc4_type[2] = 1;
+ snprintf(fdmi_rpa.os_name, sizeof(fdmi_rpa.os_name) - 1, "host%d",
+ fnic->lport->host->host_no);
+ snprintf(fdmi_rpa.host_name, sizeof(fdmi_rpa.host_name) - 1, "%s",
+ utsname()->nodename);
+ fnic_send_fcoe_frame(iport, &fdmi_rpa, sizeof(struct fc_fdmi_rpa_s));
+}
+
void fdls_fabric_timer_callback(struct timer_list *t)
{
struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, retry_timer);
@@ -1205,6 +1384,23 @@ void fdls_fabric_timer_callback(struct timer_list *t)
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
}

+void fdls_fdmi_timer_callback(struct timer_list *t)
+{
+ struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, fdmi_timer);
+ struct fnic_iport_s *iport =
+ container_of(fabric, struct fnic_iport_s, fabric);
+ struct fnic *fnic = iport->fnic;
+
+ if (iport->fabric.fdmi_retry < 7) {
+ iport->fabric.fdmi_retry++;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "retry fdmi timer %d", iport->fabric.fdmi_retry);
+ fdls_send_fdmi_plogi(iport);
+ } else {
+ iport->fabric.fdmi_pending = 0;
+ }
+}
+
static void fdls_send_delete_tport_msg(struct fnic_tport_s *tport)
{
struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
@@ -1360,6 +1556,15 @@ static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
fdls_send_fabric_plogi(iport);
fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
+
+ if ((fnic_fdmi_support == 1) && (!(iport->flags & FNIC_FDMI_ACTIVE))) {
+ /* we can do FDMI at the same time */
+ iport->fabric.fdmi_retry = 0;
+ timer_setup(&iport->fabric.fdmi_timer, fdls_fdmi_timer_callback,
+ 0);
+ fdls_send_fdmi_plogi(iport);
+ iport->flags |= FNIC_FDMI_ACTIVE;
+ }
}

static void
@@ -2440,6 +2645,69 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
}
}

+static void fdls_process_fdmi_plogi_rsp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ struct fc_els_s *plogi_rsp = (struct fc_els_s *) fchdr;
+ struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
+ struct fnic *fnic = iport->fnic;
+ u64 fdmi_tov;
+
+ if (ntoh24(fchdr->sid) == 0XFFFFFA) {
+ del_timer_sync(&iport->fabric.fdmi_timer);
+ iport->fabric.fdmi_pending = 0;
+ switch (plogi_rsp->command) {
+ case FC_LS_ACC:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS process fdmi PLOGI response status: FC_LS_ACC\n");
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Sending fdmi registration for port 0x%x\n",
+ iport->fcid);
+
+ fdls_fdmi_register_hba(iport);
+ fdls_fdmi_register_pa(iport);
+ fdmi_tov = jiffies + msecs_to_jiffies(5000);
+ mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov));
+ iport->fabric.fdmi_pending = 2;
+ break;
+ case FC_LS_REJ:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Fabric FDMI PLOGI returned FC_LS_REJ reason: 0x%x",
+ els_rjt->reason_code);
+
+ if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
+ || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
+ && (iport->fabric.fdmi_retry < 7)) {
+ iport->fabric.fdmi_retry++;
+ fdls_send_fdmi_plogi(iport);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void fdls_process_fdmi_reg_ack(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ struct fnic *fnic = iport->fnic;
+
+ if (iport->fabric.fdmi_pending > 0) {
+ iport->fabric.fdmi_pending--;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport fcid: 0x%x: Received FDMI registration ack\n",
+ iport->fcid);
+
+ if (iport->fabric.fdmi_pending == 0) {
+ del_timer_sync(&iport->fabric.fdmi_timer);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport fcid: 0x%x: Canceling FDMI timer\n",
+ iport->fcid);
+ }
+ }
+}
+
static void
fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
struct fc_hdr_s *fchdr)
@@ -3367,6 +3635,12 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
}
return FNIC_FABRIC_PLOGI_RSP;

+ case FNIC_PLOGI_FDMI_OXID:
+ return FNIC_FDMI_PLOGI_RSP;
+ case FNIC_FDMI_REG_HBA_OXID:
+ case FNIC_FDMI_RPA_OXID:
+ return FNIC_FDMI_RSP;
+
case FNIC_SCR_REQ_OXID:
if (type == FC_LS_ACC) {
if ((s_id != FC_FABRIC_CONTROLLER)
@@ -3447,6 +3721,9 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
case FNIC_FABRIC_PLOGI_RSP:
fdls_process_fabric_plogi_rsp(iport, fchdr);
break;
+ case FNIC_FDMI_PLOGI_RSP:
+ fdls_process_fdmi_plogi_rsp(iport, fchdr);
+ break;
case FNIC_FABRIC_RPN_RSP:
fdls_process_rpn_id_rsp(iport, fchdr);
break;
@@ -3514,9 +3791,13 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
case FNIC_ELS_RLS:
fdls_process_rls_req(iport, fchdr);
break;
+ case FNIC_FDMI_RSP:
+ fdls_process_fdmi_reg_ack(iport, fchdr);
+ break;
default:
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Received unknown FCoE frame of len: %d. Dropping frame", len);
break;
}
}
+
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 92cd17efa40f..7d7009197dbc 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -82,6 +82,72 @@
/* Retry supported by rport (returned by PRLI service parameters) */
#define FNIC_FC_RP_FLAGS_RETRY 0x1

+/* Cisco vendor id */
+#define PCI_VENDOR_ID_CISCO 0x1137
+#define PCI_DEVICE_ID_CISCO_VIC_FC 0x0045 /* fc vnic */
+
+/* sereno pcie switch */
+#define PCI_DEVICE_ID_CISCO_SERENO 0x004e
+#define PCI_DEVICE_ID_CISCO_CRUZ 0x007a /* Cruz */
+#define PCI_DEVICE_ID_CISCO_BODEGA 0x0131 /* Bodega */
+#define PCI_DEVICE_ID_CISCO_BEVERLY 0x025f /* Beverly */
+
+/* Sereno */
+#define PCI_SUBDEVICE_ID_CISCO_VASONA 0x004f /* vasona mezz */
+#define PCI_SUBDEVICE_ID_CISCO_COTATI 0x0084 /* cotati mlom */
+#define PCI_SUBDEVICE_ID_CISCO_LEXINGTON 0x0085 /* lexington pcie */
+#define PCI_SUBDEVICE_ID_CISCO_ICEHOUSE 0x00cd /* Icehouse */
+#define PCI_SUBDEVICE_ID_CISCO_KIRKWOODLAKE 0x00ce /* KirkwoodLake pcie */
+#define PCI_SUBDEVICE_ID_CISCO_SUSANVILLE 0x012e /* Susanville MLOM */
+#define PCI_SUBDEVICE_ID_CISCO_TORRANCE 0x0139 /* Torrance MLOM */
+
+/* Cruz */
+#define PCI_SUBDEVICE_ID_CISCO_CALISTOGA 0x012c /* Calistoga MLOM */
+#define PCI_SUBDEVICE_ID_CISCO_MOUNTAINVIEW 0x0137 /* Cruz Mezz */
+/* Cruz MountTian SIOC */
+#define PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN 0x014b
+#define PCI_SUBDEVICE_ID_CISCO_CLEARLAKE 0x014d /* ClearLake pcie */
+/* Cruz MountTian2 SIOC */
+#define PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN2 0x0157
+#define PCI_SUBDEVICE_ID_CISCO_CLAREMONT 0x015d /* Claremont MLOM */
+
+/* Bodega */
+/* VIC 1457 PCIe mLOM */
+#define PCI_SUBDEVICE_ID_CISCO_BRADBURY 0x0218
+#define PCI_SUBDEVICE_ID_CISCO_BRENTWOOD 0x0217 /* VIC 1455 PCIe */
+/* VIC 1487 PCIe mLOM */
+#define PCI_SUBDEVICE_ID_CISCO_BURLINGAME 0x021a
+#define PCI_SUBDEVICE_ID_CISCO_BAYSIDE 0x0219 /* VIC 1485 PCIe */
+/* VIC 1440 Mezz mLOM */
+#define PCI_SUBDEVICE_ID_CISCO_BAKERSFIELD 0x0215
+#define PCI_SUBDEVICE_ID_CISCO_BOONVILLE 0x0216 /* VIC 1480 Mezz */
+#define PCI_SUBDEVICE_ID_CISCO_BENICIA 0x024a /* VIC 1495 */
+#define PCI_SUBDEVICE_ID_CISCO_BEAUMONT 0x024b /* VIC 1497 */
+#define PCI_SUBDEVICE_ID_CISCO_BRISBANE 0x02af /* VIC 1467 */
+#define PCI_SUBDEVICE_ID_CISCO_BENTON 0x02b0 /* VIC 1477 */
+#define PCI_SUBDEVICE_ID_CISCO_TWIN_RIVER 0x02cf /* VIC 14425 */
+#define PCI_SUBDEVICE_ID_CISCO_TWIN_PEAK 0x02d0 /* VIC 14825 */
+
+/* Beverly */
+#define PCI_SUBDEVICE_ID_CISCO_BERN 0x02de /* VIC 15420 */
+#define PCI_SUBDEVICE_ID_CISCO_STOCKHOLM 0x02dd /* VIC 15428 */
+#define PCI_SUBDEVICE_ID_CISCO_KRAKOW 0x02dc /* VIC 15411 */
+#define PCI_SUBDEVICE_ID_CISCO_LUCERNE 0x02db /* VIC 15231 */
+#define PCI_SUBDEVICE_ID_CISCO_TURKU 0x02e8 /* VIC 15238 */
+#define PCI_SUBDEVICE_ID_CISCO_TURKU_PLUS 0x02f3 /* VIC 15237 */
+#define PCI_SUBDEVICE_ID_CISCO_ZURICH 0x02df /* VIC 15230 */
+#define PCI_SUBDEVICE_ID_CISCO_RIGA 0x02e0 /* VIC 15427 */
+#define PCI_SUBDEVICE_ID_CISCO_GENEVA 0x02e1 /* VIC 15422 */
+#define PCI_SUBDEVICE_ID_CISCO_HELSINKI 0x02e4 /* VIC 15235 */
+#define PCI_SUBDEVICE_ID_CISCO_GOTHENBURG 0x02f2 /* VIC 15425 */
+
+struct fnic_pcie_device {
+ u32 device;
+ u8 *desc;
+ u32 subsystem_device;
+ u8 *subsys_desc;
+};
+
/*
* fnic private data per SCSI command.
* These fields are locked by the hashed io_req_lock.
@@ -134,6 +200,7 @@ static inline u64 fnic_flags_and_state(struct scsi_cmnd *cmd)
#define fnic_clear_state_flags(fnicp, st_flags) \
__fnic_set_state_flags(fnicp, st_flags, 1)

+extern unsigned int fnic_fdmi_support;
extern unsigned int fnic_log_level;
extern unsigned int io_completions;
extern struct workqueue_struct *fnic_event_queue;
@@ -366,6 +433,9 @@ struct fnic {

/* interrupt resource cache line section */
____cacheline_aligned struct vnic_intr intr[FNIC_MSIX_INTR_MAX];
+
+ char subsys_desc[14];
+ int subsys_desc_len;
};

static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip)
@@ -433,5 +503,7 @@ fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
void __fnic_set_state_flags(struct fnic *, unsigned long, unsigned long);
void fnic_dump_fchost_stats(struct Scsi_Host *, struct fc_host_statistics *);
void fnic_free_txq(struct list_head *head);
+int fnic_get_desc_by_devid(struct pci_dev *pdev, char **desc,
+ char **subsys_desc);

#endif /* _FNIC_H_ */
diff --git a/drivers/scsi/fnic/fnic_fdls.h b/drivers/scsi/fnic/fnic_fdls.h
index 9eb25ed9c19f..88462363d754 100644
--- a/drivers/scsi/fnic/fnic_fdls.h
+++ b/drivers/scsi/fnic/fnic_fdls.h
@@ -329,6 +329,7 @@ void fdls_send_tport_abts(struct fnic_iport_s *iport,
struct fnic_tport_s *tport);
void fdls_delete_tport(struct fnic_iport_s *iport,
struct fnic_tport_s *tport);
+void fdls_fdmi_timer_callback(struct timer_list *t);

/* fnic_fcs.c */
void fnic_fdls_init(struct fnic *fnic, int usefip);
@@ -366,4 +367,3 @@ struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport,
uint64_t wwpn);

#endif /* _FNIC_FDLS_H_ */
-
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 577048e30c12..7d10d603f53b 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -62,6 +62,9 @@ unsigned int fnic_log_level;
module_param(fnic_log_level, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(fnic_log_level, "bit mask of fnic logging levels");

+unsigned int fnic_fdmi_support = 1;
+module_param(fnic_fdmi_support, int, 0644);
+MODULE_PARM_DESC(fnic_fdmi_support, "FDMI support");

unsigned int io_completions = FNIC_DFLT_IO_COMPLETIONS;
module_param(io_completions, int, S_IRUGO|S_IWUSR);
@@ -607,6 +610,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int i;
unsigned long flags;
int hwq;
+ char *desc, *subsys_desc;
+ int len;

/*
* Allocate SCSI Host and set up association between host,
@@ -640,6 +645,23 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fnic->fnic_num = fnic_id;
fnic_stats_debugfs_init(fnic);

+ /* Find model name from PCIe subsys ID */
+ if (fnic_get_desc_by_devid(pdev, &desc, &subsys_desc) == 0) {
+ pr_info("Model: %s\n", subsys_desc);
+
+ /* Update FDMI model */
+ fnic->subsys_desc_len = strlen(subsys_desc);
+ len = ARRAY_SIZE(fnic->subsys_desc);
+ if (fnic->subsys_desc_len > len)
+ fnic->subsys_desc_len = len;
+ memcpy(fnic->subsys_desc, subsys_desc, fnic->subsys_desc_len);
+ pr_info("FDMI Model: %s\n", fnic->subsys_desc);
+ } else {
+ fnic->subsys_desc_len = 0;
+ pr_info("Model: %s subsys_id: 0x%04x\n", "Unknown",
+ pdev->subsystem_device);
+ }
+
err = pci_enable_device(pdev);
if (err) {
pr_err("Cannot enable PCI device, aborting.\n");
@@ -1014,6 +1036,9 @@ static void fnic_remove(struct pci_dev *pdev)
fnic_fcoe_evlist_free(fnic);
}

+ if ((fnic_fdmi_support == 1) && (fnic->iport.fabric.fdmi_pending > 0))
+ del_timer_sync(&fnic->iport.fabric.fdmi_timer);
+
/*
* Log off the fabric. This stops all remote ports, dns port,
* logs off the fabric. This flushes all rport, disc, lport work
@@ -1199,3 +1224,4 @@ static void __exit fnic_cleanup_module(void)

module_init(fnic_init_module);
module_exit(fnic_cleanup_module);
+
diff --git a/drivers/scsi/fnic/fnic_pci_subsys_devid.c b/drivers/scsi/fnic/fnic_pci_subsys_devid.c
new file mode 100644
index 000000000000..1729c3a7ed05
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_pci_subsys_devid.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/mempool.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <linux/if_ether.h>
+#include "fnic.h"
+
+static struct fnic_pcie_device fnic_pcie_device_table[] = {
+ {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_VASONA,
+ "VIC 1280"},
+ {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_COTATI,
+ "VIC 1240"},
+ {PCI_DEVICE_ID_CISCO_SERENO, "Sereno",
+ PCI_SUBDEVICE_ID_CISCO_LEXINGTON, "VIC 1225"},
+ {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_ICEHOUSE,
+ "VIC 1285"},
+ {PCI_DEVICE_ID_CISCO_SERENO, "Sereno",
+ PCI_SUBDEVICE_ID_CISCO_KIRKWOODLAKE, "VIC 1225T"},
+ {PCI_DEVICE_ID_CISCO_SERENO, "Sereno",
+ PCI_SUBDEVICE_ID_CISCO_SUSANVILLE, "VIC 1227"},
+ {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_TORRANCE,
+ "VIC 1227T"},
+
+ {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_CALISTOGA,
+ "VIC 1340"},
+ {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_MOUNTAINVIEW,
+ "VIC 1380"},
+ {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN,
+ "C3260-SIOC"},
+ {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_CLEARLAKE,
+ "VIC 1385"},
+ {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN2,
+ "C3260-SIOC"},
+ {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_CLAREMONT,
+ "VIC 1387"},
+
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BRADBURY,
+ "VIC 1457"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
+ PCI_SUBDEVICE_ID_CISCO_BRENTWOOD, "VIC 1455"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
+ PCI_SUBDEVICE_ID_CISCO_BURLINGAME, "VIC 1487"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BAYSIDE,
+ "VIC 1485"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
+ PCI_SUBDEVICE_ID_CISCO_BAKERSFIELD, "VIC 1440"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
+ PCI_SUBDEVICE_ID_CISCO_BOONVILLE, "VIC 1480"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BENICIA,
+ "VIC 1495"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BEAUMONT,
+ "VIC 1497"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BRISBANE,
+ "VIC 1467"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BENTON,
+ "VIC 1477"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
+ PCI_SUBDEVICE_ID_CISCO_TWIN_RIVER, "VIC 14425"},
+ {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
+ PCI_SUBDEVICE_ID_CISCO_TWIN_PEAK, "VIC 14825"},
+
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_BERN,
+ "VIC 15420"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
+ PCI_SUBDEVICE_ID_CISCO_STOCKHOLM, "VIC 15428"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_KRAKOW,
+ "VIC 15411"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
+ PCI_SUBDEVICE_ID_CISCO_LUCERNE, "VIC 15231"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_TURKU,
+ "VIC 15238"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_GENEVA,
+ "VIC 15422"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
+ PCI_SUBDEVICE_ID_CISCO_HELSINKI, "VIC 15235"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
+ PCI_SUBDEVICE_ID_CISCO_GOTHENBURG, "VIC 15425"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
+ PCI_SUBDEVICE_ID_CISCO_TURKU_PLUS, "VIC 15237"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_ZURICH,
+ "VIC 15230"},
+ {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_RIGA,
+ "VIC 15427"},
+
+ {0,}
+};
+
+int fnic_get_desc_by_devid(struct pci_dev *pdev, char **desc,
+ char **subsys_desc)
+{
+ unsigned short device = PCI_DEVICE_ID_CISCO_VIC_FC;
+ int max = ARRAY_SIZE(fnic_pcie_device_table);
+ struct fnic_pcie_device *t = fnic_pcie_device_table;
+ int index = 0;
+
+ if (memcmp((char *) &pdev->device, (char *) &device, sizeof(short)) !=
+ 0)
+ return 1;
+
+ while (t->device != 0) {
+ if (memcmp
+ ((char *) &pdev->subsystem_device,
+ (char *) &t->subsystem_device, sizeof(short)) == 0)
+ break;
+ t++;
+ index++;
+ }
+
+ if (index >= max - 1) {
+ *desc = NULL;
+ *subsys_desc = NULL;
+ return 1;
+ }
+
+ *desc = fnic_pcie_device_table[index].desc;
+ *subsys_desc = fnic_pcie_device_table[index].subsys_desc;
+ return 0;
+}
--
2.31.1


Subject: [PATCH 07/14] scsi: fnic: Add and integrate support for FIP

Add and integrate support for FCoE Initialization
(protocol) FIP. This protocol will be exercised on
Cisco UCS rack servers.
Add support to specifically print FIP related
debug messages.
Replace existing definitions to handle new
data structures.
Clean up old and obsolete definitions.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/Makefile | 1 +
drivers/scsi/fnic/fip.c | 875 +++++++++++++++++++++++++++++++++
drivers/scsi/fnic/fip.h | 341 +++++++++++++
drivers/scsi/fnic/fnic.h | 23 +-
drivers/scsi/fnic/fnic_fcs.c | 889 ++++++----------------------------
drivers/scsi/fnic/fnic_main.c | 47 +-
6 files changed, 1402 insertions(+), 774 deletions(-)
create mode 100644 drivers/scsi/fnic/fip.c
create mode 100644 drivers/scsi/fnic/fip.h

diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
index af156c69da0c..c025e875009e 100644
--- a/drivers/scsi/fnic/Makefile
+++ b/drivers/scsi/fnic/Makefile
@@ -2,6 +2,7 @@
obj-$(CONFIG_FCOE_FNIC) += fnic.o

fnic-y := \
+ fip.o\
fnic_attrs.o \
fnic_isr.o \
fnic_main.o \
diff --git a/drivers/scsi/fnic/fip.c b/drivers/scsi/fnic/fip.c
new file mode 100644
index 000000000000..8d4f6b98407b
--- /dev/null
+++ b/drivers/scsi/fnic/fip.c
@@ -0,0 +1,875 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ */
+#include "fnic.h"
+#include "fip.h"
+#include <linux/etherdevice.h>
+
+extern struct workqueue_struct *fnic_fip_queue;
+
+#define TRUE 1
+#define FALSE 0
+
+int drop_rsp = TRUE;
+
+#define FIP_FNIC_RESET_WAIT_COUNT 15
+
+#define htonll(x) cpu_to_be64(x)
+
+/****************************** Functions ***********************************/
+
+/**
+ * fnic_fcoe_reset_vlans
+ *
+ * Frees up the list of discovered vlans
+ *
+ * @param fnic driver instance
+ */
+
+void fnic_fcoe_reset_vlans(struct fnic *fnic)
+{
+ unsigned long flags;
+ struct fcoe_vlan *vlan, *next;
+
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+ if (!list_empty(&fnic->vlan_list)) {
+ list_for_each_entry_safe(vlan, next, &fnic->vlan_list, list) {
+ list_del(&vlan->list);
+ kfree(vlan);
+ }
+ }
+
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Reset vlan complete\n");
+}
+
+/**
+ * fnic_fcoe_send_vlan_req
+ *
+ * Sends FIP vlan request to all FCFs MAC
+ *
+ * @param fnic driver instance
+ */
+
+void fnic_fcoe_send_vlan_req(struct fnic *fnic)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+ struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+ u64 vlan_tov;
+
+ int fr_len;
+ struct fip_vlan_req_s vlan_req;
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Enter send vlan req\n");
+ fnic_fcoe_reset_vlans(fnic);
+
+ fnic->set_vlan(fnic, 0);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "set vlan done\n");
+
+ fr_len = sizeof(struct fip_vlan_req_s);
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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]);
+
+ memcpy(&vlan_req, &fip_vlan_req_tmpl, fr_len);
+ memcpy(vlan_req.eth.smac, iport->hwmac, ETH_ALEN);
+ memcpy(vlan_req.mac_desc.mac, iport->hwmac, ETH_ALEN);
+
+ atomic64_inc(&fnic_stats->vlan_stats.vlan_disc_reqs);
+
+ iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
+
+ fnic_send_fip_frame(iport, &vlan_req, fr_len);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "vlan req sent\n");
+
+ 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->lport->host, fnic->fnic_num,
+ "fip timer set\n");
+}
+
+/**
+ * fnic_fcoe_process_vlan_resp
+ *
+ * Processes the vlan response from one FCF and populates VLAN list.
+ * Will wait for responses from multiple FCFs until timeout.
+ *
+ * @param fnic driver instance
+ * @param fiph received fip frame
+ */
+
+void fnic_fcoe_process_vlan_resp(struct fnic *fnic,
+ struct fip_header_s *fiph)
+{
+ struct fip_vlan_notif_s *vlan_notif = (struct fip_vlan_notif_s *) fiph;
+
+ struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+ u16 vid;
+ int num_vlan = 0;
+ int cur_desc, desc_len;
+ struct fcoe_vlan *vlan;
+ struct fip_vlan_desc_s *vlan_desc;
+ unsigned long flags;
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p got vlan resp\n", fnic);
+
+ desc_len = ntohs(vlan_notif->fip.desc_len);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "desc_len %d\n", desc_len);
+
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+
+ cur_desc = 0;
+ while (desc_len > 0) {
+ vlan_desc =
+ (struct fip_vlan_desc_s *) (((char *) vlan_notif->vlans_desc)
+ + cur_desc * 4);
+
+ if (vlan_desc->type == FIP_TYPE_VLAN) {
+ if (vlan_desc->len != 1) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Invalid descriptor length(%x) in VLan response\n",
+ vlan_desc->len);
+
+ }
+ num_vlan++;
+ vid = ntohs(vlan_desc->vlan);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "process_vlan_resp: FIP VLAN %d\n", vid);
+ vlan = kmalloc(sizeof(*vlan), GFP_ATOMIC);
+
+ if (!vlan) {
+ /* retry from timer */
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Mem Alloc failure\n");
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ goto out;
+ }
+ memset(vlan, 0, sizeof(struct fcoe_vlan));
+ vlan->vid = vid & 0x0fff;
+ vlan->state = FIP_VLAN_AVAIL;
+ list_add_tail(&vlan->list, &fnic->vlan_list);
+ break;
+ } else {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Invalid descriptor type(%x) in VLan response\n",
+ vlan_desc->type);
+ /*
+ * Note : received a type=2 descriptor here i.e. FIP
+ * MAC Address Descriptor
+ */
+ }
+ cur_desc += vlan_desc->len;
+ desc_len -= vlan_desc->len;
+ }
+
+ /* any VLAN descriptors present ? */
+ if (num_vlan == 0) {
+ atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p No VLAN descriptors in FIP VLAN response\n",
+ fnic);
+ }
+
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+
+out:
+ return;
+}
+
+/**
+ * fnic_fcoe_start_fcf_discovery
+ *
+ * Starts FIP FCF discovery in a selected vlan
+ *
+ * @param fnic driver instance
+ */
+
+void fnic_fcoe_start_fcf_discovery(struct fnic *fnic)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+ u64 fcs_tov;
+
+ int fr_len;
+ struct fip_discovery_s disc_sol;
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p start fcf discovery\n", fnic);
+ fr_len = sizeof(struct fip_discovery_s);
+ memset(iport->selected_fcf.fcf_mac, 0, ETH_ALEN);
+
+ memcpy(&disc_sol, &fip_discovery_tmpl, fr_len);
+ memcpy(disc_sol.eth.smac, iport->hwmac, ETH_ALEN);
+ memcpy(disc_sol.mac_desc.mac, iport->hwmac, ETH_ALEN);
+ iport->selected_fcf.fcf_priority = 0xFF;
+
+ disc_sol.name_desc.name = htonll(iport->wwnn);
+ fnic_send_fip_frame(iport, &disc_sol, fr_len);
+
+ iport->fip.state = FDLS_FIP_FCF_DISCOVERY_STARTED;
+
+ fcs_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FCS_TOV);
+ mod_timer(&fnic->retry_fip_timer, round_jiffies(fcs_tov));
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p Started FCF discovery", fnic);
+
+}
+
+/**
+ * fnic_fcoe_fip_discovery_resp
+ *
+ * Processes FCF advertisements.
+ * They can be:
+ * solicited Sent in response of a discover FCF FIP request
+ * We will only store the information of the FCF with
+ * highest priority.
+ * We wait until timeout in case of multiple FCFs.
+ * unsolicited Sent periodically by the FCF for keep alive.
+ * If FLOGI is in progress or completed and the advertisement is
+ * received by our selected FCF, refresh the keep alive timer.
+ *
+ * @param fnic driver instance
+ * @param fiph received frame
+ */
+
+void fnic_fcoe_fip_discovery_resp(struct fnic *fnic,
+ struct fip_header_s *fiph)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+ struct fip_disc_adv_s *disc_adv = (struct fip_disc_adv_s *) fiph;
+ u64 fcs_ka_tov;
+ int fka_has_changed;
+
+ if (iport->fip.state == FDLS_FIP_FCF_DISCOVERY_STARTED) {
+ if (ntohs(disc_adv->fip.flags) & FIP_FLAG_S) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p Solicited adv\n", fnic);
+
+ if ((disc_adv->prio_desc.priority <
+ iport->selected_fcf.fcf_priority)
+ && (ntohs(disc_adv->fip.flags) & FIP_FLAG_A)) {
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p FCF Available\n", fnic);
+ memcpy(iport->selected_fcf.fcf_mac, disc_adv->mac_desc.mac,
+ ETH_ALEN);
+ iport->selected_fcf.fcf_priority =
+ disc_adv->prio_desc.priority;
+ iport->selected_fcf.fka_adv_period =
+ ntohl(disc_adv->fka_adv_desc.fka_adv);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "adv time %d",
+ iport->selected_fcf.fka_adv_period);
+ iport->selected_fcf.ka_disabled =
+ (disc_adv->fka_adv_desc.rsvd_D & 1);
+ }
+ }
+ } else if ((iport->fip.state == FDLS_FIP_FLOGI_STARTED)
+ || (iport->fip.state == FDLS_FIP_FLOGI_COMPLETE)) {
+ if (!(ntohs(disc_adv->fip.flags) & FIP_FLAG_S)) {
+ /* same fcf */
+ if (memcmp(iport->selected_fcf.fcf_mac, disc_adv->mac_desc.mac,
+ ETH_ALEN) == 0) {
+ if (iport->selected_fcf.fka_adv_period
+ != ntohl(disc_adv->fka_adv_desc.fka_adv)) {
+ iport->selected_fcf.fka_adv_period =
+ ntohl(disc_adv->fka_adv_desc.fka_adv);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host,
+ fnic->fnic_num, "change fka to %d",
+ iport->selected_fcf.fka_adv_period);
+ }
+
+ fka_has_changed = (iport->selected_fcf.ka_disabled == 1)
+ && ((disc_adv->fka_adv_desc.rsvd_D & 1) == 0);
+
+ iport->selected_fcf.ka_disabled =
+ (disc_adv->fka_adv_desc.rsvd_D & 1);
+ if (!((iport->selected_fcf.ka_disabled)
+ || (iport->selected_fcf.fka_adv_period == 0))) {
+
+ fcs_ka_tov = jiffies
+ + 3
+ *
+ msecs_to_jiffies(
+ iport->selected_fcf.fka_adv_period);
+ mod_timer(&fnic->fcs_ka_timer,
+ round_jiffies(fcs_ka_tov));
+
+ } else {
+ if (timer_pending(&fnic->fcs_ka_timer))
+ del_timer_sync(&fnic->fcs_ka_timer);
+ }
+
+ if (fka_has_changed) {
+ u64 tov;
+
+ if (iport->selected_fcf.fka_adv_period != 0) {
+
+ tov = jiffies +
+ msecs_to_jiffies(
+ iport->selected_fcf.fka_adv_period);
+ mod_timer(&fnic->enode_ka_timer,
+ round_jiffies(tov));
+
+ tov =
+ jiffies +
+ msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
+ mod_timer(&fnic->vn_ka_timer, round_jiffies(tov));
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * fnic_fcoe_start_flogi
+ *
+ * Sends FIP FLOGI to the selected FCF
+ *
+ * @param fnic driver instance
+ */
+
+void fnic_fcoe_start_flogi(struct fnic *fnic)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+
+ int fr_len;
+ struct fip_flogi_s flogi_req;
+ u64 flogi_tov;
+
+ fr_len = sizeof(struct fip_flogi_s);
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p Start fip FLOGI\n", fnic);
+
+ memcpy(&flogi_req, &fip_flogi_tmpl, fr_len);
+ memcpy(flogi_req.eth.smac, iport->hwmac, ETH_ALEN);
+ if (iport->usefip)
+ memcpy(flogi_req.eth.dmac, iport->selected_fcf.fcf_mac, ETH_ALEN);
+
+ flogi_req.flogi_desc.flogi.nport_name = htonll(iport->wwpn);
+ flogi_req.flogi_desc.flogi.node_name = htonll(iport->wwnn);
+
+ fnic_send_fip_frame(iport, &flogi_req, fr_len);
+ iport->fip.flogi_retry++;
+
+ iport->fip.state = FDLS_FIP_FLOGI_STARTED;
+ flogi_tov = jiffies + msecs_to_jiffies(fnic->config.flogi_timeout);
+ mod_timer(&fnic->retry_fip_timer, round_jiffies(flogi_tov));
+}
+
+/**
+ * fnic_fcoe_process_flogi_resp
+ *
+ * Processes FLOGI response from FCF.
+ * If successful saves assigned fc_id and MAC, programs firmware
+ * and starts fdls discovery.
+ * Else restarts vlan discovery.
+ *
+ * @param fnic driver instance
+ * @param fiph received frame
+ */
+
+void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
+ struct fip_header_s *fiph)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+ struct fip_flogi_rsp_s *flogi_rsp = (struct fip_flogi_rsp_s *) fiph;
+ int desc_len;
+ uint32_t s_id;
+
+ struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p FIP FLOGI rsp\n", fnic);
+ desc_len = ntohs(flogi_rsp->fip.desc_len);
+ if (desc_len != 38) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Invalid Descriptor List len (%x). Dropping frame\n",
+ desc_len);
+ return;
+ }
+
+ if (!
+ ((flogi_rsp->rsp_desc.type == 7)
+ && (flogi_rsp->rsp_desc.len == 36))
+ || !((flogi_rsp->mac_desc.type == 2)
+ && (flogi_rsp->mac_desc.len == 2))) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping frame invalid type and len mix\n");
+ return;
+ }
+
+ s_id = ntoh24(flogi_rsp->rsp_desc.els.fchdr.sid);
+ if ((flogi_rsp->rsp_desc.els.fchdr.f_ctl != 0x98)
+ || (flogi_rsp->rsp_desc.els.fchdr.r_ctl != 0x23)
+ || (s_id != 0xFFFFFE)
+ || (flogi_rsp->rsp_desc.els.fchdr.ox_id != FNIC_FLOGI_OXID)
+ || (flogi_rsp->rsp_desc.els.fchdr.type != 0x01)) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping invalid frame: s_id %x F %x R %x t %x OX_ID %x\n",
+ s_id,
+ flogi_rsp->rsp_desc.els.fchdr.f_ctl,
+ flogi_rsp->rsp_desc.els.fchdr.r_ctl,
+ flogi_rsp->rsp_desc.els.fchdr.type,
+ flogi_rsp->rsp_desc.els.fchdr.ox_id);
+ return;
+ }
+
+ if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p rsp for pending FLOGI\n", fnic);
+
+ del_timer_sync(&fnic->retry_fip_timer);
+
+ if ((ntohs(flogi_rsp->fip.desc_len) == 38)
+ && (flogi_rsp->rsp_desc.els.command == FC_LS_ACC)) {
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p FLOGI success\n", fnic);
+ memcpy(iport->fpma, flogi_rsp->mac_desc.mac, ETH_ALEN);
+ iport->fcid = ntoh24(flogi_rsp->rsp_desc.els.fchdr.did);
+
+ iport->r_a_tov =
+ ntohl(flogi_rsp->rsp_desc.els.u.csp_flogi.r_a_tov);
+ iport->e_d_tov =
+ ntohl(flogi_rsp->rsp_desc.els.u.csp_flogi.e_d_tov);
+ memcpy(fnic->iport.fcfmac, iport->selected_fcf.fcf_mac,
+ ETH_ALEN);
+ vnic_dev_add_addr(fnic->vdev, flogi_rsp->mac_desc.mac);
+
+ if (fnic_fdls_register_portid(iport, iport->fcid, NULL) != 0) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p flogi registration failed\n",
+ fnic);
+ return;
+ }
+
+ iport->fip.state = FDLS_FIP_FLOGI_COMPLETE;
+ iport->state = FNIC_IPORT_STATE_FABRIC_DISC;
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport->state:%d\n", iport->state);
+ if (!((iport->selected_fcf.ka_disabled)
+ || (iport->selected_fcf.fka_adv_period == 0))) {
+ u64 tov;
+
+ tov = jiffies
+ + msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
+ mod_timer(&fnic->enode_ka_timer, round_jiffies(tov));
+
+ tov = jiffies + msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
+ mod_timer(&fnic->vn_ka_timer, round_jiffies(tov));
+
+ }
+ } else {
+ /*
+ * If there's FLOGI rejects - clear all
+ * fcf's & restart from scratch
+ */
+ atomic64_inc(&fnic_stats->vlan_stats.flogi_rejects);
+ /* start FCoE VLAN discovery */
+ fnic_fcoe_send_vlan_req(fnic);
+
+ iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
+ }
+ }
+}
+
+/**
+ * fnic_common_fip_cleanup
+ *
+ * Cleans up FCF info and timers in case of link down/CVL
+ *
+ * @param fnic driver instance
+ */
+
+void fnic_common_fip_cleanup(struct fnic *fnic)
+{
+
+ struct fnic_iport_s *iport = &fnic->iport;
+
+ if (!iport->usefip)
+ return;
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p fip cleanup\n", fnic);
+
+ iport->fip.state = FDLS_FIP_INIT;
+
+ del_timer_sync(&fnic->retry_fip_timer);
+ del_timer_sync(&fnic->fcs_ka_timer);
+ del_timer_sync(&fnic->enode_ka_timer);
+ del_timer_sync(&fnic->vn_ka_timer);
+
+ if (!is_zero_ether_addr(iport->fpma))
+ vnic_dev_del_addr(fnic->vdev, iport->fpma);
+
+ memset(iport->fpma, 0, ETH_ALEN);
+ iport->fcid = 0;
+ iport->r_a_tov = 0;
+ iport->e_d_tov = 0;
+ memset(fnic->iport.fcfmac, 0, ETH_ALEN);
+ memset(iport->selected_fcf.fcf_mac, 0, ETH_ALEN);
+ iport->selected_fcf.fcf_priority = 0;
+ iport->selected_fcf.fka_adv_period = 0;
+ iport->selected_fcf.ka_disabled = 0;
+
+ fnic_fcoe_reset_vlans(fnic);
+}
+
+/**
+ * fnic_fcoe_process_cvl
+ *
+ * Processes Clear Virtual Link from FCF
+ * Verifies that cvl is received from our current FCF for our assigned MAC
+ * Cleans up and restarts the vlan discovery
+ *
+ * @param fnic driver instance
+ * @param fiph received frame
+ */
+
+void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *fiph)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+ struct fip_cvl_s *cvl_msg = (struct fip_cvl_s *) fiph;
+ int i;
+ int found = FALSE;
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p clear virtual link handler\n", fnic);
+
+ if (!
+ ((cvl_msg->fcf_mac_desc.type == 2)
+ && (cvl_msg->fcf_mac_desc.len == 2))
+|| !((cvl_msg->name_desc.type == 4) && (cvl_msg->name_desc.len == 3))) {
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "invalid mix: ft %x fl %x ndt %x ndl %x",
+ cvl_msg->fcf_mac_desc.type, cvl_msg->fcf_mac_desc.len,
+ cvl_msg->name_desc.type, cvl_msg->name_desc.len);
+ }
+
+ if (memcmp
+ (iport->selected_fcf.fcf_mac, cvl_msg->fcf_mac_desc.mac, ETH_ALEN)
+ == 0) {
+ for (i = 0; i < ((ntohs(fiph->desc_len) / 5) - 1); i++) {
+ if (!((cvl_msg->vn_ports_desc[i].type == 11)
+ && (cvl_msg->vn_ports_desc[i].len == 5))) {
+
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Invalid type and len mix type: %d len: %d\n",
+ cvl_msg->vn_ports_desc[i].type,
+ cvl_msg->vn_ports_desc[i].len);
+ }
+ if (memcmp(iport->fpma, cvl_msg->vn_ports_desc[i].vn_port_mac,
+ ETH_ALEN) == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ return;
+ fnic_common_fip_cleanup(fnic);
+
+ fnic_fcoe_send_vlan_req(fnic);
+ }
+}
+
+/**
+ * fdls_fip_recv_frame
+ *
+ * Demultiplexer for FIP frames
+ *
+ * @param fnic driver instance
+ * @param frame received ethernet frame
+ * @return Frame processed by FIP
+ */
+
+int fdls_fip_recv_frame(struct fnic *fnic, void *frame)
+{
+ struct eth_hdr_s *eth = (struct eth_hdr_s *) frame;
+ struct fip_header_s *fiph;
+ u16 protocol;
+ u8 sub;
+
+ if (eth->eth_type == ntohs(FIP_ETH_TYPE)) {
+ fiph = (struct fip_header_s *) (eth + 1);
+ protocol = ntohs(fiph->protocol);
+ sub = ntohs(fiph->subcode);
+
+ if (protocol == FIP_DISCOVERY && sub == FIP_SUBCODE_RESP)
+ fnic_fcoe_fip_discovery_resp(fnic, fiph);
+ else if (protocol == FIP_VLAN_DISC && sub == FIP_SUBCODE_RESP)
+ fnic_fcoe_process_vlan_resp(fnic, fiph);
+ else if (protocol == FIP_KA_CVL && sub == FIP_SUBCODE_RESP)
+ fnic_fcoe_process_cvl(fnic, fiph);
+ else if (protocol == FIP_FLOGI && sub == FIP_SUBCODE_RESP)
+ fnic_fcoe_process_flogi_resp(fnic, fiph);
+
+ return 1;
+ }
+ return 0;
+}
+
+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->lport->host, fnic->fnic_num,
+ "FIP timeout\n");
+
+ if (iport->fip.state == FDLS_FIP_VLAN_DISCOVERY_STARTED) {
+ fnic_vlan_discovery_timeout(fnic);
+ } 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->lport->host, fnic->fnic_num,
+ "FCF Discovery timeout\n");
+ if (memcmp(iport->selected_fcf.fcf_mac, zmac, ETH_ALEN) != 0) {
+
+ if (iport->flags & FNIC_FIRST_LINK_UP)
+ iport->flags &= ~FNIC_FIRST_LINK_UP;
+
+ fnic_fcoe_start_flogi(fnic);
+ if (!((iport->selected_fcf.ka_disabled)
+ || (iport->selected_fcf.fka_adv_period == 0))) {
+ u64 fcf_tov;
+
+ fcf_tov = jiffies
+ + 3
+ * msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
+ mod_timer(&fnic->fcs_ka_timer, round_jiffies(fcf_tov));
+ }
+ } else {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FCF Discovery timeout\n");
+ fnic_vlan_discovery_timeout(fnic);
+ }
+ } else if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FLOGI timeout\n");
+ if (iport->fip.flogi_retry < fnic->config.flogi_retries)
+ fnic_fcoe_start_flogi(fnic);
+ else
+ fnic_vlan_discovery_timeout(fnic);
+ }
+}
+
+/**
+ * fnic_handle_fip_timer
+ *
+ * Timeout handler for FIP discover phase.
+ * Based on the current state, starts next phase or restarts discovery
+ *
+ * @param data Opaque pointer to fnic structure
+ */
+
+void fnic_handle_fip_timer(struct timer_list *t)
+{
+ struct fnic *fnic = from_timer(fnic, t, retry_fip_timer);
+
+ INIT_WORK(&fnic->fip_timer_work, fnic_work_on_fip_timer);
+ queue_work(fnic_fip_queue, &fnic->fip_timer_work);
+}
+
+/**
+ * fnic_handle_enode_ka_timer
+ *
+ * FIP node keep alive.
+ *
+ * @param data Opaque pointer to fnic struct
+ */
+void fnic_handle_enode_ka_timer(struct timer_list *t)
+{
+ struct fnic *fnic = from_timer(fnic, t, enode_ka_timer);
+
+ struct fnic_iport_s *iport = &fnic->iport;
+ int fr_len;
+ struct fip_enode_ka_s enode_ka;
+ u64 enode_ka_tov;
+
+ if (iport->fip.state != FDLS_FIP_FLOGI_COMPLETE)
+ return;
+
+ if ((iport->selected_fcf.ka_disabled)
+ || (iport->selected_fcf.fka_adv_period == 0)) {
+ return;
+ }
+
+ fr_len = sizeof(struct fip_enode_ka_s);
+
+ memcpy(&enode_ka, &fip_enode_ka_tmpl, fr_len);
+ memcpy(enode_ka.eth.smac, iport->hwmac, ETH_ALEN);
+ memcpy(enode_ka.eth.dmac, iport->selected_fcf.fcf_mac, ETH_ALEN);
+ memcpy(enode_ka.mac_desc.mac, iport->hwmac, ETH_ALEN);
+
+ fnic_send_fip_frame(iport, &enode_ka, fr_len);
+ enode_ka_tov = jiffies
+ + msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
+ mod_timer(&fnic->enode_ka_timer, round_jiffies(enode_ka_tov));
+}
+
+/**
+ * fnic_handle_vn_ka_timer
+ *
+ * FIP virtual port keep alive.
+ *
+ * @param data Opaque pointer to fnic structure
+ */
+
+void fnic_handle_vn_ka_timer(struct timer_list *t)
+{
+ struct fnic *fnic = from_timer(fnic, t, vn_ka_timer);
+
+ struct fnic_iport_s *iport = &fnic->iport;
+ int fr_len;
+ struct fip_vn_port_ka_s vn_port_ka;
+ u64 vn_ka_tov;
+ uint8_t fcid[3];
+
+ if (iport->fip.state != FDLS_FIP_FLOGI_COMPLETE)
+ return;
+
+ if ((iport->selected_fcf.ka_disabled)
+ || (iport->selected_fcf.fka_adv_period == 0)) {
+ return;
+ }
+
+ fr_len = sizeof(struct fip_vn_port_ka_s);
+
+ memcpy(&vn_port_ka, &fip_vn_port_ka_tmpl, fr_len);
+ memcpy(vn_port_ka.eth.smac, iport->fpma, ETH_ALEN);
+ memcpy(vn_port_ka.eth.dmac, iport->selected_fcf.fcf_mac, ETH_ALEN);
+ memcpy(vn_port_ka.mac_desc.mac, iport->hwmac, ETH_ALEN);
+ memcpy(vn_port_ka.vn_port_desc.vn_port_mac, iport->fpma, ETH_ALEN);
+ hton24(fcid, iport->fcid);
+ memcpy(vn_port_ka.vn_port_desc.vn_port_id, fcid, 3);
+ vn_port_ka.vn_port_desc.vn_port_name = htonll(iport->wwpn);
+
+ fnic_send_fip_frame(iport, &vn_port_ka, fr_len);
+ vn_ka_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
+ mod_timer(&fnic->vn_ka_timer, round_jiffies(vn_ka_tov));
+}
+
+/**
+ * fnic_vlan_discovery_timeout
+ *
+ * End of VLAN discovery or FCF discovery time window
+ * Start the FCF discovery if VLAN was never used
+ * Retry in case of FCF not responding or move to next VLAN
+ *
+ * @param fnic driver instance
+ */
+
+void fnic_vlan_discovery_timeout(struct fnic *fnic)
+{
+ struct fcoe_vlan *vlan;
+ struct fnic_iport_s *iport = &fnic->iport;
+ struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (fnic->stop_rx_link_events) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ if (!iport->usefip)
+ return;
+
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+ if (list_empty(&fnic->vlan_list)) {
+ /* no vlans available, try again */
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ fnic_fcoe_send_vlan_req(fnic);
+ return;
+ }
+
+ vlan = list_first_entry(&fnic->vlan_list, struct fcoe_vlan, list);
+
+ if (vlan->state == FIP_VLAN_SENT) {
+ if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
+ /*
+ * no response on this vlan, remove from the list.
+ * Try the next vlan
+ */
+ list_del(&vlan->list);
+ kfree(vlan);
+ vlan = NULL;
+ if (list_empty(&fnic->vlan_list)) {
+ /* we exhausted all vlans, restart vlan disc */
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ fnic_fcoe_send_vlan_req(fnic);
+ return;
+ }
+ /* check the next vlan */
+ vlan =
+ list_first_entry(&fnic->vlan_list, struct fcoe_vlan, list);
+
+ fnic->set_vlan(fnic, vlan->vid);
+ vlan->state = FIP_VLAN_SENT; /* sent now */
+
+ }
+ atomic64_inc(&fnic_stats->vlan_stats.sol_expiry_count);
+
+ } else {
+ fnic->set_vlan(fnic, vlan->vid);
+ vlan->state = FIP_VLAN_SENT; /* sent now */
+ }
+ vlan->sol_count++;
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ fnic_fcoe_start_fcf_discovery(fnic);
+}
+
+/**
+ * fnic_work_on_fcs_ka_timer - finish handling fcs_ka_timer in process context
+ * We need to finish this timer in a process context so that we do
+ * not hand in fip_common_cleanup. Here we clean up, bring the link down
+ * and restart all FIP discovery.
+ *
+ * @work - the work queue that we will be servicing
+ */
+
+void fnic_work_on_fcs_ka_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->lport->host, fnic->fnic_num,
+ "fnic 0x%p fcs ka timeout\n", fnic);
+
+ fnic_common_fip_cleanup(fnic);
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+ iport->state = FNIC_IPORT_STATE_FIP;
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+
+ fnic_fcoe_send_vlan_req(fnic);
+}
+
+/**
+ * fnic_handle_fcs_ka_timer
+ *
+ * No keep alives received from FCF. Clean up, bring the link down
+ * and restart all the FIP discovery.
+ *
+ * @param data Opaque pointer to fnic structure
+ */
+void fnic_handle_fcs_ka_timer(struct timer_list *t)
+{
+ struct fnic *fnic = from_timer(fnic, t, fcs_ka_timer);
+
+ INIT_WORK(&fnic->fip_timer_work, fnic_work_on_fcs_ka_timer);
+ queue_work(fnic_fip_queue, &fnic->fip_timer_work);
+}
diff --git a/drivers/scsi/fnic/fip.h b/drivers/scsi/fnic/fip.h
new file mode 100644
index 000000000000..33562c5a41e0
--- /dev/null
+++ b/drivers/scsi/fnic/fip.h
@@ -0,0 +1,341 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ */
+#ifndef _FIP_H_
+#define _FIP_H_
+
+#include "fdls_fc.h"
+
+#define FCOE_ALL_FCFS_MAC {0x01, 0x10, 0x18, 0x01, 0x00, 0x02}
+#define FIP_ETH_TYPE 0x8914
+
+#define FIP_ETH_TYPE_LE 0x1489
+#define FCOE_MAX_SIZE_LE 0x2E08
+
+#define WWNN_LEN 8
+
+#define FCOE_CTLR_FIPVLAN_TOV (3*1000)
+#define FCOE_CTLR_FCS_TOV (3*1000)
+#define FCOE_CTLR_VN_KA_TOV (90*1000)
+#define FCOE_CTLR_MAX_SOL (5*1000)
+
+#define FIP_SUBCODE_REQ 1
+#define FIP_SUBCODE_RESP 2
+
+#define FIP_FLAG_S 0x2
+#define FIP_FLAG_A 0x4
+
+/*
+ * VLAN entry.
+ */
+struct fcoe_vlan {
+ struct list_head list;
+ uint16_t vid; /* vlan ID */
+ uint16_t sol_count; /* no. of sols sent */
+ uint16_t state; /* state */
+};
+
+enum fdls_vlan_state_e {
+ FIP_VLAN_AVAIL,
+ FIP_VLAN_SENT
+};
+
+enum fdls_fip_state_e {
+ FDLS_FIP_INIT,
+ FDLS_FIP_VLAN_DISCOVERY_STARTED,
+ FDLS_FIP_FCF_DISCOVERY_STARTED,
+ FDLS_FIP_FLOGI_STARTED,
+ FDLS_FIP_FLOGI_COMPLETE,
+};
+
+enum fip_protocol_code_e {
+ FIP_DISCOVERY = 1,
+ FIP_FLOGI,
+ FIP_KA_CVL,
+ FIP_VLAN_DISC
+};
+
+struct eth_hdr_s {
+ uint8_t dmac[6];
+ uint8_t smac[6];
+ uint16_t eth_type;
+};
+
+struct fip_header_s {
+ uint32_t ver:16;
+
+ uint32_t protocol:16;
+ uint32_t subcode:16;
+
+ uint32_t desc_len:16;
+ uint32_t flags:16;
+} __packed;
+
+enum fip_desc_type_e {
+ FIP_TYPE_PRIORITY = 1,
+ FIP_TYPE_MAC,
+ FIP_TYPE_FCMAP,
+ FIP_TYPE_NAME_ID,
+ FIP_TYPE_FABRIC,
+ FIP_TYPE_MAX_FCOE,
+ FIP_TYPE_FLOGI,
+ FIP_TYPE_FDISC,
+ FIP_TYPE_LOGO,
+ FIP_TYPE_ELP,
+ FIP_TYPE_VX_PORT,
+ FIP_TYPE_FKA_ADV,
+ FIP_TYPE_VENDOR_ID,
+ FIP_TYPE_VLAN
+};
+
+struct fip_mac_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint8_t mac[6];
+} __packed;
+
+struct fip_vlan_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint16_t vlan;
+} __packed;
+
+struct fip_vlan_req_s {
+ struct eth_hdr_s eth;
+ struct fip_header_s fip;
+ struct fip_mac_desc_s mac_desc;
+} __packed;
+
+ /*
+ * Variables:
+ * eth.smac, mac_desc.mac
+ */
+struct fip_vlan_req_s fip_vlan_req_tmpl = {
+ .eth = {.dmac = FCOE_ALL_FCFS_MAC,
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {.ver = 0x10,
+ .protocol = FIP_VLAN_DISC << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 2 << 8},
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2}
+};
+
+struct fip_vlan_notif_s {
+ struct fip_header_s fip;
+ struct fip_vlan_desc_s vlans_desc[];
+} __packed;
+
+struct fip_vn_port_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint8_t vn_port_mac[6];
+ uint8_t rsvd[1];
+ uint8_t vn_port_id[3];
+ uint64_t vn_port_name;
+} __packed;
+
+struct fip_vn_port_ka_s {
+ struct eth_hdr_s eth;
+ struct fip_header_s fip;
+ struct fip_mac_desc_s mac_desc;
+ struct fip_vn_port_desc_s vn_port_desc;
+} __packed;
+
+/*
+ * Variables:
+ * fcf_mac, eth.smac, mac_desc.enode_mac
+ * vn_port_desc:mac, id, port_name
+ */
+struct fip_vn_port_ka_s fip_vn_port_ka_tmpl = {
+ .eth = {
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10,
+ .protocol = FIP_KA_CVL << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 7 << 8},
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2},
+ .vn_port_desc = {.type = FIP_TYPE_VX_PORT, .len = 5}
+};
+
+struct fip_enode_ka_s {
+ struct eth_hdr_s eth;
+ struct fip_header_s fip;
+ struct fip_mac_desc_s mac_desc;
+} __packed;
+
+/*
+ * Variables:
+ * fcf_mac, eth.smac, mac_desc.enode_mac
+ */
+struct fip_enode_ka_s fip_enode_ka_tmpl = {
+ .eth = {
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10,
+ .protocol = FIP_KA_CVL << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 2 << 8},
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2}
+};
+
+struct fip_name_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint8_t rsvd[2];
+ uint64_t name;
+} __packed;
+
+struct fip_cvl_s {
+ struct fip_header_s fip;
+ struct fip_mac_desc_s fcf_mac_desc;
+ struct fip_name_desc_s name_desc;
+ struct fip_vn_port_desc_s vn_ports_desc[];
+} __packed;
+
+struct fip_flogi_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint16_t rsvd;
+ struct fc_els_s flogi;
+} __packed;
+
+struct fip_flogi_rsp_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint16_t rsvd;
+ struct fc_els_s els;
+} __packed;
+
+struct fip_flogi_s {
+ struct eth_hdr_s eth;
+ struct fip_header_s fip;
+ struct fip_flogi_desc_s flogi_desc;
+ struct fip_mac_desc_s mac_desc;
+} __packed;
+
+struct fip_flogi_rsp_s {
+ struct fip_header_s fip;
+ struct fip_flogi_rsp_desc_s rsp_desc;
+ struct fip_mac_desc_s mac_desc;
+} __packed;
+
+/*
+ * Variables:
+ * fcf_mac, eth.smac, mac_desc.enode_mac
+ */
+struct fip_flogi_s fip_flogi_tmpl = {
+ .eth = {
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10,
+ .protocol = FIP_FLOGI << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 38 << 8,
+ .flags = 0x80},
+ .flogi_desc = {
+ .type = FIP_TYPE_FLOGI, .len = 36,
+ .flogi = {
+ .fchdr = {
+ .r_ctl = 0x22,
+ .did = {0xFF, 0xFF, 0xFE},
+ .type = 0x01,
+ .f_ctl = FNIC_ELS_REQ_FCTL,
+ .ox_id = FNIC_FLOGI_OXID,
+ .rx_id = 0xFFFF},
+ .command = FC_ELS_FLOGI_REQ,
+ .u.csp_flogi = {
+ .fc_ph_ver = FNIC_FC_PH_VER,
+ .b2b_credits =
+ FNIC_FC_B2B_CREDIT,
+ .b2b_rdf_size =
+ FNIC_FC_B2B_RDF_SZ},
+ .spc3 = {0x88, 0x00}
+ }
+ },
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2}
+};
+
+struct fip_fcoe_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint16_t max_fcoe_size;
+} __packed;
+
+struct fip_discovery_s {
+ struct eth_hdr_s eth;
+ struct fip_header_s fip;
+ struct fip_mac_desc_s mac_desc;
+ struct fip_name_desc_s name_desc;
+ struct fip_fcoe_desc_s fcoe_desc;
+} __packed;
+
+/*
+ * Variables:
+ * eth.smac, mac_desc.enode_mac, node_name
+ */
+struct fip_discovery_s fip_discovery_tmpl = {
+ .eth = {.dmac = FCOE_ALL_FCFS_MAC,
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10, .protocol = FIP_DISCOVERY << 8,
+ .subcode = FIP_SUBCODE_REQ << 8, .desc_len = 6 << 8,
+ .flags = 0x80},
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2},
+ .name_desc = {.type = FIP_TYPE_NAME_ID, .len = 3},
+ .fcoe_desc = {
+ .type = FIP_TYPE_MAX_FCOE, .len = 1,
+ .max_fcoe_size = FCOE_MAX_SIZE_LE}
+};
+
+struct fip_prio_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint8_t rsvd;
+ uint8_t priority;
+} __packed;
+
+struct fip_fabric_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint16_t vf_id;
+ uint8_t rsvd;
+ uint8_t fc_map[3];
+ uint64_t fabric_name;
+} __packed;
+
+struct fip_fka_adv_desc_s {
+ uint8_t type;
+ uint8_t len;
+ uint8_t rsvd;
+ uint8_t rsvd_D;
+ uint32_t fka_adv;
+} __packed;
+
+struct fip_disc_adv_s {
+ struct fip_header_s fip;
+ struct fip_prio_desc_s prio_desc;
+ struct fip_mac_desc_s mac_desc;
+ struct fip_name_desc_s name_desc;
+ struct fip_fabric_desc_s fabric_desc;
+ struct fip_fka_adv_desc_s fka_adv_desc;
+} __packed;
+
+void fnic_fcoe_process_vlan_resp(struct fnic *fnic,
+ struct fip_header_s *fiph);
+void fnic_fcoe_fip_discovery_resp(struct fnic *fnic,
+ struct fip_header_s *fiph);
+void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
+ struct fip_header_s *fiph);
+void fnic_work_on_fip_timer(struct work_struct *work);
+void fnic_work_on_fcs_ka_timer(struct work_struct *work);
+void fnic_fcoe_send_vlan_req(struct fnic *fnic);
+void fnic_fcoe_start_fcf_discovery(struct fnic *fnic);
+void fnic_fcoe_start_flogi(struct fnic *fnic);
+void fnic_fcoe_process_cvl(struct fnic *fnic,
+ struct fip_header_s *fiph);
+void fnic_vlan_discovery_timeout(struct fnic *fnic);
+
+#endif /* _FIP_H_ */
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 7d7009197dbc..0c7926627663 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -230,6 +230,12 @@ do { \
"fnic<%d>: %s: %d: " fmt, fnic_num,\
__func__, __LINE__, ##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_SCSI_DBG(kern_level, host, fnic_num, fmt, args...) \
FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
shost_printk(kern_level, host, \
@@ -406,13 +412,15 @@ struct fnic {
/*** FIP related data members -- start ***/
void (*set_vlan)(struct fnic *, u16 vlan);
struct work_struct fip_frame_work;
- struct sk_buff_head fip_frame_queue;
+ struct work_struct fip_timer_work;
+ struct list_head fip_frame_queue;
struct timer_list fip_timer;
- struct list_head vlans;
spinlock_t vlans_lock;
-
- struct work_struct event_work;
- struct list_head evlist;
+ struct timer_list retry_fip_timer;
+ struct timer_list fcs_ka_timer;
+ struct timer_list enode_ka_timer;
+ struct timer_list vn_ka_timer;
+ struct list_head vlan_list;
/*** FIP related data members -- end ***/

/* copy work queue cache line section */
@@ -462,9 +470,6 @@ int fnic_rq_cmpl_handler(struct fnic *fnic, int);
int fnic_alloc_rq_frame(struct vnic_rq *rq);
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
void fnic_flush_tx(struct work_struct *work);
-void fnic_eth_send(struct fcoe_ctlr *, struct sk_buff *skb);
-void fnic_set_port_id(struct fc_lport *, u32, struct fc_frame *);
-void fnic_update_mac(struct fc_lport *, u8 *new);
void fnic_update_mac_locked(struct fnic *, u8 *new);

int fnic_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
@@ -493,7 +498,7 @@ int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);
void fnic_handle_fip_frame(struct work_struct *work);
void fnic_handle_fip_event(struct fnic *fnic);
void fnic_fcoe_reset_vlans(struct fnic *fnic);
-void fnic_fcoe_evlist_free(struct fnic *fnic);
+extern void fnic_handle_fip_timer(struct timer_list *t);

static inline int
fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 90d0c4c8920c..8a7c471d3ff5 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -25,16 +25,9 @@
#include "cq_enet_desc.h"
#include "cq_exch_desc.h"

-static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
-struct workqueue_struct *fnic_fip_queue;
+extern struct workqueue_struct *fnic_fip_queue;
struct workqueue_struct *fnic_event_queue;

-static void fnic_set_eth_mode(struct fnic *);
-static void fnic_fcoe_start_fcf_disc(struct fnic *fnic);
-static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *);
-static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag);
-static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb);
-
/* Frame initialization */
/*
* Variables:
@@ -252,11 +245,6 @@ void fnic_handle_link(struct work_struct *work)
fnic->lport->host->host_no, FNIC_FC_LE,
"Link Status: UP_DOWN",
strlen("Link Status: UP_DOWN"));
- if (fnic->config.flags & VFCF_FIP_CAPABLE) {
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "deleting fip-timer during link-down\n");
- del_timer_sync(&fnic->fip_timer);
- }
fcoe_ctlr_link_down(&fnic->ctlr);
}

@@ -299,496 +287,73 @@ void fnic_handle_frame(struct work_struct *work)
}
}

-void fnic_fcoe_evlist_free(struct fnic *fnic)
-{
- struct fnic_event *fevt = NULL;
- struct fnic_event *next = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (list_empty(&fnic->evlist)) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
-
- list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
- list_del(&fevt->list);
- kfree(fevt);
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-}
-
-void fnic_handle_event(struct work_struct *work)
+void fnic_handle_fip_frame(struct work_struct *work)
{
- struct fnic *fnic = container_of(work, struct fnic, event_work);
- struct fnic_event *fevt = NULL;
- struct fnic_event *next = NULL;
- unsigned long flags;
+ struct fnic_stats *fnic_stats;
+ struct fnic_frame_list *cur_frame, *next;
+ struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);

- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (list_empty(&fnic->evlist)) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
+ fnic_stats = &fnic->fnic_stats;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Processing FIP frame\n");

- list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+ list_for_each_entry_safe(cur_frame, next, &fnic->fip_frame_queue,
+ links) {
if (fnic->stop_rx_link_events) {
- list_del(&fevt->list);
- kfree(fevt);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ list_del(&cur_frame->links);
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ kfree(cur_frame->fp);
+ kfree(cur_frame);
return;
}
+
/*
* If we're in a transitional state, just re-queue and return.
* The queue will be serviced when we get to a stable state.
*/
if (fnic->state != FNIC_IN_FC_MODE &&
- fnic->state != FNIC_IN_ETH_MODE) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ fnic->state != FNIC_IN_ETH_MODE) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
return;
}

- list_del(&fevt->list);
- switch (fevt->event) {
- case FNIC_EVT_START_VLAN_DISC:
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- fnic_fcoe_send_vlan_req(fnic);
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- break;
- case FNIC_EVT_START_FCF_DISC:
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "Start FCF Discovery\n");
- fnic_fcoe_start_fcf_disc(fnic);
- break;
- default:
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "Unknown event 0x%x\n", fevt->event);
- break;
- }
- kfree(fevt);
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-}
-
-/**
- * is_fnic_fip_flogi_reject() - Check if the Received FIP FLOGI frame is rejected
- * @fip: The FCoE controller that received the frame
- * @skb: The received FIP frame
- *
- * Returns non-zero if the frame is rejected with unsupported cmd with
- * insufficient resource els explanation.
- */
-static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip,
- struct sk_buff *skb)
-{
- struct fc_lport *lport = fip->lp;
- struct fip_header *fiph;
- struct fc_frame_header *fh = NULL;
- struct fip_desc *desc;
- struct fip_encaps *els;
- u16 op;
- u8 els_op;
- u8 sub;
-
- size_t rlen;
- size_t dlen = 0;
-
- if (skb_linearize(skb))
- return 0;
-
- if (skb->len < sizeof(*fiph))
- return 0;
-
- fiph = (struct fip_header *)skb->data;
- op = ntohs(fiph->fip_op);
- sub = fiph->fip_subcode;
-
- if (op != FIP_OP_LS)
- return 0;
-
- if (sub != FIP_SC_REP)
- return 0;
-
- rlen = ntohs(fiph->fip_dl_len) * 4;
- if (rlen + sizeof(*fiph) > skb->len)
- return 0;
-
- desc = (struct fip_desc *)(fiph + 1);
- dlen = desc->fip_dlen * FIP_BPW;
-
- if (desc->fip_dtype == FIP_DT_FLOGI) {
-
- if (dlen < sizeof(*els) + sizeof(*fh) + 1)
- return 0;
-
- els = (struct fip_encaps *)desc;
- fh = (struct fc_frame_header *)(els + 1);
-
- if (!fh)
- return 0;
-
- /*
- * ELS command code, reason and explanation should be = Reject,
- * unsupported command and insufficient resource
- */
- els_op = *(u8 *)(fh + 1);
- if (els_op == ELS_LS_RJT) {
- shost_printk(KERN_INFO, lport->host,
- "Flogi Request Rejected by Switch\n");
- return 1;
- }
- shost_printk(KERN_INFO, lport->host,
- "Flogi Request Accepted by Switch\n");
- }
- return 0;
-}
-
-void fnic_fcoe_send_vlan_req(struct fnic *fnic)
-{
- struct fcoe_ctlr *fip = &fnic->ctlr;
- struct fnic_stats *fnic_stats = &fnic->fnic_stats;
- struct sk_buff *skb;
- char *eth_fr;
- struct fip_vlan *vlan;
- u64 vlan_tov;
-
- fnic_fcoe_reset_vlans(fnic);
- fnic->set_vlan(fnic, 0);
-
- if (printk_ratelimit())
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "Sending VLAN request...\n");
-
- skb = dev_alloc_skb(sizeof(struct fip_vlan));
- if (!skb)
- return;
-
- eth_fr = (char *)skb->data;
- vlan = (struct fip_vlan *)eth_fr;
-
- memset(vlan, 0, sizeof(*vlan));
- memcpy(vlan->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
- memcpy(vlan->eth.h_dest, fcoe_all_fcfs, ETH_ALEN);
- vlan->eth.h_proto = htons(ETH_P_FIP);
-
- vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
- vlan->fip.fip_op = htons(FIP_OP_VLAN);
- vlan->fip.fip_subcode = FIP_SC_VL_REQ;
- vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
-
- vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
- vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW;
- memcpy(&vlan->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
-
- vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
- vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW;
- put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn);
- atomic64_inc(&fnic_stats->vlan_stats.vlan_disc_reqs);
-
- skb_put(skb, sizeof(*vlan));
- skb->protocol = htons(ETH_P_FIP);
- skb_reset_mac_header(skb);
- skb_reset_network_header(skb);
- fip->send(fip, skb);
-
- /* set a timer so that we can retry if there no response */
- vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV);
- mod_timer(&fnic->fip_timer, round_jiffies(vlan_tov));
-}
-
-static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
-{
- struct fcoe_ctlr *fip = &fnic->ctlr;
- struct fip_header *fiph;
- struct fip_desc *desc;
- struct fnic_stats *fnic_stats = &fnic->fnic_stats;
- u16 vid;
- size_t rlen;
- size_t dlen;
- struct fcoe_vlan *vlan;
- u64 sol_time;
- unsigned long flags;
-
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "Received VLAN response...\n");
-
- fiph = (struct fip_header *) skb->data;
-
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "Received VLAN response... OP 0x%x SUB_OP 0x%x\n",
- ntohs(fiph->fip_op), fiph->fip_subcode);
-
- rlen = ntohs(fiph->fip_dl_len) * 4;
- fnic_fcoe_reset_vlans(fnic);
- spin_lock_irqsave(&fnic->vlans_lock, flags);
- desc = (struct fip_desc *)(fiph + 1);
- while (rlen > 0) {
- dlen = desc->fip_dlen * FIP_BPW;
- switch (desc->fip_dtype) {
- case FIP_DT_VLAN:
- vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan);
- shost_printk(KERN_INFO, fnic->lport->host,
- "process_vlan_resp: FIP VLAN %d\n", vid);
- vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
- if (!vlan) {
- /* retry from timer */
- spin_unlock_irqrestore(&fnic->vlans_lock,
- flags);
- goto out;
- }
- vlan->vid = vid & 0x0fff;
- vlan->state = FIP_VLAN_AVAIL;
- list_add_tail(&vlan->list, &fnic->vlans);
- break;
- }
- desc = (struct fip_desc *)((char *)desc + dlen);
- rlen -= dlen;
- }
-
- /* any VLAN descriptors present ? */
- if (list_empty(&fnic->vlans)) {
- /* retry from timer */
- atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "No VLAN descriptors in FIP VLAN response\n");
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- goto out;
- }
-
- vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
- fnic->set_vlan(fnic, vlan->vid);
- vlan->state = FIP_VLAN_SENT; /* sent now */
- vlan->sol_count++;
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
-
- /* start the solicitation */
- fcoe_ctlr_link_up(fip);
-
- sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
- mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
-out:
- return;
-}
-
-static void fnic_fcoe_start_fcf_disc(struct fnic *fnic)
-{
- unsigned long flags;
- struct fcoe_vlan *vlan;
- u64 sol_time;
-
- spin_lock_irqsave(&fnic->vlans_lock, flags);
- vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
- fnic->set_vlan(fnic, vlan->vid);
- vlan->state = FIP_VLAN_SENT; /* sent now */
- vlan->sol_count = 1;
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
-
- /* start the solicitation */
- fcoe_ctlr_link_up(&fnic->ctlr);
-
- sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
- mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
-}
-
-static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag)
-{
- unsigned long flags;
- struct fcoe_vlan *fvlan;
-
- spin_lock_irqsave(&fnic->vlans_lock, flags);
- if (list_empty(&fnic->vlans)) {
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- return -EINVAL;
- }
-
- fvlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
- if (fvlan->state == FIP_VLAN_USED) {
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- return 0;
- }
-
- if (fvlan->state == FIP_VLAN_SENT) {
- fvlan->state = FIP_VLAN_USED;
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- return 0;
- }
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- return -EINVAL;
-}
-
-static void fnic_event_enq(struct fnic *fnic, enum fnic_evt ev)
-{
- struct fnic_event *fevt;
- unsigned long flags;
-
- fevt = kmalloc(sizeof(*fevt), GFP_ATOMIC);
- if (!fevt)
- return;
-
- fevt->fnic = fnic;
- fevt->event = ev;
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- list_add_tail(&fevt->list, &fnic->evlist);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
- schedule_work(&fnic->event_work);
-}
-
-static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb)
-{
- struct fip_header *fiph;
- int ret = 1;
- u16 op;
- u8 sub;
-
- if (!skb || !(skb->data))
- return -1;
-
- if (skb_linearize(skb))
- goto drop;
-
- fiph = (struct fip_header *)skb->data;
- op = ntohs(fiph->fip_op);
- sub = fiph->fip_subcode;
-
- if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
- goto drop;
-
- if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
- goto drop;
-
- if (op == FIP_OP_DISC && sub == FIP_SC_ADV) {
- if (fnic_fcoe_vlan_check(fnic, ntohs(fiph->fip_flags)))
- goto drop;
- /* pass it on to fcoe */
- ret = 1;
- } else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_NOTE) {
- /* set the vlan as used */
- fnic_fcoe_process_vlan_resp(fnic, skb);
- ret = 0;
- } else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) {
- /* received CVL request, restart vlan disc */
- fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
- /* pass it on to fcoe */
- ret = 1;
- }
-drop:
- return ret;
-}
-
-void fnic_handle_fip_frame(struct work_struct *work)
-{
- struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);
- struct fnic_stats *fnic_stats = &fnic->fnic_stats;
- unsigned long flags;
- struct sk_buff *skb;
- struct ethhdr *eh;
+ list_del(&cur_frame->links);

- while ((skb = skb_dequeue(&fnic->fip_frame_queue))) {
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (fnic->stop_rx_link_events) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- dev_kfree_skb(skb);
- return;
- }
- /*
- * If we're in a transitional state, just re-queue and return.
- * The queue will be serviced when we get to a stable state.
- */
- if (fnic->state != FNIC_IN_FC_MODE &&
- fnic->state != FNIC_IN_ETH_MODE) {
- skb_queue_head(&fnic->fip_frame_queue, skb);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- eh = (struct ethhdr *)skb->data;
- if (eh->h_proto == htons(ETH_P_FIP)) {
- skb_pull(skb, sizeof(*eh));
- if (fnic_fcoe_handle_fip_frame(fnic, skb) <= 0) {
- dev_kfree_skb(skb);
- continue;
- }
- /*
- * If there's FLOGI rejects - clear all
- * fcf's & restart from scratch
- */
- if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) {
- atomic64_inc(
- &fnic_stats->vlan_stats.flogi_rejects);
- shost_printk(KERN_INFO, fnic->lport->host,
- "Trigger a Link down - VLAN Disc\n");
- fcoe_ctlr_link_down(&fnic->ctlr);
- /* start FCoE VLAN discovery */
- fnic_fcoe_send_vlan_req(fnic);
- dev_kfree_skb(skb);
- continue;
- }
- fcoe_ctlr_recv(&fnic->ctlr, skb);
- continue;
+ if (fdls_fip_recv_frame(fnic, cur_frame->fp)) {
+ kfree(cur_frame->fp);
+ kfree(cur_frame);
}
}
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
}

/**
* fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame.
* @fnic: fnic instance.
- * @skb: Ethernet Frame.
+ * @fp: Ethernet Frame.
*/
-static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb)
+static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, void *fp)
{
- struct fc_frame *fp;
- struct ethhdr *eh;
- struct fcoe_hdr *fcoe_hdr;
- struct fcoe_crc_eof *ft;
+ struct fnic_eth_hdr_s *eh;
+ struct fnic_frame_list *fip_fr_elem;
+ unsigned long flags;

- /*
- * Undo VLAN encapsulation if present.
- */
- eh = (struct ethhdr *)skb->data;
- if (eh->h_proto == htons(ETH_P_8021Q)) {
- memmove((u8 *)eh + VLAN_HLEN, eh, ETH_ALEN * 2);
- eh = skb_pull(skb, VLAN_HLEN);
- skb_reset_mac_header(skb);
- }
- if (eh->h_proto == htons(ETH_P_FIP)) {
- if (!(fnic->config.flags & VFCF_FIP_CAPABLE)) {
- printk(KERN_ERR "Dropped FIP frame, as firmware "
- "uses non-FIP mode, Enable FIP "
- "using UCSM\n");
- goto drop;
- }
- if ((fnic_fc_trace_set_data(fnic->lport->host->host_no,
- FNIC_FC_RECV|0x80, (char *)skb->data, skb->len)) != 0) {
- printk(KERN_ERR "fnic ctlr frame trace error!!!");
- }
- skb_queue_tail(&fnic->fip_frame_queue, skb);
+ eh = (struct fnic_eth_hdr_s *) fp;
+ if ((eh->ether_type == htons(ETH_TYPE_FIP)) && (fnic->iport.usefip)) {
+ fip_fr_elem = (struct fnic_frame_list *)
+ kmalloc(sizeof(struct fnic_frame_list), GFP_ATOMIC);
+ if (!fip_fr_elem)
+ return 0;
+ memset(fip_fr_elem, 0, sizeof(struct fnic_frame_list));
+ fip_fr_elem->fp = fp;
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ list_add_tail(&fip_fr_elem->links, &fnic->fip_frame_queue);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
queue_work(fnic_fip_queue, &fnic->fip_frame_work);
- return 1; /* let caller know packet was used */
- }
- if (eh->h_proto != htons(ETH_P_FCOE))
- goto drop;
- skb_set_network_header(skb, sizeof(*eh));
- skb_pull(skb, sizeof(*eh));
-
- fcoe_hdr = (struct fcoe_hdr *)skb->data;
- if (FC_FCOE_DECAPS_VER(fcoe_hdr) != FC_FCOE_VER)
- goto drop;
-
- fp = (struct fc_frame *)skb;
- fc_frame_init(fp);
- fr_sof(fp) = fcoe_hdr->fcoe_sof;
- skb_pull(skb, sizeof(struct fcoe_hdr));
- skb_reset_transport_header(skb);
-
- ft = (struct fcoe_crc_eof *)(skb->data + skb->len - sizeof(*ft));
- fr_eof(fp) = ft->fcoe_eof;
- skb_trim(skb, skb->len - sizeof(*ft));
- return 0;
-drop:
- dev_kfree_skb_irq(skb);
- return -1;
+ return 1; /* let caller know packet was used */
+ } else
+ return 0;
}

/**
@@ -800,206 +365,146 @@ static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb)
*/
void fnic_update_mac_locked(struct fnic *fnic, u8 *new)
{
- u8 *ctl = fnic->ctlr.ctl_src_addr;
+ struct fnic_iport_s *iport = &fnic->iport;
+ u8 *ctl = iport->hwmac;
u8 *data = fnic->data_src_addr;

if (is_zero_ether_addr(new))
new = ctl;
if (ether_addr_equal(data, new))
return;
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "update_mac %pM\n", new);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Update MAC: %u\n", *new);
+
if (!is_zero_ether_addr(data) && !ether_addr_equal(data, ctl))
vnic_dev_del_addr(fnic->vdev, data);
+
memcpy(data, new, ETH_ALEN);
if (!ether_addr_equal(new, ctl))
vnic_dev_add_addr(fnic->vdev, new);
}

-/**
- * fnic_update_mac() - set data MAC address and filters.
- * @lport: local port.
- * @new: newly-assigned FCoE MAC address.
- */
-void fnic_update_mac(struct fc_lport *lport, u8 *new)
-{
- struct fnic *fnic = lport_priv(lport);
-
- spin_lock_irq(&fnic->fnic_lock);
- fnic_update_mac_locked(fnic, new);
- spin_unlock_irq(&fnic->fnic_lock);
-}
-
-/**
- * fnic_set_port_id() - set the port_ID after successful FLOGI.
- * @lport: local port.
- * @port_id: assigned FC_ID.
- * @fp: received frame containing the FLOGI accept or NULL.
- *
- * This is called from libfc when a new FC_ID has been assigned.
- * This causes us to reset the firmware to FC_MODE and setup the new MAC
- * address and FC_ID.
- *
- * It is also called with FC_ID 0 when we're logged off.
- *
- * If the FC_ID is due to point-to-point, fp may be NULL.
- */
-void fnic_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp)
-{
- struct fnic *fnic = lport_priv(lport);
- u8 *mac;
- int ret;
-
- FNIC_FCS_DBG(KERN_DEBUG, lport->host, fnic->fnic_num,
- "set port_id 0x%x fp 0x%p\n",
- port_id, fp);
-
- /*
- * If we're clearing the FC_ID, change to use the ctl_src_addr.
- * Set ethernet mode to send FLOGI.
- */
- if (!port_id) {
- fnic_update_mac(lport, fnic->ctlr.ctl_src_addr);
- fnic_set_eth_mode(fnic);
- return;
- }
-
- if (fp) {
- mac = fr_cb(fp)->granted_mac;
- if (is_zero_ether_addr(mac)) {
- /* non-FIP - FLOGI already accepted - ignore return */
- fcoe_ctlr_recv_flogi(&fnic->ctlr, lport, fp);
- }
- fnic_update_mac(lport, mac);
- }
-
- /* Change state to reflect transition to FC mode */
- spin_lock_irq(&fnic->fnic_lock);
- 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_ERR, fnic->lport->host, fnic->fnic_num,
- "Unexpected fnic state: %s processing FLOGI response",
- fnic_state_to_str(fnic->state));
- spin_unlock_irq(&fnic->fnic_lock);
- return;
- }
- spin_unlock_irq(&fnic->fnic_lock);
-
- /*
- * Send FLOGI registration to firmware to set up FC mode.
- * The new address will be set up when registration completes.
- */
- ret = fnic_flogi_reg_handler(fnic, port_id);
-
- if (ret < 0) {
- spin_lock_irq(&fnic->fnic_lock);
- if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE)
- fnic->state = FNIC_IN_ETH_MODE;
- spin_unlock_irq(&fnic->fnic_lock);
- }
-}
-
static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
*cq_desc, struct vnic_rq_buf *buf,
int skipped __attribute__((unused)),
void *opaque)
{
struct fnic *fnic = vnic_dev_priv(rq->vdev);
- struct sk_buff *skb;
- struct fc_frame *fp;
+ uint8_t *fp;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+ unsigned int ethhdr_stripped;
u8 type, color, eop, sop, ingress_port, vlan_stripped;
- u8 fcoe = 0, fcoe_sof, fcoe_eof;
- u8 fcoe_fc_crc_ok = 1, fcoe_enc_error = 0;
- u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
- u8 ipv6, ipv4, ipv4_fragment, rss_type, csum_not_calc;
+ u8 fcoe_fnic_crc_ok = 1, fcoe_enc_error = 0;
u8 fcs_ok = 1, packet_error = 0;
- u16 q_number, completed_index, bytes_written = 0, vlan, checksum;
+ u16 q_number, completed_index, vlan;
u32 rss_hash;
+ u16 checksum;
+ u8 csum_not_calc, rss_type, ipv4, ipv6, ipv4_fragment;
+ u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
+ u8 fcoe = 0, fcoe_sof, fcoe_eof;
u16 exchange_id, tmpl;
u8 sof = 0;
u8 eof = 0;
u32 fcp_bytes_written = 0;
+ u16 enet_bytes_written = 0;
+ u32 bytes_written = 0;
unsigned long flags;
+ struct fnic_frame_list *frame_elem = NULL;
+ struct fnic_eth_hdr_s *eh;

dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
- DMA_FROM_DEVICE);
- skb = buf->os_buf;
- fp = (struct fc_frame *)skb;
+ DMA_FROM_DEVICE);
+ fp = (uint8_t *) buf->os_buf;
buf->os_buf = NULL;

cq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index);
if (type == CQ_DESC_TYPE_RQ_FCP) {
- cq_fcp_rq_desc_dec((struct cq_fcp_rq_desc *)cq_desc,
- &type, &color, &q_number, &completed_index,
- &eop, &sop, &fcoe_fc_crc_ok, &exchange_id,
- &tmpl, &fcp_bytes_written, &sof, &eof,
- &ingress_port, &packet_error,
- &fcoe_enc_error, &fcs_ok, &vlan_stripped,
- &vlan);
- skb_trim(skb, fcp_bytes_written);
- fr_sof(fp) = sof;
- fr_eof(fp) = eof;
-
+ cq_fcp_rq_desc_dec((struct cq_fcp_rq_desc *) cq_desc, &type,
+ &color, &q_number, &completed_index, &eop, &sop,
+ &fcoe_fnic_crc_ok, &exchange_id, &tmpl,
+ &fcp_bytes_written, &sof, &eof, &ingress_port,
+ &packet_error, &fcoe_enc_error, &fcs_ok,
+ &vlan_stripped, &vlan);
+ ethhdr_stripped = 1;
+ bytes_written = fcp_bytes_written;
} else if (type == CQ_DESC_TYPE_RQ_ENET) {
- cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
- &type, &color, &q_number, &completed_index,
- &ingress_port, &fcoe, &eop, &sop,
- &rss_type, &csum_not_calc, &rss_hash,
- &bytes_written, &packet_error,
- &vlan_stripped, &vlan, &checksum,
- &fcoe_sof, &fcoe_fc_crc_ok,
- &fcoe_enc_error, &fcoe_eof,
- &tcp_udp_csum_ok, &udp, &tcp,
- &ipv4_csum_ok, &ipv6, &ipv4,
- &ipv4_fragment, &fcs_ok);
- skb_trim(skb, bytes_written);
+ cq_enet_rq_desc_dec((struct cq_enet_rq_desc *) cq_desc, &type,
+ &color, &q_number, &completed_index,
+ &ingress_port, &fcoe, &eop, &sop, &rss_type,
+ &csum_not_calc, &rss_hash, &enet_bytes_written,
+ &packet_error, &vlan_stripped, &vlan,
+ &checksum, &fcoe_sof, &fcoe_fnic_crc_ok,
+ &fcoe_enc_error, &fcoe_eof, &tcp_udp_csum_ok,
+ &udp, &tcp, &ipv4_csum_ok, &ipv6, &ipv4,
+ &ipv4_fragment, &fcs_ok);
+
+ ethhdr_stripped = 0;
+ bytes_written = enet_bytes_written;
+
if (!fcs_ok) {
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fcs error. dropping packet.\n");
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p fcs error. Dropping packet.\n", fnic);
goto drop;
}
- if (fnic_import_rq_eth_pkt(fnic, skb))
- return;
+ eh = (struct fnic_eth_hdr_s *) fp;
+ if (eh->ether_type != htons(ETH_TYPE_FCOE)) {
+
+ if (fnic_import_rq_eth_pkt(fnic, fp))
+ return;

+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping ether_type 0x%x",
+ ntohs(eh->ether_type));
+ goto drop;
+ }
} else {
- /* wrong CQ type*/
- shost_printk(KERN_ERR, fnic->lport->host,
- "fnic rq_cmpl wrong cq type x%x\n", type);
+ /* wrong CQ type */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic rq_cmpl wrong cq type x%x\n", type);
goto drop;
}

- if (!fcs_ok || packet_error || !fcoe_fc_crc_ok || fcoe_enc_error) {
+ if (!fcs_ok || packet_error || !fcoe_fnic_crc_ok || fcoe_enc_error) {
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fnic rq_cmpl fcoe x%x fcsok x%x"
- " pkterr x%x fcoe_fc_crc_ok x%x, fcoe_enc_err"
- " x%x\n",
- fcoe, fcs_ok, packet_error,
- fcoe_fc_crc_ok, fcoe_enc_error);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fcoe %x fcsok %x pkterr %x ffco %x fee %x\n",
+ fcoe, fcs_ok, packet_error,
+ fcoe_fnic_crc_ok, fcoe_enc_error);
goto drop;
}

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->lport->host, fnic->fnic_num,
+ "fnic->stop_rx_link_events: %d\n",
+ fnic->stop_rx_link_events);
goto drop;
}
- fr_dev(fp) = fnic->lport;
+
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- if ((fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_RECV,
- (char *)skb->data, skb->len)) != 0) {
- printk(KERN_ERR "fnic ctlr frame trace error!!!");
+
+ frame_elem =
+ kmalloc(sizeof(struct fnic_frame_list),
+ GFP_ATOMIC);
+ if (!frame_elem) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unable to alloc frame element of size: %ld\n",
+ sizeof(struct fnic_frame_list));
+ goto drop;
}
+ memset(frame_elem, 0, sizeof(struct fnic_frame_list));
+ frame_elem->fp = fp;
+ frame_elem->rx_ethhdr_stripped = ethhdr_stripped;
+ frame_elem->frame_len = bytes_written;

- skb_queue_tail(&fnic->frame_queue, skb);
queue_work(fnic_event_queue, &fnic->frame_work);
-
return;
+
drop:
- dev_kfree_skb_irq(skb);
+ kfree(fp);
}

static int fnic_rq_cmpl_handler_cont(struct vnic_dev *vdev,
@@ -1089,62 +594,6 @@ void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
buf->os_buf = NULL;
}

-/**
- * fnic_eth_send() - Send Ethernet frame.
- * @fip: fcoe_ctlr instance.
- * @skb: Ethernet Frame, FIP, without VLAN encapsulation.
- */
-void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
- struct fnic *fnic = fnic_from_ctlr(fip);
- struct vnic_wq *wq = &fnic->wq[0];
- dma_addr_t pa;
- struct ethhdr *eth_hdr;
- struct vlan_ethhdr *vlan_hdr;
- unsigned long flags;
-
- if (!fnic->vlan_hw_insert) {
- eth_hdr = (struct ethhdr *)skb_mac_header(skb);
- vlan_hdr = skb_push(skb, sizeof(*vlan_hdr) - sizeof(*eth_hdr));
- memcpy(vlan_hdr, eth_hdr, 2 * ETH_ALEN);
- vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
- vlan_hdr->h_vlan_encapsulated_proto = eth_hdr->h_proto;
- vlan_hdr->h_vlan_TCI = htons(fnic->vlan_id);
- if ((fnic_fc_trace_set_data(fnic->lport->host->host_no,
- FNIC_FC_SEND|0x80, (char *)eth_hdr, skb->len)) != 0) {
- printk(KERN_ERR "fnic ctlr frame trace error!!!");
- }
- } else {
- if ((fnic_fc_trace_set_data(fnic->lport->host->host_no,
- FNIC_FC_SEND|0x80, (char *)skb->data, skb->len)) != 0) {
- printk(KERN_ERR "fnic ctlr frame trace error!!!");
- }
- }
-
- pa = dma_map_single(&fnic->pdev->dev, skb->data, skb->len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(&fnic->pdev->dev, pa)) {
- printk(KERN_ERR "DMA mapping failed\n");
- goto free_skb;
- }
-
- spin_lock_irqsave(&fnic->wq_lock[0], flags);
- if (!vnic_wq_desc_avail(wq))
- goto irq_restore;
-
- fnic_queue_wq_eth_desc(wq, skb, pa, skb->len,
- 0 /* hw inserts cos value */,
- fnic->vlan_id, 1);
- spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
- return;
-
-irq_restore:
- spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
- dma_unmap_single(&fnic->pdev->dev, pa, skb->len, DMA_TO_DEVICE);
-free_skb:
- kfree_skb(skb);
-}
-
/*
* Send FC frame.
*/
@@ -1245,6 +694,27 @@ fdls_send_fcoe_frame(struct fnic *fnic, void *payload, int payload_sz,
return ret;
}

+static int
+fdls_send_fip_frame(struct fnic *fnic, void *payload, int payload_sz)
+{
+ uint8_t *frame;
+ int max_framesz = FNIC_FCOE_FRAME_MAXSZ;
+ int ret;
+
+ frame = kmalloc(max_framesz, GFP_ATOMIC);
+ if (!frame) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic 0x%p Failed to allocate fip frame\n", fnic);
+ return -1;
+ }
+ memset(frame, 0, max_framesz);
+
+ memcpy(frame, (uint8_t *) payload, payload_sz);
+ ret = fnic_send_frame(fnic, frame, payload_sz);
+
+ return ret;
+}
+
int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
int payload_sz)
{
@@ -1269,6 +739,18 @@ int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
return ret;
}

+int
+fnic_send_fip_frame(struct fnic_iport_s *iport, void *payload,
+ int payload_sz)
+{
+ struct fnic *fnic = iport->fnic;
+
+ if (fnic->in_remove)
+ return -1;
+
+ return fdls_send_fip_frame(fnic, payload, payload_sz);
+}
+
/**
* fnic_flush_tx() - send queued frames.
* @work: pointer to work element
@@ -1342,44 +824,6 @@ fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
return 0;
}

-/**
- * fnic_set_eth_mode() - put fnic into ethernet mode.
- * @fnic: fnic device
- *
- * Called without fnic lock held.
- */
-static void fnic_set_eth_mode(struct fnic *fnic)
-{
- unsigned long flags;
- enum fnic_state old_state;
- int ret;
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
-again:
- old_state = fnic->state;
- switch (old_state) {
- case FNIC_IN_FC_MODE:
- case FNIC_IN_ETH_TRANS_FC_MODE:
- default:
- fnic->state = FNIC_IN_FC_TRANS_ETH_MODE;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
- ret = fnic_fw_reset_handler(fnic);
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (fnic->state != FNIC_IN_FC_TRANS_ETH_MODE)
- goto again;
- if (ret)
- fnic->state = old_state;
- break;
-
- case FNIC_IN_FC_TRANS_ETH_MODE:
- case FNIC_IN_ETH_MODE:
- break;
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-}
-
void fnic_free_txq(struct list_head *head)
{
struct fnic_frame_list *cur_frame, *next;
@@ -1449,24 +893,3 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
buf->os_buf = NULL;
}

-void fnic_fcoe_reset_vlans(struct fnic *fnic)
-{
- unsigned long flags;
- struct fcoe_vlan *vlan;
- struct fcoe_vlan *next;
-
- /*
- * indicate a link down to fcoe so that all fcf's are free'd
- * might not be required since we did this before sending vlan
- * discovery request
- */
- spin_lock_irqsave(&fnic->vlans_lock, flags);
- if (!list_empty(&fnic->vlans)) {
- list_for_each_entry_safe(vlan, next, &fnic->vlans, list) {
- list_del(&vlan->list);
- kfree(vlan);
- }
- }
- spin_unlock_irqrestore(&fnic->vlans_lock, flags);
-}
-
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 7d10d603f53b..d850ce4b743d 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -85,12 +85,13 @@ module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN");

static struct libfc_function_template fnic_transport_template = {
- .lport_set_port_id = fnic_set_port_id,
.fcp_abort_io = fnic_empty_scsi_cleanup,
.fcp_cleanup = fnic_empty_scsi_cleanup,
.exch_mgr_reset = fnic_exch_mgr_reset
};

+struct workqueue_struct *fnic_fip_queue;
+
static int fnic_slave_alloc(struct scsi_device *sdev)
{
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
@@ -413,13 +414,6 @@ static void fnic_notify_timer(struct timer_list *t)
round_jiffies(jiffies + FNIC_NOTIFY_TIMER_PERIOD));
}

-static void fnic_fip_notify_timer(struct timer_list *t)
-{
- struct fnic *fnic = from_timer(fnic, t, fip_timer);
-
- /* Placeholder function */
-}
-
static void fnic_notify_timer_start(struct fnic *fnic)
{
switch (vnic_dev_get_intr_mode(fnic->vdev)) {
@@ -531,17 +525,6 @@ static void fnic_iounmap(struct fnic *fnic)
iounmap(fnic->bar0.vaddr);
}

-/**
- * fnic_get_mac() - get assigned data MAC address for FIP code.
- * @lport: local port.
- */
-static u8 *fnic_get_mac(struct fc_lport *lport)
-{
- struct fnic *fnic = lport_priv(lport);
-
- return fnic->data_src_addr;
-}
-
static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id)
{
vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
@@ -814,26 +797,23 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fnic->vlan_hw_insert = 1;
fnic->vlan_id = 0;

- /* Initialize the FIP fcoe_ctrl struct */
- fnic->ctlr.send = fnic_eth_send;
- fnic->ctlr.update_mac = fnic_update_mac;
- fnic->ctlr.get_src_addr = fnic_get_mac;
if (fnic->config.flags & VFCF_FIP_CAPABLE) {
pr_info("firmware supports FIP\n");
/* enable directed and multicast */
vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0);
vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS);
vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr);
- fnic->set_vlan = fnic_set_vlan;
fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO);
- timer_setup(&fnic->fip_timer, fnic_fip_notify_timer, 0);
spin_lock_init(&fnic->vlans_lock);
INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
- INIT_WORK(&fnic->event_work, fnic_handle_event);
INIT_WORK(&fnic->flush_work, fnic_flush_tx);
- skb_queue_head_init(&fnic->fip_frame_queue);
- INIT_LIST_HEAD(&fnic->evlist);
- INIT_LIST_HEAD(&fnic->vlans);
+ INIT_LIST_HEAD(&fnic->fip_frame_queue);
+ INIT_LIST_HEAD(&fnic->vlan_list);
+ timer_setup(&fnic->retry_fip_timer, fnic_handle_fip_timer, 0);
+ timer_setup(&fnic->fcs_ka_timer, fnic_handle_fcs_ka_timer, 0);
+ timer_setup(&fnic->enode_ka_timer, fnic_handle_enode_ka_timer, 0);
+ timer_setup(&fnic->vn_ka_timer, fnic_handle_vn_ka_timer, 0);
+ fnic->set_vlan = fnic_set_vlan;
} else {
pr_info("firmware uses non-FIP mode\n");
fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_NON_FIP);
@@ -1030,10 +1010,13 @@ static void fnic_remove(struct pci_dev *pdev)
fnic_free_txq(&fnic->tx_queue);

if (fnic->config.flags & VFCF_FIP_CAPABLE) {
- del_timer_sync(&fnic->fip_timer);
- skb_queue_purge(&fnic->fip_frame_queue);
+ del_timer_sync(&fnic->retry_fip_timer);
+ del_timer_sync(&fnic->fcs_ka_timer);
+ del_timer_sync(&fnic->enode_ka_timer);
+ del_timer_sync(&fnic->vn_ka_timer);
+
+ fnic_free_txq(&fnic->fip_frame_queue);
fnic_fcoe_reset_vlans(fnic);
- fnic_fcoe_evlist_free(fnic);
}

if ((fnic_fdmi_support == 1) && (fnic->iport.fabric.fdmi_pending > 0))
--
2.31.1


Subject: [PATCH 09/14] scsi: fnic: Modify IO path to use FDLS

Modify IO path to use FDLS.
Add helper functions to process IOs.
Remove unused template functions.
Cleanup obsolete code.
Refactor old function definitions.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fnic.h | 20 +-
drivers/scsi/fnic/fnic_io.h | 3 +
drivers/scsi/fnic/fnic_main.c | 5 +-
drivers/scsi/fnic/fnic_scsi.c | 1107 +++++++++++++++++++-------------
drivers/scsi/fnic/fnic_stats.h | 2 -
5 files changed, 680 insertions(+), 457 deletions(-)

diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 5fbd5cf23bfe..870b8fea452d 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -40,6 +40,7 @@
#define FNIC_DFLT_IO_REQ 256 /* Default scsi_cmnd tag map entries */
#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

/*
* Tag bits used for special requests.
@@ -472,7 +473,6 @@ int fnic_set_intr_mode_msix(struct fnic *fnic);
void fnic_free_intr(struct fnic *fnic);
int fnic_request_intr(struct fnic *fnic);

-int fnic_send(struct fc_lport *, struct fc_frame *);
void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf);
void fnic_handle_frame(struct work_struct *work);
void fnic_tport_event_handler(struct work_struct *work);
@@ -489,11 +489,9 @@ int fnic_abort_cmd(struct scsi_cmnd *);
int fnic_device_reset(struct scsi_cmnd *);
int fnic_eh_host_reset_handler(struct scsi_cmnd *sc);
int fnic_host_reset(struct Scsi_Host *shost);
-int fnic_reset(struct Scsi_Host *);
-void fnic_scsi_cleanup(struct fc_lport *);
-void fnic_scsi_abort_io(struct fc_lport *);
-void fnic_empty_scsi_cleanup(struct fc_lport *);
-void fnic_exch_mgr_reset(struct fc_lport *, u32, u32);
+void fnic_reset(struct Scsi_Host *shost);
+int fnic_issue_fc_host_lip(struct Scsi_Host *shost);
+void fnic_scsi_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);
@@ -505,7 +503,8 @@ const char *fnic_state_to_str(unsigned int state);
void fnic_mq_map_queues_cpus(struct Scsi_Host *host);
void fnic_log_q_error(struct fnic *fnic);
void fnic_handle_link_event(struct fnic *fnic);
-
+void fnic_stats_debugfs_init(struct fnic *fnic);
+void fnic_stats_debugfs_remove(struct fnic *fnic);
int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);

void fnic_handle_fip_frame(struct work_struct *work);
@@ -526,5 +525,12 @@ int fnic_get_desc_by_devid(struct pci_dev *pdev, char **desc,
void fnic_fdls_link_status_change(struct fnic *fnic, int linkup);
void fnic_delete_fcp_tports(struct fnic *fnic);
void fnic_flush_tport_event_list(struct fnic *fnic);
+int fnic_count_ioreqs_wq(struct fnic *fnic, u32 hwq, u32 portid);
+unsigned int fnic_count_ioreqs(struct fnic *fnic, u32 portid);
+unsigned int fnic_count_all_ioreqs(struct fnic *fnic);
+unsigned int fnic_count_lun_ioreqs_wq(struct fnic *fnic, u32 hwq,
+ struct scsi_device *device);
+unsigned int fnic_count_lun_ioreqs(struct fnic *fnic,
+ struct scsi_device *device);

#endif /* _FNIC_H_ */
diff --git a/drivers/scsi/fnic/fnic_io.h b/drivers/scsi/fnic/fnic_io.h
index 6fe642cb387b..0d974e040ab7 100644
--- a/drivers/scsi/fnic/fnic_io.h
+++ b/drivers/scsi/fnic/fnic_io.h
@@ -7,6 +7,7 @@
#define _FNIC_IO_H_

#include <scsi/fc/fc_fcp.h>
+#include "fnic_fdls.h"

#define FNIC_DFLT_SG_DESC_CNT 32
#define FNIC_MAX_SG_DESC_CNT 256 /* Maximum descriptors per sgl */
@@ -41,6 +42,8 @@ enum fnic_ioreq_state {
};

struct fnic_io_req {
+ struct fnic_iport_s *iport;
+ struct fnic_tport_s *tport;
struct host_sg_desc *sgl_list; /* sgl list */
void *sgl_list_alloc; /* sgl list address used for free */
dma_addr_t sense_buf_pa; /* dma address for sense buffer*/
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 1310e8b46f82..5a352d95c654 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -85,9 +85,6 @@ module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN");

static struct libfc_function_template fnic_transport_template = {
- .fcp_abort_io = fnic_empty_scsi_cleanup,
- .fcp_cleanup = fnic_empty_scsi_cleanup,
- .exch_mgr_reset = fnic_exch_mgr_reset
};

struct workqueue_struct *fnic_fip_queue;
@@ -162,7 +159,7 @@ static struct fc_function_template fnic_fc_functions = {
.show_starget_port_id = 1,
.show_rport_dev_loss_tmo = 1,
.set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo,
- .issue_fc_host_lip = fnic_reset,
+ .issue_fc_host_lip = fnic_issue_fc_host_lip,
.get_fc_host_stats = fnic_get_stats,
.reset_fc_host_stats = fnic_reset_host_stats,
.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 5d5d1205e984..e5bbe4319316 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -25,9 +25,12 @@
#include <scsi/fc/fc_fcoe.h>
#include <scsi/libfc.h>
#include <scsi/fc_frame.h>
+#include <scsi/scsi_transport_fc.h>
#include "fnic_io.h"
#include "fnic.h"

+static void fnic_cleanup_io(struct fnic *fnic, int exclude_id);
+
const char *fnic_state_str[] = {
[FNIC_IN_FC_MODE] = "FNIC_IN_FC_MODE",
[FNIC_IN_FC_TRANS_ETH_MODE] = "FNIC_IN_FC_TRANS_ETH_MODE",
@@ -65,6 +68,18 @@ static const char *fcpio_status_str[] = {
[FCPIO_LUNMAP_CHNG_PEND] = "FCPIO_LUNHMAP_CHNG_PEND",
};

+enum terminate_io_return {
+ TERM_SUCCESS = 0,
+ TERM_NO_SC = 1,
+ TERM_IO_REQ_NOT_FOUND,
+ TERM_ANOTHER_PORT,
+ TERM_GSTATE,
+ TERM_IO_BLOCKED,
+ TERM_OUT_OF_WQ_DESC,
+ TERM_TIMED_OUT,
+ TERM_MISC,
+};
+
const char *fnic_state_to_str(unsigned int state)
{
if (state >= ARRAY_SIZE(fnic_state_str) || !fnic_state_str[state])
@@ -90,8 +105,6 @@ static const char *fnic_fcpio_status_to_str(unsigned int status)
return fcpio_status_str[status];
}

-static void fnic_cleanup_io(struct fnic *fnic);
-
/*
* Unmap the data buffer and sense buffer for an io_req,
* also unmap and free the device-private scatter/gather list.
@@ -114,6 +127,80 @@ static void fnic_release_ioreq_buf(struct fnic *fnic,
SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
}

+int fnic_count_ioreqs_wq(struct fnic *fnic, u32 hwq, u32 portid)
+{
+ unsigned long flags = 0;
+ int i = 0, count = 0;
+
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
+ for (i = 0; i != fnic->sw_copy_wq[hwq].ioreq_table_size; ++i) {
+ if (fnic->sw_copy_wq[hwq].io_req_table[i] != NULL &&
+ (!portid
+ || fnic->sw_copy_wq[hwq].io_req_table[i]->port_id == portid))
+ count++;
+ }
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+
+ return count;
+}
+
+unsigned int fnic_count_ioreqs(struct fnic *fnic, u32 portid)
+{
+ int i;
+ unsigned int count = 0;
+
+ for (i = 0; i < fnic->wq_copy_count; i++)
+ count += fnic_count_ioreqs_wq(fnic, i, portid);
+
+ return count;
+}
+
+unsigned int fnic_count_all_ioreqs(struct fnic *fnic)
+{
+ return fnic_count_ioreqs(fnic, 0);
+}
+
+unsigned int fnic_count_lun_ioreqs_wq(struct fnic *fnic, u32 hwq,
+ struct scsi_device *device)
+{
+ struct fnic_io_req *io_req;
+ int i;
+ unsigned int count = 0;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
+ for (i = 0; i != fnic->sw_copy_wq[hwq].ioreq_table_size; ++i) {
+ io_req = fnic->sw_copy_wq[hwq].io_req_table[i];
+
+ if (io_req != NULL) {
+ struct scsi_cmnd *sc =
+ scsi_host_find_tag(fnic->lport->host, io_req->tag);
+
+ if (!sc)
+ continue;
+
+ if (sc->device == device)
+ count++;
+ }
+ }
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+
+ return count;
+}
+
+unsigned int fnic_count_lun_ioreqs(struct fnic *fnic,
+ struct scsi_device *device)
+{
+ int hwq;
+ unsigned int count = 0;
+
+ /*count if any pending IOs on this lun */
+ for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
+ count += fnic_count_lun_ioreqs_wq(fnic, hwq, device);
+
+ 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)
{
@@ -179,12 +266,11 @@ int fnic_fw_reset_handler(struct fnic *fnic)
struct vnic_wq_copy *wq = &fnic->hw_copy_wq[0];
int ret = 0;
unsigned long flags;
+ unsigned int ioreq_count;

/* indicate fwreset to io path */
fnic_set_state_flags(fnic, FNIC_FLAGS_FWRESET);
-
- fnic_free_txq(&fnic->frame_queue);
- fnic_free_txq(&fnic->tx_queue);
+ ioreq_count = fnic_count_all_ioreqs(fnic);

/* wait for io cmpl */
while (atomic_read(&fnic->in_flight))
@@ -231,10 +317,10 @@ int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id)
{
struct vnic_wq_copy *wq = &fnic->hw_copy_wq[0];
enum fcpio_flogi_reg_format_type format;
- struct fc_lport *lp = fnic->lport;
u8 gw_mac[ETH_ALEN];
int ret = 0;
unsigned long flags;
+ struct fnic_iport_s *iport = &fnic->iport;

spin_lock_irqsave(&fnic->wq_copy_lock[0], flags);

@@ -246,28 +332,23 @@ int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id)
goto flogi_reg_ioreq_end;
}

- if (fnic->ctlr.map_dest) {
- eth_broadcast_addr(gw_mac);
- format = FCPIO_FLOGI_REG_DEF_DEST;
- } else {
- memcpy(gw_mac, fnic->ctlr.dest_addr, ETH_ALEN);
- format = FCPIO_FLOGI_REG_GW_DEST;
- }
+ memcpy(gw_mac, fnic->iport.fcfmac, ETH_ALEN);
+ format = FCPIO_FLOGI_REG_GW_DEST;

- if ((fnic->config.flags & VFCF_FIP_CAPABLE) && !fnic->ctlr.map_dest) {
+ if (fnic->config.flags & VFCF_FIP_CAPABLE) {
fnic_queue_wq_copy_desc_fip_reg(wq, SCSI_NO_TAG,
fc_id, gw_mac,
- fnic->data_src_addr,
- lp->r_a_tov, lp->e_d_tov);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "FLOGI FIP reg issued fcid %x src %pM dest %pM\n",
- fc_id, fnic->data_src_addr, gw_mac);
+ fnic->iport.fpma,
+ iport->r_a_tov, iport->e_d_tov);
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
- "FLOGI reg issued fcid 0x%x map %d dest 0x%p\n",
- fc_id, fnic->ctlr.map_dest, gw_mac);
+ "FLOGI reg issued fcid 0x%x dest %p\n",
+ fc_id, gw_mac);
}

atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs);
@@ -295,13 +376,17 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
{
struct scatterlist *sg;
struct fc_rport *rport = starget_to_rport(scsi_target(sc->device));
- struct fc_rport_libfc_priv *rp = rport->dd_data;
struct host_sg_desc *desc;
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
unsigned int i;
int flags;
u8 exch_flags;
struct scsi_lun fc_lun;
+ struct fnic_tport_s *tport;
+ struct rport_dd_data_s *rdd_data;
+
+ rdd_data = rport->dd_data;
+ tport = rdd_data->tport;

if (sg_count) {
/* For each SGE, create a device desc entry */
@@ -356,7 +441,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,

exch_flags = 0;
if ((fnic->config.flags & VFCF_FCP_SEQ_LVL_ERR) &&
- (rp->flags & FC_RP_FLAGS_RETRY))
+ (tport->tgt_flags & FDLS_FC_RP_FLAGS_RETRY))
exch_flags |= FCPIO_ICMND_SRFLAG_RETRY;

fnic_queue_wq_copy_desc_icmnd_16(wq, mqtag,
@@ -371,8 +456,8 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
sc->cmnd, sc->cmd_len,
scsi_bufflen(sc),
fc_lun.scsi_lun, io_req->port_id,
- rport->maxframe_size, rp->r_a_tov,
- rp->e_d_tov);
+ tport->max_payload_size,
+ tport->r_a_tov, tport->e_d_tov);

atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs);
if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) >
@@ -388,10 +473,10 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
struct request *const rq = scsi_cmd_to_rq(sc);
uint32_t mqtag = 0;
void (*done)(struct scsi_cmnd *) = scsi_done;
- struct fc_lport *lp = shost_priv(sc->device->host);
struct fc_rport *rport;
struct fnic_io_req *io_req = NULL;
- struct fnic *fnic = lport_priv(lp);
+ struct fnic *fnic = *((struct fnic **) shost_priv(sc->device->host));
+ struct fnic_iport_s *iport = NULL;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
struct vnic_wq_copy *wq;
int ret = 1;
@@ -400,32 +485,14 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
unsigned long flags = 0;
unsigned long ptr;
int io_lock_acquired = 0;
- struct fc_rport_libfc_priv *rp;
uint16_t hwq = 0;
-
- mqtag = blk_mq_unique_tag(rq);
- spin_lock_irqsave(&fnic->fnic_lock, flags);
-
- if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
- "fnic IO blocked flags: 0x%lx. Returning SCSI_MLQUEUE_HOST_BUSY\n",
- fnic->state_flags);
- return SCSI_MLQUEUE_HOST_BUSY;
- }
-
- if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET))) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
- "fnic flags: 0x%lx. Returning SCSI_MLQUEUE_HOST_BUSY\n",
- fnic->state_flags);
- return SCSI_MLQUEUE_HOST_BUSY;
- }
+ struct fnic_tport_s *tport = NULL;
+ struct rport_dd_data_s *rdd_data;
+ uint16_t lun0_delay = 0;

rport = starget_to_rport(scsi_target(sc->device));
if (!rport) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
"returning DID_NO_CONNECT for IO as rport is NULL\n");
sc->result = DID_NO_CONNECT << 16;
done(sc);
@@ -434,50 +501,95 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)

ret = fc_remote_port_chkready(rport);
if (ret) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
"rport is not ready\n");
- atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
sc->result = ret;
done(sc);
return 0;
}

- rp = rport->dd_data;
- if (!rp || rp->rp_state == RPORT_ST_DELETE) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "rport 0x%x removed, returning DID_NO_CONNECT\n",
- rport->port_id);
+ mqtag = blk_mq_unique_tag(rq);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ iport = &fnic->iport;

- atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
- sc->result = DID_NO_CONNECT<<16;
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "returning DID_NO_CONNECT for IO as iport state: %d\n",
+ iport->state);
+ sc->result = DID_NO_CONNECT << 16;
done(sc);
return 0;
}

- if (rp->rp_state != RPORT_ST_READY) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "rport 0x%x in state 0x%x, returning DID_IMM_RETRY\n",
- rport->port_id, rp->rp_state);
+ /* fc_remote_port_add() may have added the tport to
+ * fc_transport but dd_data not yet set
+ */
+ rdd_data = rport->dd_data;
+ tport = rdd_data->tport;
+ if (!tport || (rdd_data->iport != iport)) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
+ "returning DID_BUS_BUSY for IO as tport not found for: 0x%x\n",
+ rport->port_id);
+ sc->result = DID_BUS_BUSY << 16;
+ done(sc);
+ return 0;
+ }

- sc->result = DID_IMM_RETRY << 16;
+ /* Re-assign same params as in fnic_fdls_add_tport */
+ rport->maxframe_size = FNIC_FC_MAX_PAYLOAD_LEN;
+ rport->supported_classes =
+ FC_COS_CLASS3 | FC_RPORT_ROLE_FCP_TARGET;
+ /* the dd_data is allocated by fctransport of size dd_fcrport_size */
+ rdd_data = rport->dd_data;
+ rdd_data->tport = tport;
+ rdd_data->iport = iport;
+ tport->rport = rport;
+ tport->flags |= FNIC_FDLS_SCSI_REGISTERED;
+ }
+
+ 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->lport->host, fnic->fnic_num,
+ "returning DID_NO_CONNECT for IO as tport state: %d\n",
+ tport->state);
+ sc->result = DID_NO_CONNECT << 16;
done(sc);
return 0;
}

- if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
+ atomic_inc(&fnic->in_flight);
+ atomic_inc(&tport->in_flight);
+
+ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) {
+ atomic_dec(&fnic->in_flight);
+ atomic_dec(&tport->in_flight);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
+ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET))) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
- "state not ready: %d/link not up: %d Returning HOST_BUSY\n",
- lp->state, lp->link_up);
+ "fnic flags FW reset: 0x%lx. Returning SCSI_MLQUEUE_HOST_BUSY\n",
+ fnic->state_flags);
return SCSI_MLQUEUE_HOST_BUSY;
}

- atomic_inc(&fnic->in_flight);
+ if (!tport->lun0_delay) {
+ lun0_delay = 1;
+ tport->lun0_delay++;
+ }

spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
fnic_priv(sc)->state = FNIC_IOREQ_NOT_INITED;
fnic_priv(sc)->flags = FNIC_NO_FLAGS;

@@ -499,6 +611,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
goto out;
}

+ io_req->tport = tport;
/* Determine the type of scatter/gather list we need */
io_req->sgl_cnt = sg_count;
io_req->sgl_type = FNIC_SGL_CACHE_DFLT;
@@ -575,6 +688,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
mempool_free(io_req, fnic->io_req_pool);
}
atomic_dec(&fnic->in_flight);
+ atomic_dec(&tport->in_flight);
return ret;
} else {
atomic64_inc(&fnic_stats->io_stats.active_ios);
@@ -602,6 +716,14 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);

atomic_dec(&fnic->in_flight);
+ atomic_dec(&tport->in_flight);
+
+ if (lun0_delay) {
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "LUN0 delay\n");
+ mdelay(LUN0_DELAY_TIME);
+ }
+
return ret;
}

@@ -625,7 +747,7 @@ 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);
+ fnic_cleanup_io(fnic, SCSI_NO_TAG);

atomic64_set(&fnic->fnic_stats.fw_stats.active_fw_reqs, 0);
atomic64_set(&fnic->fnic_stats.io_stats.active_ios, 0);
@@ -646,12 +768,6 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
"reset failed with header status: %s\n",
fnic_fcpio_status_to_str(hdr_status));

- /*
- * Unable to change to eth mode, cannot send out flogi
- * Change state to fc mode, so that subsequent Flogi
- * requests from libFC will cause more attempts to
- * reset the firmware. Free the cached flogi
- */
fnic->state = FNIC_IN_FC_MODE;
atomic64_inc(&reset_stats->fw_reset_failures);
ret = -1;
@@ -664,15 +780,14 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
ret = -1;
}

- /* Thread removing device blocks till firmware reset is complete */
- if (fnic->remove_wait)
- complete(fnic->remove_wait);
+ if (fnic->fw_reset_done)
+ complete(fnic->fw_reset_done);

/*
* If fnic is being removed, or fw reset failed
* free the flogi frame. Else, send it out
*/
- if (fnic->remove_wait || ret) {
+ if (ret) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
fnic_free_txq(&fnic->tx_queue);
goto reset_cmpl_handler_end;
@@ -711,12 +826,12 @@ 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->lport->host, fnic->fnic_num,
- "flog reg succeeded\n");
+ "FLOGI reg succeeded\n");
fnic->state = FNIC_IN_FC_MODE;
} else {
FNIC_SCSI_DBG(KERN_DEBUG,
fnic->lport->host, fnic->fnic_num,
- "fnic flogi reg :failed %s\n",
+ "fnic flogi reg failed: %s\n",
fnic_fcpio_status_to_str(hdr_status));
fnic->state = FNIC_IN_ETH_MODE;
ret = -1;
@@ -1023,15 +1138,6 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
jiffies_to_msecs(jiffies - start_time)),
desc, cmd_trace, fnic_flags_and_state(sc));

- if (sc->sc_data_direction == DMA_FROM_DEVICE) {
- fnic->lport->host_stats.fcp_input_requests++;
- fnic->fcp_input_bytes += xfer_len;
- } else if (sc->sc_data_direction == DMA_TO_DEVICE) {
- fnic->lport->host_stats.fcp_output_requests++;
- fnic->fcp_output_bytes += xfer_len;
- } else
- fnic->lport->host_stats.fcp_control_requests++;
-
/* Call SCSI completion function to complete the IO */
scsi_done(sc);

@@ -1409,37 +1515,33 @@ int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do, unsigned i
return cur_work_done;
}

-static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
+static void fnic_cleanup_one_io(struct fnic_io_req *io_req,
+ struct fnic *fnic, uint16_t hwq)
{
- struct request *const rq = scsi_cmd_to_rq(sc);
- struct fnic *fnic = data;
- struct fnic_io_req *io_req;
- unsigned long flags = 0;
+ int tag;
+ struct scsi_cmnd *sc;
unsigned long start_time = 0;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
- uint16_t hwq = 0;
- int tag;
- int mqtag;

- mqtag = blk_mq_unique_tag(rq);
- hwq = blk_mq_unique_tag_to_hwq(mqtag);
- tag = blk_mq_unique_tag_to_tag(mqtag);
+ if (!io_req) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "tag: 0x%x hwq: %d ioreq is NULL\n", tag, hwq);
+ return;
+ }

- spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
+ tag = io_req->tag;

- fnic->sw_copy_wq[hwq].io_req_table[tag] = NULL;
+ sc = scsi_host_find_tag(fnic->lport->host, tag);
+ if (!sc)
+ return;

- 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->lport->host, fnic->fnic_num,
- "hwq: %d mqtag: 0x%x tag: 0x%x flags: 0x%x No ioreq. Returning\n",
- hwq, mqtag, tag, fnic_priv(sc)->flags);
- return true;
- }
+ fnic_priv(sc)->io_req = NULL;
+ io_req->sc = NULL;
+ fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(tag)] =
+ NULL;

if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
- !(fnic_priv(sc)->flags & FNIC_DEV_RST_DONE)) {
+ !(fnic_priv(sc)->flags & FNIC_DEV_RST_DONE)) {
/*
* We will be here only when FW completes reset
* without sending completions for outstanding ios.
@@ -1447,18 +1549,17 @@ static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
fnic_priv(sc)->flags |= FNIC_DEV_RST_DONE;
if (io_req && io_req->dr_done)
complete(io_req->dr_done);
- else if (io_req && io_req->abts_done)
- complete(io_req->abts_done);
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- return true;
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ return;
} else if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- return true;
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ return;
}

- fnic_priv(sc)->io_req = NULL;
- io_req->sc = NULL;
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);

/*
* If there is a scsi_cmnd associated with this io_req, then
@@ -1469,9 +1570,9 @@ 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->lport->host, fnic->fnic_num,
- "mqtag:0x%x tag: 0x%x sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
- mqtag, tag, sc, (jiffies - start_time));
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "tag:0x%x hwq:%d sc duration = %lu DID_TRANSPORT_DISRUPTED\n",
+ tag, hwq, (jiffies - start_time));

if (atomic64_read(&fnic->io_cmpl_skip))
atomic64_dec(&fnic->io_cmpl_skip);
@@ -1479,23 +1580,73 @@ static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data)
atomic64_inc(&fnic_stats->io_stats.io_completions);

FNIC_TRACE(fnic_cleanup_io,
- sc->device->host->host_no, tag, sc,
- jiffies_to_msecs(jiffies - start_time),
- 0, ((u64)sc->cmnd[0] << 32 |
- (u64)sc->cmnd[2] << 24 |
- (u64)sc->cmnd[3] << 16 |
- (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
- fnic_flags_and_state(sc));
-
+ sc->device->host->host_no, tag, sc,
+ jiffies_to_msecs(jiffies - start_time),
+ 0, ((u64) sc->cmnd[0] << 32 |
+ (u64) sc->cmnd[2] << 24 |
+ (u64) sc->cmnd[3] << 16 |
+ (u64) sc->cmnd[4] << 8 | sc->cmnd[5]),
+ (((u64) fnic_priv(sc)->flags << 32) | fnic_priv(sc)->
+ state));
+
+ /* Complete the command to SCSI */
scsi_done(sc);
-
- return true;
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
}

-static void fnic_cleanup_io(struct fnic *fnic)
+static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
{
- scsi_host_busy_iter(fnic->lport->host,
- fnic_cleanup_io_iter, fnic);
+ int hwq, i;
+ unsigned int io_count = 0;
+ struct fnic_io_req *io_req = NULL;
+ struct scsi_cmnd *sc;
+
+ io_count = fnic_count_all_ioreqs(fnic);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "Outstanding ioreq count: %d active io count: %lld Waiting\n",
+ io_count,
+ atomic64_read(&fnic->fnic_stats.io_stats.active_ios));
+
+ for (hwq = 0; hwq < fnic->wq_copy_count; hwq++) {
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ for (i = 0; i != fnic->sw_copy_wq[hwq].ioreq_table_size; ++i) {
+ io_req = fnic->sw_copy_wq[hwq].io_req_table[i];
+ if (io_req != NULL)
+ fnic_cleanup_one_io(io_req, fnic, hwq);
+ }
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ }
+ /* with sg3utils device reset, SC needs to be retrieved from ioreq */
+ spin_lock_irqsave(&fnic->wq_copy_lock[0],
+ fnic->sw_copy_wq[0].hw_lock_flags);
+ io_req = fnic->sw_copy_wq[0].io_req_table[fnic->fnic_max_tag_id];
+ if (io_req) {
+ sc = io_req->sc;
+ if (sc) {
+ if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET)
+ && !(fnic_priv(sc)->flags & FNIC_DEV_RST_DONE)) {
+ fnic_priv(sc)->flags |= FNIC_DEV_RST_DONE;
+ if (io_req && io_req->dr_done)
+ complete(io_req->dr_done);
+ }
+
+ }
+
+ }
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[0],
+ fnic->sw_copy_wq[0].hw_lock_flags);
+
+ while ((io_count = fnic_count_all_ioreqs(fnic))) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "Outstanding ioreq count: %d active io count: %lld Waiting\n",
+ io_count,
+ atomic64_read(&fnic->fnic_stats.io_stats.active_ios));
+
+ schedule_timeout(msecs_to_jiffies(100));
+ }
}

void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
@@ -1567,10 +1718,13 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
struct vnic_wq_copy *wq = &fnic->hw_copy_wq[hwq];
struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
unsigned long flags;
+ struct fnic_tport_s *tport = io_req->tport;

spin_lock_irqsave(&fnic->fnic_lock, flags);
if (unlikely(fnic_chk_state_flags_locked(fnic,
FNIC_FLAGS_IO_BLOCKED))) {
+ atomic_dec(&fnic->in_flight);
+ atomic_dec(&tport->in_flight);
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return 1;
} else
@@ -1585,6 +1739,7 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
if (!vnic_wq_copy_desc_avail(wq)) {
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->lport->host, fnic->fnic_num,
"fnic_queue_abort_io_req: failure: no descriptors\n");
atomic64_inc(&misc_stats->abts_cpwq_alloc_failures);
@@ -1612,98 +1767,94 @@ struct fnic_rport_abort_io_iter_data {
int term_cnt;
};

-static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
+static int fnic_rport_exch_terminate_io(struct fnic_io_req *io_req,
+ struct fnic *fnic, u32 port_id,
+ int hwq, int new_sc)
{
- struct request *const rq = scsi_cmd_to_rq(sc);
- struct fnic_rport_abort_io_iter_data *iter_data = data;
- struct fnic *fnic = iter_data->fnic;
- int abt_tag = 0;
- struct fnic_io_req *io_req;
+ int tag;
+ int abt_tag;
+ int ret = 0;
unsigned long flags;
+ struct scsi_cmnd *sc;
struct reset_stats *reset_stats = &fnic->fnic_stats.reset_stats;
struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
struct scsi_lun fc_lun;
- enum fnic_ioreq_state old_ioreq_state;
- uint16_t hwq = 0;

- abt_tag = blk_mq_unique_tag(rq);
- hwq = blk_mq_unique_tag_to_hwq(abt_tag);
+ tag = io_req->tag;
+ abt_tag = tag;
+ sc = io_req->sc;

- spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "tag: 0x%p hwq: %d matching for rport: 0x%x\n", sc, hwq,
+ port_id);

- io_req = fnic_priv(sc)->io_req;
+ if (!sc) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "sc is NULL tag: 0x%x hwq: %d\n", tag, hwq);
+ return TERM_NO_SC;
+ }

- if (!io_req || io_req->port_id != iter_data->port_id) {
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- return true;
+ io_req = (struct fnic_io_req *) fnic_priv(sc)->io_req;
+ if (!io_req) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "ioreq not found sc: 0x%p tag: 0x%x hwq: %d\n", sc,
+ tag, hwq);
+ return TERM_IO_REQ_NOT_FOUND;
}

- if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET) &&
- !(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED)) {
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
- "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);
- return true;
+ if (io_req->port_id != port_id) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "port id mismatch: pid:0x%x io->pid: 0x%x tag: 0x%x hwq: %d\n",
+ port_id, io_req->port_id, tag, hwq);
+ return TERM_ANOTHER_PORT;
}

- /*
- * Found IO that is still pending with firmware and
- * belongs to rport that went away
- */
- if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING) {
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- return true;
+ if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET)
+ && (!(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED))) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "dev reset not pending sc 0x%p\n", sc);
}
+
if (io_req->abts_done) {
shost_printk(KERN_ERR, fnic->lport->host,
- "fnic_rport_exch_reset: io_req->abts_done is set "
- "state is %s\n",
- fnic_ioreq_state_to_str(fnic_priv(sc)->state));
+ "%s: io_req->abts_done is set state is %s\n",
+ __func__,
+ fnic_ioreq_state_to_str(fnic_priv(sc)->state));
}

if (!(fnic_priv(sc)->flags & FNIC_IO_ISSUED)) {
shost_printk(KERN_ERR, fnic->lport->host,
- "rport_exch_reset "
- "IO not yet issued %p tag 0x%x flags "
- "%x state %d\n",
- sc, abt_tag, fnic_priv(sc)->flags, fnic_priv(sc)->state);
+ "rport_exch_reset IO not yet issued %p tag 0x%x",
+ sc, tag);
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "flags %x state %d\n", fnic_priv(sc)->flags,
+ fnic_priv(sc)->state);
}
- old_ioreq_state = fnic_priv(sc)->state;
- fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
+
fnic_priv(sc)->abts_status = FCPIO_INVALID_CODE;
+
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
atomic64_inc(&reset_stats->device_reset_terminates);
- abt_tag |= FNIC_TAG_DEV_RST;
+ abt_tag = (tag | FNIC_TAG_DEV_RST);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "dev reset sc 0x%p\n", sc);
}
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fnic_rport_exch_reset dev rst sc 0x%p\n", sc);
- BUG_ON(io_req->abts_done);
-
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fnic_rport_reset_exch: Issuing abts\n");

- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+ WARN_ON_ONCE(io_req->abts_done);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);

- /* Now queue the abort command to firmware */
+ /* Queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);

- if (fnic_queue_abort_io_req(fnic, abt_tag,
- FCPIO_ITMF_ABT_TASK_TERM,
- fc_lun.scsi_lun, io_req, hwq)) {
- /*
- * Revert the cmd state back to old state, if
- * it hasn't changed in between. This cmd will get
- * aborted later by scsi_eh, or cleaned up during
- * lun reset
- */
- spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
- "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)
- fnic_priv(sc)->state = old_ioreq_state;
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
+send_terminate:
+ ret = fnic_queue_abort_io_req(fnic, abt_tag,
+ FCPIO_ITMF_ABT_TASK_TERM,
+ fc_lun.scsi_lun, io_req, hwq);
+ if (ret) {
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ return ret;
} else {
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET)
@@ -1712,67 +1863,167 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
fnic_priv(sc)->flags |= FNIC_IO_INTERNAL_TERM_ISSUED;
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic64_inc(&term_stats->terminates);
- iter_data->term_cnt++;
}
- return true;
+
+ /* for lun reset send terminate to the original io if it is not sg3reset */
+ if (abt_tag != tag && !new_sc) {
+ abt_tag = tag;
+ goto send_terminate;
+ }
+
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ return TERM_SUCCESS;
}

void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
{
- struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
- struct fnic_rport_abort_io_iter_data iter_data = {
- .fnic = fnic,
- .port_id = port_id,
- .term_cnt = 0,
- };
+ struct terminate_stats *term_stats;
+ unsigned int io_count = 0;
+ int hwq, i;
+ unsigned long flags;
+ unsigned int term_count = 0, nosc_count = 0, noioreq_count = 0,
+ another_port_count = 0;
+ int ret;
+ struct fnic_io_req *io_req;
+ struct scsi_cmnd *sc;
+ unsigned long old_state;

- FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host, fnic->fnic_num,
- "fnic_rport_exch_reset called portid 0x%06x\n",
- port_id);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "fnic rport exchange reset for tport: 0x%06x\n",
+ port_id);

if (fnic->in_remove)
return;

- scsi_host_busy_iter(fnic->lport->host, fnic_rport_abort_io_iter,
- &iter_data);
- if (iter_data.term_cnt > atomic64_read(&term_stats->max_terminates))
- atomic64_set(&term_stats->max_terminates, iter_data.term_cnt);
-
-}
-
-void fnic_terminate_rport_io(struct fc_rport *rport)
-{
- struct fc_rport_libfc_priv *rdata;
- struct fc_lport *lport;
- struct fnic *fnic;
+ io_count = fnic_count_ioreqs(fnic, port_id);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "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));

- if (!rport) {
- printk(KERN_ERR "fnic_terminate_rport_io: rport is NULL\n");
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ atomic_inc(&fnic->in_flight);
+ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) {
+ atomic_dec(&fnic->in_flight);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return;
}
- rdata = rport->dd_data;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);

- if (!rdata) {
- printk(KERN_ERR "fnic_terminate_rport_io: rdata is NULL\n");
- return;
+ for (hwq = 0; hwq < fnic->wq_copy_count; hwq++) {
+ spin_lock_irqsave(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ for (i = 0; i != fnic->sw_copy_wq[hwq].ioreq_table_size; ++i) {
+
+ io_req = fnic->sw_copy_wq[hwq].io_req_table[i];
+ if (!io_req)
+ continue;
+
+ if (io_req->port_id != port_id)
+ continue;
+
+ sc = scsi_host_find_tag(fnic->lport->host, io_req->tag);
+ if (!sc)
+ continue;
+
+ if (fnic_priv(sc)->state == FNIC_IOREQ_ABTS_PENDING)
+ continue;
+
+ old_state = fnic_priv(sc)->state;
+ fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
+
+ ret =
+ fnic_rport_exch_terminate_io(io_req, fnic, port_id, hwq,
+ 0);
+ switch (ret) {
+ case TERM_ANOTHER_PORT:
+ another_port_count++;
+ break;
+ case TERM_IO_BLOCKED:
+ atomic_dec(&fnic->in_flight);
+ fnic_priv(sc)->state = old_state;
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
+ return;
+ }
+
+ }
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq],
+ fnic->sw_copy_wq[hwq].hw_lock_flags);
}
- lport = rdata->local_port;

- if (!lport) {
- printk(KERN_ERR "fnic_terminate_rport_io: lport is NULL\n");
- return;
+ spin_lock_irqsave(&fnic->wq_copy_lock[0],
+ fnic->sw_copy_wq[0].hw_lock_flags);
+ /* if it sg3reset for this port we need to send terminate for this */
+ io_req = fnic->sw_copy_wq[0].io_req_table[fnic->fnic_max_tag_id];
+ if (io_req && (io_req->port_id == port_id)) {
+
+ sc = io_req->sc;
+ if (sc && (fnic_priv(sc)->state != FNIC_IOREQ_ABTS_PENDING)) {
+ old_state = fnic_priv(sc)->state;
+ fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "sg3 dev rst sc 0x%p sg\n", sc);
+ if (fnic_rport_exch_terminate_io(io_req, fnic, port_id, 0, 1)
+ == TERM_IO_BLOCKED) {
+ atomic_dec(&fnic->in_flight);
+ fnic_priv(sc)->state = old_state;
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[0],
+ fnic->sw_copy_wq[0].hw_lock_flags);
+ return;
+ }
+
+ }
}
- fnic = lport_priv(lport);
+ spin_unlock_irqrestore(&fnic->wq_copy_lock[0],
+ fnic->sw_copy_wq[0].hw_lock_flags);
+
+ atomic_dec(&fnic->in_flight);
+
+ while ((io_count = fnic_count_ioreqs(fnic, port_id)))
+ schedule_timeout(msecs_to_jiffies(1000));
+
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "IOs terminated: rport: 0x%x terminated: %d ",
+ port_id, term_count);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "wwpn 0x%llx, wwnn0x%llx, rport 0x%p, portid 0x%06x\n",
- rport->port_name, rport->node_name, rport,
- rport->port_id);
+ "remaining portid-io-count: %d ",
+ io_count);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "nosc_count: %d noioreq_count: %d another_port_count: %d\n",
+ nosc_count, noioreq_count,
+ another_port_count);

- if (fnic->in_remove)
+ term_stats = &fnic->fnic_stats.term_stats;
+
+ if (term_count > atomic64_read(&term_stats->max_terminates))
+ atomic64_set(&term_stats->max_terminates, term_count);
+}
+
+void fnic_terminate_rport_io(struct fc_rport *rport)
+{
+ struct fnic_tport_s *tport;
+ struct rport_dd_data_s *rdd_data;
+
+ if (!rport) {
+ pr_err("rport is NULL\n");
return;
+ }

- fnic_rport_exch_reset(fnic, rport->port_id);
+ rdd_data = rport->dd_data;
+ if (rdd_data) {
+ tport = rdd_data->tport;
+ if (!tport) {
+ pr_err(
+ "term rport io called after tport is deleted. Returning 0x%8x\n",
+ rport->port_id);
+ } else {
+ pr_err(
+ "term rport io called after tport is set 0x%8x. tport maybe rediscovered\n",
+ rport->port_id);
+ }
+ }
}

/*
@@ -1783,10 +2034,12 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
int fnic_abort_cmd(struct scsi_cmnd *sc)
{
struct request *const rq = scsi_cmd_to_rq(sc);
- struct fc_lport *lp;
+ struct fnic_iport_s *iport;
+ struct fnic_tport_s *tport;
struct fnic *fnic;
struct fnic_io_req *io_req = NULL;
struct fc_rport *rport;
+ struct rport_dd_data_s *rdd_data;
unsigned long flags;
unsigned long start_time = 0;
int ret = SUCCESS;
@@ -1806,11 +2059,11 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
fc_block_scsi_eh(sc);

/* Get local-port, check ready and link up */
- lp = shost_priv(sc->device->host);
-
- fnic = lport_priv(lp);
+ fnic = *((struct fnic **) shost_priv(sc->device->host));

spin_lock_irqsave(&fnic->fnic_lock, flags);
+ iport = &fnic->iport;
+
fnic_stats = &fnic->fnic_stats;
abts_stats = &fnic->fnic_stats.abts_stats;
term_stats = &fnic->fnic_stats.term_stats;
@@ -1821,7 +2074,43 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)

fnic_priv(sc)->flags = FNIC_NO_FLAGS;

- if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
+ rdd_data = rport->dd_data;
+ tport = rdd_data->tport;
+
+ if (!tport) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Abort cmd called after tport delete! rport fcid: 0x%x",
+ rport->port_id);
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "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);
+ ret = FAILED;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ goto fnic_abort_cmd_end;
+ }
+
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
+ "Op: 0x%x flags: 0x%x\n",
+ sc->cmnd[0],
+ fnic_priv(sc)->flags);
+
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport NOT in READY state");
+ ret = FAILED;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ goto fnic_abort_cmd_end;
+ }
+
+ if ((tport->state != FDLS_TGT_STATE_READY) &&
+ (tport->state != FDLS_TGT_STATE_ADISC)) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "tport state: %d\n", tport->state);
ret = FAILED;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
goto fnic_abort_cmd_end;
@@ -1843,6 +2132,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
+ ret = FAILED;
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
goto fnic_abort_cmd_end;
}
@@ -1893,7 +2183,6 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
if (fc_remote_port_chkready(rport) == 0)
task_req = FCPIO_ITMF_ABT_TASK;
else {
- atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
task_req = FCPIO_ITMF_ABT_TASK_TERM;
}

@@ -2027,6 +2316,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
unsigned long flags;
uint16_t hwq = 0;
uint32_t tag = 0;
+ struct fnic_tport_s *tport = io_req->tport;

tag = io_req->tag;
hwq = blk_mq_unique_tag_to_hwq(tag);
@@ -2037,8 +2327,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
FNIC_FLAGS_IO_BLOCKED))) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return FAILED;
- } else
+ } else {
atomic_inc(&fnic->in_flight);
+ atomic_inc(&tport->in_flight);
+ }
spin_unlock_irqrestore(&fnic->fnic_lock, flags);

spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
@@ -2072,6 +2364,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
lr_io_req_end:
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
atomic_dec(&fnic->in_flight);
+ atomic_inc(&tport->in_flight);

return ret;
}
@@ -2274,11 +2567,11 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
int fnic_device_reset(struct scsi_cmnd *sc)
{
struct request *rq = scsi_cmd_to_rq(sc);
- struct fc_lport *lp;
struct fnic *fnic;
struct fnic_io_req *io_req = NULL;
struct fc_rport *rport;
int status;
+ int count = 0;
int ret = FAILED;
unsigned long flags;
unsigned long start_time = 0;
@@ -2289,31 +2582,61 @@ int fnic_device_reset(struct scsi_cmnd *sc)
DECLARE_COMPLETION_ONSTACK(tm_done);
bool new_sc = 0;
uint16_t hwq = 0;
+ struct fnic_iport_s *iport = NULL;
+ struct rport_dd_data_s *rdd_data;
+ struct fnic_tport_s *tport;
+ u32 old_soft_reset_count;
+ u32 old_link_down_cnt;
+ int exit_dr = 0;

/* Wait for rport to unblock */
fc_block_scsi_eh(sc);

/* Get local-port, check ready and link up */
- lp = shost_priv(sc->device->host);
+ fnic = *((struct fnic **) shost_priv(sc->device->host));
+ iport = &fnic->iport;

- fnic = lport_priv(lp);
fnic_stats = &fnic->fnic_stats;
reset_stats = &fnic->fnic_stats.reset_stats;

atomic64_inc(&reset_stats->device_resets);

rport = starget_to_rport(scsi_target(sc->device));
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fcid: 0x%x lun: 0x%llx hwq: %d mqtag: 0x%x flags: 0x%x Device reset\n",
+ "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);

- if (lp->state != LPORT_ST_READY || !(lp->link_up))
+ rdd_data = rport->dd_data;
+ tport = rdd_data->tport;
+ if (!tport) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "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);
+ goto fnic_device_reset_end;
+ }
+
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "iport NOT in READY state");
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ goto fnic_device_reset_end;
+ }
+
+ if ((tport->state != FDLS_TGT_STATE_READY) &&
+ (tport->state != FDLS_TGT_STATE_ADISC)) {
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "tport state: %d\n", tport->state);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
goto fnic_device_reset_end;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);

/* Check if remote port up */
if (fc_remote_port_chkready(rport)) {
- atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
goto fnic_device_reset_end;
}

@@ -2352,6 +2675,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
io_req->port_id = rport->port_id;
io_req->tag = mqtag;
fnic_priv(sc)->io_req = io_req;
+ io_req->tport = tport;
io_req->sc = sc;

if (fnic->sw_copy_wq[hwq].io_req_table[blk_mq_unique_tag_to_tag(mqtag)] != NULL)
@@ -2383,6 +2707,11 @@ int fnic_device_reset(struct scsi_cmnd *sc)
fnic_priv(sc)->flags |= FNIC_DEV_RST_ISSUED;
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);

+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ old_link_down_cnt = iport->fnic->link_down_cnt;
+ old_soft_reset_count = fnic->soft_reset_count;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
/*
* Wait on the local completion for LUN reset. The io_req may be
* freed while we wait since we hold no lock.
@@ -2390,6 +2719,24 @@ int fnic_device_reset(struct scsi_cmnd *sc)
wait_for_completion_timeout(&tm_done,
msecs_to_jiffies(FNIC_LUN_RESET_TIMEOUT));

+ /*
+ * Wake up can be due to the following reasons:
+ * 1) The device reset completed from target.
+ * 2) Device reset timed out.
+ * 3) A link-down/host_reset may have happened in between.
+ * 4) The device reset was aborted and io_req->dr_done was called.
+ */
+
+ exit_dr = 0;
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if ((old_link_down_cnt != fnic->link_down_cnt) ||
+ (fnic->reset_in_progress) ||
+ (fnic->soft_reset_count != old_soft_reset_count) ||
+ (iport->state != FNIC_IPORT_STATE_READY))
+ exit_dr = 1;
+
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
if (!io_req) {
@@ -2398,6 +2745,13 @@ int fnic_device_reset(struct scsi_cmnd *sc)
"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->lport->host, fnic->fnic_num,
+ "Host reset called for fnic. Exit device reset\n");
+ io_req->dr_done = NULL;
+ goto fnic_device_reset_clean;
+ }
io_req->dr_done = NULL;

status = fnic_priv(sc)->lr_status;
@@ -2411,50 +2765,8 @@ int fnic_device_reset(struct scsi_cmnd *sc)
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Device reset timed out\n");
fnic_priv(sc)->flags |= FNIC_DEV_RST_TIMED_OUT;
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
int_to_scsilun(sc->device->lun, &fc_lun);
- /*
- * Issue abort and terminate on device reset request.
- * If q'ing of terminate fails, retry it after a delay.
- */
- while (1) {
- spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
- if (fnic_priv(sc)->flags & FNIC_DEV_RST_TERM_ISSUED) {
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- break;
- }
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- if (fnic_queue_abort_io_req(fnic,
- mqtag | FNIC_TAG_DEV_RST,
- FCPIO_ITMF_ABT_TASK_TERM,
- fc_lun.scsi_lun, io_req, hwq)) {
- wait_for_completion_timeout(&tm_done,
- msecs_to_jiffies(FNIC_ABT_TERM_DELAY_TIMEOUT));
- } else {
- spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
- fnic_priv(sc)->flags |= FNIC_DEV_RST_TERM_ISSUED;
- fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
- io_req->abts_done = &tm_done;
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "Abort and terminate issued on Device reset mqtag 0x%x sc 0x%p\n",
- mqtag, sc);
- break;
- }
- }
- while (1) {
- spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
- if (!(fnic_priv(sc)->flags & FNIC_DEV_RST_DONE)) {
- spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- wait_for_completion_timeout(&tm_done,
- msecs_to_jiffies(FNIC_LUN_RESET_TIMEOUT));
- break;
- } else {
- io_req = fnic_priv(sc)->io_req;
- io_req->abts_done = NULL;
- goto fnic_device_reset_clean;
- }
- }
+ goto fnic_device_reset_clean;
} else {
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
}
@@ -2480,8 +2792,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
io_req = fnic_priv(sc)->io_req;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "Device reset failed"
- " since could not abort all IOs\n");
+ "Device reset failed: Cannot abort all IOs\n");
goto fnic_device_reset_clean;
}

@@ -2507,6 +2818,15 @@ int fnic_device_reset(struct scsi_cmnd *sc)
mempool_free(io_req, fnic->io_req_pool);
}

+ /*
+ * If link-event is seen while LUN reset is issued we need
+ * to complete the LUN reset here
+ */
+ if (!new_sc) {
+ sc->result = DID_RESET << 16;
+ scsi_done(sc);
+ }
+
fnic_device_reset_end:
FNIC_TRACE(fnic_device_reset, sc->device->host->host_no, rq->tag, sc,
jiffies_to_msecs(jiffies - start_time),
@@ -2520,6 +2840,17 @@ int fnic_device_reset(struct scsi_cmnd *sc)
mutex_unlock(&fnic->sgreset_mutex);
}

+ while ((ret == SUCCESS) && fnic_count_lun_ioreqs(fnic, sc->device)) {
+ if (count >= 2) {
+ ret = FAILED;
+ break;
+ }
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Cannot clean up all IOs for the LUN\n");
+ schedule_timeout(msecs_to_jiffies(1000));
+ count++;
+ }
+
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
"Returning from device reset %s\n",
(ret == SUCCESS) ?
@@ -2531,50 +2862,54 @@ int fnic_device_reset(struct scsi_cmnd *sc)
return ret;
}

-/* Clean up all IOs, clean up libFC local port */
-int fnic_reset(struct Scsi_Host *shost)
+static void fnic_post_flogo_linkflap(struct fnic *fnic)
+{
+ unsigned long flags;
+
+ fnic_fdls_link_status_change(fnic, 0);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+
+ if (fnic->link_status) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ fnic_fdls_link_status_change(fnic, 1);
+ return;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+/* Logout from all the targets and simulate link flap */
+void fnic_reset(struct Scsi_Host *shost)
{
- struct fc_lport *lp;
struct fnic *fnic;
- int ret = 0;
struct reset_stats *reset_stats;

- lp = shost_priv(shost);
- fnic = lport_priv(lp);
+ fnic = *((struct fnic **) shost_priv(shost));
reset_stats = &fnic->fnic_stats.reset_stats;

FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "Issuing fnic reset\n");
+ "Issuing fnic reset\n");

atomic64_inc(&reset_stats->fnic_resets);
-
- /*
- * Reset local port, this will clean up libFC exchanges,
- * reset remote port sessions, and if link is up, begin flogi
- */
- ret = fc_lport_reset(lp);
+ fnic_post_flogo_linkflap(fnic);

FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "Returning from fnic reset with: %s\n",
- (ret == 0) ? "SUCCESS" : "FAILED");
+ "Returning from fnic reset");

- if (ret == 0)
- atomic64_inc(&reset_stats->fnic_reset_completions);
- else
- atomic64_inc(&reset_stats->fnic_reset_failures);
+ atomic64_inc(&reset_stats->fnic_reset_completions);
+}
+
+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->lport->host, fnic->fnic_num,
+ "FC host lip issued");

+ ret = fnic_host_reset(shost);
return ret;
}

-/*
- * SCSI Error handling calls driver's eh_host_reset if all prior
- * error handling levels return FAILED. If host reset completes
- * successfully, and if link is up, then Fabric login begins.
- *
- * Host Reset is the highest level of error recovery. If this fails, then
- * host is offlined by SCSI.
- *
- */
int fnic_host_reset(struct Scsi_Host *shost)
{
int ret;
@@ -2637,122 +2972,6 @@ int fnic_host_reset(struct Scsi_Host *shost)
return ret;
}

-/*
- * This fxn is called from libFC when host is removed
- */
-void fnic_scsi_abort_io(struct fc_lport *lp)
-{
- int err = 0;
- unsigned long flags;
- enum fnic_state old_state;
- struct fnic *fnic = lport_priv(lp);
- DECLARE_COMPLETION_ONSTACK(remove_wait);
-
- /* Issue firmware reset for fnic, wait for reset to complete */
-retry_fw_reset:
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) &&
- fnic->link_events) {
- /* fw reset is in progress, poll for its completion */
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- schedule_timeout(msecs_to_jiffies(100));
- goto retry_fw_reset;
- }
-
- fnic->remove_wait = &remove_wait;
- old_state = fnic->state;
- fnic->state = FNIC_IN_FC_TRANS_ETH_MODE;
- fnic_update_mac_locked(fnic, fnic->ctlr.ctl_src_addr);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
- err = fnic_fw_reset_handler(fnic);
- if (err) {
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)
- fnic->state = old_state;
- fnic->remove_wait = NULL;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
-
- /* Wait for firmware reset to complete */
- wait_for_completion_timeout(&remove_wait,
- msecs_to_jiffies(FNIC_RMDEVICE_TIMEOUT));
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- fnic->remove_wait = NULL;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fnic_scsi_abort_io %s\n",
- (fnic->state == FNIC_IN_ETH_MODE) ?
- "SUCCESS" : "FAILED");
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
-}
-
-/*
- * This fxn called from libFC to clean up driver IO state on link down
- */
-void fnic_scsi_cleanup(struct fc_lport *lp)
-{
- unsigned long flags;
- enum fnic_state old_state;
- struct fnic *fnic = lport_priv(lp);
-
- /* issue fw reset */
-retry_fw_reset:
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- 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);
- schedule_timeout(msecs_to_jiffies(100));
- goto retry_fw_reset;
- }
- old_state = fnic->state;
- fnic->state = FNIC_IN_FC_TRANS_ETH_MODE;
- fnic_update_mac_locked(fnic, fnic->ctlr.ctl_src_addr);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
- if (fnic_fw_reset_handler(fnic)) {
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)
- fnic->state = old_state;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- }
-
-}
-
-void fnic_empty_scsi_cleanup(struct fc_lport *lp)
-{
-}
-
-void fnic_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
-{
- struct fnic *fnic = lport_priv(lp);
-
- /* Non-zero sid, nothing to do */
- if (sid)
- goto call_fc_exch_mgr_reset;
-
- if (did) {
- fnic_rport_exch_reset(fnic, did);
- goto call_fc_exch_mgr_reset;
- }
-
- /*
- * sid = 0, did = 0
- * link down or device being removed
- */
- if (!fnic->in_remove)
- fnic_scsi_cleanup(lp);
- else
- fnic_scsi_abort_io(lp);
-
- /* call libFC exch mgr reset to reset its exchanges */
-call_fc_exch_mgr_reset:
- fc_exch_mgr_reset(lp, sid, did);
-
-}
-
static bool fnic_abts_pending_iter(struct scsi_cmnd *sc, void *data)
{
struct request *const rq = scsi_cmd_to_rq(sc);
diff --git a/drivers/scsi/fnic/fnic_stats.h b/drivers/scsi/fnic/fnic_stats.h
index 9d7f98c452dd..1f1a1ec90a23 100644
--- a/drivers/scsi/fnic/fnic_stats.h
+++ b/drivers/scsi/fnic/fnic_stats.h
@@ -127,6 +127,4 @@ struct stats_debug_info {
};

int fnic_get_stats_data(struct stats_debug_info *, struct fnic_stats *);
-void fnic_stats_debugfs_init(struct fnic *);
-void fnic_stats_debugfs_remove(struct fnic *);
#endif /* _FNIC_STATS_H_ */
--
2.31.1


Subject: [PATCH 11/14] scsi: fnic: Add stats and related functionality

Add statistics and related functionality for FDLS.
Add supporting functions to display stats.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fdls_disc.c | 28 ++++++++++++
drivers/scsi/fnic/fnic.h | 2 +
drivers/scsi/fnic/fnic_fdls.h | 6 ++-
drivers/scsi/fnic/fnic_main.c | 37 +++++++++++++++-
drivers/scsi/fnic/fnic_scsi.c | 15 +++++++
drivers/scsi/fnic/fnic_stats.h | 46 ++++++++++++++++++-
drivers/scsi/fnic/fnic_trace.c | 81 +++++++++++++++++++++++++++++-----
7 files changed, 198 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
index 952b5924e42b..eb997701371e 100644
--- a/drivers/scsi/fnic/fdls_disc.c
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -493,6 +493,7 @@ static void fdls_send_fabric_flogi(struct fnic_iport_s *iport)

fnic_send_fcoe_frame(iport, &flogi, sizeof(struct fc_els_s));
/* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
+ atomic64_inc(&iport->iport_stats.fabric_flogi_sent);
fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
}

@@ -516,6 +517,7 @@ static void fdls_send_fabric_plogi(struct fnic_iport_s *iport)
FNIC_SET_NODE_NAME(plogi, iport->wwnn);
FNIC_SET_RDF_SIZE(plogi.u.csp_plogi, iport->max_payload_size);

+ atomic64_inc(&iport->iport_stats.fabric_plogi_sent);
fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
/* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
@@ -587,6 +589,7 @@ static void fdls_send_scr(struct fnic_iport_s *iport)
hton24(fcid, iport->fcid);
FNIC_SET_S_ID((&scr_req.fchdr), fcid);

+ atomic64_inc(&iport->iport_stats.fabric_scr_sent);
fnic_send_fcoe_frame(iport, &scr_req, sizeof(struct fc_scr_s));
/* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
@@ -651,6 +654,7 @@ fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"sending ADISC to tgt fcid: 0x%x", tport->fcid);

+ atomic64_inc(&iport->iport_stats.tport_adisc_sent);
fnic_send_fcoe_frame(iport, &adisc, sizeof(struct fc_els_adisc_s));
/* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
fdls_start_tport_timer(iport, tport, 2 * iport->e_d_tov);
@@ -752,6 +756,7 @@ fdls_send_tgt_plogi(struct fnic_iport_s *iport, struct fnic_tport_s *tport)

timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);

+ atomic64_inc(&iport->iport_stats.tport_plogi_sent);
fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
/* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
fdls_start_tport_timer(iport, tport, timeout);
@@ -859,6 +864,7 @@ fdls_send_tgt_prli(struct fnic_iport_s *iport, struct fnic_tport_s *tport)

timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);

+ atomic64_inc(&iport->iport_stats.tport_prli_sent);
fnic_send_fcoe_frame(iport, &prli, sizeof(struct fc_els_prli_s));
/* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
fdls_start_tport_timer(iport, tport, timeout);
@@ -951,6 +957,7 @@ void fdls_tgt_logout(struct fnic_iport_s *iport,
memcpy(&logo.fcid, s_id, 3);
logo.wwpn = htonll(iport->wwpn);

+ atomic64_inc(&iport->iport_stats.tport_logo_sent);
fnic_send_fcoe_frame(iport, &logo, sizeof(struct fc_logo_req_s));
}

@@ -1618,6 +1625,7 @@ fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,

switch (adisc_rsp->command) {
case FC_LS_ACC:
+ atomic64_inc(&iport->iport_stats.tport_adisc_ls_accepts);
if (tport->timer_pending) {
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"tport 0x%p Canceling fabric disc timer\n",
@@ -1642,6 +1650,7 @@ fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
break;

case FC_LS_REJ:
+ atomic64_inc(&iport->iport_stats.tport_adisc_ls_rejects);
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (tport->retry_counter < FDLS_RETRY_COUNT)) {
@@ -1716,6 +1725,7 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,

switch (plogi_rsp->command) {
case FC_LS_ACC:
+ atomic64_inc(&iport->iport_stats.tport_plogi_ls_accepts);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"PLOGI accepted by target: 0x%x", tgt_fcid);
oxid = ntohs(FNIC_GET_OX_ID(fchdr));
@@ -1723,6 +1733,7 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
break;

case FC_LS_REJ:
+ atomic64_inc(&iport->iport_stats.tport_plogi_ls_rejects);
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (tport->retry_counter < iport->max_plogi_retries)) {
@@ -1742,6 +1753,7 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
return;

default:
+ atomic64_inc(&iport->iport_stats.tport_plogi_misc_rejects);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"PLOGI not accepted from target fcid: 0x%x",
tgt_fcid);
@@ -1845,6 +1857,7 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,

switch (prli_rsp->command) {
case FC_LS_ACC:
+ atomic64_inc(&iport->iport_stats.tport_prli_ls_accepts);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"PRLI accepted from target: 0x%x", tgt_fcid);
oxid = ntohs(FNIC_GET_OX_ID(fchdr));
@@ -1864,6 +1877,7 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
break;

case FC_LS_REJ:
+ atomic64_inc(&iport->iport_stats.tport_prli_ls_rejects);
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (tport->retry_counter < FDLS_RETRY_COUNT)) {
@@ -1889,6 +1903,7 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
break;

default:
+ atomic64_inc(&iport->iport_stats.tport_prli_misc_rejects);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"PRLI not accepted from target: 0x%x", tgt_fcid);
return;
@@ -2153,6 +2168,7 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)

switch (scr_rsp->command) {
case FC_LS_ACC:
+ atomic64_inc(&iport->iport_stats.fabric_scr_ls_accepts);
if (iport->fabric.timer_pending) {
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
@@ -2164,6 +2180,7 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
break;

case FC_LS_REJ:
+ atomic64_inc(&iport->iport_stats.fabric_scr_ls_rejects);
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (fdls->retry_counter < FDLS_RETRY_COUNT)) {
@@ -2187,6 +2204,7 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
break;

default:
+ atomic64_inc(&iport->iport_stats.fabric_scr_misc_rejects);
break;
}
}
@@ -2494,6 +2512,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,

switch (flogi_rsp->command) {
case FC_LS_ACC:
+ atomic64_inc(&iport->iport_stats.fabric_flogi_ls_accepts);
if (iport->fabric.timer_pending) {
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"iport fcid: 0x%x Canceling fabric disc timer\n",
@@ -2567,6 +2586,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
break;

case FC_LS_REJ:
+ atomic64_inc(&iport->iport_stats.fabric_flogi_ls_rejects);
els_rjt = (struct fc_els_reject_s *) fchdr;
if (fabric->retry_counter < iport->max_flogi_retries) {
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
@@ -2594,6 +2614,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"FLOGI response not accepted: 0x%x",
flogi_rsp->command);
+ atomic64_inc(&iport->iport_stats.fabric_flogi_misc_rejects);
break;
}
}
@@ -2615,6 +2636,7 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,

switch (plogi_rsp->command) {
case FC_LS_ACC:
+ atomic64_inc(&iport->iport_stats.fabric_plogi_ls_accepts);
if (iport->fabric.timer_pending) {
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"iport fcid: 0x%x fabric PLOGI response: Accepted\n",
@@ -2627,6 +2649,7 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
fdls_send_rpn_id(iport);
break;
case FC_LS_REJ:
+ atomic64_inc(&iport->iport_stats.fabric_plogi_ls_rejects);
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (iport->fabric.retry_counter < iport->max_plogi_retries)) {
@@ -2652,6 +2675,7 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"PLOGI response not accepted: 0x%x",
plogi_rsp->command);
+ atomic64_inc(&iport->iport_stats.fabric_plogi_misc_rejects);
break;
}
}
@@ -2932,6 +2956,7 @@ fdls_process_unsupported_els_req(struct fnic_iport_s *iport,
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Dropping unsupported ELS with illegal frame bits 0x%x\n",
d_id);
+ atomic64_inc(&iport->iport_stats.unsupported_frames_dropped);
return;
}

@@ -2940,6 +2965,7 @@ fdls_process_unsupported_els_req(struct fnic_iport_s *iport,
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Dropping unsupported ELS request in iport state: %d",
iport->state);
+ atomic64_inc(&iport->iport_stats.unsupported_frames_dropped);
return;
}

@@ -3333,6 +3359,8 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
struct fnic_fdls_fabric_s *fdls = &iport->fabric;
struct fnic *fnic = iport->fnic;

+ atomic64_inc(&iport->iport_stats.num_rscns);
+
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"FDLS process RSCN %p", iport);

diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 084c35b5e866..7480fb11a89b 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -531,5 +531,7 @@ unsigned int fnic_count_lun_ioreqs_wq(struct fnic *fnic, u32 hwq,
unsigned int fnic_count_lun_ioreqs(struct fnic *fnic,
struct scsi_device *device);
void fnic_scsi_unload(struct fnic *fnic);
+int fnic_get_debug_info(struct stats_debug_info *info,
+ struct fnic *fnic);

#endif /* _FNIC_H_ */
diff --git a/drivers/scsi/fnic/fnic_fdls.h b/drivers/scsi/fnic/fnic_fdls.h
index 88462363d754..242dd50dedb9 100644
--- a/drivers/scsi/fnic/fnic_fdls.h
+++ b/drivers/scsi/fnic/fnic_fdls.h
@@ -258,10 +258,12 @@ struct fnic_iport_s {
uint16_t max_payload_size;
spinlock_t deleted_tport_lst_lock;
struct completion *flogi_reg_done;
+ struct fnic_iport_stats iport_stats;
char str_wwpn[20];
char str_wwnn[20];
- };
- struct rport_dd_data_s {
+};
+
+struct rport_dd_data_s {
struct fnic_tport_s *tport;
struct fnic_iport_s *iport;
};
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index cc5691b65106..6cbea74bc20c 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -162,7 +162,7 @@ static struct fc_function_template fnic_fc_functions = {
.show_rport_dev_loss_tmo = 1,
.set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo,
.issue_fc_host_lip = fnic_issue_fc_host_lip,
- .get_fc_host_stats = NULL,
+ .get_fc_host_stats = fnic_get_stats,
.reset_fc_host_stats = fnic_reset_host_stats,
.dd_fcrport_size = sizeof(struct rport_dd_data_s),
.terminate_rport_io = fnic_terminate_rport_io,
@@ -173,9 +173,11 @@ static void fnic_get_host_speed(struct Scsi_Host *shost)
{
struct fnic *fnic = *((struct fnic **) shost_priv(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,
"port_speed: %d Mbps", port_speed);
+ atomic64_set(&fnic_stats->misc_stats.port_speed_in_mbps, port_speed);

/* Add in other values as they get defined in fw */
switch (port_speed) {
@@ -233,7 +235,38 @@ static void fnic_get_host_speed(struct Scsi_Host *shost)
/* Placeholder function */
static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *host)
{
- struct fc_host_statistics *stats;
+ int ret;
+ struct fnic *fnic = *((struct fnic **) shost_priv(host));
+ struct fc_host_statistics *stats = &fnic->fnic_stats.host_stats;
+ struct vnic_stats *vs;
+ unsigned long flags;
+
+ if (time_before
+ (jiffies, fnic->stats_time + HZ / FNIC_STATS_RATE_LIMIT))
+ return stats;
+ fnic->stats_time = jiffies;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ ret = vnic_dev_stats_dump(fnic->vdev, &fnic->stats);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ if (ret) {
+ FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ "fnic: Get vnic stats failed: 0x%x", ret);
+ return stats;
+ }
+ vs = fnic->stats;
+ stats->tx_frames = vs->tx.tx_unicast_frames_ok;
+ stats->tx_words = vs->tx.tx_unicast_bytes_ok / 4;
+ stats->rx_frames = vs->rx.rx_unicast_frames_ok;
+ stats->rx_words = vs->rx.rx_unicast_bytes_ok / 4;
+ stats->error_frames = vs->tx.tx_errors + vs->rx.rx_errors;
+ stats->dumped_frames = vs->tx.tx_drops + vs->rx.rx_drop;
+ stats->invalid_crc_count = vs->rx.rx_crc_errors;
+ stats->seconds_since_last_reset =
+ (jiffies - fnic->stats_reset_time) / HZ;
+ stats->fcp_input_megabytes = div_u64(fnic->fcp_input_bytes, 1000000);
+ stats->fcp_output_megabytes = div_u64(fnic->fcp_output_bytes, 1000000);
return stats;
}

diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 30e1b687d3ed..7603106a98a5 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -503,6 +503,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
if (ret) {
FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
"rport is not ready\n");
+ atomic64_inc(&fnic_stats->misc_stats.tport_not_ready);
sc->result = ret;
done(sc);
return 0;
@@ -1138,6 +1139,15 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, unsigned int cq_ind
jiffies_to_msecs(jiffies - start_time)),
desc, cmd_trace, fnic_flags_and_state(sc));

+ if (sc->sc_data_direction == DMA_FROM_DEVICE) {
+ fnic_stats->host_stats.fcp_input_requests++;
+ fnic->fcp_input_bytes += xfer_len;
+ } else if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ fnic_stats->host_stats.fcp_output_requests++;
+ fnic->fcp_output_bytes += xfer_len;
+ } else
+ fnic_stats->host_stats.fcp_control_requests++;
+
/* Call SCSI completion function to complete the IO */
scsi_done(sc);

@@ -2134,6 +2144,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
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->lport->host, fnic->fnic_num,
"iport NOT in READY state");
ret = FAILED;
@@ -2217,6 +2228,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
if (fc_remote_port_chkready(rport) == 0)
task_req = FCPIO_ITMF_ABT_TASK;
else {
+ atomic64_inc(&fnic_stats->misc_stats.tport_not_ready);
task_req = FCPIO_ITMF_ABT_TASK_TERM;
}

@@ -2654,6 +2666,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->lport->host, fnic->fnic_num,
"iport NOT in READY state");
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
@@ -2671,6 +2684,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)

/* Check if remote port up */
if (fc_remote_port_chkready(rport)) {
+ atomic64_inc(&fnic_stats->misc_stats.tport_not_ready);
goto fnic_device_reset_end;
}

@@ -3148,6 +3162,7 @@ void fnic_scsi_fcpio_reset(struct fnic *fnic)
"FW reset completion timed out after %d ms)\n",
FNIC_FW_RESET_TIMEOUT);
}
+ atomic64_inc(&fnic->fnic_stats.reset_stats.fw_reset_timeouts);
}
fnic->fw_reset_done = NULL;
}
diff --git a/drivers/scsi/fnic/fnic_stats.h b/drivers/scsi/fnic/fnic_stats.h
index 1f1a1ec90a23..ef7cdc909940 100644
--- a/drivers/scsi/fnic/fnic_stats.h
+++ b/drivers/scsi/fnic/fnic_stats.h
@@ -63,6 +63,7 @@ struct reset_stats {
atomic64_t fw_resets;
atomic64_t fw_reset_completions;
atomic64_t fw_reset_failures;
+ atomic64_t fw_reset_timeouts;
atomic64_t fnic_resets;
atomic64_t fnic_reset_completions;
atomic64_t fnic_reset_failures;
@@ -102,10 +103,51 @@ struct misc_stats {
atomic64_t no_icmnd_itmf_cmpls;
atomic64_t check_condition;
atomic64_t queue_fulls;
- atomic64_t rport_not_ready;
+ atomic64_t tport_not_ready;
+ atomic64_t iport_not_ready;
atomic64_t frame_errors;
atomic64_t current_port_speed;
atomic64_t intx_dummy;
+ atomic64_t port_speed_in_mbps;
+};
+
+struct fnic_iport_stats {
+ atomic64_t num_linkdn;
+ atomic64_t num_linkup;
+ atomic64_t link_failure_count;
+ atomic64_t num_rscns;
+ atomic64_t rscn_redisc;
+ atomic64_t rscn_not_redisc;
+ atomic64_t frame_err;
+ atomic64_t num_rnid;
+ atomic64_t fabric_flogi_sent;
+ atomic64_t fabric_flogi_ls_accepts;
+ atomic64_t fabric_flogi_ls_rejects;
+ atomic64_t fabric_flogi_misc_rejects;
+ atomic64_t fabric_plogi_sent;
+ atomic64_t fabric_plogi_ls_accepts;
+ atomic64_t fabric_plogi_ls_rejects;
+ atomic64_t fabric_plogi_misc_rejects;
+ atomic64_t fabric_scr_sent;
+ atomic64_t fabric_scr_ls_accepts;
+ atomic64_t fabric_scr_ls_rejects;
+ atomic64_t fabric_scr_misc_rejects;
+ atomic64_t fabric_logo_sent;
+ atomic64_t tport_alive;
+ atomic64_t tport_plogi_sent;
+ atomic64_t tport_plogi_ls_accepts;
+ atomic64_t tport_plogi_ls_rejects;
+ atomic64_t tport_plogi_misc_rejects;
+ atomic64_t tport_prli_sent;
+ atomic64_t tport_prli_ls_accepts;
+ atomic64_t tport_prli_ls_rejects;
+ atomic64_t tport_prli_misc_rejects;
+ atomic64_t tport_adisc_sent;
+ atomic64_t tport_adisc_ls_accepts;
+ atomic64_t tport_adisc_ls_rejects;
+ atomic64_t tport_logo_sent;
+ atomic64_t unsupported_frames_ls_rejects;
+ atomic64_t unsupported_frames_dropped;
};

struct fnic_stats {
@@ -116,6 +158,7 @@ struct fnic_stats {
struct reset_stats reset_stats;
struct fw_stats fw_stats;
struct vlan_stats vlan_stats;
+ struct fc_host_statistics host_stats;
struct misc_stats misc_stats;
};

@@ -127,4 +170,5 @@ struct stats_debug_info {
};

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_ */
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index d717886808df..6729b988c541 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -8,6 +8,7 @@
#include <linux/kallsyms.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
+#include <scsi/scsi_transport_fc.h>
#include "fnic_io.h"
#include "fnic.h"

@@ -29,6 +30,17 @@ int fnic_fc_tracing_enabled = 1;
int fnic_fc_trace_cleared = 1;
static DEFINE_SPINLOCK(fnic_fc_trace_lock);

+const char *fnic_role_str[] = {
+ [FNIC_ROLE_FCP_INITIATOR] = "FCP_Initiator",
+};
+
+const char *fnic_role_to_str(unsigned int role)
+{
+ if (role >= ARRAY_SIZE(fnic_role_str) || !fnic_role_str[role])
+ return "Unknown";
+
+ return fnic_role_str[role];
+}

/*
* fnic_trace_get_buf - Give buffer pointer to user to fill up trace information
@@ -423,7 +435,8 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
"Number of Check Conditions encountered: %lld\n"
"Number of QUEUE Fulls: %lld\n"
"Number of rport not ready: %lld\n"
- "Number of receive frame errors: %lld\n",
+ "Number of receive frame errors: %lld\n"
+ "Port speed (in Mbps): %lld\n",
(u64)stats->misc_stats.last_isr_time,
(s64)val1.tv_sec, val1.tv_nsec,
(u64)stats->misc_stats.last_ack_time,
@@ -446,13 +459,9 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
(u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls),
(u64)atomic64_read(&stats->misc_stats.check_condition),
(u64)atomic64_read(&stats->misc_stats.queue_fulls),
- (u64)atomic64_read(&stats->misc_stats.rport_not_ready),
- (u64)atomic64_read(&stats->misc_stats.frame_errors));
-
- len += scnprintf(debug->debug_buffer + len, buf_size - len,
- "Firmware reported port speed: %llu\n",
- (u64)atomic64_read(
- &stats->misc_stats.current_port_speed));
+ (u64)atomic64_read(&stats->misc_stats.tport_not_ready),
+ (u64)atomic64_read(&stats->misc_stats.frame_errors),
+ (u64)atomic64_read(&stats->misc_stats.port_speed_in_mbps));

return len;

@@ -460,8 +469,56 @@ int fnic_get_stats_data(struct stats_debug_info *debug,

int fnic_get_debug_info(struct stats_debug_info *info, struct fnic *fnic)
{
- /* Placeholder function */
- return 0;
+ struct fnic_iport_s *iport = &fnic->iport;
+ int buf_size = info->buf_size;
+ int len = info->buffer_len;
+ struct fnic_tport_s *tport, *next;
+ unsigned long flags;
+
+ len += snprintf(info->debug_buffer + len, buf_size - len,
+ "------------------------------------------\n"
+ "\t\t Debug Info\n"
+ "------------------------------------------\n");
+ len += snprintf(info->debug_buffer + len, buf_size - len,
+ "fnic Name:%s number:%d Role:%s State:%s\n",
+ fnic->name, fnic->fnic_num,
+ fnic_role_to_str(fnic->role),
+ fnic_state_to_str(fnic->state));
+ len +=
+ snprintf(info->debug_buffer + len, buf_size - len,
+ "iport State:%d Flags:0x%x vlan_id:%d fcid:0x%x\n",
+ iport->state, iport->flags, iport->vlan_id, iport->fcid);
+ len +=
+ snprintf(info->debug_buffer + len, buf_size - len,
+ "usefip:%d fip_state:%d fip_flogi_retry:%d\n",
+ iport->usefip, iport->fip.state, iport->fip.flogi_retry);
+ len +=
+ snprintf(info->debug_buffer + len, buf_size - len,
+ "fpma %02x:%02x:%02x:%02x:%02x:%02x",
+ iport->fpma[5], iport->fpma[4], iport->fpma[3],
+ iport->fpma[2], iport->fpma[1], iport->fpma[0]);
+ len +=
+ snprintf(info->debug_buffer + len, buf_size - len,
+ "fcfmac %02x:%02x:%02x:%02x:%02x:%02x\n",
+ iport->fcfmac[5], iport->fcfmac[4], iport->fcfmac[3],
+ iport->fcfmac[2], iport->fcfmac[1], iport->fcfmac[0]);
+ len +=
+ snprintf(info->debug_buffer + len, buf_size - len,
+ "fabric state:%d flags:0x%x retry_counter:%d e_d_tov:%d r_a_tov:%d\n",
+ iport->fabric.state, iport->fabric.flags,
+ iport->fabric.retry_counter, iport->e_d_tov,
+ iport->r_a_tov);
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
+ len += snprintf(info->debug_buffer + len, buf_size - len,
+ "tport fcid:0x%x state:%d flags:0x%x inflight:%d retry_counter:%d\n",
+ tport->fcid, tport->state, tport->flags,
+ atomic_read(&tport->in_flight),
+ tport->retry_counter);
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return len;
}

/*
@@ -694,7 +751,7 @@ int fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
*/
if (frame_type == FNIC_FC_RECV) {
eth_fcoe_hdr_len = sizeof(struct ethhdr) +
- sizeof(struct fcoe_hdr);
+ sizeof(struct fnic_fcoe_hdr_s);
memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len);
/* Copy the rest of data frame */
memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame,
@@ -800,7 +857,7 @@ void copy_and_format_trace_data(struct fc_trace_hdr *tdata,
{
int j, i = 1, len;
int ethhdr_len = sizeof(struct ethhdr) - 1;
- int fcoehdr_len = sizeof(struct fcoe_hdr);
+ int fcoehdr_len = sizeof(struct fnic_fcoe_hdr_s);
int fchdr_len = sizeof(struct fc_frame_header);
int max_size = fnic_fc_trace_max_pages * PAGE_SIZE * 3;
char *fc_trace;
--
2.31.1


Subject: [PATCH 10/14] scsi: fnic: Modify fnic interfaces to use FDLS

Modify fnic driver interfaces to use FDLS and
supporting functions.
Refactor code in fnic_probe and fnic_remove.
Get fnic from shost_priv.
Add error handling in stats processing functions.
Modify some print statements.
Add support to do module unload cleanup.
Use placeholder functions/modify function declarations
to not break compilation.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fnic.h | 11 +-
drivers/scsi/fnic/fnic_attrs.c | 12 +-
drivers/scsi/fnic/fnic_debugfs.c | 28 +-
drivers/scsi/fnic/fnic_fcs.c | 16 +
drivers/scsi/fnic/fnic_main.c | 490 +++++++++++++++++--------------
drivers/scsi/fnic/fnic_res.c | 29 +-
drivers/scsi/fnic/fnic_scsi.c | 34 +++
drivers/scsi/fnic/fnic_trace.c | 6 +
8 files changed, 375 insertions(+), 251 deletions(-)

diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 870b8fea452d..084c35b5e866 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -81,6 +81,7 @@
#define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)

#define FNIC_FW_RESET_TIMEOUT 60000 /* mSec */
+#define FNIC_FCOE_MAX_CMD_LEN 16
/* Retry supported by rport (returned by PRLI service parameters) */
#define FNIC_FC_RP_FLAGS_RETRY 0x1

@@ -340,6 +341,7 @@ struct fnic {
int fnic_num;
enum fnic_role_e role;
struct fnic_iport_s iport;
+ struct Scsi_Host *host;
struct fc_lport *lport;
struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
struct vnic_dev_bar bar0;
@@ -458,11 +460,6 @@ struct fnic {
int subsys_desc_len;
};

-static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip)
-{
- return container_of(fip, struct fnic, ctlr);
-}
-
extern struct workqueue_struct *fnic_event_queue;
extern struct workqueue_struct *fnic_fip_queue;
extern const struct attribute_group *fnic_host_groups[];
@@ -491,6 +488,7 @@ int fnic_eh_host_reset_handler(struct scsi_cmnd *sc);
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_scsi_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);
@@ -503,7 +501,7 @@ const char *fnic_state_to_str(unsigned int state);
void fnic_mq_map_queues_cpus(struct Scsi_Host *host);
void fnic_log_q_error(struct fnic *fnic);
void fnic_handle_link_event(struct fnic *fnic);
-void fnic_stats_debugfs_init(struct fnic *fnic);
+int fnic_stats_debugfs_init(struct fnic *fnic);
void fnic_stats_debugfs_remove(struct fnic *fnic);
int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);

@@ -532,5 +530,6 @@ unsigned int fnic_count_lun_ioreqs_wq(struct fnic *fnic, u32 hwq,
struct scsi_device *device);
unsigned int fnic_count_lun_ioreqs(struct fnic *fnic,
struct scsi_device *device);
+void fnic_scsi_unload(struct fnic *fnic);

#endif /* _FNIC_H_ */
diff --git a/drivers/scsi/fnic/fnic_attrs.c b/drivers/scsi/fnic/fnic_attrs.c
index 0c5e57c7e322..705718f0809b 100644
--- a/drivers/scsi/fnic/fnic_attrs.c
+++ b/drivers/scsi/fnic/fnic_attrs.c
@@ -11,8 +11,8 @@
static ssize_t fnic_show_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct fc_lport *lp = shost_priv(class_to_shost(dev));
- struct fnic *fnic = lport_priv(lp);
+ struct fnic *fnic =
+ *((struct fnic **) shost_priv(class_to_shost(dev)));

return sysfs_emit(buf, "%s\n", fnic_state_str[fnic->state]);
}
@@ -26,9 +26,13 @@ static ssize_t fnic_show_drv_version(struct device *dev,
static ssize_t fnic_show_link_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct fc_lport *lp = shost_priv(class_to_shost(dev));
+ struct fnic *fnic =
+ *((struct fnic **) shost_priv(class_to_shost(dev)));

- return sysfs_emit(buf, "%s\n", (lp->link_up) ? "Link Up" : "Link Down");
+ return sysfs_emit(buf, "%s\n",
+ ((fnic->iport.state != FNIC_IPORT_STATE_INIT) &&
+ (fnic->iport.state != FNIC_IPORT_STATE_LINK_WAIT)) ?
+ "Link Up" : "Link Down");
}

static DEVICE_ATTR(fnic_state, S_IRUGO, fnic_show_state, NULL);
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c
index 2619a2d4f5f1..3748bbe190f7 100644
--- a/drivers/scsi/fnic/fnic_debugfs.c
+++ b/drivers/scsi/fnic/fnic_debugfs.c
@@ -7,6 +7,9 @@
#include <linux/vmalloc.h>
#include "fnic.h"

+extern int fnic_get_debug_info(struct stats_debug_info *debug_buffer,
+ struct fnic *fnic);
+
static struct dentry *fnic_trace_debugfs_root;
static struct dentry *fnic_trace_debugfs_file;
static struct dentry *fnic_trace_enable;
@@ -593,6 +596,7 @@ static int fnic_stats_debugfs_open(struct inode *inode,
debug->buf_size = buf_size;
memset((void *)debug->debug_buffer, 0, buf_size);
debug->buffer_len = fnic_get_stats_data(debug, fnic_stats);
+ debug->buffer_len += fnic_get_debug_info(debug, fnic);

file->private_data = debug;

@@ -673,26 +677,48 @@ static const struct file_operations fnic_reset_debugfs_fops = {
* It will create file stats and reset_stats under statistics/host# directory
* to log per fnic stats.
*/
-void fnic_stats_debugfs_init(struct fnic *fnic)
+int fnic_stats_debugfs_init(struct fnic *fnic)
{
+ int rc = -1;
char name[16];

snprintf(name, sizeof(name), "host%d", fnic->lport->host->host_no);

+ if (!fnic_stats_debugfs_root) {
+ pr_debug("fnic_stats root doesn't exist\n");
+ return rc;
+ }
+
fnic->fnic_stats_debugfs_host = debugfs_create_dir(name,
fnic_stats_debugfs_root);

+ if (!fnic->fnic_stats_debugfs_host) {
+ pr_debug("Cannot create host directory\n");
+ return rc;
+ }
+
fnic->fnic_stats_debugfs_file = debugfs_create_file("stats",
S_IFREG|S_IRUGO|S_IWUSR,
fnic->fnic_stats_debugfs_host,
fnic,
&fnic_stats_debugfs_fops);

+ if (!fnic->fnic_stats_debugfs_file) {
+ pr_debug("Cannot create host stats file\n");
+ return rc;
+ }
+
fnic->fnic_reset_debugfs_file = debugfs_create_file("reset_stats",
S_IFREG|S_IRUGO|S_IWUSR,
fnic->fnic_stats_debugfs_host,
fnic,
&fnic_reset_debugfs_fops);
+ if (!fnic->fnic_reset_debugfs_file) {
+ pr_debug("Cannot create host stats file\n");
+ return rc;
+ }
+ rc = 0;
+ return rc;
}

/*
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 6f5414fba0ee..b516144247fa 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -80,6 +80,22 @@ static inline void fnic_fdls_set_fcoe_dstmac(struct fnic *fnic,
memcpy(fnic->iport.fcfmac, dst_mac, 6);
}

+void fnic_get_host_port_state(struct Scsi_Host *shost)
+{
+ struct fnic *fnic = *((struct fnic **) shost_priv(shost));
+ struct fnic_iport_s *iport = &fnic->iport;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (!fnic->link_status)
+ fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+ else if (iport->state == FNIC_IPORT_STATE_READY)
+ fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+ else
+ fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
void fnic_fdls_link_status_change(struct fnic *fnic, int linkup)
{
struct fnic_iport_s *iport = &fnic->iport;
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 5a352d95c654..cc5691b65106 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -66,6 +66,11 @@ unsigned int fnic_fdmi_support = 1;
module_param(fnic_fdmi_support, int, 0644);
MODULE_PARM_DESC(fnic_fdmi_support, "FDMI support");

+unsigned int fnic_tgt_id_binding = 1;
+module_param(fnic_tgt_id_binding, uint, 0644);
+MODULE_PARM_DESC(fnic_tgt_id_binding,
+ "Target ID binding (0 for none. 1 for binding by WWPN (default))");
+
unsigned int io_completions = FNIC_DFLT_IO_COMPLETIONS;
module_param(io_completions, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(io_completions, "Max CQ entries to process at a time");
@@ -84,9 +89,6 @@ 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");

-static struct libfc_function_template fnic_transport_template = {
-};
-
struct workqueue_struct *fnic_fip_queue;

static int fnic_slave_alloc(struct scsi_device *sdev)
@@ -148,7 +150,7 @@ static struct fc_function_template fnic_fc_functions = {
.get_host_speed = fnic_get_host_speed,
.show_host_speed = 1,
.show_host_port_type = 1,
- .get_host_port_state = fc_get_host_port_state,
+ .get_host_port_state = fnic_get_host_port_state,
.show_host_port_state = 1,
.show_host_symbolic_name = 1,
.show_rport_maxframe_size = 1,
@@ -160,79 +162,78 @@ static struct fc_function_template fnic_fc_functions = {
.show_rport_dev_loss_tmo = 1,
.set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo,
.issue_fc_host_lip = fnic_issue_fc_host_lip,
- .get_fc_host_stats = fnic_get_stats,
+ .get_fc_host_stats = NULL,
.reset_fc_host_stats = fnic_reset_host_stats,
- .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
+ .dd_fcrport_size = sizeof(struct rport_dd_data_s),
.terminate_rport_io = fnic_terminate_rport_io,
- .bsg_request = fc_lport_bsg_request,
+ .bsg_request = NULL,
};

static void fnic_get_host_speed(struct Scsi_Host *shost)
{
- struct fc_lport *lp = shost_priv(shost);
- struct fnic *fnic = lport_priv(lp);
+ struct fnic *fnic = *((struct fnic **) shost_priv(shost));
u32 port_speed = vnic_dev_port_speed(fnic->vdev);

+ FNIC_MAIN_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "port_speed: %d Mbps", port_speed);
+
/* Add in other values as they get defined in fw */
switch (port_speed) {
+ case DCEM_PORTSPEED_1G:
+ fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+ break;
+ case DCEM_PORTSPEED_2G:
+ fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
+ break;
+ case DCEM_PORTSPEED_4G:
+ fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
+ break;
+ case DCEM_PORTSPEED_8G:
+ fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
+ break;
case DCEM_PORTSPEED_10G:
fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
break;
+ case DCEM_PORTSPEED_16G:
+ fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
+ break;
case DCEM_PORTSPEED_20G:
fc_host_speed(shost) = FC_PORTSPEED_20GBIT;
break;
case DCEM_PORTSPEED_25G:
fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
break;
+ case DCEM_PORTSPEED_32G:
+ fc_host_speed(shost) = FC_PORTSPEED_32GBIT;
+ break;
case DCEM_PORTSPEED_40G:
case DCEM_PORTSPEED_4x10G:
fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
break;
+ case DCEM_PORTSPEED_50G:
+ fc_host_speed(shost) = FC_PORTSPEED_50GBIT;
+ break;
+ case DCEM_PORTSPEED_64G:
+ fc_host_speed(shost) = FC_PORTSPEED_64GBIT;
+ break;
case DCEM_PORTSPEED_100G:
fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
break;
+ case DCEM_PORTSPEED_128G:
+ fc_host_speed(shost) = FC_PORTSPEED_128GBIT;
+ break;
default:
+ FNIC_MAIN_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "Unknown FC speed: %d Mbps", port_speed);
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
}
}

+/* Placeholder function */
static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *host)
{
- int ret;
- struct fc_lport *lp = shost_priv(host);
- struct fnic *fnic = lport_priv(lp);
- struct fc_host_statistics *stats = &lp->host_stats;
- struct vnic_stats *vs;
- unsigned long flags;
-
- if (time_before(jiffies, fnic->stats_time + HZ / FNIC_STATS_RATE_LIMIT))
- return stats;
- fnic->stats_time = jiffies;
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- ret = vnic_dev_stats_dump(fnic->vdev, &fnic->stats);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
- if (ret) {
- FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "fnic: Get vnic stats failed"
- " 0x%x", ret);
- return stats;
- }
- vs = fnic->stats;
- stats->tx_frames = vs->tx.tx_unicast_frames_ok;
- stats->tx_words = vs->tx.tx_unicast_bytes_ok / 4;
- stats->rx_frames = vs->rx.rx_unicast_frames_ok;
- stats->rx_words = vs->rx.rx_unicast_bytes_ok / 4;
- stats->error_frames = vs->tx.tx_errors + vs->rx.rx_errors;
- stats->dumped_frames = vs->tx.tx_drops + vs->rx.rx_drop;
- stats->invalid_crc_count = vs->rx.rx_crc_errors;
- stats->seconds_since_last_reset =
- (jiffies - fnic->stats_reset_time) / HZ;
- stats->fcp_input_megabytes = div_u64(fnic->fcp_input_bytes, 1000000);
- stats->fcp_output_megabytes = div_u64(fnic->fcp_output_bytes, 1000000);
-
+ struct fc_host_statistics *stats;
return stats;
}

@@ -313,8 +314,7 @@ void fnic_dump_fchost_stats(struct Scsi_Host *host,
static void fnic_reset_host_stats(struct Scsi_Host *host)
{
int ret;
- struct fc_lport *lp = shost_priv(host);
- struct fnic *fnic = lport_priv(lp);
+ struct fnic *fnic = *((struct fnic **) shost_priv(host));
struct fc_host_statistics *stats;
unsigned long flags;

@@ -527,9 +527,23 @@ static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id)
vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
}

+static void fnic_scsi_init(struct fnic *fnic)
+{
+ struct Scsi_Host *host = fnic->host;
+
+ snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME,
+ host->host_no);
+
+ host->transportt = fnic_fc_transport;
+}
+
static int fnic_scsi_drv_init(struct fnic *fnic)
{
struct Scsi_Host *host = fnic->lport->host;
+ int err;
+ struct pci_dev *pdev = fnic->pdev;
+ struct fnic_iport_s *iport = &fnic->iport;
+ int hwq;

/* Configure maximum outstanding IO reqs*/
if (fnic->config.io_throttle_count != FNIC_UCSM_DFLT_THROTTLE_CNT_BLD)
@@ -540,7 +554,7 @@ static int fnic_scsi_drv_init(struct fnic *fnic)
fnic->fnic_max_tag_id = host->can_queue;
host->max_lun = fnic->config.luns_per_tgt;
host->max_id = FNIC_MAX_FCP_TARGET;
- host->max_cmd_len = FCOE_MAX_CMD_LEN;
+ host->max_cmd_len = FNIC_FCOE_MAX_CMD_LEN;

host->nr_hw_queues = fnic->wq_copy_count;

@@ -550,13 +564,62 @@ static int fnic_scsi_drv_init(struct fnic *fnic)
pr_info("fnic: max_id: %d max_cmd_len: %d nr_hw_queues: %d",
host->max_id, host->max_cmd_len, host->nr_hw_queues);

+ 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);
+ }
+
+ pr_info("fnic copy wqs: %d, Q0 ioreq table size: %d\n",
+ fnic->wq_copy_count, fnic->sw_copy_wq[0].ioreq_table_size);
+
+ fnic_scsi_init(fnic);
+
+ err = scsi_add_host(fnic->host, &pdev->dev);
+ if (err) {
+ pr_err("fnic: scsi add host failed: aborting\n");
+ return -1;
+ }
+ fc_host_maxframe_size(fnic->host) = iport->max_payload_size;
+ fc_host_dev_loss_tmo(fnic->host) =
+ fnic->config.port_down_timeout / 1000;
+ sprintf(fc_host_symbolic_name(fnic->host),
+ DRV_NAME " v" DRV_VERSION " over %s", fnic->name);
+ fc_host_port_type(fnic->host) = FC_PORTTYPE_NPORT;
+ fc_host_node_name(fnic->host) = iport->wwnn;
+ fc_host_port_name(fnic->host) = iport->wwpn;
+ fc_host_supported_classes(fnic->host) = FC_COS_CLASS3;
+ memset(fc_host_supported_fc4s(fnic->host), 0,
+ sizeof(fc_host_supported_fc4s(fnic->host)));
+ fc_host_supported_fc4s(fnic->host)[2] = 1;
+ fc_host_supported_fc4s(fnic->host)[7] = 1;
+ fc_host_supported_speeds(fnic->host) = 0;
+ fc_host_supported_speeds(fnic->host) |= FC_PORTSPEED_8GBIT;
+
+ pr_info("shost_data: 0x%p\n", fnic->host->shost_data);
+ if (fnic->host->shost_data != NULL) {
+ if (fnic_tgt_id_binding == 0) {
+ pr_info("Setting target binding to NONE\n");
+ fc_host_tgtid_bind_type(fnic->host) = FC_TGTID_BIND_NONE;
+ } else {
+ pr_info("Setting target binding to WWPN\n");
+ fc_host_tgtid_bind_type(fnic->host) = FC_TGTID_BIND_BY_WWPN;
+ }
+ }
+
+ fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
+ if (!fnic->io_req_pool) {
+ scsi_remove_host(fnic->host);
+ return -ENOMEM;
+ }
+
return 0;
}

void fnic_mq_map_queues_cpus(struct Scsi_Host *host)
{
- struct fc_lport *lp = shost_priv(host);
- struct fnic *fnic = lport_priv(lp);
+ struct fnic *fnic = *((struct fnic **) shost_priv(host));
struct pci_dev *l_pdev = fnic->pdev;
int intr_mode = fnic->config.intr_mode;
struct blk_mq_queue_map *qmap = &host->tag_set.map[HCTX_TYPE_DEFAULT];
@@ -581,31 +644,27 @@ void fnic_mq_map_queues_cpus(struct Scsi_Host *host)

static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- struct Scsi_Host *host;
- struct fc_lport *lp;
+ struct Scsi_Host *host = NULL;
struct fnic *fnic;
mempool_t *pool;
+ struct fnic_iport_s *iport;
int err = 0;
int fnic_id = 0;
int i;
unsigned long flags;
- int hwq;
char *desc, *subsys_desc;
int len;

/*
- * Allocate SCSI Host and set up association between host,
- * local port, and fnic
+ * Allocate fnic
*/
- lp = libfc_host_alloc(&fnic_host_template, sizeof(struct fnic));
- if (!lp) {
- pr_err("Unable to alloc libfc local port\n");
+ fnic = kzalloc(sizeof(struct fnic), GFP_KERNEL);
+ if (!fnic) {
err = -ENOMEM;
- goto err_out;
+ goto err_out_fnic_alloc;
}

- host = lp->host;
- fnic = lport_priv(lp);
+ iport = &fnic->iport;

fnic_id = ida_alloc(&fnic_ida, GFP_KERNEL);
if (fnic_id < 0) {
@@ -613,17 +672,9 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = fnic_id;
goto err_out_ida_alloc;
}
- fnic->lport = lp;
- fnic->ctlr.lp = lp;
- fnic->link_events = 0;
- fnic->pdev = pdev;
-
- snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME,
- host->host_no);

- host->transportt = fnic_fc_transport;
+ fnic->pdev = pdev;
fnic->fnic_num = fnic_id;
- fnic_stats_debugfs_init(fnic);

/* Find model name from PCIe subsys ID */
if (fnic_get_desc_by_devid(pdev, &desc, &subsys_desc) == 0) {
@@ -645,13 +696,13 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = pci_enable_device(pdev);
if (err) {
pr_err("Cannot enable PCI device, aborting.\n");
- goto err_out_free_hba;
+ goto err_out_pci_enable_device;
}

err = pci_request_regions(pdev, DRV_NAME);
if (err) {
pr_err("Cannot enable PCI resources, aborting\n");
- goto err_out_disable_device;
+ goto err_out_pci_request_regions;
}

pci_set_master(pdev);
@@ -666,7 +717,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err) {
pr_err("No usable DMA configuration "
"aborting\n");
- goto err_out_release_regions;
+ goto err_out_set_dma_mask;
}
}

@@ -674,7 +725,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
pr_err("BAR0 not memory-map'able, aborting.\n");
err = -ENODEV;
- goto err_out_release_regions;
+ goto err_out_map_bar;
}

fnic->bar0.vaddr = pci_iomap(pdev, 0, 0);
@@ -685,7 +736,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pr_err("Cannot memory-map BAR0 res hdr, "
"aborting.\n");
err = -ENODEV;
- goto err_out_release_regions;
+ goto err_out_fnic_map_bar;
}

fnic->vdev = vnic_dev_register(NULL, fnic, pdev, &fnic->bar0);
@@ -693,43 +744,66 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pr_err("vNIC registration failed, "
"aborting.\n");
err = -ENODEV;
- goto err_out_iounmap;
+ goto err_out_dev_register;
}

err = vnic_dev_cmd_init(fnic->vdev);
if (err) {
pr_err("vnic_dev_cmd_init() returns %d, aborting\n",
err);
- goto err_out_vnic_unregister;
+ goto err_out_dev_cmd_init;
}

err = fnic_dev_wait(fnic->vdev, vnic_dev_open,
vnic_dev_open_done, CMD_OPENF_RQ_ENABLE_THEN_POST);
if (err) {
pr_err("vNIC dev open failed, aborting.\n");
- goto err_out_dev_cmd_deinit;
+ goto err_out_dev_open;
}

err = vnic_dev_init(fnic->vdev, 0);
if (err) {
pr_err("vNIC dev init failed, aborting.\n");
- goto err_out_dev_close;
+ goto err_out_dev_init;
}

- err = vnic_dev_mac_addr(fnic->vdev, fnic->ctlr.ctl_src_addr);
+ err = vnic_dev_mac_addr(fnic->vdev, iport->hwmac);
if (err) {
pr_err("vNIC get MAC addr failed\n");
- goto err_out_dev_close;
+ goto err_out_dev_mac_addr;
}
/* set data_src for point-to-point mode and to keep it non-zero */
- memcpy(fnic->data_src_addr, fnic->ctlr.ctl_src_addr, ETH_ALEN);
+ memcpy(fnic->data_src_addr, iport->hwmac, ETH_ALEN);

/* Get vNIC configuration */
err = fnic_get_vnic_config(fnic);
if (err) {
pr_err("Get vNIC configuration failed, "
"aborting.\n");
- goto err_out_dev_close;
+ goto err_out_fnic_get_config;
+ }
+
+ switch (fnic->config.flags & 0xff0) {
+ case VFCF_FC_INITIATOR:
+ {
+ host =
+ scsi_host_alloc(&fnic_host_template,
+ sizeof(struct fnic *));
+ if (!host) {
+ pr_err("Unable to allocate scsi host\n");
+ err = -ENOMEM;
+ goto err_out_scsi_host_alloc;
+ }
+ *((struct fnic **) shost_priv(host)) = fnic;
+
+ fnic->host = host;
+ fnic->role = FNIC_ROLE_FCP_INITIATOR;
+ pr_info("fnic: %d is scsi initiator\n", fnic->fnic_num);
+ }
+ break;
+ default:
+ pr_info("fnic: %d has no role defined\n", fnic->fnic_num);
+ goto err_out_fnic_role;
}

/* Setup PCI resources */
@@ -741,26 +815,15 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err) {
pr_err("Failed to set intr mode, "
"aborting.\n");
- goto err_out_dev_close;
+ goto err_out_fnic_set_intr_mode;
}

err = fnic_alloc_vnic_resources(fnic);
if (err) {
pr_err("Failed to alloc vNIC resources, "
"aborting.\n");
- goto err_out_clear_intr;
- }
-
- fnic_scsi_drv_init(fnic);
-
- 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);
+ goto err_out_fnic_alloc_vnic_res;
}
- pr_info("fnic copy wqs: %d, Q0 ioreq table size: %d\n",
- fnic->wq_copy_count, fnic->sw_copy_wq[0].ioreq_table_size);

/* initialize all fnic locks */
spin_lock_init(&fnic->fnic_lock);
@@ -775,14 +838,9 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fnic->fw_ack_index[i] = -1;
}

- err = -ENOMEM;
- fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
- if (!fnic->io_req_pool)
- goto err_out_free_resources;
-
pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
if (!pool)
- goto err_out_free_ioreq_pool;
+ goto err_out_free_resources;
fnic->io_sgl_pool[FNIC_SGL_CACHE_DFLT] = pool;

pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
@@ -799,8 +857,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* enable directed and multicast */
vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0);
vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS);
- vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr);
- fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO);
+ vnic_dev_add_addr(fnic->vdev, iport->hwmac);
spin_lock_init(&fnic->vlans_lock);
INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
INIT_WORK(&fnic->flush_work, fnic_flush_tx);
@@ -813,8 +870,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fnic->set_vlan = fnic_set_vlan;
} else {
pr_info("firmware uses non-FIP mode\n");
- fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_NON_FIP);
- fnic->ctlr.state = FIP_ST_NON_FIP;
}
fnic->state = FNIC_IN_FC_MODE;

@@ -828,7 +883,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = fnic_notify_set(fnic);
if (err) {
pr_err("Failed to alloc notify buffer, aborting.\n");
- goto err_out_free_max_pool;
+ goto err_out_fnic_notify_set;
}

/* Setup notify timer when using MSI interrupts */
@@ -841,10 +896,52 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err) {
pr_err("fnic_alloc_rq_frame can't alloc "
"frame\n");
- goto err_out_rq_buf;
+ goto err_out_alloc_rq_buf;
}
}

+ init_completion(&fnic->reset_completion_wait);
+
+ /* Start local port initialization */
+ 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;
+
+ iport->boot_time = jiffies;
+ iport->e_d_tov = fnic->config.ed_tov;
+ iport->r_a_tov = fnic->config.ra_tov;
+ iport->link_supported_speeds = FNIC_PORTSPEED_10GBIT;
+ iport->wwpn = fnic->config.port_wwn;
+ iport->wwnn = fnic->config.node_wwn;
+
+ iport->max_payload_size = fnic->config.maxdatafieldsize;
+
+ if ((iport->max_payload_size < FNIC_MIN_DATA_FIELD_SIZE) ||
+ (iport->max_payload_size > FNIC_FC_MAX_PAYLOAD_LEN) ||
+ ((iport->max_payload_size % 4) != 0)) {
+ iport->max_payload_size = FNIC_FC_MAX_PAYLOAD_LEN;
+ }
+
+ iport->flags |= FNIC_FIRST_LINK_UP;
+
+ timer_setup(&(iport->fabric.retry_timer), fdls_fabric_timer_callback,
+ 0);
+
+ fnic->stats_reset_time = jiffies;
+
+ INIT_WORK(&fnic->link_work, fnic_handle_link);
+ INIT_WORK(&fnic->frame_work, fnic_handle_frame);
+ INIT_WORK(&fnic->tport_work, fnic_tport_event_handler);
+
+ INIT_LIST_HEAD(&fnic->frame_queue);
+ INIT_LIST_HEAD(&fnic->tx_queue);
+ INIT_LIST_HEAD(&fnic->tport_event_list);
+
/* Enable all queues */
for (i = 0; i < fnic->raw_wq_count; i++)
vnic_wq_enable(&fnic->wq[i]);
@@ -855,158 +952,105 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < fnic->wq_copy_count; i++)
vnic_wq_copy_enable(&fnic->hw_copy_wq[i]);

+ vnic_dev_enable(fnic->vdev);
+
err = fnic_request_intr(fnic);
if (err) {
pr_err("Unable to request irq.\n");
- goto err_out_request_intr;
- }
-
- /*
- * Initialization done with PCI system, hardware, firmware.
- * Add host to SCSI
- */
- err = scsi_add_host(lp->host, &pdev->dev);
- if (err) {
- pr_err("fnic: scsi_add_host failed...exiting\n");
- goto err_out_scsi_add_host;
+ goto err_out_fnic_request_intr;
}

+ fnic_notify_timer_start(fnic);

- /* Start local port initiatialization */
-
- lp->link_up = 0;
-
- lp->max_retry_count = fnic->config.flogi_retries;
- lp->max_rport_retry_count = fnic->config.plogi_retries;
- lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
- FCP_SPPF_CONF_COMPL);
- if (fnic->config.flags & VFCF_FCP_SEQ_LVL_ERR)
- lp->service_params |= FCP_SPPF_RETRY;
-
- lp->boot_time = jiffies;
- lp->e_d_tov = fnic->config.ed_tov;
- lp->r_a_tov = fnic->config.ra_tov;
- lp->link_supported_speeds = FC_PORTSPEED_10GBIT;
- fc_set_wwnn(lp, fnic->config.node_wwn);
- fc_set_wwpn(lp, fnic->config.port_wwn);
-
- fcoe_libfc_config(lp, &fnic->ctlr, &fnic_transport_template, 0);
-
- if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCPIO_HOST_EXCH_RANGE_START,
- FCPIO_HOST_EXCH_RANGE_END, NULL)) {
- err = -ENOMEM;
- goto err_out_fc_exch_mgr_alloc;
- }
-
- fc_lport_init_stats(lp);
- fnic->stats_reset_time = jiffies;
+ fnic_fdls_init(fnic, (fnic->config.flags & VFCF_FIP_CAPABLE));

- fc_lport_config(lp);
+ if (IS_FNIC_FCP_INITIATOR(fnic) && fnic_scsi_drv_init(fnic))
+ goto err_out_scsi_drv_init;

- if (fc_set_mfs(lp, fnic->config.maxdatafieldsize +
- sizeof(struct fc_frame_header))) {
- err = -EINVAL;
- goto err_out_free_exch_mgr;
+ err = fnic_stats_debugfs_init(fnic);
+ if (err) {
+ pr_err("Failed to initialize debugfs for stats\n");
+ goto err_out_free_stats_debugfs;
}
- fc_host_maxframe_size(lp->host) = lp->mfs;
- fc_host_dev_loss_tmo(lp->host) = fnic->config.port_down_timeout / 1000;

- sprintf(fc_host_symbolic_name(lp->host),
- DRV_NAME " v" DRV_VERSION " over %s", fnic->name);
+ for (i = 0; i < fnic->intr_count; i++)
+ vnic_intr_unmask(&fnic->intr[i]);

spin_lock_irqsave(&fnic_list_lock, flags);
list_add_tail(&fnic->list, &fnic_list);
spin_unlock_irqrestore(&fnic_list_lock, flags);

- INIT_WORK(&fnic->link_work, fnic_handle_link);
- INIT_WORK(&fnic->frame_work, fnic_handle_frame);
- INIT_WORK(&fnic->tport_work, fnic_tport_event_handler);
- INIT_LIST_HEAD(&fnic->frame_queue);
- INIT_LIST_HEAD(&fnic->tx_queue);
- INIT_LIST_HEAD(&fnic->tport_event_list);
-
- fc_fabric_login(lp);
-
- vnic_dev_enable(fnic->vdev);
-
- for (i = 0; i < fnic->intr_count; i++)
- vnic_intr_unmask(&fnic->intr[i]);
-
- fnic_notify_timer_start(fnic);
-
return 0;

-err_out_free_exch_mgr:
- fc_exch_mgr_free(lp);
-err_out_fc_exch_mgr_alloc:
- fc_remove_host(lp->host);
- scsi_remove_host(lp->host);
-err_out_scsi_add_host:
+err_out_free_stats_debugfs:
+ fnic_stats_debugfs_remove(fnic);
+ scsi_remove_host(fnic->host);
+err_out_scsi_drv_init:
fnic_free_intr(fnic);
-err_out_request_intr:
- for (i = 0; i < fnic->rq_count; i++)
+err_out_fnic_request_intr:
+err_out_alloc_rq_buf:
+ for (i = 0; i < fnic->rq_count; i++) {
+ if (ioread32(&fnic->rq[i].ctrl->enable))
+ vnic_rq_disable(&fnic->rq[i]);
vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf);
-err_out_rq_buf:
+ }
vnic_dev_notify_unset(fnic->vdev);
-err_out_free_max_pool:
+err_out_fnic_notify_set:
mempool_destroy(fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX]);
err_out_free_dflt_pool:
mempool_destroy(fnic->io_sgl_pool[FNIC_SGL_CACHE_DFLT]);
-err_out_free_ioreq_pool:
- mempool_destroy(fnic->io_req_pool);
err_out_free_resources:
- for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
- kfree(fnic->sw_copy_wq[hwq].io_req_table);
fnic_free_vnic_resources(fnic);
-err_out_clear_intr:
+err_out_fnic_alloc_vnic_res:
fnic_clear_intr_mode(fnic);
-err_out_dev_close:
+err_out_fnic_set_intr_mode:
+ 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:
+err_out_dev_mac_addr:
+err_out_dev_init:
vnic_dev_close(fnic->vdev);
-err_out_dev_cmd_deinit:
-err_out_vnic_unregister:
+err_out_dev_open:
+err_out_dev_cmd_init:
vnic_dev_unregister(fnic->vdev);
-err_out_iounmap:
+err_out_dev_register:
fnic_iounmap(fnic);
-err_out_release_regions:
+err_out_fnic_map_bar:
+err_out_map_bar:
+err_out_set_dma_mask:
pci_release_regions(pdev);
-err_out_disable_device:
+err_out_pci_request_regions:
pci_disable_device(pdev);
-err_out_free_hba:
- fnic_stats_debugfs_remove(fnic);
+err_out_pci_enable_device:
ida_free(&fnic_ida, fnic->fnic_num);
err_out_ida_alloc:
- scsi_host_put(lp->host);
-err_out:
+ kfree(fnic);
+err_out_fnic_alloc:
return err;
}

static void fnic_remove(struct pci_dev *pdev)
{
struct fnic *fnic = pci_get_drvdata(pdev);
- struct fc_lport *lp = fnic->lport;
unsigned long flags;
- int hwq;

- /*
- * Mark state so that the workqueue thread stops forwarding
- * received frames and link events to the local port. ISR and
- * other threads that can queue work items will also stop
- * creating work items on the fnic workqueue
- */
spin_lock_irqsave(&fnic->fnic_lock, flags);
fnic->stop_rx_link_events = 1;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);

- if (vnic_dev_get_intr_mode(fnic->vdev) == VNIC_DEV_INTR_MODE_MSI)
- del_timer_sync(&fnic->notify_timer);
-
/*
* Flush the fnic event queue. After this call, there should
* be no event queued for this fnic device in the workqueue
*/
flush_workqueue(fnic_event_queue);
- fnic_free_txq(&fnic->frame_queue);
- fnic_free_txq(&fnic->tx_queue);
+
+ if (IS_FNIC_FCP_INITIATOR(fnic))
+ fnic_scsi_unload(fnic);
+
+ if (vnic_dev_get_intr_mode(fnic->vdev) == VNIC_DEV_INTR_MODE_MSI)
+ del_timer_sync(&fnic->notify_timer);

if (fnic->config.flags & VFCF_FIP_CAPABLE) {
del_timer_sync(&fnic->retry_fip_timer);
@@ -1021,19 +1065,6 @@ static void fnic_remove(struct pci_dev *pdev)
if ((fnic_fdmi_support == 1) && (fnic->iport.fabric.fdmi_pending > 0))
del_timer_sync(&fnic->iport.fabric.fdmi_timer);

- /*
- * Log off the fabric. This stops all remote ports, dns port,
- * logs off the fabric. This flushes all rport, disc, lport work
- * before returning
- */
- fc_fabric_logoff(fnic->lport);
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- fnic->in_remove = 1;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
-
- fcoe_ctlr_destroy(&fnic->ctlr);
- fc_lport_destroy(lp);
fnic_stats_debugfs_remove(fnic);

/*
@@ -1047,11 +1078,9 @@ static void fnic_remove(struct pci_dev *pdev)
list_del(&fnic->list);
spin_unlock_irqrestore(&fnic_list_lock, flags);

- fc_remove_host(fnic->lport->host);
- scsi_remove_host(fnic->lport->host);
- for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
- kfree(fnic->sw_copy_wq[hwq].io_req_table);
- fc_exch_mgr_free(fnic->lport);
+ fnic_free_txq(&fnic->frame_queue);
+ fnic_free_txq(&fnic->tx_queue);
+
vnic_dev_notify_unset(fnic->vdev);
fnic_free_intr(fnic);
fnic_free_vnic_resources(fnic);
@@ -1061,8 +1090,11 @@ static void fnic_remove(struct pci_dev *pdev)
fnic_iounmap(fnic);
pci_release_regions(pdev);
pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
ida_free(&fnic_ida, fnic->fnic_num);
- scsi_host_put(lp->host);
+ if (IS_FNIC_FCP_INITIATOR(fnic))
+ scsi_host_put(fnic->host);
+ kfree(fnic);
}

static struct pci_driver fnic_driver = {
@@ -1190,8 +1222,10 @@ static void __exit fnic_cleanup_module(void)
{
pci_unregister_driver(&fnic_driver);
destroy_workqueue(fnic_event_queue);
- if (fnic_fip_queue)
+ if (fnic_fip_queue) {
+ flush_workqueue(fnic_fip_queue);
destroy_workqueue(fnic_fip_queue);
+ }
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
kmem_cache_destroy(fnic_io_req_cache);
diff --git a/drivers/scsi/fnic/fnic_res.c b/drivers/scsi/fnic/fnic_res.c
index 21cbe02b398c..0bf12ff5cc8c 100644
--- a/drivers/scsi/fnic/fnic_res.c
+++ b/drivers/scsi/fnic/fnic_res.c
@@ -58,6 +58,11 @@ int fnic_get_vnic_config(struct fnic *fnic)
GET_CONFIG(intr_mode);
GET_CONFIG(wq_copy_count);

+ if ((c->flags & (VFCF_FC_INITIATOR)) == 0) {
+ pr_info("vNIC role not defined (default role: FC Initiator)\n");
+ c->flags |= VFCF_FC_INITIATOR;
+ }
+
c->wq_enet_desc_count =
min_t(u32, VNIC_FNIC_WQ_DESCS_MAX,
max_t(u32, VNIC_FNIC_WQ_DESCS_MIN,
@@ -137,29 +142,29 @@ int fnic_get_vnic_config(struct fnic *fnic)

c->wq_copy_count = min_t(u16, FNIC_WQ_COPY_MAX, c->wq_copy_count);

- pr_info("vNIC MAC addr %pM "
+ pr_info("fNIC MAC addr %p "
"wq/wq_copy/rq %d/%d/%d\n",
- fnic->ctlr.ctl_src_addr,
+ fnic->data_src_addr,
c->wq_enet_desc_count, c->wq_copy_desc_count,
c->rq_desc_count);
- pr_info("vNIC node wwn %llx port wwn %llx\n",
+ pr_info("fNIC node wwn 0x%llx port wwn 0x%llx\n",
c->node_wwn, c->port_wwn);
- pr_info("vNIC ed_tov %d ra_tov %d\n",
+ pr_info("fNIC ed_tov %d ra_tov %d\n",
c->ed_tov, c->ra_tov);
- pr_info("vNIC mtu %d intr timer %d\n",
+ pr_info("fNIC mtu %d intr timer %d\n",
c->maxdatafieldsize, c->intr_timer);
- pr_info("vNIC flags 0x%x luns per tgt %d\n",
+ pr_info("fNIC flags 0x%x luns per tgt %d\n",
c->flags, c->luns_per_tgt);
- pr_info("vNIC flogi_retries %d flogi timeout %d\n",
+ pr_info("fNIC flogi_retries %d flogi timeout %d\n",
c->flogi_retries, c->flogi_timeout);
- pr_info("vNIC plogi retries %d plogi timeout %d\n",
+ pr_info("fNIC plogi retries %d plogi timeout %d\n",
c->plogi_retries, c->plogi_timeout);
- pr_info("vNIC io throttle count %d link dn timeout %d\n",
+ pr_info("fNIC io throttle count %d link dn timeout %d\n",
c->io_throttle_count, c->link_down_timeout);
- pr_info("vNIC port dn io retries %d port dn timeout %d\n",
+ pr_info("fNIC port dn io retries %d port dn timeout %d\n",
c->port_down_io_retries, c->port_down_timeout);
- pr_info("vNIC wq_copy_count: %d\n", c->wq_copy_count);
- pr_info("vNIC intr mode: %d\n", c->intr_mode);
+ pr_info("fNIC wq_copy_count: %d\n", c->wq_copy_count);
+ pr_info("fNIC intr mode: %d\n", c->intr_mode);

return 0;
}
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index e5bbe4319316..30e1b687d3ed 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -2026,6 +2026,40 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
}
}

+/*
+ * FCP-SCSI specific handling for module unload
+ *
+ */
+void fnic_scsi_unload(struct fnic *fnic)
+{
+ int hwq = 0;
+ unsigned long flags;
+
+ /*
+ * Mark state so that the workqueue thread stops forwarding
+ * received frames and link events to the local port. ISR and
+ * other threads that can queue work items will also stop
+ * creating work items on the fnic workqueue
+ */
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ fnic->iport.state = FNIC_IPORT_STATE_LINK_WAIT;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ if (fdls_get_state(&fnic->iport.fabric) != FDLS_STATE_INIT)
+ fnic_scsi_fcpio_reset(fnic);
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ fnic->in_remove = 1;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ fnic_flush_tport_event_list(fnic);
+ fnic_delete_fcp_tports(fnic);
+ fc_remove_host(fnic->host);
+ scsi_remove_host(fnic->host);
+ for (hwq = 0; hwq < fnic->wq_copy_count; hwq++)
+ kfree(fnic->sw_copy_wq[hwq].io_req_table);
+}
+
/*
* This function is exported to SCSI for sending abort cmnds.
* A SCSI IO is represented by a io_req in the driver.
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index aaa4ea02fb7c..d717886808df 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -458,6 +458,12 @@ int fnic_get_stats_data(struct stats_debug_info *debug,

}

+int fnic_get_debug_info(struct stats_debug_info *info, struct fnic *fnic)
+{
+ /* Placeholder function */
+ return 0;
+}
+
/*
* fnic_trace_buf_init - Initialize fnic trace buffer logging facility
*
--
2.31.1


Subject: [PATCH 05/14] scsi: fnic: Add support for unsolicited requests and responses

Add support for unsolicited requests and responses.
Add support to accept and reject frames.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fdls_disc.c | 566 +++++++++++++++++++++++++++++++++-
1 file changed, 563 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
index d920202d413d..ad115de86f15 100644
--- a/drivers/scsi/fnic/fdls_disc.c
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -125,6 +125,21 @@ struct fc_scr_s fnic_scr_req = {
.reg_func = 0x03
};

+/*
+ * Variables:
+ * did, ox_id, rx_id
+ */
+struct fc_els_acc_s fnic_els_acc = {
+ .fchdr = {.r_ctl = 0x23, .did = {0xFF, 0xFF, 0xFD}, .type = 0x01,
+ .f_ctl = FNIC_ELS_REP_FCTL},
+ .command = FC_LS_ACC,
+};
+
+struct fc_els_reject_s fnic_els_rjt = {
+ .fchdr = {.r_ctl = 0x23, .type = 0x01, .f_ctl = FNIC_ELS_REP_FCTL},
+ .command = FC_LS_REJ,
+};
+
/*
* Variables:
* did, ox_id, rx_id, fcid, wwpn
@@ -135,6 +150,13 @@ struct fc_logo_req_s fnic_logo_req = {
.command = FC_ELS_LOGO,
};

+static struct fc_abts_ba_acc_s fnic_ba_acc = {
+ .fchdr = {.r_ctl = 0x84,
+ .f_ctl = FNIC_FCP_RSP_FCTL},
+ .low_seq_cnt = 0,
+ .high_seq_cnt = 0xFFFF,
+};
+
#define RETRIES_EXHAUSTED(iport) \
(iport->fabric.retry_counter == FABRIC_LOGO_MAX_RETRY)

@@ -150,7 +172,6 @@ static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
static void fdls_target_restart_nexus(struct fnic_tport_s *tport);
static void fdls_start_tport_timer(struct fnic_iport_s *iport,
struct fnic_tport_s *tport, int timeout);
-
static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
int timeout);
static void fdls_tport_timer_callback(struct timer_list *t);
@@ -231,6 +252,48 @@ fdls_start_tport_timer(struct fnic_iport_s *iport,
tport->timer_pending = 1;
}

+static void
+fdls_send_rscn_resp(struct fnic_iport_s *iport,
+ struct fc_hdr_s *rscn_fchdr)
+{
+ struct fc_els_acc_s els_acc;
+ uint16_t oxid;
+ uint8_t fcid[3];
+
+ memcpy(&els_acc, &fnic_els_acc, sizeof(struct fc_els_acc_s));
+
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID((&els_acc.fchdr), fcid);
+ FNIC_SET_D_ID((&els_acc.fchdr), rscn_fchdr->sid);
+
+ oxid = FNIC_GET_OX_ID(rscn_fchdr);
+ FNIC_SET_OX_ID((&els_acc.fchdr), oxid);
+
+ FNIC_SET_RX_ID((&els_acc.fchdr), FNIC_RSCN_RESP_OXID);
+
+ fnic_send_fcoe_frame(iport, &els_acc, sizeof(struct fc_els_acc_s));
+}
+
+static void
+fdls_send_logo_resp(struct fnic_iport_s *iport, struct fc_hdr_s *req_fchdr)
+{
+ struct fc_els_acc_s logo_resp;
+ uint16_t oxid;
+ uint8_t fcid[3];
+
+ memcpy(&logo_resp, &fnic_els_acc, sizeof(struct fc_els_acc_s));
+
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID((&logo_resp.fchdr), fcid);
+ FNIC_SET_D_ID((&logo_resp.fchdr), req_fchdr->sid);
+
+ oxid = FNIC_GET_OX_ID(req_fchdr);
+ FNIC_SET_OX_ID((&logo_resp.fchdr), oxid);
+
+ FNIC_SET_RX_ID((&logo_resp.fchdr), FNIC_LOGO_RESP_OXID);
+ fnic_send_fcoe_frame(iport, &logo_resp, sizeof(struct fc_els_acc_s));
+}
+
void
fdls_send_tport_abts(struct fnic_iport_s *iport,
struct fnic_tport_s *tport)
@@ -2541,6 +2604,188 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
}
}

+static void
+fdls_process_abts_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fc_abts_ba_acc_s ba_acc;
+ uint32_t nport_id;
+ uint16_t oxid;
+ struct fnic_tport_s *tport;
+ struct fnic *fnic = iport->fnic;
+
+ nport_id = ntoh24(fchdr->sid);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received abort from SID %8x", nport_id);
+
+ tport = fnic_find_tport_by_fcid(iport, nport_id);
+ if (tport) {
+ oxid = FNIC_GET_OX_ID(fchdr);
+ if (tport->oxid_used == oxid) {
+ tport->flags |= FNIC_FDLS_TGT_ABORT_ISSUED;
+ fdls_free_tgt_oxid(iport, ntohs(oxid));
+ }
+ }
+
+ memcpy(&ba_acc, &fnic_ba_acc, sizeof(struct fc_abts_ba_acc_s));
+ FNIC_SET_S_ID((&ba_acc.fchdr), fchdr->did);
+ FNIC_SET_D_ID((&ba_acc.fchdr), fchdr->sid);
+
+ ba_acc.fchdr.rx_id = fchdr->rx_id;
+ ba_acc.rx_id = ba_acc.fchdr.rx_id;
+ ba_acc.fchdr.ox_id = fchdr->ox_id;
+ ba_acc.ox_id = ba_acc.fchdr.ox_id;
+
+ fnic_send_fcoe_frame(iport, &ba_acc, sizeof(struct fc_abts_ba_acc_s));
+}
+
+static void
+fdls_process_unsupported_els_req(struct fnic_iport_s *iport,
+ struct fc_hdr_s *fchdr)
+{
+ struct fc_els_reject_s ls_rsp;
+ uint16_t oxid;
+ uint32_t d_id = ntoh24(fchdr->did);
+ struct fnic *fnic = iport->fnic;
+
+ memcpy(&ls_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));
+
+ if (iport->fcid != d_id) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping unsupported ELS with illegal frame bits 0x%x\n",
+ d_id);
+ return;
+ }
+
+ if ((iport->state != FNIC_IPORT_STATE_READY)
+ && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping unsupported ELS request in iport state: %d",
+ iport->state);
+ return;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Process unsupported ELS request from SID: 0x%x",
+ ntoh24(fchdr->sid));
+ /* We don't support this ELS request, send a reject */
+ ls_rsp.reason_code = 0x0B;
+ ls_rsp.reason_expl = 0x0;
+ ls_rsp.vendor_specific = 0x0;
+
+ FNIC_SET_S_ID((&ls_rsp.fchdr), fchdr->did);
+ FNIC_SET_D_ID((&ls_rsp.fchdr), fchdr->sid);
+ oxid = FNIC_GET_OX_ID(fchdr);
+ FNIC_SET_OX_ID((&ls_rsp.fchdr), oxid);
+
+ FNIC_SET_RX_ID((&ls_rsp.fchdr), FNIC_UNSUPPORTED_RESP_OXID);
+ fnic_send_fcoe_frame(iport, &ls_rsp, sizeof(struct fc_els_reject_s));
+}
+
+static void
+fdls_process_rls_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fc_els_rls_ls_acc_s rls_acc_rsp;
+ uint16_t oxid;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Process RLS request %d", iport->fnic->fnic_num);
+
+ if ((iport->state != FNIC_IPORT_STATE_READY)
+ && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received RLS req in iport state: %d. Dropping the frame.",
+ iport->state);
+ return;
+ }
+
+ memset(&rls_acc_rsp, 0, sizeof(struct fc_els_rls_ls_acc_s));
+
+ FNIC_SET_S_ID((&rls_acc_rsp.fchdr), fchdr->did);
+ FNIC_SET_D_ID((&rls_acc_rsp.fchdr), fchdr->sid);
+ oxid = FNIC_GET_OX_ID(fchdr);
+ FNIC_SET_OX_ID((&rls_acc_rsp.fchdr), oxid);
+ FNIC_SET_RX_ID((&rls_acc_rsp.fchdr), 0xffff);
+ rls_acc_rsp.fchdr.f_ctl = FNIC_ELS_REP_FCTL;
+ rls_acc_rsp.fchdr.r_ctl = 0x23;
+ rls_acc_rsp.fchdr.type = 0x01;
+ rls_acc_rsp.command = FC_LS_ACC;
+ rls_acc_rsp.link_fail_count = htonl(iport->fnic->link_down_cnt);
+
+ fnic_send_fcoe_frame(iport, &rls_acc_rsp,
+ sizeof(struct fc_els_rls_ls_acc_s));
+}
+
+static void
+fdls_process_els_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
+ uint32_t len)
+{
+ struct fc_els_acc_s *els_acc;
+ uint16_t oxid;
+ uint8_t fcid[3];
+ uint8_t *fc_payload;
+ uint8_t *dst_frame;
+ uint8_t type;
+ struct fnic *fnic = iport->fnic;
+
+ fc_payload = (uint8_t *) fchdr + sizeof(struct fc_hdr_s);
+ type = *fc_payload;
+
+ if ((iport->state != FNIC_IPORT_STATE_READY)
+ && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Dropping ELS frame type :%x in iport state: %d",
+ type, iport->state);
+ return;
+ }
+ switch (type) {
+ case FC_ELS_ECHO_REQ:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "sending LS_ACC for ECHO request %d\n",
+ iport->fnic->fnic_num);
+ break;
+
+ case FC_ELS_RRQ_REQ:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "sending LS_ACC for RRQ request %d\n",
+ iport->fnic->fnic_num);
+ break;
+
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "sending LS_ACC for %x ELS frame\n", type);
+ break;
+ }
+ dst_frame = kzalloc(len, GFP_ATOMIC);
+ if (!dst_frame) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to allocate ELS response for %x", type);
+ return;
+ }
+ if (type == FC_ELS_ECHO_REQ) {
+ /* Brocade sends a longer payload, copy all frame back */
+ memcpy(dst_frame, fchdr, len);
+ }
+
+ els_acc = (struct fc_els_acc_s *) dst_frame;
+ memcpy(els_acc, &fnic_els_acc, sizeof(struct fc_els_acc_s));
+
+ hton24(fcid, iport->fcid);
+ FNIC_SET_S_ID((&els_acc->fchdr), fcid);
+ FNIC_SET_D_ID((&els_acc->fchdr), fchdr->sid);
+
+ oxid = FNIC_GET_OX_ID(fchdr);
+ FNIC_SET_OX_ID((&els_acc->fchdr), oxid);
+ FNIC_SET_RX_ID((&els_acc->fchdr), 0xffff);
+
+ if (type == FC_ELS_ECHO_REQ)
+ fnic_send_fcoe_frame(iport, els_acc, len);
+ else
+ fnic_send_fcoe_frame(iport, els_acc, sizeof(struct fc_els_acc_s));
+
+ kfree(dst_frame);
+}
+
static void
fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
struct fc_hdr_s *fchdr)
@@ -2584,8 +2829,8 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
if ((oxid >= FDLS_ADISC_OXID_BASE) && (oxid < FDLS_TGT_OXID_POOL_END)) {
if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
- "Received tgt ADISC abts response BA_ACC for OX_ID: 0x%x tgt_fcid: 0x%x",
- ba_acc->ox_id, tport->fcid);
+ "OX_ID: 0x%x tgt_fcid: 0x%x rcvd tgt adisc abts resp BA_ACC",
+ ba_acc->ox_id, tport->fcid);
} else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
"ADISC BA_RJT rcvd tport_fcid: 0x%x tport_state: %d ",
@@ -2676,6 +2921,296 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
"Received ABTS response for unknown frame %p", iport);
}

+static void
+fdls_process_plogi_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fc_els_reject_s plogi_rsp;
+ uint16_t oxid;
+ uint32_t d_id = ntoh24(fchdr->did);
+ struct fnic *fnic = iport->fnic;
+
+ memcpy(&plogi_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));
+
+ if (iport->fcid != d_id) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received PLOGI with illegal frame bits. Dropping frame %p",
+ iport);
+ return;
+ }
+
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Received PLOGI request in iport state: %d Dropping frame",
+ iport->state);
+ return;
+ }
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Process PLOGI request from SID: 0x%x",
+ ntoh24(fchdr->sid));
+
+ /* We don't support PLOGI request, send a reject */
+ plogi_rsp.reason_code = 0x0B;
+ plogi_rsp.reason_expl = 0x0;
+ plogi_rsp.vendor_specific = 0x0;
+
+ FNIC_SET_S_ID((&plogi_rsp.fchdr), fchdr->did);
+ FNIC_SET_D_ID((&plogi_rsp.fchdr), fchdr->sid);
+
+ oxid = FNIC_GET_OX_ID(fchdr);
+ FNIC_SET_OX_ID((&plogi_rsp.fchdr), oxid);
+
+ FNIC_SET_RX_ID((&plogi_rsp.fchdr), FNIC_PLOGI_RESP_OXID);
+ fnic_send_fcoe_frame(iport, &plogi_rsp,
+ sizeof(struct fc_els_reject_s));
+}
+
+static void
+fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fc_logo_req_s *logo = (struct fc_logo_req_s *) fchdr;
+ uint32_t nport_id;
+ uint64_t nport_name;
+ struct fnic_tport_s *tport;
+ struct fnic *fnic = iport->fnic;
+ uint16_t oxid;
+
+ nport_id = ntoh24(logo->fcid);
+ nport_name = logo->wwpn;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Process LOGO request from fcid: 0x%x", nport_id);
+
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Dropping LOGO req from 0x%x in iport state: %d",
+ nport_id, iport->state);
+ return;
+ }
+
+ tport = fnic_find_tport_by_fcid(iport, nport_id);
+
+ if (!tport) {
+ /* We are not logged in with the nport, log and drop... */
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Received LOGO from an nport not logged in: 0x%x",
+ nport_id);
+ return;
+ }
+ if (tport->fcid != nport_id) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Received LOGO with invalid target port fcid: 0x%x",
+ nport_id);
+ return;
+ }
+ if (tport->timer_pending) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "tport fcid 0x%x: Canceling disc timer\n",
+ tport->fcid);
+ fnic_del_tport_timer_sync();
+ tport->timer_pending = 0;
+ }
+
+ /* got a logo in response to adisc to a target which has logged out */
+ if (tport->state == FDLS_TGT_STATE_ADISC) {
+ tport->retry_counter = 0;
+ oxid = ntohs(tport->oxid_used);
+ fdls_free_tgt_oxid(iport, oxid);
+ fdls_delete_tport(iport, tport);
+ fdls_send_logo_resp(iport, &logo->fchdr);
+ if ((iport->state == FNIC_IPORT_STATE_READY)
+ && (fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT)
+ && (fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Sending GPNFT in response to LOGO from Target:0x%x",
+ nport_id);
+ fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
+ return;
+ }
+ } else {
+ fdls_delete_tport(iport, tport);
+ }
+ if (iport->state == FNIC_IPORT_STATE_READY) {
+ fdls_send_logo_resp(iport, &logo->fchdr);
+ if ((fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT) &&
+ (fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Sending GPNFT in response to LOGO from Target:0x%x",
+ nport_id);
+ fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
+ }
+ }
+}
+
+static void
+fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fc_rscn_hdr_s *rscn;
+ struct fc_rscn_port_s *rscn_port = NULL;
+ int num_ports;
+ struct fnic_tport_s *tport, *next;
+ uint32_t nport_id;
+ uint8_t fcid[3];
+ int newports = 0;
+ struct fnic_fdls_fabric_s *fdls = &iport->fabric;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS process RSCN %p", iport);
+
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS RSCN received in state(%d). Dropping",
+ fdls_get_state(fdls));
+ return;
+ }
+
+ rscn = (struct fc_rscn_hdr_s *) fchdr;
+ /* frame validation */
+ if ((rscn->payload_len % 4 != 0) || (rscn->payload_len < 8)
+ || (rscn->payload_len > 1024) || (rscn->page_len != 4)) {
+ num_ports = 0;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RSCN payload_len: 0x%x page_len: 0x%x",
+ rscn->payload_len, rscn->page_len);
+ /* if this happens then we need to send ADISC to all the tports. */
+ list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
+ if (tport->state == FDLS_TGT_STATE_READY)
+ tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RSCN for port id: 0x%x", tport->fcid);
+ }
+ } else {
+ num_ports = (rscn->payload_len - 4) / rscn->page_len;
+ rscn_port = (struct fc_rscn_port_s *) (rscn + 1);
+ }
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RSCN received for num_ports: %d payload_len: %d page_len: %d ",
+ num_ports, rscn->payload_len, rscn->page_len);
+
+ /*
+ * RSCN have at least one Port_ID page , but may not have any port_id
+ * in it. If no port_id is specified in the Port_ID page , we send
+ * ADISC to all the tports
+ */
+
+ while (num_ports) {
+
+ memcpy(fcid, rscn_port->port_id, 3);
+
+ nport_id = ntoh24(fcid);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RSCN event: 0x%x for 0x%x", rscn_port->rscn_evt_q,
+ nport_id);
+ rscn_port++;
+ num_ports--;
+ /* if this happens then we need to send ADISC to all the tports. */
+ if (nport_id == 0) {
+ list_for_each_entry_safe(tport, next, &iport->tport_list,
+ links) {
+ if (tport->state == FDLS_TGT_STATE_READY)
+ tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RSCN for port id: 0x%x", tport->fcid);
+ }
+ break;
+ }
+ tport = fnic_find_tport_by_fcid(iport, nport_id);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "RSCN port id list: 0x%x", nport_id);
+
+ if (!tport) {
+ newports++;
+ continue;
+ }
+ if (tport->state == FDLS_TGT_STATE_READY)
+ tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FDLS process RSCN sending GPN_FT %p", iport);
+ fdls_send_gpn_ft(iport, FDLS_STATE_RSCN_GPN_FT);
+ fdls_send_rscn_resp(iport, fchdr);
+}
+
+static void
+fdls_process_adisc_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
+{
+ struct fc_els_adisc_ls_acc_s adisc_acc;
+ struct fc_els_adisc_s *adisc_req = (struct fc_els_adisc_s *) fchdr;
+ uint64_t frame_wwnn;
+ uint64_t frame_wwpn;
+ uint32_t tgt_fcid;
+ struct fnic_tport_s *tport;
+ uint8_t *fcid;
+ struct fc_els_reject_s rjts_rsp;
+ uint16_t oxid;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Process ADISC request %d", iport->fnic->fnic_num);
+
+ fcid = FNIC_GET_S_ID(fchdr);
+ tgt_fcid = ntoh24(fcid);
+ tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
+ if (!tport) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "tport for fcid: 0x%x not found. Dropping ADISC req.",
+ tgt_fcid);
+ return;
+ }
+ if (iport->state != FNIC_IPORT_STATE_READY) {
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "Dropping ADISC req from fcid: 0x%x in iport state: %d",
+ tgt_fcid, iport->state);
+ return;
+ }
+
+ frame_wwnn = ntohll(adisc_req->node_name);
+ frame_wwpn = ntohll(adisc_req->nport_name);
+
+ if ((frame_wwnn != tport->wwnn) || (frame_wwpn != tport->wwpn)) {
+ /* send reject */
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "ADISC req from fcid: 0x%x mismatch wwpn: 0x%llx wwnn: 0x%llx",
+ tgt_fcid, frame_wwpn, frame_wwnn);
+ FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "local tport wwpn: 0x%llx wwnn: 0x%llx. Sending RJT",
+ tport->wwpn, tport->wwnn);
+
+ memcpy(&rjts_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));
+
+ rjts_rsp.reason_code = 0x03; /* logical error */
+ rjts_rsp.reason_expl = 0x1E; /* N_port login required */
+ rjts_rsp.vendor_specific = 0x0;
+ FNIC_SET_S_ID((&rjts_rsp.fchdr), fchdr->did);
+ FNIC_SET_D_ID((&rjts_rsp.fchdr), fchdr->sid);
+ oxid = FNIC_GET_OX_ID(fchdr);
+ FNIC_SET_OX_ID((&rjts_rsp.fchdr), oxid);
+ FNIC_SET_RX_ID((&rjts_rsp.fchdr), FNIC_ADISC_RESP_OXID);
+ fnic_send_fcoe_frame(iport, &rjts_rsp,
+ sizeof(struct fc_els_reject_s));
+ return;
+ }
+ memset(&adisc_acc.fchdr, 0, sizeof(struct fc_hdr_s));
+ FNIC_SET_S_ID((&adisc_acc.fchdr), fchdr->did);
+ FNIC_SET_D_ID((&adisc_acc.fchdr), fchdr->sid);
+ adisc_acc.fchdr.f_ctl = FNIC_ELS_REP_FCTL;
+ adisc_acc.fchdr.r_ctl = 0x23;
+ adisc_acc.fchdr.type = 0x01;
+ oxid = FNIC_GET_OX_ID(fchdr);
+ FNIC_SET_OX_ID((&adisc_acc.fchdr), oxid);
+ FNIC_SET_RX_ID((&adisc_acc.fchdr), FNIC_ADISC_RESP_OXID);
+ adisc_acc.command = FC_LS_ACC;
+
+ FNIC_SET_NPORT_NAME(adisc_acc, iport->wwpn);
+ FNIC_SET_NODE_NAME(adisc_acc, iport->wwnn);
+ memcpy(adisc_acc.fcid, fchdr->did, 3);
+ fnic_send_fcoe_frame(iport, &adisc_acc,
+ sizeof(struct fc_els_adisc_ls_acc_s));
+}
+
/*
* Performs a validation for all FCOE frames and return the frame type
*/
@@ -2954,6 +3489,31 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
} else
fdls_process_tgt_abts_rsp(iport, fchdr);
break;
+ case FNIC_BLS_ABTS_REQ:
+ fdls_process_abts_req(iport, fchdr);
+ break;
+ case FNIC_ELS_UNSUPPORTED_REQ:
+ fdls_process_unsupported_els_req(iport, fchdr);
+ break;
+ case FNIC_ELS_PLOGI_REQ:
+ fdls_process_plogi_req(iport, fchdr);
+ break;
+ case FNIC_ELS_RSCN_REQ:
+ fdls_process_rscn(iport, fchdr);
+ break;
+ case FNIC_ELS_LOGO_REQ:
+ fdls_process_logo_req(iport, fchdr);
+ break;
+ case FNIC_ELS_RRQ:
+ case FNIC_ELS_ECHO_REQ:
+ fdls_process_els_req(iport, fchdr, len);
+ break;
+ case FNIC_ELS_ADISC:
+ fdls_process_adisc_req(iport, fchdr);
+ break;
+ case FNIC_ELS_RLS:
+ fdls_process_rls_req(iport, fchdr);
+ break;
default:
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Received unknown FCoE frame of len: %d. Dropping frame", len);
--
2.31.1


Subject: [PATCH 13/14] scsi: fnic: Add support to handle port channel RSCN

Add support to handle port channel RSCN.

Port channel RSCN is a Cisco vendor specific RSCN
event. It is applicable only to Cisco UCS fabrics.
If there's a change in the port channel configuration,
an RCSN is sent to fnic. This is used to serially
reset the scsi initiator fnics so that there's no
all paths down scenario. The affected fnics are added
to a list that are reset with a small time gap
between them.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fdls_disc.c | 63 +++++++++++++++++++++++++++--------
drivers/scsi/fnic/fnic.h | 25 ++++++++++++++
drivers/scsi/fnic/fnic_fcs.c | 35 +++++++++++++++++++
drivers/scsi/fnic/fnic_main.c | 30 +++++++++++++++++
4 files changed, 140 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
index 55c4e1c7c130..a823061d15fb 100644
--- a/drivers/scsi/fnic/fdls_disc.c
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -3358,6 +3358,9 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
int newports = 0;
struct fnic_fdls_fabric_s *fdls = &iport->fabric;
struct fnic *fnic = iport->fnic;
+ int rscn_type = NOT_PC_RSCN;
+ uint32_t sid = ntoh24(fchdr->sid);
+ unsigned long reset_fnic_list_lock_flags = 0;

atomic64_inc(&iport->iport_stats.num_rscns);

@@ -3376,16 +3379,23 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if ((rscn->payload_len % 4 != 0) || (rscn->payload_len < 8)
|| (rscn->payload_len > 1024) || (rscn->page_len != 4)) {
num_ports = 0;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RSCN payload_len: 0x%x page_len: 0x%x",
- rscn->payload_len, rscn->page_len);
- /* if this happens then we need to send ADISC to all the tports. */
- list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
- if (tport->state == FDLS_TGT_STATE_READY)
- tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
+ if ((rscn->payload_len == 0xFFFF) && (sid == FC_FABRIC_CONTROLLER)) {
+ rscn_type = PC_RSCN;
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RSCN for port id: 0x%x", tport->fcid);
- }
+ "pcrscn: PCRSCN received. sid: 0x%x payload len: 0x%x", sid,
+ rscn->payload_len);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "RSCN payload_len: 0x%x page_len: 0x%x",
+ rscn->payload_len, rscn->page_len);
+ /* if this happens then we need to send ADISC to all the tports. */
+ list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
+ if (tport->state == FDLS_TGT_STATE_READY)
+ tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "RSCN for port id: 0x%x", tport->fcid);
+ }
+ } /* end else */
} else {
num_ports = (rscn->payload_len - 4) / rscn->page_len;
rscn_port = (struct fc_rscn_port_s *) (rscn + 1);
@@ -3435,10 +3445,37 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS process RSCN sending GPN_FT %p", iport);
- fdls_send_gpn_ft(iport, FDLS_STATE_RSCN_GPN_FT);
- fdls_send_rscn_resp(iport, fchdr);
+ if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON &&
+ rscn_type == PC_RSCN && fnic->role == FNIC_ROLE_FCP_INITIATOR) {
+
+ if (fnic->pc_rscn_handling_status == PC_RSCN_HANDLING_IN_PROGRESS) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "PCRSCN handling already in progress. Skip host reset: %d",
+ iport->fnic->fnic_num);
+ return;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "Processing PCRSCN. Queuing fnic for host reset: %d",
+ iport->fnic->fnic_num);
+ fnic->pc_rscn_handling_status = PC_RSCN_HANDLING_IN_PROGRESS;
+
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+
+ spin_lock_irqsave(&reset_fnic_list_lock,
+ reset_fnic_list_lock_flags);
+ list_add_tail(&fnic->links, &reset_fnic_list);
+ spin_unlock_irqrestore(&reset_fnic_list_lock,
+ reset_fnic_list_lock_flags);
+
+ queue_work(reset_fnic_work_queue, &reset_fnic_work);
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "FDLS process RSCN sending GPN_FT %p", iport);
+ fdls_send_gpn_ft(iport, FDLS_STATE_RSCN_GPN_FT);
+ fdls_send_rscn_resp(iport, fchdr);
+ }
}

void fnic_fdls_disc_start(struct fnic_iport_s *iport)
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 1c3d794ecd65..bcf2aaed0b1f 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -211,11 +211,33 @@ enum reset_states {
RESET_ERROR
};

+enum rscn_type {
+ NOT_PC_RSCN = 0,
+ PC_RSCN
+};
+
+enum pc_rscn_handling_status {
+ PC_RSCN_HANDLING_NOT_IN_PROGRESS = 0,
+ PC_RSCN_HANDLING_IN_PROGRESS
+};
+
+enum pc_rscn_handling_feature {
+ PC_RSCN_HANDLING_FEATURE_OFF = 0,
+ PC_RSCN_HANDLING_FEATURE_ON
+};
+
extern unsigned int fnic_fdmi_support;
extern unsigned int fnic_log_level;
extern unsigned int io_completions;
extern struct workqueue_struct *fnic_event_queue;

+extern unsigned int pc_rscn_handling_feature_flag;
+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;
+
+
#define FNIC_MAIN_LOGGING 0x01
#define FNIC_FCS_LOGGING 0x02
#define FNIC_SCSI_LOGGING 0x04
@@ -396,6 +418,7 @@ struct fnic {
int link_status;

struct list_head list;
+ struct list_head links;
struct pci_dev *pdev;
struct vnic_fc_config config;
struct vnic_dev *vdev;
@@ -455,6 +478,7 @@ struct fnic {

char subsys_desc[14];
int subsys_desc_len;
+ int pc_rscn_handling_status;
};

extern struct workqueue_struct *fnic_event_queue;
@@ -503,6 +527,7 @@ void fnic_stats_debugfs_remove(struct fnic *fnic);
int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);

void fnic_handle_fip_frame(struct work_struct *work);
+void fnic_reset_work_handler(struct work_struct *work);
void fnic_handle_fip_event(struct fnic *fnic);
void fnic_fcoe_reset_vlans(struct fnic *fnic);
extern void fnic_handle_fip_timer(struct timer_list *t);
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 2e4147b11d9f..c1a1b125ccb3 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -1121,4 +1121,39 @@ void fnic_flush_tport_event_list(struct fnic *fnic)
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
}

+void fnic_reset_work_handler(struct work_struct *work)
+{
+ struct fnic *cur_fnic, *next_fnic;
+ unsigned long reset_fnic_list_lock_flags;
+ int host_reset_ret_code;
+
+ /*
+ * This is a single thread. It is per fnic module, not per fnic
+ * All the fnics that need to be reset
+ * have been serialized via the reset fnic list.
+ */
+ spin_lock_irqsave(&reset_fnic_list_lock, reset_fnic_list_lock_flags);
+ list_for_each_entry_safe(cur_fnic, next_fnic, &reset_fnic_list, links) {
+ list_del(&cur_fnic->links);
+ spin_unlock_irqrestore(&reset_fnic_list_lock,
+ reset_fnic_list_lock_flags);
+
+ pr_err("fnic: <%d>: pcrscn: issuing a host reset\n",
+ cur_fnic->fnic_num);
+ host_reset_ret_code = fnic_host_reset(cur_fnic->host);
+ pr_err(
+ "fnic: <%d>: pcrscn: 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 =
+ PC_RSCN_HANDLING_NOT_IN_PROGRESS;
+ spin_unlock_irqrestore(&cur_fnic->fnic_lock, cur_fnic->lock_flags);
+
+ spin_lock_irqsave(&reset_fnic_list_lock,
+ reset_fnic_list_lock_flags);
+ }
+ spin_unlock_irqrestore(&reset_fnic_list_lock,
+ reset_fnic_list_lock_flags);
+}

diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 477b09b5dde2..ec8728cb12a6 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -44,6 +44,10 @@ 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);
+
/* Supported devices by fnic module */
static struct pci_device_id fnic_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_FNIC) },
@@ -88,6 +92,12 @@ 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");

+unsigned int pc_rscn_handling_feature_flag = PC_RSCN_HANDLING_FEATURE_ON;
+module_param(pc_rscn_handling_feature_flag, uint, 0644);
+MODULE_PARM_DESC(pc_rscn_handling_feature_flag,
+ "PCRSCN handling (0 for none. 1 to handle PCRSCN (default))");
+
+struct workqueue_struct *reset_fnic_work_queue;
struct workqueue_struct *fnic_fip_queue;

static int fnic_slave_alloc(struct scsi_device *sdev)
@@ -1216,6 +1226,19 @@ static int __init fnic_init_module(void)
goto err_create_fip_workq;
}

+ if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON) {
+ reset_fnic_work_queue =
+ create_singlethread_workqueue("reset_fnic_work_queue");
+ if (!reset_fnic_work_queue) {
+ pr_err("reset fnic work queue create failed\n");
+ err = -ENOMEM;
+ goto err_create_reset_fnic_workq;
+ }
+ spin_lock_init(&reset_fnic_list_lock);
+ INIT_LIST_HEAD(&reset_fnic_list);
+ INIT_WORK(&reset_fnic_work, fnic_reset_work_handler);
+ }
+
fnic_fc_transport = fc_attach_transport(&fnic_fc_functions);
if (!fnic_fc_transport) {
printk(KERN_ERR PFX "fc_attach_transport error\n");
@@ -1236,6 +1259,9 @@ static int __init fnic_init_module(void)
err_fc_transport:
destroy_workqueue(fnic_fip_queue);
err_create_fip_workq:
+ if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON)
+ destroy_workqueue(reset_fnic_work_queue);
+err_create_reset_fnic_workq:
destroy_workqueue(fnic_event_queue);
err_create_fnic_workq:
kmem_cache_destroy(fnic_io_req_cache);
@@ -1254,6 +1280,10 @@ static void __exit fnic_cleanup_module(void)
{
pci_unregister_driver(&fnic_driver);
destroy_workqueue(fnic_event_queue);
+
+ if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON)
+ destroy_workqueue(reset_fnic_work_queue);
+
if (fnic_fip_queue) {
flush_workqueue(fnic_fip_queue);
destroy_workqueue(fnic_fip_queue);
--
2.31.1


Subject: [PATCH 14/14] scsi: fnic: Increment driver version

Increment driver version to 1.8.0.0

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Tested-by: Karan Tilak Kumar <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fnic.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index bcf2aaed0b1f..8bdfdd67f08c 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -30,7 +30,7 @@

#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.7.0.0"
+#define DRV_VERSION "1.8.0.0"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "

--
2.31.1


Subject: [PATCH 12/14] scsi: fnic: Code cleanup

Replace existing host structure with fnic host.
Add headers from scsi to support new functionality.
Remove unused code and declarations.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fdls_disc.c | 508 +++++++++++++++----------------
drivers/scsi/fnic/fip.c | 78 ++---
drivers/scsi/fnic/fnic.h | 11 +-
drivers/scsi/fnic/fnic_debugfs.c | 2 +-
drivers/scsi/fnic/fnic_fcs.c | 125 ++++----
drivers/scsi/fnic/fnic_isr.c | 28 +-
drivers/scsi/fnic/fnic_main.c | 13 +-
drivers/scsi/fnic/fnic_scsi.c | 237 +++++++-------
8 files changed, 499 insertions(+), 503 deletions(-)

diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
index eb997701371e..55c4e1c7c130 100644
--- a/drivers/scsi/fnic/fdls_disc.c
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -267,7 +267,7 @@ static void fdls_free_tgt_oxid(struct fnic_iport_s *iport, uint16_t oxid)
struct fnic *fnic = iport->fnic;

if (iport->tgt_oxid_pool[oxid - FDLS_PLOGI_OXID_BASE] != 1) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Freeing unused OXID: 0x%x", oxid);
}
iport->tgt_oxid_pool[oxid - FDLS_PLOGI_OXID_BASE] = 0;
@@ -280,7 +280,7 @@ fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
struct fnic *fnic = iport->fnic;

if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport fcid: 0x%x: Canceling fabric disc timer\n",
iport->fcid);
fnic_del_fabric_timer_sync();
@@ -293,7 +293,7 @@ fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
fabric_tov = jiffies + msecs_to_jiffies(timeout);
mod_timer(&iport->fabric.retry_timer, round_jiffies(fabric_tov));
iport->fabric.timer_pending = 1;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fabric timer is %d ", timeout);
}

@@ -305,7 +305,7 @@ fdls_start_tport_timer(struct fnic_iport_s *iport,
struct fnic *fnic = iport->fnic;

if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport fcid 0x%x: Canceling disc timer\n",
tport->fcid);
fnic_del_tport_timer_sync();
@@ -387,7 +387,7 @@ fdls_send_tport_abts(struct fnic_iport_s *iport,

fc_abts_s.ox_id = tport->oxid_used;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS sending tport abts: tport->state: %d ",
tport->state);

@@ -464,7 +464,7 @@ static void fdls_send_fabric_abts(struct fnic_iport_s *iport)
default:
return;
}
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS sending fabric abts. iport->fabric.state: %d",
iport->fabric.state);

@@ -481,7 +481,7 @@ static void fdls_send_fabric_flogi(struct fnic_iport_s *iport)
struct fc_els_s flogi;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS send fabric FLOGI", iport->fcid);

memcpy(&flogi, &fnic_flogi_req, sizeof(struct fc_els_s));
@@ -505,7 +505,7 @@ static void fdls_send_fabric_plogi(struct fnic_iport_s *iport)
uint8_t fcid[3];
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS send fabric PLOGI", iport->fcid);

memcpy(&plogi, &fnic_plogi_req, sizeof(struct fc_els_s));
@@ -531,7 +531,7 @@ static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport)
struct fnic *fnic = iport->fnic;
u64 fdmi_tov;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fcid: 0x%x: FDLS send FDMI PLOGI", iport->fcid);

memcpy(&plogi, &fnic_plogi_req, sizeof(plogi));
@@ -559,7 +559,7 @@ static void fdls_send_rpn_id(struct fnic_iport_s *iport)
uint8_t fcid[3];
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS send RPN ID", iport->fcid);

memcpy(&rpn_id, &fnic_rpn_id_req, sizeof(struct fc_rpn_id_s));
@@ -581,7 +581,7 @@ static void fdls_send_scr(struct fnic_iport_s *iport)
uint8_t fcid[3];
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS send SCR", iport->fcid);

memcpy(&scr_req, &fnic_scr_req, sizeof(struct fc_scr_s));
@@ -601,7 +601,7 @@ static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state)
uint8_t fcid[3];
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS send GPN FT", iport->fcid);

memcpy(&gpn_ft, &fnic_gpn_ft_req, sizeof(struct fc_gpn_ft_s));
@@ -636,7 +636,7 @@ fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport)

oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_ADISC_OXID_BASE));
if (oxid == 0xFFFF) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to allocate OXID to send ADISC %p", iport);
return;
}
@@ -651,7 +651,7 @@ fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
memcpy(adisc.fcid, s_id, 3);
adisc.command = FNIC_ELS_ADISC_REQ;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"sending ADISC to tgt fcid: 0x%x", tport->fcid);

atomic64_inc(&iport->iport_stats.tport_adisc_sent);
@@ -679,7 +679,7 @@ void fdls_delete_tport(struct fnic_iport_s *iport,
tport->flags |= FNIC_FDLS_TPORT_TERMINATING;

if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport fcid 0x%x: Canceling disc timer\n",
tport->fcid);
fnic_del_tport_timer_sync();
@@ -695,7 +695,7 @@ void fdls_delete_tport(struct fnic_iport_s *iport,
tport_del_evt =
kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
if (!tport_del_evt) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to allocate memory for tport fcid: 0x%0x\n",
tport->fcid);
return;
@@ -705,7 +705,7 @@ void fdls_delete_tport(struct fnic_iport_s *iport,
list_add_tail(&tport_del_evt->links, &fnic->tport_event_list);
queue_work(fnic_event_queue, &fnic->tport_work);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport 0x%x not reg with scsi_transport. Freeing locally",
tport->fcid);
list_del(&tport->links);
@@ -724,7 +724,7 @@ fdls_send_tgt_plogi(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
struct fnic *fnic = iport->fnic;
uint32_t timeout;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Send tgt PLOGI to fcid: 0x%x", tport->fcid);

memcpy(&plogi, &fnic_plogi_req, sizeof(struct fc_els_s));
@@ -738,13 +738,13 @@ fdls_send_tgt_plogi(struct fnic_iport_s *iport, struct fnic_tport_s *tport)

oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_PLOGI_OXID_BASE));
if (oxid == 0xFFFF) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Failed to allocate oxid to send PLOGI to fcid: 0x%x",
iport->fcid, tport->fcid);
return;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"send tgt PLOGI: tgt fcid: 0x%x oxid: 0x%x", tport->fcid,
ntohs(oxid));
tport->oxid_used = oxid;
@@ -772,7 +772,7 @@ fnic_fc_plogi_rsp_rdf(struct fnic_iport_s *iport,
FNIC_FC_C3_RDF);
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"MFS: b2b_rdf_size: 0x%x spc3_rdf_size: 0x%x",
b2b_rdf_size, spc3_rdf_size);

@@ -785,7 +785,7 @@ static void fdls_send_register_fc4_types(struct fnic_iport_s *iport)
uint8_t fcid[3];
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS sending FC4 Types", iport->fcid);

memset(&rft_id, 0, sizeof(struct fc_rft_id));
@@ -808,7 +808,7 @@ static void fdls_send_register_fc4_features(struct fnic_iport_s *iport)
uint8_t fcid[3];
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS sending FC4 features", iport->fcid);
memcpy(&rff_id, &fnic_rff_id_req, sizeof(struct fc_rff_id));

@@ -820,7 +820,7 @@ static void fdls_send_register_fc4_features(struct fnic_iport_s *iport)
if (IS_FNIC_FCP_INITIATOR(fnic)) {
rff_id.fc4_type = 0x08;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Unknown type", iport->fcid);
}

@@ -838,16 +838,16 @@ fdls_send_tgt_prli(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
struct fnic *fnic = iport->fnic;
uint32_t timeout;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS sending PRLI to tgt: 0x%x", tport->fcid);

oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_PRLI_OXID_BASE));
if (oxid == 0xFFFF) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to allocate OXID to send PRLI %p", iport);
return;
}
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS sending PRLI to tgt: 0x%x OXID: 0x%x", tport->fcid,
ntohs(oxid));

@@ -897,7 +897,7 @@ void fdls_send_fabric_logo(struct fnic_iport_s *iport)
uint8_t d_id[3] = { 0xFF, 0xFF, 0xFE };
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Sending logo to fabric from iport->fcid: 0x%x",
iport->fcid);
memcpy(&logo, &fnic_logo_req, sizeof(struct fc_logo_req_s));
@@ -943,7 +943,7 @@ void fdls_tgt_logout(struct fnic_iport_s *iport,
uint8_t d_id[3];
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Sending logo to tport fcid: 0x%x", tport->fcid);
memcpy(&logo, &fnic_logo_req, sizeof(struct fc_logo_req_s));

@@ -967,7 +967,7 @@ static void fdls_tgt_discovery_start(struct fnic_iport_s *iport)
u32 old_link_down_cnt = iport->fnic->link_down_cnt;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Starting FDLS target discovery", iport->fcid);

list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
@@ -1020,7 +1020,7 @@ static void fdls_target_restart_nexus(struct fnic_tport_s *tport)
int nexus_restart_count;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport fcid: 0x%x state: %d restart_count: %d",
tport->fcid, tport->state, tport->nexus_restart_count);

@@ -1031,7 +1031,7 @@ static void fdls_target_restart_nexus(struct fnic_tport_s *tport)
fdls_delete_tport(iport, tport);

if (nexus_restart_count >= FNIC_TPORT_MAX_NEXUS_RESTART) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Exceeded nexus restart retries tport: 0x%x", fcid);
return;
}
@@ -1047,7 +1047,7 @@ static void fdls_target_restart_nexus(struct fnic_tport_s *tport)
*/
new_tport = fdls_create_tport(iport, fcid, wwpn);
if (!new_tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Error creating new tport: 0x%x", fcid);
return;
}
@@ -1076,12 +1076,12 @@ static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
struct fnic_tport_s *tport;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS create tport: fcid: 0x%x wwpn: 0x%llx", fcid, wwpn);

tport = kzalloc(sizeof(struct fnic_tport_s), GFP_ATOMIC);
if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Memory allocation failure while creating tport: 0x%x\n",
fcid);
return NULL;
@@ -1094,12 +1094,12 @@ static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
tport->wwpn = wwpn;
tport->iport = iport;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Need to setup tport timer callback");

timer_setup(&tport->retry_timer, fdls_tport_timer_callback, 0);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Added tport 0x%x", tport->fcid);
fdls_set_tport_state(tport, FDLS_TGT_STATE_INIT);
list_add_tail(&tport->links, &iport->tport_list);
@@ -1200,7 +1200,7 @@ static void fdls_fdmi_register_pa(struct fnic_iport_s *iport)
fdmi_rpa.current_speed = htonl(port_speed_bm);
fdmi_rpa.fc4_type[2] = 1;
snprintf(fdmi_rpa.os_name, sizeof(fdmi_rpa.os_name) - 1, "host%d",
- fnic->lport->host->host_no);
+ fnic->host->host_no);
snprintf(fdmi_rpa.host_name, sizeof(fdmi_rpa.host_name) - 1, "%s",
utsname()->nodename);
fnic_send_fcoe_frame(iport, &fdmi_rpa, sizeof(struct fc_fdmi_rpa_s));
@@ -1214,7 +1214,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
struct fnic *fnic = iport->fnic;
unsigned long flags;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tp: %d fab state: %d fab retry counter: %d max_flogi_retries: %d",
iport->fabric.timer_pending, iport->fabric.state,
iport->fabric.retry_counter, iport->max_flogi_retries);
@@ -1229,7 +1229,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
if (iport->fabric.del_timer_inprogress) {
iport->fabric.del_timer_inprogress = 0;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fabric_del_timer inprogress(%d). Skip timer cb",
iport->fabric.del_timer_inprogress);
return;
@@ -1260,7 +1260,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
fdls_send_fabric_flogi(iport);
} else
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Exceeded max FLOGI retries");
}
break;
@@ -1285,7 +1285,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
fdls_send_fabric_plogi(iport);
} else
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Exceeded max PLOGI retries");
}
break;
@@ -1319,7 +1319,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
fdls_send_fabric_abts(iport);
else {
/* ABTS has timed out (2*ra_tov), we give up */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ABTS timed out. Starting PLOGI: %p", iport);
fnic_fdls_start_plogi(iport);
}
@@ -1338,7 +1338,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
fdls_send_fabric_abts(iport);
} else {
/* ABTS has timed out (2*ra_tov), we give up */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ABTS timed out. Starting PLOGI: %p", iport);
fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
}
@@ -1357,7 +1357,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
fdls_send_fabric_abts(iport);
else {
/* ABTS has timed out (2*ra_tov), we give up */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ABTS timed out. Starting PLOGI %p", iport);
fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
}
@@ -1384,7 +1384,7 @@ void fdls_fabric_timer_callback(struct timer_list *t)
if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
fdls_send_gpn_ft(iport, iport->fabric.state);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ABTS timeout for fabric GPN_FT. Check name server: %p",
iport);
}
@@ -1405,7 +1405,7 @@ void fdls_fdmi_timer_callback(struct timer_list *t)

if (iport->fabric.fdmi_retry < 7) {
iport->fabric.fdmi_retry++;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"retry fdmi timer %d", iport->fabric.fdmi_retry);
fdls_send_fdmi_plogi(iport);
} else {
@@ -1424,7 +1424,7 @@ static void fdls_send_delete_tport_msg(struct fnic_tport_s *tport)

tport_del_evt = kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
if (!tport_del_evt) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to allocate memory for tport event fcid: 0x%x",
tport->fcid);
return;
@@ -1457,13 +1457,13 @@ static void fdls_tport_timer_callback(struct timer_list *t)
if (tport->del_timer_inprogress) {
tport->del_timer_inprogress = 0;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport_del_timer inprogress. Skip timer cb tport fcid: 0x%x\n",
tport->fcid);
return;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport fcid: 0x%x timer pending: %d state: %d retry counter: %d",
tport->fcid, tport->timer_pending, tport->state,
tport->retry_counter);
@@ -1540,14 +1540,14 @@ static void fdls_tport_timer_callback(struct timer_list *t)
}
/* exceeded retry count */
fdls_free_tgt_oxid(iport, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ADISC not responding. Deleting target port: 0x%x",
tport->fcid);
fdls_send_delete_tport_msg(tport);
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return;
default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown tport state: 0x%x", tport->state);
break;
}
@@ -1599,26 +1599,26 @@ fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
tport = fnic_find_tport_by_fcid(iport, tgt_fcid);

if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Tgt ADISC response tport not found: 0x%x", tgt_fcid);
return;
}
if ((iport->state != FNIC_IPORT_STATE_READY)
|| (tport->state != FDLS_TGT_STATE_ADISC)
|| (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping this ADISC response");
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport state: %d tport state: %d Is abort issued on PRLI? %d",
iport->state, tport->state,
(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED));
return;
}
if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping frame from target: 0x%x",
tgt_fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Reason: Stale ADISC/Aborted ADISC/OOO frame delivery");
return;
}
@@ -1627,7 +1627,7 @@ fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
case FC_LS_ACC:
atomic64_inc(&iport->iport_stats.tport_adisc_ls_accepts);
if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport 0x%p Canceling fabric disc timer\n",
tport);
fnic_del_tport_timer_sync();
@@ -1639,12 +1639,12 @@ fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
frame_wwnn = htonll(adisc_rsp->node_name);
frame_wwpn = htonll(adisc_rsp->nport_name);
if ((frame_wwnn == tport->wwnn) && (frame_wwpn == tport->wwpn)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ADISC accepted from target: 0x%x. Target logged in",
tgt_fcid);
fdls_set_tport_state(tport, FDLS_TGT_STATE_READY);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Error mismatch frame: ADISC");
}
break;
@@ -1654,14 +1654,14 @@ fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (tport->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ADISC ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
tgt_fcid);

/* Retry ADISC again from the timer routine. */
tport->flags |= FNIC_FDLS_RETRY_FRAME;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"ADISC returned FC_LS_REJ from target: 0x%x",
tgt_fcid);
oxid = ntohs(fchdr->ox_id);
@@ -1689,26 +1689,26 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
fcid = FNIC_GET_S_ID(fchdr);
tgt_fcid = ntoh24(fcid);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS processing target PLOGI response: tgt_fcid: 0x%x",
tgt_fcid);

tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport not found: 0x%x", tgt_fcid);
return;
}
if ((iport->state != FNIC_IPORT_STATE_READY)
|| (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping frame! iport state: %d tport state: %d",
iport->state, tport->state);
return;
}

if (tport->state != FDLS_TGT_STATE_PLOGI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI rsp recvd in wrong state. Restarting nexus");
oxid = ntohs(FNIC_GET_OX_ID(fchdr));
fdls_free_tgt_oxid(iport, oxid);
@@ -1717,7 +1717,7 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
}

if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI response from target: 0x%x. Dropping frame",
tgt_fcid);
return;
@@ -1726,7 +1726,7 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
switch (plogi_rsp->command) {
case FC_LS_ACC:
atomic64_inc(&iport->iport_stats.tport_plogi_ls_accepts);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI accepted by target: 0x%x", tgt_fcid);
oxid = ntohs(FNIC_GET_OX_ID(fchdr));
fdls_free_tgt_oxid(iport, oxid);
@@ -1737,14 +1737,14 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (tport->retry_counter < iport->max_plogi_retries)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
tgt_fcid);
/* Retry plogi again from the timer routine. */
tport->flags |= FNIC_FDLS_RETRY_FRAME;
return;
}
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI returned FC_LS_REJ from target: 0x%x",
tgt_fcid);
oxid = ntohs(fchdr->ox_id);
@@ -1754,18 +1754,18 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,

default:
atomic64_inc(&iport->iport_stats.tport_plogi_misc_rejects);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI not accepted from target fcid: 0x%x",
tgt_fcid);
return;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Found the PLOGI target: 0x%x and state: %d",
(unsigned int) tgt_fcid, tport->state);

if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport fcid 0x%x: Canceling disc timer\n",
tport->fcid);
fnic_del_tport_timer_sync();
@@ -1783,13 +1783,13 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
MIN(max_payload_size, iport->max_payload_size);

if (tport->max_payload_size < FNIC_MIN_DATA_FIELD_SIZE) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"MFS: tport max frame size below spec bounds: %d",
tport->max_payload_size);
tport->max_payload_size = FNIC_MIN_DATA_FIELD_SIZE;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"MAX frame size: %d iport max_payload_size: %d tport mfs: %d",
max_payload_size, iport->max_payload_size,
tport->max_payload_size);
@@ -1818,12 +1818,12 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
fcid = FNIC_GET_S_ID(fchdr);
tgt_fcid = ntoh24(fcid);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS process tgt PRLI response: 0x%x", tgt_fcid);

tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport not found: 0x%x", tgt_fcid);
/* Handle or just drop? */
return;
@@ -1831,14 +1831,14 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,

if ((iport->state != FNIC_IPORT_STATE_READY)
|| (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping frame! iport st: %d tport st: %d tport fcid: 0x%x",
iport->state, tport->state, tport->fcid);
return;
}

if (tport->state != FDLS_TGT_STATE_PRLI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PRLI rsp recvd in wrong state. Restarting nexus");
oxid = ntohs(FNIC_GET_OX_ID(fchdr));
fdls_free_tgt_oxid(iport, oxid);
@@ -1847,10 +1847,10 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
}

if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping PRLI response from target: 0x%x ",
tgt_fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Reason: Stale PRLI response/Aborted PDISC/OOO frame delivery");
return;
}
@@ -1858,13 +1858,13 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
switch (prli_rsp->command) {
case FC_LS_ACC:
atomic64_inc(&iport->iport_stats.tport_prli_ls_accepts);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PRLI accepted from target: 0x%x", tgt_fcid);
oxid = ntohs(FNIC_GET_OX_ID(fchdr));
fdls_free_tgt_oxid(iport, oxid);

if (prli_rsp->sp.type != FC_FC4_TYPE_SCSI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"mismatched target zoned with FC SCSI initiator: 0x%x",
tgt_fcid);
mismatched_tgt = true;
@@ -1882,7 +1882,7 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (tport->retry_counter < FDLS_RETRY_COUNT)) {

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PRLI ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
tgt_fcid);

@@ -1890,7 +1890,7 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
tport->flags |= FNIC_FDLS_RETRY_FRAME;
return;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PRLI returned FC_LS_REJ from target: 0x%x",
tgt_fcid);

@@ -1904,18 +1904,18 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,

default:
atomic64_inc(&iport->iport_stats.tport_prli_misc_rejects);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PRLI not accepted from target: 0x%x", tgt_fcid);
return;
break;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Found the PRLI target: 0x%x and state: %d",
(unsigned int) tgt_fcid, tport->state);

if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport fcid 0x%x: Canceling disc timer\n",
tport->fcid);
fnic_del_tport_timer_sync();
@@ -1934,7 +1934,7 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,

/* Check if the device plays Target Mode Function */
if (!(tport->fcp_csp & FCP_PRLI_FUNC_TARGET)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Remote port(0x%x): no target support. Deleting it\n",
tgt_fcid);
fdls_tgt_logout(iport, tport);
@@ -1947,14 +1947,14 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
/* Inform the driver about new target added */
tport_add_evt = kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
if (!tport_add_evt) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport event memory allocation failure: 0x%0x\n",
tport->fcid);
return;
}
tport_add_evt->event = TGT_EV_RPORT_ADD;
tport_add_evt->arg1 = (void *) tport;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport fcid: 0x%x add tport event fcid: 0x%x\n",
tport->fcid, iport->fcid);
list_add_tail(&tport_add_evt->links, &fnic->tport_event_list);
@@ -1972,21 +1972,21 @@ fdls_process_rff_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
uint8_t reason_code;

if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_FEATURES) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RFF_ID resp recvd in state(%d). Dropping.",
fdls_get_state(fdls));
return;
}

rsp = FNIC_GET_FC_CT_CMD((&rff_rsp->fc_ct_hdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS process RFF ID response: 0x%04x", iport->fcid,
(uint32_t) rsp);

switch (rsp) {
case FC_CT_ACC:
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2000,17 +2000,17 @@ fdls_process_rff_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
|| (reason_code == FC_CT_RJT_BUSY))
&& (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RFF_ID ret FC_LS_REJ BUSY. Retry from timer routine %p",
iport);

/* Retry again from the timer routine */
fdls->flags |= FNIC_FDLS_RETRY_FRAME;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RFF_ID returned FC_LS_REJ. Halting discovery %p", iport);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2033,21 +2033,21 @@ fdls_process_rft_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
struct fnic *fnic = iport->fnic;

if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_TYPES) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RFT_ID resp recvd in state(%d). Dropping.",
fdls_get_state(fdls));
return;
}

rsp = FNIC_GET_FC_CT_CMD((&rft_rsp->fc_ct_hdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS process RFT ID response: 0x%04x", iport->fcid,
(uint32_t) rsp);

switch (rsp) {
case FC_CT_ACC:
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2061,19 +2061,19 @@ fdls_process_rft_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
|| (reason_code == FC_CT_RJT_BUSY))
&& (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: RFT_ID ret FC_LS_REJ BUSY. Retry from timer routine",
iport->fcid);

/* Retry again from the timer routine */
fdls->flags |= FNIC_FDLS_RETRY_FRAME;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: RFT_ID REJ. Halting discovery reason %d expl %d",
iport->fcid, reason_code,
rft_rsp->fc_ct_hdr.reason_expl);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2096,21 +2096,21 @@ fdls_process_rpn_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
struct fnic *fnic = iport->fnic;

if (fdls_get_state(fdls) != FDLS_STATE_RPN_ID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RPN_ID resp recvd in state(%d). Dropping.",
fdls_get_state(fdls));
return;
}

rsp = FNIC_GET_FC_CT_CMD((&rpn_rsp->fc_ct_hdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS process RPN ID response: 0x%04x", iport->fcid,
(uint32_t) rsp);

switch (rsp) {
case FC_CT_ACC:
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2124,17 +2124,17 @@ fdls_process_rpn_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
|| (reason_code == FC_CT_RJT_BUSY))
&& (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RPN_ID returned REJ BUSY. Retry from timer routine %p",
iport);

/* Retry again from the timer routine */
fdls->flags |= FNIC_FDLS_RETRY_FRAME;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RPN_ID FC_LS_REJ. Halting discovery %p", iport);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2155,12 +2155,12 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS process SCR response: 0x%04x",
(uint32_t) scr_rsp->command);

if (fdls_get_state(fdls) != FDLS_STATE_SCR) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"SCR resp recvd in state(%d). Dropping.",
fdls_get_state(fdls));
return;
@@ -2170,7 +2170,7 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
case FC_LS_ACC:
atomic64_inc(&iport->iport_stats.fabric_scr_ls_accepts);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2184,17 +2184,17 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"SCR FC_LS_REJ BUSY. Retry from timer routine %p",
iport);
/* Retry again from the timer routine */
fdls->flags |= FNIC_FDLS_RETRY_FRAME;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"SCR returned FC_LS_REJ. Halting discovery %p",
iport);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2222,7 +2222,7 @@ fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
u32 old_link_down_cnt = iport->fnic->link_down_cnt;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS process GPN_FT tgt list", iport->fcid);

gpn_ft_tgt =
@@ -2237,7 +2237,7 @@ fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
fcid = ntoh24(gpn_ft_tgt->fcid);
wwpn = ntohll(gpn_ft_tgt->wwpn);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"tport: 0x%x: ctrl:0x%x", fcid, gpn_ft_tgt->ctrl);

if (fcid == iport->fcid) {
@@ -2284,7 +2284,7 @@ fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
rem_len -= sizeof(struct fc_gpn_ft_rsp_iu_s);
}
if (rem_len <= 0) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"GPN_FT response: malformed/corrupt frame rxlen: %d remlen: %d",
len, rem_len);
}
@@ -2294,7 +2294,7 @@ fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
list_for_each_entry_safe(tport, next, &iport->tport_list, links) {

if (!(tport->flags & FNIC_FDLS_TPORT_IN_GPN_FT_LIST)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Remove port: 0x%x not found in GPN_FT list",
tport->fcid);
fdls_delete_tport(iport, tport);
@@ -2322,7 +2322,7 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
u32 old_link_down_cnt = iport->fnic->link_down_cnt;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS process GPN_FT response: iport state: %d len: %d",
iport->state, len);

@@ -2342,7 +2342,7 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
&& ((fdls_get_state(fdls) == FDLS_STATE_RSCN_GPN_FT)
|| (fdls_get_state(fdls) == FDLS_STATE_SEND_GPNFT)
|| (fdls_get_state(fdls) == FDLS_STATE_TGT_DISCOVERY))))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"GPNFT resp recvd in fab state(%d) iport_state(%d). Dropping.",
fdls_get_state(fdls), iport->state);
return;
@@ -2354,10 +2354,10 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
switch (rsp) {

case FC_CT_ACC:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: GPNFT_RSP accept", iport->fcid);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Canceling fabric disc timer\n",
iport->fcid);
fnic_del_fabric_timer_sync();
@@ -2372,7 +2372,7 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
* that will be taken care in next link up event
*/
if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Halting target discovery: fab st: %d iport st: %d ",
fdls_get_state(fdls), iport->state);
break;
@@ -2382,22 +2382,22 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,

case FC_CT_REJ:
reason_code = gpn_ft_rsp->fc_ct_hdr.reason_code;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: GPNFT_RSP Reject", iport->fcid);

if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
|| (reason_code == FC_CT_RJT_BUSY))
&& (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: GPNFT_RSP ret REJ/BSY. Retry from timer routine",
iport->fcid);
/* Retry again from the timer routine */
fdls->flags |= FNIC_FDLS_RETRY_FRAME;
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: GPNFT_RSP reject", iport->fcid);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Canceling fabric disc timer\n",
iport->fcid);
fnic_del_fabric_timer_sync();
@@ -2411,7 +2411,7 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
count = 0;
list_for_each_entry_safe(tport, next, &iport->tport_list,
links) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"GPN_FT_REJECT: Remove port: 0x%x",
tport->fcid);
fdls_delete_tport(iport, tport);
@@ -2421,7 +2421,7 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
}
count++;
}
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"GPN_FT_REJECT: Removed (0x%x) ports", count);
}
break;
@@ -2454,7 +2454,7 @@ fdls_process_fabric_logo_rsp(struct fnic_iport_s *iport,
switch (flogo_rsp->command) {
case FC_LS_ACC:
if (iport->fabric.state != FDLS_STATE_FABRIC_LOGO) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Flogo response. Fabric not in LOGO state. Dropping! %p",
iport);
return;
@@ -2464,25 +2464,25 @@ fdls_process_fabric_logo_rsp(struct fnic_iport_s *iport,
iport->state = FNIC_IPORT_STATE_LINK_WAIT;

if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "lport 0x%p Canceling fabric disc timer\n",
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
+ "iport 0x%p Canceling fabric disc timer\n",
iport);
fnic_del_fabric_timer_sync();
}
iport->fabric.timer_pending = 0;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Flogo response from Fabric for did: 0x%x",
ntoh24(fchdr->did));
return;

case FC_LS_REJ:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Flogo response from Fabric for did: 0x%x returned FC_LS_REJ",
ntoh24(fchdr->did));
return;

default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGO response not accepted or rejected: 0x%x",
flogo_rsp->command);
}
@@ -2500,11 +2500,11 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
uint8_t fcmac[6] = { 0x0E, 0XFC, 0x00, 0x00, 0x00, 0x00 };
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS processing FLOGI response", iport->fcid);

if (fdls_get_state(fabric) != FDLS_STATE_FABRIC_FLOGI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI response received in state (%d). Dropping frame",
fdls_get_state(fabric));
return;
@@ -2514,7 +2514,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
case FC_LS_ACC:
atomic64_inc(&iport->iport_stats.fabric_flogi_ls_accepts);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport fcid: 0x%x Canceling fabric disc timer\n",
iport->fcid);
fnic_del_fabric_timer_sync();
@@ -2524,7 +2524,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
iport->fabric.retry_counter = 0;
fcid = FNIC_GET_D_ID(fchdr);
iport->fcid = ntoh24(fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FLOGI response accepted", iport->fcid);

/* Learn the Service Params */
@@ -2534,7 +2534,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
iport->max_payload_size = MIN(rdf_size,
iport->max_payload_size);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"max_payload_size from fabric: %d set: %d", rdf_size,
iport->max_payload_size);

@@ -2544,26 +2544,26 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
if (flogi_rsp->u.csp_flogi.features & FNIC_FC_EDTOV_NSEC)
iport->e_d_tov = iport->e_d_tov / FNIC_NSEC_TO_MSEC;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"From fabric: R_A_TOV: %d E_D_TOV: %d",
iport->r_a_tov, iport->e_d_tov);

if (IS_FNIC_FCP_INITIATOR(fnic)) {
- fc_host_fabric_name(iport->fnic->lport->host) =
+ fc_host_fabric_name(iport->fnic->host) =
get_unaligned_be64(&flogi_rsp->node_name);
- fc_host_port_id(iport->fnic->lport->host) = iport->fcid;
+ fc_host_port_id(iport->fnic->host) = iport->fcid;
}

fnic_fdls_learn_fcoe_macs(iport, rx_frame, fcid);

if (fnic_fdls_register_portid(iport, iport->fcid, rx_frame) != 0) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FLOGI registration failed", iport->fcid);
break;
}

memcpy(&fcmac[3], fcid, 3);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Adding vNIC device MAC addr: %02x:%02x:%02x:%02x:%02x:%02x",
fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
fcmac[5]);
@@ -2571,7 +2571,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,

if (fdls_get_state(fabric) == FDLS_STATE_FABRIC_FLOGI) {
fnic_fdls_start_plogi(iport);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI response received. Starting PLOGI");
} else {
/* From FDLS_STATE_FABRIC_FLOGI state fabric can only go to
@@ -2579,7 +2579,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
* state, hence we don't have to worry about undoing:
* the fnic_fdls_register_portid and vnic_dev_add_addr
*/
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI response received in state (%d). Dropping frame",
fdls_get_state(fabric));
}
@@ -2589,7 +2589,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
atomic64_inc(&iport->iport_stats.fabric_flogi_ls_rejects);
els_rjt = (struct fc_els_reject_s *) fchdr;
if (fabric->retry_counter < iport->max_flogi_retries) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI returned FC_LS_REJ BUSY. Retry from timer routine %p",
iport);

@@ -2597,10 +2597,10 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
fabric->flags |= FNIC_FDLS_RETRY_FRAME;

} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI returned FC_LS_REJ. Halting discovery %p", iport);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport 0x%p Canceling fabric disc timer\n",
iport);
fnic_del_fabric_timer_sync();
@@ -2611,7 +2611,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
break;

default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI response not accepted: 0x%x",
flogi_rsp->command);
atomic64_inc(&iport->iport_stats.fabric_flogi_misc_rejects);
@@ -2628,7 +2628,7 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
struct fnic *fnic = iport->fnic;

if (fdls_get_state((&iport->fabric)) != FDLS_STATE_FABRIC_PLOGI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Fabric PLOGI response received in state (%d). Dropping frame",
fdls_get_state(&iport->fabric));
return;
@@ -2638,7 +2638,7 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
case FC_LS_ACC:
atomic64_inc(&iport->iport_stats.fabric_plogi_ls_accepts);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport fcid: 0x%x fabric PLOGI response: Accepted\n",
iport->fcid);
fnic_del_fabric_timer_sync();
@@ -2653,15 +2653,15 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
|| (els_rjt->reason_code == FC_ELS_RJT_BUSY))
&& (iport->fabric.retry_counter < iport->max_plogi_retries)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Fabric PLOGI FC_LS_REJ BUSY. Retry from timer routine",
iport->fcid);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Fabric PLOGI FC_LS_REJ. Halting discovery",
iport->fcid);
if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport fcid: 0x%x Canceling fabric disc timer\n",
iport->fcid);
fnic_del_fabric_timer_sync();
@@ -2672,7 +2672,7 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
}
break;
default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI response not accepted: 0x%x",
plogi_rsp->command);
atomic64_inc(&iport->iport_stats.fabric_plogi_misc_rejects);
@@ -2693,9 +2693,9 @@ static void fdls_process_fdmi_plogi_rsp(struct fnic_iport_s *iport,
iport->fabric.fdmi_pending = 0;
switch (plogi_rsp->command) {
case FC_LS_ACC:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS process fdmi PLOGI response status: FC_LS_ACC\n");
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Sending fdmi registration for port 0x%x\n",
iport->fcid);

@@ -2706,7 +2706,7 @@ static void fdls_process_fdmi_plogi_rsp(struct fnic_iport_s *iport,
iport->fabric.fdmi_pending = 2;
break;
case FC_LS_REJ:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Fabric FDMI PLOGI returned FC_LS_REJ reason: 0x%x",
els_rjt->reason_code);

@@ -2730,13 +2730,13 @@ static void fdls_process_fdmi_reg_ack(struct fnic_iport_s *iport,

if (iport->fabric.fdmi_pending > 0) {
iport->fabric.fdmi_pending--;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport fcid: 0x%x: Received FDMI registration ack\n",
iport->fcid);

if (iport->fabric.fdmi_pending == 0) {
del_timer_sync(&iport->fabric.fdmi_timer);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport fcid: 0x%x: Canceling FDMI timer\n",
iport->fcid);
}
@@ -2758,14 +2758,14 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,

if (!((s_id == FC_DIR_SERVER) || (s_id == FC_DOMAIN_CONTR)
|| (s_id == FC_FABRIC_CONTROLLER))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received abts rsp with invalid SID: 0x%x. Dropping frame",
s_id);
return;
}

if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Canceling fabric disc timer %p\n", iport);
fnic_del_fabric_timer_sync();
}
@@ -2773,11 +2773,11 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;

if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received abts rsp BA_ACC for fabric_state: %d OX_ID: 0x%x",
fabric_state, ba_acc->ox_id);
} else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"BA_RJT fs: %d OX_ID: 0x%x rc: 0x%x rce: 0x%x",
fabric_state, ba_rjt->fchdr.ox_id,
ba_rjt->reason_code, ba_rjt->reason_explanation);
@@ -2790,10 +2790,10 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
if (iport->fabric.retry_counter < iport->max_flogi_retries)
fdls_send_fabric_flogi(iport);
else
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Exceeded max FLOGI retries");
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x FABRIC_FLOGI state. Drop frame",
fchdr->ox_id);
}
@@ -2803,7 +2803,7 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
if (!RETRIES_EXHAUSTED(iport))
fdls_send_fabric_logo(iport);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x FABRIC_FLOGI state. Drop frame",
fchdr->ox_id);
}
@@ -2813,10 +2813,10 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
if (iport->fabric.retry_counter < iport->max_plogi_retries)
fdls_send_fabric_plogi(iport);
else
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Exceeded max PLOGI retries");
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x FABRIC_PLOGI state. Drop frame",
fchdr->ox_id);
}
@@ -2831,7 +2831,7 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
fnic_fdls_start_plogi(iport);
}
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x RPN_ID state. Drop frame",
fchdr->ox_id);
}
@@ -2842,13 +2842,13 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT)
fdls_send_scr(iport);
else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"abts rsp fab SCR after two tries. Start fabric PLOGI %p",
iport);
fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
}
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x SCR state. Drop frame",
fchdr->ox_id);
}
@@ -2858,13 +2858,13 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT) {
fdls_send_register_fc4_types(iport);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"abts rsp fab RFT_ID two tries. Start fabric PLOGI %p",
iport);
fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
}
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x RFT state. Drop frame",
fchdr->ox_id);
}
@@ -2874,13 +2874,13 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT)
fdls_send_register_fc4_features(iport);
else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"abts rsp fab SCR after two tries. Start fabric PLOGI %p",
iport);
fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
}
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x RFF state. Drop frame",
fchdr->ox_id);
}
@@ -2891,12 +2891,12 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT) {
fdls_send_gpn_ft(iport, fabric_state);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"abts rsp fab GPN_FT after two tries %p",
iport);
}
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown abts rsp OX_ID: 0x%x GPN_FT state. Drop frame",
fchdr->ox_id);
}
@@ -2917,7 +2917,7 @@ fdls_process_abts_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
struct fnic *fnic = iport->fnic;

nport_id = ntoh24(fchdr->sid);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received abort from SID %8x", nport_id);

tport = fnic_find_tport_by_fcid(iport, nport_id);
@@ -2953,7 +2953,7 @@ fdls_process_unsupported_els_req(struct fnic_iport_s *iport,
memcpy(&ls_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));

if (iport->fcid != d_id) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping unsupported ELS with illegal frame bits 0x%x\n",
d_id);
atomic64_inc(&iport->iport_stats.unsupported_frames_dropped);
@@ -2962,14 +2962,14 @@ fdls_process_unsupported_els_req(struct fnic_iport_s *iport,

if ((iport->state != FNIC_IPORT_STATE_READY)
&& (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping unsupported ELS request in iport state: %d",
iport->state);
atomic64_inc(&iport->iport_stats.unsupported_frames_dropped);
return;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Process unsupported ELS request from SID: 0x%x",
ntoh24(fchdr->sid));
/* We don't support this ELS request, send a reject */
@@ -2993,12 +2993,12 @@ fdls_process_rls_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
uint16_t oxid;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Process RLS request %d", iport->fnic->fnic_num);

if ((iport->state != FNIC_IPORT_STATE_READY)
&& (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received RLS req in iport state: %d. Dropping the frame.",
iport->state);
return;
@@ -3038,32 +3038,32 @@ fdls_process_els_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,

if ((iport->state != FNIC_IPORT_STATE_READY)
&& (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping ELS frame type :%x in iport state: %d",
type, iport->state);
return;
}
switch (type) {
case FC_ELS_ECHO_REQ:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"sending LS_ACC for ECHO request %d\n",
iport->fnic->fnic_num);
break;

case FC_ELS_RRQ_REQ:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"sending LS_ACC for RRQ request %d\n",
iport->fnic->fnic_num);
break;

default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"sending LS_ACC for %x ELS frame\n", type);
break;
}
dst_frame = kzalloc(len, GFP_ATOMIC);
if (!dst_frame) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to allocate ELS response for %x", type);
return;
}
@@ -3109,18 +3109,18 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,

tport = fnic_find_tport_by_fcid(iport, s_id);
if (!tport) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Received tgt abts rsp with invalid SID: 0x%x", s_id);
return;
}

if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"tport 0x%p Canceling fabric disc timer\n", tport);
fnic_del_tport_timer_sync();
}
if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Received tgt abts rsp in iport state(%d). Dropping.",
iport->state);
return;
@@ -3133,14 +3133,14 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
/*This abort rsp is for ADISC */
if ((oxid >= FDLS_ADISC_OXID_BASE) && (oxid < FDLS_TGT_OXID_POOL_END)) {
if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"OX_ID: 0x%x tgt_fcid: 0x%x rcvd tgt adisc abts resp BA_ACC",
ba_acc->ox_id, tport->fcid);
} else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"ADISC BA_RJT rcvd tport_fcid: 0x%x tport_state: %d ",
tport->fcid, tport_state);
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"reason code: 0x%x reason code explanation:0x%x ",
ba_rjt->reason_code, ba_rjt->reason_explanation);
}
@@ -3151,7 +3151,7 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
return;
}
fdls_free_tgt_oxid(iport, oxid);
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"ADISC not responding. Deleting target port: 0x%x",
tport->fcid);
fdls_delete_tport(iport, tport);
@@ -3167,14 +3167,14 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
/*This abort rsp is for PLOGI */
if ((oxid >= FDLS_PLOGI_OXID_BASE) && (oxid < FDLS_PRLI_OXID_BASE)) {
if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Received tgt PLOGI abts response BA_ACC tgt_fcid: 0x%x",
tport->fcid);
} else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PLOGI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x",
tport->fcid, fchdr->ox_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"reason code: 0x%x reason code explanation: 0x%x",
ba_rjt->reason_code, ba_rjt->reason_explanation);
}
@@ -3198,14 +3198,14 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
/*This abort rsp is for PRLI */
if ((oxid >= FDLS_PRLI_OXID_BASE) && (oxid < FDLS_ADISC_OXID_BASE)) {
if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: Received tgt PRLI abts response BA_ACC",
tport->fcid);
} else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PRLI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x ",
tport->fcid, fchdr->ox_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"reason code: 0x%x reason code explanation: 0x%x",
ba_rjt->reason_code,
ba_rjt->reason_explanation);
@@ -3222,7 +3222,7 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
return;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received ABTS response for unknown frame %p", iport);
}

@@ -3237,19 +3237,19 @@ fdls_process_plogi_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
memcpy(&plogi_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));

if (iport->fcid != d_id) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received PLOGI with illegal frame bits. Dropping frame %p",
iport);
return;
}

if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received PLOGI request in iport state: %d Dropping frame",
iport->state);
return;
}
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Process PLOGI request from SID: 0x%x",
ntoh24(fchdr->sid));

@@ -3282,11 +3282,11 @@ fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
nport_id = ntoh24(logo->fcid);
nport_name = logo->wwpn;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Process LOGO request from fcid: 0x%x", nport_id);

if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Dropping LOGO req from 0x%x in iport state: %d",
nport_id, iport->state);
return;
@@ -3296,19 +3296,19 @@ fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)

if (!tport) {
/* We are not logged in with the nport, log and drop... */
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Received LOGO from an nport not logged in: 0x%x",
nport_id);
return;
}
if (tport->fcid != nport_id) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Received LOGO with invalid target port fcid: 0x%x",
nport_id);
return;
}
if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"tport fcid 0x%x: Canceling disc timer\n",
tport->fcid);
fnic_del_tport_timer_sync();
@@ -3325,7 +3325,7 @@ fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if ((iport->state == FNIC_IPORT_STATE_READY)
&& (fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT)
&& (fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Sending GPNFT in response to LOGO from Target:0x%x",
nport_id);
fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
@@ -3338,7 +3338,7 @@ fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
fdls_send_logo_resp(iport, &logo->fchdr);
if ((fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT) &&
(fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Sending GPNFT in response to LOGO from Target:0x%x",
nport_id);
fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
@@ -3361,11 +3361,11 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)

atomic64_inc(&iport->iport_stats.num_rscns);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS process RSCN %p", iport);

if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS RSCN received in state(%d). Dropping",
fdls_get_state(fdls));
return;
@@ -3376,21 +3376,21 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if ((rscn->payload_len % 4 != 0) || (rscn->payload_len < 8)
|| (rscn->payload_len > 1024) || (rscn->page_len != 4)) {
num_ports = 0;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RSCN payload_len: 0x%x page_len: 0x%x",
rscn->payload_len, rscn->page_len);
/* if this happens then we need to send ADISC to all the tports. */
list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
if (tport->state == FDLS_TGT_STATE_READY)
tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RSCN for port id: 0x%x", tport->fcid);
}
} else {
num_ports = (rscn->payload_len - 4) / rscn->page_len;
rscn_port = (struct fc_rscn_port_s *) (rscn + 1);
}
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RSCN received for num_ports: %d payload_len: %d page_len: %d ",
num_ports, rscn->payload_len, rscn->page_len);

@@ -3405,7 +3405,7 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
memcpy(fcid, rscn_port->port_id, 3);

nport_id = ntoh24(fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RSCN event: 0x%x for 0x%x", rscn_port->rscn_evt_q,
nport_id);
rscn_port++;
@@ -3417,14 +3417,14 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
if (tport->state == FDLS_TGT_STATE_READY)
tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RSCN for port id: 0x%x", tport->fcid);
}
break;
}
tport = fnic_find_tport_by_fcid(iport, nport_id);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"RSCN port id list: 0x%x", nport_id);

if (!tport) {
@@ -3435,7 +3435,7 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FDLS process RSCN sending GPN_FT %p", iport);
fdls_send_gpn_ft(iport, FDLS_STATE_RSCN_GPN_FT);
fdls_send_rscn_resp(iport, fchdr);
@@ -3446,8 +3446,8 @@ void fnic_fdls_disc_start(struct fnic_iport_s *iport)
struct fnic *fnic = iport->fnic;

if (IS_FNIC_FCP_INITIATOR(fnic)) {
- fc_host_fabric_name(iport->fnic->lport->host) = 0;
- fc_host_post_event(iport->fnic->lport->host, fc_get_event_number(),
+ fc_host_fabric_name(iport->fnic->host) = 0;
+ fc_host_post_event(iport->fnic->host, fc_get_event_number(),
FCH_EVT_LIPRESET, 0);
}

@@ -3478,20 +3478,20 @@ fdls_process_adisc_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
uint16_t oxid;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Process ADISC request %d", iport->fnic->fnic_num);

fcid = FNIC_GET_S_ID(fchdr);
tgt_fcid = ntoh24(fcid);
tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
if (!tport) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"tport for fcid: 0x%x not found. Dropping ADISC req.",
tgt_fcid);
return;
}
if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Dropping ADISC req from fcid: 0x%x in iport state: %d",
tgt_fcid, iport->state);
return;
@@ -3502,10 +3502,10 @@ fdls_process_adisc_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)

if ((frame_wwnn != tport->wwnn) || (frame_wwpn != tport->wwpn)) {
/* send reject */
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"ADISC req from fcid: 0x%x mismatch wwpn: 0x%llx wwnn: 0x%llx",
tgt_fcid, frame_wwpn, frame_wwnn);
- FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"local tport wwpn: 0x%llx wwnn: 0x%llx. Sending RJT",
tport->wwpn, tport->wwnn);

@@ -3569,7 +3569,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if (iport->fcid)
if (fdls_get_state(fabric) > FDLS_STATE_FABRIC_FLOGI) {
if ((iport->fcid != d_id) || (!FNIC_FC_FRAME_CS_CTL(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"invalid frame received. Dropping frame");
return -1;
}
@@ -3579,7 +3579,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if ((fchdr->r_ctl == FNIC_BA_ACC_RCTL)
|| (fchdr->r_ctl == FNIC_BA_RJT_RCTL)) {
if (!(FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received ABTS invalid frame. Dropping frame");
return -1;

@@ -3587,7 +3587,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
return FNIC_BLS_ABTS_RSP;
}
if ((fchdr->r_ctl == FC_ABTS_RCTL) && (FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Receiving Abort Request from s_id: 0x%x", s_id);
return FNIC_BLS_ABTS_REQ;
}
@@ -3599,7 +3599,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
|| (!FNIC_FC_FRAME_UNSOLICITED(fchdr))
|| (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received LOGO invalid frame. Dropping frame");
return -1;
}
@@ -3608,7 +3608,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
|| (!FNIC_FC_FRAME_TYPE_ELS(fchdr))
|| (!FNIC_FC_FRAME_UNSOLICITED(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received RSCN invalid FCTL. Dropping frame");
return -1;
}
@@ -3626,7 +3626,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
case FC_ELS_RRQ_REQ:
return FNIC_ELS_RRQ;
default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unsupported frame (type:0x%02x) from fcid: 0x%x",
type, s_id);
return FNIC_ELS_UNSUPPORTED_REQ;
@@ -3637,7 +3637,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if ((ntohs(oxid) >= FDLS_PLOGI_OXID_BASE)
&& (ntohs(oxid) < FDLS_PRLI_OXID_BASE)) {
if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping Unknown frame in PLOGI exchange range type: 0x%x.",
fchdr->type);
return -1;
@@ -3647,7 +3647,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if ((ntohs(oxid) >= FDLS_PRLI_OXID_BASE)
&& (ntohs(oxid) < FDLS_ADISC_OXID_BASE)) {
if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping Unknown frame in PRLI exchange range type: 0x%x.",
fchdr->type);
return -1;
@@ -3658,7 +3658,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if ((ntohs(oxid) >= FDLS_ADISC_OXID_BASE)
&& (ntohs(oxid) < FDLS_TGT_OXID_POOL_END)) {
if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping Unknown frame in ADISC exchange range type: 0x%x.",
fchdr->type);
return -1;
@@ -3679,7 +3679,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if (type == FC_LS_ACC) {
if ((s_id != FC_DOMAIN_CONTR)
|| (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown frame. Dropping frame");
return -1;
}
@@ -3690,7 +3690,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if (type == FC_LS_ACC) {
if ((s_id != FC_DIR_SERVER)
|| (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown frame. Dropping frame");
return -1;
}
@@ -3707,7 +3707,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
if (type == FC_LS_ACC) {
if ((s_id != FC_FABRIC_CONTROLLER)
|| (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown frame. Dropping frame");
return -1;
}
@@ -3716,21 +3716,21 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,

case FNIC_RPN_REQ_OXID:
if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown frame. Dropping frame");
return -1;
}
return FNIC_FABRIC_RPN_RSP;
case FNIC_RFT_REQ_OXID:
if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown frame. Dropping frame");
return -1;
}
return FNIC_FABRIC_RFT_RSP;
case FNIC_RFF_REQ_OXID:
if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown frame. Dropping frame");
return -1;
}
@@ -3738,7 +3738,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,

case FNIC_GPN_FT_OXID:
if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown frame. Dropping frame");
return -1;
}
@@ -3746,7 +3746,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,

default:
/* Drop the Rx frame and log/stats it */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Solicited response: unknown OXID: 0x%x", oxid);
return -1;
}
@@ -3812,7 +3812,7 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
break;
case FNIC_TPORT_LOGO_RSP:
/* Logo response from tgt which we have deleted */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Logo response from tgt: 0x%x",
ntoh24(fchdr->sid));
break;
@@ -3857,7 +3857,7 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
fdls_process_fdmi_reg_ack(iport, fchdr);
break;
default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Received unknown FCoE frame of len: %d. Dropping frame", len);
break;
}
@@ -3875,7 +3875,7 @@ void fnic_fdls_link_down(struct fnic_iport_s *iport)
struct fnic_tport_s *tport, *next;
struct fnic *fnic = iport->fnic;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS processing link down", iport->fcid);

fdls_set_state((&iport->fabric), FDLS_STATE_LINKDOWN);
@@ -3888,7 +3888,7 @@ void fnic_fdls_link_down(struct fnic_iport_s *iport)
fdls_init_tgt_oxid_pool(iport);

list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"removing rport: 0x%x", tport->fcid);
fdls_delete_tport(iport, tport);
}
@@ -3899,7 +3899,7 @@ void fnic_fdls_link_down(struct fnic_iport_s *iport)
iport->fabric.fdmi_pending = 0;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"0x%x: FDLS finish processing link down", iport->fcid);
}

diff --git a/drivers/scsi/fnic/fip.c b/drivers/scsi/fnic/fip.c
index 0c4a412cfd7b..73a6d9d9c180 100644
--- a/drivers/scsi/fnic/fip.c
+++ b/drivers/scsi/fnic/fip.c
@@ -42,7 +42,7 @@ void fnic_fcoe_reset_vlans(struct fnic *fnic)
}

spin_unlock_irqrestore(&fnic->vlans_lock, flags);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Reset vlan complete\n");
}

@@ -63,17 +63,17 @@ void fnic_fcoe_send_vlan_req(struct fnic *fnic)
int fr_len;
struct fip_vlan_req_s vlan_req;

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Enter send vlan req\n");
fnic_fcoe_reset_vlans(fnic);

fnic->set_vlan(fnic, 0);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"set vlan done\n");

fr_len = sizeof(struct fip_vlan_req_s);

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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]);
@@ -87,12 +87,12 @@ void fnic_fcoe_send_vlan_req(struct fnic *fnic)
iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;

fnic_send_fip_frame(iport, &vlan_req, fr_len);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"vlan req sent\n");

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->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fip timer set\n");
}

@@ -119,11 +119,11 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic,
struct fip_vlan_desc_s *vlan_desc;
unsigned long flags;

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p got vlan resp\n", fnic);

desc_len = ntohs(vlan_notif->fip.desc_len);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"desc_len %d\n", desc_len);

spin_lock_irqsave(&fnic->vlans_lock, flags);
@@ -136,20 +136,20 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic,

if (vlan_desc->type == FIP_TYPE_VLAN) {
if (vlan_desc->len != 1) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Invalid descriptor length(%x) in VLan response\n",
vlan_desc->len);

}
num_vlan++;
vid = ntohs(vlan_desc->vlan);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"process_vlan_resp: FIP VLAN %d\n", vid);
vlan = kmalloc(sizeof(*vlan), GFP_ATOMIC);

if (!vlan) {
/* retry from timer */
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Mem Alloc failure\n");
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
goto out;
@@ -160,7 +160,7 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic,
list_add_tail(&vlan->list, &fnic->vlan_list);
break;
} else {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Invalid descriptor type(%x) in VLan response\n",
vlan_desc->type);
/*
@@ -175,7 +175,7 @@ void fnic_fcoe_process_vlan_resp(struct fnic *fnic,
/* any VLAN descriptors present ? */
if (num_vlan == 0) {
atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p No VLAN descriptors in FIP VLAN response\n",
fnic);
}
@@ -202,7 +202,7 @@ void fnic_fcoe_start_fcf_discovery(struct fnic *fnic)
int fr_len;
struct fip_discovery_s disc_sol;

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p start fcf discovery\n", fnic);
fr_len = sizeof(struct fip_discovery_s);
memset(iport->selected_fcf.fcf_mac, 0, ETH_ALEN);
@@ -220,7 +220,7 @@ void fnic_fcoe_start_fcf_discovery(struct fnic *fnic)
fcs_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FCS_TOV);
mod_timer(&fnic->retry_fip_timer, round_jiffies(fcs_tov));

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p Started FCF discovery", fnic);

}
@@ -252,14 +252,14 @@ void fnic_fcoe_fip_discovery_resp(struct fnic *fnic,

if (iport->fip.state == FDLS_FIP_FCF_DISCOVERY_STARTED) {
if (ntohs(disc_adv->fip.flags) & FIP_FLAG_S) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p Solicited adv\n", fnic);

if ((disc_adv->prio_desc.priority <
iport->selected_fcf.fcf_priority)
&& (ntohs(disc_adv->fip.flags) & FIP_FLAG_A)) {

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p FCF Available\n", fnic);
memcpy(iport->selected_fcf.fcf_mac, disc_adv->mac_desc.mac,
ETH_ALEN);
@@ -267,7 +267,7 @@ void fnic_fcoe_fip_discovery_resp(struct fnic *fnic,
disc_adv->prio_desc.priority;
iport->selected_fcf.fka_adv_period =
ntohl(disc_adv->fka_adv_desc.fka_adv);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"adv time %d",
iport->selected_fcf.fka_adv_period);
iport->selected_fcf.ka_disabled =
@@ -284,7 +284,7 @@ void fnic_fcoe_fip_discovery_resp(struct fnic *fnic,
!= ntohl(disc_adv->fka_adv_desc.fka_adv)) {
iport->selected_fcf.fka_adv_period =
ntohl(disc_adv->fka_adv_desc.fka_adv);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host,
fnic->fnic_num, "change fka to %d",
iport->selected_fcf.fka_adv_period);
}
@@ -349,7 +349,7 @@ void fnic_fcoe_start_flogi(struct fnic *fnic)
u64 flogi_tov;

fr_len = sizeof(struct fip_flogi_s);
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p Start fip FLOGI\n", fnic);

memcpy(&flogi_req, &fip_flogi_tmpl, fr_len);
@@ -390,11 +390,11 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,

struct fnic_stats *fnic_stats = &fnic->fnic_stats;

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p FIP FLOGI rsp\n", fnic);
desc_len = ntohs(flogi_rsp->fip.desc_len);
if (desc_len != 38) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Invalid Descriptor List len (%x). Dropping frame\n",
desc_len);
return;
@@ -405,7 +405,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
&& (flogi_rsp->rsp_desc.len == 36))
|| !((flogi_rsp->mac_desc.type == 2)
&& (flogi_rsp->mac_desc.len == 2))) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping frame invalid type and len mix\n");
return;
}
@@ -416,7 +416,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
|| (s_id != 0xFFFFFE)
|| (flogi_rsp->rsp_desc.els.fchdr.ox_id != FNIC_FLOGI_OXID)
|| (flogi_rsp->rsp_desc.els.fchdr.type != 0x01)) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping invalid frame: s_id %x F %x R %x t %x OX_ID %x\n",
s_id,
flogi_rsp->rsp_desc.els.fchdr.f_ctl,
@@ -427,7 +427,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
}

if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p rsp for pending FLOGI\n", fnic);

del_timer_sync(&fnic->retry_fip_timer);
@@ -435,7 +435,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
if ((ntohs(flogi_rsp->fip.desc_len) == 38)
&& (flogi_rsp->rsp_desc.els.command == FC_LS_ACC)) {

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p FLOGI success\n", fnic);
memcpy(iport->fpma, flogi_rsp->mac_desc.mac, ETH_ALEN);
iport->fcid = ntoh24(flogi_rsp->rsp_desc.els.fchdr.did);
@@ -449,7 +449,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
vnic_dev_add_addr(fnic->vdev, flogi_rsp->mac_desc.mac);

if (fnic_fdls_register_portid(iport, iport->fcid, NULL) != 0) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p flogi registration failed\n",
fnic);
return;
@@ -457,7 +457,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,

iport->fip.state = FDLS_FIP_FLOGI_COMPLETE;
iport->state = FNIC_IPORT_STATE_FABRIC_DISC;
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport->state:%d\n", iport->state);
fnic_fdls_disc_start(iport);
if (!((iport->selected_fcf.ka_disabled)
@@ -501,7 +501,7 @@ void fnic_common_fip_cleanup(struct fnic *fnic)

if (!iport->usefip)
return;
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p fip cleanup\n", fnic);

iport->fip.state = FDLS_FIP_INIT;
@@ -546,7 +546,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *fiph)
int found = FALSE;
int max_count = 0;

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p clear virtual link handler\n", fnic);

if (!
@@ -554,7 +554,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *fiph)
&& (cvl_msg->fcf_mac_desc.len == 2))
|| !((cvl_msg->name_desc.type == 4) && (cvl_msg->name_desc.len == 3))) {

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"invalid mix: ft %x fl %x ndt %x ndl %x",
cvl_msg->fcf_mac_desc.type, cvl_msg->fcf_mac_desc.len,
cvl_msg->name_desc.type, cvl_msg->name_desc.len);
@@ -567,7 +567,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *fiph)
if (!((cvl_msg->vn_ports_desc[i].type == 11)
&& (cvl_msg->vn_ports_desc[i].len == 5))) {

- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Invalid type and len mix type: %d len: %d\n",
cvl_msg->vn_ports_desc[i].type,
cvl_msg->vn_ports_desc[i].len);
@@ -589,12 +589,12 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *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->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Rthr waited too long. Skipping handle link event %p\n",
fnic);
return;
}
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic reset in progress. Link event needs to wait %p",
fnic);
}
@@ -647,7 +647,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->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FIP timeout\n");

if (iport->fip.state == FDLS_FIP_VLAN_DISCOVERY_STARTED) {
@@ -655,7 +655,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->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FCF Discovery timeout\n");
if (memcmp(iport->selected_fcf.fcf_mac, zmac, ETH_ALEN) != 0) {

@@ -675,12 +675,12 @@ void fnic_work_on_fip_timer(struct work_struct *work)
mod_timer(&fnic->fcs_ka_timer, round_jiffies(fcf_tov));
}
} else {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FCF Discovery timeout\n");
fnic_vlan_discovery_timeout(fnic);
}
} else if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
- FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI timeout\n");
if (iport->fip.flogi_retry < fnic->config.flogi_retries)
fnic_fcoe_start_flogi(fnic);
@@ -871,7 +871,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->lport->host, fnic->fnic_num,
+ FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p fcs ka timeout\n", fnic);

fnic_common_fip_cleanup(fnic);
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 7480fb11a89b..1c3d794ecd65 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -10,8 +10,10 @@
#include <linux/netdevice.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
-#include <scsi/libfc.h>
-#include <scsi/libfcoe.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/fc_frame.h>
#include "fnic_io.h"
#include "fnic_res.h"
#include "fnic_trace.h"
@@ -342,8 +344,6 @@ struct fnic {
enum fnic_role_e role;
struct fnic_iport_s iport;
struct Scsi_Host *host;
- struct fc_lport *lport;
- struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
struct vnic_dev_bar bar0;

struct fnic_msix_entry msix[FNIC_MSIX_INTR_MAX];
@@ -376,9 +376,6 @@ struct fnic {
u32 vlan_hw_insert:1; /* let hw insert the tag */
u32 in_remove:1; /* fnic device in removal */
u32 stop_rx_link_events:1; /* stop proc. rx frames, link events */
- u32 link_events:1; /* set when we get any link event*/
-
- struct completion *remove_wait; /* device remove thread blocks */

struct completion *fw_reset_done;
u32 reset_in_progress;
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c
index 3748bbe190f7..caee32bc9190 100644
--- a/drivers/scsi/fnic/fnic_debugfs.c
+++ b/drivers/scsi/fnic/fnic_debugfs.c
@@ -682,7 +682,7 @@ int fnic_stats_debugfs_init(struct fnic *fnic)
int rc = -1;
char name[16];

- snprintf(name, sizeof(name), "host%d", fnic->lport->host->host_no);
+ snprintf(name, sizeof(name), "host%d", fnic->host->host_no);

if (!fnic_stats_debugfs_root) {
pr_debug("fnic_stats root doesn't exist\n");
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index b516144247fa..2e4147b11d9f 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -16,7 +16,8 @@
#include <scsi/fc/fc_els.h>
#include <scsi/fc/fc_fcoe.h>
#include <scsi/fc_frame.h>
-#include <scsi/libfc.h>
+#include <linux/etherdevice.h>
+#include <scsi/scsi_transport_fc.h>
#include "fnic_io.h"
#include "fnic.h"
#include "fnic_fip.h"
@@ -57,7 +58,7 @@ uint8_t FCOE_ALL_FCF_MAC[6] = { 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe };
static inline void fnic_fdls_set_fcoe_srcmac(struct fnic *fnic,
uint8_t *src_mac)
{
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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]);
@@ -72,7 +73,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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]);
@@ -100,7 +101,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"link up: %d, usefip: %d", linkup, iport->usefip);

spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
@@ -108,12 +109,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport->state: %d", iport->state);
fnic_fdls_disc_start(iport);
}
@@ -143,13 +144,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"learn fcoe: dst_mac: %02x:%02x:%02x:%02x:%02x:%02x",
ethhdr->dst_mac[0], ethhdr->dst_mac[1],
ethhdr->dst_mac[2], ethhdr->dst_mac[3],
ethhdr->dst_mac[4], ethhdr->dst_mac[5]);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"learn fcoe: fc_mac: %02x:%02x:%02x:%02x:%02x:%02x",
fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
fcmac[5]);
@@ -167,7 +168,7 @@ void fnic_fdls_init(struct fnic *fnic, int usefip)
iport->fnic = fnic;
iport->usefip = usefip;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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]);
@@ -186,14 +187,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Stop link rx events\n");
return;
}
@@ -202,10 +203,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic in transitional state: %d. link up: %d ignored",
fnic->state, vnic_dev_link_status(fnic->vdev));
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Current link status: %d iport state: %d\n",
fnic->link_status, fnic->iport.state);
return;
@@ -217,36 +218,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"waiting for reset completion\n");
wait_for_completion_timeout(&fnic->reset_completion_wait,
msecs_to_jiffies(5000));
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"old link status: %d link status: %d\n",
old_link_status, (int) fnic->link_status);
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"old down count %d down count: %d\n",
old_link_down_cnt, (int) fnic->link_down_cnt);
}
@@ -255,36 +256,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"up->down. Link down\n");
fnic_fdls_link_status_change(fnic, 0);

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"up->down. Link down\n");
fnic_fdls_link_status_change(fnic, 0);
}
@@ -293,7 +294,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Marking fnic reset completion\n");
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
}
@@ -324,7 +325,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Cannot process frame in transitional state\n");
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
return;
@@ -354,7 +355,7 @@ void fnic_handle_fip_frame(struct work_struct *work)
struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);

fnic_stats = &fnic->fnic_stats;
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Processing FIP frame\n");

spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
@@ -434,7 +435,7 @@ void fnic_update_mac_locked(struct fnic *fnic, u8 *new)
if (ether_addr_equal(data, new))
return;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Update MAC: %u\n", *new);

if (!is_zero_ether_addr(data) && !ether_addr_equal(data, ctl))
@@ -504,7 +505,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p fcs error. Dropping packet.\n", fnic);
goto drop;
}
@@ -514,21 +515,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Dropping ether_type 0x%x",
ntohs(eh->ether_type));
goto drop;
}
} else {
/* wrong CQ type */
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fcoe %x fcsok %x pkterr %x ffco %x fee %x\n",
fcoe, fcs_ok, packet_error,
fcoe_fnic_crc_ok, fcoe_enc_error);
@@ -538,7 +539,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic->stop_rx_link_events: %d\n",
fnic->stop_rx_link_events);
goto drop;
@@ -550,7 +551,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
kmalloc(sizeof(struct fnic_frame_list),
GFP_ATOMIC);
if (!frame_elem) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unable to alloc frame element of size: %ld\n",
sizeof(struct fnic_frame_list));
goto drop;
@@ -597,7 +598,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->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"fnic_alloc_rq_frame can't alloc"
" frame\n");
}
@@ -623,7 +624,7 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
len = FNIC_FRAME_HT_ROOM;
buf = kmalloc(len, GFP_ATOMIC);
if (!buf) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unable to allocate RQ buffer of size: %d\n", len);
return -ENOMEM;
}
@@ -631,7 +632,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"PCI mapping failed with error %d\n", ret);
goto free_buf;
}
@@ -670,7 +671,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic ctlr frame trace error");
}

@@ -678,7 +679,7 @@ 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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"vnic work queue descriptor is not available");
ret = -1;
goto fnic_send_frame_end;
@@ -706,7 +707,7 @@ fdls_send_fcoe_frame(struct fnic *fnic, void *payload, int payload_sz,

frame = kmalloc(max_framesz, GFP_ATOMIC);
if (!frame) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to allocate frame for flogi\n");
return -ENOMEM;
}
@@ -735,14 +736,14 @@ fdls_send_fcoe_frame(struct fnic *fnic, void *payload, int payload_sz,
&& (fnic->state != FNIC_IN_ETH_MODE)) {
frame_elem = kmalloc(sizeof(struct fnic_frame_list), GFP_ATOMIC);
if (!frame_elem) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to allocate memory for fnic_frame_list: %ld\n",
sizeof(struct fnic_frame_list));
return -ENOMEM;
}
memset(frame_elem, 0, sizeof(struct fnic_frame_list));

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Queuing frame: 0x%p\n", frame);

frame_elem->fp = frame;
@@ -764,7 +765,7 @@ fdls_send_fip_frame(struct fnic *fnic, void *payload, int payload_sz)

frame = kmalloc(max_framesz, GFP_ATOMIC);
if (!frame) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic 0x%p Failed to allocate fip frame\n", fnic);
return -1;
}
@@ -828,7 +829,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Flush queued frames");

list_for_each_entry_safe(cur_frame, next, &fnic->tx_queue, links) {
@@ -846,7 +847,7 @@ fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
struct fnic_eth_hdr_s *ethhdr;
int ret;

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Setting port id: 0x%x fp: 0x%p fnic state: %d", port_id,
fp, fnic->state);

@@ -859,7 +860,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unexpected fnic state while processing FLOGI response\n");
return -1;
}
@@ -870,7 +871,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI registration error ret: %d fnic state: %d\n",
ret, fnic->state);
if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE)
@@ -880,7 +881,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI registration success\n");
return 0;
}
@@ -960,7 +961,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Adding rport fcid: 0x%x", tport->fcid);

ids.node_name = tport->wwnn;
@@ -969,15 +970,15 @@ fnic_fdls_add_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport,
ids.roles = FC_RPORT_ROLE_FCP_TARGET;

spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- rport = fc_remote_port_add(fnic->lport->host, 0, &ids);
+ rport = fc_remote_port_add(fnic->host, 0, &ids);
spin_lock_irqsave(&fnic->fnic_lock, flags);
if (!rport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Failed to add rport for tport: 0x%x", tport->fcid);
return;
}

- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Added rport fcid: 0x%x", tport->fcid);

/* Mimic these assignments in queuecommand to avoid timing issues */
@@ -1016,7 +1017,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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Deregistered and freed tport fcid: 0x%x from scsi transport fc",
tport->fcid);

@@ -1043,7 +1044,7 @@ 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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"removing fcp rport fcid: 0x%x", tport->fcid);
fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINING);
fnic_fdls_remove_tport(&fnic->iport, tport, flags);
@@ -1068,36 +1069,36 @@ 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->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Add rport event");
if (tport->state == FDLS_TGT_STATE_READY) {
fnic_fdls_add_tport(&fnic->iport,
(struct fnic_tport_s *) cur_evt->arg1, flags);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Target not ready. Add rport event dropped: 0x%x",
tport->fcid);
}
break;
case TGT_EV_RPORT_DEL:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Remove rport event");
if (tport->state == FDLS_TGT_STATE_OFFLINING) {
fnic_fdls_remove_tport(&fnic->iport,
(struct fnic_tport_s *) cur_evt->arg1, flags);
} else {
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"remove rport event dropped tport fcid: 0x%x",
tport->fcid);
}
break;
case TGT_EV_TPORT_DELETE:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Delete tport event");
fdls_delete_tport(tport->iport, tport);
break;
default:
- FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Unknown tport event");
break;
}
diff --git a/drivers/scsi/fnic/fnic_isr.c b/drivers/scsi/fnic/fnic_isr.c
index ff85441c6cea..7ed50b11afa6 100644
--- a/drivers/scsi/fnic/fnic_isr.c
+++ b/drivers/scsi/fnic/fnic_isr.c
@@ -7,7 +7,7 @@
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
-#include <scsi/libfc.h>
+#include <scsi/scsi_transport_fc.h>
#include <scsi/fc_frame.h>
#include "vnic_dev.h"
#include "vnic_intr.h"
@@ -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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"rq-array size: %d wq-array size: %d copy-wq array size: %d\n",
n, m, o);
- FNIC_ISR_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"allocated %d MSI-X vectors\n",
vec_count);

if (vec_count > 0) {
if (vec_count < vecs) {
- FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"interrupts number mismatch: vec_count: %d vecs: %d\n",
vec_count, vecs);
if (vec_count < min_irqs) {
- FNIC_ISR_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"intr_count: %d err_intr_offset: %u",
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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_ISR_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Using Legacy Interrupts\n");
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);

diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 6cbea74bc20c..477b09b5dde2 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -22,7 +22,6 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_tcq.h>
-#include <scsi/libfc.h>
#include <scsi/fc_frame.h>

#include "vnic_dev.h"
@@ -251,7 +250,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->lport->host, fnic->fnic_num,
+ FNIC_MAIN_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"fnic: Get vnic stats failed: 0x%x", ret);
return stats;
}
@@ -360,7 +359,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->lport->host, fnic->fnic_num,
+ FNIC_MAIN_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"fnic: Reset vnic stats failed"
" 0x%x", ret);
return;
@@ -572,7 +571,7 @@ static void fnic_scsi_init(struct fnic *fnic)

static int fnic_scsi_drv_init(struct fnic *fnic)
{
- struct Scsi_Host *host = fnic->lport->host;
+ struct Scsi_Host *host = fnic->host;
int err;
struct pci_dev *pdev = fnic->pdev;
struct fnic_iport_s *iport = &fnic->iport;
@@ -658,16 +657,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->lport->host, fnic->fnic_num,
+ FNIC_MAIN_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"intr_mode is not msix\n");
return;
}

- FNIC_MAIN_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_MAIN_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"qmap->nr_queues: %d\n", qmap->nr_queues);

if (l_pdev == NULL) {
- FNIC_MAIN_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_MAIN_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"l_pdev is null\n");
return;
}
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 7603106a98a5..ee5b08b46d9f 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -23,7 +23,6 @@
#include <scsi/scsi_tcq.h>
#include <scsi/fc/fc_els.h>
#include <scsi/fc/fc_fcoe.h>
-#include <scsi/libfc.h>
#include <scsi/fc_frame.h>
#include <scsi/scsi_transport_fc.h>
#include "fnic_io.h"
@@ -174,7 +173,7 @@ unsigned int fnic_count_lun_ioreqs_wq(struct fnic *fnic, u32 hwq,

if (io_req != NULL) {
struct scsi_cmnd *sc =
- scsi_host_find_tag(fnic->lport->host, io_req->tag);
+ scsi_host_find_tag(fnic->host, io_req->tag);

if (!sc)
continue;
@@ -297,11 +296,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Issued fw reset\n");
} else {
fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Failed to issue fw reset\n");
}

@@ -340,13 +339,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FLOGI reg issued fcid 0x%x dest %p\n",
fc_id, gw_mac);
}
@@ -427,7 +426,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic_queue_wq_copy_desc failure - no descriptors\n");
atomic64_inc(&misc_stats->io_cpwq_alloc_failures);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -492,7 +491,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)

rport = starget_to_rport(scsi_target(sc->device));
if (!rport) {
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"returning DID_NO_CONNECT for IO as rport is NULL\n");
sc->result = DID_NO_CONNECT << 16;
done(sc);
@@ -501,7 +500,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)

ret = fc_remote_port_chkready(rport);
if (ret) {
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"rport is not ready\n");
atomic64_inc(&fnic_stats->misc_stats.tport_not_ready);
sc->result = ret;
@@ -515,7 +514,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)

if (iport->state != FNIC_IPORT_STATE_READY) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"returning DID_NO_CONNECT for IO as iport state: %d\n",
iport->state);
sc->result = DID_NO_CONNECT << 16;
@@ -529,13 +528,13 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
rdd_data = rport->dd_data;
tport = rdd_data->tport;
if (!tport || (rdd_data->iport != iport)) {
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"returning DID_BUS_BUSY for IO as tport not found for: 0x%x\n",
rport->port_id);
sc->result = DID_BUS_BUSY << 16;
@@ -558,7 +557,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"returning DID_NO_CONNECT for IO as tport state: %d\n",
tport->state);
sc->result = DID_NO_CONNECT << 16;
@@ -578,7 +577,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)

if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET))) {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"fnic flags FW reset: 0x%lx. Returning SCSI_MLQUEUE_HOST_BUSY\n",
fnic->state_flags);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -720,7 +719,7 @@ int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
atomic_dec(&tport->in_flight);

if (lun0_delay) {
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"LUN0 delay\n");
mdelay(LUN0_DELAY_TIME);
}
@@ -760,12 +759,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"reset cmpl success\n");
/* Ready to send flogi out */
fnic->state = FNIC_IN_ETH_MODE;
} else {
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"reset failed with header status: %s\n",
fnic_fcpio_status_to_str(hdr_status));

@@ -774,7 +773,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
ret = -1;
}
} else {
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Unexpected state while processing reset completion: %s\n",
fnic_state_to_str(fnic->state));
atomic64_inc(&reset_stats->fw_reset_failures);
@@ -826,19 +825,19 @@ 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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"FLOGI reg succeeded\n");
fnic->state = FNIC_IN_FC_MODE;
} else {
FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host, fnic->fnic_num,
+ fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Unexpected fnic state %s while"
" processing flogi reg completion\n",
fnic_state_to_str(fnic->state));
@@ -911,7 +910,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->lport->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3],
+ fnic->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3],
ox_id_tag[4], ox_id_tag[5]);
}

@@ -949,36 +948,36 @@ 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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hdr status: %s Out of range tag\n",
fnic_fcpio_status_to_str(hdr_status));
return;
}
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);

- sc = scsi_host_find_tag(fnic->lport->host, id);
+ sc = scsi_host_find_tag(fnic->host, id);
WARN_ON_ONCE(!sc);
if (!sc) {
atomic64_inc(&fnic_stats->io_stats.sc_null);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- shost_printk(KERN_ERR, fnic->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"icmnd_cmpl sc is null - "
"hdr status = %s tag = 0x%x desc = 0x%p\n",
fnic_fcpio_status_to_str(hdr_status), id, desc);
FNIC_TRACE(fnic_fcpio_icmnd_cmpl_handler,
- fnic->lport->host->host_no, id,
+ fnic->host->host_no, id,
((u64)icmnd_cmpl->_resvd0[1] << 16 |
(u64)icmnd_cmpl->_resvd0[0]),
((u64)hdr_status << 16 |
@@ -1001,7 +1000,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->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"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);
@@ -1028,7 +1027,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"icmnd_cmpl abts pending "
"hdr status = %s tag = 0x%x sc = 0x%p "
"scsi_status = %x residual = %d\n",
@@ -1120,7 +1119,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->lport->host, "hdr status = %s\n",
+ shost_printk(KERN_ERR, fnic->host, "hdr status = %s\n",
fnic_fcpio_status_to_str(hdr_status));
}

@@ -1213,27 +1212,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x cq index: %d ",
hwq, mqtag, tag, cq_index);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hdr status: %s Tag out of range\n",
fnic_fcpio_status_to_str(hdr_status));
return;
@@ -1249,14 +1248,14 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, unsigned int cq_inde
if (io_req)
sc = io_req->sc;
} else {
- sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
+ sc = scsi_host_find_tag(fnic->host, id & FNIC_TAG_MASK);
}

WARN_ON_ONCE(!sc);
if (!sc) {
atomic64_inc(&fnic_stats->io_stats.sc_null);
spin_unlock_irqrestore(&fnic->wq_copy_lock[hwq], flags);
- shost_printk(KERN_ERR, fnic->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n",
fnic_fcpio_status_to_str(hdr_status), tag);
return;
@@ -1268,7 +1267,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->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"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);
@@ -1279,7 +1278,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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));
@@ -1291,7 +1290,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->lport->host,
+ shost_printk(KERN_DEBUG, fnic->host,
"hwq: %d mqtag: 0x%x tag: 0x%x Abort header status: %s\n",
hwq, mqtag, tag,
fnic_fcpio_status_to_str(hdr_status));
@@ -1306,7 +1305,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"abort reject recd. id %d\n",
(int)(id & FNIC_TAG_MASK));
break;
@@ -1341,7 +1340,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"abts cmpl recd. id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
fnic_fcpio_status_to_str(hdr_status));
@@ -1354,11 +1353,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->lport->host,
+ shost_printk(KERN_INFO, fnic->host,
"hwq: %d mqtag: 0x%x tag: 0x%x Waking up abort thread\n",
hwq, mqtag, tag);
} else {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Completing IO\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@@ -1389,7 +1388,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->lport->host,
+ shost_printk(KERN_INFO, fnic->host,
"hwq: %d mqtag: 0x%x tag: 0x%x DR hst: %s\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@@ -1401,7 +1400,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x hst: %s Terminate pending\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@@ -1414,7 +1413,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"dev reset cmpl recd after time out. "
"id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
@@ -1423,7 +1422,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"hwq: %d mqtag: 0x%x tag: 0x%x hst: %s DR completion received\n",
hwq, mqtag,
tag, fnic_fcpio_status_to_str(hdr_status));
@@ -1432,7 +1431,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->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"%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);
@@ -1487,7 +1486,7 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
break;

default:
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"firmware completion type %d\n",
desc->hdr.type);
break;
@@ -1534,14 +1533,14 @@ static void fnic_cleanup_one_io(struct fnic_io_req *io_req,
struct fnic_stats *fnic_stats = &fnic->fnic_stats;

if (!io_req) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"tag: 0x%x hwq: %d ioreq is NULL\n", tag, hwq);
return;
}

tag = io_req->tag;

- sc = scsi_host_find_tag(fnic->lport->host, tag);
+ sc = scsi_host_find_tag(fnic->host, tag);
if (!sc)
return;

@@ -1580,7 +1579,7 @@ static void fnic_cleanup_one_io(struct fnic_io_req *io_req,
mempool_free(io_req, fnic->io_req_pool);

sc->result = DID_TRANSPORT_DISRUPTED << 16;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"tag:0x%x hwq:%d sc duration = %lu DID_TRANSPORT_DISRUPTED\n",
tag, hwq, (jiffies - start_time));

@@ -1613,7 +1612,7 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
struct scsi_cmnd *sc;

io_count = fnic_count_all_ioreqs(fnic);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Outstanding ioreq count: %d active io count: %lld Waiting\n",
io_count,
atomic64_read(&fnic->fnic_stats.io_stats.active_ios));
@@ -1650,7 +1649,7 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
fnic->sw_copy_wq[0].hw_lock_flags);

while ((io_count = fnic_count_all_ioreqs(fnic))) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Outstanding ioreq count: %d active io count: %lld Waiting\n",
io_count,
atomic64_read(&fnic->fnic_stats.io_stats.active_ios));
@@ -1677,7 +1676,7 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
if (id >= fnic->fnic_max_tag_id)
return;

- sc = scsi_host_find_tag(fnic->lport->host, id);
+ sc = scsi_host_find_tag(fnic->host, id);
if (!sc)
return;

@@ -1706,7 +1705,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->lport->host, fnic->fnic_num, "wq_copy_cleanup_handler:"
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num, "wq_copy_cleanup_handler:"
" DID_NO_CONNECT\n");

FNIC_TRACE(fnic_wq_copy_cleanup_handler,
@@ -1750,7 +1749,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"fnic_queue_abort_io_req: failure: no descriptors\n");
atomic64_inc(&misc_stats->abts_cpwq_alloc_failures);
return 1;
@@ -1794,26 +1793,26 @@ static int fnic_rport_exch_terminate_io(struct fnic_io_req *io_req,
abt_tag = tag;
sc = io_req->sc;

- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"tag: 0x%p hwq: %d matching for rport: 0x%x\n", sc, hwq,
port_id);

if (!sc) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"sc is NULL tag: 0x%x hwq: %d\n", tag, hwq);
return TERM_NO_SC;
}

io_req = (struct fnic_io_req *) fnic_priv(sc)->io_req;
if (!io_req) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"ioreq not found sc: 0x%p tag: 0x%x hwq: %d\n", sc,
tag, hwq);
return TERM_IO_REQ_NOT_FOUND;
}

if (io_req->port_id != port_id) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"port id mismatch: pid:0x%x io->pid: 0x%x tag: 0x%x hwq: %d\n",
port_id, io_req->port_id, tag, hwq);
return TERM_ANOTHER_PORT;
@@ -1821,22 +1820,22 @@ static int fnic_rport_exch_terminate_io(struct fnic_io_req *io_req,

if ((fnic_priv(sc)->flags & FNIC_DEVICE_RESET)
&& (!(fnic_priv(sc)->flags & FNIC_DEV_RST_ISSUED))) {
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"dev reset not pending sc 0x%p\n", sc);
}

if (io_req->abts_done) {
- shost_printk(KERN_ERR, fnic->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"%s: io_req->abts_done is set state is %s\n",
__func__,
fnic_ioreq_state_to_str(fnic_priv(sc)->state));
}

if (!(fnic_priv(sc)->flags & FNIC_IO_ISSUED)) {
- shost_printk(KERN_ERR, fnic->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"rport_exch_reset IO not yet issued %p tag 0x%x",
sc, tag);
- shost_printk(KERN_ERR, fnic->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"flags %x state %d\n", fnic_priv(sc)->flags,
fnic_priv(sc)->state);
}
@@ -1846,7 +1845,7 @@ static int fnic_rport_exch_terminate_io(struct fnic_io_req *io_req,
if (fnic_priv(sc)->flags & FNIC_DEVICE_RESET) {
atomic64_inc(&reset_stats->device_reset_terminates);
abt_tag = (tag | FNIC_TAG_DEV_RST);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"dev reset sc 0x%p\n", sc);
}

@@ -1899,7 +1898,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
struct scsi_cmnd *sc;
unsigned long old_state;

- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"fnic rport exchange reset for tport: 0x%06x\n",
port_id);

@@ -1907,7 +1906,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"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));
@@ -1933,7 +1932,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
if (io_req->port_id != port_id)
continue;

- sc = scsi_host_find_tag(fnic->lport->host, io_req->tag);
+ sc = scsi_host_find_tag(fnic->host, io_req->tag);
if (!sc)
continue;

@@ -1973,7 +1972,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
if (sc && (fnic_priv(sc)->state != FNIC_IOREQ_ABTS_PENDING)) {
old_state = fnic_priv(sc)->state;
fnic_priv(sc)->state = FNIC_IOREQ_ABTS_PENDING;
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"sg3 dev rst sc 0x%p sg\n", sc);
if (fnic_rport_exch_terminate_io(io_req, fnic, port_id, 0, 1)
== TERM_IO_BLOCKED) {
@@ -1994,13 +1993,13 @@ 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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"IOs terminated: rport: 0x%x terminated: %d ",
port_id, term_count);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"remaining portid-io-count: %d ",
io_count);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"nosc_count: %d noioreq_count: %d another_port_count: %d\n",
nosc_count, noioreq_count,
another_port_count);
@@ -2122,10 +2121,10 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
tport = rdd_data->tport;

if (!tport) {
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Abort cmd called after tport delete! rport fcid: 0x%x",
rport->port_id);
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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);
@@ -2134,18 +2133,18 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
goto fnic_abort_cmd_end;
}

- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport NOT in READY state");
ret = FAILED;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
@@ -2154,7 +2153,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"tport state: %d\n", tport->state);
ret = FAILED;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
@@ -2205,7 +2204,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"CDB Opcode: 0x%02x Abort issued time: %lu msec\n",
sc->cmnd[0], abt_issued_time);
/*
@@ -2296,7 +2295,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Issuing host reset due to out of order IO\n");

ret = FAILED;
@@ -2344,7 +2343,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Returning from abort cmd type %x %s\n", task_req,
(ret == SUCCESS) ?
"SUCCESS" : "FAILED");
@@ -2385,7 +2384,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"queue_dr_io_req failure - no descriptors\n");
atomic64_inc(&misc_stats->devrst_cpwq_alloc_failures);
ret = -EAGAIN;
@@ -2453,7 +2452,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Found IO in %s on lun\n",
fnic_ioreq_state_to_str(fnic_priv(sc)->state));

@@ -2463,14 +2462,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"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->lport->host,
+ shost_printk(KERN_ERR, fnic->host,
"%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;
@@ -2486,7 +2485,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"dev rst sc 0x%p\n", sc);
}

@@ -2508,7 +2507,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"hwq: %d abt_tag: 0x%lx Abort could not be queued\n",
hwq, abt_tag);
return false;
@@ -2587,7 +2586,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,

iter_data.lr_sc = lr_sc;

- scsi_host_busy_iter(fnic->lport->host,
+ scsi_host_busy_iter(fnic->host,
fnic_pending_aborts_iter, &iter_data);
if (iter_data.ret == FAILED) {
ret = iter_data.ret;
@@ -2600,7 +2599,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
ret = 1;

clean_pending_aborts_end:
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"exit status: %d\n", ret);
return ret;
}
@@ -2650,7 +2649,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"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);
@@ -2658,7 +2657,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"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);
@@ -2667,7 +2666,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"iport NOT in READY state");
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
goto fnic_device_reset_end;
@@ -2675,7 +2674,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"tport state: %d\n", tport->state);
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
goto fnic_device_reset_end;
@@ -2738,7 +2737,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->lport->host, fnic->fnic_num, "TAG %x\n", mqtag);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num, "TAG %x\n", mqtag);

/*
* issue the device reset, if enqueue failed, clean up the ioreq
@@ -2789,13 +2788,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Host reset called for fnic. Exit device reset\n");
io_req->dr_done = NULL;
goto fnic_device_reset_clean;
@@ -2810,7 +2809,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Device reset timed out\n");
fnic_priv(sc)->flags |= FNIC_DEV_RST_TIMED_OUT;
int_to_scsilun(sc->device->lun, &fc_lun);
@@ -2823,7 +2822,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
if (status != FCPIO_SUCCESS) {
spin_lock_irqsave(&fnic->wq_copy_lock[hwq], flags);
FNIC_SCSI_DBG(KERN_DEBUG,
- fnic->lport->host, fnic->fnic_num,
+ fnic->host, fnic->fnic_num,
"Device reset completed - failed\n");
io_req = fnic_priv(sc)->io_req;
goto fnic_device_reset_clean;
@@ -2839,7 +2838,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Device reset failed: Cannot abort all IOs\n");
goto fnic_device_reset_clean;
}
@@ -2893,13 +2892,13 @@ int fnic_device_reset(struct scsi_cmnd *sc)
ret = FAILED;
break;
}
- FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"Cannot clean up all IOs for the LUN\n");
schedule_timeout(msecs_to_jiffies(1000));
count++;
}

- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
"Returning from device reset %s\n",
(ret == SUCCESS) ?
"SUCCESS" : "FAILED");
@@ -2934,13 +2933,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Issuing fnic reset\n");

atomic64_inc(&reset_stats->fnic_resets);
fnic_post_flogo_linkflap(fnic);

- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Returning from fnic reset");

atomic64_inc(&reset_stats->fnic_reset_completions);
@@ -2951,7 +2950,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FC host lip issued");

ret = fnic_host_reset(shost);
@@ -2977,7 +2976,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_WARNING, fnic->host, fnic->fnic_num,
"Firmware reset in progress. Skipping another host reset\n");
return SUCCESS;
}
@@ -3015,7 +3014,7 @@ int fnic_host_reset(struct Scsi_Host *shost)
}
spin_unlock_irqrestore(&fnic->fnic_lock, flags);

- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"host reset return status: %d\n", ret);
return ret;
}
@@ -3055,7 +3054,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"hwq: %d tag: 0x%x Found IO in state: %s on lun\n",
hwq, tag,
fnic_ioreq_state_to_str(fnic_priv(sc)->state));
@@ -3088,7 +3087,7 @@ int fnic_is_abts_pending(struct fnic *fnic, struct scsi_cmnd *lr_sc)
}

/* walk again to check, if IOs are still pending in fw */
- scsi_host_busy_iter(fnic->lport->host,
+ scsi_host_busy_iter(fnic->host,
fnic_abts_pending_iter, &iter_data);

return iter_data.ret;
@@ -3109,7 +3108,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->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
"SCSI error handling: fnic host reset");

ret = fnic_host_reset(shost);
@@ -3130,7 +3129,7 @@ void fnic_scsi_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_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"fnic is in unexpected state: %d for fw_reset\n",
fnic->state);
return;
@@ -3143,7 +3142,7 @@ void fnic_scsi_fcpio_reset(struct fnic *fnic)
fnic->fw_reset_done = &fw_reset_done;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);

- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Issuing fw reset\n");
if (fnic_fw_reset_handler(fnic)) {
spin_lock_irqsave(&fnic->fnic_lock, flags);
@@ -3151,14 +3150,14 @@ void fnic_scsi_fcpio_reset(struct fnic *fnic)
fnic->state = old_state;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
} else {
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Waiting for fw completion\n");
time_remain = wait_for_completion_timeout(&fw_reset_done,
msecs_to_jiffies(FNIC_FW_RESET_TIMEOUT));
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"Woken up after fw completion timeout\n");
if (time_remain == 0) {
- FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
"FW reset completion timed out after %d ms)\n",
FNIC_FW_RESET_TIMEOUT);
}
--
2.31.1


Subject: [PATCH 08/14] scsi: fnic: Add functionality in fnic to support FDLS

Add interfaces in fnic to use FDLS services.
Modify link up and link down functionality to use FDLS.
Replace existing interfaces to handle new functionality
provided by FDLS.
Modify data types of some data members to handle new
functionality.
Add processing of tports and handling of tports.

Reviewed-by: Sesidhar Baddela <[email protected]>
Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
Reviewed-by: Gian Carlo Boffa <[email protected]>
Signed-off-by: Karan Tilak Kumar <[email protected]>
---
drivers/scsi/fnic/fdls_disc.c | 74 +++++
drivers/scsi/fnic/fip.c | 27 +-
drivers/scsi/fnic/fnic.h | 20 +-
drivers/scsi/fnic/fnic_fcs.c | 498 ++++++++++++++++++++++++----------
drivers/scsi/fnic/fnic_main.c | 10 +-
drivers/scsi/fnic/fnic_scsi.c | 127 +++++++--
6 files changed, 587 insertions(+), 169 deletions(-)

diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
index 42127a70c369..952b5924e42b 100644
--- a/drivers/scsi/fnic/fdls_disc.c
+++ b/drivers/scsi/fnic/fdls_disc.c
@@ -239,6 +239,11 @@ static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
int timeout);
static void fdls_tport_timer_callback(struct timer_list *t);

+void fdls_init_tgt_oxid_pool(struct fnic_iport_s *iport)
+{
+ memset(iport->tgt_oxid_pool, 0, FDLS_TGT_OXID_POOL_SZ);
+}
+
static uint16_t fdls_alloc_tgt_oxid(struct fnic_iport_s *iport,
uint16_t base)
{
@@ -2532,6 +2537,12 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,

fnic_fdls_learn_fcoe_macs(iport, rx_frame, fcid);

+ if (fnic_fdls_register_portid(iport, iport->fcid, rx_frame) != 0) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FLOGI registration failed", iport->fcid);
+ break;
+ }
+
memcpy(&fcmac[3], fcid, 3);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"Adding vNIC device MAC addr: %02x:%02x:%02x:%02x:%02x:%02x",
@@ -3402,6 +3413,29 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
fdls_send_rscn_resp(iport, fchdr);
}

+void fnic_fdls_disc_start(struct fnic_iport_s *iport)
+{
+ struct fnic *fnic = iport->fnic;
+
+ if (IS_FNIC_FCP_INITIATOR(fnic)) {
+ fc_host_fabric_name(iport->fnic->lport->host) = 0;
+ fc_host_post_event(iport->fnic->lport->host, fc_get_event_number(),
+ FCH_EVT_LIPRESET, 0);
+ }
+
+ if (!iport->usefip) {
+ if (iport->flags & FNIC_FIRST_LINK_UP) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ fnic_scsi_fcpio_reset(iport->fnic);
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+
+ iport->flags &= ~FNIC_FIRST_LINK_UP;
+ }
+ fnic_fdls_start_flogi(iport);
+ } else
+ fnic_fdls_start_plogi(iport);
+}
+
static void
fdls_process_adisc_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
{
@@ -3801,3 +3835,43 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
}
}

+
+void fnic_fdls_disc_init(struct fnic_iport_s *iport)
+{
+ fdls_init_tgt_oxid_pool(iport);
+ fdls_set_state((&iport->fabric), FDLS_STATE_INIT);
+}
+
+void fnic_fdls_link_down(struct fnic_iport_s *iport)
+{
+ struct fnic_tport_s *tport, *next;
+ struct fnic *fnic = iport->fnic;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS processing link down", iport->fcid);
+
+ fdls_set_state((&iport->fabric), FDLS_STATE_LINKDOWN);
+ iport->fabric.flags = 0;
+
+ if (IS_FNIC_FCP_INITIATOR(fnic)) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ fnic_scsi_fcpio_reset(iport->fnic);
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+ fdls_init_tgt_oxid_pool(iport);
+
+ list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "removing rport: 0x%x", tport->fcid);
+ fdls_delete_tport(iport, tport);
+ }
+ }
+
+ if ((fnic_fdmi_support == 1) && (iport->fabric.fdmi_pending > 0)) {
+ del_timer_sync(&iport->fabric.fdmi_timer);
+ iport->fabric.fdmi_pending = 0;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "0x%x: FDLS finish processing link down", iport->fcid);
+}
+
diff --git a/drivers/scsi/fnic/fip.c b/drivers/scsi/fnic/fip.c
index 8d4f6b98407b..0c4a412cfd7b 100644
--- a/drivers/scsi/fnic/fip.c
+++ b/drivers/scsi/fnic/fip.c
@@ -459,6 +459,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
iport->state = FNIC_IPORT_STATE_FABRIC_DISC;
FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"iport->state:%d\n", iport->state);
+ fnic_fdls_disc_start(iport);
if (!((iport->selected_fcf.ka_disabled)
|| (iport->selected_fcf.fka_adv_period == 0))) {
u64 tov;
@@ -543,6 +544,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *fiph)
struct fip_cvl_s *cvl_msg = (struct fip_cvl_s *) fiph;
int i;
int found = FALSE;
+ int max_count = 0;

FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
"fnic 0x%p clear virtual link handler\n", fnic);
@@ -580,6 +582,26 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *fiph)
return;
fnic_common_fip_cleanup(fnic);

+ while (fnic->reset_in_progress == IN_PROGRESS) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ wait_for_completion_timeout(&fnic->reset_completion_wait,
+ msecs_to_jiffies(5000));
+ 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->lport->host, fnic->fnic_num,
+ "Rthr waited too long. Skipping handle link event %p\n",
+ fnic);
+ return;
+ }
+ FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic reset in progress. Link event needs to wait %p",
+ fnic);
+ }
+ fnic->reset_in_progress = IN_PROGRESS;
+ fnic_fdls_link_down(iport);
+ fnic->reset_in_progress = NOT_IN_PROGRESS;
+ complete(&fnic->reset_completion_wait);
fnic_fcoe_send_vlan_req(fnic);
}
}
@@ -637,8 +659,10 @@ void fnic_work_on_fip_timer(struct work_struct *work)
"FCF Discovery timeout\n");
if (memcmp(iport->selected_fcf.fcf_mac, zmac, ETH_ALEN) != 0) {

- if (iport->flags & FNIC_FIRST_LINK_UP)
+ if (iport->flags & FNIC_FIRST_LINK_UP) {
+ fnic_scsi_fcpio_reset(iport->fnic);
iport->flags &= ~FNIC_FIRST_LINK_UP;
+ }

fnic_fcoe_start_flogi(fnic);
if (!((iport->selected_fcf.ka_disabled)
@@ -852,6 +876,7 @@ void fnic_work_on_fcs_ka_timer(struct work_struct *work)

fnic_common_fip_cleanup(fnic);
spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+ fnic_fdls_link_down(iport);
iport->state = FNIC_IPORT_STATE_FIP;
spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);

diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 0c7926627663..5fbd5cf23bfe 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -79,6 +79,7 @@

#define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)

+#define FNIC_FW_RESET_TIMEOUT 60000 /* mSec */
/* Retry supported by rport (returned by PRLI service parameters) */
#define FNIC_FC_RP_FLAGS_RETRY 0x1

@@ -200,6 +201,12 @@ static inline u64 fnic_flags_and_state(struct scsi_cmnd *cmd)
#define fnic_clear_state_flags(fnicp, st_flags) \
__fnic_set_state_flags(fnicp, st_flags, 1)

+enum reset_states {
+ NOT_IN_PROGRESS = 0,
+ IN_PROGRESS,
+ RESET_ERROR
+};
+
extern unsigned int fnic_fdmi_support;
extern unsigned int fnic_log_level;
extern unsigned int io_completions;
@@ -352,6 +359,7 @@ struct fnic {
unsigned int wq_count;
unsigned int cq_count;

+ struct completion reset_completion_wait;
struct mutex sgreset_mutex;
spinlock_t sgreset_lock; /* lock for sgreset */
struct scsi_cmnd *sgreset_sc;
@@ -369,6 +377,8 @@ struct fnic {

struct completion *remove_wait; /* device remove thread blocks */

+ struct completion *fw_reset_done;
+ u32 reset_in_progress;
atomic_t in_flight; /* io counter */
bool internal_reset_inprogress;
u32 _reserved; /* fill hole */
@@ -382,6 +392,7 @@ struct fnic {
u64 fcp_input_bytes; /* internal statistic */
u64 fcp_output_bytes; /* internal statistic */
u32 link_down_cnt;
+ u32 soft_reset_count;
int link_status;

struct list_head list;
@@ -404,7 +415,7 @@ struct fnic {
struct work_struct link_work;
struct work_struct frame_work;
struct work_struct flush_work;
- struct sk_buff_head frame_queue;
+ struct list_head frame_queue;
struct list_head tx_queue;
struct work_struct tport_work;
struct list_head tport_event_list;
@@ -464,6 +475,7 @@ int fnic_request_intr(struct fnic *fnic);
int fnic_send(struct fc_lport *, struct fc_frame *);
void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf);
void fnic_handle_frame(struct work_struct *work);
+void fnic_tport_event_handler(struct work_struct *work);
void fnic_handle_link(struct work_struct *work);
void fnic_handle_event(struct work_struct *work);
int fnic_rq_cmpl_handler(struct fnic *fnic, int);
@@ -475,7 +487,8 @@ void fnic_update_mac_locked(struct fnic *, u8 *new);
int fnic_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
int fnic_abort_cmd(struct scsi_cmnd *);
int fnic_device_reset(struct scsi_cmnd *);
-int fnic_host_reset(struct scsi_cmnd *);
+int fnic_eh_host_reset_handler(struct scsi_cmnd *sc);
+int fnic_host_reset(struct Scsi_Host *shost);
int fnic_reset(struct Scsi_Host *);
void fnic_scsi_cleanup(struct fc_lport *);
void fnic_scsi_abort_io(struct fc_lport *);
@@ -510,5 +523,8 @@ void fnic_dump_fchost_stats(struct Scsi_Host *, struct fc_host_statistics *);
void fnic_free_txq(struct list_head *head);
int fnic_get_desc_by_devid(struct pci_dev *pdev, char **desc,
char **subsys_desc);
+void fnic_fdls_link_status_change(struct fnic *fnic, int linkup);
+void fnic_delete_fcp_tports(struct fnic *fnic);
+void fnic_flush_tport_event_list(struct fnic *fnic);

#endif /* _FNIC_H_ */
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 8a7c471d3ff5..6f5414fba0ee 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -25,6 +25,8 @@
#include "cq_enet_desc.h"
#include "cq_exch_desc.h"

+#define MAX_RESET_WAIT_COUNT 64
+
extern struct workqueue_struct *fnic_fip_queue;
struct workqueue_struct *fnic_event_queue;

@@ -78,6 +80,39 @@ static inline void fnic_fdls_set_fcoe_dstmac(struct fnic *fnic,
memcpy(fnic->iport.fcfmac, dst_mac, 6);
}

+void fnic_fdls_link_status_change(struct fnic *fnic, int linkup)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "link up: %d, usefip: %d", linkup, iport->usefip);
+
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+
+ if (linkup) {
+ if (iport->usefip) {
+ iport->state = FNIC_IPORT_STATE_FIP;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
+ "iport->state: %d", iport->state);
+ fnic_fdls_disc_start(iport);
+ }
+ } else {
+ iport->state = FNIC_IPORT_STATE_LINK_WAIT;
+ if (!is_zero_ether_addr(iport->fpma))
+ vnic_dev_del_addr(fnic->vdev, iport->fpma);
+ fnic_common_fip_cleanup(fnic);
+ fnic_fdls_link_down(iport);
+
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+}
+
+
/*
* FPMA can be either taken from ethhdr(dst_mac) or flogi resp
* or derive from FC_MAP and FCID combination. While it should be
@@ -107,147 +142,144 @@ void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
fnic_fdls_set_fcoe_dstmac(fnic, ethhdr->src_mac);
}

+void fnic_fdls_init(struct fnic *fnic, int usefip)
+{
+ struct fnic_iport_s *iport = &fnic->iport;
+
+ /* Initialize iPort structure */
+ iport->state = FNIC_IPORT_STATE_INIT;
+ iport->fnic = fnic;
+ iport->usefip = usefip;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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);
+}
+
void fnic_handle_link(struct work_struct *work)
{
struct fnic *fnic = container_of(work, struct fnic, link_work);
- unsigned long flags;
int old_link_status;
u32 old_link_down_cnt;
- u64 old_port_speed, new_port_speed;
+ int max_count = 0;

- spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (vnic_dev_get_intr_mode(fnic->vdev) != VNIC_DEV_INTR_MODE_MSI)
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Interrupt mode is not MSI\n");

- fnic->link_events = 1; /* less work to just set everytime*/
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);

if (fnic->stop_rx_link_events) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Stop link rx events\n");
+ return;
+ }
+
+ /* Do not process if the fnic is already in transitional state */
+ 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->lport->host, fnic->fnic_num,
+ "fnic in transitional state: %d. link up: %d ignored",
+ fnic->state, vnic_dev_link_status(fnic->vdev));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Current link status: %d iport state: %d\n",
+ fnic->link_status, fnic->iport.state);
return;
}

old_link_down_cnt = fnic->link_down_cnt;
old_link_status = fnic->link_status;
- old_port_speed = atomic64_read(
- &fnic->fnic_stats.misc_stats.current_port_speed);
-
fnic->link_status = vnic_dev_link_status(fnic->vdev);
fnic->link_down_cnt = vnic_dev_link_down_cnt(fnic->vdev);

- new_port_speed = vnic_dev_port_speed(fnic->vdev);
- atomic64_set(&fnic->fnic_stats.misc_stats.current_port_speed,
- new_port_speed);
- if (old_port_speed != new_port_speed)
+ while (fnic->reset_in_progress == IN_PROGRESS) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
- "Current vnic speed set to: %llu\n",
- new_port_speed);
-
- switch (vnic_dev_port_speed(fnic->vdev)) {
- case DCEM_PORTSPEED_10G:
- fc_host_speed(fnic->lport->host) = FC_PORTSPEED_10GBIT;
- fnic->lport->link_supported_speeds = FC_PORTSPEED_10GBIT;
- break;
- case DCEM_PORTSPEED_20G:
- fc_host_speed(fnic->lport->host) = FC_PORTSPEED_20GBIT;
- fnic->lport->link_supported_speeds = FC_PORTSPEED_20GBIT;
- break;
- case DCEM_PORTSPEED_25G:
- fc_host_speed(fnic->lport->host) = FC_PORTSPEED_25GBIT;
- fnic->lport->link_supported_speeds = FC_PORTSPEED_25GBIT;
- break;
- case DCEM_PORTSPEED_40G:
- case DCEM_PORTSPEED_4x10G:
- fc_host_speed(fnic->lport->host) = FC_PORTSPEED_40GBIT;
- fnic->lport->link_supported_speeds = FC_PORTSPEED_40GBIT;
- break;
- case DCEM_PORTSPEED_100G:
- fc_host_speed(fnic->lport->host) = FC_PORTSPEED_100GBIT;
- fnic->lport->link_supported_speeds = FC_PORTSPEED_100GBIT;
- break;
- default:
- fc_host_speed(fnic->lport->host) = FC_PORTSPEED_UNKNOWN;
- fnic->lport->link_supported_speeds = FC_PORTSPEED_UNKNOWN;
- break;
+ "waiting for reset completion\n");
+ wait_for_completion_timeout(&fnic->reset_completion_wait,
+ msecs_to_jiffies(5000));
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
+ "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->lport->host, fnic->fnic_num,
+ "old link status: %d link status: %d\n",
+ old_link_status, (int) fnic->link_status);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "old down count %d down count: %d\n",
+ old_link_down_cnt, (int) fnic->link_down_cnt);
}

if (old_link_status == fnic->link_status) {
if (!fnic->link_status) {
/* DOWN -> DOWN */
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- fnic_fc_trace_set_data(fnic->lport->host->host_no,
- FNIC_FC_LE, "Link Status: DOWN->DOWN",
- strlen("Link Status: DOWN->DOWN"));
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "down->down\n");
+ "down->down\n");
} else {
if (old_link_down_cnt != fnic->link_down_cnt) {
/* UP -> DOWN -> UP */
- fnic->lport->host_stats.link_failure_count++;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- fnic_fc_trace_set_data(
- fnic->lport->host->host_no,
- FNIC_FC_LE,
- "Link Status:UP_DOWN_UP",
- strlen("Link_Status:UP_DOWN_UP")
- );
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "link down\n");
- fcoe_ctlr_link_down(&fnic->ctlr);
- if (fnic->config.flags & VFCF_FIP_CAPABLE) {
- /* start FCoE VLAN discovery */
- fnic_fc_trace_set_data(
- fnic->lport->host->host_no,
- FNIC_FC_LE,
- "Link Status: UP_DOWN_UP_VLAN",
- strlen(
- "Link Status: UP_DOWN_UP_VLAN")
- );
- fnic_fcoe_send_vlan_req(fnic);
- return;
- }
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "up->down. Link down\n");
+ fnic_fdls_link_status_change(fnic, 0);
+
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "up->down->up: Link up\n");
- fcoe_ctlr_link_up(&fnic->ctlr);
+ "down->up. Link up\n");
+ fnic_fdls_link_status_change(fnic, 1);
} else {
/* UP -> UP */
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- fnic_fc_trace_set_data(
- fnic->lport->host->host_no, FNIC_FC_LE,
- "Link Status: UP_UP",
- strlen("Link Status: UP_UP"));
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "up->up\n");
+ "up->up\n");
}
}
} else if (fnic->link_status) {
/* DOWN -> UP */
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- if (fnic->config.flags & VFCF_FIP_CAPABLE) {
- /* start FCoE VLAN discovery */
- fnic_fc_trace_set_data(fnic->lport->host->host_no,
- FNIC_FC_LE, "Link Status: DOWN_UP_VLAN",
- strlen("Link Status: DOWN_UP_VLAN"));
- fnic_fcoe_send_vlan_req(fnic);
-
- return;
- }
-
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "down->up: Link up\n");
- fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_LE,
- "Link Status: DOWN_UP", strlen("Link Status: DOWN_UP"));
- fcoe_ctlr_link_up(&fnic->ctlr);
+ "down->up. Link up\n");
+ fnic_fdls_link_status_change(fnic, 1);
} else {
/* UP -> DOWN */
- fnic->lport->host_stats.link_failure_count++;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
- "up->down: Link down\n");
- fnic_fc_trace_set_data(
- fnic->lport->host->host_no, FNIC_FC_LE,
- "Link Status: UP_DOWN",
- strlen("Link Status: UP_DOWN"));
- fcoe_ctlr_link_down(&fnic->ctlr);
+ "up->down. Link down\n");
+ fnic_fdls_link_status_change(fnic, 0);
}

+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+ fnic->reset_in_progress = NOT_IN_PROGRESS;
+ complete(&fnic->reset_completion_wait);
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Marking fnic reset completion\n");
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
}

/*
@@ -256,35 +288,47 @@ void fnic_handle_link(struct work_struct *work)
void fnic_handle_frame(struct work_struct *work)
{
struct fnic *fnic = container_of(work, struct fnic, frame_work);
- struct fc_lport *lp = fnic->lport;
- unsigned long flags;
- struct sk_buff *skb;
- struct fc_frame *fp;
-
- while ((skb = skb_dequeue(&fnic->frame_queue))) {
+ struct fnic_frame_list *cur_frame, *next;
+ int fchdr_offset = 0;
+ struct fc_hdr_s *fchdr;

- spin_lock_irqsave(&fnic->fnic_lock, flags);
+ spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
+ list_for_each_entry_safe(cur_frame, next, &fnic->frame_queue, links) {
if (fnic->stop_rx_link_events) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- dev_kfree_skb(skb);
+ list_del(&cur_frame->links);
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
+ kfree(cur_frame->fp);
+ kfree(cur_frame);
return;
}
- fp = (struct fc_frame *)skb;

/*
* If we're in a transitional state, just re-queue and return.
* The queue will be serviced when we get to a stable state.
*/
if (fnic->state != FNIC_IN_FC_MODE &&
- fnic->state != FNIC_IN_ETH_MODE) {
- skb_queue_head(&fnic->frame_queue, skb);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ fnic->state != FNIC_IN_ETH_MODE) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Cannot process frame in transitional state\n");
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
return;
}
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);

- fc_exch_recv(lp, fp);
+ list_del(&cur_frame->links);
+
+ /* Frames from FCP_RQ will have ethhdrs stripped off */
+ fchdr_offset = (cur_frame->rx_ethhdr_stripped) ?
+ 0 : FNIC_FCOE_FCHDR_OFFSET;
+ fchdr =
+ (struct fc_hdr_s *) ((uint8_t *) cur_frame->fp + fchdr_offset);
+
+ fnic_fdls_recv_frame(&fnic->iport, cur_frame->fp,
+ cur_frame->frame_len, fchdr_offset);
+
+ kfree(cur_frame->fp);
+ kfree(cur_frame);
}
+ spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
}

void fnic_handle_fip_frame(struct work_struct *work)
@@ -500,6 +544,10 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
frame_elem->rx_ethhdr_stripped = ethhdr_stripped;
frame_elem->frame_len = bytes_written;

+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ list_add_tail(&frame_elem->links, &fnic->frame_queue);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
queue_work(fnic_event_queue, &fnic->frame_work);
return;

@@ -530,7 +578,7 @@ int fnic_rq_cmpl_handler(struct fnic *fnic, int rq_work_to_do)
cur_work_done = vnic_cq_service(&fnic->cq[i], rq_work_to_do,
fnic_rq_cmpl_handler_cont,
NULL);
- if (cur_work_done) {
+ 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->lport->host,
@@ -551,46 +599,43 @@ int fnic_rq_cmpl_handler(struct fnic *fnic, int rq_work_to_do)
int fnic_alloc_rq_frame(struct vnic_rq *rq)
{
struct fnic *fnic = vnic_dev_priv(rq->vdev);
- struct sk_buff *skb;
+ void *buf;
u16 len;
dma_addr_t pa;
- int r;
+ int ret;

- len = FC_FRAME_HEADROOM + FC_MAX_FRAME + FC_FRAME_TAILROOM;
- skb = dev_alloc_skb(len);
- if (!skb) {
- FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "Unable to allocate RQ sk_buff\n");
+ len = FNIC_FRAME_HT_ROOM;
+ buf = kmalloc(len, GFP_ATOMIC);
+ if (!buf) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unable to allocate RQ buffer of size: %d\n", len);
return -ENOMEM;
}
- skb_reset_mac_header(skb);
- skb_reset_transport_header(skb);
- skb_reset_network_header(skb);
- skb_put(skb, len);
- pa = dma_map_single(&fnic->pdev->dev, skb->data, len, DMA_FROM_DEVICE);
+
+ pa = dma_map_single(&fnic->pdev->dev, buf, len, DMA_FROM_DEVICE);
if (dma_mapping_error(&fnic->pdev->dev, pa)) {
- r = -ENOMEM;
- printk(KERN_ERR "PCI mapping failed with error %d\n", r);
- goto free_skb;
+ ret = -ENOMEM;
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "PCI mapping failed with error %d\n", ret);
+ goto free_buf;
}

- fnic_queue_rq_desc(rq, skb, pa, len);
+ fnic_queue_rq_desc(rq, buf, pa, len);
return 0;
-
-free_skb:
- kfree_skb(skb);
- return r;
+free_buf:
+ kfree(buf);
+ return ret;
}

void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
{
- struct fc_frame *fp = buf->os_buf;
+ void *rq_buf = buf->os_buf;
struct fnic *fnic = vnic_dev_priv(rq->vdev);

dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
DMA_FROM_DEVICE);

- dev_kfree_skb(fp_skb(fp));
+ kfree(rq_buf);
buf->os_buf = NULL;
}

@@ -839,13 +884,11 @@ static void fnic_wq_complete_frame_send(struct vnic_wq *wq,
struct cq_desc *cq_desc,
struct vnic_wq_buf *buf, void *opaque)
{
- struct sk_buff *skb = buf->os_buf;
- struct fc_frame *fp = (struct fc_frame *)skb;
struct fnic *fnic = vnic_dev_priv(wq->vdev);

dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);
- dev_kfree_skb_irq(fp_skb(fp));
+ kfree(buf->os_buf);
buf->os_buf = NULL;
}

@@ -883,13 +926,182 @@ int fnic_wq_cmpl_handler(struct fnic *fnic, int work_to_do)

void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
{
- struct fc_frame *fp = buf->os_buf;
struct fnic *fnic = vnic_dev_priv(wq->vdev);

dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);

- dev_kfree_skb(fp_skb(fp));
+ kfree(buf->os_buf);
buf->os_buf = NULL;
}

+void
+fnic_fdls_add_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport,
+ unsigned long flags)
+{
+ struct fnic *fnic = iport->fnic;
+ struct fc_rport *rport;
+ struct fc_rport_identifiers ids;
+ struct rport_dd_data_s *rdd_data;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Adding rport fcid: 0x%x", tport->fcid);
+
+ ids.node_name = tport->wwnn;
+ ids.port_name = tport->wwpn;
+ ids.port_id = tport->fcid;
+ ids.roles = FC_RPORT_ROLE_FCP_TARGET;
+
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ rport = fc_remote_port_add(fnic->lport->host, 0, &ids);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (!rport) {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Failed to add rport for tport: 0x%x", tport->fcid);
+ return;
+ }
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Added rport fcid: 0x%x", tport->fcid);
+
+ /* Mimic these assignments in queuecommand to avoid timing issues */
+ rport->maxframe_size = FNIC_FC_MAX_PAYLOAD_LEN;
+ rport->supported_classes = FC_COS_CLASS3 | FC_RPORT_ROLE_FCP_TARGET;
+ rdd_data = rport->dd_data;
+ rdd_data->tport = tport;
+ rdd_data->iport = iport;
+ tport->rport = rport;
+ tport->flags |= FNIC_FDLS_SCSI_REGISTERED;
+}
+
+void
+fnic_fdls_remove_tport(struct fnic_iport_s *iport,
+ struct fnic_tport_s *tport, unsigned long flags)
+{
+ struct fnic *fnic = iport->fnic;
+ struct rport_dd_data_s *rdd_data;
+
+ struct fc_rport *rport;
+
+ if (!tport)
+ return;
+
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINE);
+ rport = tport->rport;
+
+ if (rport) {
+ /* tport resource release will be done
+ * after fnic_terminate_rport_io()
+ */
+ tport->flags |= FNIC_FDLS_TPORT_DELETED;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ /* Interface to scsi_fc_transport */
+ fc_remote_port_delete(rport);
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Deregistered and freed tport fcid: 0x%x from scsi transport fc",
+ tport->fcid);
+
+ /*
+ * the dd_data is allocated by fc transport
+ * of size dd_fcrport_size
+ */
+ rdd_data = rport->dd_data;
+ rdd_data->tport = NULL;
+ rdd_data->iport = NULL;
+ list_del(&tport->links);
+ kfree(tport);
+ } else {
+ fnic_del_tport_timer_sync();
+ list_del(&tport->links);
+ kfree(tport);
+ }
+}
+
+void fnic_delete_fcp_tports(struct fnic *fnic)
+{
+ struct fnic_tport_s *tport, *next;
+ unsigned long flags;
+
+ 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->lport->host, fnic->fnic_num,
+ "removing fcp rport fcid: 0x%x", tport->fcid);
+ fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINING);
+ fnic_fdls_remove_tport(&fnic->iport, tport, flags);
+ fnic_del_tport_timer_sync();
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+/**
+ * fnic_tport_work() - Handler for remote port events in the tport_event_queue
+ * @work: Handle to the remote port being dequeued
+ */
+void fnic_tport_event_handler(struct work_struct *work)
+{
+ struct fnic *fnic = container_of(work, struct fnic, tport_work);
+ struct fnic_tport_event_s *cur_evt, *next;
+ unsigned long flags;
+ struct fnic_tport_s *tport;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ list_for_each_entry_safe(cur_evt, next, &fnic->tport_event_list, links) {
+ tport = cur_evt->arg1;
+ switch (cur_evt->event) {
+ case TGT_EV_RPORT_ADD:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Add rport event");
+ if (tport->state == FDLS_TGT_STATE_READY) {
+ fnic_fdls_add_tport(&fnic->iport,
+ (struct fnic_tport_s *) cur_evt->arg1, flags);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Target not ready. Add rport event dropped: 0x%x",
+ tport->fcid);
+ }
+ break;
+ case TGT_EV_RPORT_DEL:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Remove rport event");
+ if (tport->state == FDLS_TGT_STATE_OFFLINING) {
+ fnic_fdls_remove_tport(&fnic->iport,
+ (struct fnic_tport_s *) cur_evt->arg1, flags);
+ } else {
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "remove rport event dropped tport fcid: 0x%x",
+ tport->fcid);
+ }
+ break;
+ case TGT_EV_TPORT_DELETE:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Delete tport event");
+ fdls_delete_tport(tport->iport, tport);
+ break;
+ default:
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Unknown tport event");
+ break;
+ }
+ list_del(&cur_evt->links);
+ kfree(cur_evt);
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+void fnic_flush_tport_event_list(struct fnic *fnic)
+{
+ struct fnic_tport_event_s *cur_evt, *next;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ list_for_each_entry_safe(cur_evt, next, &fnic->tport_event_list, links) {
+ list_del(&cur_evt->links);
+ kfree(cur_evt);
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index d850ce4b743d..1310e8b46f82 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -110,7 +110,7 @@ static const struct scsi_host_template fnic_host_template = {
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = fnic_abort_cmd,
.eh_device_reset_handler = fnic_device_reset,
- .eh_host_reset_handler = fnic_host_reset,
+ .eh_host_reset_handler = fnic_eh_host_reset_handler,
.slave_alloc = fnic_slave_alloc,
.change_queue_depth = scsi_change_queue_depth,
.this_id = -1,
@@ -923,8 +923,10 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

INIT_WORK(&fnic->link_work, fnic_handle_link);
INIT_WORK(&fnic->frame_work, fnic_handle_frame);
- skb_queue_head_init(&fnic->frame_queue);
+ INIT_WORK(&fnic->tport_work, fnic_tport_event_handler);
+ INIT_LIST_HEAD(&fnic->frame_queue);
INIT_LIST_HEAD(&fnic->tx_queue);
+ INIT_LIST_HEAD(&fnic->tport_event_list);

fc_fabric_login(lp);

@@ -1006,7 +1008,7 @@ static void fnic_remove(struct pci_dev *pdev)
* be no event queued for this fnic device in the workqueue
*/
flush_workqueue(fnic_event_queue);
- skb_queue_purge(&fnic->frame_queue);
+ fnic_free_txq(&fnic->frame_queue);
fnic_free_txq(&fnic->tx_queue);

if (fnic->config.flags & VFCF_FIP_CAPABLE) {
@@ -1044,8 +1046,6 @@ static void fnic_remove(struct pci_dev *pdev)
*/
fnic_cleanup(fnic);

- BUG_ON(!skb_queue_empty(&fnic->frame_queue));
-
spin_lock_irqsave(&fnic_list_lock, flags);
list_del(&fnic->list);
spin_unlock_irqrestore(&fnic_list_lock, flags);
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 295dcda4ec16..5d5d1205e984 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -183,7 +183,7 @@ int fnic_fw_reset_handler(struct fnic *fnic)
/* indicate fwreset to io path */
fnic_set_state_flags(fnic, FNIC_FLAGS_FWRESET);

- skb_queue_purge(&fnic->frame_queue);
+ fnic_free_txq(&fnic->frame_queue);
fnic_free_txq(&fnic->tx_queue);

/* wait for io cmpl */
@@ -2575,23 +2575,30 @@ int fnic_reset(struct Scsi_Host *shost)
* host is offlined by SCSI.
*
*/
-int fnic_host_reset(struct scsi_cmnd *sc)
+int fnic_host_reset(struct Scsi_Host *shost)
{
int ret;
unsigned long wait_host_tmo;
- struct Scsi_Host *shost = sc->device->host;
- struct fc_lport *lp = shost_priv(shost);
- struct fnic *fnic = lport_priv(lp);
+ struct fnic *fnic = *((struct fnic **) shost_priv(shost));
unsigned long flags;
+ struct fnic_iport_s *iport = &fnic->iport;

spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (!fnic->internal_reset_inprogress) {
- fnic->internal_reset_inprogress = true;
+ if (fnic->reset_in_progress == NOT_IN_PROGRESS) {
+ fnic->reset_in_progress = IN_PROGRESS;
} else {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
- "host reset in progress skipping another host reset\n");
- return SUCCESS;
+ wait_for_completion_timeout(&fnic->reset_completion_wait,
+ msecs_to_jiffies(10000));
+
+ 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->lport->host, fnic->fnic_num,
+ "Firmware reset in progress. Skipping another host reset\n");
+ return SUCCESS;
+ }
+ fnic->reset_in_progress = IN_PROGRESS;
}
spin_unlock_irqrestore(&fnic->fnic_lock, flags);

@@ -2600,23 +2607,33 @@ int fnic_host_reset(struct scsi_cmnd *sc)
* scsi-ml tries to send a TUR to every device if host reset is
* successful, so before returning to scsi, fabric should be up
*/
- ret = (fnic_reset(shost) == 0) ? SUCCESS : FAILED;
- if (ret == SUCCESS) {
+ fnic_reset(shost);
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ fnic->reset_in_progress = NOT_IN_PROGRESS;
+ complete(&fnic->reset_completion_wait);
+ fnic->soft_reset_count++;
+
+ /* wait till the link is up */
+ if (fnic->link_status) {
wait_host_tmo = jiffies + FNIC_HOST_RESET_SETTLE_TIME * HZ;
ret = FAILED;
while (time_before(jiffies, wait_host_tmo)) {
- if ((lp->state == LPORT_ST_READY) &&
- (lp->link_up)) {
+ if (iport->state != FNIC_IPORT_STATE_READY
+ && fnic->link_status) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ ssleep(1);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ } else {
ret = SUCCESS;
break;
}
- ssleep(1);
}
}
-
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- fnic->internal_reset_inprogress = false;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "host reset return status: %d\n", ret);
return ret;
}

@@ -2809,3 +2826,77 @@ int fnic_is_abts_pending(struct fnic *fnic, struct scsi_cmnd *lr_sc)

return iter_data.ret;
}
+
+/*
+ * SCSI Error handling calls driver's eh_host_reset if all prior
+ * error handling levels return FAILED. If host reset completes
+ * successfully, and if link is up, then Fabric login begins.
+ *
+ * Host Reset is the highest level of error recovery. If this fails, then
+ * host is offlined by SCSI.
+ *
+ */
+int fnic_eh_host_reset_handler(struct scsi_cmnd *sc)
+{
+ int ret = 0;
+ struct Scsi_Host *shost = sc->device->host;
+ struct fnic *fnic = *((struct fnic **) shost_priv(shost));
+
+ FNIC_SCSI_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
+ "SCSI error handling: fnic host reset");
+
+ ret = fnic_host_reset(shost);
+ return ret;
+}
+
+
+void fnic_scsi_fcpio_reset(struct fnic *fnic)
+{
+ unsigned long flags;
+ enum fnic_state old_state;
+ struct fnic_iport_s *iport = &fnic->iport;
+ DECLARE_COMPLETION_ONSTACK(fw_reset_done);
+ int time_remain;
+
+ /* issue fw reset */
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ 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_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "fnic is in unexpected state: %d for fw_reset\n",
+ fnic->state);
+ return;
+ }
+
+ old_state = fnic->state;
+ fnic->state = FNIC_IN_FC_TRANS_ETH_MODE;
+
+ fnic_update_mac_locked(fnic, iport->hwmac);
+ fnic->fw_reset_done = &fw_reset_done;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Issuing fw reset\n");
+ if (fnic_fw_reset_handler(fnic)) {
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)
+ fnic->state = old_state;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ } else {
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Waiting for fw completion\n");
+ time_remain = wait_for_completion_timeout(&fw_reset_done,
+ msecs_to_jiffies(FNIC_FW_RESET_TIMEOUT));
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "Woken up after fw completion timeout\n");
+ if (time_remain == 0) {
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
+ "FW reset completion timed out after %d ms)\n",
+ FNIC_FW_RESET_TIMEOUT);
+ }
+ }
+ fnic->fw_reset_done = NULL;
+}
+
+
--
2.31.1


2024-06-10 23:18:52

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 06/14] scsi: fnic: Add and integrate support for FDMI

Hi Karan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on jejb-scsi/for-next linus/master v6.10-rc3 next-20240607]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Karan-Tilak-Kumar/scsi-fnic-Replace-shost_printk-with-pr_info-pr_err/20240611-060227
base: https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
patch link: https://lore.kernel.org/r/20240610215100.673158-7-kartilak%40cisco.com
patch subject: [PATCH 06/14] scsi: fnic: Add and integrate support for FDMI
reproduce: (https://download.01.org/0day-ci/archive/20240611/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

versioncheck warnings: (new ones prefixed by >>)
INFO PATH=/opt/cross/rustc-1.78.0-bindgen-0.65.1/cargo/bin:/opt/cross/clang-18/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/usr/bin/timeout -k 100 3h /usr/bin/make KCFLAGS= -Wtautological-compare -Wno-error=return-type -Wreturn-type -Wcast-function-type -funsigned-char -Wundef -fstrict-flex-arrays=3 -Wformat-overflow -Wformat-truncation -Wenum-conversion W=1 --keep-going LLVM=1 -j32 ARCH=x86_64 versioncheck
find ./* \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o \
-name '*.[hcS]' -type f -print | sort \
| xargs perl -w ./scripts/checkversion.pl
./drivers/accessibility/speakup/genmap.c: 13 linux/version.h not needed.
./drivers/accessibility/speakup/makemapdata.c: 13 linux/version.h not needed.
>> ./drivers/scsi/fnic/fnic_pci_subsys_devid.c: 11 linux/version.h not needed.
./drivers/staging/media/atomisp/include/linux/atomisp.h: 23 linux/version.h not needed.
./samples/bpf/spintest.bpf.c: 8 linux/version.h not needed.
./samples/trace_events/trace_custom_sched.c: 11 linux/version.h not needed.
./sound/soc/codecs/cs42l42.c: 14 linux/version.h not needed.
./tools/lib/bpf/bpf_helpers.h: 423: need linux/version.h
./tools/testing/selftests/bpf/progs/dev_cgroup.c: 9 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/netcnt_prog.c: 3 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/test_map_lock.c: 4 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/test_send_signal_kern.c: 4 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/test_spin_lock.c: 4 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/test_tcp_estats.c: 37 linux/version.h not needed.
./tools/testing/selftests/wireguard/qemu/init.c: 27 linux/version.h not needed.

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-06-11 07:09:29

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 03/14] scsi: fnic: Add support for fabric based solicited requests and responses

On 6/10/24 23:50, Karan Tilak Kumar wrote:
> Add fdls_disc.c to support fabric based solicited requests
> and responses.
> Clean up obsolete code but keep the function template so
> as to not break compilation.
> Remove duplicate definitions from header files.
> Modify definitions of data members.
>
> Reviewed-by: Sesidhar Baddela <[email protected]>
> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> Reviewed-by: Gian Carlo Boffa <[email protected]>
> Signed-off-by: Karan Tilak Kumar <[email protected]>
> ---
> drivers/scsi/fnic/Makefile | 1 +
> drivers/scsi/fnic/fdls_disc.c | 1576 +++++++++++++++++++++++++++++++++
> drivers/scsi/fnic/fnic.h | 26 +-
> drivers/scsi/fnic/fnic_fcs.c | 404 +++++----
> drivers/scsi/fnic/fnic_fdls.h | 7 +-
> drivers/scsi/fnic/fnic_io.h | 11 -
> drivers/scsi/fnic/fnic_main.c | 10 +-
> drivers/scsi/fnic/fnic_scsi.c | 6 +-
> 8 files changed, 1849 insertions(+), 192 deletions(-)
> create mode 100644 drivers/scsi/fnic/fdls_disc.c
>
> diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
> index 6214a6b2e96d..3bd6b1c8b643 100644
> --- a/drivers/scsi/fnic/Makefile
> +++ b/drivers/scsi/fnic/Makefile
> @@ -7,6 +7,7 @@ fnic-y := \
> fnic_main.o \
> fnic_res.o \
> fnic_fcs.o \
> + fdls_disc.o \
> fnic_scsi.o \
> fnic_trace.o \
> fnic_debugfs.o \
> diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
> new file mode 100644
> index 000000000000..22a2d0c1c78f
> --- /dev/null
> +++ b/drivers/scsi/fnic/fdls_disc.c
> @@ -0,0 +1,1576 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright 2008 Cisco Systems, Inc. All rights reserved.
> + * Copyright 2007 Nuova Systems, Inc. All rights reserved.
> + */
> +
> +#include <linux/workqueue.h>
> +#include "fnic.h"
> +#include "fdls_fc.h"
> +#include "fnic_fdls.h"
> +#include <scsi/fc/fc_fcp.h>
> +#include <linux/utsname.h>
> +
> +static void fdls_send_rpn_id(struct fnic_iport_s *iport);
> +
> +/* Frame initialization */
> +/*
> + * Variables:
> + * sid
> + */
> +struct fc_els_s fnic_flogi_req = {
> + .fchdr = {.r_ctl = 0x22, .did = {0xFF, 0xFF, 0xFE},
> + .type = 0x01, .f_ctl = FNIC_ELS_REQ_FCTL,
> + .ox_id = FNIC_FLOGI_OXID, .rx_id = 0xFFFF},
> + .command = FC_ELS_FLOGI_REQ,
> + .u.csp_flogi = {.fc_ph_ver = FNIC_FC_PH_VER,
> + .b2b_credits = FNIC_FC_B2B_CREDIT,
> + .b2b_rdf_size = FNIC_FC_B2B_RDF_SZ},
> + .spc3 = {0x88, 0x00}
> +};
> +
> +/*
> + * Variables:
> + * sid, did(nport logins), ox_id(nport logins), nport_name, node_name
> + */
> +struct fc_els_s fnic_plogi_req = {
> + .fchdr = {.r_ctl = 0x22, .did = {0xFF, 0xFF, 0xFC}, .type = 0x01,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_PLOGI_FABRIC_OXID,
> + .rx_id = 0xFFFF},
> + .command = FC_ELS_PLOGI_REQ,
> + .u.csp_plogi = {.fc_ph_ver = FNIC_FC_PH_VER,
> + .b2b_credits = FNIC_FC_B2B_CREDIT, .features = 0x0080,
> + .b2b_rdf_size = FNIC_FC_B2B_RDF_SZ,
> + .total_concur_seqs = FNIC_FC_CONCUR_SEQS,
> + .ro_info = FNIC_FC_RO_INFO, .e_d_tov = FNIC_E_D_TOV},
> + .spc3 = {0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xFF,
> + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}
> +};
> +
> +/*
> + * Variables:
> + * sid, port_id, port_name
> + */
> +struct fc_rpn_id_s fnic_rpn_id_req = {
> + .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_RPN_REQ_OXID,
> + .rx_id = 0xFFFF},
> + .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
> + .command = FC_CT_RPN_CMD}
> +};
> +
> +/*
> + * Variables:
> + * fh_s_id, port_id, port_name
> + */
> +struct fc_rft_id fnic_rft_id_req = {
> + .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_RFT_REQ_OXID,
> + .rx_id = 0xFFFF},
> + .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
> + .command = FC_CT_RFT_CMD}
> +};
> +
> +/*
> + * Variables:
> + * fh_s_id, port_id, port_name
> + */
> +struct fc_rff_id fnic_rff_id_req = {
> + .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_RFF_REQ_OXID,
> + .rx_id = 0xFFFF},
> + .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
> + .command = FC_CT_RFF_CMD},
> + .tgt = 0x2,
> + .fc4_type = 0x28
> +};
> +
> +/*
> + * Variables:
> + * sid
> + */
> +struct fc_gpn_ft_s fnic_gpn_ft_req = {
> + .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFC}, .type = 0x20,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_GPN_FT_OXID,
> + .rx_id = 0xFFFF},
> + .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFC, .fs_subtype = 0x02,
> + .command = FC_CT_GPN_FT_CMD},
> + .fc4_type = 0x08
> +};
> +
> +/*
> + * Variables:
> + * sid
> + */
> +struct fc_scr_s fnic_scr_req = {
> + .fchdr = {.r_ctl = 0x22, .did = {0xFF, 0xFF, 0xFD}, .type = 0x01,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_SCR_REQ_OXID,
> + .rx_id = 0xFFFF},
> + .command = FC_ELS_SCR,
> + .reg_func = 0x03
> +};
> +
> +/*
> + * Variables:
> + * did, ox_id, rx_id, fcid, wwpn
> + */
> +struct fc_logo_req_s fnic_logo_req = {
> + .fchdr = {.r_ctl = 0x22, .type = 0x01,
> + .f_ctl = FNIC_ELS_REQ_FCTL},
> + .command = FC_ELS_LOGO,
> +};
> +
> +#define RETRIES_EXHAUSTED(iport) \
> + (iport->fabric.retry_counter == FABRIC_LOGO_MAX_RETRY)
> +
> +static void fdls_process_flogi_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr, void *rx_frame);
> +static void fnic_fdls_start_plogi(struct fnic_iport_s *iport);
> +static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
> + int timeout);
> +
> +static void
> +fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
> +{
> + u64 fabric_tov;
> + struct fnic *fnic = iport->fnic;
> +
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport fcid: 0x%x: Canceling fabric disc timer\n",
> + iport->fcid);
> + fnic_del_fabric_timer_sync();
> + iport->fabric.timer_pending = 0;
> + }
> +
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
> + iport->fabric.retry_counter++;
> +
> + fabric_tov = jiffies + msecs_to_jiffies(timeout);
> + mod_timer(&iport->fabric.retry_timer, round_jiffies(fabric_tov));
> + iport->fabric.timer_pending = 1;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fabric timer is %d ", timeout);
> +}
> +
> +static void fdls_send_fabric_abts(struct fnic_iport_s *iport)
> +{
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> + struct fc_hdr_s fc_abts_s = {
> + .r_ctl = 0x81, /* ABTS */
> + .did = {0xFF, 0xFF, 0xFF}, .sid = {0x00, 0x00, 0x00}, .cs_ctl =
> + 0x00, .type = 0x00, .f_ctl = FNIC_REQ_ABTS_FCTL, .seq_id =
> + 0x00, .df_ctl = 0x00, .seq_cnt = 0x0000, .rx_id = 0xFFFF,
> + .param = 0x00000000, /* bit:0 = 0 Abort a exchange */
> + };
> +
You have a list of global static frame definitions above, and yet you
define another static frame here within the function.
Please be consistent, and either make this a global definition, too, or
move the global definitions into the caller.

> + struct fc_hdr_s *pfc_abts = &fc_abts_s;
> +
> + switch (iport->fabric.state) {
> + case FDLS_STATE_FABRIC_LOGO:
> + fc_abts_s.ox_id = FNIC_FLOGO_REQ_OXID;
> + fc_abts_s.did[2] = 0xFE;
> + break;
> + case FDLS_STATE_FABRIC_FLOGI:
> + fc_abts_s.ox_id = FNIC_FLOGI_OXID;
> + fc_abts_s.did[2] = 0xFE;
> + break;
> +
OMG. I was right. Static oxids.

Not that I am in any position to judge, but having static
OXIDs for command types feels decidedly ... odd.
I do see the motivation behind it (these OXIDs can't be used
for anything else), yet it also means that you can have only _one_
of these commands running at any given time.
And the biggest problem here is that you _cannot_ resend the
command if you run into a timeout; you have to wait for RA_TOV
(or worse) to trigger, and essentially have to tear down the
entire link just to ensure you can re-used the OXID.

In general I would _strongly_ discourage using static OXIDs.
Please use a pool of OXIDs, and allocate one from there.

> + case FDLS_STATE_FABRIC_PLOGI:
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID(pfc_abts, fcid);
> + fc_abts_s.ox_id = FNIC_PLOGI_FABRIC_OXID;
> + fc_abts_s.did[2] = 0xFC;
> + break;
> +
> + case FDLS_STATE_RPN_ID:
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID(pfc_abts, fcid);
> + fc_abts_s.ox_id = FNIC_RPN_REQ_OXID;
> + fc_abts_s.did[2] = 0xFC;
> + break;
> +
> + case FDLS_STATE_SCR:
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID(pfc_abts, fcid);
> + fc_abts_s.ox_id = FNIC_SCR_REQ_OXID;
> + fc_abts_s.did[2] = 0xFD;
> + break;
> +
> + case FDLS_STATE_REGISTER_FC4_TYPES:
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID(pfc_abts, fcid);
> + fc_abts_s.ox_id = FNIC_RFT_REQ_OXID;
> + fc_abts_s.did[2] = 0xFC;
> + break;
> +
> + case FDLS_STATE_REGISTER_FC4_FEATURES:
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID(pfc_abts, fcid);
> + fc_abts_s.ox_id = FNIC_RFF_REQ_OXID;
> + fc_abts_s.did[2] = 0xFC;
> + break;
> +
> + case FDLS_STATE_GPN_FT:
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID(pfc_abts, fcid);
> + fc_abts_s.ox_id = FNIC_GPN_FT_OXID;
> + fc_abts_s.did[2] = 0xFC;
> + break;
> + default:
> + return;
> + }
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS sending fabric abts. iport->fabric.state: %d",
> + iport->fabric.state);
> +
> + iport->fabric.flags |= FNIC_FDLS_FABRIC_ABORT_ISSUED;
> + fnic_send_fcoe_frame(iport, &fc_abts_s, sizeof(struct fc_hdr_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> +
> + fdls_start_fabric_timer(iport, 2 * iport->r_a_tov);
> + iport->fabric.timer_pending = 1;
> +}
> +
> +static void fdls_send_fabric_flogi(struct fnic_iport_s *iport)
> +{
> + struct fc_els_s flogi;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS send fabric FLOGI", iport->fcid);
> +
> + memcpy(&flogi, &fnic_flogi_req, sizeof(struct fc_els_s));
> + FNIC_SET_NPORT_NAME(flogi, iport->wwpn);
> + FNIC_SET_NODE_NAME(flogi, iport->wwnn);
> + FNIC_SET_RDF_SIZE(flogi.u.csp_flogi, iport->max_payload_size);
> + FNIC_SET_R_A_TOV(flogi.u.csp_flogi, iport->r_a_tov);
> + FNIC_SET_E_D_TOV(flogi.u.csp_flogi, iport->e_d_tov);
> +
> + fnic_send_fcoe_frame(iport, &flogi, sizeof(struct fc_els_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> +}
> +
> +
Double newline.

> +static void fdls_send_fabric_plogi(struct fnic_iport_s *iport)
> +{
> + struct fc_els_s plogi;
> + struct fc_hdr_s *fchdr = &plogi.fchdr;
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS send fabric PLOGI", iport->fcid);
> +
> + memcpy(&plogi, &fnic_plogi_req, sizeof(struct fc_els_s));
> +
> + hton24(fcid, iport->fcid);
> +
> + FNIC_SET_S_ID(fchdr, fcid);
> + FNIC_SET_NPORT_NAME(plogi, iport->wwpn);
> + FNIC_SET_NODE_NAME(plogi, iport->wwnn);
> + FNIC_SET_RDF_SIZE(plogi.u.csp_plogi, iport->max_payload_size);
> +
> + fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> +}
> +
> +static void fdls_send_rpn_id(struct fnic_iport_s *iport)
> +{
> + struct fc_rpn_id_s rpn_id;
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS send RPN ID", iport->fcid);
> +
> + memcpy(&rpn_id, &fnic_rpn_id_req, sizeof(struct fc_rpn_id_s));
> +
> + hton24(fcid, iport->fcid);
> +
> + FNIC_SET_S_ID((&rpn_id.fchdr), fcid);
> + FNIC_SET_RPN_PORT_ID((&rpn_id), fcid);
> + FNIC_SET_RPN_PORT_NAME((&rpn_id), iport->wwpn);
> +
> + fnic_send_fcoe_frame(iport, &rpn_id, sizeof(struct fc_rpn_id_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> +}
> +
> +static void fdls_send_scr(struct fnic_iport_s *iport)
> +{
> + struct fc_scr_s scr_req;
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS send SCR", iport->fcid);
> +
> + memcpy(&scr_req, &fnic_scr_req, sizeof(struct fc_scr_s));
> +
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID((&scr_req.fchdr), fcid);
> +
> + fnic_send_fcoe_frame(iport, &scr_req, sizeof(struct fc_scr_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> +}
> +
> +static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state)
> +{
> + struct fc_gpn_ft_s gpn_ft;
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS send GPN FT", iport->fcid);
> +
> + memcpy(&gpn_ft, &fnic_gpn_ft_req, sizeof(struct fc_gpn_ft_s));
> +
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID((&gpn_ft.fchdr), fcid);
> + fnic_send_fcoe_frame(iport, &gpn_ft, sizeof(struct fc_gpn_ft_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> + fdls_set_state((&iport->fabric), fdls_state);
> +}
> +
> +static void fdls_send_register_fc4_types(struct fnic_iport_s *iport)
> +{
> + struct fc_rft_id rft_id;
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS sending FC4 Types", iport->fcid);
> +
> + memset(&rft_id, 0, sizeof(struct fc_rft_id));
> + memcpy(&rft_id, &fnic_rft_id_req, sizeof(struct fc_rft_id));
> + hton24(fcid, iport->fcid);
> +
> + FNIC_SET_S_ID((&rft_id.fchdr), fcid);
> + FNIC_SET_PORT_ID((&rft_id), fcid);
> + if (IS_FNIC_FCP_INITIATOR(fnic))
> + rft_id.fc4_types[2] = 1;
> +
> + rft_id.fc4_types[7] = 1;
> + fnic_send_fcoe_frame(iport, &rft_id, sizeof(struct fc_rft_id));
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> +}
> +
> +static void fdls_send_register_fc4_features(struct fnic_iport_s *iport)
> +{
> + struct fc_rff_id rff_id;
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS sending FC4 features", iport->fcid);
> + memcpy(&rff_id, &fnic_rff_id_req, sizeof(struct fc_rff_id));
> +
> + hton24(fcid, iport->fcid);
> +
> + FNIC_SET_S_ID((&rff_id.fchdr), fcid);
> + FNIC_SET_PORT_ID((&rff_id), fcid);
> +
> + if (IS_FNIC_FCP_INITIATOR(fnic)) {
> + rff_id.fc4_type = 0x08;
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Unknown type", iport->fcid);
> + }
> +
> + fnic_send_fcoe_frame(iport, &rff_id, sizeof(struct fc_rff_id));
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> +}
> +
> +/***********************************************************************
> + * fdls_send_fabric_logo
> + *
> + * \brief Send flogo to the fcf
> + *
> + * \param[in] iport Handle to fnic iport.
> + *
> + * \param[in] start_timer 1 if we want to start a perodic timer else 0
> + *
> + * \retval void
> + *
> + * \locks Currently this assumes to be called with fnic lock held
> + *
> + * \note This function does not change or check the fabric state.
> + * It the caller responsibility to set the appropriate iport fabric
> + * state when this is called. Normall its FDLS_STATE_FABRIC_LOGO.
> + * fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_LOGO)
> + * \note Locking can be changed and made bit granuler in future
> + *
> + ***********************************************************************/
Please use the correct kernel-doc format.

> +void fdls_send_fabric_logo(struct fnic_iport_s *iport)
> +{
> + struct fc_logo_req_s logo;
> + uint8_t s_id[3];
> + uint8_t d_id[3] = { 0xFF, 0xFF, 0xFE };
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Sending logo to fabric from iport->fcid: 0x%x",
> + iport->fcid);
> + memcpy(&logo, &fnic_logo_req, sizeof(struct fc_logo_req_s));
> +
> + hton24(s_id, iport->fcid);
> +
> + FNIC_SET_S_ID((&logo.fchdr), s_id);
> + FNIC_SET_D_ID((&logo.fchdr), d_id);
> + FNIC_SET_OX_ID((&logo.fchdr), FNIC_FLOGO_REQ_OXID);
> +
> + memcpy(&logo.fcid, s_id, 3);
> + logo.wwpn = htonll(iport->wwpn);
> +
> + fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> +
> + iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> + fnic_send_fcoe_frame(iport, &logo, sizeof(struct fc_logo_req_s));
> +}
> +
> +void fdls_fabric_timer_callback(struct timer_list *t)
> +{
> + struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, retry_timer);
> + struct fnic_iport_s *iport =
> + container_of(fabric, struct fnic_iport_s, fabric);
> + struct fnic *fnic = iport->fnic;
> + unsigned long flags;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tp: %d fab state: %d fab retry counter: %d max_flogi_retries: %d",
> + iport->fabric.timer_pending, iport->fabric.state,
> + iport->fabric.retry_counter, iport->max_flogi_retries);
> +
> + spin_lock_irqsave(&fnic->fnic_lock, flags);
> +
> + if (!iport->fabric.timer_pending) {
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> +
> + if (iport->fabric.del_timer_inprogress) {
> + iport->fabric.del_timer_inprogress = 0;
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fabric_del_timer inprogress(%d). Skip timer cb",
> + iport->fabric.del_timer_inprogress);
> + return;
> + }
> +
> + iport->fabric.timer_pending = 0;
> +
> + /* The fabric state indicates which frames have time out, and we retry */
> + switch (iport->fabric.state) {
> + case FDLS_STATE_FABRIC_FLOGI:
> + /* Flogi received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < iport->max_flogi_retries)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_fabric_flogi(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + /* Flogi has time out 2*ed_tov send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> + fdls_send_fabric_abts(iport);
> + } else {
> + /* Flogi ABTS has timed out and we have waited
> + * (2 * ra_tov), we can retry safely with same
> + * exchange id
> + */
> + if (iport->fabric.retry_counter < iport->max_flogi_retries) {
> + iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> + fdls_send_fabric_flogi(iport);
> + } else
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Exceeded max FLOGI retries");
> + }
> + break;
> + case FDLS_STATE_FABRIC_PLOGI:
> + /* Plogi received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < iport->max_plogi_retries)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_fabric_plogi(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + /* Plogi has timed out 2*ed_tov send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> + fdls_send_fabric_abts(iport);
> + } else {
> + /* plogi ABTS has timed out and we have waited
> + * (2 * ra_tov) can retry safely with same
> + * exchange id
> + */
> + if (iport->fabric.retry_counter < iport->max_plogi_retries) {
> + iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> + fdls_send_fabric_plogi(iport);
> + } else
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Exceeded max PLOGI retries");
> + }
> + break;
> + case FDLS_STATE_RPN_ID:
> + /* Rpn_id received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_rpn_id(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + /* RPN have timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
> + fdls_send_fabric_abts(iport);
> + else
> + /* ABTS has timed out (2*ra_tov) */
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + break;
> + case FDLS_STATE_SCR:
> + /* scr received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_scr(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + /* scr have timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
> + fdls_send_fabric_abts(iport);
> + else {
> + /* ABTS has timed out (2*ra_tov), we give up */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ABTS timed out. Starting PLOGI: %p", iport);
> + fnic_fdls_start_plogi(iport);
> + }
> + break;
> + case FDLS_STATE_REGISTER_FC4_TYPES:
> + /* scr received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_register_fc4_types(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + /* RFT_ID timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> + fdls_send_fabric_abts(iport);
> + } else {
> + /* ABTS has timed out (2*ra_tov), we give up */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ABTS timed out. Starting PLOGI: %p", iport);
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + }
> + break;
> + case FDLS_STATE_REGISTER_FC4_FEATURES:
> + /* scr received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_register_fc4_features(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + /* scr have timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
> + fdls_send_fabric_abts(iport);
> + else {
> + /* ABTS has timed out (2*ra_tov), we give up */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ABTS timed out. Starting PLOGI %p", iport);
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + }
> + break;
> + case FDLS_STATE_RSCN_GPN_FT:
> + case FDLS_STATE_SEND_GPNFT:
> + case FDLS_STATE_GPN_FT:
> + /* GPN_FT received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_gpn_ft(iport, iport->fabric.state);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + /* gpn_gt have timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> + fdls_send_fabric_abts(iport);
> + } else {
> + /*
> + * ABTS has timed out have waited (2*ra_tov) can
> + * retry safely with same exchange id
> + */
> + if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
> + fdls_send_gpn_ft(iport, iport->fabric.state);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ABTS timeout for fabric GPN_FT. Check name server: %p",
> + iport);
> + }
> + }
> + break;
> + default:
> + break;
> + }
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> +}
> +
> +static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
> +{
> + iport->fabric.retry_counter = 0;
> + fdls_send_fabric_flogi(iport);
> + fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_FLOGI);
> + iport->fabric.flags = 0;
> +}
> +
> +static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
> +{
> + iport->fabric.retry_counter = 0;
> + fdls_send_fabric_plogi(iport);
> + fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
> + iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> +}
> +
> +static void
> +fdls_process_rff_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fnic *fnic = iport->fnic;
> + struct fnic_fdls_fabric_s *fdls = &iport->fabric;
> + struct fc_rff_id *rff_rsp = (struct fc_rff_id *) fchdr;
> + uint16_t rsp;
> + uint8_t reason_code;
> +
> + if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_FEATURES) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RFF_ID resp recvd in state(%d). Dropping.",
> + fdls_get_state(fdls));
> + return;
> + }
> +
> + rsp = FNIC_GET_FC_CT_CMD((&rff_rsp->fc_ct_hdr));
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS process RFF ID response: 0x%04x", iport->fcid,
> + (uint32_t) rsp);
> +
> + switch (rsp) {
> + case FC_CT_ACC:
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + fdls->retry_counter = 0;
> + fdls_set_state((&iport->fabric), FDLS_STATE_SCR);
> + fdls_send_scr(iport);
> + break;
> + case FC_CT_REJ:
> + reason_code = rff_rsp->fc_ct_hdr.reason_code;
> + if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
> + || (reason_code == FC_CT_RJT_BUSY))
> + && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RFF_ID ret FC_LS_REJ BUSY. Retry from timer routine %p",
> + iport);
> +
> + /* Retry again from the timer routine */
> + fdls->flags |= FNIC_FDLS_RETRY_FRAME;
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RFF_ID returned FC_LS_REJ. Halting discovery %p", iport);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + fdls->timer_pending = 0;
> + fdls->retry_counter = 0;
> + }
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static void
> +fdls_process_rft_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fnic_fdls_fabric_s *fdls = &iport->fabric;
> + struct fc_rft_id *rft_rsp = (struct fc_rft_id *) fchdr;
> + uint16_t rsp;
> + uint8_t reason_code;
> + struct fnic *fnic = iport->fnic;
> +
> + if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_TYPES) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RFT_ID resp recvd in state(%d). Dropping.",
> + fdls_get_state(fdls));
> + return;
> + }
> +
> + rsp = FNIC_GET_FC_CT_CMD((&rft_rsp->fc_ct_hdr));
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS process RFT ID response: 0x%04x", iport->fcid,
> + (uint32_t) rsp);
> +
> + switch (rsp) {
> + case FC_CT_ACC:
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + fdls->retry_counter = 0;
> + fdls_send_register_fc4_features(iport);
> + fdls_set_state((&iport->fabric), FDLS_STATE_REGISTER_FC4_FEATURES);
> + break;
> + case FC_CT_REJ:
> + reason_code = rft_rsp->fc_ct_hdr.reason_code;
> + if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
> + || (reason_code == FC_CT_RJT_BUSY))
> + && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: RFT_ID ret FC_LS_REJ BUSY. Retry from timer routine",
> + iport->fcid);
> +
> + /* Retry again from the timer routine */
> + fdls->flags |= FNIC_FDLS_RETRY_FRAME;
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: RFT_ID REJ. Halting discovery reason %d expl %d",
> + iport->fcid, reason_code,
> + rft_rsp->fc_ct_hdr.reason_expl);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + fdls->timer_pending = 0;
> + fdls->retry_counter = 0;
> + }
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static void
> +fdls_process_rpn_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fnic_fdls_fabric_s *fdls = &iport->fabric;
> + struct fc_rpn_id_s *rpn_rsp = (struct fc_rpn_id_s *) fchdr;
> + uint16_t rsp;
> + uint8_t reason_code;
> + struct fnic *fnic = iport->fnic;
> +
> + if (fdls_get_state(fdls) != FDLS_STATE_RPN_ID) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RPN_ID resp recvd in state(%d). Dropping.",
> + fdls_get_state(fdls));
> + return;
> + }
> +
> + rsp = FNIC_GET_FC_CT_CMD((&rpn_rsp->fc_ct_hdr));
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS process RPN ID response: 0x%04x", iport->fcid,
> + (uint32_t) rsp);
> +
> + switch (rsp) {
> + case FC_CT_ACC:
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + fdls->retry_counter = 0;
> + fdls_send_register_fc4_types(iport);
> + fdls_set_state((&iport->fabric), FDLS_STATE_REGISTER_FC4_TYPES);
> + break;
> + case FC_CT_REJ:
> + reason_code = rpn_rsp->fc_ct_hdr.reason_code;
> + if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
> + || (reason_code == FC_CT_RJT_BUSY))
> + && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RPN_ID returned REJ BUSY. Retry from timer routine %p",
> + iport);
> +
> + /* Retry again from the timer routine */
> + fdls->flags |= FNIC_FDLS_RETRY_FRAME;
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RPN_ID FC_LS_REJ. Halting discovery %p", iport);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + fdls->timer_pending = 0;
> + fdls->retry_counter = 0;
> + }
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static void
> +fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fnic_fdls_fabric_s *fdls = &iport->fabric;
> + struct fc_scr_s *scr_rsp = (struct fc_scr_s *) fchdr;
> + struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS process SCR response: 0x%04x",
> + (uint32_t) scr_rsp->command);
> +
> + if (fdls_get_state(fdls) != FDLS_STATE_SCR) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "SCR resp recvd in state(%d). Dropping.",
> + fdls_get_state(fdls));
> + return;
> + }
> +
> + switch (scr_rsp->command) {
> + case FC_LS_ACC:
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + iport->fabric.retry_counter = 0;
> + fdls_send_gpn_ft(iport, FDLS_STATE_GPN_FT);
> + break;
> +
> + case FC_LS_REJ:
> + if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
> + || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
> + && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "SCR FC_LS_REJ BUSY. Retry from timer routine %p",
> + iport);
> + /* Retry again from the timer routine */
> + fdls->flags |= FNIC_FDLS_RETRY_FRAME;
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "SCR returned FC_LS_REJ. Halting discovery %p",
> + iport);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + fdls->timer_pending = 0;
> + fdls->retry_counter = 0;
> + }
> + break;
> +
> + default:
> + break;
> + }
> +}
> +
> +static void
> +fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
> + int len)
> +{
> + struct fnic_fdls_fabric_s *fdls = &iport->fabric;
> + struct fc_gpn_ft_s *gpn_ft_rsp = (struct fc_gpn_ft_s *) fchdr;
> + uint16_t rsp;
> + uint8_t reason_code;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS process GPN_FT response: iport state: %d len: %d",
> + iport->state, len);
> +
> + /*
> + * GPNFT response :-
> + * FDLS_STATE_GPN_FT : GPNFT send after SCR state
> + * during fabric discovery(FNIC_IPORT_STATE_FABRIC_DISC)
> + * FDLS_STATE_RSCN_GPN_FT : GPNFT send in response to RSCN
> + * FDLS_STATE_SEND_GPNFT : GPNFT send after deleting a Target,
> + * e.g. after receiving Target LOGO
> + * FDLS_STATE_TGT_DISCOVERY :Target discovery is currently in progress
> + * from previous GPNFT response,a new GPNFT response has come.
> + */
> + if (!(((iport->state == FNIC_IPORT_STATE_FABRIC_DISC)
> + && (fdls_get_state(fdls) == FDLS_STATE_GPN_FT))
> + || ((iport->state == FNIC_IPORT_STATE_READY)
> + && ((fdls_get_state(fdls) == FDLS_STATE_RSCN_GPN_FT)
> + || (fdls_get_state(fdls) == FDLS_STATE_SEND_GPNFT)
> + || (fdls_get_state(fdls) == FDLS_STATE_TGT_DISCOVERY))))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "GPNFT resp recvd in fab state(%d) iport_state(%d). Dropping.",
> + fdls_get_state(fdls), iport->state);
> + return;
> + }
> +
> + iport->state = FNIC_IPORT_STATE_READY;
> + rsp = FNIC_GET_FC_CT_CMD((&gpn_ft_rsp->fc_ct_hdr));
> +
> + switch (rsp) {
> +
> + case FC_CT_ACC:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: GPNFT_RSP accept", iport->fcid);
> + break;
> +
> + case FC_CT_REJ:
> + reason_code = gpn_ft_rsp->fc_ct_hdr.reason_code;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: GPNFT_RSP Reject", iport->fcid);
> + break;
> +
> + default:
> + break;
> + }
> +}
> +
> +/***********************************************************************
> + * fdls_process_fabric_logo_rsp
> + *
> + * \brief Handles a flogo response from the fcf
> + *
> + * \param[in] iport Handle to fnic iport.
> + *
> + * \param[in] fchdr Incoming frame
> + *
> + * \retval void
> + *
> + *
> + ***********************************************************************/
Again, please use correct kernel-doc format.

> +static void
> +fdls_process_fabric_logo_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + struct fc_els_s *flogo_rsp = (struct fc_els_s *) fchdr;
> + struct fnic *fnic = iport->fnic;
> +
> + switch (flogo_rsp->command) {
> + case FC_LS_ACC:
> + if (iport->fabric.state != FDLS_STATE_FABRIC_LOGO) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Flogo response. Fabric not in LOGO state. Dropping! %p",
> + iport);
> + return;
> + }
> +
> + iport->fabric.state = FDLS_STATE_FLOGO_DONE;
> + iport->state = FNIC_IPORT_STATE_LINK_WAIT;
> +
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "lport 0x%p Canceling fabric disc timer\n",
> + iport);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Flogo response from Fabric for did: 0x%x",
> + ntoh24(fchdr->did));
> + return;
> +
> + case FC_LS_REJ:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Flogo response from Fabric for did: 0x%x returned FC_LS_REJ",
> + ntoh24(fchdr->did));
> + return;
> +
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGO response not accepted or rejected: 0x%x",
> + flogo_rsp->command);
> + }
> +}
> +
> +static void
> +fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
> + void *rx_frame)
> +{
> + struct fnic_fdls_fabric_s *fabric = &iport->fabric;
> + struct fc_els_s *flogi_rsp = (struct fc_els_s *) fchdr;
> + uint8_t *fcid;
> + int rdf_size;
> + struct fc_els_reject_s *els_rjt;
> + uint8_t fcmac[6] = { 0x0E, 0XFC, 0x00, 0x00, 0x00, 0x00 };
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS processing FLOGI response", iport->fcid);
> +
> + if (fdls_get_state(fabric) != FDLS_STATE_FABRIC_FLOGI) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI response received in state (%d). Dropping frame",
> + fdls_get_state(fabric));
> + return;
> + }
> +
> + switch (flogi_rsp->command) {
> + case FC_LS_ACC:
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport fcid: 0x%x Canceling fabric disc timer\n",
> + iport->fcid);
> + fnic_del_fabric_timer_sync();
> + }
> +
> + iport->fabric.timer_pending = 0;
> + iport->fabric.retry_counter = 0;
> + fcid = FNIC_GET_D_ID(fchdr);
> + iport->fcid = ntoh24(fcid);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FLOGI response accepted", iport->fcid);
> +
> + /* Learn the Service Params */
> + rdf_size = ntohs(flogi_rsp->u.csp_flogi.b2b_rdf_size);
> + if ((rdf_size >= FNIC_MIN_DATA_FIELD_SIZE)
> + && (rdf_size < FNIC_FC_MAX_PAYLOAD_LEN))
> + iport->max_payload_size = MIN(rdf_size,
> + iport->max_payload_size);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "max_payload_size from fabric: %d set: %d", rdf_size,
> + iport->max_payload_size);
> +
> + iport->r_a_tov = ntohl(flogi_rsp->u.csp_flogi.r_a_tov);
> + iport->e_d_tov = ntohl(flogi_rsp->u.csp_flogi.e_d_tov);
> +
> + if (flogi_rsp->u.csp_flogi.features & FNIC_FC_EDTOV_NSEC)
> + iport->e_d_tov = iport->e_d_tov / FNIC_NSEC_TO_MSEC;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "From fabric: R_A_TOV: %d E_D_TOV: %d",
> + iport->r_a_tov, iport->e_d_tov);
> +
> + if (IS_FNIC_FCP_INITIATOR(fnic)) {
> + fc_host_fabric_name(iport->fnic->lport->host) =
> + get_unaligned_be64(&flogi_rsp->node_name);
> + fc_host_port_id(iport->fnic->lport->host) = iport->fcid;
> + }
> +
> + fnic_fdls_learn_fcoe_macs(iport, rx_frame, fcid);
> +
> + memcpy(&fcmac[3], fcid, 3);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Adding vNIC device MAC addr: %02x:%02x:%02x:%02x:%02x:%02x",
> + fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
> + fcmac[5]);
> + vnic_dev_add_addr(iport->fnic->vdev, fcmac);
> +
> + if (fdls_get_state(fabric) == FDLS_STATE_FABRIC_FLOGI) {
> + fnic_fdls_start_plogi(iport);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI response received. Starting PLOGI");
> + } else {
> + /* From FDLS_STATE_FABRIC_FLOGI state fabric can only go to
> + * FDLS_STATE_LINKDOWN
> + * state, hence we don't have to worry about undoing:
> + * the fnic_fdls_register_portid and vnic_dev_add_addr
> + */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI response received in state (%d). Dropping frame",
> + fdls_get_state(fabric));
> + }
> + break;
> +
> + case FC_LS_REJ:
> + els_rjt = (struct fc_els_reject_s *) fchdr;
> + if (fabric->retry_counter < iport->max_flogi_retries) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI returned FC_LS_REJ BUSY. Retry from timer routine %p",
> + iport);
> +
> + /* Retry Flogi again from the timer routine. */
> + fabric->flags |= FNIC_FDLS_RETRY_FRAME;
> +
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI returned FC_LS_REJ. Halting discovery %p", iport);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport 0x%p Canceling fabric disc timer\n",
> + iport);
> + fnic_del_fabric_timer_sync();
> + }
> + fabric->timer_pending = 0;
> + fabric->retry_counter = 0;
> + }
> + break;
> +
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI response not accepted: 0x%x",
> + flogi_rsp->command);
> + break;
> + }
> +}
> +
> +static void
> +fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + struct fc_els_s *plogi_rsp = (struct fc_els_s *) fchdr;
> + struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
> + struct fnic *fnic = iport->fnic;
> +
> + if (fdls_get_state((&iport->fabric)) != FDLS_STATE_FABRIC_PLOGI) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Fabric PLOGI response received in state (%d). Dropping frame",
> + fdls_get_state(&iport->fabric));
> + return;
> + }
> +
> + switch (plogi_rsp->command) {
> + case FC_LS_ACC:
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport fcid: 0x%x fabric PLOGI response: Accepted\n",
> + iport->fcid);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + iport->fabric.retry_counter = 0;
> + fdls_set_state(&iport->fabric, FDLS_STATE_RPN_ID);
> + fdls_send_rpn_id(iport);
> + break;
> + case FC_LS_REJ:
> + if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
> + || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
> + && (iport->fabric.retry_counter < iport->max_plogi_retries)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Fabric PLOGI FC_LS_REJ BUSY. Retry from timer routine",
> + iport->fcid);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Fabric PLOGI FC_LS_REJ. Halting discovery",
> + iport->fcid);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport fcid: 0x%x Canceling fabric disc timer\n",
> + iport->fcid);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + iport->fabric.retry_counter = 0;
> + return;
> + }
> + break;
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI response not accepted: 0x%x",
> + plogi_rsp->command);
> + break;
> + }
> +}
> +
> +static void
> +fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + uint32_t s_id;
> + struct fc_abts_ba_acc_s *ba_acc = (struct fc_abts_ba_acc_s *) fchdr;
> + struct fc_abts_ba_rjt_s *ba_rjt;
> + uint32_t fabric_state = iport->fabric.state;
> + struct fnic *fnic = iport->fnic;
> +
> + s_id = ntoh24(fchdr->sid);
> + ba_rjt = (struct fc_abts_ba_rjt_s *) fchdr;
> +
> + if (!((s_id == FC_DIR_SERVER) || (s_id == FC_DOMAIN_CONTR)
> + || (s_id == FC_FABRIC_CONTROLLER))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received abts rsp with invalid SID: 0x%x. Dropping frame",
> + s_id);
> + return;
> + }
> +
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Canceling fabric disc timer %p\n", iport);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> +
> + if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received abts rsp BA_ACC for fabric_state: %d OX_ID: 0x%x",
> + fabric_state, ba_acc->ox_id);
> + } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "BA_RJT fs: %d OX_ID: 0x%x rc: 0x%x rce: 0x%x",
> + fabric_state, ba_rjt->fchdr.ox_id,
> + ba_rjt->reason_code, ba_rjt->reason_explanation);
> + }
> +
> + /* currently error handling/retry logic is same for ABTS BA_ACC & BA_RJT */
> + switch (fabric_state) {
> + case FDLS_STATE_FABRIC_FLOGI:
> + if (fchdr->ox_id == FNIC_FLOGI_OXID) {
> + if (iport->fabric.retry_counter < iport->max_flogi_retries)
> + fdls_send_fabric_flogi(iport);
> + else
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Exceeded max FLOGI retries");
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x FABRIC_FLOGI state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> + case FDLS_STATE_FABRIC_LOGO:
> + if (fchdr->ox_id == FNIC_FLOGO_REQ_OXID) {
> + if (!RETRIES_EXHAUSTED(iport))
> + fdls_send_fabric_logo(iport);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x FABRIC_FLOGI state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> + case FDLS_STATE_FABRIC_PLOGI:
> + if (fchdr->ox_id == FNIC_PLOGI_FABRIC_OXID) {
> + if (iport->fabric.retry_counter < iport->max_plogi_retries)
> + fdls_send_fabric_plogi(iport);
> + else
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Exceeded max PLOGI retries");
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x FABRIC_PLOGI state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> +
> + case FDLS_STATE_RPN_ID:
> + if (fchdr->ox_id == FNIC_RPN_REQ_OXID) {
> + if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
> + fdls_send_rpn_id(iport);
> + } else {
> + /* go back to fabric Plogi */
> + fnic_fdls_start_plogi(iport);
> + }
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x RPN_ID state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> +
> + case FDLS_STATE_SCR:
> + if (fchdr->ox_id == FNIC_SCR_REQ_OXID) {
> + if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT)
> + fdls_send_scr(iport);
> + else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "abts rsp fab SCR after two tries. Start fabric PLOGI %p",
> + iport);
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + }
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x SCR state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> + case FDLS_STATE_REGISTER_FC4_TYPES:
> + if (fchdr->ox_id == FNIC_RFT_REQ_OXID) {
> + if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT) {
> + fdls_send_register_fc4_types(iport);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "abts rsp fab RFT_ID two tries. Start fabric PLOGI %p",
> + iport);
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + }
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x RFT state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> + case FDLS_STATE_REGISTER_FC4_FEATURES:
> + if (fchdr->ox_id == FNIC_RFF_REQ_OXID) {
> + if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT)
> + fdls_send_register_fc4_features(iport);
> + else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "abts rsp fab SCR after two tries. Start fabric PLOGI %p",
> + iport);
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + }
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x RFF state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> +
> + case FDLS_STATE_GPN_FT:
> + if (fchdr->ox_id == FNIC_GPN_FT_OXID) {
> + if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT) {
> + fdls_send_gpn_ft(iport, fabric_state);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "abts rsp fab GPN_FT after two tries %p",
> + iport);
> + }
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown abts rsp OX_ID: 0x%x GPN_FT state. Drop frame",
> + fchdr->ox_id);
> + }
> + break;
> +
> + default:
> + return;
> + }
> +}
> +
> +/*
> + * Performs a validation for all FCOE frames and return the frame type
> + */
> +int
> +fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
> + void *rx_frame, int len,
> + int fchdr_offset)
> +{
> + struct fc_hdr_s *fchdr;
> + uint8_t type;
> + uint8_t *fc_payload;
> + uint16_t oxid;
> + uint32_t s_id;
> + uint32_t d_id;
> + struct fnic *fnic = iport->fnic;
> + struct fnic_fdls_fabric_s *fabric = &iport->fabric;
> +
> + fchdr = (struct fc_hdr_s *) ((uint8_t *) rx_frame + fchdr_offset);
> + oxid = FNIC_GET_OX_ID(fchdr);
> + fc_payload = (uint8_t *) fchdr + sizeof(struct fc_hdr_s);
> + type = *fc_payload;
> + s_id = ntoh24(fchdr->sid);
> + d_id = ntoh24(fchdr->did);
> +
> + /* some common validation */
> + if (iport->fcid)
> + if (fdls_get_state(fabric) > FDLS_STATE_FABRIC_FLOGI) {
> + if ((iport->fcid != d_id) || (!FNIC_FC_FRAME_CS_CTL(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "invalid frame received. Dropping frame");
> + return -1;
> + }
> + }
> +
> + /* ABTS response */
> + if ((fchdr->r_ctl == FNIC_BA_ACC_RCTL)
> + || (fchdr->r_ctl == FNIC_BA_RJT_RCTL)) {
> + if (!(FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received ABTS invalid frame. Dropping frame");
> + return -1;
> +
> + }
> + return FNIC_BLS_ABTS_RSP;
> + }
> + if ((fchdr->r_ctl == FC_ABTS_RCTL) && (FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Receiving Abort Request from s_id: 0x%x", s_id);
> + return FNIC_BLS_ABTS_REQ;
> + }
> +
> + /* unsolicited requests frames */
> + if (FNIC_FC_FRAME_UNSOLICITED(fchdr)) {
> + switch (type) {
> + case FC_ELS_LOGO:
> + if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
> + || (!FNIC_FC_FRAME_UNSOLICITED(fchdr))
> + || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received LOGO invalid frame. Dropping frame");
> + return -1;
> + }
> + return FNIC_ELS_LOGO_REQ;
> + case FC_ELS_RSCN:
> + if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
> + || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))
> + || (!FNIC_FC_FRAME_UNSOLICITED(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received RSCN invalid FCTL. Dropping frame");
> + return -1;
> + }
> + if (s_id != FC_FABRIC_CONTROLLER)
> + return FNIC_ELS_RSCN_REQ;
> + break;
> + case FC_ELS_PLOGI_REQ:
> + return FNIC_ELS_PLOGI_REQ;
> + case FC_ELS_ECHO_REQ:
> + return FNIC_ELS_ECHO_REQ;
> + case FNIC_ELS_ADISC_REQ:
> + return FNIC_ELS_ADISC;
> + case FC_ELS_RLS_REQ:
> + return FNIC_ELS_RLS;
> + case FC_ELS_RRQ_REQ:
> + return FNIC_ELS_RRQ;
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unsupported frame (type:0x%02x) from fcid: 0x%x",
> + type, s_id);
> + return FNIC_ELS_UNSUPPORTED_REQ;
> + }
> + }
> +
> + /*response from fabric */
> + switch (oxid) {
> +
> + case FNIC_FLOGO_REQ_OXID:
> + return FNIC_FABRIC_LOGO_RSP;
> +
> + case FNIC_FLOGI_OXID:
> + if (type == FC_LS_ACC) {
> + if ((s_id != FC_DOMAIN_CONTR)
> + || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown frame. Dropping frame");
> + return -1;
> + }
> + }
> + return FNIC_FABRIC_FLOGI_RSP;
> +
> + case FNIC_PLOGI_FABRIC_OXID:
> + if (type == FC_LS_ACC) {
> + if ((s_id != FC_DIR_SERVER)
> + || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown frame. Dropping frame");
> + return -1;
> + }
> + }
> + return FNIC_FABRIC_PLOGI_RSP;
> +
> + case FNIC_SCR_REQ_OXID:
> + if (type == FC_LS_ACC) {
> + if ((s_id != FC_FABRIC_CONTROLLER)
> + || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown frame. Dropping frame");
> + return -1;
> + }
> + }
> + return FNIC_FABRIC_SCR_RSP;
> +
> + case FNIC_RPN_REQ_OXID:
> + if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown frame. Dropping frame");
> + return -1;
> + }
> + return FNIC_FABRIC_RPN_RSP;
> + case FNIC_RFT_REQ_OXID:
> + if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown frame. Dropping frame");
> + return -1;
> + }
> + return FNIC_FABRIC_RFT_RSP;
> + case FNIC_RFF_REQ_OXID:
> + if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown frame. Dropping frame");
> + return -1;
> + }
> + return FNIC_FABRIC_RFF_RSP;
> +
> + case FNIC_GPN_FT_OXID:
> + if ((s_id != FC_DIR_SERVER) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown frame. Dropping frame");
> + return -1;
> + }
> + return FNIC_FABRIC_GPN_FT_RSP;
> +
> + default:
> + /* Drop the Rx frame and log/stats it */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Solicited response: unknown OXID: 0x%x", oxid);
> + return -1;
> + }
> + return -1;
> +}
> +
> +void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
> + int len, int fchdr_offset)
> +{
> + uint16_t oxid;
> + struct fc_hdr_s *fchdr;
> + uint32_t s_id = 0;
> + uint32_t d_id = 0;
> + struct fnic *fnic = iport->fnic;
> + int frame_type;
> +
> + fchdr = (struct fc_hdr_s *) ((uint8_t *) rx_frame + fchdr_offset);
> + s_id = ntoh24(fchdr->sid);
> + d_id = ntoh24(fchdr->did);
> +
> + frame_type =
> + fnic_fdls_validate_and_get_frame_type(iport, rx_frame, len,
> + fchdr_offset);
> +
> + /*if we are in flogo drop everything else */
> + if (iport->fabric.state == FDLS_STATE_FABRIC_LOGO &&
> + frame_type != FNIC_FABRIC_LOGO_RSP)
> + return;
> +
> + switch (frame_type) {
> + case FNIC_FABRIC_FLOGI_RSP:
> + fdls_process_flogi_rsp(iport, fchdr, rx_frame);
> + break;
> + case FNIC_FABRIC_PLOGI_RSP:
> + fdls_process_fabric_plogi_rsp(iport, fchdr);
> + break;
> + case FNIC_FABRIC_RPN_RSP:
> + fdls_process_rpn_id_rsp(iport, fchdr);
> + break;
> + case FNIC_FABRIC_RFT_RSP:
> + fdls_process_rft_id_rsp(iport, fchdr);
> + break;
> + case FNIC_FABRIC_RFF_RSP:
> + fdls_process_rff_id_rsp(iport, fchdr);
> + break;
> + case FNIC_FABRIC_SCR_RSP:
> + fdls_process_scr_rsp(iport, fchdr);
> + break;
> + case FNIC_FABRIC_GPN_FT_RSP:
> + fdls_process_gpn_ft_rsp(iport, fchdr, len);
> + break;
> + case FNIC_FABRIC_LOGO_RSP:
> + fdls_process_fabric_logo_rsp(iport, fchdr);
> + break;
> +
> + case FNIC_BLS_ABTS_RSP:
> + oxid = FNIC_GET_OX_ID(fchdr);
> + if ((iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)
> + && (oxid >= FNIC_FLOGI_OXID && oxid <= FNIC_RFF_REQ_OXID)) {
> + fdls_process_fabric_abts_rsp(iport, fchdr);
> + }
> + break;
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received unknown FCoE frame of len: %d. Dropping frame", len);
> + break;
> + }
> +}
> diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
> index ce73f08ee889..2d5f438f2cc4 100644
> --- a/drivers/scsi/fnic/fnic.h
> +++ b/drivers/scsi/fnic/fnic.h
> @@ -24,6 +24,7 @@
> #include "vnic_intr.h"
> #include "vnic_stats.h"
> #include "vnic_scsi.h"
> +#include "fnic_fdls.h"
>
> #define DRV_NAME "fnic"
> #define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
> @@ -31,6 +32,7 @@
> #define PFX DRV_NAME ": "
> #define DFX DRV_NAME "%d: "
>
> +#define FABRIC_LOGO_MAX_RETRY 3
> #define DESC_CLEAN_LOW_WATERMARK 8
> #define FNIC_UCSM_DFLT_THROTTLE_CNT_BLD 16 /* UCSM default throttle count */
> #define FNIC_MIN_IO_REQ 256 /* Min IO throttle count */
> @@ -75,6 +77,8 @@
> #define FNIC_DEV_RST_TERM_DONE BIT(20)
> #define FNIC_DEV_RST_ABTS_PENDING BIT(21)
>
> +#define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)
> +
> /*
> * fnic private data per SCSI command.
> * These fields are locked by the hashed io_req_lock.
> @@ -213,12 +217,26 @@ enum fnic_state {
>
> struct mempool;
>
> +enum fnic_role_e {
> + FNIC_ROLE_FCP_INITIATOR = 0,
> +};
> +
> enum fnic_evt {
> FNIC_EVT_START_VLAN_DISC = 1,
> FNIC_EVT_START_FCF_DISC = 2,
> FNIC_EVT_MAX,
> };
>
> +struct fnic_frame_list {
> + /*
> + * Link to frame lists
> + */
> + struct list_head links;
> + void *fp;
> + int frame_len;
> + int rx_ethhdr_stripped;
> +};
> +
> struct fnic_event {
> struct list_head list;
> struct fnic *fnic;
> @@ -235,6 +253,8 @@ struct fnic_cpy_wq {
> /* Per-instance private data structure */
> struct fnic {
> int fnic_num;
> + enum fnic_role_e role;
> + struct fnic_iport_s iport;
> struct fc_lport *lport;
> struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
> struct vnic_dev_bar bar0;
> @@ -278,6 +298,7 @@ struct fnic {
> unsigned long state_flags; /* protected by host lock */
> enum fnic_state state;
> spinlock_t fnic_lock;
> + unsigned long lock_flags;
>
> u16 vlan_id; /* VLAN tag including priority */
> u8 data_src_addr[ETH_ALEN];
> @@ -307,7 +328,7 @@ struct fnic {
> struct work_struct frame_work;
> struct work_struct flush_work;
> struct sk_buff_head frame_queue;
> - struct sk_buff_head tx_queue;
> + struct list_head tx_queue;
>
> /*** FIP related data members -- start ***/
> void (*set_vlan)(struct fnic *, u16 vlan);
> @@ -397,7 +418,6 @@ void fnic_handle_fip_frame(struct work_struct *work);
> void fnic_handle_fip_event(struct fnic *fnic);
> void fnic_fcoe_reset_vlans(struct fnic *fnic);
> void fnic_fcoe_evlist_free(struct fnic *fnic);
> -extern void fnic_handle_fip_timer(struct fnic *fnic);
>
> static inline int
> fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
> @@ -406,4 +426,6 @@ fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
> }
> void __fnic_set_state_flags(struct fnic *, unsigned long, unsigned long);
> void fnic_dump_fchost_stats(struct Scsi_Host *, struct fc_host_statistics *);
> +void fnic_free_txq(struct list_head *head);
> +
> #endif /* _FNIC_H_ */
> diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
> index a08293b2ad9f..90d0c4c8920c 100644
> --- a/drivers/scsi/fnic/fnic_fcs.c
> +++ b/drivers/scsi/fnic/fnic_fcs.c
> @@ -20,6 +20,8 @@
> #include "fnic_io.h"
> #include "fnic.h"
> #include "fnic_fip.h"
> +#include "fnic_fdls.h"
> +#include "fdls_fc.h"
> #include "cq_enet_desc.h"
> #include "cq_exch_desc.h"
>
> @@ -28,12 +30,90 @@ struct workqueue_struct *fnic_fip_queue;
> struct workqueue_struct *fnic_event_queue;
>
> static void fnic_set_eth_mode(struct fnic *);
> -static void fnic_fcoe_send_vlan_req(struct fnic *fnic);
> static void fnic_fcoe_start_fcf_disc(struct fnic *fnic);
> static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *);
> static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag);
> static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb);
>
> +/* Frame initialization */
> +/*
> + * Variables:
> + * dst_mac, src_mac
> + */
> +struct fnic_eth_hdr_s fnic_eth_hdr_fcoe = {
> + .ether_type = 0x0689
> +};
> +
> +/*
> + * Variables:
> + * None
> + */
> +struct fnic_fcoe_hdr_s fnic_fcoe_hdr = {
> + .sof = 0x2E
> +};
> +
> +uint8_t FCOE_ALL_FCF_MAC[6] = { 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe };
> +
> +/*
> + * Internal Functions
> + * This function will initialize the src_mac address to be
> + * used in outgoing frames
> + */
> +static inline void fnic_fdls_set_fcoe_srcmac(struct fnic *fnic,
> + uint8_t *src_mac)
> +{
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "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]);
> +
> + memcpy(fnic->iport.fpma, src_mac, 6);
> +}
> +
> +/*
> + * This function will initialize the dst_mac address to be
> + * used in outgoing frames
> + */
> +static inline void fnic_fdls_set_fcoe_dstmac(struct fnic *fnic,
> + uint8_t *dst_mac)
> +{
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "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]);
> +
> + memcpy(fnic->iport.fcfmac, dst_mac, 6);
> +}
> +
> +/*
> + * FPMA can be either taken from ethhdr(dst_mac) or flogi resp
> + * or derive from FC_MAP and FCID combination. While it should be
> + * same, revisit this if there is any possibility of not-correct.
> + */
> +void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
> + uint8_t *fcid)
> +{
> + struct fnic *fnic = iport->fnic;
> + struct fnic_eth_hdr_s *ethhdr = (struct fnic_eth_hdr_s *) rx_frame;
> + uint8_t fcmac[6] = { 0x0E, 0xFC, 0x00, 0x00, 0x00, 0x00 };
> +
> + memcpy(&fcmac[3], fcid, 3);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "learn fcoe: dst_mac: %02x:%02x:%02x:%02x:%02x:%02x",
> + ethhdr->dst_mac[0], ethhdr->dst_mac[1],
> + ethhdr->dst_mac[2], ethhdr->dst_mac[3],
> + ethhdr->dst_mac[4], ethhdr->dst_mac[5]);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "learn fcoe: fc_mac: %02x:%02x:%02x:%02x:%02x:%02x",
> + fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
> + fcmac[5]);
> +
> + fnic_fdls_set_fcoe_srcmac(fnic, fcmac);
> + fnic_fdls_set_fcoe_dstmac(fnic, ethhdr->src_mac);
> +}
> +
> void fnic_handle_link(struct work_struct *work)
> {
> struct fnic *fnic = container_of(work, struct fnic, link_work);
> @@ -363,7 +443,7 @@ static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip,
> return 0;
> }
>
> -static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
> +void fnic_fcoe_send_vlan_req(struct fnic *fnic)
> {
> struct fcoe_ctlr *fip = &fnic->ctlr;
> struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> @@ -1068,116 +1148,125 @@ void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
> /*
> * Send FC frame.
> */
> -static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
> +static int fnic_send_frame(struct fnic *fnic, void *frame, int frame_len)
> {
> struct vnic_wq *wq = &fnic->wq[0];
> - struct sk_buff *skb;
> dma_addr_t pa;
> - struct ethhdr *eth_hdr;
> - struct vlan_ethhdr *vlan_hdr;
> - struct fcoe_hdr *fcoe_hdr;
> - struct fc_frame_header *fh;
> - u32 tot_len, eth_hdr_len;
> int ret = 0;
> unsigned long flags;
>
> - fh = fc_frame_header_get(fp);
> - skb = fp_skb(fp);
> + pa = dma_map_single(&fnic->pdev->dev, frame, frame_len, DMA_TO_DEVICE);
>
> - if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
> - fcoe_ctlr_els_send(&fnic->ctlr, fnic->lport, skb))
> - return 0;
> + if ((fnic_fc_trace_set_data(fnic->fnic_num,
> + FNIC_FC_SEND | 0x80, (char *) frame,
> + frame_len)) != 0) {

Indentation running amok...

> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic ctlr frame trace error");
> + }
>
> - if (!fnic->vlan_hw_insert) {
> - eth_hdr_len = sizeof(*vlan_hdr) + sizeof(*fcoe_hdr);
> - vlan_hdr = skb_push(skb, eth_hdr_len);
> - eth_hdr = (struct ethhdr *)vlan_hdr;
> - vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
> - vlan_hdr->h_vlan_encapsulated_proto = htons(ETH_P_FCOE);
> - vlan_hdr->h_vlan_TCI = htons(fnic->vlan_id);
> - fcoe_hdr = (struct fcoe_hdr *)(vlan_hdr + 1);
> - } else {
> - eth_hdr_len = sizeof(*eth_hdr) + sizeof(*fcoe_hdr);
> - eth_hdr = skb_push(skb, eth_hdr_len);
> - eth_hdr->h_proto = htons(ETH_P_FCOE);
> - fcoe_hdr = (struct fcoe_hdr *)(eth_hdr + 1);
> + spin_lock_irqsave(&fnic->wq_lock[0], flags);
> +
> + if (!vnic_wq_desc_avail(wq)) {
> + dma_unmap_single(&fnic->pdev->dev, pa, frame_len, DMA_TO_DEVICE);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "vnic work queue descriptor is not available");
> + ret = -1;
> + goto fnic_send_frame_end;
> }
>
> - if (fnic->ctlr.map_dest)
> - fc_fcoe_set_mac(eth_hdr->h_dest, fh->fh_d_id);
> - else
> - memcpy(eth_hdr->h_dest, fnic->ctlr.dest_addr, ETH_ALEN);
> - memcpy(eth_hdr->h_source, fnic->data_src_addr, ETH_ALEN);
> + /* hw inserts cos value */
> + fnic_queue_wq_desc(wq, frame, pa, frame_len, FNIC_FCOE_EOF,
> + 0, fnic->vlan_id, 1, 1, 1);
>
> - tot_len = skb->len;
> - BUG_ON(tot_len % 4);
> +fnic_send_frame_end:
> + spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
> + return ret;
> +}
>
> - memset(fcoe_hdr, 0, sizeof(*fcoe_hdr));
> - fcoe_hdr->fcoe_sof = fr_sof(fp);
> - if (FC_FCOE_VER)
> - FC_FCOE_ENCAPS_VER(fcoe_hdr, FC_FCOE_VER);
> +static int
> +fdls_send_fcoe_frame(struct fnic *fnic, void *payload, int payload_sz,
> + uint8_t *srcmac, uint8_t *dstmac)
> +{
> + uint8_t *frame;
> + struct fnic_eth_hdr_s *ethhdr;
> + struct fnic_frame_list *frame_elem;
> + int max_framesz = FNIC_FCOE_FRAME_MAXSZ;
> + int len = 0;
> + int ret;
>
> - pa = dma_map_single(&fnic->pdev->dev, eth_hdr, tot_len, DMA_TO_DEVICE);
> - if (dma_mapping_error(&fnic->pdev->dev, pa)) {
> - ret = -ENOMEM;
> - printk(KERN_ERR "DMA map failed with error %d\n", ret);
> - goto free_skb_on_err;
> + frame = kmalloc(max_framesz, GFP_ATOMIC);
> + if (!frame) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Failed to allocate frame for flogi\n");
> + return -ENOMEM;
> }
> + memset(frame, 0, max_framesz);
> + ethhdr = (struct fnic_eth_hdr_s *) frame;
>
> - if ((fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_SEND,
> - (char *)eth_hdr, tot_len)) != 0) {
> - printk(KERN_ERR "fnic ctlr frame trace error!!!");
> - }
> + memcpy(frame, (uint8_t *) &fnic_eth_hdr_fcoe,
> + sizeof(struct fnic_eth_hdr_s));
> + len = sizeof(struct fnic_eth_hdr_s);
>
> - spin_lock_irqsave(&fnic->wq_lock[0], flags);
> + memcpy(ethhdr->src_mac, srcmac, ETH_ALEN);
> + memcpy(ethhdr->dst_mac, dstmac, ETH_ALEN);
>
> - if (!vnic_wq_desc_avail(wq)) {
> - dma_unmap_single(&fnic->pdev->dev, pa, tot_len, DMA_TO_DEVICE);
> - ret = -1;
> - goto irq_restore;
> - }
> + memcpy(frame + len, (uint8_t *) &fnic_fcoe_hdr,
> + sizeof(struct fnic_fcoe_hdr_s));
> + len += sizeof(struct fnic_fcoe_hdr_s);
>
> - fnic_queue_wq_desc(wq, skb, pa, tot_len, fr_eof(fp),
> - 0 /* hw inserts cos value */,
> - fnic->vlan_id, 1, 1, 1);
> + memcpy(frame + len, (uint8_t *) payload, payload_sz);
> + len += payload_sz;
>
> -irq_restore:
> - spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
> + /*
> + * Queue frame if in a transitional state.
> + * This occurs while registering the Port_ID / MAC address after FLOGI.
> + */
> + if ((fnic->state != FNIC_IN_FC_MODE)
> + && (fnic->state != FNIC_IN_ETH_MODE)) {
> + frame_elem = kmalloc(sizeof(struct fnic_frame_list), GFP_ATOMIC);
> + if (!frame_elem) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Failed to allocate memory for fnic_frame_list: %ld\n",
> + sizeof(struct fnic_frame_list));
> + return -ENOMEM;
> + }
> + memset(frame_elem, 0, sizeof(struct fnic_frame_list));
>
> -free_skb_on_err:
> - if (ret)
> - dev_kfree_skb_any(fp_skb(fp));
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Queuing frame: 0x%p\n", frame);
>
> + frame_elem->fp = frame;
> + frame_elem->frame_len = len;
> + list_add_tail(&frame_elem->links, &fnic->tx_queue);
> + return 0;
> + }
> +
> + ret = fnic_send_frame(fnic, frame, len);
> return ret;
> }
>
> -/*
> - * fnic_send
> - * Routine to send a raw frame
> - */
> -int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
> +int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
> + int payload_sz)
> {
> - struct fnic *fnic = lport_priv(lp);
> - unsigned long flags;
> + struct fnic *fnic = iport->fnic;
> + uint8_t *dstmac, *srcmac;
> + int ret = 0;
>
> + /* If module unload is in-progress, don't send */
> if (fnic->in_remove) {
> - dev_kfree_skb(fp_skb(fp));
> return -1;
> }
>
> - /*
> - * Queue frame if in a transitional state.
> - * This occurs while registering the Port_ID / MAC address after FLOGI.
> - */
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - if (fnic->state != FNIC_IN_FC_MODE && fnic->state != FNIC_IN_ETH_MODE) {
> - skb_queue_tail(&fnic->tx_queue, fp_skb(fp));
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - return 0;
> + if (iport->fabric.flags & FNIC_FDLS_FPMA_LEARNT) {
> + srcmac = iport->fpma;
> + dstmac = iport->fcfmac;
> + } else {
> + srcmac = iport->hwmac;
> + dstmac = FCOE_ALL_FCF_MAC;
> }
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
>
> - return fnic_send_frame(fnic, fp);
> + ret = fdls_send_fcoe_frame(fnic, payload, payload_sz, srcmac, dstmac);
> + return ret;
> }
>
> /**
> @@ -1193,13 +1282,64 @@ int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
> void fnic_flush_tx(struct work_struct *work)
> {
> struct fnic *fnic = container_of(work, struct fnic, flush_work);
> - struct sk_buff *skb;
> struct fc_frame *fp;
> + struct fnic_frame_list *cur_frame, *next;
>
> - while ((skb = skb_dequeue(&fnic->tx_queue))) {
> - fp = (struct fc_frame *)skb;
> - fnic_send_frame(fnic, fp);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Flush queued frames");
> +
> + list_for_each_entry_safe(cur_frame, next, &fnic->tx_queue, links) {
> + fp = cur_frame->fp;
> + list_del(&cur_frame->links);
> + fnic_send_frame(fnic, fp, cur_frame->frame_len);
> + }
> +}
> +
> +int
> +fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
> + void *fp)
> +{
> + struct fnic *fnic = iport->fnic;
> + struct fnic_eth_hdr_s *ethhdr;
> + int ret;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Setting port id: 0x%x fp: 0x%p fnic state: %d", port_id,
> + fp, fnic->state);
> +
> + if (fp) {
> + ethhdr = (struct fnic_eth_hdr_s *) fp;
> + vnic_dev_add_addr(fnic->vdev, ethhdr->dst_mac);
> + }
> +
> + /* Change state to reflect transition to FC mode */
> + 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->lport->host, fnic->fnic_num,
> + "Unexpected fnic state while processing FLOGI response\n");
> + return -1;
> }
> +
> + /*
> + * Send FLOGI registration to firmware to set up FC mode.
> + * The new address will be set up when registration completes.
> + */
> + ret = fnic_flogi_reg_handler(fnic, port_id);
> + if (ret < 0) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI registration error ret: %d fnic state: %d\n",
> + ret, fnic->state);
> + if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE)
> + fnic->state = FNIC_IN_ETH_MODE;
> +
> + return -1;
> + }
> + iport->fabric.flags |= FNIC_FDLS_FPMA_LEARNT;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI registration success\n");
> + return 0;
> }
>
> /**
> @@ -1240,6 +1380,17 @@ static void fnic_set_eth_mode(struct fnic *fnic)
> spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> }
>
> +void fnic_free_txq(struct list_head *head)
> +{
> + struct fnic_frame_list *cur_frame, *next;
> +
> + list_for_each_entry_safe(cur_frame, next, head, links) {
> + list_del(&cur_frame->links);
> + kfree(cur_frame->fp);
> + kfree(cur_frame);
> + }
> +}
> +
> static void fnic_wq_complete_frame_send(struct vnic_wq *wq,
> struct cq_desc *cq_desc,
> struct vnic_wq_buf *buf, void *opaque)
> @@ -1319,88 +1470,3 @@ void fnic_fcoe_reset_vlans(struct fnic *fnic)
> spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> }
>
> -void fnic_handle_fip_timer(struct fnic *fnic)
> -{
> - unsigned long flags;
> - struct fcoe_vlan *vlan;
> - struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> - u64 sol_time;
> -
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - if (fnic->stop_rx_link_events) {
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - return;
> - }
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> -
> - if (fnic->ctlr.mode == FIP_MODE_NON_FIP)
> - return;
> -
> - spin_lock_irqsave(&fnic->vlans_lock, flags);
> - if (list_empty(&fnic->vlans)) {
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - /* no vlans available, try again */
> - if (unlikely(fnic_log_level & FNIC_FCS_LOGGING))
> - if (printk_ratelimit())
> - shost_printk(KERN_DEBUG, fnic->lport->host,
> - "Start VLAN Discovery\n");
> - fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
> - return;
> - }
> -
> - vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "fip_timer: vlan %d state %d sol_count %d\n",
> - vlan->vid, vlan->state, vlan->sol_count);
> - switch (vlan->state) {
> - case FIP_VLAN_USED:
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "FIP VLAN is selected for FC transaction\n");
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - break;
> - case FIP_VLAN_FAILED:
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - /* if all vlans are in failed state, restart vlan disc */
> - if (unlikely(fnic_log_level & FNIC_FCS_LOGGING))
> - if (printk_ratelimit())
> - shost_printk(KERN_DEBUG, fnic->lport->host,
> - "Start VLAN Discovery\n");
> - fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
> - break;
> - case FIP_VLAN_SENT:
> - if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
> - /*
> - * no response on this vlan, remove from the list.
> - * Try the next vlan
> - */
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "Dequeue this VLAN ID %d from list\n",
> - vlan->vid);
> - list_del(&vlan->list);
> - kfree(vlan);
> - vlan = NULL;
> - if (list_empty(&fnic->vlans)) {
> - /* we exhausted all vlans, restart vlan disc */
> - spin_unlock_irqrestore(&fnic->vlans_lock,
> - flags);
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "fip_timer: vlan list empty, "
> - "trigger vlan disc\n");
> - fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
> - return;
> - }
> - /* check the next vlan */
> - vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan,
> - list);
> - fnic->set_vlan(fnic, vlan->vid);
> - vlan->state = FIP_VLAN_SENT; /* sent now */
> - }
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - atomic64_inc(&fnic_stats->vlan_stats.sol_expiry_count);
> - vlan->sol_count++;
> - sol_time = jiffies + msecs_to_jiffies
> - (FCOE_CTLR_START_DELAY);
> - mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
> - break;
> - }
> -}
> diff --git a/drivers/scsi/fnic/fnic_fdls.h b/drivers/scsi/fnic/fnic_fdls.h
> index fddb9390d022..095275698716 100644
> --- a/drivers/scsi/fnic/fnic_fdls.h
> +++ b/drivers/scsi/fnic/fnic_fdls.h
> @@ -321,17 +321,20 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame, int len,
> void fnic_fdls_link_down(struct fnic_iport_s *iport);
> void fdls_init_tgt_oxid_pool(struct fnic_iport_s *iport);
> void fdls_tgt_logout(struct fnic_iport_s *iport, struct fnic_tport_s *tport);
> +void fdls_send_fabric_logo(struct fnic_iport_s *iport);
> +int fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
> + void *rx_frame, int len,
> + int fchdr_offset);
>
> /* fnic_fcs.c */
> void fnic_fdls_init(struct fnic *fnic, int usefip);
> int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
> int payload_sz);
> -
> +void fnic_fcoe_send_vlan_req(struct fnic *fnic);
> int fnic_send_fip_frame(struct fnic_iport_s *iport,
> void *payload, int payload_sz);
> void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
> uint8_t *fcid);
> -
> void fnic_fdls_add_tport(struct fnic_iport_s *iport,
> struct fnic_tport_s *tport, unsigned long flags);
> void fnic_fdls_remove_tport(struct fnic_iport_s *iport,
> diff --git a/drivers/scsi/fnic/fnic_io.h b/drivers/scsi/fnic/fnic_io.h
> index 5895ead20e14..6fe642cb387b 100644
> --- a/drivers/scsi/fnic/fnic_io.h
> +++ b/drivers/scsi/fnic/fnic_io.h
> @@ -55,15 +55,4 @@ struct fnic_io_req {
> unsigned int tag;
> struct scsi_cmnd *sc; /* midlayer's cmd pointer */
> };
> -
> -enum fnic_port_speeds {
> - DCEM_PORTSPEED_NONE = 0,
> - DCEM_PORTSPEED_1G = 1000,
> - DCEM_PORTSPEED_10G = 10000,
> - DCEM_PORTSPEED_20G = 20000,
> - DCEM_PORTSPEED_25G = 25000,
> - DCEM_PORTSPEED_40G = 40000,
> - DCEM_PORTSPEED_4x10G = 41000,
> - DCEM_PORTSPEED_100G = 100000,
> -};
> #endif /* _FNIC_IO_H_ */
> diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
> index 08730bdf8b03..577048e30c12 100644
> --- a/drivers/scsi/fnic/fnic_main.c
> +++ b/drivers/scsi/fnic/fnic_main.c
> @@ -31,6 +31,8 @@
> #include "fnic_io.h"
> #include "fnic_fip.h"
> #include "fnic.h"
> +#include "fnic_fdls.h"
> +#include "fdls_fc.h"
>
> #define PCI_DEVICE_ID_CISCO_FNIC 0x0045
>
> @@ -80,7 +82,6 @@ module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR);
> MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN");
>
> static struct libfc_function_template fnic_transport_template = {
> - .frame_send = fnic_send,
> .lport_set_port_id = fnic_set_port_id,
> .fcp_abort_io = fnic_empty_scsi_cleanup,
> .fcp_cleanup = fnic_empty_scsi_cleanup,
> @@ -413,7 +414,7 @@ static void fnic_fip_notify_timer(struct timer_list *t)
> {
> struct fnic *fnic = from_timer(fnic, t, fip_timer);
>
> - fnic_handle_fip_timer(fnic);
> + /* Placeholder function */
> }
>
> static void fnic_notify_timer_start(struct fnic *fnic)
> @@ -921,7 +922,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> INIT_WORK(&fnic->link_work, fnic_handle_link);
> INIT_WORK(&fnic->frame_work, fnic_handle_frame);
> skb_queue_head_init(&fnic->frame_queue);
> - skb_queue_head_init(&fnic->tx_queue);
> + INIT_LIST_HEAD(&fnic->tx_queue);
>
> fc_fabric_login(lp);
>
> @@ -1004,7 +1005,7 @@ static void fnic_remove(struct pci_dev *pdev)
> */
> flush_workqueue(fnic_event_queue);
> skb_queue_purge(&fnic->frame_queue);
> - skb_queue_purge(&fnic->tx_queue);
> + fnic_free_txq(&fnic->tx_queue);
>
> if (fnic->config.flags & VFCF_FIP_CAPABLE) {
> del_timer_sync(&fnic->fip_timer);
> @@ -1036,7 +1037,6 @@ static void fnic_remove(struct pci_dev *pdev)
> fnic_cleanup(fnic);
>
> BUG_ON(!skb_queue_empty(&fnic->frame_queue));
> - BUG_ON(!skb_queue_empty(&fnic->tx_queue));
>
> spin_lock_irqsave(&fnic_list_lock, flags);
> list_del(&fnic->list);
> diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
> index 2ba61dba4569..295dcda4ec16 100644
> --- a/drivers/scsi/fnic/fnic_scsi.c
> +++ b/drivers/scsi/fnic/fnic_scsi.c
> @@ -184,7 +184,7 @@ int fnic_fw_reset_handler(struct fnic *fnic)
> fnic_set_state_flags(fnic, FNIC_FLAGS_FWRESET);
>
> skb_queue_purge(&fnic->frame_queue);
> - skb_queue_purge(&fnic->tx_queue);
> + fnic_free_txq(&fnic->tx_queue);
>
> /* wait for io cmpl */
> while (atomic_read(&fnic->in_flight))
> @@ -674,7 +674,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
> */
> if (fnic->remove_wait || ret) {
> spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - skb_queue_purge(&fnic->tx_queue);
> + fnic_free_txq(&fnic->tx_queue);
> goto reset_cmpl_handler_end;
> }
>
> @@ -1717,7 +1717,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
> return true;
> }
>
> -static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
> +void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
> {
> struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
> struct fnic_rport_abort_io_iter_data iter_data = {

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-11 13:46:10

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 04/14] scsi: fnic: Add support for target based solicited requests and responses

On 6/10/24 23:50, Karan Tilak Kumar wrote:
> Add support for target based solicited requests and responses.
> Add support for tport definitions and processing.
> Add support for restarting the IT nexus.
>
> Reviewed-by: Sesidhar Baddela <[email protected]>
> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> Reviewed-by: Gian Carlo Boffa <[email protected]>
> Signed-off-by: Karan Tilak Kumar <[email protected]>
> ---
> drivers/scsi/fnic/fdls_disc.c | 1540 +++++++++++++++++++++++++++++++--
> drivers/scsi/fnic/fnic.h | 6 +
> drivers/scsi/fnic/fnic_fdls.h | 4 +
> 3 files changed, 1473 insertions(+), 77 deletions(-)
>
> diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
> index 22a2d0c1c78f..d920202d413d 100644
> --- a/drivers/scsi/fnic/fdls_disc.c
> +++ b/drivers/scsi/fnic/fdls_disc.c
> @@ -11,6 +11,8 @@
> #include <scsi/fc/fc_fcp.h>
> #include <linux/utsname.h>
>
> +#define FC_FC4_TYPE_SCSI 0x08
> +
> static void fdls_send_rpn_id(struct fnic_iport_s *iport);
>
> /* Frame initialization */
> @@ -59,6 +61,19 @@ struct fc_rpn_id_s fnic_rpn_id_req = {
> .command = FC_CT_RPN_CMD}
> };
>
> +/*
> + * Variables:
> + * did, sid, oxid
> + */
> +struct fc_els_prli_s fnic_prli_req = {
> + .fchdr = {.r_ctl = 0x22, .type = 0x01,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .rx_id = 0xFFFF},
> + .command = FC_ELS_PRLI_REQ,
> + .page_len = 16,
> + .payload_len = 0x1400,
> + .sp = {.type = 0x08, .flags = 0x0020, .csp = 0xA2000000}
> +};
> +
> /*
> * Variables:
> * fh_s_id, port_id, port_name
> @@ -123,11 +138,51 @@ struct fc_logo_req_s fnic_logo_req = {
> #define RETRIES_EXHAUSTED(iport) \
> (iport->fabric.retry_counter == FABRIC_LOGO_MAX_RETRY)
>
> +#define FNIC_TPORT_MAX_NEXUS_RESTART (8)
> +
> +/* Private Functions */
> static void fdls_process_flogi_rsp(struct fnic_iport_s *iport,
> struct fc_hdr_s *fchdr, void *rx_frame);
> static void fnic_fdls_start_plogi(struct fnic_iport_s *iport);
> +static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
> + uint32_t fcid,
> + uint64_t wwpn);
> +static void fdls_target_restart_nexus(struct fnic_tport_s *tport);
> +static void fdls_start_tport_timer(struct fnic_iport_s *iport,
> + struct fnic_tport_s *tport, int timeout);
> +
> static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
> int timeout);
> +static void fdls_tport_timer_callback(struct timer_list *t);
> +
> +static uint16_t fdls_alloc_tgt_oxid(struct fnic_iport_s *iport,
> + uint16_t base)
> +{
> + int i;
> + int start, end;
> +
> + start = base - FDLS_PLOGI_OXID_BASE;
> + end = start + FDLS_TGT_OXID_BLOCK_SZ;
> +
> + for (i = start; i < end; i++) {
> + if (iport->tgt_oxid_pool[i] == 0) {
> + iport->tgt_oxid_pool[i] = 1;
> + return (i + FDLS_PLOGI_OXID_BASE);
> + }
> + }
> + return 0xFFFF;
> +}
> +
> +static void fdls_free_tgt_oxid(struct fnic_iport_s *iport, uint16_t oxid)
> +{
> + struct fnic *fnic = iport->fnic;
> +
> + if (iport->tgt_oxid_pool[oxid - FDLS_PLOGI_OXID_BASE] != 1) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Freeing unused OXID: 0x%x", oxid);
> + }
> + iport->tgt_oxid_pool[oxid - FDLS_PLOGI_OXID_BASE] = 0;
> +}
>
Better use a bitmap here; fdls_alloc_tgt_oxid() is not atomic, and will
need to be locked to avoid races.

> static void
> fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
> @@ -153,6 +208,63 @@ fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
> "fabric timer is %d ", timeout);
> }
>
> +static void
> +fdls_start_tport_timer(struct fnic_iport_s *iport,
> + struct fnic_tport_s *tport, int timeout)
> +{
> + u64 fabric_tov;
> + struct fnic *fnic = iport->fnic;
> +
> + if (tport->timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport fcid 0x%x: Canceling disc timer\n",
> + tport->fcid);
> + fnic_del_tport_timer_sync();
> + tport->timer_pending = 0;
> + }
> +
> + if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED))
> + tport->retry_counter++;
> +
> + fabric_tov = jiffies + msecs_to_jiffies(timeout);
> + mod_timer(&tport->retry_timer, round_jiffies(fabric_tov));
> + tport->timer_pending = 1;
> +}
> +
> +void
> +fdls_send_tport_abts(struct fnic_iport_s *iport,
> + struct fnic_tport_s *tport)
> +{
> + uint8_t s_id[3];
> + uint8_t d_id[3];
> + struct fnic *fnic = iport->fnic;
> +
> + struct fc_hdr_s fc_abts_s = {
> + .r_ctl = 0x81, /* ABTS */
> + .cs_ctl = 0x00, .type = 0x00, .f_ctl = FNIC_REQ_ABTS_FCTL, .seq_id =
> + 0x00, .df_ctl = 0x00, .seq_cnt = 0x0000, .rx_id = 0xFFFF,
> + .param = 0x00000000, /* bit:0 = 0 Abort a exchange */
> + };
Why do you define this as a local variable, but frames as globals?
Please make all of these frames global.

> +
> + struct fc_hdr_s *pfc_abts = &fc_abts_s;
> +
> + hton24(s_id, iport->fcid);
> + hton24(d_id, tport->fcid);
> + FNIC_SET_S_ID(pfc_abts, s_id);
> + FNIC_SET_D_ID(pfc_abts, d_id);
> + tport->flags |= FNIC_FDLS_TGT_ABORT_ISSUED;
> +
> + fc_abts_s.ox_id = tport->oxid_used;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS sending tport abts: tport->state: %d ",
> + tport->state);
> +
> + fnic_send_fcoe_frame(iport, &fc_abts_s, sizeof(struct fc_hdr_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_tport_timer(iport, tport, 2 * iport->r_a_tov);
> +}
> +
> static void fdls_send_fabric_abts(struct fnic_iport_s *iport)
> {
> uint8_t fcid[3];
> @@ -338,6 +450,169 @@ static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state)
> fdls_set_state((&iport->fabric), fdls_state);
> }
>
> +static void
> +fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
> +{
> + struct fc_els_adisc_s adisc;
> + uint8_t s_id[3];
> + uint8_t d_id[3];
> + uint16_t oxid;
> + struct fnic *fnic = iport->fnic;
> +
> + memset(&adisc, 0, sizeof(struct fc_els_adisc_s));
> + adisc.fchdr.r_ctl = 0x22;
> + adisc.fchdr.type = 0x01;
> + adisc.fchdr.f_ctl = FNIC_ELS_REQ_FCTL;
> + adisc.fchdr.rx_id = 0xFFFF;
> +
> + hton24(s_id, iport->fcid);
> + hton24(d_id, tport->fcid);
> + FNIC_SET_S_ID((&adisc.fchdr), s_id);
> + FNIC_SET_D_ID((&adisc.fchdr), d_id);
> +
> + oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_ADISC_OXID_BASE));
> + if (oxid == 0xFFFF) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Failed to allocate OXID to send ADISC %p", iport);
> + return;
> + }
> +
> + tport->oxid_used = oxid;
> + tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
> +
> + FNIC_SET_OX_ID((&adisc.fchdr), oxid);
> + FNIC_SET_NPORT_NAME(adisc, iport->wwpn);
> + FNIC_SET_NODE_NAME(adisc, iport->wwnn);
> +
> + memcpy(adisc.fcid, s_id, 3);
> + adisc.command = FNIC_ELS_ADISC_REQ;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "sending ADISC to tgt fcid: 0x%x", tport->fcid);
> +
> + fnic_send_fcoe_frame(iport, &adisc, sizeof(struct fc_els_adisc_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_tport_timer(iport, tport, 2 * iport->e_d_tov);

How do you recover the oxid if fnic_send_fcoe_frame() fails?

> +}
> +
> +void fdls_delete_tport(struct fnic_iport_s *iport,
> + struct fnic_tport_s *tport)
> +{
> + struct fnic_tport_event_s *tport_del_evt;
> + struct fnic *fnic = iport->fnic;
> +
> + if ((tport->state == FDLS_TGT_STATE_OFFLINING)
> + || (tport->state == FDLS_TGT_STATE_OFFLINE))
> + return;
> +
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINING);
> + /*
> + * By setting this flag, the tport will not be seen in a look-up
> + * in an RSCN. Even if we move to multithreaded model, this tport
> + * will be destroyed and a new RSCN will have to create a new one
> + */
> + tport->flags |= FNIC_FDLS_TPORT_TERMINATING;
> +
> + if (tport->timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport fcid 0x%x: Canceling disc timer\n",
> + tport->fcid);
> + fnic_del_tport_timer_sync();
> + tport->timer_pending = 0;
> + }
> +
> + if (IS_FNIC_FCP_INITIATOR(fnic)) {
> + spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
> + fnic_rport_exch_reset(iport->fnic, tport->fcid);
> + spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
> +
> + if (tport->flags & FNIC_FDLS_SCSI_REGISTERED) {
> + tport_del_evt =
> + kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
> + if (!tport_del_evt) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Failed to allocate memory for tport fcid: 0x%0x\n",
> + tport->fcid);
> + return;
> + }
> + tport_del_evt->event = TGT_EV_RPORT_DEL;
> + tport_del_evt->arg1 = (void *) tport;
> + list_add_tail(&tport_del_evt->links, &fnic->tport_event_list);
> + queue_work(fnic_event_queue, &fnic->tport_work);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport 0x%x not reg with scsi_transport. Freeing locally",
> + tport->fcid);
> + list_del(&tport->links);
> + kfree(tport);
> + }
> + }
> +}
> +
I'm slightly curious about locking here.
You do call spin_lock() etc when calling fnic_rport_exch_reset(), so
apparently this function runs lockless. But if it does, how do you
ensure that 'tport->flags' is not modified after checking, causing
you do queue an event for a tport which is already unregistered?
Maybe you should look at reference counting for tports?

> +static void
> +fdls_send_tgt_plogi(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
> +{
> + struct fc_els_s plogi;
> + uint8_t s_id[3];
> + uint8_t d_id[3];
> + uint16_t oxid;
> + struct fnic *fnic = iport->fnic;
> + uint32_t timeout;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Send tgt PLOGI to fcid: 0x%x", tport->fcid);
> +
> + memcpy(&plogi, &fnic_plogi_req, sizeof(struct fc_els_s));
> +
> + hton24(s_id, iport->fcid);
> + hton24(d_id, tport->fcid);
> +
> + FNIC_SET_S_ID((&plogi.fchdr), s_id);
> + FNIC_SET_D_ID((&plogi.fchdr), d_id);
> + FNIC_SET_RDF_SIZE(plogi.u.csp_plogi, iport->max_payload_size);
> +
> + oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_PLOGI_OXID_BASE));
> + if (oxid == 0xFFFF) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Failed to allocate oxid to send PLOGI to fcid: 0x%x",
> + iport->fcid, tport->fcid);
> + return;
> + }
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "send tgt PLOGI: tgt fcid: 0x%x oxid: 0x%x", tport->fcid,
> + ntohs(oxid));
> + tport->oxid_used = oxid;
> + tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
> +
> + FNIC_SET_OX_ID((&plogi.fchdr), oxid);
> + FNIC_SET_NPORT_NAME(plogi, iport->wwpn);
> + FNIC_SET_NODE_NAME(plogi, iport->wwnn);
> +
> + timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);
> +
> + fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_tport_timer(iport, tport, timeout);
> +}
> +
> +static uint16_t
> +fnic_fc_plogi_rsp_rdf(struct fnic_iport_s *iport,
> + struct fc_els_s *plogi_rsp)
> +{
> + uint16_t b2b_rdf_size = ntohs(plogi_rsp->u.csp_plogi.b2b_rdf_size);
> + uint16_t spc3_rdf_size =
> + ((uint16_t) (plogi_rsp->spc3[6] << 8 | plogi_rsp->spc3[7]) &
> + FNIC_FC_C3_RDF);
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "MFS: b2b_rdf_size: 0x%x spc3_rdf_size: 0x%x",
> + b2b_rdf_size, spc3_rdf_size);
> +
> + return MIN(b2b_rdf_size, spc3_rdf_size);
> +}
> +
> static void fdls_send_register_fc4_types(struct fnic_iport_s *iport)
> {
> struct fc_rft_id rft_id;
> @@ -387,6 +662,47 @@ static void fdls_send_register_fc4_features(struct fnic_iport_s *iport)
> fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> }
>
> +static void
> +fdls_send_tgt_prli(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
> +{
> + struct fc_els_prli_s prli;
> + uint8_t s_id[3];
> + uint8_t d_id[3];
> + uint16_t oxid;
> + struct fnic *fnic = iport->fnic;
> + uint32_t timeout;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS sending PRLI to tgt: 0x%x", tport->fcid);
> +
> + oxid = htons(fdls_alloc_tgt_oxid(iport, FDLS_PRLI_OXID_BASE));
> + if (oxid == 0xFFFF) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Failed to allocate OXID to send PRLI %p", iport);
> + return;
> + }
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS sending PRLI to tgt: 0x%x OXID: 0x%x", tport->fcid,
> + ntohs(oxid));
> +
> + tport->oxid_used = oxid;
> + tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
> + memcpy(&prli, &fnic_prli_req, sizeof(struct fc_els_prli_s));
> +
> + hton24(s_id, iport->fcid);
> + hton24(d_id, tport->fcid);
> +
> + FNIC_SET_S_ID((&prli.fchdr), s_id);
> + FNIC_SET_D_ID((&prli.fchdr), d_id);
> + FNIC_SET_OX_ID((&prli.fchdr), oxid);
> +
> + timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);
> +
> + fnic_send_fcoe_frame(iport, &prli, sizeof(struct fc_els_prli_s));
> + /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
> + fdls_start_tport_timer(iport, tport, timeout);
> +}
> +
> /***********************************************************************
> * fdls_send_fabric_logo
> *
> @@ -434,6 +750,208 @@ void fdls_send_fabric_logo(struct fnic_iport_s *iport)
> fnic_send_fcoe_frame(iport, &logo, sizeof(struct fc_logo_req_s));
> }
>
> +/***********************************************************************
> + * fdls_tgt_logout
> + *
> + * \brief Send plogo to the remote port
> + *
> + * \param[in] iport Handle to fnic iport. remote port
> + *
> + * \retval void
> + *
> + * \note This function does not change or check the fabric/tport state.
> + * It the caller responsibility to set the appropriate tport/fabric
> + * state when this is called. Normall fdls_tgt_state_plogo.
> + * fdls_set_tport_state(tport, fdls_tgt_state_plogo)
> + *
> + *\note This could be used to send plogo to nameserver process
> + * also not just target processes
> + *
> + ***********************************************************************/

Please convert to valid kernel-doc format.

> +void fdls_tgt_logout(struct fnic_iport_s *iport,
> + struct fnic_tport_s *tport)
> +{
> + struct fc_logo_req_s logo;
> + uint8_t s_id[3];
> + uint8_t d_id[3];
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Sending logo to tport fcid: 0x%x", tport->fcid);
> + memcpy(&logo, &fnic_logo_req, sizeof(struct fc_logo_req_s));
> +
> + hton24(s_id, iport->fcid);
> + hton24(d_id, tport->fcid);
> +
> + FNIC_SET_S_ID((&logo.fchdr), s_id);
> + FNIC_SET_D_ID((&logo.fchdr), d_id);
> + FNIC_SET_OX_ID((&logo.fchdr), FNIC_TLOGO_REQ_OXID);
> +
> + memcpy(&logo.fcid, s_id, 3);
> + logo.wwpn = htonll(iport->wwpn);
> +
> + fnic_send_fcoe_frame(iport, &logo, sizeof(struct fc_logo_req_s));
> +}
> +
> +static void fdls_tgt_discovery_start(struct fnic_iport_s *iport)
> +{
> + struct fnic_tport_s *tport, *next;
> + u32 old_link_down_cnt = iport->fnic->link_down_cnt;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Starting FDLS target discovery", iport->fcid);
> +
> + list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
> + if ((old_link_down_cnt != iport->fnic->link_down_cnt)
> + || (iport->state != FNIC_IPORT_STATE_READY)) {
> + break;
> + }
> + /* if we marked the tport as deleted due to GPN_FT
> + * We should not send ADISC anymore
> + */
> + if ((tport->state == FDLS_TGT_STATE_OFFLINING) ||
> + (tport->state == FDLS_TGT_STATE_OFFLINE))
> + continue;

This check is not atomic, ensure that there are not side-effects.
Maybe check if the 'state' variable shouldn't be protected.

> +
> + /* For tports which have received RSCN */
> + if (tport->flags & FNIC_FDLS_TPORT_SEND_ADISC) {
> + tport->retry_counter = 0;
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_ADISC);
> + tport->flags &= ~FNIC_FDLS_TPORT_SEND_ADISC;
> + fdls_send_tgt_adisc(iport, tport);
> + continue;
> + }
> + if (fdls_get_tport_state(tport) != FDLS_TGT_STATE_INIT) {
> + /* Not a new port, skip */
> + continue;
> + }
> + tport->retry_counter = 0;
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
> + fdls_send_tgt_plogi(iport, tport);
> + }
> + fdls_set_state((&iport->fabric), FDLS_STATE_TGT_DISCOVERY);
> +}
> +
> +/*
> + * Function to restart the IT nexus if we received any out of
> + * sequence PLOGI/PRLI response from the target.
> + * The memory for the new tport structure is allocated
> + * inside fdls_create_tport and added to the iport's tport list.
> + * This will get freed later during tport_offline/linkdown
> + * or module unload. The new_tport pointer will go out of scope
> + * safely since the memory it is
> + * pointing to it will be freed later
> + */
> +static void fdls_target_restart_nexus(struct fnic_tport_s *tport)
> +{
> + struct fnic_iport_s *iport = tport->iport;
> + struct fnic_tport_s *new_tport = NULL;
> + uint32_t fcid;
> + uint64_t wwpn;
> + int nexus_restart_count;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport fcid: 0x%x state: %d restart_count: %d",
> + tport->fcid, tport->state, tport->nexus_restart_count);
> +
> + fcid = tport->fcid;
> + wwpn = tport->wwpn;
> + nexus_restart_count = tport->nexus_restart_count;
> +
> + fdls_delete_tport(iport, tport);

And this can't fail? Really?

> +
> + if (nexus_restart_count >= FNIC_TPORT_MAX_NEXUS_RESTART) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Exceeded nexus restart retries tport: 0x%x", fcid);
> + return;
> + }
> +
> + /*
> + * Allocate memory for the new tport and add it to
> + * iport's tport list.
> + * This memory will be freed during tport_offline/linkdown
> + * or module unload. The pointer new_tport is safe to go
> + * out of scope when this function returns, since the memory
> + * it is pointing to is guaranteed to be freed later
> + * as mentioned above.
> + */
> + new_tport = fdls_create_tport(iport, fcid, wwpn);
> + if (!new_tport) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Error creating new tport: 0x%x", fcid);
> + return;
> + }
> +
> + new_tport->nexus_restart_count = nexus_restart_count + 1;
> + fdls_send_tgt_plogi(iport, new_tport);
> + fdls_set_tport_state(new_tport, FDLS_TGT_STATE_PLOGI);
> +}
> +
> +struct fnic_tport_s *fnic_find_tport_by_fcid(struct fnic_iport_s *iport,
> + uint32_t fcid)
> +{
> + struct fnic_tport_s *tport, *next;
> +
> + list_for_each_entry_safe(tport, next, &(iport->tport_list), links) {
> + if ((tport->fcid == fcid)
> + && !(tport->flags & FNIC_FDLS_TPORT_TERMINATING))
> + return tport;
> + }
> + return NULL;
> +}
> +

Locking?
The _safe() variants protect against removal from the list, they do
_not_ protect against removal of the element itself.
Nor concurrent accesses to the same element.

> +static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
> + uint32_t fcid, uint64_t wwpn)
> +{
> + struct fnic_tport_s *tport;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS create tport: fcid: 0x%x wwpn: 0x%llx", fcid, wwpn);
> +
> + tport = kzalloc(sizeof(struct fnic_tport_s), GFP_ATOMIC);
> + if (!tport) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Memory allocation failure while creating tport: 0x%x\n",
> + fcid);
> + return NULL;
> + }
> +
> + tport->max_payload_size = FNIC_FCOE_MAX_FRAME_SZ;
> + tport->r_a_tov = FNIC_R_A_TOV_DEF;
> + tport->e_d_tov = FNIC_E_D_TOV_DEF;
> + tport->fcid = fcid;
> + tport->wwpn = wwpn;
> + tport->iport = iport;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Need to setup tport timer callback");
> +
> + timer_setup(&tport->retry_timer, fdls_tport_timer_callback, 0);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Added tport 0x%x", tport->fcid);
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_INIT);
> + list_add_tail(&tport->links, &iport->tport_list);
> + atomic_set(&tport->in_flight, 0);
> + return tport;
> +}
> +
> +struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport,
> + uint64_t wwpn)
> +{
> + struct fnic_tport_s *tport, *next;
> +
> + list_for_each_entry_safe(tport, next, &(iport->tport_list), links) {
> + if ((tport->wwpn == wwpn)
> + && !(tport->flags & FNIC_FDLS_TPORT_TERMINATING))
> + return tport;
> + }
> + return NULL;
> +}
> +
> void fdls_fabric_timer_callback(struct timer_list *t)
> {
> struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, retry_timer);
> @@ -548,98 +1066,614 @@ void fdls_fabric_timer_callback(struct timer_list *t)
> else {
> /* ABTS has timed out (2*ra_tov), we give up */
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "ABTS timed out. Starting PLOGI: %p", iport);
> - fnic_fdls_start_plogi(iport);
> + "ABTS timed out. Starting PLOGI: %p", iport);
> + fnic_fdls_start_plogi(iport);
> + }
> + break;
> + case FDLS_STATE_REGISTER_FC4_TYPES:
> + /* scr received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_register_fc4_types(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
Please don't do returns here.
Convert it into if() {} else if() {} else {} clauses, and call
spin_unlock only at the end of the switch.

> + }
> + /* RFT_ID timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> + fdls_send_fabric_abts(iport);
> + } else {
> + /* ABTS has timed out (2*ra_tov), we give up */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ABTS timed out. Starting PLOGI: %p", iport);
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + }
> + break;
> + case FDLS_STATE_REGISTER_FC4_FEATURES:
> + /* scr received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_register_fc4_features(iport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
Same here.

> + }
> + /* scr have timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
> + fdls_send_fabric_abts(iport);
> + else {
> + /* ABTS has timed out (2*ra_tov), we give up */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ABTS timed out. Starting PLOGI %p", iport);
> + fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> + }
> + break;
> + case FDLS_STATE_RSCN_GPN_FT:
> + case FDLS_STATE_SEND_GPNFT:
> + case FDLS_STATE_GPN_FT:
> + /* GPN_FT received a LS_RJT with busy we retry from here */
> + if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> + && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> + iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_gpn_ft(iport, iport->fabric.state);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }

And here.

> + /* gpn_gt have timed out send abts */
> + if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> + fdls_send_fabric_abts(iport);
> + } else {
> + /*
> + * ABTS has timed out have waited (2*ra_tov) can
> + * retry safely with same exchange id
> + */
> + if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
> + fdls_send_gpn_ft(iport, iport->fabric.state);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ABTS timeout for fabric GPN_FT. Check name server: %p",
> + iport);
> + }
> + }
> + break;
> + default:
> + break;
> + }
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> +}
> +
> +static void fdls_send_delete_tport_msg(struct fnic_tport_s *tport)
> +{
> + struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
> + struct fnic *fnic = iport->fnic;
> + struct fnic_tport_event_s *tport_del_evt;
> +
> + if (!IS_FNIC_FCP_INITIATOR(fnic))
> + return;
> +
> + tport_del_evt = kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
> + if (!tport_del_evt) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Failed to allocate memory for tport event fcid: 0x%x",
> + tport->fcid);
> + return;
> + }
> + tport_del_evt->event = TGT_EV_TPORT_DELETE;
> + tport_del_evt->arg1 = (void *) tport;
> + list_add_tail(&tport_del_evt->links, &fnic->tport_event_list);
> + queue_work(fnic_event_queue, &fnic->tport_work);
> +}
> +
> +static void fdls_tport_timer_callback(struct timer_list *t)
> +{
> + struct fnic_tport_s *tport = from_timer(tport, t, retry_timer);
> + struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
> + struct fnic *fnic = iport->fnic;
> + uint16_t oxid;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&fnic->fnic_lock, flags);
> + if (!tport->timer_pending) {
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> +
> + if (iport->state != FNIC_IPORT_STATE_READY) {
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> +
> + if (tport->del_timer_inprogress) {
> + tport->del_timer_inprogress = 0;
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport_del_timer inprogress. Skip timer cb tport fcid: 0x%x\n",
> + tport->fcid);
> + return;
> + }
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport fcid: 0x%x timer pending: %d state: %d retry counter: %d",
> + tport->fcid, tport->timer_pending, tport->state,
> + tport->retry_counter);
> +
> + tport->timer_pending = 0;
> + oxid = ntohs(tport->oxid_used);
> +
> + /* We retry plogi/prli/adisc frames depending on the tport state */
> + switch (tport->state) {
> + case FDLS_TGT_STATE_PLOGI:
> + /* PLOGI frame received a LS_RJT with busy, we retry from here */
> + if ((tport->flags & FNIC_FDLS_RETRY_FRAME)
> + && (tport->retry_counter < iport->max_plogi_retries)) {
> + fdls_free_tgt_oxid(iport, oxid);
> + tport->flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_tgt_plogi(iport, tport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
Same here.

> + }
> + /* Plogi frame has timed out 2*ed_tov send abts */
> + if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
> + fdls_send_tport_abts(iport, tport);
> + } else if (tport->retry_counter < iport->max_plogi_retries) {
> + /*
> + * ABTS has timed out have waited (2*ra_tov)
> + * can retry safely
> + * even if with same exchange id
> + */
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_tgt_plogi(iport, tport);
> + } else {
> + /* exceeded plogi retry count */
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_delete_tport_msg(tport);
> + }
> + break;
> + case FDLS_TGT_STATE_PRLI:
> + /* PRLI received a LS_RJT with busy , hence we retry from here */
> + if ((tport->flags & FNIC_FDLS_RETRY_FRAME)
> + && (tport->retry_counter < FDLS_RETRY_COUNT)) {
> + fdls_free_tgt_oxid(iport, oxid);
> + tport->flags &= ~FNIC_FDLS_RETRY_FRAME;
> + fdls_send_tgt_prli(iport, tport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;

And here.

> + }
> + /* PRLI has time out 2*ed_tov send abts */
> + if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
> + fdls_send_tport_abts(iport, tport);
> + } else {
> + /* ABTS has timed out for prli, we go back to PLOGI */
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_tgt_plogi(iport, tport);
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
> + }
> + break;
> + case FDLS_TGT_STATE_ADISC:
> + /* ADISC timed out send a ABTS */
> + if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
> + fdls_send_tport_abts(iport, tport);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;Just call 'break' here instead of spin_unlock/return.

> + } else if ((tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)
> + && (tport->retry_counter < FDLS_RETRY_COUNT)) {
> + /*
> + * ABTS has timed out have waited (2*ra_tov) can
> + * retry safely even if with same exchange id
> + */
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_tgt_adisc(iport, tport);
> +
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
Same here.

> + }
> + /* exceeded retry count */
> + fdls_free_tgt_oxid(iport, oxid);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ADISC not responding. Deleting target port: 0x%x",
> + tport->fcid);
> + fdls_send_delete_tport_msg(tport);

just call 'break' here.

> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unknown tport state: 0x%x", tport->state);
> + break;
> + }
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> +}
> +
> +static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
> +{
> + iport->fabric.retry_counter = 0;
> + fdls_send_fabric_flogi(iport);
> + fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_FLOGI);
> + iport->fabric.flags = 0;
> +}
> +
> +static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
> +{
> + iport->fabric.retry_counter = 0;
> + fdls_send_fabric_plogi(iport);
> + fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
> + iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> +}
> +
> +static void
> +fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + uint32_t tgt_fcid;
> + struct fnic_tport_s *tport;
> + uint8_t *fcid;
> + uint64_t frame_wwnn;
> + uint64_t frame_wwpn;
> + uint16_t oxid;
> + struct fc_els_adisc_ls_acc_s *adisc_rsp =
> + (struct fc_els_adisc_ls_acc_s *) fchdr;
> + struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
> + struct fnic *fnic = iport->fnic;
> +
> + fcid = FNIC_GET_S_ID(fchdr);
> + tgt_fcid = ntoh24(fcid);
> + tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
> +
> + if (!tport) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Tgt ADISC response tport not found: 0x%x", tgt_fcid);
> + return;
> + }
> + if ((iport->state != FNIC_IPORT_STATE_READY)
> + || (tport->state != FDLS_TGT_STATE_ADISC)
> + || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping this ADISC response");
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport state: %d tport state: %d Is abort issued on PRLI? %d",
> + iport->state, tport->state,
> + (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED));
> + return;
> + }
> + if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping frame from target: 0x%x",
> + tgt_fcid);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Reason: Stale ADISC/Aborted ADISC/OOO frame delivery");
> + return;
> + }
> +
> + switch (adisc_rsp->command) {
> + case FC_LS_ACC:
> + if (tport->timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport 0x%p Canceling fabric disc timer\n",
> + tport);
> + fnic_del_tport_timer_sync();
> + }
> + tport->timer_pending = 0;
> + tport->retry_counter = 0;
> + oxid = ntohs(fchdr->ox_id);
> + fdls_free_tgt_oxid(iport, oxid);
> + frame_wwnn = htonll(adisc_rsp->node_name);
> + frame_wwpn = htonll(adisc_rsp->nport_name);
> + if ((frame_wwnn == tport->wwnn) && (frame_wwpn == tport->wwpn)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ADISC accepted from target: 0x%x. Target logged in",
> + tgt_fcid);
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_READY);
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Error mismatch frame: ADISC");
> + }
> + break;
> +
> + case FC_LS_REJ:
> + if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
> + || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
> + && (tport->retry_counter < FDLS_RETRY_COUNT)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ADISC ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
> + tgt_fcid);
> +
> + /* Retry ADISC again from the timer routine. */
> + tport->flags |= FNIC_FDLS_RETRY_FRAME;
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "ADISC returned FC_LS_REJ from target: 0x%x",
> + tgt_fcid);
> + oxid = ntohs(fchdr->ox_id);
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_delete_tport(iport, tport);
> + }
> + break;
> + }
> +}
> +
> +
> +static void
> +fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + uint32_t tgt_fcid;
> + struct fnic_tport_s *tport;
> + uint8_t *fcid;
> + uint16_t oxid;
> + struct fc_els_s *plogi_rsp = (struct fc_els_s *) fchdr;
> + struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
> + int max_payload_size;
> + struct fnic *fnic = iport->fnic;
> +
> + fcid = FNIC_GET_S_ID(fchdr);
> + tgt_fcid = ntoh24(fcid);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS processing target PLOGI response: tgt_fcid: 0x%x",
> + tgt_fcid);
> +
> + tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
> + if (!tport) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport not found: 0x%x", tgt_fcid);
> + return;
> + }
> + if ((iport->state != FNIC_IPORT_STATE_READY)
> + || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping frame! iport state: %d tport state: %d",
> + iport->state, tport->state);
> + return;
> + }
> +
> + if (tport->state != FDLS_TGT_STATE_PLOGI) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI rsp recvd in wrong state. Restarting nexus");
> + oxid = ntohs(FNIC_GET_OX_ID(fchdr));
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_target_restart_nexus(tport);
> + return;
> + }
> +
> + if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI response from target: 0x%x. Dropping frame",
> + tgt_fcid);
> + return;
> + }
> +
> + switch (plogi_rsp->command) {
> + case FC_LS_ACC:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI accepted by target: 0x%x", tgt_fcid);
> + oxid = ntohs(FNIC_GET_OX_ID(fchdr));
> + fdls_free_tgt_oxid(iport, oxid);
> + break;
> +
> + case FC_LS_REJ:
> + if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
> + || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
> + && (tport->retry_counter < iport->max_plogi_retries)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
> + tgt_fcid);
> + /* Retry plogi again from the timer routine. */
> + tport->flags |= FNIC_FDLS_RETRY_FRAME;
> + return;
> + }
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI returned FC_LS_REJ from target: 0x%x",
> + tgt_fcid);
> + oxid = ntohs(fchdr->ox_id);
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_delete_tport(iport, tport);
> + return;
> +
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI not accepted from target fcid: 0x%x",
> + tgt_fcid);
> + return;
> + }
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Found the PLOGI target: 0x%x and state: %d",
> + (unsigned int) tgt_fcid, tport->state);
> +
> + if (tport->timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport fcid 0x%x: Canceling disc timer\n",
> + tport->fcid);
> + fnic_del_tport_timer_sync();
> + }
> +
> + tport->timer_pending = 0;
> + tport->wwpn = htonll(plogi_rsp->nport_name);
> + tport->wwnn = htonll(plogi_rsp->node_name);
> +
> + /* Learn the Service Params */
> +
> + /* Max frame size - choose the lowest */
> + max_payload_size = fnic_fc_plogi_rsp_rdf(iport, plogi_rsp);
> + tport->max_payload_size =
> + MIN(max_payload_size, iport->max_payload_size);
> +
> + if (tport->max_payload_size < FNIC_MIN_DATA_FIELD_SIZE) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "MFS: tport max frame size below spec bounds: %d",
> + tport->max_payload_size);
> + tport->max_payload_size = FNIC_MIN_DATA_FIELD_SIZE;
> + }
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "MAX frame size: %d iport max_payload_size: %d tport mfs: %d",
> + max_payload_size, iport->max_payload_size,
> + tport->max_payload_size);
> +
> + tport->max_concur_seqs = FNIC_FC_PLOGI_RSP_CONCUR_SEQ(plogi_rsp);
> +
> + tport->retry_counter = 0;
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_PRLI);
> + fdls_send_tgt_prli(iport, tport);
> +}
> +
> +static void
> +fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + uint32_t tgt_fcid;
> + struct fnic_tport_s *tport;
> + uint8_t *fcid;
> + uint16_t oxid;
> + struct fc_els_prli_s *prli_rsp = (struct fc_els_prli_s *) fchdr;
> + struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
> + struct fnic_tport_event_s *tport_add_evt;
> + struct fnic *fnic = iport->fnic;
> + bool mismatched_tgt = false;
> +
> + fcid = FNIC_GET_S_ID(fchdr);
> + tgt_fcid = ntoh24(fcid);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS process tgt PRLI response: 0x%x", tgt_fcid);
> +
> + tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
> + if (!tport) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport not found: 0x%x", tgt_fcid);
> + /* Handle or just drop? */
> + return;
> + }
> +
> + if ((iport->state != FNIC_IPORT_STATE_READY)
> + || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping frame! iport st: %d tport st: %d tport fcid: 0x%x",
> + iport->state, tport->state, tport->fcid);
> + return;
> + }
> +
> + if (tport->state != FDLS_TGT_STATE_PRLI) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PRLI rsp recvd in wrong state. Restarting nexus");
> + oxid = ntohs(FNIC_GET_OX_ID(fchdr));
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_target_restart_nexus(tport);
> + return;
> + }
> +
> + if (ntohs(fchdr->ox_id) != ntohs(tport->oxid_used)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping PRLI response from target: 0x%x ",
> + tgt_fcid);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Reason: Stale PRLI response/Aborted PDISC/OOO frame delivery");
> + return;
> + }
> +
> + switch (prli_rsp->command) {
> + case FC_LS_ACC:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PRLI accepted from target: 0x%x", tgt_fcid);
> + oxid = ntohs(FNIC_GET_OX_ID(fchdr));
> + fdls_free_tgt_oxid(iport, oxid);
> +
> + if (prli_rsp->sp.type != FC_FC4_TYPE_SCSI) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "mismatched target zoned with FC SCSI initiator: 0x%x",
> + tgt_fcid);
> + mismatched_tgt = true;
> }
> - break;
> - case FDLS_STATE_REGISTER_FC4_TYPES:
> - /* scr received a LS_RJT with busy we retry from here */
> - if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> - && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> - iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> - fdls_send_register_fc4_types(iport);
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + if (mismatched_tgt) {
> + fdls_tgt_logout(iport, tport);
> + fdls_delete_tport(iport, tport);
> return;
> }
> - /* RFT_ID timed out send abts */
> - if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> - fdls_send_fabric_abts(iport);
> - } else {
> - /* ABTS has timed out (2*ra_tov), we give up */
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "ABTS timed out. Starting PLOGI: %p", iport);
> - fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> - }
> break;
> - case FDLS_STATE_REGISTER_FC4_FEATURES:
> - /* scr received a LS_RJT with busy we retry from here */
> - if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> - && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> - iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> - fdls_send_register_fc4_features(iport);
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - return;
> - }
> - /* scr have timed out send abts */
> - if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
> - fdls_send_fabric_abts(iport);
> - else {
> - /* ABTS has timed out (2*ra_tov), we give up */
> +
> + case FC_LS_REJ:
> + if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
> + || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
> + && (tport->retry_counter < FDLS_RETRY_COUNT)) {
> +
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "ABTS timed out. Starting PLOGI %p", iport);
> - fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
> - }
> - break;
> - case FDLS_STATE_RSCN_GPN_FT:
> - case FDLS_STATE_SEND_GPNFT:
> - case FDLS_STATE_GPN_FT:
> - /* GPN_FT received a LS_RJT with busy we retry from here */
> - if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
> - && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
> - iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
> - fdls_send_gpn_ft(iport, iport->fabric.state);
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + "PRLI ret FC_LS_REJ BUSY. Retry from timer routine: 0x%x",
> + tgt_fcid);
> +
> + /*Retry Plogi again from the timer routine. */
> + tport->flags |= FNIC_FDLS_RETRY_FRAME;
> return;
> - }
> - /* gpn_gt have timed out send abts */
> - if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
> - fdls_send_fabric_abts(iport);
> } else {
> - /*
> - * ABTS has timed out have waited (2*ra_tov) can
> - * retry safely with same exchange id
> - */
> - if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
> - fdls_send_gpn_ft(iport, iport->fabric.state);
> - } else {
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "ABTS timeout for fabric GPN_FT. Check name server: %p",
> - iport);
> - }
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PRLI returned FC_LS_REJ from target: 0x%x",
> + tgt_fcid);
> +
> + oxid = ntohs(fchdr->ox_id);
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_tgt_logout(iport, tport);
> + fdls_delete_tport(iport, tport);
> + return;
> }
> break;
> +
> default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PRLI not accepted from target: 0x%x", tgt_fcid);
> + return;
> break;
> }
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> -}
>
That has quite an odd oxid handling. For some places the oxid is
released, on others it isn't.
With no clear indication when.
If you want to have the oxid reused please add some comments to
make it clear that this isn't an oversight.

> -static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
> -{
> - iport->fabric.retry_counter = 0;
> - fdls_send_fabric_flogi(iport);
> - fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_FLOGI);
> - iport->fabric.flags = 0;
> -}
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Found the PRLI target: 0x%x and state: %d",
> + (unsigned int) tgt_fcid, tport->state);
>
> -static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
> -{
> - iport->fabric.retry_counter = 0;
> - fdls_send_fabric_plogi(iport);
> - fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
> - iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> + if (tport->timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport fcid 0x%x: Canceling disc timer\n",
> + tport->fcid);
> + fnic_del_tport_timer_sync();
> + }
> + tport->timer_pending = 0;
> +
> + oxid = ntohs(FNIC_GET_OX_ID(fchdr));
> + fdls_free_tgt_oxid(iport, oxid);
> +
> + /* Learn Service Params */
> + tport->fcp_csp = ntohl(prli_rsp->sp.csp);
> + tport->retry_counter = 0;
> +
> + if (prli_rsp->sp.csp & FCP_SPPF_RETRY)
> + tport->tgt_flags |= FNIC_FC_RP_FLAGS_RETRY;
> +
> + /* Check if the device plays Target Mode Function */
> + if (!(tport->fcp_csp & FCP_PRLI_FUNC_TARGET)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Remote port(0x%x): no target support. Deleting it\n",
> + tgt_fcid);
> + fdls_tgt_logout(iport, tport);
> + fdls_delete_tport(iport, tport);
> + return;
> + }
> +
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_READY);
> +
> + /* Inform the driver about new target added */
> + tport_add_evt = kzalloc(sizeof(struct fnic_tport_event_s), GFP_ATOMIC);
> + if (!tport_add_evt) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport event memory allocation failure: 0x%0x\n",
> + tport->fcid);
> + return;
> + }
> + tport_add_evt->event = TGT_EV_RPORT_ADD;
> + tport_add_evt->arg1 = (void *) tport;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport fcid: 0x%x add tport event fcid: 0x%x\n",
> + tport->fcid, iport->fcid);
> + list_add_tail(&tport_add_evt->links, &fnic->tport_event_list);
> + queue_work(fnic_event_queue, &fnic->tport_work);
> }
>
> +
> static void
> fdls_process_rff_id_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> {
> @@ -884,6 +1918,106 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> }
> }
>
> +static void
> +fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr, int len)
> +{
> + struct fc_gpn_ft_rsp_iu_s *gpn_ft_tgt;
> + struct fc_gpn_ft_rsp_iu_s *gpn_ft_tgt_rem;
> + struct fnic_tport_s *tport, *next;
> + uint32_t fcid;
> + uint64_t wwpn;
> + int rem_len = len;
> + u32 old_link_down_cnt = iport->fnic->link_down_cnt;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: FDLS process GPN_FT tgt list", iport->fcid);
> +
> + gpn_ft_tgt =
> + (struct fc_gpn_ft_rsp_iu_s *) ((uint8_t *) fchdr +
> + sizeof(struct fc_hdr_s)
> + + sizeof(struct fc_ct_hdr_s));
> + gpn_ft_tgt_rem = gpn_ft_tgt;
> + len -= sizeof(struct fc_hdr_s) + sizeof(struct fc_ct_hdr_s);
> +
> + while (rem_len > 0) {
> +
> + fcid = ntoh24(gpn_ft_tgt->fcid);
> + wwpn = ntohll(gpn_ft_tgt->wwpn);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "tport: 0x%x: ctrl:0x%x", fcid, gpn_ft_tgt->ctrl);
> +
> + if (fcid == iport->fcid) {
> + if (gpn_ft_tgt->ctrl & FNIC_FC_GPN_LAST_ENTRY)
> + break;
> + gpn_ft_tgt++;
> + rem_len -= sizeof(struct fc_gpn_ft_rsp_iu_s);
> + continue;
> + }
> +
> + tport = fnic_find_tport_by_wwpn(iport, wwpn);
> + if (!tport) {
> + /*
> + * New port registered with the switch or first time query
> + */
> + tport = fdls_create_tport(iport, fcid, wwpn);
> + if (!tport)
> + return;
> + }
> + /*
> + * check if this was an existing tport with same fcid
> + * but whose wwpn has changed now ,then remove it and
> + * create a new one
> + */
> + if (tport->fcid != fcid) {
> + fdls_delete_tport(iport, tport);
> + tport = fdls_create_tport(iport, fcid, wwpn);
> + if (!tport)
> + return;
> + }
> +
> + /*
> + * If this GPN_FT rsp is after RSCN then mark the tports which
> + * matches with the new GPN_FT list, if some tport is not
> + * found in GPN_FT we went to delete that tport later.
> + */
> + if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT)
> + tport->flags |= FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
> +
> + if (gpn_ft_tgt->ctrl & FNIC_FC_GPN_LAST_ENTRY)
> + break;
> +
> + gpn_ft_tgt++;
> + rem_len -= sizeof(struct fc_gpn_ft_rsp_iu_s);
> + }
> + if (rem_len <= 0) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "GPN_FT response: malformed/corrupt frame rxlen: %d remlen: %d",
> + len, rem_len);
> + }
> +
> + /*remove those ports which was not listed in GPN_FT */
> + if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT) {
> + list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
> +
> + if (!(tport->flags & FNIC_FDLS_TPORT_IN_GPN_FT_LIST)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Remove port: 0x%x not found in GPN_FT list",
> + tport->fcid);
> + fdls_delete_tport(iport, tport);
> + } else {
> + tport->flags &= ~FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
> + }
> + if ((old_link_down_cnt != iport->fnic->link_down_cnt)
> + || (iport->state != FNIC_IPORT_STATE_READY)) {
> + return;
> + }
> + }
> + }
> +}
> +
> static void
> fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
> int len)
> @@ -892,6 +2026,9 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
> struct fc_gpn_ft_s *gpn_ft_rsp = (struct fc_gpn_ft_s *) fchdr;
> uint16_t rsp;
> uint8_t reason_code;
> + int count = 0;
> + struct fnic_tport_s *tport, *next;
> + u32 old_link_down_cnt = iport->fnic->link_down_cnt;
> struct fnic *fnic = iport->fnic;
>
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> @@ -928,12 +2065,74 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
> case FC_CT_ACC:
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> "0x%x: GPNFT_RSP accept", iport->fcid);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Canceling fabric disc timer\n",
> + iport->fcid);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + iport->fabric.retry_counter = 0;
> + fdls_process_gpn_ft_tgt_list(iport, fchdr, len);
> +
> + /*
> + * iport state can change only if link down event happened
> + * We don't need to undo fdls_process_gpn_ft_tgt_list,
> + * that will be taken care in next link up event
> + */
> + if (iport->state != FNIC_IPORT_STATE_READY) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Halting target discovery: fab st: %d iport st: %d ",
> + fdls_get_state(fdls), iport->state);
> + break;
> + }
> + fdls_tgt_discovery_start(iport);
> break;
>
> case FC_CT_REJ:
> reason_code = gpn_ft_rsp->fc_ct_hdr.reason_code;
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> "0x%x: GPNFT_RSP Reject", iport->fcid);
> +
> + if (((reason_code == FC_CT_RJT_LOGICAL_BUSY)
> + || (reason_code == FC_CT_RJT_BUSY))
> + && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: GPNFT_RSP ret REJ/BSY. Retry from timer routine",
> + iport->fcid);
> + /* Retry again from the timer routine */
> + fdls->flags |= FNIC_FDLS_RETRY_FRAME;
> + } else {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: GPNFT_RSP reject", iport->fcid);
> + if (iport->fabric.timer_pending) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Canceling fabric disc timer\n",
> + iport->fcid);
> + fnic_del_fabric_timer_sync();
> + }
> + iport->fabric.timer_pending = 0;
> + iport->fabric.retry_counter = 0;
> + /*
> + * If GPN_FT ls_rjt then we should delete
> + * all existing tports
> + */
> + count = 0;
> + list_for_each_entry_safe(tport, next, &iport->tport_list,
> + links) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "GPN_FT_REJECT: Remove port: 0x%x",
> + tport->fcid);
> + fdls_delete_tport(iport, tport);
> + if ((old_link_down_cnt != iport->fnic->link_down_cnt)
> + || (iport->state != FNIC_IPORT_STATE_READY)) {
> + return;
> + }
> + count++;
> + }
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "GPN_FT_REJECT: Removed (0x%x) ports", count);
> + }
> break;
>
> default:
> @@ -1342,6 +2541,141 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
> }
> }
>
> +static void
> +fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + uint32_t s_id;
> + struct fnic_tport_s *tport;
> + uint32_t tport_state;
> + struct fc_abts_ba_acc_s *ba_acc;
> + struct fc_abts_ba_rjt_s *ba_rjt;
> + uint16_t oxid;
> + struct fnic *fnic = iport->fnic;
> +
> + s_id = ntoh24(fchdr->sid);
> + ba_acc = (struct fc_abts_ba_acc_s *) fchdr;
> + ba_rjt = (struct fc_abts_ba_rjt_s *) fchdr;
> +
> + tport = fnic_find_tport_by_fcid(iport, s_id);
> + if (!tport) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Received tgt abts rsp with invalid SID: 0x%x", s_id);
> + return;
> + }
> +
> + if (tport->timer_pending) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "tport 0x%p Canceling fabric disc timer\n", tport);
> + fnic_del_tport_timer_sync();
> + }
> + if (iport->state != FNIC_IPORT_STATE_READY) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Received tgt abts rsp in iport state(%d). Dropping.",
> + iport->state);
> + return;
> + }
> + tport->timer_pending = 0;
> + tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
> + tport_state = tport->state;
> + oxid = ntohs(fchdr->ox_id);
> +
> + /*This abort rsp is for ADISC */
> + if ((oxid >= FDLS_ADISC_OXID_BASE) && (oxid < FDLS_TGT_OXID_POOL_END)) {
> + if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Received tgt ADISC abts response BA_ACC for OX_ID: 0x%x tgt_fcid: 0x%x",
> + ba_acc->ox_id, tport->fcid);
> + } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "ADISC BA_RJT rcvd tport_fcid: 0x%x tport_state: %d ",
> + tport->fcid, tport_state);
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "reason code: 0x%x reason code explanation:0x%x ",
> + ba_rjt->reason_code, ba_rjt->reason_explanation);
> + }
> + if ((tport->retry_counter < FDLS_RETRY_COUNT)
> + && (fchdr->r_ctl == FNIC_BA_ACC_RCTL)) {
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_tgt_adisc(iport, tport);
> + return;
> + }
> + fdls_free_tgt_oxid(iport, oxid);
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "ADISC not responding. Deleting target port: 0x%x",
> + tport->fcid);
> + fdls_delete_tport(iport, tport);
> + if ((iport->state == FNIC_IPORT_STATE_READY)
> + && (iport->fabric.state != FDLS_STATE_SEND_GPNFT)
> + && (iport->fabric.state != FDLS_STATE_RSCN_GPN_FT)) {
> + fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
> + }
> + /*Restart a discovery of targets */
> + return;
> + }
> +
> + /*This abort rsp is for PLOGI */
> + if ((oxid >= FDLS_PLOGI_OXID_BASE) && (oxid < FDLS_PRLI_OXID_BASE)) {
> + if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Received tgt PLOGI abts response BA_ACC tgt_fcid: 0x%x",
> + tport->fcid);
> + } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PLOGI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x",
> + tport->fcid, fchdr->ox_id);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "reason code: 0x%x reason code explanation: 0x%x",
> + ba_rjt->reason_code, ba_rjt->reason_explanation);
> + }
> + if ((tport->retry_counter < iport->max_plogi_retries)
> + && (fchdr->r_ctl == FNIC_BA_ACC_RCTL)) {
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_tgt_plogi(iport, tport);
> + return;
> + }
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_delete_tport(iport, tport);
> + /*Restart a discovery of targets */
> + if ((iport->state == FNIC_IPORT_STATE_READY)
> + && (iport->fabric.state != FDLS_STATE_SEND_GPNFT)
> + && (iport->fabric.state != FDLS_STATE_RSCN_GPN_FT)) {
> + fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
> + }
> + return;
> + }
> +
> + /*This abort rsp is for PRLI */
> + if ((oxid >= FDLS_PRLI_OXID_BASE) && (oxid < FDLS_ADISC_OXID_BASE)) {
> + if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "0x%x: Received tgt PRLI abts response BA_ACC",
> + tport->fcid);
> + } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "PRLI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x ",
> + tport->fcid, fchdr->ox_id);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "reason code: 0x%x reason code explanation: 0x%x",
> + ba_rjt->reason_code,
> + ba_rjt->reason_explanation);
> + }
> + if ((tport->retry_counter < FDLS_RETRY_COUNT)
> + && (fchdr->r_ctl == FNIC_BA_ACC_RCTL)) {
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_tgt_prli(iport, tport);
> + return;
> + }
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_send_tgt_plogi(iport, tport); /* go back to plogi */
> + fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
> + return;
> + }
> +
I did comment on dedicated OXIDs in the previous patch. Please, don't.
Use a common pool for oxids.

> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received ABTS response for unknown frame %p", iport);
> +}
> +
> /*
> * Performs a validation for all FCOE frames and return the frame type
> */
> @@ -1434,6 +2768,42 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
> }
> }
>
> + /* ELS response from a target */
> + if ((ntohs(oxid) >= FDLS_PLOGI_OXID_BASE)
> + && (ntohs(oxid) < FDLS_PRLI_OXID_BASE)) {
> + if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping Unknown frame in PLOGI exchange range type: 0x%x.",
> + fchdr->type);
> + return -1;
> + }
> + return FNIC_TPORT_PLOGI_RSP;
> + }
> + if ((ntohs(oxid) >= FDLS_PRLI_OXID_BASE)
> + && (ntohs(oxid) < FDLS_ADISC_OXID_BASE)) {
> + if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping Unknown frame in PRLI exchange range type: 0x%x.",
> + fchdr->type);
> + return -1;
> + }
> + return FNIC_TPORT_PRLI_RSP;
> + }
> +
> + if ((ntohs(oxid) >= FDLS_ADISC_OXID_BASE)
> + && (ntohs(oxid) < FDLS_TGT_OXID_POOL_END)) {
> + if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping Unknown frame in ADISC exchange range type: 0x%x.",
> + fchdr->type);
> + return -1;
> + }
> + return FNIC_TPORT_ADISC_RSP;
> + }
> + if (ntohs(oxid) == FNIC_TLOGO_REQ_OXID) {
> + return FNIC_TPORT_LOGO_RSP;
> + }
> +
> /*response from fabric */
> switch (oxid) {
>
> @@ -1557,6 +2927,21 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
> case FNIC_FABRIC_GPN_FT_RSP:
> fdls_process_gpn_ft_rsp(iport, fchdr, len);
> break;
> + case FNIC_TPORT_PLOGI_RSP:
> + fdls_process_tgt_plogi_rsp(iport, fchdr);
> + break;
> + case FNIC_TPORT_PRLI_RSP:
> + fdls_process_tgt_prli_rsp(iport, fchdr);
> + break;
> + case FNIC_TPORT_ADISC_RSP:
> + fdls_process_tgt_adisc_rsp(iport, fchdr);
> + break;
> + case FNIC_TPORT_LOGO_RSP:
> + /* Logo response from tgt which we have deleted */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Logo response from tgt: 0x%x",
> + ntoh24(fchdr->sid));
> + break;
> case FNIC_FABRIC_LOGO_RSP:
> fdls_process_fabric_logo_rsp(iport, fchdr);
> break;
> @@ -1566,7 +2951,8 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
> if ((iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)
> && (oxid >= FNIC_FLOGI_OXID && oxid <= FNIC_RFF_REQ_OXID)) {
> fdls_process_fabric_abts_rsp(iport, fchdr);
> - }
> + } else
> + fdls_process_tgt_abts_rsp(iport, fchdr);
> break;
> default:
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
> index 2d5f438f2cc4..92cd17efa40f 100644
> --- a/drivers/scsi/fnic/fnic.h
> +++ b/drivers/scsi/fnic/fnic.h
> @@ -79,6 +79,9 @@
>
> #define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)
>
> +/* Retry supported by rport (returned by PRLI service parameters) */
> +#define FNIC_FC_RP_FLAGS_RETRY 0x1
> +
> /*
> * fnic private data per SCSI command.
> * These fields are locked by the hashed io_req_lock.
> @@ -133,6 +136,7 @@ static inline u64 fnic_flags_and_state(struct scsi_cmnd *cmd)
>
> extern unsigned int fnic_log_level;
> extern unsigned int io_completions;
> +extern struct workqueue_struct *fnic_event_queue;
>
> #define FNIC_MAIN_LOGGING 0x01
> #define FNIC_FCS_LOGGING 0x02
> @@ -329,6 +333,8 @@ struct fnic {
> struct work_struct flush_work;
> struct sk_buff_head frame_queue;
> struct list_head tx_queue;
> + struct work_struct tport_work;
> + struct list_head tport_event_list;
>
> /*** FIP related data members -- start ***/
> void (*set_vlan)(struct fnic *, u16 vlan);
> diff --git a/drivers/scsi/fnic/fnic_fdls.h b/drivers/scsi/fnic/fnic_fdls.h
> index 095275698716..9eb25ed9c19f 100644
> --- a/drivers/scsi/fnic/fnic_fdls.h
> +++ b/drivers/scsi/fnic/fnic_fdls.h
> @@ -325,6 +325,10 @@ void fdls_send_fabric_logo(struct fnic_iport_s *iport);
> int fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
> void *rx_frame, int len,
> int fchdr_offset);
> +void fdls_send_tport_abts(struct fnic_iport_s *iport,
> + struct fnic_tport_s *tport);
> +void fdls_delete_tport(struct fnic_iport_s *iport,
> + struct fnic_tport_s *tport);
>
> /* fnic_fcs.c */
> void fnic_fdls_init(struct fnic *fnic, int usefip);

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-11 16:13:10

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 03/14] scsi: fnic: Add support for fabric based solicited requests and responses

Hi Karan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on jejb-scsi/for-next linus/master v6.10-rc3 next-20240611]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Karan-Tilak-Kumar/scsi-fnic-Replace-shost_printk-with-pr_info-pr_err/20240611-060227
base: https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
patch link: https://lore.kernel.org/r/20240610215100.673158-4-kartilak%40cisco.com
patch subject: [PATCH 03/14] scsi: fnic: Add support for fabric based solicited requests and responses
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20240611/[email protected]/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240611/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

drivers/scsi/fnic/fdls_disc.c:894:10: warning: variable 'reason_code' set but not used [-Wunused-but-set-variable]
894 | uint8_t reason_code;
| ^
>> drivers/scsi/fnic/fdls_disc.c:1009:26: warning: variable 'els_rjt' set but not used [-Wunused-but-set-variable]
1009 | struct fc_els_reject_s *els_rjt;
| ^
>> drivers/scsi/fnic/fdls_disc.c:1520:11: warning: variable 's_id' set but not used [-Wunused-but-set-variable]
1520 | uint32_t s_id = 0;
| ^
>> drivers/scsi/fnic/fdls_disc.c:1521:11: warning: variable 'd_id' set but not used [-Wunused-but-set-variable]
1521 | uint32_t d_id = 0;
| ^
drivers/scsi/fnic/fdls_disc.c:627:13: warning: unused function 'fnic_fdls_start_flogi' [-Wunused-function]
627 | static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
| ^~~~~~~~~~~~~~~~~~~~~
5 warnings generated.


vim +/els_rjt +1009 drivers/scsi/fnic/fdls_disc.c

1000
1001 static void
1002 fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
1003 void *rx_frame)
1004 {
1005 struct fnic_fdls_fabric_s *fabric = &iport->fabric;
1006 struct fc_els_s *flogi_rsp = (struct fc_els_s *) fchdr;
1007 uint8_t *fcid;
1008 int rdf_size;
> 1009 struct fc_els_reject_s *els_rjt;
1010 uint8_t fcmac[6] = { 0x0E, 0XFC, 0x00, 0x00, 0x00, 0x00 };
1011 struct fnic *fnic = iport->fnic;
1012
1013 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1014 "0x%x: FDLS processing FLOGI response", iport->fcid);
1015
1016 if (fdls_get_state(fabric) != FDLS_STATE_FABRIC_FLOGI) {
1017 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1018 "FLOGI response received in state (%d). Dropping frame",
1019 fdls_get_state(fabric));
1020 return;
1021 }
1022
1023 switch (flogi_rsp->command) {
1024 case FC_LS_ACC:
1025 if (iport->fabric.timer_pending) {
1026 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1027 "iport fcid: 0x%x Canceling fabric disc timer\n",
1028 iport->fcid);
1029 fnic_del_fabric_timer_sync();
1030 }
1031
1032 iport->fabric.timer_pending = 0;
1033 iport->fabric.retry_counter = 0;
1034 fcid = FNIC_GET_D_ID(fchdr);
1035 iport->fcid = ntoh24(fcid);
1036 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1037 "0x%x: FLOGI response accepted", iport->fcid);
1038
1039 /* Learn the Service Params */
1040 rdf_size = ntohs(flogi_rsp->u.csp_flogi.b2b_rdf_size);
1041 if ((rdf_size >= FNIC_MIN_DATA_FIELD_SIZE)
1042 && (rdf_size < FNIC_FC_MAX_PAYLOAD_LEN))
1043 iport->max_payload_size = MIN(rdf_size,
1044 iport->max_payload_size);
1045
1046 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1047 "max_payload_size from fabric: %d set: %d", rdf_size,
1048 iport->max_payload_size);
1049
1050 iport->r_a_tov = ntohl(flogi_rsp->u.csp_flogi.r_a_tov);
1051 iport->e_d_tov = ntohl(flogi_rsp->u.csp_flogi.e_d_tov);
1052
1053 if (flogi_rsp->u.csp_flogi.features & FNIC_FC_EDTOV_NSEC)
1054 iport->e_d_tov = iport->e_d_tov / FNIC_NSEC_TO_MSEC;
1055
1056 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1057 "From fabric: R_A_TOV: %d E_D_TOV: %d",
1058 iport->r_a_tov, iport->e_d_tov);
1059
1060 if (IS_FNIC_FCP_INITIATOR(fnic)) {
1061 fc_host_fabric_name(iport->fnic->lport->host) =
1062 get_unaligned_be64(&flogi_rsp->node_name);
1063 fc_host_port_id(iport->fnic->lport->host) = iport->fcid;
1064 }
1065
1066 fnic_fdls_learn_fcoe_macs(iport, rx_frame, fcid);
1067
1068 memcpy(&fcmac[3], fcid, 3);
1069 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1070 "Adding vNIC device MAC addr: %02x:%02x:%02x:%02x:%02x:%02x",
1071 fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
1072 fcmac[5]);
1073 vnic_dev_add_addr(iport->fnic->vdev, fcmac);
1074
1075 if (fdls_get_state(fabric) == FDLS_STATE_FABRIC_FLOGI) {
1076 fnic_fdls_start_plogi(iport);
1077 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1078 "FLOGI response received. Starting PLOGI");
1079 } else {
1080 /* From FDLS_STATE_FABRIC_FLOGI state fabric can only go to
1081 * FDLS_STATE_LINKDOWN
1082 * state, hence we don't have to worry about undoing:
1083 * the fnic_fdls_register_portid and vnic_dev_add_addr
1084 */
1085 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1086 "FLOGI response received in state (%d). Dropping frame",
1087 fdls_get_state(fabric));
1088 }
1089 break;
1090
1091 case FC_LS_REJ:
1092 els_rjt = (struct fc_els_reject_s *) fchdr;
1093 if (fabric->retry_counter < iport->max_flogi_retries) {
1094 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1095 "FLOGI returned FC_LS_REJ BUSY. Retry from timer routine %p",
1096 iport);
1097
1098 /* Retry Flogi again from the timer routine. */
1099 fabric->flags |= FNIC_FDLS_RETRY_FRAME;
1100
1101 } else {
1102 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1103 "FLOGI returned FC_LS_REJ. Halting discovery %p", iport);
1104 if (iport->fabric.timer_pending) {
1105 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1106 "iport 0x%p Canceling fabric disc timer\n",
1107 iport);
1108 fnic_del_fabric_timer_sync();
1109 }
1110 fabric->timer_pending = 0;
1111 fabric->retry_counter = 0;
1112 }
1113 break;
1114
1115 default:
1116 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1117 "FLOGI response not accepted: 0x%x",
1118 flogi_rsp->command);
1119 break;
1120 }
1121 }
1122

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

Subject: RE: [PATCH 04/14] scsi: fnic: Add support for target based solicited requests and responses

On Tuesday, June 11, 2024 6:32 AM, Hannes Reinecke <[email protected]> wrote:
> Better use a bitmap here; fdls_alloc_tgt_oxid() is not atomic, and will
> need to be locked to avoid races.

Thanks for your review comments so far Hannes. Appreciate you taking the time.
I'll address them in the next version.

Regards,
Karan

2024-06-11 18:07:49

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 04/14] scsi: fnic: Add support for target based solicited requests and responses

Hi Karan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on jejb-scsi/for-next linus/master v6.10-rc3 next-20240611]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Karan-Tilak-Kumar/scsi-fnic-Replace-shost_printk-with-pr_info-pr_err/20240611-060227
base: https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
patch link: https://lore.kernel.org/r/20240610215100.673158-5-kartilak%40cisco.com
patch subject: [PATCH 04/14] scsi: fnic: Add support for target based solicited requests and responses
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20240612/[email protected]/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240612/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> drivers/scsi/fnic/fdls_disc.c:1926:29: warning: variable 'gpn_ft_tgt_rem' set but not used [-Wunused-but-set-variable]
1926 | struct fc_gpn_ft_rsp_iu_s *gpn_ft_tgt_rem;
| ^
drivers/scsi/fnic/fdls_disc.c:2208:26: warning: variable 'els_rjt' set but not used [-Wunused-but-set-variable]
2208 | struct fc_els_reject_s *els_rjt;
| ^
drivers/scsi/fnic/fdls_disc.c:2890:11: warning: variable 's_id' set but not used [-Wunused-but-set-variable]
2890 | uint32_t s_id = 0;
| ^
drivers/scsi/fnic/fdls_disc.c:2891:11: warning: variable 'd_id' set but not used [-Wunused-but-set-variable]
2891 | uint32_t d_id = 0;
| ^
drivers/scsi/fnic/fdls_disc.c:1286:13: warning: unused function 'fnic_fdls_start_flogi' [-Wunused-function]
1286 | static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
| ^~~~~~~~~~~~~~~~~~~~~
5 warnings generated.


vim +/gpn_ft_tgt_rem +1926 drivers/scsi/fnic/fdls_disc.c

1920
1921 static void
1922 fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
1923 struct fc_hdr_s *fchdr, int len)
1924 {
1925 struct fc_gpn_ft_rsp_iu_s *gpn_ft_tgt;
> 1926 struct fc_gpn_ft_rsp_iu_s *gpn_ft_tgt_rem;
1927 struct fnic_tport_s *tport, *next;
1928 uint32_t fcid;
1929 uint64_t wwpn;
1930 int rem_len = len;
1931 u32 old_link_down_cnt = iport->fnic->link_down_cnt;
1932 struct fnic *fnic = iport->fnic;
1933
1934 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1935 "0x%x: FDLS process GPN_FT tgt list", iport->fcid);
1936
1937 gpn_ft_tgt =
1938 (struct fc_gpn_ft_rsp_iu_s *) ((uint8_t *) fchdr +
1939 sizeof(struct fc_hdr_s)
1940 + sizeof(struct fc_ct_hdr_s));
1941 gpn_ft_tgt_rem = gpn_ft_tgt;
1942 len -= sizeof(struct fc_hdr_s) + sizeof(struct fc_ct_hdr_s);
1943
1944 while (rem_len > 0) {
1945
1946 fcid = ntoh24(gpn_ft_tgt->fcid);
1947 wwpn = ntohll(gpn_ft_tgt->wwpn);
1948
1949 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1950 "tport: 0x%x: ctrl:0x%x", fcid, gpn_ft_tgt->ctrl);
1951
1952 if (fcid == iport->fcid) {
1953 if (gpn_ft_tgt->ctrl & FNIC_FC_GPN_LAST_ENTRY)
1954 break;
1955 gpn_ft_tgt++;
1956 rem_len -= sizeof(struct fc_gpn_ft_rsp_iu_s);
1957 continue;
1958 }
1959
1960 tport = fnic_find_tport_by_wwpn(iport, wwpn);
1961 if (!tport) {
1962 /*
1963 * New port registered with the switch or first time query
1964 */
1965 tport = fdls_create_tport(iport, fcid, wwpn);
1966 if (!tport)
1967 return;
1968 }
1969 /*
1970 * check if this was an existing tport with same fcid
1971 * but whose wwpn has changed now ,then remove it and
1972 * create a new one
1973 */
1974 if (tport->fcid != fcid) {
1975 fdls_delete_tport(iport, tport);
1976 tport = fdls_create_tport(iport, fcid, wwpn);
1977 if (!tport)
1978 return;
1979 }
1980
1981 /*
1982 * If this GPN_FT rsp is after RSCN then mark the tports which
1983 * matches with the new GPN_FT list, if some tport is not
1984 * found in GPN_FT we went to delete that tport later.
1985 */
1986 if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT)
1987 tport->flags |= FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
1988
1989 if (gpn_ft_tgt->ctrl & FNIC_FC_GPN_LAST_ENTRY)
1990 break;
1991
1992 gpn_ft_tgt++;
1993 rem_len -= sizeof(struct fc_gpn_ft_rsp_iu_s);
1994 }
1995 if (rem_len <= 0) {
1996 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
1997 "GPN_FT response: malformed/corrupt frame rxlen: %d remlen: %d",
1998 len, rem_len);
1999 }
2000
2001 /*remove those ports which was not listed in GPN_FT */
2002 if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT) {
2003 list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
2004
2005 if (!(tport->flags & FNIC_FDLS_TPORT_IN_GPN_FT_LIST)) {
2006 FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
2007 "Remove port: 0x%x not found in GPN_FT list",
2008 tport->fcid);
2009 fdls_delete_tport(iport, tport);
2010 } else {
2011 tport->flags &= ~FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
2012 }
2013 if ((old_link_down_cnt != iport->fnic->link_down_cnt)
2014 || (iport->state != FNIC_IPORT_STATE_READY)) {
2015 return;
2016 }
2017 }
2018 }
2019 }
2020

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-06-11 18:53:17

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 03/14] scsi: fnic: Add support for fabric based solicited requests and responses

Hi Karan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on jejb-scsi/for-next linus/master v6.10-rc3 next-20240611]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Karan-Tilak-Kumar/scsi-fnic-Replace-shost_printk-with-pr_info-pr_err/20240611-060227
base: https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
patch link: https://lore.kernel.org/r/20240610215100.673158-4-kartilak%40cisco.com
patch subject: [PATCH 03/14] scsi: fnic: Add support for fabric based solicited requests and responses
config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20240612/[email protected]/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240612/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

In file included from drivers/scsi/fnic/fnic_fcs.c:21:
drivers/scsi/fnic/fnic_fcs.c: In function 'fdls_send_fcoe_frame':
>> drivers/scsi/fnic/fnic.h:159:33: warning: format '%ld' expects argument of type 'long int', but argument 7 has type 'unsigned int' [-Wformat=]
159 | "fnic<%d>: %s: %d: " fmt, fnic_num,\
| ^~~~~~~~~~~~~~~~~~~~
drivers/scsi/fnic/fnic.h:146:25: note: in definition of macro 'FNIC_CHECK_LOGGING'
146 | CMD; \
| ^~~
include/scsi/scsi_host.h:738:9: note: in expansion of macro 'dev_printk'
738 | dev_printk(prefix, &(shost)->shost_gendev, fmt, ##a)
| ^~~~~~~~~~
drivers/scsi/fnic/fnic.h:158:26: note: in expansion of macro 'shost_printk'
158 | shost_printk(kern_level, host, \
| ^~~~~~~~~~~~
drivers/scsi/fnic/fnic_fcs.c:1228:25: note: in expansion of macro 'FNIC_FCS_DBG'
1228 | FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
| ^~~~~~~~~~~~


vim +159 drivers/scsi/fnic/fnic.h

5df6d737dd4b0fe Abhijeet Joglekar 2009-04-17 149
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 150 #define FNIC_MAIN_DBG(kern_level, host, fnic_num, fmt, args...) \
5df6d737dd4b0fe Abhijeet Joglekar 2009-04-17 151 FNIC_CHECK_LOGGING(FNIC_MAIN_LOGGING, \
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 152 shost_printk(kern_level, host, \
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 153 "fnic<%d>: %s: %d: " fmt, fnic_num,\
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 154 __func__, __LINE__, ##args);)
5df6d737dd4b0fe Abhijeet Joglekar 2009-04-17 155
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 156 #define FNIC_FCS_DBG(kern_level, host, fnic_num, fmt, args...) \
5df6d737dd4b0fe Abhijeet Joglekar 2009-04-17 157 FNIC_CHECK_LOGGING(FNIC_FCS_LOGGING, \
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 158 shost_printk(kern_level, host, \
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 @159 "fnic<%d>: %s: %d: " fmt, fnic_num,\
3df9dd0d51c2e4b Karan Tilak Kumar 2023-12-11 160 __func__, __LINE__, ##args);)
5df6d737dd4b0fe Abhijeet Joglekar 2009-04-17 161

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-06-12 06:31:51

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 05/14] scsi: fnic: Add support for unsolicited requests and responses

On 6/10/24 23:50, Karan Tilak Kumar wrote:
> Add support for unsolicited requests and responses.
> Add support to accept and reject frames.
>
> Reviewed-by: Sesidhar Baddela <[email protected]>
> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> Reviewed-by: Gian Carlo Boffa <[email protected]>
> Signed-off-by: Karan Tilak Kumar <[email protected]>
> ---
> drivers/scsi/fnic/fdls_disc.c | 566 +++++++++++++++++++++++++++++++++-
> 1 file changed, 563 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
> index d920202d413d..ad115de86f15 100644
> --- a/drivers/scsi/fnic/fdls_disc.c
> +++ b/drivers/scsi/fnic/fdls_disc.c
> @@ -125,6 +125,21 @@ struct fc_scr_s fnic_scr_req = {
> .reg_func = 0x03
> };
>
> +/*
> + * Variables:
> + * did, ox_id, rx_id
> + */
> +struct fc_els_acc_s fnic_els_acc = {
> + .fchdr = {.r_ctl = 0x23, .did = {0xFF, 0xFF, 0xFD}, .type = 0x01,
> + .f_ctl = FNIC_ELS_REP_FCTL},
> + .command = FC_LS_ACC,
> +};
> +
> +struct fc_els_reject_s fnic_els_rjt = {
> + .fchdr = {.r_ctl = 0x23, .type = 0x01, .f_ctl = FNIC_ELS_REP_FCTL},
> + .command = FC_LS_REJ,
> +};
> +
> /*
> * Variables:
> * did, ox_id, rx_id, fcid, wwpn
> @@ -135,6 +150,13 @@ struct fc_logo_req_s fnic_logo_req = {
> .command = FC_ELS_LOGO,
> };
>
> +static struct fc_abts_ba_acc_s fnic_ba_acc = {
> + .fchdr = {.r_ctl = 0x84,
> + .f_ctl = FNIC_FCP_RSP_FCTL},
> + .low_seq_cnt = 0,
> + .high_seq_cnt = 0xFFFF,
> +};
> +
> #define RETRIES_EXHAUSTED(iport) \
> (iport->fabric.retry_counter == FABRIC_LOGO_MAX_RETRY)
>
> @@ -150,7 +172,6 @@ static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
> static void fdls_target_restart_nexus(struct fnic_tport_s *tport);
> static void fdls_start_tport_timer(struct fnic_iport_s *iport,
> struct fnic_tport_s *tport, int timeout);
> -
> static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
> int timeout);
> static void fdls_tport_timer_callback(struct timer_list *t);
> @@ -231,6 +252,48 @@ fdls_start_tport_timer(struct fnic_iport_s *iport,
> tport->timer_pending = 1;
> }
>
> +static void
> +fdls_send_rscn_resp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *rscn_fchdr)
> +{
> + struct fc_els_acc_s els_acc;
> + uint16_t oxid;
> + uint8_t fcid[3];
> +
> + memcpy(&els_acc, &fnic_els_acc, sizeof(struct fc_els_acc_s));
> +
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID((&els_acc.fchdr), fcid);
> + FNIC_SET_D_ID((&els_acc.fchdr), rscn_fchdr->sid);
> +
> + oxid = FNIC_GET_OX_ID(rscn_fchdr);
> + FNIC_SET_OX_ID((&els_acc.fchdr), oxid);
> +
> + FNIC_SET_RX_ID((&els_acc.fchdr), FNIC_RSCN_RESP_OXID);
> +
> + fnic_send_fcoe_frame(iport, &els_acc, sizeof(struct fc_els_acc_s));
> +}
> +
> +static void
> +fdls_send_logo_resp(struct fnic_iport_s *iport, struct fc_hdr_s *req_fchdr)
> +{
> + struct fc_els_acc_s logo_resp;
> + uint16_t oxid;
> + uint8_t fcid[3];
> +
> + memcpy(&logo_resp, &fnic_els_acc, sizeof(struct fc_els_acc_s));
> +
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID((&logo_resp.fchdr), fcid);
> + FNIC_SET_D_ID((&logo_resp.fchdr), req_fchdr->sid);
> +
> + oxid = FNIC_GET_OX_ID(req_fchdr);
> + FNIC_SET_OX_ID((&logo_resp.fchdr), oxid);
> +
> + FNIC_SET_RX_ID((&logo_resp.fchdr), FNIC_LOGO_RESP_OXID);
> + fnic_send_fcoe_frame(iport, &logo_resp, sizeof(struct fc_els_acc_s));
> +}
> +
> void
> fdls_send_tport_abts(struct fnic_iport_s *iport,
> struct fnic_tport_s *tport)
> @@ -2541,6 +2604,188 @@ fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
> }
> }
>
> +static void
> +fdls_process_abts_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fc_abts_ba_acc_s ba_acc;
> + uint32_t nport_id;
> + uint16_t oxid;
> + struct fnic_tport_s *tport;
> + struct fnic *fnic = iport->fnic;
> +
> + nport_id = ntoh24(fchdr->sid);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received abort from SID %8x", nport_id);
> +
> + tport = fnic_find_tport_by_fcid(iport, nport_id);
> + if (tport) {
> + oxid = FNIC_GET_OX_ID(fchdr);
> + if (tport->oxid_used == oxid) {
> + tport->flags |= FNIC_FDLS_TGT_ABORT_ISSUED;
> + fdls_free_tgt_oxid(iport, ntohs(oxid));
> + }

Hmm. This is an abort, right?
Don't you need to look up the command referred to by 'oxid'?
Just freeing the oxid doesn't abort the command itself...

> + }
> +
> + memcpy(&ba_acc, &fnic_ba_acc, sizeof(struct fc_abts_ba_acc_s));
> + FNIC_SET_S_ID((&ba_acc.fchdr), fchdr->did);
> + FNIC_SET_D_ID((&ba_acc.fchdr), fchdr->sid);
> +
> + ba_acc.fchdr.rx_id = fchdr->rx_id;
> + ba_acc.rx_id = ba_acc.fchdr.rx_id;
> + ba_acc.fchdr.ox_id = fchdr->ox_id;
> + ba_acc.ox_id = ba_acc.fchdr.ox_id;
> +
> + fnic_send_fcoe_frame(iport, &ba_acc, sizeof(struct fc_abts_ba_acc_s));
> +}
> +
> +static void
> +fdls_process_unsupported_els_req(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + struct fc_els_reject_s ls_rsp;
> + uint16_t oxid;
> + uint32_t d_id = ntoh24(fchdr->did);
> + struct fnic *fnic = iport->fnic;
> +
> + memcpy(&ls_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));
> +
> + if (iport->fcid != d_id) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping unsupported ELS with illegal frame bits 0x%x\n",
> + d_id);
> + return;
> + }
> +
> + if ((iport->state != FNIC_IPORT_STATE_READY)
> + && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping unsupported ELS request in iport state: %d",
> + iport->state);
> + return;
> + }
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Process unsupported ELS request from SID: 0x%x",
> + ntoh24(fchdr->sid));
> + /* We don't support this ELS request, send a reject */
> + ls_rsp.reason_code = 0x0B;
> + ls_rsp.reason_expl = 0x0;
> + ls_rsp.vendor_specific = 0x0;
> +
> + FNIC_SET_S_ID((&ls_rsp.fchdr), fchdr->did);
> + FNIC_SET_D_ID((&ls_rsp.fchdr), fchdr->sid);
> + oxid = FNIC_GET_OX_ID(fchdr);
> + FNIC_SET_OX_ID((&ls_rsp.fchdr), oxid);
> +
> + FNIC_SET_RX_ID((&ls_rsp.fchdr), FNIC_UNSUPPORTED_RESP_OXID);
> + fnic_send_fcoe_frame(iport, &ls_rsp, sizeof(struct fc_els_reject_s));
> +}
> +
> +static void
> +fdls_process_rls_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fc_els_rls_ls_acc_s rls_acc_rsp;
> + uint16_t oxid;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Process RLS request %d", iport->fnic->fnic_num);
> +
> + if ((iport->state != FNIC_IPORT_STATE_READY)
> + && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received RLS req in iport state: %d. Dropping the frame.",
> + iport->state);
> + return;
> + }
> +
> + memset(&rls_acc_rsp, 0, sizeof(struct fc_els_rls_ls_acc_s));
> +
> + FNIC_SET_S_ID((&rls_acc_rsp.fchdr), fchdr->did);
> + FNIC_SET_D_ID((&rls_acc_rsp.fchdr), fchdr->sid);
> + oxid = FNIC_GET_OX_ID(fchdr);
> + FNIC_SET_OX_ID((&rls_acc_rsp.fchdr), oxid);
> + FNIC_SET_RX_ID((&rls_acc_rsp.fchdr), 0xffff);
> + rls_acc_rsp.fchdr.f_ctl = FNIC_ELS_REP_FCTL;
> + rls_acc_rsp.fchdr.r_ctl = 0x23;
> + rls_acc_rsp.fchdr.type = 0x01;
> + rls_acc_rsp.command = FC_LS_ACC;
> + rls_acc_rsp.link_fail_count = htonl(iport->fnic->link_down_cnt);
> +
> + fnic_send_fcoe_frame(iport, &rls_acc_rsp,
> + sizeof(struct fc_els_rls_ls_acc_s));

Indentation.

> +}
> +
> +static void
> +fdls_process_els_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr,
> + uint32_t len)
> +{
> + struct fc_els_acc_s *els_acc;
> + uint16_t oxid;
> + uint8_t fcid[3];
> + uint8_t *fc_payload;
> + uint8_t *dst_frame;
> + uint8_t type;
> + struct fnic *fnic = iport->fnic;
> +
> + fc_payload = (uint8_t *) fchdr + sizeof(struct fc_hdr_s);
> + type = *fc_payload;
> +
> + if ((iport->state != FNIC_IPORT_STATE_READY)
> + && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping ELS frame type :%x in iport state: %d",
> + type, iport->state);
> + return;
> + }
> + switch (type) {
> + case FC_ELS_ECHO_REQ:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "sending LS_ACC for ECHO request %d\n",
> + iport->fnic->fnic_num);
> + break;
> +
> + case FC_ELS_RRQ_REQ:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "sending LS_ACC for RRQ request %d\n",
> + iport->fnic->fnic_num);
> + break;
> +
> + default:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "sending LS_ACC for %x ELS frame\n", type);
> + break;
> + }
> + dst_frame = kzalloc(len, GFP_ATOMIC);
> + if (!dst_frame) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Failed to allocate ELS response for %x", type);
> + return;
> + }
> + if (type == FC_ELS_ECHO_REQ) {
> + /* Brocade sends a longer payload, copy all frame back */
> + memcpy(dst_frame, fchdr, len);
> + }
> +
> + els_acc = (struct fc_els_acc_s *) dst_frame;
> + memcpy(els_acc, &fnic_els_acc, sizeof(struct fc_els_acc_s));
> +
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID((&els_acc->fchdr), fcid);
> + FNIC_SET_D_ID((&els_acc->fchdr), fchdr->sid);
> +
> + oxid = FNIC_GET_OX_ID(fchdr);
> + FNIC_SET_OX_ID((&els_acc->fchdr), oxid);
> + FNIC_SET_RX_ID((&els_acc->fchdr), 0xffff);
> +
> + if (type == FC_ELS_ECHO_REQ)
> + fnic_send_fcoe_frame(iport, els_acc, len);
> + else
> + fnic_send_fcoe_frame(iport, els_acc, sizeof(struct fc_els_acc_s));
> +
> + kfree(dst_frame);
> +}
> +
> static void
> fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
> struct fc_hdr_s *fchdr)
> @@ -2584,8 +2829,8 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
> if ((oxid >= FDLS_ADISC_OXID_BASE) && (oxid < FDLS_TGT_OXID_POOL_END)) {
> if (fchdr->r_ctl == FNIC_BA_ACC_RCTL) {
> FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> - "Received tgt ADISC abts response BA_ACC for OX_ID: 0x%x tgt_fcid: 0x%x",
> - ba_acc->ox_id, tport->fcid);
> + "OX_ID: 0x%x tgt_fcid: 0x%x rcvd tgt adisc abts resp BA_ACC",
> + ba_acc->ox_id, tport->fcid);
> } else if (fchdr->r_ctl == FNIC_BA_RJT_RCTL) {
> FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> "ADISC BA_RJT rcvd tport_fcid: 0x%x tport_state: %d ",
> @@ -2676,6 +2921,296 @@ fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
> "Received ABTS response for unknown frame %p", iport);
> }
>
> +static void
> +fdls_process_plogi_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fc_els_reject_s plogi_rsp;
> + uint16_t oxid;
> + uint32_t d_id = ntoh24(fchdr->did);
> + struct fnic *fnic = iport->fnic;
> +
> + memcpy(&plogi_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));
> +
> + if (iport->fcid != d_id) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received PLOGI with illegal frame bits. Dropping frame %p",
> + iport);
> + return;
> + }
> +
> + if (iport->state != FNIC_IPORT_STATE_READY) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Received PLOGI request in iport state: %d Dropping frame",
> + iport->state);
> + return;
> + }
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Process PLOGI request from SID: 0x%x",
> + ntoh24(fchdr->sid));
> +
> + /* We don't support PLOGI request, send a reject */
> + plogi_rsp.reason_code = 0x0B;
> + plogi_rsp.reason_expl = 0x0;
> + plogi_rsp.vendor_specific = 0x0;
> +
> + FNIC_SET_S_ID((&plogi_rsp.fchdr), fchdr->did);
> + FNIC_SET_D_ID((&plogi_rsp.fchdr), fchdr->sid);
> +
> + oxid = FNIC_GET_OX_ID(fchdr);
> + FNIC_SET_OX_ID((&plogi_rsp.fchdr), oxid);
> +
> + FNIC_SET_RX_ID((&plogi_rsp.fchdr), FNIC_PLOGI_RESP_OXID);
> + fnic_send_fcoe_frame(iport, &plogi_rsp,
> + sizeof(struct fc_els_reject_s));

Indentaion again.

> +}
> +
> +static void
> +fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fc_logo_req_s *logo = (struct fc_logo_req_s *) fchdr;
> + uint32_t nport_id;
> + uint64_t nport_name;
> + struct fnic_tport_s *tport;
> + struct fnic *fnic = iport->fnic;
> + uint16_t oxid;
> +
> + nport_id = ntoh24(logo->fcid);
> + nport_name = logo->wwpn;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Process LOGO request from fcid: 0x%x", nport_id);
> +
> + if (iport->state != FNIC_IPORT_STATE_READY) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Dropping LOGO req from 0x%x in iport state: %d",
> + nport_id, iport->state);
> + return;
> + }
> +
> + tport = fnic_find_tport_by_fcid(iport, nport_id);
> +
> + if (!tport) {
> + /* We are not logged in with the nport, log and drop... */
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Received LOGO from an nport not logged in: 0x%x",
> + nport_id);
> + return;
> + }
> + if (tport->fcid != nport_id) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Received LOGO with invalid target port fcid: 0x%x",
> + nport_id);
> + return;
> + }
> + if (tport->timer_pending) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "tport fcid 0x%x: Canceling disc timer\n",
> + tport->fcid);
> + fnic_del_tport_timer_sync();
> + tport->timer_pending = 0;
> + }
> +
> + /* got a logo in response to adisc to a target which has logged out */
> + if (tport->state == FDLS_TGT_STATE_ADISC) {
> + tport->retry_counter = 0;
> + oxid = ntohs(tport->oxid_used);
> + fdls_free_tgt_oxid(iport, oxid);
> + fdls_delete_tport(iport, tport);
> + fdls_send_logo_resp(iport, &logo->fchdr);
> + if ((iport->state == FNIC_IPORT_STATE_READY)
> + && (fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT)
> + && (fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Sending GPNFT in response to LOGO from Target:0x%x",
> + nport_id);
> + fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
> + return;
> + }
> + } else {
> + fdls_delete_tport(iport, tport);
> + }
> + if (iport->state == FNIC_IPORT_STATE_READY) {
> + fdls_send_logo_resp(iport, &logo->fchdr);
> + if ((fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT) &&
> + (fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Sending GPNFT in response to LOGO from Target:0x%x",
> + nport_id);
> + fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
> + }
> + }
> +}
> +
> +static void
> +fdls_process_rscn(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fc_rscn_hdr_s *rscn;
> + struct fc_rscn_port_s *rscn_port = NULL;
> + int num_ports;
> + struct fnic_tport_s *tport, *next;
> + uint32_t nport_id;
> + uint8_t fcid[3];
> + int newports = 0;
> + struct fnic_fdls_fabric_s *fdls = &iport->fabric;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS process RSCN %p", iport);
> +
> + if (iport->state != FNIC_IPORT_STATE_READY) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS RSCN received in state(%d). Dropping",
> + fdls_get_state(fdls));
> + return;
> + }
> +
> + rscn = (struct fc_rscn_hdr_s *) fchdr;
> + /* frame validation */
> + if ((rscn->payload_len % 4 != 0) || (rscn->payload_len < 8)
> + || (rscn->payload_len > 1024) || (rscn->page_len != 4)) {
> + num_ports = 0;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RSCN payload_len: 0x%x page_len: 0x%x",
> + rscn->payload_len, rscn->page_len);
> + /* if this happens then we need to send ADISC to all the tports. */
> + list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
> + if (tport->state == FDLS_TGT_STATE_READY)
> + tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RSCN for port id: 0x%x", tport->fcid);
> + }
> + } else {
> + num_ports = (rscn->payload_len - 4) / rscn->page_len;
> + rscn_port = (struct fc_rscn_port_s *) (rscn + 1);
> + }
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RSCN received for num_ports: %d payload_len: %d page_len: %d ",
> + num_ports, rscn->payload_len, rscn->page_len);
> +
> + /*
> + * RSCN have at least one Port_ID page , but may not have any port_id
> + * in it. If no port_id is specified in the Port_ID page , we send
> + * ADISC to all the tports
> + */
> +
> + while (num_ports) {
> +
> + memcpy(fcid, rscn_port->port_id, 3);
> +
> + nport_id = ntoh24(fcid);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RSCN event: 0x%x for 0x%x", rscn_port->rscn_evt_q,
> + nport_id);
> + rscn_port++;
> + num_ports--;
> + /* if this happens then we need to send ADISC to all the tports. */
> + if (nport_id == 0) {
> + list_for_each_entry_safe(tport, next, &iport->tport_list,
> + links) {
> + if (tport->state == FDLS_TGT_STATE_READY)
> + tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RSCN for port id: 0x%x", tport->fcid);
> + }
> + break;
> + }
> + tport = fnic_find_tport_by_fcid(iport, nport_id);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "RSCN port id list: 0x%x", nport_id);
> +
> + if (!tport) {
> + newports++;
> + continue;
> + }
> + if (tport->state == FDLS_TGT_STATE_READY)
> + tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
> + }
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS process RSCN sending GPN_FT %p", iport);
> + fdls_send_gpn_ft(iport, FDLS_STATE_RSCN_GPN_FT);
> + fdls_send_rscn_resp(iport, fchdr);
> +}
> +
> +static void
> +fdls_process_adisc_req(struct fnic_iport_s *iport, struct fc_hdr_s *fchdr)
> +{
> + struct fc_els_adisc_ls_acc_s adisc_acc;
> + struct fc_els_adisc_s *adisc_req = (struct fc_els_adisc_s *) fchdr;
> + uint64_t frame_wwnn;
> + uint64_t frame_wwpn;
> + uint32_t tgt_fcid;
> + struct fnic_tport_s *tport;
> + uint8_t *fcid;
> + struct fc_els_reject_s rjts_rsp;
> + uint16_t oxid;
> + struct fnic *fnic = iport->fnic;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Process ADISC request %d", iport->fnic->fnic_num);
> +
> + fcid = FNIC_GET_S_ID(fchdr);
> + tgt_fcid = ntoh24(fcid);
> + tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
> + if (!tport) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "tport for fcid: 0x%x not found. Dropping ADISC req.",
> + tgt_fcid);
> + return;
> + }
> + if (iport->state != FNIC_IPORT_STATE_READY) {
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "Dropping ADISC req from fcid: 0x%x in iport state: %d",
> + tgt_fcid, iport->state);
> + return;
> + }
> +
> + frame_wwnn = ntohll(adisc_req->node_name);
> + frame_wwpn = ntohll(adisc_req->nport_name);
> +
> + if ((frame_wwnn != tport->wwnn) || (frame_wwpn != tport->wwpn)) {
> + /* send reject */
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "ADISC req from fcid: 0x%x mismatch wwpn: 0x%llx wwnn: 0x%llx",
> + tgt_fcid, frame_wwpn, frame_wwnn);
> + FNIC_FCS_DBG(KERN_ERR, fnic->lport->host, fnic->fnic_num,
> + "local tport wwpn: 0x%llx wwnn: 0x%llx. Sending RJT",
> + tport->wwpn, tport->wwnn);
> +
> + memcpy(&rjts_rsp, &fnic_els_rjt, sizeof(struct fc_els_reject_s));
> +
> + rjts_rsp.reason_code = 0x03; /* logical error */
> + rjts_rsp.reason_expl = 0x1E; /* N_port login required */
> + rjts_rsp.vendor_specific = 0x0;
> + FNIC_SET_S_ID((&rjts_rsp.fchdr), fchdr->did);
> + FNIC_SET_D_ID((&rjts_rsp.fchdr), fchdr->sid);
> + oxid = FNIC_GET_OX_ID(fchdr);
> + FNIC_SET_OX_ID((&rjts_rsp.fchdr), oxid);
> + FNIC_SET_RX_ID((&rjts_rsp.fchdr), FNIC_ADISC_RESP_OXID);
> + fnic_send_fcoe_frame(iport, &rjts_rsp,
> + sizeof(struct fc_els_reject_s));
> + return;
> + }
> + memset(&adisc_acc.fchdr, 0, sizeof(struct fc_hdr_s));
> + FNIC_SET_S_ID((&adisc_acc.fchdr), fchdr->did);
> + FNIC_SET_D_ID((&adisc_acc.fchdr), fchdr->sid);
> + adisc_acc.fchdr.f_ctl = FNIC_ELS_REP_FCTL;
> + adisc_acc.fchdr.r_ctl = 0x23;
> + adisc_acc.fchdr.type = 0x01;
> + oxid = FNIC_GET_OX_ID(fchdr);
> + FNIC_SET_OX_ID((&adisc_acc.fchdr), oxid);
> + FNIC_SET_RX_ID((&adisc_acc.fchdr), FNIC_ADISC_RESP_OXID);
> + adisc_acc.command = FC_LS_ACC;
> +
> + FNIC_SET_NPORT_NAME(adisc_acc, iport->wwpn);
> + FNIC_SET_NODE_NAME(adisc_acc, iport->wwnn);
> + memcpy(adisc_acc.fcid, fchdr->did, 3);
> + fnic_send_fcoe_frame(iport, &adisc_acc,
> + sizeof(struct fc_els_adisc_ls_acc_s));

Indentation again.

> +}
> +
> /*
> * Performs a validation for all FCOE frames and return the frame type
> */
> @@ -2954,6 +3489,31 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
> } else
> fdls_process_tgt_abts_rsp(iport, fchdr);
> break;
> + case FNIC_BLS_ABTS_REQ:
> + fdls_process_abts_req(iport, fchdr);
> + break;
> + case FNIC_ELS_UNSUPPORTED_REQ:
> + fdls_process_unsupported_els_req(iport, fchdr);
> + break;
> + case FNIC_ELS_PLOGI_REQ:
> + fdls_process_plogi_req(iport, fchdr);
> + break;
> + case FNIC_ELS_RSCN_REQ:
> + fdls_process_rscn(iport, fchdr);
> + break;
> + case FNIC_ELS_LOGO_REQ:
> + fdls_process_logo_req(iport, fchdr);
> + break;
> + case FNIC_ELS_RRQ:
> + case FNIC_ELS_ECHO_REQ:
> + fdls_process_els_req(iport, fchdr, len);
> + break;
> + case FNIC_ELS_ADISC:
> + fdls_process_adisc_req(iport, fchdr);
> + break;
> + case FNIC_ELS_RLS:
> + fdls_process_rls_req(iport, fchdr);
> + break;
> default:
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> "Received unknown FCoE frame of len: %d. Dropping frame", len);

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-12 06:45:44

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 06/14] scsi: fnic: Add and integrate support for FDMI

On 6/10/24 23:50, Karan Tilak Kumar wrote:
> Add support for Fabric-Device Management Interface
> (FDMI) by introducing PCI device IDs for Cisco
> Hardware.
> Introduce a module parameter to enable/disable
> FDMI support.
> Integrate support for FDMI.
>
> Reviewed-by: Sesidhar Baddela <[email protected]>
> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> Reviewed-by: Gian Carlo Boffa <[email protected]>
> Signed-off-by: Karan Tilak Kumar <[email protected]>
> ---
> drivers/scsi/fnic/Makefile | 3 +-
> drivers/scsi/fnic/fdls_disc.c | 281 ++++++++++++++++++++++
> drivers/scsi/fnic/fnic.h | 72 ++++++
> drivers/scsi/fnic/fnic_fdls.h | 2 +-
> drivers/scsi/fnic/fnic_main.c | 26 ++
> drivers/scsi/fnic/fnic_pci_subsys_devid.c | 133 ++++++++++
> 6 files changed, 515 insertions(+), 2 deletions(-)
> create mode 100644 drivers/scsi/fnic/fnic_pci_subsys_devid.c
>
> diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
> index 3bd6b1c8b643..af156c69da0c 100644
> --- a/drivers/scsi/fnic/Makefile
> +++ b/drivers/scsi/fnic/Makefile
> @@ -16,4 +16,5 @@ fnic-y := \
> vnic_intr.o \
> vnic_rq.o \
> vnic_wq_copy.o \
> - vnic_wq.o
> + vnic_wq.o \
> + fnic_pci_subsys_devid.o
> diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c
> index ad115de86f15..42127a70c369 100644
> --- a/drivers/scsi/fnic/fdls_disc.c
> +++ b/drivers/scsi/fnic/fdls_disc.c
> @@ -14,6 +14,8 @@
> #define FC_FC4_TYPE_SCSI 0x08
>
> static void fdls_send_rpn_id(struct fnic_iport_s *iport);
> +static void fdls_fdmi_register_hba(struct fnic_iport_s *iport);
> +static void fdls_fdmi_register_pa(struct fnic_iport_s *iport);
>
> /* Frame initialization */
> /*
> @@ -74,6 +76,66 @@ struct fc_els_prli_s fnic_prli_req = {
> .sp = {.type = 0x08, .flags = 0x0020, .csp = 0xA2000000}
> };
>
> +/*
> + * Variables:
> + * sid, port_id, port_name
> + */
> +struct fc_fdmi_rhba_s fnic_fdmi_rhba = {
> + .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0XFF, 0XFA}, .type = 0x20,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_FDMI_REG_HBA_OXID,
> + .rx_id = 0xFFFF},
> + .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFA, .fs_subtype = 0x10,
> + .command = 0x0002},
> + .num_ports = 0x1000000,
> + .num_hba_attributes = 0x9000000,
> + .type_nn = FNIC_FDMI_TYPE_NODE_NAME,
> + .length_nn = 0xc00,
> + .type_manu = FNIC_FDMI_TYPE_MANUFACTURER,
> + .length_manu = 0x1800,
> + .manufacturer = FNIC_FDMI_MANUFACTURER,
> + .type_serial = FNIC_FDMI_TYPE_SERIAL_NUMBER,
> + .length_serial = 0x1400,
> + .type_model = FNIC_FDMI_TYPE_MODEL,
> + .length_model = 0x1000,
> + .type_model_des = FNIC_FDMI_TYPE_MODEL_DES,
> + .length_model_des = 0x3c00,
> + .model_description = FNIC_FDMI_MODEL_DESCRIPTION,
> + .type_hw_ver = FNIC_FDMI_TYPE_HARDWARE_VERSION,
> + .length_hw_ver = 0x1400,
> + .type_dr_ver = FNIC_FDMI_TYPE_DRIVER_VERSION,
> + .length_dr_ver = 0x2000,
> + .type_rom_ver = FNIC_FDMI_TYPE_ROM_VERSION,
> + .length_rom_ver = 0xc00,
> + .type_fw_ver = FNIC_FDMI_TYPE_FIRMWARE_VERSION,
> + .length_fw_ver = 0x1400,
> +};
> +
> +/*
> + * Variables
> + *sid, port_id, port_name
> + */
> +struct fc_fdmi_rpa_s fnic_fdmi_rpa = {
> + .fchdr = {.r_ctl = 0x02, .did = {0xFF, 0xFF, 0xFA}, .type = 0x20,
> + .f_ctl = FNIC_ELS_REQ_FCTL, .ox_id = FNIC_FDMI_RPA_OXID,
> + .rx_id = 0xFFFF},
> + .fc_ct_hdr = {.rev = 0x01, .fs_type = 0xFA, .fs_subtype = 0x10,
> + .command = 0x1102},
> + .num_port_attributes = 0x6000000,
> + .type_fc4 = FNIC_FDMI_TYPE_FC4_TYPES,
> + .length_fc4 = 0x2400,
> + .type_supp_speed = FNIC_FDMI_TYPE_SUPPORTED_SPEEDS,
> + .length_supp_speed = 0x800,
> + .type_cur_speed = FNIC_FDMI_TYPE_CURRENT_SPEED,
> + .length_cur_speed = 0x800,
> + .type_max_frame_size = FNIC_FDMI_TYPE_MAX_FRAME_SIZE,
> + .length_max_frame_size = 0x800,
> + .max_frame_size = 0x0080000,
> + .type_os_name = FNIC_FDMI_TYPE_OS_NAME,
> + .length_os_name = 0x1400,
> + .type_host_name = FNIC_FDMI_TYPE_HOST_NAME,
> + .length_host_name = 0x1000,
> +};
> +
> /*
> * Variables:
> * fh_s_id, port_id, port_name
> @@ -172,6 +234,7 @@ static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
> static void fdls_target_restart_nexus(struct fnic_tport_s *tport);
> static void fdls_start_tport_timer(struct fnic_iport_s *iport,
> struct fnic_tport_s *tport, int timeout);
> +static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport);
> static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
> int timeout);
> static void fdls_tport_timer_callback(struct timer_list *t);
> @@ -453,6 +516,36 @@ static void fdls_send_fabric_plogi(struct fnic_iport_s *iport)
> fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
> }
>
> +static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport)
> +{
> + struct fc_els_s plogi;
> + struct fc_hdr_s *fchdr = &plogi.fchdr;
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> + u64 fdmi_tov;
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fcid: 0x%x: FDLS send FDMI PLOGI", iport->fcid);
> +
> + memcpy(&plogi, &fnic_plogi_req, sizeof(plogi));
> +
> + hton24(fcid, iport->fcid);
> +
> + FNIC_SET_S_ID(fchdr, fcid);
> + hton24(fcid, 0XFFFFFA);
> + FNIC_SET_D_ID(fchdr, fcid);
> + FNIC_SET_OX_ID(fchdr, FNIC_PLOGI_FDMI_OXID);

Static oxids again.

> + FNIC_SET_NPORT_NAME(plogi, iport->wwpn);
> + FNIC_SET_NODE_NAME(plogi, iport->wwnn);
> + FNIC_SET_RDF_SIZE(plogi.u.csp_plogi, iport->max_payload_size);
> +
> + fnic_send_fcoe_frame(iport, &plogi, sizeof(struct fc_els_s));
> +
> + fdmi_tov = jiffies + msecs_to_jiffies(5000);
> + mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov));
> + iport->fabric.fdmi_pending = 1; > +}
> +
> static void fdls_send_rpn_id(struct fnic_iport_s *iport)
> {
> struct fc_rpn_id_s rpn_id;
> @@ -1015,6 +1108,92 @@ struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport,
> return NULL;
> }
>
> +static void fdls_fdmi_register_hba(struct fnic_iport_s *iport)
> +{
> + struct fc_fdmi_rhba_s fdmi_rhba;
> + uint8_t fcid[3];
> + uint16_t len;
> + int err;
> + struct fnic *fnic = iport->fnic;
> + struct vnic_devcmd_fw_info *fw_info = NULL;
> +
> + memcpy(&fdmi_rhba, &fnic_fdmi_rhba, sizeof(struct fc_fdmi_rhba_s));
> +
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID((&fdmi_rhba.fchdr), fcid);
> + fdmi_rhba.hba_identifier = htonll(iport->wwpn);
> + fdmi_rhba.port_name = htonll(iport->wwpn);
> + fdmi_rhba.node_name = htonll(iport->wwnn);
> +
> + err = vnic_dev_fw_info(fnic->vdev, &fw_info);
> + if (!err) {
> + snprintf(fdmi_rhba.serial_num, sizeof(fdmi_rhba.serial_num) - 1,
> + "%s", fw_info->hw_serial_number);
> + snprintf(fdmi_rhba.hardware_ver,
> + sizeof(fdmi_rhba.hardware_ver) - 1, "%s",
> + fw_info->hw_version);
> + strscpy(fdmi_rhba.firmware_ver, fw_info->fw_version,
> + sizeof(fdmi_rhba.firmware_ver) - 1);

It turns out to be _really_ useful if host-specific information (like
the hostname) is included in the FDMI information.
Especially if you want to troubleshoot fabric setups, and validate the
physical setup against the logical setup.
There is a function 'fc_system_hostname' for doing exactly this ...

> +
> + len = ARRAY_SIZE(fdmi_rhba.model);
> + if (fnic->subsys_desc_len >= len)
> + fnic->subsys_desc_len = len - 1;
> + memcpy(&fdmi_rhba.model, fnic->subsys_desc, fnic->subsys_desc_len);
> + fdmi_rhba.model[fnic->subsys_desc_len] = 0x00;
> + }
> +
> + snprintf(fdmi_rhba.driver_ver, sizeof(fdmi_rhba.driver_ver) - 1, "%s",
> + DRV_VERSION);
> + snprintf(fdmi_rhba.rom_ver, sizeof(fdmi_rhba.rom_ver) - 1, "%s",
> + "N/A");
> + fnic_send_fcoe_frame(iport, &fdmi_rhba, sizeof(struct fc_fdmi_rhba_s));
> +}
> +
> +static void fdls_fdmi_register_pa(struct fnic_iport_s *iport)
> +{
> + struct fc_fdmi_rpa_s fdmi_rpa;
> +
> + uint8_t fcid[3];
> + struct fnic *fnic = iport->fnic;
> + u32 port_speed_bm;
> + u32 port_speed = vnic_dev_port_speed(fnic->vdev);
> +
> + memcpy(&fdmi_rpa, &fnic_fdmi_rpa, sizeof(struct fc_fdmi_rpa_s));
> + hton24(fcid, iport->fcid);
> + FNIC_SET_S_ID((&fdmi_rpa.fchdr), fcid);
> + fdmi_rpa.port_name = htonll(iport->wwpn);
> +
> + /* MDS does not support GIGE speed */
> + switch (port_speed) {
> + case DCEM_PORTSPEED_10G:
> + case DCEM_PORTSPEED_20G:
> + /* There is no bit for 20G */
> + port_speed_bm = 0x010000;
> + break;
> + case DCEM_PORTSPEED_25G:
> + port_speed_bm = 0x080000;
> + break;
> + case DCEM_PORTSPEED_40G:
> + case DCEM_PORTSPEED_4x10G:
> + port_speed_bm = 0x020000;
> + break;
> + case DCEM_PORTSPEED_100G:
> + port_speed_bm = 0x040000;
> + break;
> + default:
> + port_speed_bm = 0x8000;
> + break;
> + }

Please use the standard definitions from scsi_transport_fc.h

> + fdmi_rpa.supported_speed = htonl(port_speed_bm);
> + fdmi_rpa.current_speed = htonl(port_speed_bm);
> + fdmi_rpa.fc4_type[2] = 1;
> + snprintf(fdmi_rpa.os_name, sizeof(fdmi_rpa.os_name) - 1, "host%d",
> + fnic->lport->host->host_no);
> + snprintf(fdmi_rpa.host_name, sizeof(fdmi_rpa.host_name) - 1, "%s",
> + utsname()->nodename);
> + fnic_send_fcoe_frame(iport, &fdmi_rpa, sizeof(struct fc_fdmi_rpa_s));
> +}
> +
> void fdls_fabric_timer_callback(struct timer_list *t)
> {
> struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, retry_timer);
> @@ -1205,6 +1384,23 @@ void fdls_fabric_timer_callback(struct timer_list *t)
> spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> }
>
> +void fdls_fdmi_timer_callback(struct timer_list *t)
> +{
> + struct fnic_fdls_fabric_s *fabric = from_timer(fabric, t, fdmi_timer);
> + struct fnic_iport_s *iport =
> + container_of(fabric, struct fnic_iport_s, fabric);
> + struct fnic *fnic = iport->fnic;
> +
> + if (iport->fabric.fdmi_retry < 7) {
> + iport->fabric.fdmi_retry++;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "retry fdmi timer %d", iport->fabric.fdmi_retry);
> + fdls_send_fdmi_plogi(iport);
> + } else {
> + iport->fabric.fdmi_pending = 0;
> + }
> +}
> +
> static void fdls_send_delete_tport_msg(struct fnic_tport_s *tport)
> {
> struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
> @@ -1360,6 +1556,15 @@ static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
> fdls_send_fabric_plogi(iport);
> fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
> iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
> +
> + if ((fnic_fdmi_support == 1) && (!(iport->flags & FNIC_FDMI_ACTIVE))) {
> + /* we can do FDMI at the same time */
> + iport->fabric.fdmi_retry = 0;
> + timer_setup(&iport->fabric.fdmi_timer, fdls_fdmi_timer_callback,
> + 0);
> + fdls_send_fdmi_plogi(iport);
> + iport->flags |= FNIC_FDMI_ACTIVE;
> + }
> }
>
> static void
> @@ -2440,6 +2645,69 @@ fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
> }
> }
>
> +static void fdls_process_fdmi_plogi_rsp(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + struct fc_els_s *plogi_rsp = (struct fc_els_s *) fchdr;
> + struct fc_els_reject_s *els_rjt = (struct fc_els_reject_s *) fchdr;
> + struct fnic *fnic = iport->fnic;
> + u64 fdmi_tov;
> +
> + if (ntoh24(fchdr->sid) == 0XFFFFFA) {
> + del_timer_sync(&iport->fabric.fdmi_timer);
> + iport->fabric.fdmi_pending = 0;
> + switch (plogi_rsp->command) {
> + case FC_LS_ACC:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FDLS process fdmi PLOGI response status: FC_LS_ACC\n");
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Sending fdmi registration for port 0x%x\n",
> + iport->fcid);
> +
> + fdls_fdmi_register_hba(iport);
> + fdls_fdmi_register_pa(iport);
> + fdmi_tov = jiffies + msecs_to_jiffies(5000);
> + mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov));
> + iport->fabric.fdmi_pending = 2;
> + break;
> + case FC_LS_REJ:
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Fabric FDMI PLOGI returned FC_LS_REJ reason: 0x%x",
> + els_rjt->reason_code);
> +
> + if (((els_rjt->reason_code == FC_ELS_RJT_LOGICAL_BUSY)
> + || (els_rjt->reason_code == FC_ELS_RJT_BUSY))
> + && (iport->fabric.fdmi_retry < 7)) {
> + iport->fabric.fdmi_retry++;
> + fdls_send_fdmi_plogi(iport);
> + }
> + break;
> + default:
> + break;
> + }
> + }
> +}
> +
> +static void fdls_process_fdmi_reg_ack(struct fnic_iport_s *iport,
> + struct fc_hdr_s *fchdr)
> +{
> + struct fnic *fnic = iport->fnic;
> +
> + if (iport->fabric.fdmi_pending > 0) {
> + iport->fabric.fdmi_pending--;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport fcid: 0x%x: Received FDMI registration ack\n",
> + iport->fcid);
> +
> + if (iport->fabric.fdmi_pending == 0) {
> + del_timer_sync(&iport->fabric.fdmi_timer);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport fcid: 0x%x: Canceling FDMI timer\n",
> + iport->fcid);
> + }
> + }
> +}
> +
> static void
> fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
> struct fc_hdr_s *fchdr)
> @@ -3367,6 +3635,12 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
> }
> return FNIC_FABRIC_PLOGI_RSP;
>
> + case FNIC_PLOGI_FDMI_OXID:
> + return FNIC_FDMI_PLOGI_RSP;
> + case FNIC_FDMI_REG_HBA_OXID:
> + case FNIC_FDMI_RPA_OXID:
> + return FNIC_FDMI_RSP;
> +
> case FNIC_SCR_REQ_OXID:
> if (type == FC_LS_ACC) {
> if ((s_id != FC_FABRIC_CONTROLLER)
> @@ -3447,6 +3721,9 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
> case FNIC_FABRIC_PLOGI_RSP:
> fdls_process_fabric_plogi_rsp(iport, fchdr);
> break;
> + case FNIC_FDMI_PLOGI_RSP:
> + fdls_process_fdmi_plogi_rsp(iport, fchdr);
> + break;
> case FNIC_FABRIC_RPN_RSP:
> fdls_process_rpn_id_rsp(iport, fchdr);
> break;
> @@ -3514,9 +3791,13 @@ void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
> case FNIC_ELS_RLS:
> fdls_process_rls_req(iport, fchdr);
> break;
> + case FNIC_FDMI_RSP:
> + fdls_process_fdmi_reg_ack(iport, fchdr);
> + break;
> default:
> FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> "Received unknown FCoE frame of len: %d. Dropping frame", len);
> break;
> }
> }
> +
> diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
> index 92cd17efa40f..7d7009197dbc 100644
> --- a/drivers/scsi/fnic/fnic.h
> +++ b/drivers/scsi/fnic/fnic.h
> @@ -82,6 +82,72 @@
> /* Retry supported by rport (returned by PRLI service parameters) */
> #define FNIC_FC_RP_FLAGS_RETRY 0x1
>
> +/* Cisco vendor id */
> +#define PCI_VENDOR_ID_CISCO 0x1137
> +#define PCI_DEVICE_ID_CISCO_VIC_FC 0x0045 /* fc vnic */
> +
> +/* sereno pcie switch */
> +#define PCI_DEVICE_ID_CISCO_SERENO 0x004e
> +#define PCI_DEVICE_ID_CISCO_CRUZ 0x007a /* Cruz */
> +#define PCI_DEVICE_ID_CISCO_BODEGA 0x0131 /* Bodega */
> +#define PCI_DEVICE_ID_CISCO_BEVERLY 0x025f /* Beverly */
> +
> +/* Sereno */
> +#define PCI_SUBDEVICE_ID_CISCO_VASONA 0x004f /* vasona mezz */
> +#define PCI_SUBDEVICE_ID_CISCO_COTATI 0x0084 /* cotati mlom */
> +#define PCI_SUBDEVICE_ID_CISCO_LEXINGTON 0x0085 /* lexington pcie */
> +#define PCI_SUBDEVICE_ID_CISCO_ICEHOUSE 0x00cd /* Icehouse */
> +#define PCI_SUBDEVICE_ID_CISCO_KIRKWOODLAKE 0x00ce /* KirkwoodLake pcie */
> +#define PCI_SUBDEVICE_ID_CISCO_SUSANVILLE 0x012e /* Susanville MLOM */
> +#define PCI_SUBDEVICE_ID_CISCO_TORRANCE 0x0139 /* Torrance MLOM */
> +
> +/* Cruz */
> +#define PCI_SUBDEVICE_ID_CISCO_CALISTOGA 0x012c /* Calistoga MLOM */
> +#define PCI_SUBDEVICE_ID_CISCO_MOUNTAINVIEW 0x0137 /* Cruz Mezz */
> +/* Cruz MountTian SIOC */
> +#define PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN 0x014b
> +#define PCI_SUBDEVICE_ID_CISCO_CLEARLAKE 0x014d /* ClearLake pcie */
> +/* Cruz MountTian2 SIOC */
> +#define PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN2 0x0157
> +#define PCI_SUBDEVICE_ID_CISCO_CLAREMONT 0x015d /* Claremont MLOM */
> +
> +/* Bodega */
> +/* VIC 1457 PCIe mLOM */
> +#define PCI_SUBDEVICE_ID_CISCO_BRADBURY 0x0218
> +#define PCI_SUBDEVICE_ID_CISCO_BRENTWOOD 0x0217 /* VIC 1455 PCIe */
> +/* VIC 1487 PCIe mLOM */
> +#define PCI_SUBDEVICE_ID_CISCO_BURLINGAME 0x021a
> +#define PCI_SUBDEVICE_ID_CISCO_BAYSIDE 0x0219 /* VIC 1485 PCIe */
> +/* VIC 1440 Mezz mLOM */
> +#define PCI_SUBDEVICE_ID_CISCO_BAKERSFIELD 0x0215
> +#define PCI_SUBDEVICE_ID_CISCO_BOONVILLE 0x0216 /* VIC 1480 Mezz */
> +#define PCI_SUBDEVICE_ID_CISCO_BENICIA 0x024a /* VIC 1495 */
> +#define PCI_SUBDEVICE_ID_CISCO_BEAUMONT 0x024b /* VIC 1497 */
> +#define PCI_SUBDEVICE_ID_CISCO_BRISBANE 0x02af /* VIC 1467 */
> +#define PCI_SUBDEVICE_ID_CISCO_BENTON 0x02b0 /* VIC 1477 */
> +#define PCI_SUBDEVICE_ID_CISCO_TWIN_RIVER 0x02cf /* VIC 14425 */
> +#define PCI_SUBDEVICE_ID_CISCO_TWIN_PEAK 0x02d0 /* VIC 14825 */
> +
> +/* Beverly */
> +#define PCI_SUBDEVICE_ID_CISCO_BERN 0x02de /* VIC 15420 */
> +#define PCI_SUBDEVICE_ID_CISCO_STOCKHOLM 0x02dd /* VIC 15428 */
> +#define PCI_SUBDEVICE_ID_CISCO_KRAKOW 0x02dc /* VIC 15411 */
> +#define PCI_SUBDEVICE_ID_CISCO_LUCERNE 0x02db /* VIC 15231 */
> +#define PCI_SUBDEVICE_ID_CISCO_TURKU 0x02e8 /* VIC 15238 */
> +#define PCI_SUBDEVICE_ID_CISCO_TURKU_PLUS 0x02f3 /* VIC 15237 */
> +#define PCI_SUBDEVICE_ID_CISCO_ZURICH 0x02df /* VIC 15230 */
> +#define PCI_SUBDEVICE_ID_CISCO_RIGA 0x02e0 /* VIC 15427 */
> +#define PCI_SUBDEVICE_ID_CISCO_GENEVA 0x02e1 /* VIC 15422 */
> +#define PCI_SUBDEVICE_ID_CISCO_HELSINKI 0x02e4 /* VIC 15235 */
> +#define PCI_SUBDEVICE_ID_CISCO_GOTHENBURG 0x02f2 /* VIC 15425 */
> +
> +struct fnic_pcie_device {
> + u32 device;
> + u8 *desc;
> + u32 subsystem_device;
> + u8 *subsys_desc;
> +};
> +
> /*
> * fnic private data per SCSI command.
> * These fields are locked by the hashed io_req_lock.
> @@ -134,6 +200,7 @@ static inline u64 fnic_flags_and_state(struct scsi_cmnd *cmd)
> #define fnic_clear_state_flags(fnicp, st_flags) \
> __fnic_set_state_flags(fnicp, st_flags, 1)
>
> +extern unsigned int fnic_fdmi_support;
> extern unsigned int fnic_log_level;
> extern unsigned int io_completions;
> extern struct workqueue_struct *fnic_event_queue;
> @@ -366,6 +433,9 @@ struct fnic {
>
> /* interrupt resource cache line section */
> ____cacheline_aligned struct vnic_intr intr[FNIC_MSIX_INTR_MAX];
> +
> + char subsys_desc[14];
> + int subsys_desc_len;
> };
>
Please reconsider adding it here.
As the above entries are cacheline aligned there's a good chance you
have introduced holes by placing it afterwards.

> static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip)
> @@ -433,5 +503,7 @@ fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
> void __fnic_set_state_flags(struct fnic *, unsigned long, unsigned long);
> void fnic_dump_fchost_stats(struct Scsi_Host *, struct fc_host_statistics *);
> void fnic_free_txq(struct list_head *head);
> +int fnic_get_desc_by_devid(struct pci_dev *pdev, char **desc,
> + char **subsys_desc);
>
> #endif /* _FNIC_H_ */
> diff --git a/drivers/scsi/fnic/fnic_fdls.h b/drivers/scsi/fnic/fnic_fdls.h
> index 9eb25ed9c19f..88462363d754 100644
> --- a/drivers/scsi/fnic/fnic_fdls.h
> +++ b/drivers/scsi/fnic/fnic_fdls.h
> @@ -329,6 +329,7 @@ void fdls_send_tport_abts(struct fnic_iport_s *iport,
> struct fnic_tport_s *tport);
> void fdls_delete_tport(struct fnic_iport_s *iport,
> struct fnic_tport_s *tport);
> +void fdls_fdmi_timer_callback(struct timer_list *t);
>
> /* fnic_fcs.c */
> void fnic_fdls_init(struct fnic *fnic, int usefip);
> @@ -366,4 +367,3 @@ struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport,
> uint64_t wwpn);
>
> #endif /* _FNIC_FDLS_H_ */
> -

Tsk. Fixup the patch introducing fnic_fdls.h instead.

> diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
> index 577048e30c12..7d10d603f53b 100644
> --- a/drivers/scsi/fnic/fnic_main.c
> +++ b/drivers/scsi/fnic/fnic_main.c
> @@ -62,6 +62,9 @@ unsigned int fnic_log_level;
> module_param(fnic_log_level, int, S_IRUGO|S_IWUSR);
> MODULE_PARM_DESC(fnic_log_level, "bit mask of fnic logging levels");
>
> +unsigned int fnic_fdmi_support = 1;
> +module_param(fnic_fdmi_support, int, 0644);
> +MODULE_PARM_DESC(fnic_fdmi_support, "FDMI support");
>
> unsigned int io_completions = FNIC_DFLT_IO_COMPLETIONS;
> module_param(io_completions, int, S_IRUGO|S_IWUSR);
> @@ -607,6 +610,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> int i;
> unsigned long flags;
> int hwq;
> + char *desc, *subsys_desc;
> + int len;
>
> /*
> * Allocate SCSI Host and set up association between host,
> @@ -640,6 +645,23 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> fnic->fnic_num = fnic_id;
> fnic_stats_debugfs_init(fnic);
>
> + /* Find model name from PCIe subsys ID */
> + if (fnic_get_desc_by_devid(pdev, &desc, &subsys_desc) == 0) {
> + pr_info("Model: %s\n", subsys_desc);
> +
> + /* Update FDMI model */
> + fnic->subsys_desc_len = strlen(subsys_desc);
> + len = ARRAY_SIZE(fnic->subsys_desc);
> + if (fnic->subsys_desc_len > len)
> + fnic->subsys_desc_len = len;
> + memcpy(fnic->subsys_desc, subsys_desc, fnic->subsys_desc_len);
> + pr_info("FDMI Model: %s\n", fnic->subsys_desc);
> + } else {
> + fnic->subsys_desc_len = 0;
> + pr_info("Model: %s subsys_id: 0x%04x\n", "Unknown",
> + pdev->subsystem_device);
> + }
> +
> err = pci_enable_device(pdev);
> if (err) {
> pr_err("Cannot enable PCI device, aborting.\n");
> @@ -1014,6 +1036,9 @@ static void fnic_remove(struct pci_dev *pdev)
> fnic_fcoe_evlist_free(fnic);
> }
>
> + if ((fnic_fdmi_support == 1) && (fnic->iport.fabric.fdmi_pending > 0))
> + del_timer_sync(&fnic->iport.fabric.fdmi_timer);
> +
> /*
> * Log off the fabric. This stops all remote ports, dns port,
> * logs off the fabric. This flushes all rport, disc, lport work
> @@ -1199,3 +1224,4 @@ static void __exit fnic_cleanup_module(void)
>
> module_init(fnic_init_module);
> module_exit(fnic_cleanup_module);
> +
> diff --git a/drivers/scsi/fnic/fnic_pci_subsys_devid.c b/drivers/scsi/fnic/fnic_pci_subsys_devid.c
> new file mode 100644
> index 000000000000..1729c3a7ed05
> --- /dev/null
> +++ b/drivers/scsi/fnic/fnic_pci_subsys_devid.c
> @@ -0,0 +1,133 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright 2008 Cisco Systems, Inc. All rights reserved.
> + * Copyright 2007 Nuova Systems, Inc. All rights reserved.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/mempool.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <linux/version.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/spinlock.h>
> +#include <linux/workqueue.h>
> +#include <linux/kthread.h>
> +#include <linux/if_ether.h>
> +#include "fnic.h"
> +
> +static struct fnic_pcie_device fnic_pcie_device_table[] = {
> + {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_VASONA,
> + "VIC 1280"},
> + {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_COTATI,
> + "VIC 1240"},
> + {PCI_DEVICE_ID_CISCO_SERENO, "Sereno",
> + PCI_SUBDEVICE_ID_CISCO_LEXINGTON, "VIC 1225"},
> + {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_ICEHOUSE,
> + "VIC 1285"},
> + {PCI_DEVICE_ID_CISCO_SERENO, "Sereno",
> + PCI_SUBDEVICE_ID_CISCO_KIRKWOODLAKE, "VIC 1225T"},
> + {PCI_DEVICE_ID_CISCO_SERENO, "Sereno",
> + PCI_SUBDEVICE_ID_CISCO_SUSANVILLE, "VIC 1227"},
> + {PCI_DEVICE_ID_CISCO_SERENO, "Sereno", PCI_SUBDEVICE_ID_CISCO_TORRANCE,
> + "VIC 1227T"},
> +
> + {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_CALISTOGA,
> + "VIC 1340"},
> + {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_MOUNTAINVIEW,
> + "VIC 1380"},
> + {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN,
> + "C3260-SIOC"},
> + {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_CLEARLAKE,
> + "VIC 1385"},
> + {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_MOUNTTIAN2,
> + "C3260-SIOC"},
> + {PCI_DEVICE_ID_CISCO_CRUZ, "Cruz", PCI_SUBDEVICE_ID_CISCO_CLAREMONT,
> + "VIC 1387"},
> +
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BRADBURY,
> + "VIC 1457"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
> + PCI_SUBDEVICE_ID_CISCO_BRENTWOOD, "VIC 1455"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
> + PCI_SUBDEVICE_ID_CISCO_BURLINGAME, "VIC 1487"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BAYSIDE,
> + "VIC 1485"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
> + PCI_SUBDEVICE_ID_CISCO_BAKERSFIELD, "VIC 1440"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
> + PCI_SUBDEVICE_ID_CISCO_BOONVILLE, "VIC 1480"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BENICIA,
> + "VIC 1495"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BEAUMONT,
> + "VIC 1497"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BRISBANE,
> + "VIC 1467"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega", PCI_SUBDEVICE_ID_CISCO_BENTON,
> + "VIC 1477"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
> + PCI_SUBDEVICE_ID_CISCO_TWIN_RIVER, "VIC 14425"},
> + {PCI_DEVICE_ID_CISCO_BODEGA, "Bodega",
> + PCI_SUBDEVICE_ID_CISCO_TWIN_PEAK, "VIC 14825"},
> +
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_BERN,
> + "VIC 15420"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
> + PCI_SUBDEVICE_ID_CISCO_STOCKHOLM, "VIC 15428"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_KRAKOW,
> + "VIC 15411"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
> + PCI_SUBDEVICE_ID_CISCO_LUCERNE, "VIC 15231"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_TURKU,
> + "VIC 15238"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_GENEVA,
> + "VIC 15422"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
> + PCI_SUBDEVICE_ID_CISCO_HELSINKI, "VIC 15235"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
> + PCI_SUBDEVICE_ID_CISCO_GOTHENBURG, "VIC 15425"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly",
> + PCI_SUBDEVICE_ID_CISCO_TURKU_PLUS, "VIC 15237"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_ZURICH,
> + "VIC 15230"},
> + {PCI_DEVICE_ID_CISCO_BEVERLY, "Beverly", PCI_SUBDEVICE_ID_CISCO_RIGA,
> + "VIC 15427"},
> +
> + {0,}
> +};
> +
> +int fnic_get_desc_by_devid(struct pci_dev *pdev, char **desc,
> + char **subsys_desc)
> +{
> + unsigned short device = PCI_DEVICE_ID_CISCO_VIC_FC;
> + int max = ARRAY_SIZE(fnic_pcie_device_table);
> + struct fnic_pcie_device *t = fnic_pcie_device_table;
> + int index = 0;
> +
> + if (memcmp((char *) &pdev->device, (char *) &device, sizeof(short)) !=
> + 0)
> + return 1;
> +

What on earth ... you are not seriously comparing unsigned shorts via
memcmp? What happened to the good old '=='?
Bah.

> + while (t->device != 0) {
> + if (memcmp
> + ((char *) &pdev->subsystem_device,
> + (char *) &t->subsystem_device, sizeof(short)) == 0)
> + break;
> + t++;
> + index++;
> + }
> +
> + if (index >= max - 1) {
> + *desc = NULL;
> + *subsys_desc = NULL;
> + return 1;
> + }
> +
> + *desc = fnic_pcie_device_table[index].desc;
> + *subsys_desc = fnic_pcie_device_table[index].subsys_desc;
> + return 0;
> +}

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-12 06:48:11

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 07/14] scsi: fnic: Add and integrate support for FIP

On 6/10/24 23:50, Karan Tilak Kumar wrote:
> Add and integrate support for FCoE Initialization
> (protocol) FIP. This protocol will be exercised on
> Cisco UCS rack servers.
> Add support to specifically print FIP related
> debug messages.
> Replace existing definitions to handle new
> data structures.
> Clean up old and obsolete definitions.
>
Aren't you getting a bit overboard here?

I am _positive_ that the original fnic driver _did_ do FIP.
What happened to that?
Why can't you just use that implementation?

And if you can't use that implementation, shouldn't this rather be
a new driver instead of replacing most if not all functionality of
the original fnic driver?

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-12 06:58:54

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 08/14] scsi: fnic: Add functionality in fnic to support FDLS

On 6/10/24 23:50, Karan Tilak Kumar wrote:
> Add interfaces in fnic to use FDLS services.
> Modify link up and link down functionality to use FDLS.
> Replace existing interfaces to handle new functionality
> provided by FDLS.
> Modify data types of some data members to handle new
> functionality.
> Add processing of tports and handling of tports.
>
> Reviewed-by: Sesidhar Baddela <[email protected]>
> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> Reviewed-by: Gian Carlo Boffa <[email protected]>
> Signed-off-by: Karan Tilak Kumar <[email protected]>
> ---
> drivers/scsi/fnic/fdls_disc.c | 74 +++++
> drivers/scsi/fnic/fip.c | 27 +-
> drivers/scsi/fnic/fnic.h | 20 +-
> drivers/scsi/fnic/fnic_fcs.c | 498 ++++++++++++++++++++++++----------
> drivers/scsi/fnic/fnic_main.c | 10 +-
> drivers/scsi/fnic/fnic_scsi.c | 127 +++++++--
> 6 files changed, 587 insertions(+), 169 deletions(-)
>
This seems to not just _add_ the functionality to use FDLS, but rather
_replace_ the existing functionality with FDLS.
IE it seems that after this change the driver will always do FDLS,
causing a possible service interruption with existing setups.
Hmm?

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-12 07:26:40

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 09/14] scsi: fnic: Modify IO path to use FDLS

On 6/10/24 23:50, Karan Tilak Kumar wrote:
> Modify IO path to use FDLS.
> Add helper functions to process IOs.
> Remove unused template functions.
> Cleanup obsolete code.
> Refactor old function definitions.
>
> Reviewed-by: Sesidhar Baddela <[email protected]>
> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> Reviewed-by: Gian Carlo Boffa <[email protected]>
> Signed-off-by: Karan Tilak Kumar <[email protected]>
> ---
> drivers/scsi/fnic/fnic.h | 20 +-
> drivers/scsi/fnic/fnic_io.h | 3 +
> drivers/scsi/fnic/fnic_main.c | 5 +-
> drivers/scsi/fnic/fnic_scsi.c | 1107 +++++++++++++++++++-------------
> drivers/scsi/fnic/fnic_stats.h | 2 -
> 5 files changed, 680 insertions(+), 457 deletions(-)
>

Well. This patch reverts bascially all changes I did to the fnic driver
in converting it to use tagset iterators.

Please update it to stay with tagset iterators.

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-13 15:49:46

by John Garry

[permalink] [raw]
Subject: Re: [PATCH 07/14] scsi: fnic: Add and integrate support for FIP

On 10/06/2024 22:50, Karan Tilak Kumar wrote:
> Add and integrate support for FCoE Initialization
> (protocol) FIP. This protocol will be exercised on
> Cisco UCS rack servers.
> Add support to specifically print FIP related
> debug messages.
> Replace existing definitions to handle new
> data structures.
> Clean up old and obsolete definitions.

Fill out text up to 72 characters.

It really seems that multiple steps are required below

There are approx 2.5K LoC changes here

I don't know how anyone is supposed to review that

Some sparse comments, below

>
> Reviewed-by: Sesidhar Baddela <[email protected]>
> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> Reviewed-by: Gian Carlo Boffa <[email protected]>
> Signed-off-by: Karan Tilak Kumar <[email protected]>
> ---
> drivers/scsi/fnic/Makefile | 1 +
> drivers/scsi/fnic/fip.c | 875 +++++++++++++++++++++++++++++++++
> drivers/scsi/fnic/fip.h | 341 +++++++++++++
> drivers/scsi/fnic/fnic.h | 23 +-
> drivers/scsi/fnic/fnic_fcs.c | 889 ++++++----------------------------
> drivers/scsi/fnic/fnic_main.c | 47 +-
> 6 files changed, 1402 insertions(+), 774 deletions(-)
> create mode 100644 drivers/scsi/fnic/fip.c
> create mode 100644 drivers/scsi/fnic/fip.h
>
> diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
> index af156c69da0c..c025e875009e 100644
> --- a/drivers/scsi/fnic/Makefile
> +++ b/drivers/scsi/fnic/Makefile
> @@ -2,6 +2,7 @@
> obj-$(CONFIG_FCOE_FNIC) += fnic.o
>
> fnic-y := \
> + fip.o\
> fnic_attrs.o \
> fnic_isr.o \
> fnic_main.o \
> diff --git a/drivers/scsi/fnic/fip.c b/drivers/scsi/fnic/fip.c
> new file mode 100644
> index 000000000000..8d4f6b98407b
> --- /dev/null
> +++ b/drivers/scsi/fnic/fip.c
> @@ -0,0 +1,875 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright 2008 Cisco Systems, Inc. All rights reserved.
> + * Copyright 2007 Nuova Systems, Inc. All rights reserved.
> + */
> +#include "fnic.h"
> +#include "fip.h"
> +#include <linux/etherdevice.h>
> +
> +extern struct workqueue_struct *fnic_fip_queue;
> +
> +#define TRUE 1
> +#define FALSE 0

use true and false for boolean type - they are already available

> +
> +int drop_rsp = TRUE;

this is not even referenced in this patch

> +
> +#define FIP_FNIC_RESET_WAIT_COUNT 15
> +
> +#define htonll(x) cpu_to_be64(x)

why? just use cpu_to_be64() directly

> +
> +/****************************** Functions ***********************************/
> +
> +/**
> + * fnic_fcoe_reset_vlans
> + *
> + * Frees up the list of discovered vlans
> + *
> + * @param fnic driver instance
> + */
> +
> +void fnic_fcoe_reset_vlans(struct fnic *fnic)
> +{
> + unsigned long flags;
> + struct fcoe_vlan *vlan, *next;
> +
> + spin_lock_irqsave(&fnic->vlans_lock, flags);
> + if (!list_empty(&fnic->vlan_list)) {
> + list_for_each_entry_safe(vlan, next, &fnic->vlan_list, list) {
> + list_del(&vlan->list);
> + kfree(vlan);
> + }
> + }
> +
> + spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Reset vlan complete\n");
> +}
> +
> +/**
> + * fnic_fcoe_send_vlan_req
> + *
> + * Sends FIP vlan request to all FCFs MAC
> + *
> + * @param fnic driver instance
> + */
> +
> +void fnic_fcoe_send_vlan_req(struct fnic *fnic)
> +{
> + struct fnic_iport_s *iport = &fnic->iport;
> + struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> + u64 vlan_tov;
> +
> + int fr_len;
> + struct fip_vlan_req_s vlan_req;
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Enter send vlan req\n");
> + fnic_fcoe_reset_vlans(fnic);
> +
> + fnic->set_vlan(fnic, 0);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "set vlan done\n");
> +
> + fr_len = sizeof(struct fip_vlan_req_s);
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "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]);
> +
> + memcpy(&vlan_req, &fip_vlan_req_tmpl, fr_len);
> + memcpy(vlan_req.eth.smac, iport->hwmac, ETH_ALEN);
> + memcpy(vlan_req.mac_desc.mac, iport->hwmac, ETH_ALEN);
> +
> + atomic64_inc(&fnic_stats->vlan_stats.vlan_disc_reqs);
> +
> + iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
> +
> + fnic_send_fip_frame(iport, &vlan_req, fr_len);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "vlan req sent\n");
> +
> + 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->lport->host, fnic->fnic_num,
> + "fip timer set\n");
> +}
> +
> +/**
> + * fnic_fcoe_process_vlan_resp
> + *
> + * Processes the vlan response from one FCF and populates VLAN list.
> + * Will wait for responses from multiple FCFs until timeout.
> + *
> + * @param fnic driver instance
> + * @param fiph received fip frame
> + */
> +
> +void fnic_fcoe_process_vlan_resp(struct fnic *fnic,
> + struct fip_header_s *fiph)
> +{
> + struct fip_vlan_notif_s *vlan_notif = (struct fip_vlan_notif_s *) fiph;
> +
> + struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> + u16 vid;
> + int num_vlan = 0;
> + int cur_desc, desc_len;
> + struct fcoe_vlan *vlan;
> + struct fip_vlan_desc_s *vlan_desc;
> + unsigned long flags;
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p got vlan resp\n", fnic);
> +
> + desc_len = ntohs(vlan_notif->fip.desc_len);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "desc_len %d\n", desc_len);
> +
> + spin_lock_irqsave(&fnic->vlans_lock, flags);
> +
> + cur_desc = 0;
> + while (desc_len > 0) {
> + vlan_desc =
> + (struct fip_vlan_desc_s *) (((char *) vlan_notif->vlans_desc)
> + + cur_desc * 4);
> +
> + if (vlan_desc->type == FIP_TYPE_VLAN) {
> + if (vlan_desc->len != 1) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Invalid descriptor length(%x) in VLan response\n",
> + vlan_desc->len);
> +
> + }
> + num_vlan++;
> + vid = ntohs(vlan_desc->vlan);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "process_vlan_resp: FIP VLAN %d\n", vid);
> + vlan = kmalloc(sizeof(*vlan), GFP_ATOMIC);


is this alloc under spinlock really required?

> +
> + if (!vlan) {
> + /* retry from timer */
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Mem Alloc failure\n");
> + spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> + goto out;
> + }
> + memset(vlan, 0, sizeof(struct fcoe_vlan));

kzalloc should have been used

> + vlan->vid = vid & 0x0fff;
> + vlan->state = FIP_VLAN_AVAIL;
> + list_add_tail(&vlan->list, &fnic->vlan_list);
> + break;
> + } else {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Invalid descriptor type(%x) in VLan response\n",
> + vlan_desc->type);
> + /*
> + * Note : received a type=2 descriptor here i.e. FIP
> + * MAC Address Descriptor
> + */
> + }
> + cur_desc += vlan_desc->len;
> + desc_len -= vlan_desc->len;
> + }
> +
> + /* any VLAN descriptors present ? */
> + if (num_vlan == 0) {
> + atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p No VLAN descriptors in FIP VLAN response\n",
> + fnic);
> + }
> +
> + spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> +
> +out:
> + return;
> +}
> +
> +/**
> + * fnic_fcoe_start_fcf_discovery
> + *
> + * Starts FIP FCF discovery in a selected vlan
> + *
> + * @param fnic driver instance
> + */
> +
> +void fnic_fcoe_start_fcf_discovery(struct fnic *fnic)
> +{
> + struct fnic_iport_s *iport = &fnic->iport;
> + u64 fcs_tov;
> +
> + int fr_len;
> + struct fip_discovery_s disc_sol;
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p start fcf discovery\n", fnic);
> + fr_len = sizeof(struct fip_discovery_s);
> + memset(iport->selected_fcf.fcf_mac, 0, ETH_ALEN);
> +
> + memcpy(&disc_sol, &fip_discovery_tmpl, fr_len);
> + memcpy(disc_sol.eth.smac, iport->hwmac, ETH_ALEN);
> + memcpy(disc_sol.mac_desc.mac, iport->hwmac, ETH_ALEN);
> + iport->selected_fcf.fcf_priority = 0xFF;
> +
> + disc_sol.name_desc.name = htonll(iport->wwnn);
> + fnic_send_fip_frame(iport, &disc_sol, fr_len);
> +
> + iport->fip.state = FDLS_FIP_FCF_DISCOVERY_STARTED;
> +
> + fcs_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FCS_TOV);
> + mod_timer(&fnic->retry_fip_timer, round_jiffies(fcs_tov));
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p Started FCF discovery", fnic);
> +
> +}
> +
> +/**
> + * fnic_fcoe_fip_discovery_resp
> + *
> + * Processes FCF advertisements.
> + * They can be:
> + * solicited Sent in response of a discover FCF FIP request
> + * We will only store the information of the FCF with
> + * highest priority.
> + * We wait until timeout in case of multiple FCFs.
> + * unsolicited Sent periodically by the FCF for keep alive.
> + * If FLOGI is in progress or completed and the advertisement is
> + * received by our selected FCF, refresh the keep alive timer.
> + *
> + * @param fnic driver instance
> + * @param fiph received frame
> + */
> +
> +void fnic_fcoe_fip_discovery_resp(struct fnic *fnic,
> + struct fip_header_s *fiph)
> +{
> + struct fnic_iport_s *iport = &fnic->iport;
> + struct fip_disc_adv_s *disc_adv = (struct fip_disc_adv_s *) fiph;
> + u64 fcs_ka_tov;
> + int fka_has_changed;
> +
> + if (iport->fip.state == FDLS_FIP_FCF_DISCOVERY_STARTED) {
> + if (ntohs(disc_adv->fip.flags) & FIP_FLAG_S) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p Solicited adv\n", fnic);
> +
> + if ((disc_adv->prio_desc.priority <
> + iport->selected_fcf.fcf_priority)
> + && (ntohs(disc_adv->fip.flags) & FIP_FLAG_A)) {
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p FCF Available\n", fnic);
> + memcpy(iport->selected_fcf.fcf_mac, disc_adv->mac_desc.mac,
> + ETH_ALEN);
> + iport->selected_fcf.fcf_priority =
> + disc_adv->prio_desc.priority;
> + iport->selected_fcf.fka_adv_period =
> + ntohl(disc_adv->fka_adv_desc.fka_adv);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "adv time %d",
> + iport->selected_fcf.fka_adv_period);
> + iport->selected_fcf.ka_disabled =
> + (disc_adv->fka_adv_desc.rsvd_D & 1);
> + }
> + }
> + } else if ((iport->fip.state == FDLS_FIP_FLOGI_STARTED)

switch statement is better here

> + || (iport->fip.state == FDLS_FIP_FLOGI_COMPLETE)) {
> + if (!(ntohs(disc_adv->fip.flags) & FIP_FLAG_S)) {
> + /* same fcf */
> + if (memcmp(iport->selected_fcf.fcf_mac, disc_adv->mac_desc.mac,
> + ETH_ALEN) == 0) {
> + if (iport->selected_fcf.fka_adv_period
> + != ntohl(disc_adv->fka_adv_desc.fka_adv)) {
> + iport->selected_fcf.fka_adv_period =
> + ntohl(disc_adv->fka_adv_desc.fka_adv);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host,
> + fnic->fnic_num, "change fka to %d",
> + iport->selected_fcf.fka_adv_period);
> + }
> +
> + fka_has_changed = (iport->selected_fcf.ka_disabled == 1)
> + && ((disc_adv->fka_adv_desc.rsvd_D & 1) == 0);
> +
> + iport->selected_fcf.ka_disabled =
> + (disc_adv->fka_adv_desc.rsvd_D & 1);
> + if (!((iport->selected_fcf.ka_disabled)
> + || (iport->selected_fcf.fka_adv_period == 0))) {
> +
> + fcs_ka_tov = jiffies
> + + 3
> + *
> + msecs_to_jiffies(
> + iport->selected_fcf.fka_adv_period);
> + mod_timer(&fnic->fcs_ka_timer,
> + round_jiffies(fcs_ka_tov));
> +
> + } else {
> + if (timer_pending(&fnic->fcs_ka_timer))
> + del_timer_sync(&fnic->fcs_ka_timer);
> + }
> +
> + if (fka_has_changed) {
> + u64 tov;
> +
> + if (iport->selected_fcf.fka_adv_period != 0) {
> +
> + tov = jiffies +
> + msecs_to_jiffies(
> + iport->selected_fcf.fka_adv_period);
> + mod_timer(&fnic->enode_ka_timer,
> + round_jiffies(tov));
> +
> + tov =
> + jiffies +
> + msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
> + mod_timer(&fnic->vn_ka_timer, round_jiffies(tov));

all this code is too complicated

> + }
> + }
> + }
> + }
> + }
> +}
> +
> +/**
> + * fnic_fcoe_start_flogi
> + *
> + * Sends FIP FLOGI to the selected FCF
> + *
> + * @param fnic driver instance
> + */
> +
> +void fnic_fcoe_start_flogi(struct fnic *fnic)
> +{
> + struct fnic_iport_s *iport = &fnic->iport;
> +
> + int fr_len;
> + struct fip_flogi_s flogi_req;
> + u64 flogi_tov;
> +
> + fr_len = sizeof(struct fip_flogi_s);
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p Start fip FLOGI\n", fnic);
> +
> + memcpy(&flogi_req, &fip_flogi_tmpl, fr_len);
> + memcpy(flogi_req.eth.smac, iport->hwmac, ETH_ALEN);
> + if (iport->usefip)
> + memcpy(flogi_req.eth.dmac, iport->selected_fcf.fcf_mac, ETH_ALEN);
> +
> + flogi_req.flogi_desc.flogi.nport_name = htonll(iport->wwpn);
> + flogi_req.flogi_desc.flogi.node_name = htonll(iport->wwnn);
> +
> + fnic_send_fip_frame(iport, &flogi_req, fr_len);
> + iport->fip.flogi_retry++;
> +
> + iport->fip.state = FDLS_FIP_FLOGI_STARTED;
> + flogi_tov = jiffies + msecs_to_jiffies(fnic->config.flogi_timeout);
> + mod_timer(&fnic->retry_fip_timer, round_jiffies(flogi_tov));
> +}
> +
> +/**
> + * fnic_fcoe_process_flogi_resp
> + *
> + * Processes FLOGI response from FCF.
> + * If successful saves assigned fc_id and MAC, programs firmware
> + * and starts fdls discovery.
> + * Else restarts vlan discovery.
> + *
> + * @param fnic driver instance
> + * @param fiph received frame
> + */
> +
> +void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
> + struct fip_header_s *fiph)
> +{
> + struct fnic_iport_s *iport = &fnic->iport;
> + struct fip_flogi_rsp_s *flogi_rsp = (struct fip_flogi_rsp_s *) fiph;
> + int desc_len;
> + uint32_t s_id;
> +
> + struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p FIP FLOGI rsp\n", fnic);
> + desc_len = ntohs(flogi_rsp->fip.desc_len);
> + if (desc_len != 38) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Invalid Descriptor List len (%x). Dropping frame\n",
> + desc_len);
> + return;
> + }
> +
> + if (!
> + ((flogi_rsp->rsp_desc.type == 7)
> + && (flogi_rsp->rsp_desc.len == 36))
> + || !((flogi_rsp->mac_desc.type == 2)
> + && (flogi_rsp->mac_desc.len == 2))) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping frame invalid type and len mix\n");
> + return;
> + }
> +
> + s_id = ntoh24(flogi_rsp->rsp_desc.els.fchdr.sid);
> + if ((flogi_rsp->rsp_desc.els.fchdr.f_ctl != 0x98)
> + || (flogi_rsp->rsp_desc.els.fchdr.r_ctl != 0x23)
> + || (s_id != 0xFFFFFE)
> + || (flogi_rsp->rsp_desc.els.fchdr.ox_id != FNIC_FLOGI_OXID)
> + || (flogi_rsp->rsp_desc.els.fchdr.type != 0x01)) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping invalid frame: s_id %x F %x R %x t %x OX_ID %x\n",
> + s_id,
> + flogi_rsp->rsp_desc.els.fchdr.f_ctl,
> + flogi_rsp->rsp_desc.els.fchdr.r_ctl,
> + flogi_rsp->rsp_desc.els.fchdr.type,
> + flogi_rsp->rsp_desc.els.fchdr.ox_id);
> + return;
> + }
> +
> + if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p rsp for pending FLOGI\n", fnic);
> +
> + del_timer_sync(&fnic->retry_fip_timer);
> +
> + if ((ntohs(flogi_rsp->fip.desc_len) == 38)
> + && (flogi_rsp->rsp_desc.els.command == FC_LS_ACC)) {
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p FLOGI success\n", fnic);
> + memcpy(iport->fpma, flogi_rsp->mac_desc.mac, ETH_ALEN);
> + iport->fcid = ntoh24(flogi_rsp->rsp_desc.els.fchdr.did);
> +
> + iport->r_a_tov =
> + ntohl(flogi_rsp->rsp_desc.els.u.csp_flogi.r_a_tov);
> + iport->e_d_tov =
> + ntohl(flogi_rsp->rsp_desc.els.u.csp_flogi.e_d_tov);
> + memcpy(fnic->iport.fcfmac, iport->selected_fcf.fcf_mac,
> + ETH_ALEN);
> + vnic_dev_add_addr(fnic->vdev, flogi_rsp->mac_desc.mac);
> +
> + if (fnic_fdls_register_portid(iport, iport->fcid, NULL) != 0) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p flogi registration failed\n",
> + fnic);
> + return;
> + }
> +
> + iport->fip.state = FDLS_FIP_FLOGI_COMPLETE;
> + iport->state = FNIC_IPORT_STATE_FABRIC_DISC;
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "iport->state:%d\n", iport->state);
> + if (!((iport->selected_fcf.ka_disabled)
> + || (iport->selected_fcf.fka_adv_period == 0))) {
> + u64 tov;
> +
> + tov = jiffies
> + + msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
> + mod_timer(&fnic->enode_ka_timer, round_jiffies(tov));
> +
> + tov = jiffies + msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
> + mod_timer(&fnic->vn_ka_timer, round_jiffies(tov));
> +
> + }
> + } else {
> + /*
> + * If there's FLOGI rejects - clear all
> + * fcf's & restart from scratch
> + */
> + atomic64_inc(&fnic_stats->vlan_stats.flogi_rejects);
> + /* start FCoE VLAN discovery */
> + fnic_fcoe_send_vlan_req(fnic);
> +
> + iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
> + }
> + }
> +}
> +
> +/**
> + * fnic_common_fip_cleanup
> + *
> + * Cleans up FCF info and timers in case of link down/CVL
> + *
> + * @param fnic driver instance
> + */
> +
> +void fnic_common_fip_cleanup(struct fnic *fnic)
> +{
> +
> + struct fnic_iport_s *iport = &fnic->iport;
> +
> + if (!iport->usefip)
> + return;
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p fip cleanup\n", fnic);
> +
> + iport->fip.state = FDLS_FIP_INIT;
> +
> + del_timer_sync(&fnic->retry_fip_timer);
> + del_timer_sync(&fnic->fcs_ka_timer);
> + del_timer_sync(&fnic->enode_ka_timer);
> + del_timer_sync(&fnic->vn_ka_timer);
> +
> + if (!is_zero_ether_addr(iport->fpma))
> + vnic_dev_del_addr(fnic->vdev, iport->fpma);
> +
> + memset(iport->fpma, 0, ETH_ALEN);
> + iport->fcid = 0;
> + iport->r_a_tov = 0;
> + iport->e_d_tov = 0;
> + memset(fnic->iport.fcfmac, 0, ETH_ALEN);
> + memset(iport->selected_fcf.fcf_mac, 0, ETH_ALEN);
> + iport->selected_fcf.fcf_priority = 0;
> + iport->selected_fcf.fka_adv_period = 0;
> + iport->selected_fcf.ka_disabled = 0;
> +
> + fnic_fcoe_reset_vlans(fnic);
> +}
> +
> +/**
> + * fnic_fcoe_process_cvl
> + *
> + * Processes Clear Virtual Link from FCF
> + * Verifies that cvl is received from our current FCF for our assigned MAC
> + * Cleans up and restarts the vlan discovery
> + *
> + * @param fnic driver instance
> + * @param fiph received frame
> + */
> +
> +void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header_s *fiph)
> +{
> + struct fnic_iport_s *iport = &fnic->iport;
> + struct fip_cvl_s *cvl_msg = (struct fip_cvl_s *) fiph;
> + int i;
> + int found = FALSE;
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p clear virtual link handler\n", fnic);
> +
> + if (!
> + ((cvl_msg->fcf_mac_desc.type == 2)
> + && (cvl_msg->fcf_mac_desc.len == 2))
> +|| !((cvl_msg->name_desc.type == 4) && (cvl_msg->name_desc.len == 3))) {
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "invalid mix: ft %x fl %x ndt %x ndl %x",
> + cvl_msg->fcf_mac_desc.type, cvl_msg->fcf_mac_desc.len,
> + cvl_msg->name_desc.type, cvl_msg->name_desc.len);
> + }
> +
> + if (memcmp
> + (iport->selected_fcf.fcf_mac, cvl_msg->fcf_mac_desc.mac, ETH_ALEN)
> + == 0) {

you could do:

if (memcmp
> + (iport->selected_fcf.fcf_mac, cvl_msg->fcf_mac_desc.mac, ETH_ALEN))
return;

and then have the rest, below, to reduce indentation

> + for (i = 0; i < ((ntohs(fiph->desc_len) / 5) - 1); i++) {
> + if (!((cvl_msg->vn_ports_desc[i].type == 11)
> + && (cvl_msg->vn_ports_desc[i].len == 5))) {
> +
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Invalid type and len mix type: %d len: %d\n",
> + cvl_msg->vn_ports_desc[i].type,
> + cvl_msg->vn_ports_desc[i].len);
> + }
> + if (memcmp(iport->fpma, cvl_msg->vn_ports_desc[i].vn_port_mac,
> + ETH_ALEN) == 0) {
> + found = TRUE;
> + break;
> + }
> + }
> + if (!found)
> + return;
> + fnic_common_fip_cleanup(fnic);
> +
> + fnic_fcoe_send_vlan_req(fnic);
> + }
> +}
> +
> +/**
> + * fdls_fip_recv_frame
> + *
> + * Demultiplexer for FIP frames
> + *
> + * @param fnic driver instance
> + * @param frame received ethernet frame
> + * @return Frame processed by FIP
> + */
> +
> +int fdls_fip_recv_frame(struct fnic *fnic, void *frame)
> +{
> + struct eth_hdr_s *eth = (struct eth_hdr_s *) frame;
> + struct fip_header_s *fiph;
> + u16 protocol;
> + u8 sub;
> +
> + if (eth->eth_type == ntohs(FIP_ETH_TYPE)) {
> + fiph = (struct fip_header_s *) (eth + 1);
> + protocol = ntohs(fiph->protocol);
> + sub = ntohs(fiph->subcode);
> +
> + if (protocol == FIP_DISCOVERY && sub == FIP_SUBCODE_RESP)
> + fnic_fcoe_fip_discovery_resp(fnic, fiph);
> + else if (protocol == FIP_VLAN_DISC && sub == FIP_SUBCODE_RESP)
> + fnic_fcoe_process_vlan_resp(fnic, fiph);
> + else if (protocol == FIP_KA_CVL && sub == FIP_SUBCODE_RESP)
> + fnic_fcoe_process_cvl(fnic, fiph);
> + else if (protocol == FIP_FLOGI && sub == FIP_SUBCODE_RESP)
> + fnic_fcoe_process_flogi_resp(fnic, fiph);
> +
> + return 1;
> + }
> + return 0;

what does 1 and 0 mean here?

> +}
> +
> +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->lport->host, fnic->fnic_num,
> + "FIP timeout\n");
> +
> + if (iport->fip.state == FDLS_FIP_VLAN_DISCOVERY_STARTED) {
> + fnic_vlan_discovery_timeout(fnic);
> + } 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->lport->host, fnic->fnic_num,
> + "FCF Discovery timeout\n");
> + if (memcmp(iport->selected_fcf.fcf_mac, zmac, ETH_ALEN) != 0) {
> +
> + if (iport->flags & FNIC_FIRST_LINK_UP)
> + iport->flags &= ~FNIC_FIRST_LINK_UP;
> +
> + fnic_fcoe_start_flogi(fnic);
> + if (!((iport->selected_fcf.ka_disabled)
> + || (iport->selected_fcf.fka_adv_period == 0))) {
> + u64 fcf_tov;
> +
> + fcf_tov = jiffies
> + + 3
> + * msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
> + mod_timer(&fnic->fcs_ka_timer, round_jiffies(fcf_tov));
> + }
> + } else {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FCF Discovery timeout\n");
> + fnic_vlan_discovery_timeout(fnic);
> + }
> + } else if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
> + FNIC_FIP_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "FLOGI timeout\n");
> + if (iport->fip.flogi_retry < fnic->config.flogi_retries)
> + fnic_fcoe_start_flogi(fnic);
> + else
> + fnic_vlan_discovery_timeout(fnic);
> + }
> +}
> +
> +/**
> + * fnic_handle_fip_timer
> + *
> + * Timeout handler for FIP discover phase.
> + * Based on the current state, starts next phase or restarts discovery
> + *
> + * @param data Opaque pointer to fnic structure
> + */
> +
> +void fnic_handle_fip_timer(struct timer_list *t)
> +{
> + struct fnic *fnic = from_timer(fnic, t, retry_fip_timer);
> +
> + INIT_WORK(&fnic->fip_timer_work, fnic_work_on_fip_timer);

do you really need to init every time?

> + queue_work(fnic_fip_queue, &fnic->fip_timer_work);
> +}
> +
> +/**
> + * fnic_handle_enode_ka_timer
> + *
> + * FIP node keep alive.
> + *
> + * @param data Opaque pointer to fnic struct
> + */
> +void fnic_handle_enode_ka_timer(struct timer_list *t)
> +{
> + struct fnic *fnic = from_timer(fnic, t, enode_ka_timer);
> +
> + struct fnic_iport_s *iport = &fnic->iport;
> + int fr_len;
> + struct fip_enode_ka_s enode_ka;
> + u64 enode_ka_tov;
> +
> + if (iport->fip.state != FDLS_FIP_FLOGI_COMPLETE)
> + return;
> +
> + if ((iport->selected_fcf.ka_disabled)
> + || (iport->selected_fcf.fka_adv_period == 0)) {
> + return;
> + }
> +
> + fr_len = sizeof(struct fip_enode_ka_s);
> +
> + memcpy(&enode_ka, &fip_enode_ka_tmpl, fr_len);
> + memcpy(enode_ka.eth.smac, iport->hwmac, ETH_ALEN);
> + memcpy(enode_ka.eth.dmac, iport->selected_fcf.fcf_mac, ETH_ALEN);
> + memcpy(enode_ka.mac_desc.mac, iport->hwmac, ETH_ALEN);
> +
> + fnic_send_fip_frame(iport, &enode_ka, fr_len);
> + enode_ka_tov = jiffies
> + + msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
> + mod_timer(&fnic->enode_ka_timer, round_jiffies(enode_ka_tov));
> +}
> +
> +/**
> + * fnic_handle_vn_ka_timer
> + *
> + * FIP virtual port keep alive.
> + *
> + * @param data Opaque pointer to fnic structure
> + */
> +
> +void fnic_handle_vn_ka_timer(struct timer_list *t)
> +{
> + struct fnic *fnic = from_timer(fnic, t, vn_ka_timer);
> +
> + struct fnic_iport_s *iport = &fnic->iport;
> + int fr_len;
> + struct fip_vn_port_ka_s vn_port_ka;
> + u64 vn_ka_tov;
> + uint8_t fcid[3];
> +
> + if (iport->fip.state != FDLS_FIP_FLOGI_COMPLETE)
> + return;
> +
> + if ((iport->selected_fcf.ka_disabled)
> + || (iport->selected_fcf.fka_adv_period == 0)) {
> + return;
> + }

exact same code is duplicated from fnic_handle_enode_ka_timer(), above

> +
> + fr_len = sizeof(struct fip_vn_port_ka_s);
> +
> + memcpy(&vn_port_ka, &fip_vn_port_ka_tmpl, fr_len);
> + memcpy(vn_port_ka.eth.smac, iport->fpma, ETH_ALEN);
> + memcpy(vn_port_ka.eth.dmac, iport->selected_fcf.fcf_mac, ETH_ALEN);
> + memcpy(vn_port_ka.mac_desc.mac, iport->hwmac, ETH_ALEN);
> + memcpy(vn_port_ka.vn_port_desc.vn_port_mac, iport->fpma, ETH_ALEN);
> + hton24(fcid, iport->fcid);
> + memcpy(vn_port_ka.vn_port_desc.vn_port_id, fcid, 3);
> + vn_port_ka.vn_port_desc.vn_port_name = htonll(iport->wwpn);
> +
> + fnic_send_fip_frame(iport, &vn_port_ka, fr_len);
> + vn_ka_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
> + mod_timer(&fnic->vn_ka_timer, round_jiffies(vn_ka_tov));
> +}
> +
> +/**
> + * fnic_vlan_discovery_timeout
> + *
> + * End of VLAN discovery or FCF discovery time window
> + * Start the FCF discovery if VLAN was never used
> + * Retry in case of FCF not responding or move to next VLAN
> + *
> + * @param fnic driver instance
> + */
> +
> +void fnic_vlan_discovery_timeout(struct fnic *fnic)
> +{
> + struct fcoe_vlan *vlan;
> + struct fnic_iport_s *iport = &fnic->iport;
> + struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&fnic->fnic_lock, flags);
> + if (fnic->stop_rx_link_events) {

I assume that you are relying in the in-built memory barriers in
spin_lock_irqsave() and spin_unlock_irqrestore()...

> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + return;
> + }
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> +
> + if (!iport->usefip)
> + return;
> +
> + spin_lock_irqsave(&fnic->vlans_lock, flags);

it's hardly worth dropping the lock before the !iport->usefip check.

> + if (list_empty(&fnic->vlan_list)) {
> + /* no vlans available, try again */
> + spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> + fnic_fcoe_send_vlan_req(fnic);
> + return;
> + }
> +
> + vlan = list_first_entry(&fnic->vlan_list, struct fcoe_vlan, list);
> +
> + if (vlan->state == FIP_VLAN_SENT) {
> + if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
> + /*
> + * no response on this vlan, remove from the list.
> + * Try the next vlan
> + */
> + list_del(&vlan->list);
> + kfree(vlan);
> + vlan = NULL;
> + if (list_empty(&fnic->vlan_list)) {
> + /* we exhausted all vlans, restart vlan disc */
> + spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> + fnic_fcoe_send_vlan_req(fnic);
> + return;
> + }
> + /* check the next vlan */
> + vlan =
> + list_first_entry(&fnic->vlan_list, struct fcoe_vlan, list);
> +
> + fnic->set_vlan(fnic, vlan->vid);
> + vlan->state = FIP_VLAN_SENT; /* sent now */
> +
> + }
> + atomic64_inc(&fnic_stats->vlan_stats.sol_expiry_count);
> +
> + } else {
> + fnic->set_vlan(fnic, vlan->vid);
> + vlan->state = FIP_VLAN_SENT; /* sent now */
> + }
> + vlan->sol_count++;
> + spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> + fnic_fcoe_start_fcf_discovery(fnic);
> +}
> +
> +/**
> + * fnic_work_on_fcs_ka_timer - finish handling fcs_ka_timer in process context
> + * We need to finish this timer in a process context so that we do
> + * not hand in fip_common_cleanup. Here we clean up, bring the link down
> + * and restart all FIP discovery.
> + *
> + * @work - the work queue that we will be servicing
> + */
> +
> +void fnic_work_on_fcs_ka_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->lport->host, fnic->fnic_num,
> + "fnic 0x%p fcs ka timeout\n", fnic);
> +
> + fnic_common_fip_cleanup(fnic);
> + spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
> + iport->state = FNIC_IPORT_STATE_FIP;
> + spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
> +
> + fnic_fcoe_send_vlan_req(fnic);
> +}
> +
> +/**
> + * fnic_handle_fcs_ka_timer
> + *
> + * No keep alives received from FCF. Clean up, bring the link down
> + * and restart all the FIP discovery.
> + *
> + * @param data Opaque pointer to fnic structure
> + */
> +void fnic_handle_fcs_ka_timer(struct timer_list *t)
> +{
> + struct fnic *fnic = from_timer(fnic, t, fcs_ka_timer);
> +
> + INIT_WORK(&fnic->fip_timer_work, fnic_work_on_fcs_ka_timer);
> + queue_work(fnic_fip_queue, &fnic->fip_timer_work);
> +}
> diff --git a/drivers/scsi/fnic/fip.h b/drivers/scsi/fnic/fip.h
> new file mode 100644
> index 000000000000..33562c5a41e0
> --- /dev/null
> +++ b/drivers/scsi/fnic/fip.h
> @@ -0,0 +1,341 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright 2008 Cisco Systems, Inc. All rights reserved.
> + * Copyright 2007 Nuova Systems, Inc. All rights reserved.

Is this a driver for HW older than 15 years?

> + */
> +#ifndef _FIP_H_
> +#define _FIP_H_
> +
> +#include "fdls_fc.h"
> +
> +#define FCOE_ALL_FCFS_MAC {0x01, 0x10, 0x18, 0x01, 0x00, 0x02}
> +#define FIP_ETH_TYPE 0x8914
> +
> +#define FIP_ETH_TYPE_LE 0x1489
> +#define FCOE_MAX_SIZE_LE 0x2E08
> +
> +#define WWNN_LEN 8
> +
> +#define FCOE_CTLR_FIPVLAN_TOV (3*1000)
> +#define FCOE_CTLR_FCS_TOV (3*1000)
> +#define FCOE_CTLR_VN_KA_TOV (90*1000)
> +#define FCOE_CTLR_MAX_SOL (5*1000)
> +
> +#define FIP_SUBCODE_REQ 1
> +#define FIP_SUBCODE_RESP 2
> +
> +#define FIP_FLAG_S 0x2
> +#define FIP_FLAG_A 0x4
> +
> +/*
> + * VLAN entry.
> + */
> +struct fcoe_vlan {
> + struct list_head list;
> + uint16_t vid; /* vlan ID */
> + uint16_t sol_count; /* no. of sols sent */
> + uint16_t state; /* state */
> +};
> +
> +enum fdls_vlan_state_e {
> + FIP_VLAN_AVAIL,
> + FIP_VLAN_SENT
> +};
> +
> +enum fdls_fip_state_e {
> + FDLS_FIP_INIT,
> + FDLS_FIP_VLAN_DISCOVERY_STARTED,
> + FDLS_FIP_FCF_DISCOVERY_STARTED,
> + FDLS_FIP_FLOGI_STARTED,
> + FDLS_FIP_FLOGI_COMPLETE,
> +};
> +
> +enum fip_protocol_code_e {
> + FIP_DISCOVERY = 1,
> + FIP_FLOGI,
> + FIP_KA_CVL,
> + FIP_VLAN_DISC
> +};
> +
> +struct eth_hdr_s {
> + uint8_t dmac[6];
> + uint8_t smac[6];
> + uint16_t eth_type;
> +};
> +
> +struct fip_header_s {
> + uint32_t ver:16;
> +
> + uint32_t protocol:16;
> + uint32_t subcode:16;
> +
> + uint32_t desc_len:16;
> + uint32_t flags:16;
> +} __packed;


Do you really want to use __packed?

I don't even get what you are trying to do here in terms of formatting
of these structures and their members.

> +
> +enum fip_desc_type_e {
> + FIP_TYPE_PRIORITY = 1,
> + FIP_TYPE_MAC,
> + FIP_TYPE_FCMAP,
> + FIP_TYPE_NAME_ID,
> + FIP_TYPE_FABRIC,
> + FIP_TYPE_MAX_FCOE,
> + FIP_TYPE_FLOGI,
> + FIP_TYPE_FDISC,
> + FIP_TYPE_LOGO,
> + FIP_TYPE_ELP,
> + FIP_TYPE_VX_PORT,
> + FIP_TYPE_FKA_ADV,
> + FIP_TYPE_VENDOR_ID,
> + FIP_TYPE_VLAN
> +};
> +
> +struct fip_mac_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint8_t mac[6];
> +} __packed;
> +
> +struct fip_vlan_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint16_t vlan;
> +} __packed;
> +
> +struct fip_vlan_req_s {
> + struct eth_hdr_s eth;
> + struct fip_header_s fip;
> + struct fip_mac_desc_s mac_desc;
> +} __packed;
> +
> + /*
> + * Variables:
> + * eth.smac, mac_desc.mac
> + */
> +struct fip_vlan_req_s fip_vlan_req_tmpl = {

static const?

> + .eth = {.dmac = FCOE_ALL_FCFS_MAC,
> + .eth_type = FIP_ETH_TYPE_LE},
> + .fip = {.ver = 0x10,
> + .protocol = FIP_VLAN_DISC << 8,
> + .subcode = FIP_SUBCODE_REQ << 8,
> + .desc_len = 2 << 8},
> + .mac_desc = {.type = FIP_TYPE_MAC, .len = 2}
> +};
> +
> +struct fip_vlan_notif_s {
> + struct fip_header_s fip;
> + struct fip_vlan_desc_s vlans_desc[];
> +} __packed;
> +
> +struct fip_vn_port_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint8_t vn_port_mac[6];
> + uint8_t rsvd[1];
> + uint8_t vn_port_id[3];
> + uint64_t vn_port_name;
> +} __packed;
> +
> +struct fip_vn_port_ka_s {
> + struct eth_hdr_s eth;
> + struct fip_header_s fip;
> + struct fip_mac_desc_s mac_desc;
> + struct fip_vn_port_desc_s vn_port_desc;
> +} __packed;
> +
> +/*
> + * Variables:
> + * fcf_mac, eth.smac, mac_desc.enode_mac
> + * vn_port_desc:mac, id, port_name
> + */
> +struct fip_vn_port_ka_s fip_vn_port_ka_tmpl = {
> + .eth = {
> + .eth_type = FIP_ETH_TYPE_LE},
> + .fip = {
> + .ver = 0x10,
> + .protocol = FIP_KA_CVL << 8,
> + .subcode = FIP_SUBCODE_REQ << 8,
> + .desc_len = 7 << 8},
> + .mac_desc = {.type = FIP_TYPE_MAC, .len = 2},
> + .vn_port_desc = {.type = FIP_TYPE_VX_PORT, .len = 5}
> +};
> +
> +struct fip_enode_ka_s {
> + struct eth_hdr_s eth;
> + struct fip_header_s fip;
> + struct fip_mac_desc_s mac_desc;
> +} __packed;
> +
> +/*
> + * Variables:
> + * fcf_mac, eth.smac, mac_desc.enode_mac
> + */
> +struct fip_enode_ka_s fip_enode_ka_tmpl = {
> + .eth = {
> + .eth_type = FIP_ETH_TYPE_LE},
> + .fip = {
> + .ver = 0x10,
> + .protocol = FIP_KA_CVL << 8,
> + .subcode = FIP_SUBCODE_REQ << 8,
> + .desc_len = 2 << 8},
> + .mac_desc = {.type = FIP_TYPE_MAC, .len = 2}
> +};
> +
> +struct fip_name_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint8_t rsvd[2];
> + uint64_t name;
> +} __packed;
> +
> +struct fip_cvl_s {
> + struct fip_header_s fip;
> + struct fip_mac_desc_s fcf_mac_desc;
> + struct fip_name_desc_s name_desc;
> + struct fip_vn_port_desc_s vn_ports_desc[];
> +} __packed;
> +
> +struct fip_flogi_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint16_t rsvd;
> + struct fc_els_s flogi;
> +} __packed;
> +
> +struct fip_flogi_rsp_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint16_t rsvd;
> + struct fc_els_s els;
> +} __packed;
> +
> +struct fip_flogi_s {
> + struct eth_hdr_s eth;
> + struct fip_header_s fip;
> + struct fip_flogi_desc_s flogi_desc;
> + struct fip_mac_desc_s mac_desc;
> +} __packed;
> +
> +struct fip_flogi_rsp_s {
> + struct fip_header_s fip;
> + struct fip_flogi_rsp_desc_s rsp_desc;
> + struct fip_mac_desc_s mac_desc;
> +} __packed;
> +
> +/*
> + * Variables:
> + * fcf_mac, eth.smac, mac_desc.enode_mac
> + */
> +struct fip_flogi_s fip_flogi_tmpl = {
> + .eth = {
> + .eth_type = FIP_ETH_TYPE_LE},
> + .fip = {
> + .ver = 0x10,
> + .protocol = FIP_FLOGI << 8,
> + .subcode = FIP_SUBCODE_REQ << 8,
> + .desc_len = 38 << 8,
> + .flags = 0x80},
> + .flogi_desc = {
> + .type = FIP_TYPE_FLOGI, .len = 36,
> + .flogi = {
> + .fchdr = {
> + .r_ctl = 0x22,
> + .did = {0xFF, 0xFF, 0xFE},
> + .type = 0x01,
> + .f_ctl = FNIC_ELS_REQ_FCTL,
> + .ox_id = FNIC_FLOGI_OXID,
> + .rx_id = 0xFFFF},
> + .command = FC_ELS_FLOGI_REQ,
> + .u.csp_flogi = {
> + .fc_ph_ver = FNIC_FC_PH_VER,
> + .b2b_credits =
> + FNIC_FC_B2B_CREDIT,
> + .b2b_rdf_size =
> + FNIC_FC_B2B_RDF_SZ},
> + .spc3 = {0x88, 0x00}
> + }
> + },
> + .mac_desc = {.type = FIP_TYPE_MAC, .len = 2}
> +};
> +
> +struct fip_fcoe_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint16_t max_fcoe_size;
> +} __packed;
> +
> +struct fip_discovery_s {
> + struct eth_hdr_s eth;
> + struct fip_header_s fip;
> + struct fip_mac_desc_s mac_desc;
> + struct fip_name_desc_s name_desc;
> + struct fip_fcoe_desc_s fcoe_desc;
> +} __packed;
> +
> +/*
> + * Variables:
> + * eth.smac, mac_desc.enode_mac, node_name
> + */
> +struct fip_discovery_s fip_discovery_tmpl = {
> + .eth = {.dmac = FCOE_ALL_FCFS_MAC,
> + .eth_type = FIP_ETH_TYPE_LE},
> + .fip = {
> + .ver = 0x10, .protocol = FIP_DISCOVERY << 8,
> + .subcode = FIP_SUBCODE_REQ << 8, .desc_len = 6 << 8,
> + .flags = 0x80},
> + .mac_desc = {.type = FIP_TYPE_MAC, .len = 2},
> + .name_desc = {.type = FIP_TYPE_NAME_ID, .len = 3},
> + .fcoe_desc = {
> + .type = FIP_TYPE_MAX_FCOE, .len = 1,
> + .max_fcoe_size = FCOE_MAX_SIZE_LE}
> +};
> +
> +struct fip_prio_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint8_t rsvd;
> + uint8_t priority;
> +} __packed;
> +
> +struct fip_fabric_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint16_t vf_id;
> + uint8_t rsvd;
> + uint8_t fc_map[3];
> + uint64_t fabric_name;
> +} __packed;
> +
> +struct fip_fka_adv_desc_s {
> + uint8_t type;
> + uint8_t len;
> + uint8_t rsvd;
> + uint8_t rsvd_D;
> + uint32_t fka_adv;
> +} __packed;
> +
> +struct fip_disc_adv_s {
> + struct fip_header_s fip;
> + struct fip_prio_desc_s prio_desc;
> + struct fip_mac_desc_s mac_desc;
> + struct fip_name_desc_s name_desc;
> + struct fip_fabric_desc_s fabric_desc;
> + struct fip_fka_adv_desc_s fka_adv_desc;
> +} __packed;
> +
> +void fnic_fcoe_process_vlan_resp(struct fnic *fnic,
> + struct fip_header_s *fiph);
> +void fnic_fcoe_fip_discovery_resp(struct fnic *fnic,
> + struct fip_header_s *fiph);
> +void fnic_fcoe_process_flogi_resp(struct fnic *fnic,
> + struct fip_header_s *fiph);
> +void fnic_work_on_fip_timer(struct work_struct *work);
> +void fnic_work_on_fcs_ka_timer(struct work_struct *work);
> +void fnic_fcoe_send_vlan_req(struct fnic *fnic);
> +void fnic_fcoe_start_fcf_discovery(struct fnic *fnic);
> +void fnic_fcoe_start_flogi(struct fnic *fnic);
> +void fnic_fcoe_process_cvl(struct fnic *fnic,
> + struct fip_header_s *fiph);
> +void fnic_vlan_discovery_timeout(struct fnic *fnic);
> +
> +#endif /* _FIP_H_ */
> diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
> index 7d7009197dbc..0c7926627663 100644
> --- a/drivers/scsi/fnic/fnic.h
> +++ b/drivers/scsi/fnic/fnic.h
> @@ -230,6 +230,12 @@ do { \
> "fnic<%d>: %s: %d: " fmt, fnic_num,\
> __func__, __LINE__, ##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_SCSI_DBG(kern_level, host, fnic_num, fmt, args...) \
> FNIC_CHECK_LOGGING(FNIC_SCSI_LOGGING, \
> shost_printk(kern_level, host, \
> @@ -406,13 +412,15 @@ struct fnic {
> /*** FIP related data members -- start ***/
> void (*set_vlan)(struct fnic *, u16 vlan);
> struct work_struct fip_frame_work;
> - struct sk_buff_head fip_frame_queue;
> + struct work_struct fip_timer_work;
> + struct list_head fip_frame_queue;
> struct timer_list fip_timer;
> - struct list_head vlans;
> spinlock_t vlans_lock;
> -
> - struct work_struct event_work;
> - struct list_head evlist;
> + struct timer_list retry_fip_timer;
> + struct timer_list fcs_ka_timer;
> + struct timer_list enode_ka_timer;
> + struct timer_list vn_ka_timer;
> + struct list_head vlan_list;
> /*** FIP related data members -- end ***/
>
> /* copy work queue cache line section */
> @@ -462,9 +470,6 @@ int fnic_rq_cmpl_handler(struct fnic *fnic, int);
> int fnic_alloc_rq_frame(struct vnic_rq *rq);
> void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
> void fnic_flush_tx(struct work_struct *work);
> -void fnic_eth_send(struct fcoe_ctlr *, struct sk_buff *skb);
> -void fnic_set_port_id(struct fc_lport *, u32, struct fc_frame *);
> -void fnic_update_mac(struct fc_lport *, u8 *new);
> void fnic_update_mac_locked(struct fnic *, u8 *new);
>
> int fnic_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
> @@ -493,7 +498,7 @@ int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);
> void fnic_handle_fip_frame(struct work_struct *work);
> void fnic_handle_fip_event(struct fnic *fnic);
> void fnic_fcoe_reset_vlans(struct fnic *fnic);
> -void fnic_fcoe_evlist_free(struct fnic *fnic);
> +extern void fnic_handle_fip_timer(struct timer_list *t);
>
> static inline int
> fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
> diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
> index 90d0c4c8920c..8a7c471d3ff5 100644
> --- a/drivers/scsi/fnic/fnic_fcs.c
> +++ b/drivers/scsi/fnic/fnic_fcs.c
> @@ -25,16 +25,9 @@
> #include "cq_enet_desc.h"
> #include "cq_exch_desc.h"
>
> -static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
> -struct workqueue_struct *fnic_fip_queue;
> +extern struct workqueue_struct *fnic_fip_queue;
> struct workqueue_struct *fnic_event_queue;
>
> -static void fnic_set_eth_mode(struct fnic *);
> -static void fnic_fcoe_start_fcf_disc(struct fnic *fnic);
> -static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *);
> -static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag);
> -static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb);
> -
> /* Frame initialization */
> /*
> * Variables:
> @@ -252,11 +245,6 @@ void fnic_handle_link(struct work_struct *work)
> fnic->lport->host->host_no, FNIC_FC_LE,
> "Link Status: UP_DOWN",
> strlen("Link Status: UP_DOWN"));
> - if (fnic->config.flags & VFCF_FIP_CAPABLE) {
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "deleting fip-timer during link-down\n");
> - del_timer_sync(&fnic->fip_timer);
> - }
> fcoe_ctlr_link_down(&fnic->ctlr);
> }
>
> @@ -299,496 +287,73 @@ void fnic_handle_frame(struct work_struct *work)
> }
> }
>
> -void fnic_fcoe_evlist_free(struct fnic *fnic)
> -{
> - struct fnic_event *fevt = NULL;
> - struct fnic_event *next = NULL;
> - unsigned long flags;
> -
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - if (list_empty(&fnic->evlist)) {
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - return;
> - }
> -
> - list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
> - list_del(&fevt->list);
> - kfree(fevt);
> - }
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> -}
> -
> -void fnic_handle_event(struct work_struct *work)
> +void fnic_handle_fip_frame(struct work_struct *work)
> {
> - struct fnic *fnic = container_of(work, struct fnic, event_work);
> - struct fnic_event *fevt = NULL;
> - struct fnic_event *next = NULL;
> - unsigned long flags;
> + struct fnic_stats *fnic_stats;
> + struct fnic_frame_list *cur_frame, *next;
> + struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);
>
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - if (list_empty(&fnic->evlist)) {
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - return;
> - }
> + fnic_stats = &fnic->fnic_stats;
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Processing FIP frame\n");
>
> - list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
> + spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
> + list_for_each_entry_safe(cur_frame, next, &fnic->fip_frame_queue,
> + links) {
> if (fnic->stop_rx_link_events) {
> - list_del(&fevt->list);
> - kfree(fevt);
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + list_del(&cur_frame->links);
> + spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
> + kfree(cur_frame->fp);
> + kfree(cur_frame);
> return;
> }
> +
> /*
> * If we're in a transitional state, just re-queue and return.
> * The queue will be serviced when we get to a stable state.
> */
> if (fnic->state != FNIC_IN_FC_MODE &&
> - fnic->state != FNIC_IN_ETH_MODE) {
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> + fnic->state != FNIC_IN_ETH_MODE) {
> + spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
> return;
> }
>
> - list_del(&fevt->list);
> - switch (fevt->event) {
> - case FNIC_EVT_START_VLAN_DISC:
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - fnic_fcoe_send_vlan_req(fnic);
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - break;
> - case FNIC_EVT_START_FCF_DISC:
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "Start FCF Discovery\n");
> - fnic_fcoe_start_fcf_disc(fnic);
> - break;
> - default:
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "Unknown event 0x%x\n", fevt->event);
> - break;
> - }
> - kfree(fevt);
> - }
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> -}
> -
> -/**
> - * is_fnic_fip_flogi_reject() - Check if the Received FIP FLOGI frame is rejected
> - * @fip: The FCoE controller that received the frame
> - * @skb: The received FIP frame
> - *
> - * Returns non-zero if the frame is rejected with unsupported cmd with
> - * insufficient resource els explanation.
> - */
> -static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip,
> - struct sk_buff *skb)
> -{
> - struct fc_lport *lport = fip->lp;
> - struct fip_header *fiph;
> - struct fc_frame_header *fh = NULL;
> - struct fip_desc *desc;
> - struct fip_encaps *els;
> - u16 op;
> - u8 els_op;
> - u8 sub;
> -
> - size_t rlen;
> - size_t dlen = 0;
> -
> - if (skb_linearize(skb))
> - return 0;
> -
> - if (skb->len < sizeof(*fiph))
> - return 0;
> -
> - fiph = (struct fip_header *)skb->data;
> - op = ntohs(fiph->fip_op);
> - sub = fiph->fip_subcode;
> -
> - if (op != FIP_OP_LS)
> - return 0;
> -
> - if (sub != FIP_SC_REP)
> - return 0;
> -
> - rlen = ntohs(fiph->fip_dl_len) * 4;
> - if (rlen + sizeof(*fiph) > skb->len)
> - return 0;
> -
> - desc = (struct fip_desc *)(fiph + 1);
> - dlen = desc->fip_dlen * FIP_BPW;
> -
> - if (desc->fip_dtype == FIP_DT_FLOGI) {
> -
> - if (dlen < sizeof(*els) + sizeof(*fh) + 1)
> - return 0;
> -
> - els = (struct fip_encaps *)desc;
> - fh = (struct fc_frame_header *)(els + 1);
> -
> - if (!fh)
> - return 0;
> -
> - /*
> - * ELS command code, reason and explanation should be = Reject,
> - * unsupported command and insufficient resource
> - */
> - els_op = *(u8 *)(fh + 1);
> - if (els_op == ELS_LS_RJT) {
> - shost_printk(KERN_INFO, lport->host,
> - "Flogi Request Rejected by Switch\n");
> - return 1;
> - }
> - shost_printk(KERN_INFO, lport->host,
> - "Flogi Request Accepted by Switch\n");
> - }
> - return 0;
> -}
> -
> -void fnic_fcoe_send_vlan_req(struct fnic *fnic)

why is so much being deleted?


> -{
> - struct fcoe_ctlr *fip = &fnic->ctlr;
> - struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> - struct sk_buff *skb;
> - char *eth_fr;
> - struct fip_vlan *vlan;
> - u64 vlan_tov;
> -
> - fnic_fcoe_reset_vlans(fnic);
> - fnic->set_vlan(fnic, 0);
> -
> - if (printk_ratelimit())
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "Sending VLAN request...\n");
> -
> - skb = dev_alloc_skb(sizeof(struct fip_vlan));
> - if (!skb)
> - return;
> -
> - eth_fr = (char *)skb->data;
> - vlan = (struct fip_vlan *)eth_fr;
> -
> - memset(vlan, 0, sizeof(*vlan));
> - memcpy(vlan->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
> - memcpy(vlan->eth.h_dest, fcoe_all_fcfs, ETH_ALEN);
> - vlan->eth.h_proto = htons(ETH_P_FIP);
> -
> - vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
> - vlan->fip.fip_op = htons(FIP_OP_VLAN);
> - vlan->fip.fip_subcode = FIP_SC_VL_REQ;
> - vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
> -
> - vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
> - vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW;
> - memcpy(&vlan->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
> -
> - vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
> - vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW;
> - put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn);
> - atomic64_inc(&fnic_stats->vlan_stats.vlan_disc_reqs);
> -
> - skb_put(skb, sizeof(*vlan));
> - skb->protocol = htons(ETH_P_FIP);
> - skb_reset_mac_header(skb);
> - skb_reset_network_header(skb);
> - fip->send(fip, skb);
> -
> - /* set a timer so that we can retry if there no response */
> - vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV);
> - mod_timer(&fnic->fip_timer, round_jiffies(vlan_tov));
> -}
> -
> -static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
> -{
> - struct fcoe_ctlr *fip = &fnic->ctlr;
> - struct fip_header *fiph;
> - struct fip_desc *desc;
> - struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> - u16 vid;
> - size_t rlen;
> - size_t dlen;
> - struct fcoe_vlan *vlan;
> - u64 sol_time;
> - unsigned long flags;
> -
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "Received VLAN response...\n");
> -
> - fiph = (struct fip_header *) skb->data;
> -
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "Received VLAN response... OP 0x%x SUB_OP 0x%x\n",
> - ntohs(fiph->fip_op), fiph->fip_subcode);
> -
> - rlen = ntohs(fiph->fip_dl_len) * 4;
> - fnic_fcoe_reset_vlans(fnic);
> - spin_lock_irqsave(&fnic->vlans_lock, flags);
> - desc = (struct fip_desc *)(fiph + 1);
> - while (rlen > 0) {
> - dlen = desc->fip_dlen * FIP_BPW;
> - switch (desc->fip_dtype) {
> - case FIP_DT_VLAN:
> - vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan);
> - shost_printk(KERN_INFO, fnic->lport->host,
> - "process_vlan_resp: FIP VLAN %d\n", vid);
> - vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
> - if (!vlan) {
> - /* retry from timer */
> - spin_unlock_irqrestore(&fnic->vlans_lock,
> - flags);
> - goto out;
> - }
> - vlan->vid = vid & 0x0fff;
> - vlan->state = FIP_VLAN_AVAIL;
> - list_add_tail(&vlan->list, &fnic->vlans);
> - break;
> - }
> - desc = (struct fip_desc *)((char *)desc + dlen);
> - rlen -= dlen;
> - }
> -
> - /* any VLAN descriptors present ? */
> - if (list_empty(&fnic->vlans)) {
> - /* retry from timer */
> - atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
> - FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> - "No VLAN descriptors in FIP VLAN response\n");
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - goto out;
> - }
> -
> - vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
> - fnic->set_vlan(fnic, vlan->vid);
> - vlan->state = FIP_VLAN_SENT; /* sent now */
> - vlan->sol_count++;
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> -
> - /* start the solicitation */
> - fcoe_ctlr_link_up(fip);
> -
> - sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
> - mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
> -out:
> - return;
> -}
> -
> -static void fnic_fcoe_start_fcf_disc(struct fnic *fnic)
> -{
> - unsigned long flags;
> - struct fcoe_vlan *vlan;
> - u64 sol_time;
> -
> - spin_lock_irqsave(&fnic->vlans_lock, flags);
> - vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
> - fnic->set_vlan(fnic, vlan->vid);
> - vlan->state = FIP_VLAN_SENT; /* sent now */
> - vlan->sol_count = 1;
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> -
> - /* start the solicitation */
> - fcoe_ctlr_link_up(&fnic->ctlr);
> -
> - sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
> - mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
> -}
> -
> -static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag)
> -{
> - unsigned long flags;
> - struct fcoe_vlan *fvlan;
> -
> - spin_lock_irqsave(&fnic->vlans_lock, flags);
> - if (list_empty(&fnic->vlans)) {
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - return -EINVAL;
> - }
> -
> - fvlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
> - if (fvlan->state == FIP_VLAN_USED) {
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - return 0;
> - }
> -
> - if (fvlan->state == FIP_VLAN_SENT) {
> - fvlan->state = FIP_VLAN_USED;
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - return 0;
> - }
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> - return -EINVAL;
> -}
> -
> -static void fnic_event_enq(struct fnic *fnic, enum fnic_evt ev)
> -{
> - struct fnic_event *fevt;
> - unsigned long flags;

it's very hard to review so much code being deleted....

> -
> - fevt = kmalloc(sizeof(*fevt), GFP_ATOMIC);
> - if (!fevt)
> - return;
> -
> - fevt->fnic = fnic;
> - fevt->event = ev;
> -
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - list_add_tail(&fevt->list, &fnic->evlist);
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> -
> - schedule_work(&fnic->event_work);
> -}
> -
> -static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb)
> -{
> - struct fip_header *fiph;
> - int ret = 1;
> - u16 op;
> - u8 sub;
> -
> - if (!skb || !(skb->data))
> - return -1;
> -
> - if (skb_linearize(skb))
> - goto drop;
> -
> - fiph = (struct fip_header *)skb->data;
> - op = ntohs(fiph->fip_op);
> - sub = fiph->fip_subcode;
> -
> - if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
> - goto drop;
> -
> - if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
> - goto drop;
> -
> - if (op == FIP_OP_DISC && sub == FIP_SC_ADV) {
> - if (fnic_fcoe_vlan_check(fnic, ntohs(fiph->fip_flags)))
> - goto drop;
> - /* pass it on to fcoe */
> - ret = 1;
> - } else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_NOTE) {
> - /* set the vlan as used */
> - fnic_fcoe_process_vlan_resp(fnic, skb);
> - ret = 0;
> - } else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) {
> - /* received CVL request, restart vlan disc */
> - fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
> - /* pass it on to fcoe */
> - ret = 1;
> - }
> -drop:
> - return ret;
> -}
> -
> -void fnic_handle_fip_frame(struct work_struct *work)
> -{
> - struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);
> - struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> - unsigned long flags;
> - struct sk_buff *skb;
> - struct ethhdr *eh;
> + list_del(&cur_frame->links);
>
> - while ((skb = skb_dequeue(&fnic->fip_frame_queue))) {
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - if (fnic->stop_rx_link_events) {
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - dev_kfree_skb(skb);
> - return;
> - }
> - /*
> - * If we're in a transitional state, just re-queue and return.
> - * The queue will be serviced when we get to a stable state.
> - */
> - if (fnic->state != FNIC_IN_FC_MODE &&
> - fnic->state != FNIC_IN_ETH_MODE) {
> - skb_queue_head(&fnic->fip_frame_queue, skb);
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - return;
> - }
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - eh = (struct ethhdr *)skb->data;
> - if (eh->h_proto == htons(ETH_P_FIP)) {
> - skb_pull(skb, sizeof(*eh));
> - if (fnic_fcoe_handle_fip_frame(fnic, skb) <= 0) {
> - dev_kfree_skb(skb);
> - continue;
> - }
> - /*
> - * If there's FLOGI rejects - clear all
> - * fcf's & restart from scratch
> - */
> - if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) {
> - atomic64_inc(
> - &fnic_stats->vlan_stats.flogi_rejects);
> - shost_printk(KERN_INFO, fnic->lport->host,
> - "Trigger a Link down - VLAN Disc\n");
> - fcoe_ctlr_link_down(&fnic->ctlr);
> - /* start FCoE VLAN discovery */
> - fnic_fcoe_send_vlan_req(fnic);
> - dev_kfree_skb(skb);
> - continue;
> - }
> - fcoe_ctlr_recv(&fnic->ctlr, skb);
> - continue;
> + if (fdls_fip_recv_frame(fnic, cur_frame->fp)) {
> + kfree(cur_frame->fp);
> + kfree(cur_frame);
> }
> }
> + spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
> }
>
> /**
> * fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame.
> * @fnic: fnic instance.
> - * @skb: Ethernet Frame.
> + * @fp: Ethernet Frame.
> */
> -static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb)
> +static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, void *fp)
> {
> - struct fc_frame *fp;
> - struct ethhdr *eh;
> - struct fcoe_hdr *fcoe_hdr;
> - struct fcoe_crc_eof *ft;
> + struct fnic_eth_hdr_s *eh;
> + struct fnic_frame_list *fip_fr_elem;
> + unsigned long flags;
>
> - /*
> - * Undo VLAN encapsulation if present.
> - */
> - eh = (struct ethhdr *)skb->data;
> - if (eh->h_proto == htons(ETH_P_8021Q)) {
> - memmove((u8 *)eh + VLAN_HLEN, eh, ETH_ALEN * 2);
> - eh = skb_pull(skb, VLAN_HLEN);
> - skb_reset_mac_header(skb);
> - }
> - if (eh->h_proto == htons(ETH_P_FIP)) {
> - if (!(fnic->config.flags & VFCF_FIP_CAPABLE)) {
> - printk(KERN_ERR "Dropped FIP frame, as firmware "
> - "uses non-FIP mode, Enable FIP "
> - "using UCSM\n");
> - goto drop;
> - }
> - if ((fnic_fc_trace_set_data(fnic->lport->host->host_no,
> - FNIC_FC_RECV|0x80, (char *)skb->data, skb->len)) != 0) {
> - printk(KERN_ERR "fnic ctlr frame trace error!!!");
> - }
> - skb_queue_tail(&fnic->fip_frame_queue, skb);
> + eh = (struct fnic_eth_hdr_s *) fp;
> + if ((eh->ether_type == htons(ETH_TYPE_FIP)) && (fnic->iport.usefip)) {
> + fip_fr_elem = (struct fnic_frame_list *)
> + kmalloc(sizeof(struct fnic_frame_list), GFP_ATOMIC);
> + if (!fip_fr_elem)
> + return 0;
> + memset(fip_fr_elem, 0, sizeof(struct fnic_frame_list));
> + fip_fr_elem->fp = fp;
> + spin_lock_irqsave(&fnic->fnic_lock, flags);
> + list_add_tail(&fip_fr_elem->links, &fnic->fip_frame_queue);
> + spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> queue_work(fnic_fip_queue, &fnic->fip_frame_work);
> - return 1; /* let caller know packet was used */
> - }
> - if (eh->h_proto != htons(ETH_P_FCOE))
> - goto drop;
> - skb_set_network_header(skb, sizeof(*eh));
> - skb_pull(skb, sizeof(*eh));
> -
> - fcoe_hdr = (struct fcoe_hdr *)skb->data;
> - if (FC_FCOE_DECAPS_VER(fcoe_hdr) != FC_FCOE_VER)
> - goto drop;
> -
> - fp = (struct fc_frame *)skb;
> - fc_frame_init(fp);
> - fr_sof(fp) = fcoe_hdr->fcoe_sof;
> - skb_pull(skb, sizeof(struct fcoe_hdr));
> - skb_reset_transport_header(skb);
> -
> - ft = (struct fcoe_crc_eof *)(skb->data + skb->len - sizeof(*ft));
> - fr_eof(fp) = ft->fcoe_eof;
> - skb_trim(skb, skb->len - sizeof(*ft));
> - return 0;
> -drop:
> - dev_kfree_skb_irq(skb);
> - return -1;
> + return 1; /* let caller know packet was used */
> + } else
> + return 0;
> }
>
> /**
> @@ -800,206 +365,146 @@ static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb)
> */
> void fnic_update_mac_locked(struct fnic *fnic, u8 *new)
> {
> - u8 *ctl = fnic->ctlr.ctl_src_addr;
> + struct fnic_iport_s *iport = &fnic->iport;
> + u8 *ctl = iport->hwmac;
> u8 *data = fnic->data_src_addr;
>
> if (is_zero_ether_addr(new))
> new = ctl;
> if (ether_addr_equal(data, new))
> return;
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "update_mac %pM\n", new);
> +
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Update MAC: %u\n", *new);
> +
> if (!is_zero_ether_addr(data) && !ether_addr_equal(data, ctl))
> vnic_dev_del_addr(fnic->vdev, data);
> +
> memcpy(data, new, ETH_ALEN);
> if (!ether_addr_equal(new, ctl))
> vnic_dev_add_addr(fnic->vdev, new);
> }
>
> -/**
> - * fnic_update_mac() - set data MAC address and filters.
> - * @lport: local port.
> - * @new: newly-assigned FCoE MAC address.
> - */
> -void fnic_update_mac(struct fc_lport *lport, u8 *new)
> -{
> - struct fnic *fnic = lport_priv(lport);
> -
> - spin_lock_irq(&fnic->fnic_lock);
> - fnic_update_mac_locked(fnic, new);
> - spin_unlock_irq(&fnic->fnic_lock);
> -}
> -
> -/**
> - * fnic_set_port_id() - set the port_ID after successful FLOGI.
> - * @lport: local port.
> - * @port_id: assigned FC_ID.
> - * @fp: received frame containing the FLOGI accept or NULL.
> - *
> - * This is called from libfc when a new FC_ID has been assigned.
> - * This causes us to reset the firmware to FC_MODE and setup the new MAC
> - * address and FC_ID.
> - *
> - * It is also called with FC_ID 0 when we're logged off.
> - *
> - * If the FC_ID is due to point-to-point, fp may be NULL.
> - */
> -void fnic_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp)
> -{
> - struct fnic *fnic = lport_priv(lport);
> - u8 *mac;
> - int ret;
> -
> - FNIC_FCS_DBG(KERN_DEBUG, lport->host, fnic->fnic_num,
> - "set port_id 0x%x fp 0x%p\n",
> - port_id, fp);
> -
> - /*
> - * If we're clearing the FC_ID, change to use the ctl_src_addr.
> - * Set ethernet mode to send FLOGI.
> - */
> - if (!port_id) {
> - fnic_update_mac(lport, fnic->ctlr.ctl_src_addr);
> - fnic_set_eth_mode(fnic);
> - return;
> - }
> -
> - if (fp) {
> - mac = fr_cb(fp)->granted_mac;
> - if (is_zero_ether_addr(mac)) {
> - /* non-FIP - FLOGI already accepted - ignore return */
> - fcoe_ctlr_recv_flogi(&fnic->ctlr, lport, fp);
> - }
> - fnic_update_mac(lport, mac);
> - }
> -
> - /* Change state to reflect transition to FC mode */
> - spin_lock_irq(&fnic->fnic_lock);
> - 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_ERR, fnic->lport->host, fnic->fnic_num,
> - "Unexpected fnic state: %s processing FLOGI response",
> - fnic_state_to_str(fnic->state));
> - spin_unlock_irq(&fnic->fnic_lock);
> - return;
> - }
> - spin_unlock_irq(&fnic->fnic_lock);
> -
> - /*
> - * Send FLOGI registration to firmware to set up FC mode.
> - * The new address will be set up when registration completes.
> - */
> - ret = fnic_flogi_reg_handler(fnic, port_id);
> -
> - if (ret < 0) {
> - spin_lock_irq(&fnic->fnic_lock);
> - if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE)
> - fnic->state = FNIC_IN_ETH_MODE;
> - spin_unlock_irq(&fnic->fnic_lock);
> - }
> -}
> -
> static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
> *cq_desc, struct vnic_rq_buf *buf,
> int skipped __attribute__((unused)),
> void *opaque)
> {
> struct fnic *fnic = vnic_dev_priv(rq->vdev);
> - struct sk_buff *skb;
> - struct fc_frame *fp;
> + uint8_t *fp;
> struct fnic_stats *fnic_stats = &fnic->fnic_stats;
> + unsigned int ethhdr_stripped;
> u8 type, color, eop, sop, ingress_port, vlan_stripped;
> - u8 fcoe = 0, fcoe_sof, fcoe_eof;
> - u8 fcoe_fc_crc_ok = 1, fcoe_enc_error = 0;
> - u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
> - u8 ipv6, ipv4, ipv4_fragment, rss_type, csum_not_calc;
> + u8 fcoe_fnic_crc_ok = 1, fcoe_enc_error = 0;
> u8 fcs_ok = 1, packet_error = 0;
> - u16 q_number, completed_index, bytes_written = 0, vlan, checksum;
> + u16 q_number, completed_index, vlan;
> u32 rss_hash;
> + u16 checksum;
> + u8 csum_not_calc, rss_type, ipv4, ipv6, ipv4_fragment;
> + u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
> + u8 fcoe = 0, fcoe_sof, fcoe_eof;
> u16 exchange_id, tmpl;
> u8 sof = 0;
> u8 eof = 0;
> u32 fcp_bytes_written = 0;
> + u16 enet_bytes_written = 0;
> + u32 bytes_written = 0;
> unsigned long flags;
> + struct fnic_frame_list *frame_elem = NULL;
> + struct fnic_eth_hdr_s *eh;

so many local variables tells me that this function is too big without
even looking at it further

>
> dma_unmap_single(&fnic->pdev->dev, buf->dma_addr, buf->len,
> - DMA_FROM_DEVICE);
> - skb = buf->os_buf;
> - fp = (struct fc_frame *)skb;
> + DMA_FROM_DEVICE);
> + fp = (uint8_t *) buf->os_buf;
> buf->os_buf = NULL;
>
> cq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index);
> if (type == CQ_DESC_TYPE_RQ_FCP) {
> - cq_fcp_rq_desc_dec((struct cq_fcp_rq_desc *)cq_desc,
> - &type, &color, &q_number, &completed_index,
> - &eop, &sop, &fcoe_fc_crc_ok, &exchange_id,
> - &tmpl, &fcp_bytes_written, &sof, &eof,
> - &ingress_port, &packet_error,
> - &fcoe_enc_error, &fcs_ok, &vlan_stripped,
> - &vlan);
> - skb_trim(skb, fcp_bytes_written);
> - fr_sof(fp) = sof;
> - fr_eof(fp) = eof;
> -
> + cq_fcp_rq_desc_dec((struct cq_fcp_rq_desc *) cq_desc, &type,
> + &color, &q_number, &completed_index, &eop, &sop,
> + &fcoe_fnic_crc_ok, &exchange_id, &tmpl,
> + &fcp_bytes_written, &sof, &eof, &ingress_port,
> + &packet_error, &fcoe_enc_error, &fcs_ok,
> + &vlan_stripped, &vlan);
> + ethhdr_stripped = 1;
> + bytes_written = fcp_bytes_written;
> } else if (type == CQ_DESC_TYPE_RQ_ENET) {
> - cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
> - &type, &color, &q_number, &completed_index,
> - &ingress_port, &fcoe, &eop, &sop,
> - &rss_type, &csum_not_calc, &rss_hash,
> - &bytes_written, &packet_error,
> - &vlan_stripped, &vlan, &checksum,
> - &fcoe_sof, &fcoe_fc_crc_ok,
> - &fcoe_enc_error, &fcoe_eof,
> - &tcp_udp_csum_ok, &udp, &tcp,
> - &ipv4_csum_ok, &ipv6, &ipv4,
> - &ipv4_fragment, &fcs_ok);

I think that cq_enet_rq_desc_dec() accepts too many arguments, to say
the least

I also could not help but notice that there is a cq_enet_rq_desc_dec()
in this driver and also one in
drivers/net/ethernet/cisco/enic/cq_enet_desc.h - could they be made common?

> - skb_trim(skb, bytes_written);
> + cq_enet_rq_desc_dec((struct cq_enet_rq_desc *) cq_desc, &type,
> + &color, &q_number, &completed_index,
> + &ingress_port, &fcoe, &eop, &sop, &rss_type,
> + &csum_not_calc, &rss_hash, &enet_bytes_written,
> + &packet_error, &vlan_stripped, &vlan,
> + &checksum, &fcoe_sof, &fcoe_fnic_crc_ok,
> + &fcoe_enc_error, &fcoe_eof, &tcp_udp_csum_ok,
> + &udp, &tcp, &ipv4_csum_ok, &ipv6, &ipv4,
> + &ipv4_fragment, &fcs_ok);
> +
> + ethhdr_stripped = 0;
> + bytes_written = enet_bytes_written;
> +
> if (!fcs_ok) {
> atomic64_inc(&fnic_stats->misc_stats.frame_errors);
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "fcs error. dropping packet.\n");
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p fcs error. Dropping packet.\n", fnic);
> goto drop;
> }
> - if (fnic_import_rq_eth_pkt(fnic, skb))
> - return;
> + eh = (struct fnic_eth_hdr_s *) fp;
> + if (eh->ether_type != htons(ETH_TYPE_FCOE)) {
> +
> + if (fnic_import_rq_eth_pkt(fnic, fp))
> + return;
>
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Dropping ether_type 0x%x",
> + ntohs(eh->ether_type));
> + goto drop;
> + }
> } else {
> - /* wrong CQ type*/
> - shost_printk(KERN_ERR, fnic->lport->host,
> - "fnic rq_cmpl wrong cq type x%x\n", type);
> + /* wrong CQ type */
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic rq_cmpl wrong cq type x%x\n", type);
> goto drop;
> }
>
> - if (!fcs_ok || packet_error || !fcoe_fc_crc_ok || fcoe_enc_error) {
> + if (!fcs_ok || packet_error || !fcoe_fnic_crc_ok || fcoe_enc_error) {
> atomic64_inc(&fnic_stats->misc_stats.frame_errors);
> - FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
> - "fnic rq_cmpl fcoe x%x fcsok x%x"
> - " pkterr x%x fcoe_fc_crc_ok x%x, fcoe_enc_err"
> - " x%x\n",
> - fcoe, fcs_ok, packet_error,
> - fcoe_fc_crc_ok, fcoe_enc_error);
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fcoe %x fcsok %x pkterr %x ffco %x fee %x\n",
> + fcoe, fcs_ok, packet_error,
> + fcoe_fnic_crc_ok, fcoe_enc_error);
> goto drop;
> }
>
> 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->lport->host, fnic->fnic_num,
> + "fnic->stop_rx_link_events: %d\n",
> + fnic->stop_rx_link_events);
> goto drop;
> }
> - fr_dev(fp) = fnic->lport;
> +
> spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> - if ((fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_RECV,
> - (char *)skb->data, skb->len)) != 0) {
> - printk(KERN_ERR "fnic ctlr frame trace error!!!");
> +
> + frame_elem =
> + kmalloc(sizeof(struct fnic_frame_list),
> + GFP_ATOMIC);

GFP_ATOMIC is used way too much

> + if (!frame_elem) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "Unable to alloc frame element of size: %ld\n",
> + sizeof(struct fnic_frame_list));
> + goto drop;
> }
> + memset(frame_elem, 0, sizeof(struct fnic_frame_list));
> + frame_elem->fp = fp;
> + frame_elem->rx_ethhdr_stripped = ethhdr_stripped;
> + frame_elem->frame_len = bytes_written;
>
> - skb_queue_tail(&fnic->frame_queue, skb);
> queue_work(fnic_event_queue, &fnic->frame_work);
> -
> return;
> +
> drop:
> - dev_kfree_skb_irq(skb);
> + kfree(fp);
> }
>
> static int fnic_rq_cmpl_handler_cont(struct vnic_dev *vdev,
> @@ -1089,62 +594,6 @@ void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
> buf->os_buf = NULL;
> }
>
> -/**
> - * fnic_eth_send() - Send Ethernet frame.
> - * @fip: fcoe_ctlr instance.
> - * @skb: Ethernet Frame, FIP, without VLAN encapsulation.
> - */
> -void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
> -{
> - struct fnic *fnic = fnic_from_ctlr(fip);
> - struct vnic_wq *wq = &fnic->wq[0];
> - dma_addr_t pa;
> - struct ethhdr *eth_hdr;
> - struct vlan_ethhdr *vlan_hdr;
> - unsigned long flags;
> -
> - if (!fnic->vlan_hw_insert) {
> - eth_hdr = (struct ethhdr *)skb_mac_header(skb);
> - vlan_hdr = skb_push(skb, sizeof(*vlan_hdr) - sizeof(*eth_hdr));
> - memcpy(vlan_hdr, eth_hdr, 2 * ETH_ALEN);
> - vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
> - vlan_hdr->h_vlan_encapsulated_proto = eth_hdr->h_proto;
> - vlan_hdr->h_vlan_TCI = htons(fnic->vlan_id);
> - if ((fnic_fc_trace_set_data(fnic->lport->host->host_no,
> - FNIC_FC_SEND|0x80, (char *)eth_hdr, skb->len)) != 0) {
> - printk(KERN_ERR "fnic ctlr frame trace error!!!");
> - }
> - } else {
> - if ((fnic_fc_trace_set_data(fnic->lport->host->host_no,
> - FNIC_FC_SEND|0x80, (char *)skb->data, skb->len)) != 0) {
> - printk(KERN_ERR "fnic ctlr frame trace error!!!");
> - }
> - }
> -
> - pa = dma_map_single(&fnic->pdev->dev, skb->data, skb->len,
> - DMA_TO_DEVICE);
> - if (dma_mapping_error(&fnic->pdev->dev, pa)) {
> - printk(KERN_ERR "DMA mapping failed\n");
> - goto free_skb;
> - }
> -
> - spin_lock_irqsave(&fnic->wq_lock[0], flags);
> - if (!vnic_wq_desc_avail(wq))
> - goto irq_restore;
> -
> - fnic_queue_wq_eth_desc(wq, skb, pa, skb->len,
> - 0 /* hw inserts cos value */,
> - fnic->vlan_id, 1);
> - spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
> - return;
> -
> -irq_restore:
> - spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
> - dma_unmap_single(&fnic->pdev->dev, pa, skb->len, DMA_TO_DEVICE);
> -free_skb:
> - kfree_skb(skb);
> -}
> -
> /*
> * Send FC frame.
> */
> @@ -1245,6 +694,27 @@ fdls_send_fcoe_frame(struct fnic *fnic, void *payload, int payload_sz,
> return ret;
> }
>
> +static int
> +fdls_send_fip_frame(struct fnic *fnic, void *payload, int payload_sz)
> +{
> + uint8_t *frame;
> + int max_framesz = FNIC_FCOE_FRAME_MAXSZ;
> + int ret;
> +
> + frame = kmalloc(max_framesz, GFP_ATOMIC);

why even use GFP_ATOMIC here (and not GFP_KERNEL)?

> + if (!frame) {
> + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
> + "fnic 0x%p Failed to allocate fip frame\n", fnic);
> + return -1;
> + }
> + memset(frame, 0, max_framesz);
> +
> + memcpy(frame, (uint8_t *) payload, payload_sz);
> + ret = fnic_send_frame(fnic, frame, payload_sz);
> +
> + return ret;
> +}
> +
> int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
> int payload_sz)
> {
> @@ -1269,6 +739,18 @@ int fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *payload,
> return ret;
> }
>
> +int

who checks this return value? None, AFAICS

> +fnic_send_fip_frame(struct fnic_iport_s *iport, void *payload,
> + int payload_sz)
> +{
> + struct fnic *fnic = iport->fnic;
> +
> + if (fnic->in_remove)
> + return -1;
> +
> + return fdls_send_fip_frame(fnic, payload, payload_sz);
> +}
> +
> /**
> * fnic_flush_tx() - send queued frames.
> * @work: pointer to work element
> @@ -1342,44 +824,6 @@ fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
> return 0;
> }
>
> -/**
> - * fnic_set_eth_mode() - put fnic into ethernet mode.
> - * @fnic: fnic device
> - *
> - * Called without fnic lock held.
> - */
> -static void fnic_set_eth_mode(struct fnic *fnic)
> -{
> - unsigned long flags;
> - enum fnic_state old_state;
> - int ret;
> -
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> -again:
> - old_state = fnic->state;
> - switch (old_state) {
> - case FNIC_IN_FC_MODE:
> - case FNIC_IN_ETH_TRANS_FC_MODE:
> - default:
> - fnic->state = FNIC_IN_FC_TRANS_ETH_MODE;
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> -
> - ret = fnic_fw_reset_handler(fnic);
> -
> - spin_lock_irqsave(&fnic->fnic_lock, flags);
> - if (fnic->state != FNIC_IN_FC_TRANS_ETH_MODE)
> - goto again;
> - if (ret)
> - fnic->state = old_state;
> - break;
> -
> - case FNIC_IN_FC_TRANS_ETH_MODE:
> - case FNIC_IN_ETH_MODE:
> - break;
> - }
> - spin_unlock_irqrestore(&fnic->fnic_lock, flags);
> -}
> -
> void fnic_free_txq(struct list_head *head)
> {
> struct fnic_frame_list *cur_frame, *next;
> @@ -1449,24 +893,3 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
> buf->os_buf = NULL;
> }
>
> -void fnic_fcoe_reset_vlans(struct fnic *fnic)
> -{
> - unsigned long flags;
> - struct fcoe_vlan *vlan;
> - struct fcoe_vlan *next;
> -
> - /*
> - * indicate a link down to fcoe so that all fcf's are free'd
> - * might not be required since we did this before sending vlan
> - * discovery request
> - */
> - spin_lock_irqsave(&fnic->vlans_lock, flags);
> - if (!list_empty(&fnic->vlans)) {
> - list_for_each_entry_safe(vlan, next, &fnic->vlans, list) {
> - list_del(&vlan->list);
> - kfree(vlan);
> - }
> - }
> - spin_unlock_irqrestore(&fnic->vlans_lock, flags);
> -}
> -
> diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
> index 7d10d603f53b..d850ce4b743d 100644
> --- a/drivers/scsi/fnic/fnic_main.c
> +++ b/drivers/scsi/fnic/fnic_main.c
> @@ -85,12 +85,13 @@ module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR);
> MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN");
>
> static struct libfc_function_template fnic_transport_template = {
> - .lport_set_port_id = fnic_set_port_id,
> .fcp_abort_io = fnic_empty_scsi_cleanup,
> .fcp_cleanup = fnic_empty_scsi_cleanup,
> .exch_mgr_reset = fnic_exch_mgr_reset
> };
>
> +struct workqueue_struct *fnic_fip_queue;
> +
> static int fnic_slave_alloc(struct scsi_device *sdev)
> {
> struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
> @@ -413,13 +414,6 @@ static void fnic_notify_timer(struct timer_list *t)
> round_jiffies(jiffies + FNIC_NOTIFY_TIMER_PERIOD));
> }
>
> -static void fnic_fip_notify_timer(struct timer_list *t)
> -{
> - struct fnic *fnic = from_timer(fnic, t, fip_timer);
> -
> - /* Placeholder function */
> -}
> -
> static void fnic_notify_timer_start(struct fnic *fnic)
> {
> switch (vnic_dev_get_intr_mode(fnic->vdev)) {
> @@ -531,17 +525,6 @@ static void fnic_iounmap(struct fnic *fnic)
> iounmap(fnic->bar0.vaddr);
> }
>
> -/**
> - * fnic_get_mac() - get assigned data MAC address for FIP code.
> - * @lport: local port.
> - */
> -static u8 *fnic_get_mac(struct fc_lport *lport)
> -{
> - struct fnic *fnic = lport_priv(lport);
> -
> - return fnic->data_src_addr;
> -}
> -
> static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id)
> {
> vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
> @@ -814,26 +797,23 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> fnic->vlan_hw_insert = 1;
> fnic->vlan_id = 0;
>
> - /* Initialize the FIP fcoe_ctrl struct */
> - fnic->ctlr.send = fnic_eth_send;
> - fnic->ctlr.update_mac = fnic_update_mac;
> - fnic->ctlr.get_src_addr = fnic_get_mac;
> if (fnic->config.flags & VFCF_FIP_CAPABLE) {
> pr_info("firmware supports FIP\n");
> /* enable directed and multicast */
> vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0);
> vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS);
> vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr);
> - fnic->set_vlan = fnic_set_vlan;
> fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO);
> - timer_setup(&fnic->fip_timer, fnic_fip_notify_timer, 0);
> spin_lock_init(&fnic->vlans_lock);
> INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
> - INIT_WORK(&fnic->event_work, fnic_handle_event);
> INIT_WORK(&fnic->flush_work, fnic_flush_tx);
> - skb_queue_head_init(&fnic->fip_frame_queue);
> - INIT_LIST_HEAD(&fnic->evlist);
> - INIT_LIST_HEAD(&fnic->vlans);
> + INIT_LIST_HEAD(&fnic->fip_frame_queue);
> + INIT_LIST_HEAD(&fnic->vlan_list);
> + timer_setup(&fnic->retry_fip_timer, fnic_handle_fip_timer, 0);
> + timer_setup(&fnic->fcs_ka_timer, fnic_handle_fcs_ka_timer, 0);
> + timer_setup(&fnic->enode_ka_timer, fnic_handle_enode_ka_timer, 0);
> + timer_setup(&fnic->vn_ka_timer, fnic_handle_vn_ka_timer, 0);
> + fnic->set_vlan = fnic_set_vlan;

so many timers, work structs, lists. I don't know how all this is
co-ordinated sanely....

> } else {
> pr_info("firmware uses non-FIP mode\n");
> fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_NON_FIP);
> @@ -1030,10 +1010,13 @@ static void fnic_remove(struct pci_dev *pdev)
> fnic_free_txq(&fnic->tx_queue);
>
> if (fnic->config.flags & VFCF_FIP_CAPABLE) {
> - del_timer_sync(&fnic->fip_timer);
> - skb_queue_purge(&fnic->fip_frame_queue);
> + del_timer_sync(&fnic->retry_fip_timer);
> + del_timer_sync(&fnic->fcs_ka_timer);
> + del_timer_sync(&fnic->enode_ka_timer);
> + del_timer_sync(&fnic->vn_ka_timer);
> +
> + fnic_free_txq(&fnic->fip_frame_queue);
> fnic_fcoe_reset_vlans(fnic);
> - fnic_fcoe_evlist_free(fnic);
> }
>
> if ((fnic_fdmi_support == 1) && (fnic->iport.fabric.fdmi_pending > 0))


Subject: RE: [PATCH 07/14] scsi: fnic: Add and integrate support for FIP

On Tuesday, June 11, 2024 11:48 PM, Hannes Reinecke <[email protected]> wrote:
>
> On 6/10/24 23:50, Karan Tilak Kumar wrote:
> > Add and integrate support for FCoE Initialization
> > (protocol) FIP. This protocol will be exercised on Cisco UCS rack
> > servers.
> > Add support to specifically print FIP related debug messages.
> > Replace existing definitions to handle new data structures.
> > Clean up old and obsolete definitions.
> >
> Aren't you getting a bit overboard here?
>
> I am _positive_ that the original fnic driver _did_ do FIP.
> What happened to that?
> Why can't you just use that implementation?
>
> And if you can't use that implementation, shouldn't this rather be a new driver instead of replacing most if not all functionality of the original fnic driver?

Thanks for your review comments, Hannes.
As you can see from this patch, and some of the later patches, fnic driver would be reliant on FDLS.
FDLS helps solve some of the issues that we have seen in our hardware where:

1) the adapter hangs such that FC offload is impacted,
2) the fabric gets into a blackhole situation, where nothing comes out of the fabric.

These situations get easily escalated and are quite hard to diagnose.
FDLS has helped us in these instances to chart a way forward, and to solve the issue.

Cisco has been shipping async fnic driver based on FDLS for the past six years.
Cisco officially supports the async driver.
The async driver has support for PC-RSCN (seen in a later patch) and NVME initiators.
Since the async driver has been in the field for quite a while now, it is a well-seasoned driver.
It has also gone through lots of QA cycles to reach a level of stability today.
Therefore, the Cisco team feels comfortable in upstreaming this change.

Keeping in line with the upstreaming best practices, our preferred line of approach is to modify the existing driver with this change.
I assume that there will be challenges in maintaining two separate upstream drivers and hence the current approach.
However, we want to be mindful of your comments.
If you believe that a new driver is warranted based on these changes, the Cisco team can evaluate that approach.
Please share your thoughts with us.

Regards,
Karan

Subject: RE: [PATCH 08/14] scsi: fnic: Add functionality in fnic to support FDLS

On Tuesday, June 11, 2024 11:57 PM, Hannes Reinecke <[email protected]> wrote:
>
> On 6/10/24 23:50, Karan Tilak Kumar wrote:
> > Add interfaces in fnic to use FDLS services.
> > Modify link up and link down functionality to use FDLS.
> > Replace existing interfaces to handle new functionality provided by
> > FDLS.
> > Modify data types of some data members to handle new functionality.
> > Add processing of tports and handling of tports.
> >
> > Reviewed-by: Sesidhar Baddela <[email protected]>
> > Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
> > Reviewed-by: Gian Carlo Boffa <[email protected]>
> > Signed-off-by: Karan Tilak Kumar <[email protected]>
> > ---
> > drivers/scsi/fnic/fdls_disc.c | 74 +++++
> > drivers/scsi/fnic/fip.c | 27 +-
> > drivers/scsi/fnic/fnic.h | 20 +-
> > drivers/scsi/fnic/fnic_fcs.c | 498 ++++++++++++++++++++++++----------
> > drivers/scsi/fnic/fnic_main.c | 10 +-
> > drivers/scsi/fnic/fnic_scsi.c | 127 +++++++--
> > 6 files changed, 587 insertions(+), 169 deletions(-)
> >
> This seems to not just _add_ the functionality to use FDLS, but rather _replace_ the existing functionality with FDLS.
> IE it seems that after this change the driver will always do FDLS, causing a possible service interruption with existing setups.
> Hmm?

Thanks for your review comments, Hannes.
As I mentioned in the other patch comments, Cisco has been shipping an async driver based on FDLS for the past six years.
The async driver is backward compatible and supports all the adapters that are supported by the existing upstream driver, and more.
The async driver in fact overrides the upstream driver on our installations.

On Cisco hardware, the best practice out in the field, is to update the driver to the async driver during OS installation itself.
Due to this best practice, we have _not_ received any feedback from customers indicating an abnormal service interruption specifically due to the driver update.

I hope this addresses your concerns about this issue.
Please feel free to share your thoughts or any other insights regarding this.

Regards,
Karan

2024-06-15 09:05:18

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 07/14] scsi: fnic: Add and integrate support for FIP

On 6/15/24 05:44, Karan Tilak Kumar (kartilak) wrote:
> On Tuesday, June 11, 2024 11:48 PM, Hannes Reinecke <[email protected]> wrote:
>>
>> On 6/10/24 23:50, Karan Tilak Kumar wrote:
>>> Add and integrate support for FCoE Initialization
>>> (protocol) FIP. This protocol will be exercised on Cisco UCS rack
>>> servers.
>>> Add support to specifically print FIP related debug messages.
>>> Replace existing definitions to handle new data structures.
>>> Clean up old and obsolete definitions.
>>>
>> Aren't you getting a bit overboard here?
>>
>> I am _positive_ that the original fnic driver _did_ do FIP.
>> What happened to that?
>> Why can't you just use that implementation?
>>
>> And if you can't use that implementation, shouldn't this rather be a new driver instead of replacing
>> most if not all functionality of the original fnic driver?
>
> Thanks for your review comments, Hannes.
> As you can see from this patch, and some of the later patches, fnic driver would be reliant on FDLS.
> FDLS helps solve some of the issues that we have seen in our hardware where:
>
> 1) the adapter hangs such that FC offload is impacted,
> 2) the fabric gets into a blackhole situation, where nothing comes out of the fabric.
>
> These situations get easily escalated and are quite hard to diagnose.
> FDLS has helped us in these instances to chart a way forward, and to solve the issue.
>
> Cisco has been shipping async fnic driver based on FDLS for the past six years.
> Cisco officially supports the async driver.
> The async driver has support for PC-RSCN (seen in a later patch) and NVME initiators.
> Since the async driver has been in the field for quite a while now, it is a well-seasoned driver.
> It has also gone through lots of QA cycles to reach a level of stability today.
> Therefore, the Cisco team feels comfortable in upstreaming this change.
>
> Keeping in line with the upstreaming best practices, our preferred line of approach is to modify
> the existing driver with this change.
> I assume that there will be challenges in maintaining two separate upstream drivers and hence the
> current approach.
> However, we want to be mindful of your comments.
> If you believe that a new driver is warranted based on these changes, the Cisco team can evaluate
> that approach.
> Please share your thoughts with us.
>
In generally, adding new functionality to an existing driver is the
correct way to do. What I am worrying about is that we avoid code
duplication (hence my comment for FIP handling), and that existing
functionality is not impacted.
But when adding new functionality one always has to check how much
shared functionality there is; if there is very little overlap it
would make sense to split the driver in two.
However, that is personal preference; if you think that the driver is
easier to maintain as a single driver, that's fine, too.
But your effort in upstreaming the driver is very much appreciated.
Keep up the good work.

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


2024-06-15 09:07:29

by Hannes Reinecke

[permalink] [raw]
Subject: Re: [PATCH 08/14] scsi: fnic: Add functionality in fnic to support FDLS

On 6/15/24 05:47, Karan Tilak Kumar (kartilak) wrote:
> On Tuesday, June 11, 2024 11:57 PM, Hannes Reinecke <[email protected]> wrote:
>>
>> On 6/10/24 23:50, Karan Tilak Kumar wrote:
>>> Add interfaces in fnic to use FDLS services.
>>> Modify link up and link down functionality to use FDLS.
>>> Replace existing interfaces to handle new functionality provided by
>>> FDLS.
>>> Modify data types of some data members to handle new functionality.
>>> Add processing of tports and handling of tports.
>>>
>>> Reviewed-by: Sesidhar Baddela <[email protected]>
>>> Reviewed-by: Arulprabhu Ponnusamy <[email protected]>
>>> Reviewed-by: Gian Carlo Boffa <[email protected]>
>>> Signed-off-by: Karan Tilak Kumar <[email protected]>
>>> ---
>>> drivers/scsi/fnic/fdls_disc.c | 74 +++++
>>> drivers/scsi/fnic/fip.c | 27 +-
>>> drivers/scsi/fnic/fnic.h | 20 +-
>>> drivers/scsi/fnic/fnic_fcs.c | 498 ++++++++++++++++++++++++----------
>>> drivers/scsi/fnic/fnic_main.c | 10 +-
>>> drivers/scsi/fnic/fnic_scsi.c | 127 +++++++--
>>> 6 files changed, 587 insertions(+), 169 deletions(-)
>>>
>> This seems to not just _add_ the functionality to use FDLS, but rather _replace_ the existing
>> functionality with FDLS.
>> IE it seems that after this change the driver will always do FDLS, causing a possible service
>> interruption with existing setups.
>> Hmm?
>
> Thanks for your review comments, Hannes.
> As I mentioned in the other patch comments, Cisco has been shipping an async driver based on FDLS
> for the past six years.
> The async driver is backward compatible and supports all the adapters that are supported by the
> existing upstream driver, and more.
> The async driver in fact overrides the upstream driver on our installations.
>
Ah. Good to know. Ever more a reason to have your driver upstreamed, then...


> On Cisco hardware, the best practice out in the field, is to update the driver to the async
> driver during OS installation itself.
> Due to this best practice, we have _not_ received any feedback from customers indicating an
> abnormal service interruption specifically due to the driver update.
>
Ah. I wasn't aware of that.
So that's fine, then, and you can disregard my comments here.

Cheers,

Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
[email protected] +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich