Commit 37ea0558 authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley

[SCSI] bfa: Added support to collect and reset fcport stats

- Added support to collect and reset fcport stats.
- Modified design to allow multiple requests for fcport stats.
  - fcport will remember the stats request in its stats_pending
    queue and service each of the queued requests after receiving
    a firmware response for the prior request.
Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 42a8e6e2
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
struct bfa_s; struct bfa_s;
typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m); typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);
/* /*
* Interrupt message handlers * Interrupt message handlers
...@@ -121,6 +122,7 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg), ...@@ -121,6 +122,7 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \ #define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \ (__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \ (__hcb_qe)->cbarg = (__cbarg); \
(__hcb_qe)->pre_rmv = BFA_FALSE; \
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \ list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
} while (0) } while (0)
...@@ -135,6 +137,11 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg), ...@@ -135,6 +137,11 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
} \ } \
} while (0) } while (0)
#define bfa_cb_queue_status(__bfa, __hcb_qe, __status) do { \
(__hcb_qe)->fw_status = (__status); \
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
} while (0)
#define bfa_cb_queue_done(__hcb_qe) do { \ #define bfa_cb_queue_done(__hcb_qe) do { \
(__hcb_qe)->once = BFA_FALSE; \ (__hcb_qe)->once = BFA_FALSE; \
} while (0) } while (0)
...@@ -408,4 +415,18 @@ void bfa_iocfc_disable(struct bfa_s *bfa); ...@@ -408,4 +415,18 @@ void bfa_iocfc_disable(struct bfa_s *bfa);
#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \ #define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \
bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout) bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
struct bfa_cb_pending_q_s {
struct bfa_cb_qe_s hcb_qe;
void *data; /* Driver buffer */
};
/* Common macros to operate on pending stats/attr apis */
#define bfa_pending_q_init(__qe, __cbfn, __cbarg, __data) do { \
bfa_q_qe_init(&((__qe)->hcb_qe.qe)); \
(__qe)->hcb_qe.cbfn = (__cbfn); \
(__qe)->hcb_qe.cbarg = (__cbarg); \
(__qe)->hcb_qe.pre_rmv = BFA_TRUE; \
(__qe)->data = (__data); \
} while (0)
#endif /* __BFA_H__ */ #endif /* __BFA_H__ */
...@@ -1533,10 +1533,17 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q) ...@@ -1533,10 +1533,17 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
struct list_head *qe; struct list_head *qe;
struct list_head *qen; struct list_head *qen;
struct bfa_cb_qe_s *hcb_qe; struct bfa_cb_qe_s *hcb_qe;
bfa_cb_cbfn_status_t cbfn;
list_for_each_safe(qe, qen, comp_q) { list_for_each_safe(qe, qen, comp_q) {
hcb_qe = (struct bfa_cb_qe_s *) qe; hcb_qe = (struct bfa_cb_qe_s *) qe;
hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE); if (hcb_qe->pre_rmv) {
/* qe is invalid after return, dequeue before cbfn() */
list_del(qe);
cbfn = (bfa_cb_cbfn_status_t)(hcb_qe->cbfn);
cbfn(hcb_qe->cbarg, hcb_qe->fw_status);
} else
hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
} }
} }
...@@ -1549,6 +1556,7 @@ bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q) ...@@ -1549,6 +1556,7 @@ bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
while (!list_empty(comp_q)) { while (!list_empty(comp_q)) {
bfa_q_deq(comp_q, &qe); bfa_q_deq(comp_q, &qe);
hcb_qe = (struct bfa_cb_qe_s *) qe; hcb_qe = (struct bfa_cb_qe_s *) qe;
WARN_ON(hcb_qe->pre_rmv);
hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE); hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE);
} }
} }
......
...@@ -367,6 +367,8 @@ struct bfa_cb_qe_s { ...@@ -367,6 +367,8 @@ struct bfa_cb_qe_s {
struct list_head qe; struct list_head qe;
bfa_cb_cbfn_t cbfn; bfa_cb_cbfn_t cbfn;
bfa_boolean_t once; bfa_boolean_t once;
bfa_boolean_t pre_rmv; /* set for stack based qe(s) */
bfa_status_t fw_status; /* to access fw status in comp proc */
void *cbarg; void *cbarg;
}; };
......
...@@ -2910,6 +2910,9 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, ...@@ -2910,6 +2910,9 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS; port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
INIT_LIST_HEAD(&fcport->stats_pending_q);
INIT_LIST_HEAD(&fcport->statsclr_pending_q);
bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport); bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
} }
...@@ -3138,30 +3141,38 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d, ...@@ -3138,30 +3141,38 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
static void static void
__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete) __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
{ {
struct bfa_fcport_s *fcport = cbarg; struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
struct bfa_cb_pending_q_s *cb;
struct list_head *qe, *qen;
union bfa_fcport_stats_u *ret;
if (complete) { if (complete) {
if (fcport->stats_status == BFA_STATUS_OK) { struct timeval tv;
struct timeval tv; if (fcport->stats_status == BFA_STATUS_OK)
do_gettimeofday(&tv);
/* Swap FC QoS or FCoE stats */
if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) { list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
bfa_fcport_qos_stats_swap( bfa_q_deq(&fcport->stats_pending_q, &qe);
&fcport->stats_ret->fcqos, cb = (struct bfa_cb_pending_q_s *)qe;
&fcport->stats->fcqos); if (fcport->stats_status == BFA_STATUS_OK) {
} else { ret = (union bfa_fcport_stats_u *)cb->data;
bfa_fcport_fcoe_stats_swap( /* Swap FC QoS or FCoE stats */
&fcport->stats_ret->fcoe, if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
&fcport->stats->fcoe); bfa_fcport_qos_stats_swap(&ret->fcqos,
&fcport->stats->fcqos);
do_gettimeofday(&tv); else {
fcport->stats_ret->fcoe.secs_reset = bfa_fcport_fcoe_stats_swap(&ret->fcoe,
&fcport->stats->fcoe);
ret->fcoe.secs_reset =
tv.tv_sec - fcport->stats_reset_time; tv.tv_sec - fcport->stats_reset_time;
}
} }
bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
fcport->stats_status);
} }
fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); fcport->stats_status = BFA_STATUS_OK;
} else { } else {
fcport->stats_busy = BFA_FALSE; INIT_LIST_HEAD(&fcport->stats_pending_q);
fcport->stats_status = BFA_STATUS_OK; fcport->stats_status = BFA_STATUS_OK;
} }
} }
...@@ -3179,8 +3190,7 @@ bfa_fcport_stats_get_timeout(void *cbarg) ...@@ -3179,8 +3190,7 @@ bfa_fcport_stats_get_timeout(void *cbarg)
} }
fcport->stats_status = BFA_STATUS_ETIMER; fcport->stats_status = BFA_STATUS_ETIMER;
bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get, __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
fcport);
} }
static void static void
...@@ -3210,7 +3220,9 @@ bfa_fcport_send_stats_get(void *cbarg) ...@@ -3210,7 +3220,9 @@ bfa_fcport_send_stats_get(void *cbarg)
static void static void
__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete) __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
{ {
struct bfa_fcport_s *fcport = cbarg; struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
struct bfa_cb_pending_q_s *cb;
struct list_head *qe, *qen;
if (complete) { if (complete) {
struct timeval tv; struct timeval tv;
...@@ -3220,10 +3232,15 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete) ...@@ -3220,10 +3232,15 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
*/ */
do_gettimeofday(&tv); do_gettimeofday(&tv);
fcport->stats_reset_time = tv.tv_sec; fcport->stats_reset_time = tv.tv_sec;
list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); bfa_q_deq(&fcport->statsclr_pending_q, &qe);
cb = (struct bfa_cb_pending_q_s *)qe;
bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
fcport->stats_status);
}
fcport->stats_status = BFA_STATUS_OK;
} else { } else {
fcport->stats_busy = BFA_FALSE; INIT_LIST_HEAD(&fcport->statsclr_pending_q);
fcport->stats_status = BFA_STATUS_OK; fcport->stats_status = BFA_STATUS_OK;
} }
} }
...@@ -3241,8 +3258,7 @@ bfa_fcport_stats_clr_timeout(void *cbarg) ...@@ -3241,8 +3258,7 @@ bfa_fcport_stats_clr_timeout(void *cbarg)
} }
fcport->stats_status = BFA_STATUS_ETIMER; fcport->stats_status = BFA_STATUS_ETIMER;
bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
__bfa_cb_fcport_stats_clr, fcport);
} }
static void static void
...@@ -3462,28 +3478,26 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) ...@@ -3462,28 +3478,26 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
/* /*
* check for timer pop before processing the rsp * check for timer pop before processing the rsp
*/ */
if (fcport->stats_busy == BFA_FALSE || if (list_empty(&fcport->stats_pending_q) ||
fcport->stats_status == BFA_STATUS_ETIMER) (fcport->stats_status == BFA_STATUS_ETIMER))
break; break;
bfa_timer_stop(&fcport->timer); bfa_timer_stop(&fcport->timer);
fcport->stats_status = i2hmsg.pstatsget_rsp->status; fcport->stats_status = i2hmsg.pstatsget_rsp->status;
bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
__bfa_cb_fcport_stats_get, fcport);
break; break;
case BFI_FCPORT_I2H_STATS_CLEAR_RSP: case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
/* /*
* check for timer pop before processing the rsp * check for timer pop before processing the rsp
*/ */
if (fcport->stats_busy == BFA_FALSE || if (list_empty(&fcport->statsclr_pending_q) ||
fcport->stats_status == BFA_STATUS_ETIMER) (fcport->stats_status == BFA_STATUS_ETIMER))
break; break;
bfa_timer_stop(&fcport->timer); bfa_timer_stop(&fcport->timer);
fcport->stats_status = BFA_STATUS_OK; fcport->stats_status = BFA_STATUS_OK;
bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
__bfa_cb_fcport_stats_clr, fcport);
break; break;
case BFI_FCPORT_I2H_ENABLE_AEN: case BFI_FCPORT_I2H_ENABLE_AEN:
...@@ -3815,25 +3829,25 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr) ...@@ -3815,25 +3829,25 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
* Fetch port statistics (FCQoS or FCoE). * Fetch port statistics (FCQoS or FCoE).
*/ */
bfa_status_t bfa_status_t
bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
bfa_cb_port_t cbfn, void *cbarg)
{ {
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
if (fcport->stats_busy) { if (bfa_ioc_is_disabled(&bfa->ioc))
bfa_trc(bfa, fcport->stats_busy); return BFA_STATUS_IOC_DISABLED;
return BFA_STATUS_DEVBUSY;
}
fcport->stats_busy = BFA_TRUE; if (!list_empty(&fcport->statsclr_pending_q))
fcport->stats_ret = stats; return BFA_STATUS_DEVBUSY;
fcport->stats_cbfn = cbfn;
fcport->stats_cbarg = cbarg;
bfa_fcport_send_stats_get(fcport); if (list_empty(&fcport->stats_pending_q)) {
list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
bfa_fcport_send_stats_get(fcport);
bfa_timer_start(bfa, &fcport->timer,
bfa_fcport_stats_get_timeout,
fcport, BFA_FCPORT_STATS_TOV);
} else
list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
fcport, BFA_FCPORT_STATS_TOV);
return BFA_STATUS_OK; return BFA_STATUS_OK;
} }
...@@ -3841,27 +3855,25 @@ bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, ...@@ -3841,27 +3855,25 @@ bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
* Reset port statistics (FCQoS or FCoE). * Reset port statistics (FCQoS or FCoE).
*/ */
bfa_status_t bfa_status_t
bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
{ {
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
if (fcport->stats_busy) { if (!list_empty(&fcport->stats_pending_q))
bfa_trc(bfa, fcport->stats_busy);
return BFA_STATUS_DEVBUSY; return BFA_STATUS_DEVBUSY;
}
fcport->stats_busy = BFA_TRUE; if (list_empty(&fcport->statsclr_pending_q)) {
fcport->stats_cbfn = cbfn; list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
fcport->stats_cbarg = cbarg; bfa_fcport_send_stats_clear(fcport);
bfa_timer_start(bfa, &fcport->timer,
bfa_fcport_stats_clr_timeout,
fcport, BFA_FCPORT_STATS_TOV);
} else
list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
bfa_fcport_send_stats_clear(fcport);
bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
fcport, BFA_FCPORT_STATS_TOV);
return BFA_STATUS_OK; return BFA_STATUS_OK;
} }
/* /*
* Fetch port attributes. * Fetch port attributes.
*/ */
......
...@@ -441,7 +441,6 @@ void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); ...@@ -441,7 +441,6 @@ void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
*/ */
#define BFA_FCPORT(_bfa) (&((_bfa)->modules.port)) #define BFA_FCPORT(_bfa) (&((_bfa)->modules.port))
typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);
/* /*
* Link notification data structure * Link notification data structure
...@@ -495,13 +494,11 @@ struct bfa_fcport_s { ...@@ -495,13 +494,11 @@ struct bfa_fcport_s {
u8 *stats_kva; u8 *stats_kva;
u64 stats_pa; u64 stats_pa;
union bfa_fcport_stats_u *stats; union bfa_fcport_stats_u *stats;
union bfa_fcport_stats_u *stats_ret; /* driver stats location */
bfa_status_t stats_status; /* stats/statsclr status */ bfa_status_t stats_status; /* stats/statsclr status */
bfa_boolean_t stats_busy; /* outstanding stats/statsclr */ struct list_head stats_pending_q;
struct list_head statsclr_pending_q;
bfa_boolean_t stats_qfull; bfa_boolean_t stats_qfull;
u32 stats_reset_time; /* stats reset time stamp */ u32 stats_reset_time; /* stats reset time stamp */
bfa_cb_port_t stats_cbfn; /* driver callback function */
void *stats_cbarg; /* *!< user callback arg */
bfa_boolean_t diag_busy; /* diag busy status */ bfa_boolean_t diag_busy; /* diag busy status */
bfa_boolean_t beacon; /* port beacon status */ bfa_boolean_t beacon; /* port beacon status */
bfa_boolean_t link_e2e_beacon; /* link beacon status */ bfa_boolean_t link_e2e_beacon; /* link beacon status */
...@@ -552,10 +549,9 @@ void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon, ...@@ -552,10 +549,9 @@ void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
bfa_boolean_t link_e2e_beacon); bfa_boolean_t link_e2e_beacon);
bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa); bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
union bfa_fcport_stats_u *stats, struct bfa_cb_pending_q_s *cb);
bfa_cb_port_t cbfn, void *cbarg); bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa,
bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, struct bfa_cb_pending_q_s *cb);
void *cbarg);
bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa); bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa); bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
......
...@@ -2023,6 +2023,55 @@ bfad_iocmd_itnim_get_ioprofile(struct bfad_s *bfad, void *cmd) ...@@ -2023,6 +2023,55 @@ bfad_iocmd_itnim_get_ioprofile(struct bfad_s *bfad, void *cmd)
return 0; return 0;
} }
int
bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcport_stats_s *iocmd =
(struct bfa_bsg_fcport_stats_s *)cmd;
struct bfad_hal_comp fcomp;
unsigned long flags;
struct bfa_cb_pending_q_s cb_qe;
init_completion(&fcomp.comp);
bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
&fcomp, &iocmd->stats);
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK) {
bfa_trc(bfad, iocmd->status);
goto out;
}
wait_for_completion(&fcomp.comp);
iocmd->status = fcomp.status;
out:
return 0;
}
int
bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
struct bfad_hal_comp fcomp;
unsigned long flags;
struct bfa_cb_pending_q_s cb_qe;
init_completion(&fcomp.comp);
bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, &fcomp, NULL);
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK) {
bfa_trc(bfad, iocmd->status);
goto out;
}
wait_for_completion(&fcomp.comp);
iocmd->status = fcomp.status;
out:
return 0;
}
static int static int
bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
unsigned int payload_len) unsigned int payload_len)
...@@ -2291,6 +2340,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, ...@@ -2291,6 +2340,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_ITNIM_GET_IOPROFILE: case IOCMD_ITNIM_GET_IOPROFILE:
rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd); rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd);
break; break;
case IOCMD_FCPORT_GET_STATS:
rc = bfad_iocmd_fcport_get_stats(bfad, iocmd);
break;
case IOCMD_FCPORT_RESET_STATS:
rc = bfad_iocmd_fcport_reset_stats(bfad, iocmd);
break;
default: default:
rc = -EINVAL; rc = -EINVAL;
break; break;
......
...@@ -119,6 +119,8 @@ enum { ...@@ -119,6 +119,8 @@ enum {
IOCMD_FCPIM_PROFILE_ON, IOCMD_FCPIM_PROFILE_ON,
IOCMD_FCPIM_PROFILE_OFF, IOCMD_FCPIM_PROFILE_OFF,
IOCMD_ITNIM_GET_IOPROFILE, IOCMD_ITNIM_GET_IOPROFILE,
IOCMD_FCPORT_GET_STATS,
IOCMD_FCPORT_RESET_STATS,
}; };
struct bfa_bsg_gen_s { struct bfa_bsg_gen_s {
...@@ -150,6 +152,13 @@ struct bfa_bsg_itnim_ioprofile_s { ...@@ -150,6 +152,13 @@ struct bfa_bsg_itnim_ioprofile_s {
struct bfa_itnim_ioprofile_s ioprofile; struct bfa_itnim_ioprofile_s ioprofile;
}; };
struct bfa_bsg_fcport_stats_s {
bfa_status_t status;
u16 bfad_num;
u16 rsvd;
union bfa_fcport_stats_u stats;
};
struct bfa_bsg_ioc_name_s { struct bfa_bsg_ioc_name_s {
bfa_status_t status; bfa_status_t status;
u16 bfad_num; u16 bfad_num;
......
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