Commit 1a898a79 authored by Vijaya Mohan Guvva's avatar Vijaya Mohan Guvva Committed by James Bottomley

[SCSI] bfa: Add dynamic diagnostic port support

D-Port is a new port type created with the intention of running link
level diagnostic tests like loopback, traffic test. In static D-port
mode, user configures the port to D-port mode and starts the test, but
in dynamic D-port, once the Brocade switch port is configured to
D-port, it will reject the regular FLOGI from HBA with reason that it is
in D-port mode. So based on the reason code HBA port will turn itself into
D-port and start diagnostic test.
Signed-off-by: default avatarSudarsana Reddy Kalluru <skalluru@brocade.com>
Signed-off-by: default avatarVijaya Mohan Guvva <vmohan@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 4e1e0d8d
...@@ -199,15 +199,34 @@ enum bfa_status { ...@@ -199,15 +199,34 @@ enum bfa_status {
BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */ 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_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */
BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */ BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */
BFA_STATUS_DPORT_NO_SFP = 243, /* SFP is not present.\n D-port will be
* enabled but it will be operational
* only after inserting a valid SFP. */
BFA_STATUS_DPORT_ERR = 245, /* D-port mode is enabled */ BFA_STATUS_DPORT_ERR = 245, /* D-port mode is enabled */
BFA_STATUS_DPORT_ENOSYS = 254, /* Switch has no D_Port functionality */
BFA_STATUS_DPORT_CANT_PERF = 255, /* Switch port is not D_Port capable
* or D_Port is disabled */
BFA_STATUS_DPORT_LOGICALERR = 256, /* Switch D_Port fail */
BFA_STATUS_DPORT_SWBUSY = 257, /* Switch port busy */
BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT = 258, /*!< BB credit recovery is BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT = 258, /*!< BB credit recovery is
* supported at max port speed alone */ * supported at max port speed alone */
BFA_STATUS_ERROR_BBCR_ENABLED = 259, /*!< BB credit recovery BFA_STATUS_ERROR_BBCR_ENABLED = 259, /*!< BB credit recovery
* is enabled */ * is enabled */
BFA_STATUS_INVALID_BBSCN = 260, /*!< Invalid BBSCN value. BFA_STATUS_INVALID_BBSCN = 260, /*!< Invalid BBSCN value.
* Valid range is [1-15] */ * Valid range is [1-15] */
BFA_STATUS_DDPORT_ERR = 261, /* Dynamic D_Port mode is active.\n To
* exit dynamic mode, disable D_Port on
* the remote port */
BFA_STATUS_DPORT_SFPWRAP_ERR = 262, /* Clear e/o_wrap fail, check or
* replace SFP */
BFA_STATUS_BBCR_CFG_NO_CHANGE = 265, /*!< BBCR is operational. BFA_STATUS_BBCR_CFG_NO_CHANGE = 265, /*!< BBCR is operational.
* Disable BBCR and try this operation again. */ * Disable BBCR and try this operation again. */
BFA_STATUS_DPORT_SW_NOTREADY = 268, /* Remote port is not ready to
* start dport test. Check remote
* port status. */
BFA_STATUS_DPORT_INV_SFP = 271, /* Invalid SFP for D-PORT mode. */
BFA_STATUS_DPORT_CMD_NOTSUPP = 273, /* Dport is not supported by
* remote port */
BFA_STATUS_MAX_VAL /* Unknown error code */ BFA_STATUS_MAX_VAL /* Unknown error code */
}; };
#define bfa_status_t enum bfa_status #define bfa_status_t enum bfa_status
...@@ -526,17 +545,6 @@ struct bfa_ioc_aen_data_s { ...@@ -526,17 +545,6 @@ struct bfa_ioc_aen_data_s {
mac_t mac; 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 ------------ * ---------------------- mfg definitions ------------
*/ */
...@@ -1136,6 +1144,7 @@ struct bfa_flash_attr_s { ...@@ -1136,6 +1144,7 @@ struct bfa_flash_attr_s {
#define LB_PATTERN_DEFAULT 0xB5B5B5B5 #define LB_PATTERN_DEFAULT 0xB5B5B5B5
#define QTEST_CNT_DEFAULT 10 #define QTEST_CNT_DEFAULT 10
#define QTEST_PAT_DEFAULT LB_PATTERN_DEFAULT #define QTEST_PAT_DEFAULT LB_PATTERN_DEFAULT
#define DPORT_ENABLE_LOOPCNT_DEFAULT (1024 * 1024)
struct bfa_diag_memtest_s { struct bfa_diag_memtest_s {
u8 algo; u8 algo;
...@@ -1164,6 +1173,54 @@ struct bfa_diag_loopback_result_s { ...@@ -1164,6 +1173,54 @@ struct bfa_diag_loopback_result_s {
u8 rsvd[3]; u8 rsvd[3];
}; };
enum bfa_diag_dport_test_status {
DPORT_TEST_ST_IDLE = 0, /* the test has not started yet. */
DPORT_TEST_ST_FINAL = 1, /* the test done successfully */
DPORT_TEST_ST_SKIP = 2, /* the test skipped */
DPORT_TEST_ST_FAIL = 3, /* the test failed */
DPORT_TEST_ST_INPRG = 4, /* the testing is in progress */
DPORT_TEST_ST_RESPONDER = 5, /* test triggered from remote port */
DPORT_TEST_ST_STOPPED = 6, /* the test stopped by user. */
DPORT_TEST_ST_MAX
};
enum bfa_diag_dport_test_type {
DPORT_TEST_ELOOP = 0,
DPORT_TEST_OLOOP = 1,
DPORT_TEST_ROLOOP = 2,
DPORT_TEST_LINK = 3,
DPORT_TEST_MAX
};
enum bfa_diag_dport_test_opmode {
BFA_DPORT_OPMODE_AUTO = 0,
BFA_DPORT_OPMODE_MANU = 1,
};
struct bfa_diag_dport_subtest_result_s {
u8 status; /* bfa_diag_dport_test_status */
u8 rsvd[7]; /* 64bit align */
u64 start_time; /* timestamp */
};
struct bfa_diag_dport_result_s {
wwn_t rp_pwwn; /* switch port wwn */
wwn_t rp_nwwn; /* switch node wwn */
u64 start_time; /* user/sw start time */
u64 end_time; /* timestamp */
u8 status; /* bfa_diag_dport_test_status */
u8 mode; /* bfa_diag_dport_test_opmode */
u8 rsvd; /* 64bit align */
u8 speed; /* link speed for buf_reqd */
u16 buffer_required;
u16 frmsz; /* frame size for buf_reqd */
u32 lpcnt; /* Frame count */
u32 pat; /* Pattern */
u32 roundtrip_latency; /* in nano sec */
u32 est_cable_distance; /* in meter */
struct bfa_diag_dport_subtest_result_s subtest[DPORT_TEST_MAX];
};
struct bfa_diag_ledtest_s { struct bfa_diag_ledtest_s {
u32 cmd; /* bfa_led_op_t */ u32 cmd; /* bfa_led_op_t */
u32 color; /* bfa_led_color_t */ u32 color; /* bfa_led_color_t */
......
...@@ -761,6 +761,7 @@ enum bfa_port_states { ...@@ -761,6 +761,7 @@ enum bfa_port_states {
BFA_PORT_ST_TOGGLING_QWAIT = 14, BFA_PORT_ST_TOGGLING_QWAIT = 14,
BFA_PORT_ST_FAA_MISCONFIG = 15, BFA_PORT_ST_FAA_MISCONFIG = 15,
BFA_PORT_ST_DPORT = 16, BFA_PORT_ST_DPORT = 16,
BFA_PORT_ST_DDPORT = 17,
BFA_PORT_ST_MAX_STATE, BFA_PORT_ST_MAX_STATE,
}; };
......
...@@ -70,6 +70,8 @@ enum bfa_fcport_sm_event { ...@@ -70,6 +70,8 @@ enum bfa_fcport_sm_event {
BFA_FCPORT_SM_DPORTENABLE = 10, /* enable dport */ BFA_FCPORT_SM_DPORTENABLE = 10, /* enable dport */
BFA_FCPORT_SM_DPORTDISABLE = 11,/* disable dport */ BFA_FCPORT_SM_DPORTDISABLE = 11,/* disable dport */
BFA_FCPORT_SM_FAA_MISCONFIG = 12, /* FAA misconfiguratin */ BFA_FCPORT_SM_FAA_MISCONFIG = 12, /* FAA misconfiguratin */
BFA_FCPORT_SM_DDPORTENABLE = 13, /* enable ddport */
BFA_FCPORT_SM_DDPORTDISABLE = 14, /* disable ddport */
}; };
/* /*
...@@ -202,6 +204,8 @@ static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport, ...@@ -202,6 +204,8 @@ static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event); enum bfa_fcport_sm_event event);
static void bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, static void bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event); enum bfa_fcport_sm_event event);
static void bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event);
static void bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport, static void bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event); enum bfa_fcport_sm_event event);
...@@ -234,6 +238,7 @@ static struct bfa_sm_table_s hal_port_sm_table[] = { ...@@ -234,6 +238,7 @@ static struct bfa_sm_table_s hal_port_sm_table[] = {
{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN}, {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_iocfail), BFA_PORT_ST_IOCDOWN},
{BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT}, {BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
{BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},
{BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG}, {BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
}; };
...@@ -2646,6 +2651,10 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport, ...@@ -2646,6 +2651,10 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
bfa_sm_set_state(fcport, bfa_fcport_sm_dport); bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
break; break;
case BFA_FCPORT_SM_DDPORTENABLE:
bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
break;
default: default:
bfa_sm_fault(fcport->bfa, event); bfa_sm_fault(fcport->bfa, event);
} }
...@@ -2758,6 +2767,40 @@ bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event) ...@@ -2758,6 +2767,40 @@ bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
} }
} }
static void
bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event)
{
bfa_trc(fcport->bfa, event);
switch (event) {
case BFA_FCPORT_SM_DISABLE:
case BFA_FCPORT_SM_DDPORTDISABLE:
bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
break;
case BFA_FCPORT_SM_DPORTENABLE:
case BFA_FCPORT_SM_DPORTDISABLE:
case BFA_FCPORT_SM_ENABLE:
case BFA_FCPORT_SM_START:
/**
* Ignore event for a port that is ddport
*/
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;
default:
bfa_sm_fault(fcport->bfa, event);
}
}
static void static void
bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport, bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event) enum bfa_fcport_sm_event event)
...@@ -3860,6 +3903,8 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology) ...@@ -3860,6 +3903,8 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
return BFA_STATUS_LOOP_UNSUPP_MEZZ; return BFA_STATUS_LOOP_UNSUPP_MEZZ;
if (bfa_fcport_is_dport(bfa) != BFA_FALSE) if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
return BFA_STATUS_DPORT_ERR; return BFA_STATUS_DPORT_ERR;
if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
return BFA_STATUS_DPORT_ERR;
break; break;
case BFA_PORT_TOPOLOGY_AUTO: case BFA_PORT_TOPOLOGY_AUTO:
...@@ -4127,6 +4172,15 @@ bfa_fcport_is_dport(struct bfa_s *bfa) ...@@ -4127,6 +4172,15 @@ bfa_fcport_is_dport(struct bfa_s *bfa)
BFA_PORT_ST_DPORT); BFA_PORT_ST_DPORT);
} }
bfa_boolean_t
bfa_fcport_is_ddport(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_DDPORT);
}
bfa_status_t bfa_status_t
bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw) bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
{ {
...@@ -4320,6 +4374,24 @@ bfa_fcport_dportdisable(struct bfa_s *bfa) ...@@ -4320,6 +4374,24 @@ bfa_fcport_dportdisable(struct bfa_s *bfa)
bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE); bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
} }
void
bfa_fcport_ddportenable(struct bfa_s *bfa)
{
/*
* Assume caller check for port is in disable state
*/
bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
}
void
bfa_fcport_ddportdisable(struct bfa_s *bfa)
{
/*
* Assume caller check for port is in disable state
*/
bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
}
/* /*
* Rport State machine functions * Rport State machine functions
*/ */
...@@ -5705,6 +5777,14 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw) ...@@ -5705,6 +5777,14 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
* Dport forward declaration * Dport forward declaration
*/ */
enum bfa_dport_test_state_e {
BFA_DPORT_ST_DISABLED = 0, /*!< dport is disabled */
BFA_DPORT_ST_INP = 1, /*!< test in progress */
BFA_DPORT_ST_COMP = 2, /*!< test complete successfully */
BFA_DPORT_ST_NO_SFP = 3, /*!< sfp is not present */
BFA_DPORT_ST_NOTSTART = 4, /*!< test not start dport is enabled */
};
/* /*
* BFA DPORT state machine events * BFA DPORT state machine events
*/ */
...@@ -5714,6 +5794,9 @@ enum bfa_dport_sm_event { ...@@ -5714,6 +5794,9 @@ enum bfa_dport_sm_event {
BFA_DPORT_SM_FWRSP = 3, /* fw enable/disable rsp */ BFA_DPORT_SM_FWRSP = 3, /* fw enable/disable rsp */
BFA_DPORT_SM_QRESUME = 4, /* CQ space available */ BFA_DPORT_SM_QRESUME = 4, /* CQ space available */
BFA_DPORT_SM_HWFAIL = 5, /* IOC h/w failure */ BFA_DPORT_SM_HWFAIL = 5, /* IOC h/w failure */
BFA_DPORT_SM_START = 6, /* re-start dport test */
BFA_DPORT_SM_REQFAIL = 7, /* request failure */
BFA_DPORT_SM_SCN = 8, /* state change notify frm fw */
}; };
static void bfa_dport_sm_disabled(struct bfa_dport_s *dport, static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
...@@ -5728,9 +5811,19 @@ static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport, ...@@ -5728,9 +5811,19 @@ static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event); enum bfa_dport_sm_event event);
static void bfa_dport_sm_disabling(struct bfa_dport_s *dport, static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event); enum bfa_dport_sm_event event);
static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event);
static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event);
static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event);
static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event);
static void bfa_dport_qresume(void *cbarg); static void bfa_dport_qresume(void *cbarg);
static void bfa_dport_req_comp(struct bfa_dport_s *dport, static void bfa_dport_req_comp(struct bfa_dport_s *dport,
bfi_diag_dport_rsp_t *msg); struct bfi_diag_dport_rsp_s *msg);
static void bfa_dport_scn(struct bfa_dport_s *dport,
struct bfi_diag_dport_scn_s *msg);
/* /*
* BFA fcdiag module * BFA fcdiag module
...@@ -5772,6 +5865,8 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, ...@@ -5772,6 +5865,8 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport); bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
dport->cbfn = NULL; dport->cbfn = NULL;
dport->cbarg = NULL; dport->cbarg = NULL;
dport->test_state = BFA_DPORT_ST_DISABLED;
memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
} }
static void static void
...@@ -5974,7 +6069,12 @@ bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg) ...@@ -5974,7 +6069,12 @@ bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg); bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
break; break;
case BFI_DIAG_I2H_DPORT: case BFI_DIAG_I2H_DPORT:
bfa_dport_req_comp(&fcdiag->dport, (bfi_diag_dport_rsp_t *)msg); bfa_dport_req_comp(&fcdiag->dport,
(struct bfi_diag_dport_rsp_s *)msg);
break;
case BFI_DIAG_I2H_DPORT_SCN:
bfa_dport_scn(&fcdiag->dport,
(struct bfi_diag_dport_scn_s *)msg);
break; break;
default: default:
bfa_trc(fcdiag, msg->mhdr.msg_id); bfa_trc(fcdiag, msg->mhdr.msg_id);
...@@ -6069,7 +6169,11 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode, ...@@ -6069,7 +6169,11 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
return BFA_STATUS_UNSUPP_SPEED; return BFA_STATUS_UNSUPP_SPEED;
} }
} }
/* check to see if fcport is dport */
if (bfa_fcport_is_dport(bfa)) {
bfa_trc(fcdiag, fcdiag->lb.lock);
return BFA_STATUS_DPORT_ENABLED;
}
/* check to see if there is another destructive diag cmd running */ /* check to see if there is another destructive diag cmd running */
if (fcdiag->lb.lock) { if (fcdiag->lb.lock) {
bfa_trc(fcdiag, fcdiag->lb.lock); bfa_trc(fcdiag, fcdiag->lb.lock);
...@@ -6173,6 +6277,15 @@ bfa_fcdiag_lb_is_running(struct bfa_s *bfa) ...@@ -6173,6 +6277,15 @@ bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
/* /*
* D-port * D-port
*/ */
#define bfa_dport_result_start(__dport, __mode) do { \
(__dport)->result.start_time = bfa_get_log_time(); \
(__dport)->result.status = DPORT_TEST_ST_INPRG; \
(__dport)->result.mode = (__mode); \
(__dport)->result.rp_pwwn = (__dport)->rp_pwwn; \
(__dport)->result.rp_nwwn = (__dport)->rp_nwwn; \
(__dport)->result.lpcnt = (__dport)->lpcnt; \
} while (0)
static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport, static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
enum bfi_dport_req req); enum bfi_dport_req req);
static void static void
...@@ -6207,6 +6320,18 @@ bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) ...@@ -6207,6 +6320,18 @@ bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
/* ignore */ /* ignore */
break; break;
case BFA_DPORT_SM_SCN:
if (dport->i2hmsg.scn.state == BFI_DPORT_SCN_DDPORT_ENABLE) {
bfa_fcport_ddportenable(dport->bfa);
dport->dynamic = BFA_TRUE;
dport->test_state = BFA_DPORT_ST_NOTSTART;
bfa_sm_set_state(dport, bfa_dport_sm_enabled);
} else {
bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
WARN_ON(1);
}
break;
default: default:
bfa_sm_fault(dport->bfa, event); bfa_sm_fault(dport->bfa, event);
} }
...@@ -6242,9 +6367,23 @@ bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) ...@@ -6242,9 +6367,23 @@ bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
switch (event) { switch (event) {
case BFA_DPORT_SM_FWRSP: case BFA_DPORT_SM_FWRSP:
memset(&dport->result, 0,
sizeof(struct bfa_diag_dport_result_s));
if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
dport->test_state = BFA_DPORT_ST_NO_SFP;
} else {
dport->test_state = BFA_DPORT_ST_INP;
bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
}
bfa_sm_set_state(dport, bfa_dport_sm_enabled); bfa_sm_set_state(dport, bfa_dport_sm_enabled);
break; break;
case BFA_DPORT_SM_REQFAIL:
dport->test_state = BFA_DPORT_ST_DISABLED;
bfa_fcport_dportdisable(dport->bfa);
bfa_sm_set_state(dport, bfa_dport_sm_disabled);
break;
case BFA_DPORT_SM_HWFAIL: case BFA_DPORT_SM_HWFAIL:
bfa_sm_set_state(dport, bfa_dport_sm_disabled); bfa_sm_set_state(dport, bfa_dport_sm_disabled);
bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
...@@ -6261,8 +6400,11 @@ bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) ...@@ -6261,8 +6400,11 @@ bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
bfa_trc(dport->bfa, event); bfa_trc(dport->bfa, event);
switch (event) { switch (event) {
case BFA_DPORT_SM_ENABLE: case BFA_DPORT_SM_START:
/* Already enabled */ if (bfa_dport_send_req(dport, BFI_DPORT_START))
bfa_sm_set_state(dport, bfa_dport_sm_starting);
else
bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
break; break;
case BFA_DPORT_SM_DISABLE: case BFA_DPORT_SM_DISABLE:
...@@ -6277,6 +6419,48 @@ bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) ...@@ -6277,6 +6419,48 @@ bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
bfa_sm_set_state(dport, bfa_dport_sm_disabled); bfa_sm_set_state(dport, bfa_dport_sm_disabled);
break; break;
case BFA_DPORT_SM_SCN:
switch (dport->i2hmsg.scn.state) {
case BFI_DPORT_SCN_TESTCOMP:
dport->test_state = BFA_DPORT_ST_COMP;
break;
case BFI_DPORT_SCN_TESTSTART:
dport->test_state = BFA_DPORT_ST_INP;
break;
case BFI_DPORT_SCN_TESTSKIP:
case BFI_DPORT_SCN_SUBTESTSTART:
/* no state change */
break;
case BFI_DPORT_SCN_SFP_REMOVED:
dport->test_state = BFA_DPORT_ST_NO_SFP;
break;
case BFI_DPORT_SCN_DDPORT_DISABLE:
bfa_fcport_ddportdisable(dport->bfa);
if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
bfa_sm_set_state(dport,
bfa_dport_sm_dynamic_disabling);
else
bfa_sm_set_state(dport,
bfa_dport_sm_dynamic_disabling_qwait);
break;
case BFI_DPORT_SCN_FCPORT_DISABLE:
bfa_fcport_ddportdisable(dport->bfa);
bfa_sm_set_state(dport, bfa_dport_sm_disabled);
dport->dynamic = BFA_FALSE;
break;
default:
bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
bfa_sm_fault(dport->bfa, event);
}
break;
default: default:
bfa_sm_fault(dport->bfa, event); bfa_sm_fault(dport->bfa, event);
} }
...@@ -6300,6 +6484,10 @@ bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport, ...@@ -6300,6 +6484,10 @@ bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
break; break;
case BFA_DPORT_SM_SCN:
/* ignore */
break;
default: default:
bfa_sm_fault(dport->bfa, event); bfa_sm_fault(dport->bfa, event);
} }
...@@ -6312,7 +6500,98 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) ...@@ -6312,7 +6500,98 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
switch (event) { switch (event) {
case BFA_DPORT_SM_FWRSP: case BFA_DPORT_SM_FWRSP:
dport->test_state = BFA_DPORT_ST_DISABLED;
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_sm_set_state(dport, bfa_dport_sm_disabled);
bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
break;
case BFA_DPORT_SM_SCN:
/* no state change */
break;
default:
bfa_sm_fault(dport->bfa, event);
}
}
static void
bfa_dport_sm_starting_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_starting);
bfa_dport_send_req(dport, BFI_DPORT_START);
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_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
{
bfa_trc(dport->bfa, event);
switch (event) {
case BFA_DPORT_SM_FWRSP:
memset(&dport->result, 0,
sizeof(struct bfa_diag_dport_result_s));
if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
dport->test_state = BFA_DPORT_ST_NO_SFP;
} else {
dport->test_state = BFA_DPORT_ST_INP;
bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
}
/* fall thru */
case BFA_DPORT_SM_REQFAIL:
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_dynamic_disabling(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event)
{
bfa_trc(dport->bfa, event);
switch (event) {
case BFA_DPORT_SM_SCN:
switch (dport->i2hmsg.scn.state) {
case BFI_DPORT_SCN_DDPORT_DISABLED:
bfa_sm_set_state(dport, bfa_dport_sm_disabled);
dport->dynamic = BFA_FALSE;
bfa_fcport_enable(dport->bfa);
break;
default:
bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
bfa_sm_fault(dport->bfa, event);
}
break; break;
case BFA_DPORT_SM_HWFAIL: case BFA_DPORT_SM_HWFAIL:
...@@ -6325,18 +6604,38 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) ...@@ -6325,18 +6604,38 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
} }
} }
static void
bfa_dport_sm_dynamic_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_dynamic_disabling);
bfa_dport_send_req(dport, BFI_DPORT_DYN_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;
case BFA_DPORT_SM_SCN:
/* ignore */
break;
default:
bfa_sm_fault(dport->bfa, event);
}
}
static bfa_boolean_t static bfa_boolean_t
bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req) bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
{ {
struct bfi_diag_dport_req_s *m; 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 * check for room in queue to send request now
*/ */
...@@ -6349,7 +6648,10 @@ bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req) ...@@ -6349,7 +6648,10 @@ bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT, bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
bfa_fn_lpu(dport->bfa)); bfa_fn_lpu(dport->bfa));
m->req = req; m->req = req;
m->msgtag = dport->msgtag; if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
m->lpcnt = cpu_to_be32(dport->lpcnt);
m->payload = cpu_to_be32(dport->payload);
}
/* /*
* queue I/O message to firmware * queue I/O message to firmware
...@@ -6368,19 +6670,131 @@ bfa_dport_qresume(void *cbarg) ...@@ -6368,19 +6670,131 @@ bfa_dport_qresume(void *cbarg)
} }
static void static void
bfa_dport_req_comp(struct bfa_dport_s *dport, bfi_diag_dport_rsp_t *msg) bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
{ {
bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP); msg->status = cpu_to_be32(msg->status);
dport->i2hmsg.rsp.status = msg->status;
dport->rp_pwwn = msg->pwwn;
dport->rp_nwwn = msg->nwwn;
if ((msg->status == BFA_STATUS_OK) ||
(msg->status == BFA_STATUS_DPORT_NO_SFP)) {
bfa_trc(dport->bfa, msg->status);
bfa_trc(dport->bfa, dport->rp_pwwn);
bfa_trc(dport->bfa, dport->rp_nwwn);
bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
} else {
bfa_trc(dport->bfa, msg->status);
bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
}
bfa_cb_fcdiag_dport(dport, msg->status); bfa_cb_fcdiag_dport(dport, msg->status);
} }
static bfa_boolean_t
bfa_dport_is_sending_req(struct bfa_dport_s *dport)
{
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) ||
bfa_sm_cmp_state(dport, bfa_dport_sm_starting) ||
bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
return BFA_TRUE;
} else {
return BFA_FALSE;
}
}
static void
bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
{
int i;
uint8_t subtesttype;
bfa_trc(dport->bfa, msg->state);
dport->i2hmsg.scn.state = msg->state;
switch (dport->i2hmsg.scn.state) {
case BFI_DPORT_SCN_TESTCOMP:
dport->result.end_time = bfa_get_log_time();
bfa_trc(dport->bfa, dport->result.end_time);
dport->result.status = msg->info.testcomp.status;
bfa_trc(dport->bfa, dport->result.status);
dport->result.roundtrip_latency =
cpu_to_be32(msg->info.testcomp.latency);
dport->result.est_cable_distance =
cpu_to_be32(msg->info.testcomp.distance);
dport->result.buffer_required =
be16_to_cpu(msg->info.testcomp.numbuffer);
dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
dport->result.speed = msg->info.testcomp.speed;
bfa_trc(dport->bfa, dport->result.roundtrip_latency);
bfa_trc(dport->bfa, dport->result.est_cable_distance);
bfa_trc(dport->bfa, dport->result.buffer_required);
bfa_trc(dport->bfa, dport->result.frmsz);
bfa_trc(dport->bfa, dport->result.speed);
for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
dport->result.subtest[i].status =
msg->info.testcomp.subtest_status[i];
bfa_trc(dport->bfa, dport->result.subtest[i].status);
}
break;
case BFI_DPORT_SCN_TESTSKIP:
case BFI_DPORT_SCN_DDPORT_ENABLE:
memset(&dport->result, 0,
sizeof(struct bfa_diag_dport_result_s));
break;
case BFI_DPORT_SCN_TESTSTART:
memset(&dport->result, 0,
sizeof(struct bfa_diag_dport_result_s));
dport->rp_pwwn = msg->info.teststart.pwwn;
dport->rp_nwwn = msg->info.teststart.nwwn;
dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
break;
case BFI_DPORT_SCN_SUBTESTSTART:
subtesttype = msg->info.teststart.type;
dport->result.subtest[subtesttype].start_time =
bfa_get_log_time();
dport->result.subtest[subtesttype].status =
DPORT_TEST_ST_INPRG;
bfa_trc(dport->bfa, subtesttype);
bfa_trc(dport->bfa,
dport->result.subtest[subtesttype].start_time);
break;
case BFI_DPORT_SCN_SFP_REMOVED:
case BFI_DPORT_SCN_DDPORT_DISABLED:
case BFI_DPORT_SCN_DDPORT_DISABLE:
case BFI_DPORT_SCN_FCPORT_DISABLE:
dport->result.status = DPORT_TEST_ST_IDLE;
break;
default:
bfa_sm_fault(dport->bfa, msg->state);
}
bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
}
/* /*
* Dport enable * Dport enable
* *
* @param[in] *bfa - bfa data struct * @param[in] *bfa - bfa data struct
*/ */
bfa_status_t bfa_status_t
bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
bfa_cb_diag_t cbfn, void *cbarg)
{ {
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
struct bfa_dport_s *dport = &fcdiag->dport; struct bfa_dport_s *dport = &fcdiag->dport;
...@@ -6393,6 +6807,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) ...@@ -6393,6 +6807,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
return BFA_STATUS_CMD_NOTSUPP_MEZZ; return BFA_STATUS_CMD_NOTSUPP_MEZZ;
} }
/*
* Dport is supported in CT2 or above
*/
if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
return BFA_STATUS_FEATURE_NOT_SUPPORTED;
}
/* /*
* Check to see if IOC is down * Check to see if IOC is down
*/ */
...@@ -6430,6 +6852,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) ...@@ -6430,6 +6852,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
return BFA_STATUS_ERROR_TRUNK_ENABLED; return BFA_STATUS_ERROR_TRUNK_ENABLED;
} }
/*
* Check if diag loopback is running
*/
if (bfa_fcdiag_lb_is_running(bfa)) {
bfa_trc(dport->bfa, 0);
return BFA_STATUS_DIAG_BUSY;
}
/* /*
* Check to see if port is disable or in dport state * Check to see if port is disable or in dport state
*/ */
...@@ -6439,15 +6869,17 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) ...@@ -6439,15 +6869,17 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
return BFA_STATUS_PORT_NOT_DISABLED; return BFA_STATUS_PORT_NOT_DISABLED;
} }
/*
* Check if dport is in dynamic mode
*/
if (dport->dynamic)
return BFA_STATUS_DDPORT_ERR;
/* /*
* Check if dport is busy * Check if dport is busy
*/ */
if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) || if (bfa_dport_is_sending_req(dport))
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; return BFA_STATUS_DEVBUSY;
}
/* /*
* Check if dport is already enabled * Check if dport is already enabled
...@@ -6457,6 +6889,10 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) ...@@ -6457,6 +6889,10 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
return BFA_STATUS_DPORT_ENABLED; return BFA_STATUS_DPORT_ENABLED;
} }
bfa_trc(dport->bfa, lpcnt);
bfa_trc(dport->bfa, pat);
dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
dport->cbfn = cbfn; dport->cbfn = cbfn;
dport->cbarg = cbarg; dport->cbarg = cbarg;
...@@ -6484,6 +6920,13 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) ...@@ -6484,6 +6920,13 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
return BFA_STATUS_PBC; return BFA_STATUS_PBC;
} }
/*
* Check if dport is in dynamic mode
*/
if (dport->dynamic) {
return BFA_STATUS_DDPORT_ERR;
}
/* /*
* Check to see if port is disable or in dport state * Check to see if port is disable or in dport state
*/ */
...@@ -6496,10 +6939,7 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) ...@@ -6496,10 +6939,7 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
/* /*
* Check if dport is busy * Check if dport is busy
*/ */
if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) || if (bfa_dport_is_sending_req(dport))
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; return BFA_STATUS_DEVBUSY;
/* /*
...@@ -6518,30 +6958,105 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) ...@@ -6518,30 +6958,105 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
} }
/* /*
* Get D-port state * Dport start -- restart dport test
* *
* @param[in] *bfa - bfa data struct * @param[in] *bfa - bfa data struct
*/ */
bfa_status_t
bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
bfa_cb_diag_t cbfn, void *cbarg)
{
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
struct bfa_dport_s *dport = &fcdiag->dport;
/*
* Check to see if IOC is down
*/
if (!bfa_iocfc_is_operational(bfa))
return BFA_STATUS_IOC_NON_OP;
/*
* Check if dport is in dynamic mode
*/
if (dport->dynamic)
return BFA_STATUS_DDPORT_ERR;
/*
* Check if dport is busy
*/
if (bfa_dport_is_sending_req(dport))
return BFA_STATUS_DEVBUSY;
/*
* Check if dport is in enabled state.
* Test can only be restart when previous test has completed
*/
if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
bfa_trc(dport->bfa, 0);
return BFA_STATUS_DPORT_DISABLED;
} else {
if (dport->test_state == BFA_DPORT_ST_NO_SFP)
return BFA_STATUS_DPORT_INV_SFP;
if (dport->test_state == BFA_DPORT_ST_INP)
return BFA_STATUS_DEVBUSY;
WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
}
bfa_trc(dport->bfa, lpcnt);
bfa_trc(dport->bfa, pat);
dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
dport->cbfn = cbfn;
dport->cbarg = cbarg;
bfa_sm_send_event(dport, BFA_DPORT_SM_START);
return BFA_STATUS_OK;
}
/*
* Dport show -- return dport test result
*
* @param[in] *bfa - bfa data struct
*/
bfa_status_t bfa_status_t
bfa_dport_get_state(struct bfa_s *bfa, enum bfa_dport_state *state) bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
{ {
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
struct bfa_dport_s *dport = &fcdiag->dport; struct bfa_dport_s *dport = &fcdiag->dport;
if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) /*
*state = BFA_DPORT_ST_ENABLED; * Check to see if IOC is down
else if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) || */
bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait)) if (!bfa_iocfc_is_operational(bfa))
*state = BFA_DPORT_ST_ENABLING; return BFA_STATUS_IOC_NON_OP;
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) || * Check if dport is busy
bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait)) */
*state = BFA_DPORT_ST_DISABLING; if (bfa_dport_is_sending_req(dport))
else { return BFA_STATUS_DEVBUSY;
bfa_trc(dport->bfa, BFA_STATUS_EINVAL);
return BFA_STATUS_EINVAL; /*
* Check if dport is in enabled state.
*/
if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
bfa_trc(dport->bfa, 0);
return BFA_STATUS_DPORT_DISABLED;
} }
/*
* Check if there is SFP
*/
if (dport->test_state == BFA_DPORT_ST_NO_SFP)
return BFA_STATUS_DPORT_INV_SFP;
memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
return BFA_STATUS_OK; return BFA_STATUS_OK;
} }
...@@ -551,6 +551,7 @@ void bfa_fcport_event_register(struct bfa_s *bfa, ...@@ -551,6 +551,7 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
enum bfa_port_linkstate event), void *event_cbarg); enum bfa_port_linkstate event), void *event_cbarg);
bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa); bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
bfa_boolean_t bfa_fcport_is_dport(struct bfa_s *bfa); bfa_boolean_t bfa_fcport_is_dport(struct bfa_s *bfa);
bfa_boolean_t bfa_fcport_is_ddport(struct bfa_s *bfa);
bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa, bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa,
struct bfa_qos_bw_s *qos_bw); struct bfa_qos_bw_s *qos_bw);
enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa); enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
...@@ -715,10 +716,18 @@ struct bfa_fcdiag_lb_s { ...@@ -715,10 +716,18 @@ struct bfa_fcdiag_lb_s {
struct bfa_dport_s { struct bfa_dport_s {
struct bfa_s *bfa; /* Back pointer to BFA */ struct bfa_s *bfa; /* Back pointer to BFA */
bfa_sm_t sm; /* finite state machine */ bfa_sm_t sm; /* finite state machine */
u32 msgtag; /* firmware msg tag for reply */
struct bfa_reqq_wait_s reqq_wait; struct bfa_reqq_wait_s reqq_wait;
bfa_cb_diag_t cbfn; bfa_cb_diag_t cbfn;
void *cbarg; void *cbarg;
union bfi_diag_dport_msg_u i2hmsg;
u8 test_state; /* enum dport_test_state */
u8 dynamic; /* boolean_t */
u8 rsvd[2];
u32 lpcnt;
u32 payload; /* user defined payload pattern */
wwn_t rp_pwwn;
wwn_t rp_nwwn;
struct bfa_diag_dport_result_s result;
}; };
struct bfa_fcdiag_s { struct bfa_fcdiag_s {
...@@ -742,11 +751,13 @@ bfa_status_t bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore, ...@@ -742,11 +751,13 @@ bfa_status_t bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore,
u32 queue, struct bfa_diag_qtest_result_s *result, u32 queue, struct bfa_diag_qtest_result_s *result,
bfa_cb_diag_t cbfn, void *cbarg); bfa_cb_diag_t cbfn, void *cbarg);
bfa_status_t bfa_fcdiag_lb_is_running(struct bfa_s *bfa); bfa_status_t bfa_fcdiag_lb_is_running(struct bfa_s *bfa);
bfa_status_t bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, bfa_status_t bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
void *cbarg); bfa_cb_diag_t cbfn, void *cbarg);
bfa_status_t bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, bfa_status_t bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn,
void *cbarg); void *cbarg);
bfa_status_t bfa_dport_get_state(struct bfa_s *bfa, bfa_status_t bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
enum bfa_dport_state *state); bfa_cb_diag_t cbfn, void *cbarg);
bfa_status_t bfa_dport_show(struct bfa_s *bfa,
struct bfa_diag_dport_result_s *result);
#endif /* __BFA_SVC_H__ */ #endif /* __BFA_SVC_H__ */
...@@ -1785,51 +1785,87 @@ bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd) ...@@ -1785,51 +1785,87 @@ bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
} }
int int
bfad_iocmd_diag_cfg_dport(struct bfad_s *bfad, unsigned int cmd, void *pcmd) bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd)
{ {
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; struct bfa_bsg_dport_enable_s *iocmd =
(struct bfa_bsg_dport_enable_s *)pcmd;
unsigned long flags; unsigned long flags;
struct bfad_hal_comp fcomp; struct bfad_hal_comp fcomp;
init_completion(&fcomp.comp); init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags); spin_lock_irqsave(&bfad->bfad_lock, flags);
if (cmd == IOCMD_DIAG_DPORT_ENABLE) iocmd->status = bfa_dport_enable(&bfad->bfa, iocmd->lpcnt,
iocmd->status = bfa_dport_enable(&bfad->bfa, iocmd->pat, bfad_hcb_comp, &fcomp);
bfad_hcb_comp, &fcomp); spin_unlock_irqrestore(&bfad->bfad_lock, flags);
else if (cmd == IOCMD_DIAG_DPORT_DISABLE) if (iocmd->status != BFA_STATUS_OK)
iocmd->status = bfa_dport_disable(&bfad->bfa, bfa_trc(bfad, iocmd->status);
bfad_hcb_comp, &fcomp);
else { else {
bfa_trc(bfad, 0); wait_for_completion(&fcomp.comp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags); iocmd->status = fcomp.status;
return -EINVAL;
} }
spin_unlock_irqrestore(&bfad->bfad_lock, flags); return 0;
}
int
bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
unsigned long flags;
struct bfad_hal_comp fcomp;
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_dport_disable(&bfad->bfa, bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK) if (iocmd->status != BFA_STATUS_OK)
bfa_trc(bfad, iocmd->status); bfa_trc(bfad, iocmd->status);
else { else {
wait_for_completion(&fcomp.comp); wait_for_completion(&fcomp.comp);
iocmd->status = fcomp.status; iocmd->status = fcomp.status;
} }
return 0;
}
int
bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_dport_enable_s *iocmd =
(struct bfa_bsg_dport_enable_s *)pcmd;
unsigned long flags;
struct bfad_hal_comp fcomp;
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_dport_start(&bfad->bfa, iocmd->lpcnt,
iocmd->pat, bfad_hcb_comp,
&fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK) {
bfa_trc(bfad, iocmd->status);
} else {
wait_for_completion(&fcomp.comp);
iocmd->status = fcomp.status;
}
return 0; return 0;
} }
int int
bfad_iocmd_diag_dport_get_state(struct bfad_s *bfad, void *pcmd) bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd)
{ {
struct bfa_bsg_diag_dport_get_state_s *iocmd = struct bfa_bsg_diag_dport_show_s *iocmd =
(struct bfa_bsg_diag_dport_get_state_s *)pcmd; (struct bfa_bsg_diag_dport_show_s *)pcmd;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags); spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_dport_get_state(&bfad->bfa, &iocmd->state); iocmd->status = bfa_dport_show(&bfad->bfa, &iocmd->result);
spin_unlock_irqrestore(&bfad->bfad_lock, flags); spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return 0; return 0;
} }
int int
bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd) bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
{ {
...@@ -2934,11 +2970,16 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, ...@@ -2934,11 +2970,16 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
rc = bfad_iocmd_diag_lb_stat(bfad, iocmd); rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
break; break;
case IOCMD_DIAG_DPORT_ENABLE: case IOCMD_DIAG_DPORT_ENABLE:
rc = bfad_iocmd_diag_dport_enable(bfad, iocmd);
break;
case IOCMD_DIAG_DPORT_DISABLE: case IOCMD_DIAG_DPORT_DISABLE:
rc = bfad_iocmd_diag_cfg_dport(bfad, cmd, iocmd); rc = bfad_iocmd_diag_dport_disable(bfad, iocmd);
break;
case IOCMD_DIAG_DPORT_SHOW:
rc = bfad_iocmd_diag_dport_show(bfad, iocmd);
break; break;
case IOCMD_DIAG_DPORT_GET_STATE: case IOCMD_DIAG_DPORT_START:
rc = bfad_iocmd_diag_dport_get_state(bfad, iocmd); rc = bfad_iocmd_diag_dport_start(bfad, iocmd);
break; break;
case IOCMD_PHY_GET_ATTR: case IOCMD_PHY_GET_ATTR:
rc = bfad_iocmd_phy_get_attr(bfad, iocmd); rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
......
...@@ -144,7 +144,6 @@ enum { ...@@ -144,7 +144,6 @@ enum {
IOCMD_FCPIM_LUNMASK_DELETE, IOCMD_FCPIM_LUNMASK_DELETE,
IOCMD_DIAG_DPORT_ENABLE, IOCMD_DIAG_DPORT_ENABLE,
IOCMD_DIAG_DPORT_DISABLE, IOCMD_DIAG_DPORT_DISABLE,
IOCMD_DIAG_DPORT_GET_STATE,
IOCMD_QOS_SET_BW, IOCMD_QOS_SET_BW,
IOCMD_FCPIM_THROTTLE_QUERY, IOCMD_FCPIM_THROTTLE_QUERY,
IOCMD_FCPIM_THROTTLE_SET, IOCMD_FCPIM_THROTTLE_SET,
...@@ -153,6 +152,8 @@ enum { ...@@ -153,6 +152,8 @@ enum {
IOCMD_FRUVPD_READ, IOCMD_FRUVPD_READ,
IOCMD_FRUVPD_UPDATE, IOCMD_FRUVPD_UPDATE,
IOCMD_FRUVPD_GET_MAX_SIZE, IOCMD_FRUVPD_GET_MAX_SIZE,
IOCMD_DIAG_DPORT_SHOW,
IOCMD_DIAG_DPORT_START,
}; };
struct bfa_bsg_gen_s { struct bfa_bsg_gen_s {
...@@ -593,6 +594,21 @@ struct bfa_bsg_diag_loopback_s { ...@@ -593,6 +594,21 @@ struct bfa_bsg_diag_loopback_s {
struct bfa_diag_loopback_result_s result; struct bfa_diag_loopback_result_s result;
}; };
struct bfa_bsg_diag_dport_show_s {
bfa_status_t status;
u16 bfad_num;
u16 rsvd;
struct bfa_diag_dport_result_s result;
};
struct bfa_bsg_dport_enable_s {
bfa_status_t status;
u16 bfad_num;
u16 rsvd;
u16 lpcnt;
u16 pat;
};
struct bfa_bsg_diag_fwping_s { struct bfa_bsg_diag_fwping_s {
bfa_status_t status; bfa_status_t status;
u16 bfad_num; u16 bfad_num;
...@@ -640,13 +656,6 @@ struct bfa_bsg_diag_lb_stat_s { ...@@ -640,13 +656,6 @@ struct bfa_bsg_diag_lb_stat_s {
u16 rsvd; u16 rsvd;
}; };
struct bfa_bsg_diag_dport_get_state_s {
bfa_status_t status;
u16 bfad_num;
u16 rsvd;
enum bfa_dport_state state;
};
struct bfa_bsg_phy_attr_s { struct bfa_bsg_phy_attr_s {
bfa_status_t status; bfa_status_t status;
u16 bfad_num; u16 bfad_num;
......
...@@ -973,6 +973,7 @@ enum bfi_diag_i2h { ...@@ -973,6 +973,7 @@ enum bfi_diag_i2h {
BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST), BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST),
BFI_DIAG_I2H_QTEST = BFA_I2HM(BFI_DIAG_H2I_QTEST), BFI_DIAG_I2H_QTEST = BFA_I2HM(BFI_DIAG_H2I_QTEST),
BFI_DIAG_I2H_DPORT = BFA_I2HM(BFI_DIAG_H2I_DPORT), BFI_DIAG_I2H_DPORT = BFA_I2HM(BFI_DIAG_H2I_DPORT),
BFI_DIAG_I2H_DPORT_SCN = BFA_I2HM(8),
}; };
#define BFI_DIAG_MAX_SGES 2 #define BFI_DIAG_MAX_SGES 2
...@@ -1064,16 +1065,73 @@ struct bfi_diag_qtest_req_s { ...@@ -1064,16 +1065,73 @@ struct bfi_diag_qtest_req_s {
enum bfi_dport_req { enum bfi_dport_req {
BFI_DPORT_DISABLE = 0, /* disable dport request */ BFI_DPORT_DISABLE = 0, /* disable dport request */
BFI_DPORT_ENABLE = 1, /* enable dport request */ BFI_DPORT_ENABLE = 1, /* enable dport request */
BFI_DPORT_START = 2, /* start dport request */
BFI_DPORT_SHOW = 3, /* show dport request */
BFI_DPORT_DYN_DISABLE = 4, /* disable dynamic dport request */
};
enum bfi_dport_scn {
BFI_DPORT_SCN_TESTSTART = 1,
BFI_DPORT_SCN_TESTCOMP = 2,
BFI_DPORT_SCN_SFP_REMOVED = 3,
BFI_DPORT_SCN_DDPORT_ENABLE = 4,
BFI_DPORT_SCN_DDPORT_DISABLE = 5,
BFI_DPORT_SCN_FCPORT_DISABLE = 6,
BFI_DPORT_SCN_SUBTESTSTART = 7,
BFI_DPORT_SCN_TESTSKIP = 8,
BFI_DPORT_SCN_DDPORT_DISABLED = 9,
}; };
struct bfi_diag_dport_req_s { struct bfi_diag_dport_req_s {
struct bfi_mhdr_s mh; /* 4 bytes */ struct bfi_mhdr_s mh; /* 4 bytes */
u8 req; /* request 1: enable 0: disable */ u8 req; /* request 1: enable 0: disable */
u8 status; /* reply status */ u8 rsvd[3];
u8 rsvd[2]; u32 lpcnt;
u32 msgtag; /* msgtag for reply */ u32 payload;
};
struct bfi_diag_dport_rsp_s {
struct bfi_mhdr_s mh; /* header 4 bytes */
bfa_status_t status; /* reply status */
wwn_t pwwn; /* switch port wwn. 8 bytes */
wwn_t nwwn; /* switch node wwn. 8 bytes */
};
struct bfi_diag_dport_scn_teststart_s {
wwn_t pwwn; /* switch port wwn. 8 bytes */
wwn_t nwwn; /* switch node wwn. 8 bytes */
u8 type; /* bfa_diag_dport_test_type_e */
u8 rsvd[3];
u32 numfrm; /* from switch uint in 1M */
};
struct bfi_diag_dport_scn_testcomp_s {
u8 status; /* bfa_diag_dport_test_status_e */
u8 speed; /* bfa_port_speed_t */
u16 numbuffer; /* from switch */
u8 subtest_status[DPORT_TEST_MAX]; /* 4 bytes */
u32 latency; /* from switch */
u32 distance; /* from swtich unit in meters */
/* Buffers required to saturate the link */
u16 frm_sz; /* from switch for buf_reqd */
u8 rsvd[2];
};
struct bfi_diag_dport_scn_s { /* max size == RDS_RMESZ */
struct bfi_mhdr_s mh; /* header 4 bytes */
u8 state; /* new state */
u8 rsvd[3];
union {
struct bfi_diag_dport_scn_teststart_s teststart;
struct bfi_diag_dport_scn_testcomp_s testcomp;
} info;
};
union bfi_diag_dport_msg_u {
struct bfi_diag_dport_req_s req;
struct bfi_diag_dport_rsp_s rsp;
struct bfi_diag_dport_scn_s scn;
}; };
#define bfi_diag_dport_rsp_t struct bfi_diag_dport_req_s
/* /*
* PHY module specific * PHY module specific
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment