Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7826f304 authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley
Browse files

[SCSI] bfa: Add FC-transport based Asynchronous Event Notification support.



- Added support to post vendor unique events on fc_host.
- Supports adapter, port, ioc, flash and remote port based AEN events.

Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent a53becc9
Loading
Loading
Loading
Loading
+143 −0
Original line number Diff line number Diff line
@@ -164,6 +164,8 @@ enum bfa_status {
	BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
	BFA_STATUS_PBC		= 154, /*  Operation not allowed for pre-boot
					*  configuration */
	BFA_STATUS_BAD_FWCFG = 156,	/* Bad firmware configuration */
	BFA_STATUS_INVALID_VENDOR = 158, /* Invalid switch vendor */
	BFA_STATUS_SFP_NOT_READY = 159,	/* SFP info is not ready. Retry */
	BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
					 * this adapter */
@@ -358,6 +360,139 @@ struct bfa_ioc_attr_s {
	u8				rsvd[4];	/*  64bit align	*/
};

/*
 *			AEN related definitions
 */
enum bfa_aen_category {
	BFA_AEN_CAT_ADAPTER	= 1,
	BFA_AEN_CAT_PORT	= 2,
	BFA_AEN_CAT_LPORT	= 3,
	BFA_AEN_CAT_RPORT	= 4,
	BFA_AEN_CAT_ITNIM	= 5,
	BFA_AEN_CAT_AUDIT	= 8,
	BFA_AEN_CAT_IOC		= 9,
};

/* BFA adapter level events */
enum bfa_adapter_aen_event {
	BFA_ADAPTER_AEN_ADD	= 1,	/* New Adapter found event */
	BFA_ADAPTER_AEN_REMOVE	= 2,	/* Adapter removed event */
};

struct bfa_adapter_aen_data_s {
	char	serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
	u32	nports; /* Number of NPorts */
	wwn_t	pwwn;   /* WWN of one of its physical port */
};

/* BFA physical port Level events */
enum bfa_port_aen_event {
	BFA_PORT_AEN_ONLINE	= 1,    /* Physical Port online event */
	BFA_PORT_AEN_OFFLINE	= 2,    /* Physical Port offline event */
	BFA_PORT_AEN_RLIR	= 3,    /* RLIR event, not supported */
	BFA_PORT_AEN_SFP_INSERT	= 4,    /* SFP inserted event */
	BFA_PORT_AEN_SFP_REMOVE	= 5,    /* SFP removed event */
	BFA_PORT_AEN_SFP_POM	= 6,    /* SFP POM event */
	BFA_PORT_AEN_ENABLE	= 7,    /* Physical Port enable event */
	BFA_PORT_AEN_DISABLE	= 8,    /* Physical Port disable event */
	BFA_PORT_AEN_AUTH_ON	= 9,    /* Physical Port auth success event */
	BFA_PORT_AEN_AUTH_OFF	= 10,   /* Physical Port auth fail event */
	BFA_PORT_AEN_DISCONNECT	= 11,   /* Physical Port disconnect event */
	BFA_PORT_AEN_QOS_NEG	= 12,   /* Base Port QOS negotiation event */
	BFA_PORT_AEN_FABRIC_NAME_CHANGE	= 13, /* Fabric Name/WWN change */
	BFA_PORT_AEN_SFP_ACCESS_ERROR	= 14, /* SFP read error event */
	BFA_PORT_AEN_SFP_UNSUPPORT	= 15, /* Unsupported SFP event */
};

enum bfa_port_aen_sfp_pom {
	BFA_PORT_AEN_SFP_POM_GREEN = 1, /* Normal */
	BFA_PORT_AEN_SFP_POM_AMBER = 2, /* Warning */
	BFA_PORT_AEN_SFP_POM_RED   = 3, /* Critical */
	BFA_PORT_AEN_SFP_POM_MAX   = BFA_PORT_AEN_SFP_POM_RED
};

struct bfa_port_aen_data_s {
	wwn_t		pwwn;		/* WWN of the physical port */
	wwn_t		fwwn;		/* WWN of the fabric port */
	u32		phy_port_num;	/* For SFP related events */
	u16		ioc_type;
	u16		level;		/* Only transitions will be informed */
	mac_t		mac;		/* MAC address of the ethernet port */
	u16		rsvd;
};

/* BFA AEN logical port events */
enum bfa_lport_aen_event {
	BFA_LPORT_AEN_NEW	= 1,		/* LPort created event */
	BFA_LPORT_AEN_DELETE	= 2,		/* LPort deleted event */
	BFA_LPORT_AEN_ONLINE	= 3,		/* LPort online event */
	BFA_LPORT_AEN_OFFLINE	= 4,		/* LPort offline event */
	BFA_LPORT_AEN_DISCONNECT = 5,		/* LPort disconnect event */
	BFA_LPORT_AEN_NEW_PROP	= 6,		/* VPort created event */
	BFA_LPORT_AEN_DELETE_PROP = 7,		/* VPort deleted event */
	BFA_LPORT_AEN_NEW_STANDARD = 8,		/* VPort created event */
	BFA_LPORT_AEN_DELETE_STANDARD = 9,	/* VPort deleted event */
	BFA_LPORT_AEN_NPIV_DUP_WWN = 10,	/* VPort with duplicate WWN */
	BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11,	/* Max NPIV in fabric/fport */
	BFA_LPORT_AEN_NPIV_UNKNOWN = 12,	/* Unknown NPIV Error code */
};

struct bfa_lport_aen_data_s {
	u16	vf_id;	/* vf_id of this logical port */
	u16	roles;	/* Logical port mode,IM/TM/IP etc */
	u32	rsvd;
	wwn_t	ppwwn;	/* WWN of its physical port */
	wwn_t	lpwwn;	/* WWN of this logical port */
};

/* BFA ITNIM events */
enum bfa_itnim_aen_event {
	BFA_ITNIM_AEN_ONLINE	 = 1,	/* Target online */
	BFA_ITNIM_AEN_OFFLINE	 = 2,	/* Target offline */
	BFA_ITNIM_AEN_DISCONNECT = 3,	/* Target disconnected */
};

struct bfa_itnim_aen_data_s {
	u16		vf_id;		/* vf_id of the IT nexus */
	u16		rsvd[3];
	wwn_t		ppwwn;		/* WWN of its physical port */
	wwn_t		lpwwn;		/* WWN of logical port */
	wwn_t		rpwwn;		/* WWN of remote(target) port */
};

/* BFA audit events */
enum bfa_audit_aen_event {
	BFA_AUDIT_AEN_AUTH_ENABLE	= 1,
	BFA_AUDIT_AEN_AUTH_DISABLE	= 2,
	BFA_AUDIT_AEN_FLASH_ERASE	= 3,
	BFA_AUDIT_AEN_FLASH_UPDATE	= 4,
};

struct bfa_audit_aen_data_s {
	wwn_t	pwwn;
	int	partition_inst;
	int	partition_type;
};

/* BFA IOC level events */
enum bfa_ioc_aen_event {
	BFA_IOC_AEN_HBGOOD  = 1,	/* Heart Beat restore event	*/
	BFA_IOC_AEN_HBFAIL  = 2,	/* Heart Beat failure event	*/
	BFA_IOC_AEN_ENABLE  = 3,	/* IOC enabled event		*/
	BFA_IOC_AEN_DISABLE = 4,	/* IOC disabled event		*/
	BFA_IOC_AEN_FWMISMATCH  = 5,	/* IOC firmware mismatch	*/
	BFA_IOC_AEN_FWCFG_ERROR = 6,	/* IOC firmware config error	*/
	BFA_IOC_AEN_INVALID_VENDOR = 7,
	BFA_IOC_AEN_INVALID_NWWN = 8,	/* Zero NWWN			*/
	BFA_IOC_AEN_INVALID_PWWN = 9	/* Zero PWWN			*/
};

struct bfa_ioc_aen_data_s {
	wwn_t	pwwn;
	u16	ioc_type;
	mac_t	mac;
};

/*
 * ---------------------- mfg definitions ------------
 */
@@ -587,6 +722,14 @@ struct bfa_ablk_cfg_s {
 */
#define SFP_DIAGMON_SIZE	10 /* num bytes of diag monitor data */

/* SFP state change notification event */
#define BFA_SFP_SCN_REMOVED	0
#define BFA_SFP_SCN_INSERTED	1
#define BFA_SFP_SCN_POM		2
#define BFA_SFP_SCN_FAILED	3
#define BFA_SFP_SCN_UNSUPPORT	4
#define BFA_SFP_SCN_VALID	5

enum bfa_defs_sfp_media_e {
	BFA_SFP_MEDIA_UNKNOWN	= 0x00,
	BFA_SFP_MEDIA_CU	= 0x01,
+48 −0
Original line number Diff line number Diff line
@@ -1228,4 +1228,52 @@ struct bfa_cee_stats_s {

#pragma pack()

/*
 *			AEN related definitions
 */
#define BFAD_NL_VENDOR_ID (((u64)0x01 << SCSI_NL_VID_TYPE_SHIFT) \
			   | BFA_PCI_VENDOR_ID_BROCADE)

/* BFA remote port events */
enum bfa_rport_aen_event {
	BFA_RPORT_AEN_ONLINE     = 1,   /* RPort online event */
	BFA_RPORT_AEN_OFFLINE    = 2,   /* RPort offline event */
	BFA_RPORT_AEN_DISCONNECT = 3,   /* RPort disconnect event */
	BFA_RPORT_AEN_QOS_PRIO   = 4,   /* QOS priority change event */
	BFA_RPORT_AEN_QOS_FLOWID = 5,   /* QOS flow Id change event */
};

struct bfa_rport_aen_data_s {
	u16             vf_id;  /* vf_id of this logical port */
	u16             rsvd[3];
	wwn_t           ppwwn;  /* WWN of its physical port */
	wwn_t           lpwwn;  /* WWN of this logical port */
	wwn_t           rpwwn;  /* WWN of this remote port */
	union {
		struct bfa_rport_qos_attr_s qos;
	} priv;
};

union bfa_aen_data_u {
	struct bfa_adapter_aen_data_s	adapter;
	struct bfa_port_aen_data_s	port;
	struct bfa_lport_aen_data_s	lport;
	struct bfa_rport_aen_data_s	rport;
	struct bfa_itnim_aen_data_s	itnim;
	struct bfa_audit_aen_data_s	audit;
	struct bfa_ioc_aen_data_s	ioc;
};

#define BFA_AEN_MAX_ENTRY	512

struct bfa_aen_entry_s {
	struct list_head	qe;
	enum bfa_aen_category   aen_category;
	u32                     aen_type;
	union bfa_aen_data_u    aen_data;
	struct timeval          aen_tv;
	u32                     seq_num;
	u32                     bfad_num;
};

#endif /* __BFA_DEFS_SVC_H__ */
+26 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
 */

#include "bfad_drv.h"
#include "bfad_im.h"
#include "bfa_fcs.h"
#include "bfa_fcbuild.h"

@@ -1327,6 +1328,29 @@ bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
	bfa_trc(fabric->fcs, status);
}


/*
 * Send AEN notification
 */
static void
bfa_fcs_fabric_aen_post(struct bfa_fcs_lport_s *port,
			enum bfa_port_aen_event event)
{
	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
	struct bfa_aen_entry_s  *aen_entry;

	bfad_get_aen_entry(bfad, aen_entry);
	if (!aen_entry)
		return;

	aen_entry->aen_data.port.pwwn = bfa_fcs_lport_get_pwwn(port);
	aen_entry->aen_data.port.fwwn = bfa_fcs_lport_get_fabric_name(port);

	/* Send the AEN notification */
	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
				  BFA_AEN_CAT_PORT, event);
}

/*
 *
 * @param[in] fabric - fabric
@@ -1358,6 +1382,8 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
		BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
			"Base port WWN = %s Fabric WWN = %s\n",
			pwwn_ptr, fwwn_ptr);
		bfa_fcs_fabric_aen_post(&fabric->bport,
				BFA_PORT_AEN_FABRIC_NAME_CHANGE);
	}
}

+1 −0
Original line number Diff line number Diff line
@@ -675,6 +675,7 @@ struct bfa_fcs_s {
	struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */
	struct bfa_fcs_stats_s	stats;	/*  FCS statistics */
	struct bfa_wc_s		wc;	/*  waiting counter */
	int			fcs_aen_seq;
};

/*
+35 −2
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ static void bfa_fcs_itnim_prli_response(void *fcsarg,
			 struct bfa_fcxp_s *fcxp, void *cbarg,
			    bfa_status_t req_status, u32 rsp_len,
			    u32 resid_len, struct fchs_s *rsp_fchs);
static void	bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
			enum bfa_itnim_aen_event event);

/*
 *  fcs_itnim_sm FCS itnim state machine events
@@ -269,6 +271,7 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
		"Target (WWN = %s) is online for initiator (WWN = %s)\n",
		rpwwn_buf, lpwwn_buf);
		bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
		break;

	case BFA_FCS_ITNIM_SM_OFFLINE:
@@ -305,14 +308,17 @@ bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
		bfa_itnim_offline(itnim->bfa_itnim);
		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
		wwn2str(rpwwn_buf, itnim->rport->pwwn);
		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) {
			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
			"Target (WWN = %s) connectivity lost for "
			"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
		else
			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
		} else {
			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
			"Target (WWN = %s) offlined by initiator (WWN = %s)\n",
			rpwwn_buf, lpwwn_buf);
			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
		}
		break;

	case BFA_FCS_ITNIM_SM_DELETE:
@@ -381,6 +387,33 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
	}
}

static void
bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
			enum bfa_itnim_aen_event event)
{
	struct bfa_fcs_rport_s *rport = itnim->rport;
	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
	struct bfa_aen_entry_s	*aen_entry;

	/* Don't post events for well known addresses */
	if (BFA_FCS_PID_IS_WKA(rport->pid))
		return;

	bfad_get_aen_entry(bfad, aen_entry);
	if (!aen_entry)
		return;

	aen_entry->aen_data.itnim.vf_id = rport->port->fabric->vf_id;
	aen_entry->aen_data.itnim.ppwwn = bfa_fcs_lport_get_pwwn(
					bfa_fcs_get_base_port(itnim->fcs));
	aen_entry->aen_data.itnim.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
	aen_entry->aen_data.itnim.rpwwn = rport->pwwn;

	/* Send the AEN notification */
	bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
				  BFA_AEN_CAT_ITNIM, event);
}

static void
bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
{
Loading