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

[SCSI] bfa: Add diagnostic port (D-Port) support



- Introduced support for D-Port which is a new port mode during which
  link level diagnostics can be run.
- Provided mechanism to dynamically configure D-Port and initiate diagnostic
  tests to isolate any link level issues.
- In D-Port mode, the HBA port does not participate in fabric or login to the
  remote device or run data traffic.
- Diagnostic tests include running various loopback tests in conjunction with
  the attached device.

Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 1306e31d
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ enum bfa_status {
	BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
	BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
	BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
	BFA_STATUS_CMD_NOTSUPP_CNA = 146, /* Command not supported for CNA */
	BFA_STATUS_PBC		= 154, /*  Operation not allowed for pre-boot
					*  configuration */
	BFA_STATUS_BAD_FWCFG = 156,	/* Bad firmware configuration */
@@ -189,6 +190,10 @@ enum bfa_status {
	BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */
	BFA_STATUS_LOOP_UNSUPP_MEZZ = 231, /* Loop topology is not supported
					    * on mezz cards */
	BFA_STATUS_DPORT_ENABLED = 235, /* D-port mode is already enabled */
	BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */
	BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */
	BFA_STATUS_DPORT_ERR = 245,	/* D-port mode is enabled */
	BFA_STATUS_MAX_VAL		/* Unknown error code */
};
#define bfa_status_t enum bfa_status
@@ -507,6 +512,17 @@ struct bfa_ioc_aen_data_s {
	mac_t	mac;
};

/*
 *	D-port states
 *
*/
enum bfa_dport_state {
	BFA_DPORT_ST_DISABLED	= 0,	/* D-port is Disabled */
	BFA_DPORT_ST_DISABLING	= 1,	/* D-port is Disabling */
	BFA_DPORT_ST_ENABLING	= 2,	/* D-port is Enabling */
	BFA_DPORT_ST_ENABLED	= 3,	/* D-port is Enabled */
};

/*
 * ---------------------- mfg definitions ------------
 */
+1 −0
Original line number Diff line number Diff line
@@ -722,6 +722,7 @@ enum bfa_port_states {
	BFA_PORT_ST_PREBOOT_DISABLED	= 13,
	BFA_PORT_ST_TOGGLING_QWAIT	= 14,
	BFA_PORT_ST_ACQ_ADDR		= 15,
	BFA_PORT_ST_DPORT		= 16,
	BFA_PORT_ST_MAX_STATE,
};

+32 −0
Original line number Diff line number Diff line
@@ -250,6 +250,12 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
		return BFA_STATUS_IOC_FAILURE;
	}

	/* if port is d-port enabled, return error */
	if (port->dport_enabled) {
		bfa_trc(port, BFA_STATUS_DPORT_ERR);
		return BFA_STATUS_DPORT_ERR;
	}

	if (port->endis_pending) {
		bfa_trc(port, BFA_STATUS_DEVBUSY);
		return BFA_STATUS_DEVBUSY;
@@ -300,6 +306,12 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
		return BFA_STATUS_IOC_FAILURE;
	}

	/* if port is d-port enabled, return error */
	if (port->dport_enabled) {
		bfa_trc(port, BFA_STATUS_DPORT_ERR);
		return BFA_STATUS_DPORT_ERR;
	}

	if (port->endis_pending) {
		bfa_trc(port, BFA_STATUS_DEVBUSY);
		return BFA_STATUS_DEVBUSY;
@@ -431,6 +443,10 @@ bfa_port_notify(void *arg, enum bfa_ioc_event_e event)
			port->endis_cbfn = NULL;
			port->endis_pending = BFA_FALSE;
		}

		/* clear D-port mode */
		if (port->dport_enabled)
			bfa_port_set_dportenabled(port, BFA_FALSE);
		break;
	default:
		break;
@@ -467,6 +483,7 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
	port->stats_cbfn = NULL;
	port->endis_cbfn = NULL;
	port->pbc_disabled = BFA_FALSE;
	port->dport_enabled = BFA_FALSE;

	bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
	bfa_q_qe_init(&port->ioc_notify);
@@ -482,6 +499,21 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
	bfa_trc(port, 0);
}

/*
 * bfa_port_set_dportenabled();
 *
 * Port module- set pbc disabled flag
 *
 * @param[in] port - Pointer to the Port module data structure
 *
 * @return void
 */
void
bfa_port_set_dportenabled(struct bfa_port_s *port, bfa_boolean_t enabled)
{
	port->dport_enabled = enabled;
}

/*
 *	CEE module specific definitions
 */
+3 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct bfa_port_s {
	bfa_status_t			endis_status;
	struct bfa_ioc_notify_s		ioc_notify;
	bfa_boolean_t			pbc_disabled;
	bfa_boolean_t			dport_enabled;
	struct bfa_mem_dma_s		port_dma;
};

@@ -66,6 +67,8 @@ bfa_status_t bfa_port_disable(struct bfa_port_s *port,
u32     bfa_port_meminfo(void);
void	     bfa_port_mem_claim(struct bfa_port_s *port,
				 u8 *dma_kva, u64 dma_pa);
void	bfa_port_set_dportenabled(struct bfa_port_s *port,
				  bfa_boolean_t enabled);

/*
 * CEE declaration
+502 −3
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ enum bfa_fcport_sm_event {
	BFA_FCPORT_SM_LINKDOWN	= 7,	/*  firmware linkup down	*/
	BFA_FCPORT_SM_QRESUME	= 8,	/*  CQ space available	*/
	BFA_FCPORT_SM_HWFAIL	= 9,	/*  IOC h/w failure		*/
	BFA_FCPORT_SM_DPORTENABLE = 10, /*  enable dport      */
	BFA_FCPORT_SM_DPORTDISABLE = 11,/*  disable dport     */
};

/*
@@ -197,6 +199,8 @@ static void bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
					enum bfa_fcport_sm_event event);
static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
					enum bfa_fcport_sm_event event);
static void	bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
					enum bfa_fcport_sm_event event);

static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
					enum bfa_fcport_ln_sm_event event);
@@ -226,6 +230,7 @@ static struct bfa_sm_table_s hal_port_sm_table[] = {
	{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
	{BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
};


@@ -2606,6 +2611,10 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
		break;

	case BFA_FCPORT_SM_DPORTENABLE:
		bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
		break;

	default:
		bfa_sm_fault(fcport->bfa, event);
	}
@@ -2686,6 +2695,38 @@ bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
	}
}

static void
bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
{
	bfa_trc(fcport->bfa, event);

	switch (event) {
	case BFA_FCPORT_SM_DPORTENABLE:
	case BFA_FCPORT_SM_DISABLE:
	case BFA_FCPORT_SM_ENABLE:
	case BFA_FCPORT_SM_START:
		/*
		 * Ignore event for a port that is dport
		 */
		break;

	case BFA_FCPORT_SM_STOP:
		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
		break;

	case BFA_FCPORT_SM_HWFAIL:
		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
		break;

	case BFA_FCPORT_SM_DPORTDISABLE:
		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
		break;

	default:
		bfa_sm_fault(fcport->bfa, event);
	}
}

/*
 * Link state is down
 */
@@ -3707,6 +3748,8 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
			return BFA_STATUS_UNSUPP_SPEED;
		if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
			return BFA_STATUS_LOOP_UNSUPP_MEZZ;
		if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
			return BFA_STATUS_DPORT_ERR;
		break;

	case BFA_PORT_TOPOLOGY_AUTO:
@@ -3962,6 +4005,15 @@ bfa_fcport_is_disabled(struct bfa_s *bfa)

}

bfa_boolean_t
bfa_fcport_is_dport(struct bfa_s *bfa)
{
	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);

	return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
		BFA_PORT_ST_DPORT);
}

bfa_boolean_t
bfa_fcport_is_ratelim(struct bfa_s *bfa)
{
@@ -4039,6 +4091,26 @@ bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
	return fcport->cfg.trunked;
}

void
bfa_fcport_dportenable(struct bfa_s *bfa)
{
	/*
	 * Assume caller check for port is in disable state
	 */
	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
	bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
}

void
bfa_fcport_dportdisable(struct bfa_s *bfa)
{
	/*
	 * Assume caller check for port is in disable state
	 */
	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
	bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
}

/*
 * Rport State machine functions
 */
@@ -5420,6 +5492,37 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
	}
}

/*
 *	Dport forward declaration
 */

/*
 * BFA DPORT state machine events
 */
enum bfa_dport_sm_event {
	BFA_DPORT_SM_ENABLE	= 1,	/* dport enable event         */
	BFA_DPORT_SM_DISABLE    = 2,    /* dport disable event        */
	BFA_DPORT_SM_FWRSP      = 3,    /* fw enable/disable rsp      */
	BFA_DPORT_SM_QRESUME    = 4,    /* CQ space available         */
	BFA_DPORT_SM_HWFAIL     = 5,    /* IOC h/w failure            */
};

static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
				  enum bfa_dport_sm_event event);
static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
				  enum bfa_dport_sm_event event);
static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
				  enum bfa_dport_sm_event event);
static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
				 enum bfa_dport_sm_event event);
static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
				 enum bfa_dport_sm_event event);
static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
				   enum bfa_dport_sm_event event);
static void bfa_dport_qresume(void *cbarg);
static void bfa_dport_req_comp(struct bfa_dport_s *dport,
			       bfi_diag_dport_rsp_t *msg);

/*
 *	BFA fcdiag module
 */
@@ -5450,15 +5553,24 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
		struct bfa_pcidev_s *pcidev)
{
	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
	struct bfa_dport_s  *dport = &fcdiag->dport;

	fcdiag->bfa             = bfa;
	fcdiag->trcmod  = bfa->trcmod;
	/* The common DIAG attach bfa_diag_attach() will do all memory claim */
	dport->bfa = bfa;
	bfa_sm_set_state(dport, bfa_dport_sm_disabled);
	bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
	dport->cbfn = NULL;
	dport->cbarg = NULL;
}

static void
bfa_fcdiag_iocdisable(struct bfa_s *bfa)
{
	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
	struct bfa_dport_s *dport = &fcdiag->dport;

	bfa_trc(fcdiag, fcdiag->lb.lock);
	if (fcdiag->lb.lock) {
		fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
@@ -5466,6 +5578,8 @@ bfa_fcdiag_iocdisable(struct bfa_s *bfa)
		fcdiag->lb.lock = 0;
		bfa_fcdiag_set_busy_status(fcdiag);
	}

	bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
}

static void
@@ -5650,6 +5764,9 @@ bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
	case BFI_DIAG_I2H_QTEST:
		bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
		break;
	case BFI_DIAG_I2H_DPORT:
		bfa_dport_req_comp(&fcdiag->dport, (bfi_diag_dport_rsp_t *)msg);
		break;
	default:
		bfa_trc(fcdiag, msg->mhdr.msg_id);
		WARN_ON(1);
@@ -5719,12 +5836,18 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
		}
	}

	/*
	 * For CT2, 1G is not supported
	 */
	if ((speed == BFA_PORT_SPEED_1GBPS) &&
	    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
		bfa_trc(fcdiag, speed);
		return BFA_STATUS_UNSUPP_SPEED;
	}

	/* For Mezz card, port speed entered needs to be checked */
	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
		if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
			if ((speed == BFA_PORT_SPEED_1GBPS) &&
			    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
				return BFA_STATUS_UNSUPP_SPEED;
			if (!(speed == BFA_PORT_SPEED_1GBPS ||
			      speed == BFA_PORT_SPEED_2GBPS ||
			      speed == BFA_PORT_SPEED_4GBPS ||
@@ -5837,3 +5960,379 @@ bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
	return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
}

/*
 *	D-port
 */
static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
					enum bfi_dport_req req);
static void
bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
{
	if (dport->cbfn != NULL) {
		dport->cbfn(dport->cbarg, bfa_status);
		dport->cbfn = NULL;
		dport->cbarg = NULL;
	}
}

static void
bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
{
	bfa_trc(dport->bfa, event);

	switch (event) {
	case BFA_DPORT_SM_ENABLE:
		bfa_fcport_dportenable(dport->bfa);
		if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
			bfa_sm_set_state(dport, bfa_dport_sm_enabling);
		else
			bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
		break;

	case BFA_DPORT_SM_DISABLE:
		/* Already disabled */
		break;

	case BFA_DPORT_SM_HWFAIL:
		/* ignore */
		break;

	default:
		bfa_sm_fault(dport->bfa, event);
	}
}

static void
bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
			    enum bfa_dport_sm_event event)
{
	bfa_trc(dport->bfa, event);

	switch (event) {
	case BFA_DPORT_SM_QRESUME:
		bfa_sm_set_state(dport, bfa_dport_sm_enabling);
		bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
		break;

	case BFA_DPORT_SM_HWFAIL:
		bfa_reqq_wcancel(&dport->reqq_wait);
		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
		break;

	default:
		bfa_sm_fault(dport->bfa, event);
	}
}

static void
bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
{
	bfa_trc(dport->bfa, event);

	switch (event) {
	case BFA_DPORT_SM_FWRSP:
		bfa_sm_set_state(dport, bfa_dport_sm_enabled);
		break;

	case BFA_DPORT_SM_HWFAIL:
		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
		break;

	default:
		bfa_sm_fault(dport->bfa, event);
	}
}

static void
bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
{
	bfa_trc(dport->bfa, event);

	switch (event) {
	case BFA_DPORT_SM_ENABLE:
		/* Already enabled */
		break;

	case BFA_DPORT_SM_DISABLE:
		bfa_fcport_dportdisable(dport->bfa);
		if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
			bfa_sm_set_state(dport, bfa_dport_sm_disabling);
		else
			bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
		break;

	case BFA_DPORT_SM_HWFAIL:
		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
		break;

	default:
		bfa_sm_fault(dport->bfa, event);
	}
}

static void
bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
			     enum bfa_dport_sm_event event)
{
	bfa_trc(dport->bfa, event);

	switch (event) {
	case BFA_DPORT_SM_QRESUME:
		bfa_sm_set_state(dport, bfa_dport_sm_disabling);
		bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
		break;

	case BFA_DPORT_SM_HWFAIL:
		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
		bfa_reqq_wcancel(&dport->reqq_wait);
		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
		break;

	default:
		bfa_sm_fault(dport->bfa, event);
	}
}

static void
bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
{
	bfa_trc(dport->bfa, event);

	switch (event) {
	case BFA_DPORT_SM_FWRSP:
		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
		break;

	case BFA_DPORT_SM_HWFAIL:
		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
		break;

	default:
		bfa_sm_fault(dport->bfa, event);
	}
}


static bfa_boolean_t
bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
{
	struct bfi_diag_dport_req_s *m;

	/*
	 * Increment message tag before queue check, so that responses to old
	 * requests are discarded.
	 */
	dport->msgtag++;

	/*
	 * check for room in queue to send request now
	 */
	m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
	if (!m) {
		bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
		return BFA_FALSE;
	}

	bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
		    bfa_fn_lpu(dport->bfa));
	m->req  = req;
	m->msgtag = dport->msgtag;

	/*
	 * queue I/O message to firmware
	 */
	bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);

	return BFA_TRUE;
}

static void
bfa_dport_qresume(void *cbarg)
{
	struct bfa_dport_s *dport = cbarg;

	bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
}

static void
bfa_dport_req_comp(struct bfa_dport_s *dport, bfi_diag_dport_rsp_t *msg)
{
	bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
	bfa_cb_fcdiag_dport(dport, msg->status);
}

/*
 * Dport enable
 *
 * @param[in] *bfa            - bfa data struct
 */
bfa_status_t
bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
{
	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
	struct bfa_dport_s  *dport = &fcdiag->dport;

	/*
	 * Dport is not support in MEZZ card
	 */
	if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
		bfa_trc(dport->bfa, BFA_STATUS_PBC);
		return BFA_STATUS_CMD_NOTSUPP_MEZZ;
	}

	/*
	 * Check to see if IOC is down
	*/
	if (!bfa_iocfc_is_operational(bfa))
		return BFA_STATUS_IOC_NON_OP;

	/* if port is PBC disabled, return error */
	if (bfa_fcport_is_pbcdisabled(bfa)) {
		bfa_trc(dport->bfa, BFA_STATUS_PBC);
		return BFA_STATUS_PBC;
	}

	/*
	 * Check if port mode is FC port
	 */
	if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
		bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
		return BFA_STATUS_CMD_NOTSUPP_CNA;
	}

	/*
	 * Check if port is in LOOP mode
	 */
	if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
	    (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
		bfa_trc(dport->bfa, 0);
		return BFA_STATUS_TOPOLOGY_LOOP;
	}

	/*
	 * Check if port is TRUNK mode
	 */
	if (bfa_fcport_is_trunk_enabled(bfa)) {
		bfa_trc(dport->bfa, 0);
		return BFA_STATUS_ERROR_TRUNK_ENABLED;
	}

	/*
	 * Check to see if port is disable or in dport state
	 */
	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
		bfa_trc(dport->bfa, 0);
		return BFA_STATUS_PORT_NOT_DISABLED;
	}

	/*
	 * Check if dport is busy
	 */
	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
	    bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait)) {
		return BFA_STATUS_DEVBUSY;
	}

	/*
	 * Check if dport is already enabled
	 */
	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
		bfa_trc(dport->bfa, 0);
		return BFA_STATUS_DPORT_ENABLED;
	}

	dport->cbfn = cbfn;
	dport->cbarg = cbarg;

	bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
	return BFA_STATUS_OK;
}

/*
 *	Dport disable
 *
 *	@param[in] *bfa            - bfa data struct
 */
bfa_status_t
bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
{
	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
	struct bfa_dport_s *dport = &fcdiag->dport;

	if (bfa_ioc_is_disabled(&bfa->ioc))
		return BFA_STATUS_IOC_DISABLED;

	/* if port is PBC disabled, return error */
	if (bfa_fcport_is_pbcdisabled(bfa)) {
		bfa_trc(dport->bfa, BFA_STATUS_PBC);
		return BFA_STATUS_PBC;
	}

	/*
	 * Check to see if port is disable or in dport state
	 */
	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
		bfa_trc(dport->bfa, 0);
		return BFA_STATUS_PORT_NOT_DISABLED;
	}

	/*
	 * Check if dport is busy
	 */
	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
	    bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait))
		return BFA_STATUS_DEVBUSY;

	/*
	 * Check if dport is already disabled
	 */
	if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
		bfa_trc(dport->bfa, 0);
		return BFA_STATUS_DPORT_DISABLED;
	}

	dport->cbfn = cbfn;
	dport->cbarg = cbarg;

	bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
	return BFA_STATUS_OK;
}

/*
 *	Get D-port state
 *
 * @param[in] *bfa            - bfa data struct
 */

bfa_status_t
bfa_dport_get_state(struct bfa_s *bfa, enum bfa_dport_state *state)
{
	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
	struct bfa_dport_s *dport = &fcdiag->dport;

	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled))
		*state = BFA_DPORT_ST_ENABLED;
	else if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
		 bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait))
		*state = BFA_DPORT_ST_ENABLING;
	else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled))
		*state = BFA_DPORT_ST_DISABLED;
	else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
		 bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait))
		*state = BFA_DPORT_ST_DISABLING;
	else {
		bfa_trc(dport->bfa, BFA_STATUS_EINVAL);
		return BFA_STATUS_EINVAL;
	}
	return BFA_STATUS_OK;
}
Loading