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

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

[SCSI] bfa: Added Fabric Assigned Address(FAA) support



- Updated/added data structures and definitions to support FAA protocol.
- Modified the IOC state machine to support FAA.
- Introduced FAA feature configuration - enable/disable/query.

Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 5a0adaed
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -241,6 +241,31 @@ struct bfa_hwif_s {
};
typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);

struct bfa_faa_cbfn_s {
	bfa_cb_iocfc_t	faa_cbfn;
	void		*faa_cbarg;
};

#define BFA_FAA_ENABLED		1
#define BFA_FAA_DISABLED	2

/*
 *	FAA attributes
 */
struct bfa_faa_attr_s {
	wwn_t	faa;
	u8	faa_state;
	u8	pwwn_source;
	u8	rsvd[6];
};

struct bfa_faa_args_s {
	struct bfa_faa_attr_s	*faa_attr;
	struct bfa_faa_cbfn_s	faa_cb;
	u8			faa_state;
	bfa_boolean_t		busy;
};

struct bfa_iocfc_s {
	struct bfa_s		*bfa;
	struct bfa_iocfc_cfg_s	cfg;
@@ -266,6 +291,7 @@ struct bfa_iocfc_s {
	bfa_cb_iocfc_t		updateq_cbfn; /*  bios callback function */
	void			*updateq_cbarg;	/*  bios callback arg */
	u32	intr_mask;
	struct bfa_faa_args_s	faa_args;
};

#define bfa_lpuid(__bfa)						\
+192 −0
Original line number Diff line number Diff line
@@ -795,6 +795,181 @@ bfa_iocfc_reset_queues(struct bfa_s *bfa)
	}
}

/* Fabric Assigned Address specific functions */

/*
 *	Check whether IOC is ready before sending command down
 */
static bfa_status_t
bfa_faa_validate_request(struct bfa_s *bfa)
{
	enum bfa_ioc_type_e	ioc_type = bfa_get_type(bfa);
	u32	card_type = bfa->ioc.attr->card_type;

	if (bfa_ioc_is_operational(&bfa->ioc)) {
		if ((ioc_type != BFA_IOC_TYPE_FC) || bfa_mfg_is_mezz(card_type))
			return BFA_STATUS_FEATURE_NOT_SUPPORTED;
	} else {
		if (!bfa_ioc_is_acq_addr(&bfa->ioc))
			return BFA_STATUS_IOC_NON_OP;
	}

	return BFA_STATUS_OK;
}

bfa_status_t
bfa_faa_enable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn, void *cbarg)
{
	struct bfi_faa_en_dis_s faa_enable_req;
	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
	bfa_status_t		status;

	iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
	iocfc->faa_args.faa_cb.faa_cbarg = cbarg;

	status = bfa_faa_validate_request(bfa);
	if (status != BFA_STATUS_OK)
		return status;

	if (iocfc->faa_args.busy == BFA_TRUE)
		return BFA_STATUS_DEVBUSY;

	if (iocfc->faa_args.faa_state == BFA_FAA_ENABLED)
		return BFA_STATUS_FAA_ENABLED;

	if (bfa_fcport_is_trunk_enabled(bfa))
		return BFA_STATUS_ERROR_TRUNK_ENABLED;

	bfa_fcport_cfg_faa(bfa, BFA_FAA_ENABLED);
	iocfc->faa_args.busy = BFA_TRUE;

	memset(&faa_enable_req, 0, sizeof(struct bfi_faa_en_dis_s));
	bfi_h2i_set(faa_enable_req.mh, BFI_MC_IOCFC,
		BFI_IOCFC_H2I_FAA_ENABLE_REQ, bfa_lpuid(bfa));

	bfa_ioc_mbox_send(&bfa->ioc, &faa_enable_req,
			sizeof(struct bfi_faa_en_dis_s));

	return BFA_STATUS_OK;
}

bfa_status_t
bfa_faa_disable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn,
		void *cbarg)
{
	struct bfi_faa_en_dis_s faa_disable_req;
	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
	bfa_status_t		status;

	iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
	iocfc->faa_args.faa_cb.faa_cbarg = cbarg;

	status = bfa_faa_validate_request(bfa);
	if (status != BFA_STATUS_OK)
		return status;

	if (iocfc->faa_args.busy == BFA_TRUE)
		return BFA_STATUS_DEVBUSY;

	if (iocfc->faa_args.faa_state == BFA_FAA_DISABLED)
		return BFA_STATUS_FAA_DISABLED;

	bfa_fcport_cfg_faa(bfa, BFA_FAA_DISABLED);
	iocfc->faa_args.busy = BFA_TRUE;

	memset(&faa_disable_req, 0, sizeof(struct bfi_faa_en_dis_s));
	bfi_h2i_set(faa_disable_req.mh, BFI_MC_IOCFC,
		BFI_IOCFC_H2I_FAA_DISABLE_REQ, bfa_lpuid(bfa));

	bfa_ioc_mbox_send(&bfa->ioc, &faa_disable_req,
		sizeof(struct bfi_faa_en_dis_s));

	return BFA_STATUS_OK;
}

bfa_status_t
bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
		bfa_cb_iocfc_t cbfn, void *cbarg)
{
	struct bfi_faa_query_s  faa_attr_req;
	struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
	bfa_status_t            status;

	iocfc->faa_args.faa_attr = attr;
	iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
	iocfc->faa_args.faa_cb.faa_cbarg = cbarg;

	status = bfa_faa_validate_request(bfa);
	if (status != BFA_STATUS_OK)
		return status;

	if (iocfc->faa_args.busy == BFA_TRUE)
		return BFA_STATUS_DEVBUSY;

	iocfc->faa_args.busy = BFA_TRUE;
	memset(&faa_attr_req, 0, sizeof(struct bfi_faa_query_s));
	bfi_h2i_set(faa_attr_req.mh, BFI_MC_IOCFC,
		BFI_IOCFC_H2I_FAA_QUERY_REQ, bfa_lpuid(bfa));

	bfa_ioc_mbox_send(&bfa->ioc, &faa_attr_req,
		sizeof(struct bfi_faa_query_s));

	return BFA_STATUS_OK;
}

/*
 *	FAA enable response
 */
static void
bfa_faa_enable_reply(struct bfa_iocfc_s *iocfc,
		struct bfi_faa_en_dis_rsp_s *rsp)
{
	void	*cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
	bfa_status_t	status = rsp->status;

	WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);

	iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
	iocfc->faa_args.busy = BFA_FALSE;
}

/*
 *	FAA disable response
 */
static void
bfa_faa_disable_reply(struct bfa_iocfc_s *iocfc,
		struct bfi_faa_en_dis_rsp_s *rsp)
{
	void	*cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
	bfa_status_t	status = rsp->status;

	WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);

	iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
	iocfc->faa_args.busy = BFA_FALSE;
}

/*
 *	FAA query response
 */
static void
bfa_faa_query_reply(struct bfa_iocfc_s *iocfc,
		bfi_faa_query_rsp_t *rsp)
{
	void	*cbarg = iocfc->faa_args.faa_cb.faa_cbarg;

	if (iocfc->faa_args.faa_attr) {
		iocfc->faa_args.faa_attr->faa = rsp->faa;
		iocfc->faa_args.faa_attr->faa_state = rsp->faa_status;
		iocfc->faa_args.faa_attr->pwwn_source = rsp->addr_source;
	}

	WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);

	iocfc->faa_args.faa_cb.faa_cbfn(cbarg, BFA_STATUS_OK);
	iocfc->faa_args.busy = BFA_FALSE;
}

/*
 * IOC enable request is complete
 */
@@ -803,6 +978,12 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
{
	struct bfa_s	*bfa = bfa_arg;

	if (status == BFA_STATUS_FAA_ACQ_ADDR) {
		bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
				bfa_iocfc_init_cb, bfa);
		return;
	}

	if (status != BFA_STATUS_OK) {
		bfa_isr_disable(bfa);
		if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
@@ -968,6 +1149,17 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
	case BFI_IOCFC_I2H_UPDATEQ_RSP:
		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
		break;
	case BFI_IOCFC_I2H_FAA_ENABLE_RSP:
		bfa_faa_enable_reply(iocfc,
			(struct bfi_faa_en_dis_rsp_s *)msg);
		break;
	case BFI_IOCFC_I2H_FAA_DISABLE_RSP:
		bfa_faa_disable_reply(iocfc,
			(struct bfi_faa_en_dis_rsp_s *)msg);
		break;
	case BFI_IOCFC_I2H_FAA_QUERY_RSP:
		bfa_faa_query_reply(iocfc, (bfi_faa_query_rsp_t *)msg);
		break;
	default:
		WARN_ON(1);
	}
+9 −4
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ enum bfa_status {
	BFA_STATUS_IOC_FAILURE	= 56,	/* IOC failure - Retry, if persists
					 * contact support */
	BFA_STATUS_INVALID_WWN	= 57,	/*  Invalid WWN */
	BFA_STATUS_IOC_NON_OP   = 61,	/* IOC is not operational */
	BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */
	BFA_STATUS_DIAG_BUSY	= 71,	/*  diag busy */
	BFA_STATUS_ENOFSAVE	= 78,	/*  No saved firmware trace */
@@ -157,6 +158,12 @@ enum bfa_status {
	BFA_STATUS_TRUNK_DISABLED  = 165, /* Trunking is disabled on
					   * the adapter */
	BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
	BFA_STATUS_FEATURE_NOT_SUPPORTED = 192,	/* Feature not supported */
	BFA_STATUS_FAA_ENABLED = 197,	/* FAA is already enabled */
	BFA_STATUS_FAA_DISABLED = 198,	/* FAA is already disabled */
	BFA_STATUS_FAA_ACQUIRED = 199,	/* FAA is already acquired */
	BFA_STATUS_FAA_ACQ_ADDR = 200,	/* Acquiring addr */
	BFA_STATUS_ERROR_TRUNK_ENABLED = 203,	/* Trunk enabled on adapter */
	BFA_STATUS_MAX_VAL		/* Unknown error code */
};
#define bfa_status_t enum bfa_status
@@ -275,6 +282,7 @@ enum bfa_ioc_state {
	BFA_IOC_FWMISMATCH	= 11,	/*  IOC f/w different from drivers */
	BFA_IOC_ENABLING	= 12,	/*  IOC is being enabled */
	BFA_IOC_HWFAIL		= 13,	/*  PCI mapping doesn't exist */
	BFA_IOC_ACQ_ADDR	= 14,	/*  Acquiring addr from fabric */
};

/*
@@ -455,10 +463,7 @@ enum bfa_port_speed {
	BFA_PORT_SPEED_8GBPS	= 8,
	BFA_PORT_SPEED_10GBPS	= 10,
	BFA_PORT_SPEED_16GBPS	= 16,
	BFA_PORT_SPEED_AUTO =
		(BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
		 BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS |
		 BFA_PORT_SPEED_16GBPS),
	BFA_PORT_SPEED_AUTO	= 0xf,
};
#define bfa_port_speed_t enum bfa_port_speed

+3 −1
Original line number Diff line number Diff line
@@ -635,6 +635,7 @@ enum bfa_port_states {
	BFA_PORT_ST_FWMISMATCH		= 12,
	BFA_PORT_ST_PREBOOT_DISABLED	= 13,
	BFA_PORT_ST_TOGGLING_QWAIT	= 14,
	BFA_PORT_ST_ACQ_ADDR		= 15,
	BFA_PORT_ST_MAX_STATE,
};

@@ -748,7 +749,8 @@ struct bfa_port_cfg_s {
	u8	 ratelimit;	/*  ratelimit enabled or not	*/
	u8	 trl_def_speed;	/*  ratelimit default speed	*/
	u8	bb_scn;
	u8	rsvd[3];
	u8	faa_state;	/*  FAA enabled/disabled        */
	u8	rsvd[2];
	u16 path_tov;	/*  device path timeout	*/
	u16 q_depth;	/*  SCSI Queue depth		*/
};
+66 −1
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ enum ioc_event {
	IOC_E_HWERROR		= 10,	/*  hardware error interrupt	*/
	IOC_E_TIMEOUT		= 11,	/*  timeout			*/
	IOC_E_HWFAILED		= 12,	/*  PCI mapping failure notice	*/
	IOC_E_FWRSP_ACQ_ADDR	= 13,	/*  Acquiring address		*/
};

bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
@@ -125,6 +126,7 @@ bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, acq_addr, struct bfa_ioc_s, enum ioc_event);

static struct bfa_sm_table_s ioc_sm_table[] = {
	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -137,6 +139,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
	{BFA_SM(bfa_ioc_sm_acq_addr), BFA_IOC_ACQ_ADDR},
};

/*
@@ -368,10 +371,16 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
	case IOC_E_FWRSP_GETATTR:
		bfa_ioc_timer_stop(ioc);
		bfa_ioc_check_attr_wwns(ioc);
		bfa_ioc_hb_monitor(ioc);
		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
		break;

	case IOC_E_FWRSP_ACQ_ADDR:
		bfa_ioc_timer_stop(ioc);
		bfa_ioc_hb_monitor(ioc);
		bfa_fsm_set_state(ioc, bfa_ioc_sm_acq_addr);
		break;

	case IOC_E_PFFAILED:
	case IOC_E_HWERROR:
		bfa_ioc_timer_stop(ioc);
@@ -396,6 +405,50 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
	}
}

/*
 * Acquiring address from fabric (entry function)
 */
static void
bfa_ioc_sm_acq_addr_entry(struct bfa_ioc_s *ioc)
{
}

/*
 *	Acquiring address from the fabric
 */
static void
bfa_ioc_sm_acq_addr(struct bfa_ioc_s *ioc, enum ioc_event event)
{
	bfa_trc(ioc, event);

	switch (event) {
	case IOC_E_FWRSP_GETATTR:
		bfa_ioc_check_attr_wwns(ioc);
		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
		break;

	case IOC_E_PFFAILED:
	case IOC_E_HWERROR:
		bfa_hb_timer_stop(ioc);
	case IOC_E_HBFAIL:
		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
		if (event != IOC_E_PFFAILED)
			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
		break;

	case IOC_E_DISABLE:
		bfa_hb_timer_stop(ioc);
		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
		break;

	case IOC_E_ENABLE:
		break;

	default:
		bfa_sm_fault(ioc, event);
	}
}

static void
bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
@@ -404,7 +457,6 @@ bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)

	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
	bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
	bfa_ioc_hb_monitor(ioc);
	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
}

@@ -2065,6 +2117,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
		bfa_ioc_getattr_reply(ioc);
		break;

	case BFI_IOC_I2H_ACQ_ADDR_REPLY:
		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ACQ_ADDR);
		break;

	default:
		bfa_trc(ioc, msg->mh.msg_id);
		WARN_ON(1);
@@ -2359,6 +2415,15 @@ bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
}

/*
 * Return TRUE if IOC is in acquiring address state
 */
bfa_boolean_t
bfa_ioc_is_acq_addr(struct bfa_ioc_s *ioc)
{
	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_acq_addr);
}

/*
 * return true if IOC firmware is different.
 */
Loading