struct bfa_s;
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
#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \
+ (__hcb_qe)->pre_rmv = BFA_FALSE; \
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
} 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 { \
(__hcb_qe)->once = BFA_FALSE; \
} while (0)
#define bfa_timer_start(_bfa, _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__ */
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);
}
static void
__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 (fcport->stats_status == BFA_STATUS_OK) {
- struct timeval tv;
-
- /* Swap FC QoS or FCoE stats */
- if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
- bfa_fcport_qos_stats_swap(
- &fcport->stats_ret->fcqos,
- &fcport->stats->fcqos);
- } else {
- bfa_fcport_fcoe_stats_swap(
- &fcport->stats_ret->fcoe,
- &fcport->stats->fcoe);
-
- do_gettimeofday(&tv);
- fcport->stats_ret->fcoe.secs_reset =
+ struct timeval tv;
+ if (fcport->stats_status == BFA_STATUS_OK)
+ do_gettimeofday(&tv);
+
+ list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
+ bfa_q_deq(&fcport->stats_pending_q, &qe);
+ cb = (struct bfa_cb_pending_q_s *)qe;
+ if (fcport->stats_status == BFA_STATUS_OK) {
+ ret = (union bfa_fcport_stats_u *)cb->data;
+ /* Swap FC QoS or FCoE stats */
+ if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
+ bfa_fcport_qos_stats_swap(&ret->fcqos,
+ &fcport->stats->fcqos);
+ else {
+ bfa_fcport_fcoe_stats_swap(&ret->fcoe,
+ &fcport->stats->fcoe);
+ ret->fcoe.secs_reset =
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 {
- fcport->stats_busy = BFA_FALSE;
+ INIT_LIST_HEAD(&fcport->stats_pending_q);
fcport->stats_status = BFA_STATUS_OK;
}
}
}
fcport->stats_status = BFA_STATUS_ETIMER;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
- fcport);
+ __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
}
static void
static void
__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) {
struct timeval tv;
*/
do_gettimeofday(&tv);
fcport->stats_reset_time = tv.tv_sec;
-
- fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+ list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
+ 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 {
- fcport->stats_busy = BFA_FALSE;
+ INIT_LIST_HEAD(&fcport->statsclr_pending_q);
fcport->stats_status = BFA_STATUS_OK;
}
}
}
fcport->stats_status = BFA_STATUS_ETIMER;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
- __bfa_cb_fcport_stats_clr, fcport);
+ __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
}
static void
/*
* check for timer pop before processing the rsp
*/
- if (fcport->stats_busy == BFA_FALSE ||
- fcport->stats_status == BFA_STATUS_ETIMER)
+ if (list_empty(&fcport->stats_pending_q) ||
+ (fcport->stats_status == BFA_STATUS_ETIMER))
break;
bfa_timer_stop(&fcport->timer);
fcport->stats_status = i2hmsg.pstatsget_rsp->status;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
- __bfa_cb_fcport_stats_get, fcport);
+ __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
break;
case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
/*
* check for timer pop before processing the rsp
*/
- if (fcport->stats_busy == BFA_FALSE ||
- fcport->stats_status == BFA_STATUS_ETIMER)
+ if (list_empty(&fcport->statsclr_pending_q) ||
+ (fcport->stats_status == BFA_STATUS_ETIMER))
break;
bfa_timer_stop(&fcport->timer);
fcport->stats_status = BFA_STATUS_OK;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
- __bfa_cb_fcport_stats_clr, fcport);
+ __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
break;
case BFI_FCPORT_I2H_ENABLE_AEN:
* Fetch port statistics (FCQoS or FCoE).
*/
bfa_status_t
-bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
- bfa_cb_port_t cbfn, void *cbarg)
+bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- if (fcport->stats_busy) {
- bfa_trc(bfa, fcport->stats_busy);
- return BFA_STATUS_DEVBUSY;
- }
+ if (bfa_ioc_is_disabled(&bfa->ioc))
+ return BFA_STATUS_IOC_DISABLED;
- fcport->stats_busy = BFA_TRUE;
- fcport->stats_ret = stats;
- fcport->stats_cbfn = cbfn;
- fcport->stats_cbarg = cbarg;
+ if (!list_empty(&fcport->statsclr_pending_q))
+ return BFA_STATUS_DEVBUSY;
- 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;
}
* Reset port statistics (FCQoS or FCoE).
*/
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);
- if (fcport->stats_busy) {
- bfa_trc(bfa, fcport->stats_busy);
+ if (!list_empty(&fcport->stats_pending_q))
return BFA_STATUS_DEVBUSY;
- }
- fcport->stats_busy = BFA_TRUE;
- fcport->stats_cbfn = cbfn;
- fcport->stats_cbarg = cbarg;
+ if (list_empty(&fcport->statsclr_pending_q)) {
+ 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);
+ } 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;
}
-
/*
* Fetch port attributes.
*/
*/
#define BFA_FCPORT(_bfa) (&((_bfa)->modules.port))
-typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);
/*
* Link notification data structure
u8 *stats_kva;
u64 stats_pa;
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_boolean_t stats_busy; /* outstanding stats/statsclr */
+ struct list_head stats_pending_q;
+ struct list_head statsclr_pending_q;
bfa_boolean_t stats_qfull;
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 beacon; /* port beacon status */
bfa_boolean_t link_e2e_beacon; /* link beacon status */
bfa_boolean_t link_e2e_beacon);
bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
- union bfa_fcport_stats_u *stats,
- bfa_cb_port_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
- void *cbarg);
+ struct bfa_cb_pending_q_s *cb);
+bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa,
+ struct bfa_cb_pending_q_s *cb);
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_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
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
bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
unsigned int payload_len)
case IOCMD_ITNIM_GET_IOPROFILE:
rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd);
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:
rc = -EINVAL;
break;