Commit 9693e7df authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley

[SCSI] bfa: Introduce a link notification state machine.

Introduce a link notification state machine to handle next incoming
link events while the current event is being delivered to the driver.

When the event has been processed by the driver, the link notification
state machine will queue the next event (if there is any) to the
driver.
Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 738c9e66
...@@ -26,16 +26,6 @@ ...@@ -26,16 +26,6 @@
BFA_TRC_FILE(HAL, PPORT); BFA_TRC_FILE(HAL, PPORT);
BFA_MODULE(pport); BFA_MODULE(pport);
#define bfa_pport_callback(__pport, __event) do { \
if ((__pport)->bfa->fcs) { \
(__pport)->event_cbfn((__pport)->event_cbarg, (__event)); \
} else { \
(__pport)->hcb_event = (__event); \
bfa_cb_queue((__pport)->bfa, &(__pport)->hcb_qe, \
__bfa_cb_port_event, (__pport)); \
} \
} while (0)
/* /*
* The port is considered disabled if corresponding physical port or IOC are * The port is considered disabled if corresponding physical port or IOC are
* disabled explicitly * disabled explicitly
...@@ -57,7 +47,10 @@ static void __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete); ...@@ -57,7 +47,10 @@ static void __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete);
static void __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete); static void __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete);
static void bfa_port_stats_timeout(void *cbarg); static void bfa_port_stats_timeout(void *cbarg);
static void bfa_port_stats_clr_timeout(void *cbarg); static void bfa_port_stats_clr_timeout(void *cbarg);
static void bfa_pport_callback(struct bfa_pport_s *pport,
enum bfa_pport_linkstate event);
static void bfa_pport_queue_cb(struct bfa_pport_ln_s *ln,
enum bfa_pport_linkstate event);
/** /**
* bfa_pport_private * bfa_pport_private
*/ */
...@@ -77,6 +70,16 @@ enum bfa_pport_sm_event { ...@@ -77,6 +70,16 @@ enum bfa_pport_sm_event {
BFA_PPORT_SM_HWFAIL = 9, /* IOC h/w failure */ BFA_PPORT_SM_HWFAIL = 9, /* IOC h/w failure */
}; };
/**
* BFA port link notification state machine events
*/
enum bfa_pport_ln_sm_event {
BFA_PPORT_LN_SM_LINKUP = 1, /* linkup event */
BFA_PPORT_LN_SM_LINKDOWN = 2, /* linkdown event */
BFA_PPORT_LN_SM_NOTIFICATION = 3 /* done notification */
};
static void bfa_pport_sm_uninit(struct bfa_pport_s *pport, static void bfa_pport_sm_uninit(struct bfa_pport_s *pport,
enum bfa_pport_sm_event event); enum bfa_pport_sm_event event);
static void bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport, static void bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
...@@ -100,6 +103,21 @@ static void bfa_pport_sm_iocdown(struct bfa_pport_s *pport, ...@@ -100,6 +103,21 @@ static void bfa_pport_sm_iocdown(struct bfa_pport_s *pport,
static void bfa_pport_sm_iocfail(struct bfa_pport_s *pport, static void bfa_pport_sm_iocfail(struct bfa_pport_s *pport,
enum bfa_pport_sm_event event); enum bfa_pport_sm_event event);
static void bfa_pport_ln_sm_dn(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event);
static void bfa_pport_ln_sm_dn_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event);
static void bfa_pport_ln_sm_dn_up_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event);
static void bfa_pport_ln_sm_up(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event);
static void bfa_pport_ln_sm_up_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event);
static void bfa_pport_ln_sm_up_dn_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event);
static void bfa_pport_ln_sm_up_dn_up_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event);
static struct bfa_sm_table_s hal_pport_sm_table[] = { static struct bfa_sm_table_s hal_pport_sm_table[] = {
{BFA_SM(bfa_pport_sm_uninit), BFA_PPORT_ST_UNINIT}, {BFA_SM(bfa_pport_sm_uninit), BFA_PPORT_ST_UNINIT},
{BFA_SM(bfa_pport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT}, {BFA_SM(bfa_pport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
...@@ -619,7 +637,163 @@ bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) ...@@ -619,7 +637,163 @@ bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
} }
} }
/**
* Link state is down
*/
static void
bfa_pport_ln_sm_dn(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event)
{
bfa_trc(ln->pport->bfa, event);
switch (event) {
case BFA_PPORT_LN_SM_LINKUP:
bfa_sm_set_state(ln, bfa_pport_ln_sm_up_nf);
bfa_pport_queue_cb(ln, BFA_PPORT_LINKUP);
break;
default:
bfa_sm_fault(ln->pport->bfa, event);
}
}
/**
* Link state is waiting for down notification
*/
static void
bfa_pport_ln_sm_dn_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event)
{
bfa_trc(ln->pport->bfa, event);
switch (event) {
case BFA_PPORT_LN_SM_LINKUP:
bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_up_nf);
break;
case BFA_PPORT_LN_SM_NOTIFICATION:
bfa_sm_set_state(ln, bfa_pport_ln_sm_dn);
break;
default:
bfa_sm_fault(ln->pport->bfa, event);
}
}
/**
* Link state is waiting for down notification and there is a pending up
*/
static void
bfa_pport_ln_sm_dn_up_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event)
{
bfa_trc(ln->pport->bfa, event);
switch (event) {
case BFA_PPORT_LN_SM_LINKDOWN:
bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_nf);
break;
case BFA_PPORT_LN_SM_NOTIFICATION:
bfa_sm_set_state(ln, bfa_pport_ln_sm_up_nf);
bfa_pport_queue_cb(ln, BFA_PPORT_LINKUP);
break;
default:
bfa_sm_fault(ln->pport->bfa, event);
}
}
/**
* Link state is up
*/
static void
bfa_pport_ln_sm_up(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event)
{
bfa_trc(ln->pport->bfa, event);
switch (event) {
case BFA_PPORT_LN_SM_LINKDOWN:
bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_nf);
bfa_pport_queue_cb(ln, BFA_PPORT_LINKDOWN);
break;
default:
bfa_sm_fault(ln->pport->bfa, event);
}
}
/**
* Link state is waiting for up notification
*/
static void
bfa_pport_ln_sm_up_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event)
{
bfa_trc(ln->pport->bfa, event);
switch (event) {
case BFA_PPORT_LN_SM_LINKDOWN:
bfa_sm_set_state(ln, bfa_pport_ln_sm_up_dn_nf);
break;
case BFA_PPORT_LN_SM_NOTIFICATION:
bfa_sm_set_state(ln, bfa_pport_ln_sm_up);
break;
default:
bfa_sm_fault(ln->pport->bfa, event);
}
}
/**
* Link state is waiting for up notification and there is a pending down
*/
static void
bfa_pport_ln_sm_up_dn_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event)
{
bfa_trc(ln->pport->bfa, event);
switch (event) {
case BFA_PPORT_LN_SM_LINKUP:
bfa_sm_set_state(ln, bfa_pport_ln_sm_up_dn_up_nf);
break;
case BFA_PPORT_LN_SM_NOTIFICATION:
bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_nf);
bfa_pport_queue_cb(ln, BFA_PPORT_LINKDOWN);
break;
default:
bfa_sm_fault(ln->pport->bfa, event);
}
}
/**
* Link state is waiting for up notification and there are pending down and up
*/
static void
bfa_pport_ln_sm_up_dn_up_nf(struct bfa_pport_ln_s *ln,
enum bfa_pport_ln_sm_event event)
{
bfa_trc(ln->pport->bfa, event);
switch (event) {
case BFA_PPORT_LN_SM_LINKDOWN:
bfa_sm_set_state(ln, bfa_pport_ln_sm_up_dn_nf);
break;
case BFA_PPORT_LN_SM_NOTIFICATION:
bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_up_nf);
bfa_pport_queue_cb(ln, BFA_PPORT_LINKDOWN);
break;
default:
bfa_sm_fault(ln->pport->bfa, event);
}
}
/** /**
* bfa_pport_private * bfa_pport_private
...@@ -628,10 +802,12 @@ bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) ...@@ -628,10 +802,12 @@ bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
static void static void
__bfa_cb_port_event(void *cbarg, bfa_boolean_t complete) __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete)
{ {
struct bfa_pport_s *pport = cbarg; struct bfa_pport_ln_s *ln = cbarg;
if (complete) if (complete)
pport->event_cbfn(pport->event_cbarg, pport->hcb_event); ln->pport->event_cbfn(ln->pport->event_cbarg, ln->ln_event);
else
bfa_sm_send_event(ln, BFA_PPORT_LN_SM_NOTIFICATION);
} }
#define PPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), \ #define PPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), \
...@@ -681,13 +857,16 @@ bfa_pport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, ...@@ -681,13 +857,16 @@ bfa_pport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
{ {
struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
struct bfa_pport_cfg_s *port_cfg = &pport->cfg; struct bfa_pport_cfg_s *port_cfg = &pport->cfg;
struct bfa_pport_ln_s *ln = &pport->ln;
bfa_os_memset(pport, 0, sizeof(struct bfa_pport_s)); bfa_os_memset(pport, 0, sizeof(struct bfa_pport_s));
pport->bfa = bfa; pport->bfa = bfa;
ln->pport = pport;
bfa_pport_mem_claim(pport, meminfo); bfa_pport_mem_claim(pport, meminfo);
bfa_sm_set_state(pport, bfa_pport_sm_uninit); bfa_sm_set_state(pport, bfa_pport_sm_uninit);
bfa_sm_set_state(ln, bfa_pport_ln_sm_dn);
/** /**
* initialize and set default configuration * initialize and set default configuration
...@@ -1368,6 +1547,33 @@ bfa_port_stats_clr_timeout(void *cbarg) ...@@ -1368,6 +1547,33 @@ bfa_port_stats_clr_timeout(void *cbarg)
bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats_clr, port); bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats_clr, port);
} }
static void
bfa_pport_callback(struct bfa_pport_s *pport, enum bfa_pport_linkstate event)
{
if (pport->bfa->fcs) {
pport->event_cbfn(pport->event_cbarg, event);
return;
}
switch (event) {
case BFA_PPORT_LINKUP:
bfa_sm_send_event(&pport->ln, BFA_PPORT_LN_SM_LINKUP);
break;
case BFA_PPORT_LINKDOWN:
bfa_sm_send_event(&pport->ln, BFA_PPORT_LN_SM_LINKDOWN);
break;
default:
bfa_assert(0);
}
}
static void
bfa_pport_queue_cb(struct bfa_pport_ln_s *ln, enum bfa_pport_linkstate event)
{
ln->ln_event = event;
bfa_cb_queue(ln->pport->bfa, &ln->ln_qe, __bfa_cb_port_event, ln);
}
static void static void
__bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete) __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete)
{ {
......
...@@ -22,6 +22,16 @@ ...@@ -22,6 +22,16 @@
#include <bfi/bfi_pport.h> #include <bfi/bfi_pport.h>
#include "bfa_intr_priv.h" #include "bfa_intr_priv.h"
/**
* Link notification data structure
*/
struct bfa_pport_ln_s {
struct bfa_pport_s *pport;
bfa_sm_t sm;
struct bfa_cb_qe_s ln_qe; /* BFA callback queue elem for ln */
enum bfa_pport_linkstate ln_event; /* ln event for callback */
};
/** /**
* BFA physical port data structure * BFA physical port data structure
*/ */
...@@ -52,9 +62,8 @@ struct bfa_pport_s { ...@@ -52,9 +62,8 @@ struct bfa_pport_s {
union bfi_pport_i2h_msg_u i2hmsg; union bfi_pport_i2h_msg_u i2hmsg;
} event_arg; } event_arg;
void *bfad; /* BFA driver handle */ void *bfad; /* BFA driver handle */
struct bfa_pport_ln_s ln; /* Link Notification */
struct bfa_cb_qe_s hcb_qe; /* BFA callback queue elem */ struct bfa_cb_qe_s hcb_qe; /* BFA callback queue elem */
enum bfa_pport_linkstate hcb_event;
/* link event for callback */
u32 msgtag; /* fimrware msg tag for reply */ u32 msgtag; /* fimrware msg tag for reply */
u8 *stats_kva; u8 *stats_kva;
u64 stats_pa; u64 stats_pa;
......
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