Commit 7d6f88e7 authored by Martin K. Petersen's avatar Martin K. Petersen
Browse files

Merge patch series "Introduce support for Fabric Discovery and Login Services"

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

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. The compiler used is GCC
13.3. Some function calls have been coded as placeholders with
appropriate comments to avoid compiler warnings.

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.

Link: https://lore.kernel.org/r/20241212020312.4786-1-kartilak@cisco.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 295006f6 86979346
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -2,11 +2,13 @@
obj-$(CONFIG_FCOE_FNIC) += fnic.o

fnic-y	:= \
	fip.o\
	fnic_attrs.o \
	fnic_isr.o \
	fnic_main.o \
	fnic_res.o \
	fnic_fcs.o \
	fdls_disc.o \
	fnic_scsi.o \
	fnic_trace.o \
	fnic_debugfs.o \
@@ -15,4 +17,5 @@ fnic-y := \
	vnic_intr.o \
	vnic_rq.o \
	vnic_wq_copy.o \
	vnic_wq.o
	vnic_wq.o \
	fnic_pci_subsys_devid.o
+4997 −0

File added.

Preview size limit exceeded, changes collapsed.

+253 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
 * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
 */

#ifndef _FDLS_FC_H_
#define _FDLS_FC_H_

/* This file contains the declarations for FC fabric services
 * and target discovery
 *
 * Request and Response for
 * 1. FLOGI
 * 2. PLOGI to Fabric Controller
 * 3. GPN_ID, GPN_FT
 * 4. RSCN
 * 5. PLOGI to Target
 * 6. PRLI to Target
 */

#include <scsi/scsi.h>
#include <scsi/fc/fc_els.h>
#include <uapi/scsi/fc/fc_fs.h>
#include <uapi/scsi/fc/fc_ns.h>
#include <uapi/scsi/fc/fc_gs.h>
#include <uapi/linux/if_ether.h>
#include <scsi/fc/fc_ms.h>
#include <linux/minmax.h>
#include <linux/if_ether.h>
#include <scsi/fc/fc_encaps.h>
#include <scsi/fc/fc_fcoe.h>

#define FDLS_MIN_FRAMES	(32)
#define FDLS_MIN_FRAME_ELEM	(4)
#define FNIC_FCP_SP_RD_XRDY_DIS 0x00000002
#define FNIC_FCP_SP_TARGET      0x00000010
#define FNIC_FCP_SP_INITIATOR   0x00000020
#define FNIC_FCP_SP_CONF_CMPL   0x00000080
#define FNIC_FCP_SP_RETRY       0x00000100

#define FNIC_FC_CONCUR_SEQS    (0xFF)
#define FNIC_FC_RO_INFO        (0x1F)

/* Little Endian */
#define FNIC_UNASSIGNED_OXID	(0xffff)
#define FNIC_UNASSIGNED_RXID	(0xffff)
#define FNIC_ELS_REQ_FCTL      (0x000029)
#define FNIC_ELS_REP_FCTL      (0x000099)

#define FNIC_FCP_RSP_FCTL      (0x000099)
#define FNIC_REQ_ABTS_FCTL     (0x000009)

#define FNIC_FC_PH_VER_HI      (0x20)
#define FNIC_FC_PH_VER_LO      (0x20)
#define FNIC_FC_PH_VER         (0x2020)
#define FNIC_FC_B2B_CREDIT     (0x0A)
#define FNIC_FC_B2B_RDF_SZ     (0x0800)

#define FNIC_LOGI_RDF_SIZE(_logi) ((_logi).fl_csp.sp_bb_data)
#define FNIC_LOGI_R_A_TOV(_logi) ((_logi).fl_csp.sp_r_a_tov)
#define FNIC_LOGI_E_D_TOV(_logi) ((_logi).fl_csp.sp_e_d_tov)
#define FNIC_LOGI_FEATURES(_logi) (be16_to_cpu((_logi).fl_csp.sp_features))
#define FNIC_LOGI_PORT_NAME(_logi) ((_logi).fl_wwpn)
#define FNIC_LOGI_NODE_NAME(_logi) ((_logi).fl_wwnn)

#define FNIC_LOGI_SET_RDF_SIZE(_logi, _rdf_size) \
	(FNIC_LOGI_RDF_SIZE(_logi) = cpu_to_be16(_rdf_size))
#define FNIC_LOGI_SET_E_D_TOV(_logi, _e_d_tov) \
	(FNIC_LOGI_E_D_TOV(_logi) = cpu_to_be32(_e_d_tov))
#define FNIC_LOGI_SET_R_A_TOV(_logi, _r_a_tov) \
	(FNIC_LOGI_R_A_TOV(_logi) = cpu_to_be32(_r_a_tov))

#define FNIC_STD_SET_S_ID(_fchdr, _sid)        memcpy((_fchdr).fh_s_id, _sid, 3)
#define FNIC_STD_SET_D_ID(_fchdr, _did)        memcpy((_fchdr).fh_d_id, _did, 3)
#define FNIC_STD_SET_OX_ID(_fchdr, _oxid)      ((_fchdr).fh_ox_id = cpu_to_be16(_oxid))
#define FNIC_STD_SET_RX_ID(_fchdr, _rxid)      ((_fchdr).fh_rx_id = cpu_to_be16(_rxid))

#define FNIC_STD_SET_R_CTL(_fchdr, _rctl)	((_fchdr).fh_r_ctl = _rctl)
#define FNIC_STD_SET_TYPE(_fchdr, _type)	((_fchdr).fh_type = _type)
#define FNIC_STD_SET_F_CTL(_fchdr, _fctl) \
	put_unaligned_be24(_fctl, &((_fchdr).fh_f_ctl))

#define FNIC_STD_SET_NPORT_NAME(_ptr, _wwpn)	put_unaligned_be64(_wwpn, _ptr)
#define FNIC_STD_SET_NODE_NAME(_ptr, _wwnn)	put_unaligned_be64(_wwnn, _ptr)
#define FNIC_STD_SET_PORT_ID(__req, __portid) \
	memcpy(__req.fr_fid.fp_fid, __portid, 3)
#define FNIC_STD_SET_PORT_NAME(_req, _pName) \
	(put_unaligned_be64(_pName, &_req.fr_wwn))

#define FNIC_STD_GET_OX_ID(_fchdr)		(be16_to_cpu((_fchdr)->fh_ox_id))
#define FNIC_STD_GET_RX_ID(_fchdr)		(be16_to_cpu((_fchdr)->fh_rx_id))
#define FNIC_STD_GET_S_ID(_fchdr)		((_fchdr)->fh_s_id)
#define FNIC_STD_GET_D_ID(_fchdr)		((_fchdr)->fh_d_id)
#define FNIC_STD_GET_TYPE(_fchdr)		((_fchdr)->fh_type)
#define FNIC_STD_GET_F_CTL(_fchdr)		((_fchdr)->fh_f_ctl)
#define FNIC_STD_GET_R_CTL(_fchdr)		((_fchdr)->fh_r_ctl)

#define FNIC_STD_GET_FC_CT_CMD(__fcct_hdr)  (be16_to_cpu(__fcct_hdr->ct_cmd))

#define FNIC_FCOE_MAX_FRAME_SZ  (2048)
#define FNIC_FCOE_MIN_FRAME_SZ  (280)
#define FNIC_FC_MAX_PAYLOAD_LEN (2048)
#define FNIC_MIN_DATA_FIELD_SIZE  (256)

#define FNIC_FC_EDTOV_NSEC    (0x400)
#define FNIC_NSEC_TO_MSEC     (0x1000000)
#define FCP_PRLI_FUNC_TARGET	(0x0010)

#define FNIC_FC_R_CTL_SOLICITED_DATA			(0x21)
#define FNIC_FC_F_CTL_LAST_END_SEQ				(0x98)
#define FNIC_FC_F_CTL_LAST_END_SEQ_INT			(0x99)
#define FNIC_FC_F_CTL_FIRST_LAST_SEQINIT		(0x29)
#define FNIC_FC_R_CTL_FC4_SCTL					(0x03)
#define FNIC_FC_CS_CTL							(0x00)

#define FNIC_FC_FRAME_UNSOLICITED(_fchdr)				\
		(_fchdr->fh_r_ctl == FC_RCTL_ELS_REQ)
#define FNIC_FC_FRAME_SOLICITED_DATA(_fchdr)			\
		(_fchdr->fh_r_ctl == FNIC_FC_R_CTL_SOLICITED_DATA)
#define FNIC_FC_FRAME_SOLICITED_CTRL_REPLY(_fchdr)		\
		(_fchdr->fh_r_ctl == FC_RCTL_ELS_REP)
#define FNIC_FC_FRAME_FCTL_LAST_END_SEQ(_fchdr)			\
		(_fchdr->fh_f_ctl[0] == FNIC_FC_F_CTL_LAST_END_SEQ)
#define FNIC_FC_FRAME_FCTL_LAST_END_SEQ_INT(_fchdr)		\
		(_fchdr->fh_f_ctl[0] == FNIC_FC_F_CTL_LAST_END_SEQ_INT)
#define FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(_fchdr)	\
		(_fchdr->fh_f_ctl[0] == FNIC_FC_F_CTL_FIRST_LAST_SEQINIT)
#define FNIC_FC_FRAME_FC4_SCTL(_fchdr)					\
		(_fchdr->fh_r_ctl == FNIC_FC_R_CTL_FC4_SCTL)
#define FNIC_FC_FRAME_TYPE_BLS(_fchdr) (_fchdr->fh_type == FC_TYPE_BLS)
#define FNIC_FC_FRAME_TYPE_ELS(_fchdr) (_fchdr->fh_type == FC_TYPE_ELS)
#define FNIC_FC_FRAME_TYPE_FC_GS(_fchdr) (_fchdr->fh_type == FC_TYPE_CT)
#define FNIC_FC_FRAME_CS_CTL(_fchdr) (_fchdr->fh_cs_ctl == FNIC_FC_CS_CTL)

#define FNIC_FC_C3_RDF         (0xfff)
#define FNIC_FC_PLOGI_RSP_RDF(_plogi_rsp) \
	(min(_plogi_rsp->u.csp_plogi.b2b_rdf_size, \
	(_plogi_rsp->spc3[4] & FNIC_FC_C3_RDF)))
#define FNIC_FC_PLOGI_RSP_CONCUR_SEQ(_plogi_rsp) \
	(min((uint16_t) (be16_to_cpu(_plogi_rsp->els.fl_csp.sp_tot_seq)), \
	 (uint16_t) (be16_to_cpu(_plogi_rsp->els.fl_cssp[2].cp_con_seq) & 0xff)))

/* FLOGI/PLOGI struct */
struct fc_std_flogi {
	struct fc_frame_header fchdr;
	struct fc_els_flogi els;
} __packed;

struct fc_std_els_acc_rsp {
	struct fc_frame_header fchdr;
	struct fc_els_ls_acc acc;
} __packed;

struct fc_std_els_rjt_rsp {
	struct fc_frame_header fchdr;
	struct fc_els_ls_rjt rej;
} __packed;

struct fc_std_els_adisc {
	struct fc_frame_header fchdr;
	struct fc_els_adisc els;
} __packed;

struct fc_std_rls_acc {
	struct fc_frame_header fchdr;
	struct fc_els_rls_resp els;
} __packed;

struct fc_std_abts_ba_acc {
	struct fc_frame_header fchdr;
	struct fc_ba_acc acc;
} __packed;

struct fc_std_abts_ba_rjt {
	struct fc_frame_header fchdr;
	struct fc_ba_rjt rjt;
} __packed;

struct fc_std_els_prli {
	struct fc_frame_header fchdr;
	struct fc_els_prli els_prli;
	struct fc_els_spp sp;
}	 __packed;

struct fc_std_rpn_id {
	struct fc_frame_header fchdr;
	struct fc_ct_hdr fc_std_ct_hdr;
	struct fc_ns_rn_id rpn_id;
} __packed;

struct fc_std_fdmi_rhba {
	struct fc_frame_header fchdr;
	struct fc_ct_hdr fc_std_ct_hdr;
	struct fc_fdmi_rhba rhba;
} __packed;

struct fc_std_fdmi_rpa {
	struct fc_frame_header fchdr;
	struct fc_ct_hdr fc_std_ct_hdr;
	struct fc_fdmi_rpa rpa;
}	 __packed;

struct fc_std_rft_id {
	struct fc_frame_header fchdr;
	struct fc_ct_hdr fc_std_ct_hdr;
	struct fc_ns_rft_id rft_id;
} __packed;

struct fc_std_rff_id {
	struct fc_frame_header fchdr;
	struct fc_ct_hdr fc_std_ct_hdr;
	struct fc_ns_rff_id rff_id;
} __packed;

struct fc_std_gpn_ft {
	struct fc_frame_header fchdr;
	struct fc_ct_hdr fc_std_ct_hdr;
	struct fc_ns_gid_ft gpn_ft;
} __packed;

/* Accept CT_IU	for	GPN_FT	*/
struct fc_gpn_ft_rsp_iu {
	uint8_t		ctrl;
	uint8_t		fcid[3];
	uint32_t	rsvd;
	__be64		wwpn;
} __packed;

struct fc_std_rls {
	struct fc_frame_header fchdr;
	struct fc_els_rls els;
} __packed;

struct fc_std_scr {
	struct fc_frame_header fchdr;
	struct fc_els_scr scr;
} __packed;

struct fc_std_rscn {
	struct fc_frame_header fchdr;
	struct fc_els_rscn els;
} __packed;

struct fc_std_logo {
	struct fc_frame_header fchdr;
	struct fc_els_logo els;
} __packed;

#define	FNIC_ETH_FCOE_HDRS_OFFSET	\
	(sizeof(struct ethhdr) + sizeof(struct fcoe_hdr))

#endif	/*	_FDLS_FC_H	*/
+1005 −0

File added.

Preview size limit exceeded, changes collapsed.

+159 −0
Original line number Diff line number Diff line
/* 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"
#include "fnic_fdls.h"
#include <scsi/fc/fc_fip.h>

/* Drop the cast from the standard definition */
#define FCOE_ALL_FCFS_MAC {0x01, 0x10, 0x18, 0x01, 0x00, 0x02}
#define FCOE_MAX_SIZE 0x082E

#define FCOE_CTLR_FIPVLAN_TOV (3*1000)
#define FCOE_CTLR_FCS_TOV     (3*1000)
#define FCOE_CTLR_MAX_SOL      (5*1000)

#define FIP_DISC_SOL_LEN (6)
#define FIP_VLAN_REQ_LEN (2)
#define FIP_ENODE_KA_LEN (2)
#define FIP_VN_KA_LEN (7)
#define FIP_FLOGI_LEN (38)

enum fdls_vlan_state {
	FIP_VLAN_AVAIL,
	FIP_VLAN_SENT
};

enum fdls_fip_state {
	FDLS_FIP_INIT,
	FDLS_FIP_VLAN_DISCOVERY_STARTED,
	FDLS_FIP_FCF_DISCOVERY_STARTED,
	FDLS_FIP_FLOGI_STARTED,
	FDLS_FIP_FLOGI_COMPLETE,
};

/*
 * 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 */
};

struct fip_vlan_req {
	struct ethhdr eth;
	struct fip_header fip;
	struct fip_mac_desc mac_desc;
} __packed;

struct fip_vlan_notif {
	struct fip_header fip;
	struct fip_vlan_desc vlans_desc[];
} __packed;

struct fip_vn_port_ka {
	struct ethhdr eth;
	struct fip_header fip;
	struct fip_mac_desc mac_desc;
	struct fip_vn_desc vn_port_desc;
} __packed;

struct fip_enode_ka {
	struct ethhdr eth;
	struct fip_header fip;
	struct fip_mac_desc mac_desc;
} __packed;

struct fip_cvl {
	struct fip_header fip;
	struct fip_mac_desc fcf_mac_desc;
	struct fip_wwn_desc name_desc;
	struct fip_vn_desc vn_ports_desc[];
} __packed;

struct fip_flogi_desc {
	struct fip_desc fd_desc;
	uint16_t rsvd;
	struct fc_std_flogi flogi;
} __packed;

struct fip_flogi_rsp_desc {
	struct fip_desc fd_desc;
	uint16_t rsvd;
	struct fc_std_flogi flogi;
} __packed;

struct fip_flogi {
	struct ethhdr eth;
	struct fip_header fip;
	struct fip_flogi_desc flogi_desc;
	struct fip_mac_desc mac_desc;
} __packed;

struct fip_flogi_rsp {
	struct fip_header fip;
	struct fip_flogi_rsp_desc rsp_desc;
	struct fip_mac_desc mac_desc;
} __packed;

struct fip_discovery {
	struct ethhdr eth;
	struct fip_header fip;
	struct fip_mac_desc mac_desc;
	struct fip_wwn_desc name_desc;
	struct fip_size_desc fcoe_desc;
} __packed;

struct fip_disc_adv {
	struct fip_header fip;
	struct fip_pri_desc prio_desc;
	struct fip_mac_desc mac_desc;
	struct fip_wwn_desc name_desc;
	struct fip_fab_desc fabric_desc;
	struct fip_fka_desc fka_adv_desc;
} __packed;

void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct fip_header *fiph);
void fnic_fcoe_fip_discovery_resp(struct fnic *fnic, struct fip_header *fiph);
void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *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 *fiph);
void fnic_vlan_discovery_timeout(struct fnic *fnic);

extern struct workqueue_struct *fnic_fip_queue;

#ifdef FNIC_DEBUG
static inline void
fnic_debug_dump_fip_frame(struct fnic *fnic, struct ethhdr *eth,
				int len, char *pfx)
{
	struct fip_header *fiph = (struct fip_header *)(eth + 1);
	u16 op = be16_to_cpu(fiph->fip_op);
	u8 sub = fiph->fip_subcode;

	FNIC_FCS_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
		"FIP %s packet contents: op: 0x%x sub: 0x%x (len = %d)",
		pfx, op, sub, len);

	fnic_debug_dump(fnic, (uint8_t *)eth, len);
}

#else /* FNIC_DEBUG */

static inline void
fnic_debug_dump_fip_frame(struct fnic *fnic, struct ethhdr *eth,
				int len, char *pfx) {}
#endif /* FNIC_DEBUG */

#endif	/* _FIP_H_ */
Loading