aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2011-07-20 20:02:11 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-07-27 06:48:52 -0400
commit37ea0558b87abb151245bc750070a4dcda490aca (patch)
tree352d00d22b8f9c91ace2dc8d72dc465deb6ffa7b /drivers/scsi/bfa
parent42a8e6e298f39518445785c53a16357267db37ef (diff)
[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: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r--drivers/scsi/bfa/bfa.h21
-rw-r--r--drivers/scsi/bfa/bfa_core.c10
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h2
-rw-r--r--drivers/scsi/bfa/bfa_svc.c130
-rw-r--r--drivers/scsi/bfa/bfa_svc.h14
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c55
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h9
7 files changed, 172 insertions, 69 deletions
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
index 6e3869a41cb9..32f46265daa5 100644
--- a/drivers/scsi/bfa/bfa.h
+++ b/drivers/scsi/bfa/bfa.h
@@ -27,6 +27,7 @@
27struct bfa_s; 27struct bfa_s;
28 28
29typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m); 29typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
30typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);
30 31
31/* 32/*
32 * Interrupt message handlers 33 * Interrupt message handlers
@@ -121,6 +122,7 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
121#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \ 122#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
122 (__hcb_qe)->cbfn = (__cbfn); \ 123 (__hcb_qe)->cbfn = (__cbfn); \
123 (__hcb_qe)->cbarg = (__cbarg); \ 124 (__hcb_qe)->cbarg = (__cbarg); \
125 (__hcb_qe)->pre_rmv = BFA_FALSE; \
124 list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \ 126 list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
125 } while (0) 127 } while (0)
126 128
@@ -135,6 +137,11 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
135 } \ 137 } \
136 } while (0) 138 } while (0)
137 139
140#define bfa_cb_queue_status(__bfa, __hcb_qe, __status) do { \
141 (__hcb_qe)->fw_status = (__status); \
142 list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
143} while (0)
144
138#define bfa_cb_queue_done(__hcb_qe) do { \ 145#define bfa_cb_queue_done(__hcb_qe) do { \
139 (__hcb_qe)->once = BFA_FALSE; \ 146 (__hcb_qe)->once = BFA_FALSE; \
140 } while (0) 147 } while (0)
@@ -408,4 +415,18 @@ void bfa_iocfc_disable(struct bfa_s *bfa);
408#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \ 415#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \
409 bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout) 416 bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
410 417
418struct bfa_cb_pending_q_s {
419 struct bfa_cb_qe_s hcb_qe;
420 void *data; /* Driver buffer */
421};
422
423/* Common macros to operate on pending stats/attr apis */
424#define bfa_pending_q_init(__qe, __cbfn, __cbarg, __data) do { \
425 bfa_q_qe_init(&((__qe)->hcb_qe.qe)); \
426 (__qe)->hcb_qe.cbfn = (__cbfn); \
427 (__qe)->hcb_qe.cbarg = (__cbarg); \
428 (__qe)->hcb_qe.pre_rmv = BFA_TRUE; \
429 (__qe)->data = (__data); \
430} while (0)
431
411#endif /* __BFA_H__ */ 432#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 0c236964c67e..4613bddd58e4 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -1533,10 +1533,17 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
1533 struct list_head *qe; 1533 struct list_head *qe;
1534 struct list_head *qen; 1534 struct list_head *qen;
1535 struct bfa_cb_qe_s *hcb_qe; 1535 struct bfa_cb_qe_s *hcb_qe;
1536 bfa_cb_cbfn_status_t cbfn;
1536 1537
1537 list_for_each_safe(qe, qen, comp_q) { 1538 list_for_each_safe(qe, qen, comp_q) {
1538 hcb_qe = (struct bfa_cb_qe_s *) qe; 1539 hcb_qe = (struct bfa_cb_qe_s *) qe;
1539 hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE); 1540 if (hcb_qe->pre_rmv) {
1541 /* qe is invalid after return, dequeue before cbfn() */
1542 list_del(qe);
1543 cbfn = (bfa_cb_cbfn_status_t)(hcb_qe->cbfn);
1544 cbfn(hcb_qe->cbarg, hcb_qe->fw_status);
1545 } else
1546 hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
1540 } 1547 }
1541} 1548}
1542 1549
@@ -1549,6 +1556,7 @@ bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
1549 while (!list_empty(comp_q)) { 1556 while (!list_empty(comp_q)) {
1550 bfa_q_deq(comp_q, &qe); 1557 bfa_q_deq(comp_q, &qe);
1551 hcb_qe = (struct bfa_cb_qe_s *) qe; 1558 hcb_qe = (struct bfa_cb_qe_s *) qe;
1559 WARN_ON(hcb_qe->pre_rmv);
1552 hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE); 1560 hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE);
1553 } 1561 }
1554} 1562}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 28bf6e18f33e..a7463c955117 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -367,6 +367,8 @@ struct bfa_cb_qe_s {
367 struct list_head qe; 367 struct list_head qe;
368 bfa_cb_cbfn_t cbfn; 368 bfa_cb_cbfn_t cbfn;
369 bfa_boolean_t once; 369 bfa_boolean_t once;
370 bfa_boolean_t pre_rmv; /* set for stack based qe(s) */
371 bfa_status_t fw_status; /* to access fw status in comp proc */
370 void *cbarg; 372 void *cbarg;
371}; 373};
372 374
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 6e1ed9a9aa2a..9884d6edfb57 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -2910,6 +2910,9 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
2910 2910
2911 port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS; 2911 port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
2912 2912
2913 INIT_LIST_HEAD(&fcport->stats_pending_q);
2914 INIT_LIST_HEAD(&fcport->statsclr_pending_q);
2915
2913 bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport); 2916 bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
2914} 2917}
2915 2918
@@ -3138,30 +3141,38 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3138static void 3141static void
3139__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete) 3142__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3140{ 3143{
3141 struct bfa_fcport_s *fcport = cbarg; 3144 struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
3145 struct bfa_cb_pending_q_s *cb;
3146 struct list_head *qe, *qen;
3147 union bfa_fcport_stats_u *ret;
3142 3148
3143 if (complete) { 3149 if (complete) {
3144 if (fcport->stats_status == BFA_STATUS_OK) { 3150 struct timeval tv;
3145 struct timeval tv; 3151 if (fcport->stats_status == BFA_STATUS_OK)
3146 3152 do_gettimeofday(&tv);
3147 /* Swap FC QoS or FCoE stats */ 3153
3148 if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) { 3154 list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
3149 bfa_fcport_qos_stats_swap( 3155 bfa_q_deq(&fcport->stats_pending_q, &qe);
3150 &fcport->stats_ret->fcqos, 3156 cb = (struct bfa_cb_pending_q_s *)qe;
3151 &fcport->stats->fcqos); 3157 if (fcport->stats_status == BFA_STATUS_OK) {
3152 } else { 3158 ret = (union bfa_fcport_stats_u *)cb->data;
3153 bfa_fcport_fcoe_stats_swap( 3159 /* Swap FC QoS or FCoE stats */
3154 &fcport->stats_ret->fcoe, 3160 if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
3155 &fcport->stats->fcoe); 3161 bfa_fcport_qos_stats_swap(&ret->fcqos,
3156 3162 &fcport->stats->fcqos);
3157 do_gettimeofday(&tv); 3163 else {
3158 fcport->stats_ret->fcoe.secs_reset = 3164 bfa_fcport_fcoe_stats_swap(&ret->fcoe,
3165 &fcport->stats->fcoe);
3166 ret->fcoe.secs_reset =
3159 tv.tv_sec - fcport->stats_reset_time; 3167 tv.tv_sec - fcport->stats_reset_time;
3168 }
3160 } 3169 }
3170 bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3171 fcport->stats_status);
3161 } 3172 }
3162 fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); 3173 fcport->stats_status = BFA_STATUS_OK;
3163 } else { 3174 } else {
3164 fcport->stats_busy = BFA_FALSE; 3175 INIT_LIST_HEAD(&fcport->stats_pending_q);
3165 fcport->stats_status = BFA_STATUS_OK; 3176 fcport->stats_status = BFA_STATUS_OK;
3166 } 3177 }
3167} 3178}
@@ -3179,8 +3190,7 @@ bfa_fcport_stats_get_timeout(void *cbarg)
3179 } 3190 }
3180 3191
3181 fcport->stats_status = BFA_STATUS_ETIMER; 3192 fcport->stats_status = BFA_STATUS_ETIMER;
3182 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get, 3193 __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3183 fcport);
3184} 3194}
3185 3195
3186static void 3196static void
@@ -3210,7 +3220,9 @@ bfa_fcport_send_stats_get(void *cbarg)
3210static void 3220static void
3211__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete) 3221__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3212{ 3222{
3213 struct bfa_fcport_s *fcport = cbarg; 3223 struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3224 struct bfa_cb_pending_q_s *cb;
3225 struct list_head *qe, *qen;
3214 3226
3215 if (complete) { 3227 if (complete) {
3216 struct timeval tv; 3228 struct timeval tv;
@@ -3220,10 +3232,15 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3220 */ 3232 */
3221 do_gettimeofday(&tv); 3233 do_gettimeofday(&tv);
3222 fcport->stats_reset_time = tv.tv_sec; 3234 fcport->stats_reset_time = tv.tv_sec;
3223 3235 list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
3224 fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); 3236 bfa_q_deq(&fcport->statsclr_pending_q, &qe);
3237 cb = (struct bfa_cb_pending_q_s *)qe;
3238 bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3239 fcport->stats_status);
3240 }
3241 fcport->stats_status = BFA_STATUS_OK;
3225 } else { 3242 } else {
3226 fcport->stats_busy = BFA_FALSE; 3243 INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3227 fcport->stats_status = BFA_STATUS_OK; 3244 fcport->stats_status = BFA_STATUS_OK;
3228 } 3245 }
3229} 3246}
@@ -3241,8 +3258,7 @@ bfa_fcport_stats_clr_timeout(void *cbarg)
3241 } 3258 }
3242 3259
3243 fcport->stats_status = BFA_STATUS_ETIMER; 3260 fcport->stats_status = BFA_STATUS_ETIMER;
3244 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, 3261 __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3245 __bfa_cb_fcport_stats_clr, fcport);
3246} 3262}
3247 3263
3248static void 3264static void
@@ -3462,28 +3478,26 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3462 /* 3478 /*
3463 * check for timer pop before processing the rsp 3479 * check for timer pop before processing the rsp
3464 */ 3480 */
3465 if (fcport->stats_busy == BFA_FALSE || 3481 if (list_empty(&fcport->stats_pending_q) ||
3466 fcport->stats_status == BFA_STATUS_ETIMER) 3482 (fcport->stats_status == BFA_STATUS_ETIMER))
3467 break; 3483 break;
3468 3484
3469 bfa_timer_stop(&fcport->timer); 3485 bfa_timer_stop(&fcport->timer);
3470 fcport->stats_status = i2hmsg.pstatsget_rsp->status; 3486 fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3471 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, 3487 __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3472 __bfa_cb_fcport_stats_get, fcport);
3473 break; 3488 break;
3474 3489
3475 case BFI_FCPORT_I2H_STATS_CLEAR_RSP: 3490 case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3476 /* 3491 /*
3477 * check for timer pop before processing the rsp 3492 * check for timer pop before processing the rsp
3478 */ 3493 */
3479 if (fcport->stats_busy == BFA_FALSE || 3494 if (list_empty(&fcport->statsclr_pending_q) ||
3480 fcport->stats_status == BFA_STATUS_ETIMER) 3495 (fcport->stats_status == BFA_STATUS_ETIMER))
3481 break; 3496 break;
3482 3497
3483 bfa_timer_stop(&fcport->timer); 3498 bfa_timer_stop(&fcport->timer);
3484 fcport->stats_status = BFA_STATUS_OK; 3499 fcport->stats_status = BFA_STATUS_OK;
3485 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, 3500 __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3486 __bfa_cb_fcport_stats_clr, fcport);
3487 break; 3501 break;
3488 3502
3489 case BFI_FCPORT_I2H_ENABLE_AEN: 3503 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 * Fetch port statistics (FCQoS or FCoE). 3829 * Fetch port statistics (FCQoS or FCoE).
3816 */ 3830 */
3817bfa_status_t 3831bfa_status_t
3818bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, 3832bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
3819 bfa_cb_port_t cbfn, void *cbarg)
3820{ 3833{
3821 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); 3834 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3822 3835
3823 if (fcport->stats_busy) { 3836 if (bfa_ioc_is_disabled(&bfa->ioc))
3824 bfa_trc(bfa, fcport->stats_busy); 3837 return BFA_STATUS_IOC_DISABLED;
3825 return BFA_STATUS_DEVBUSY;
3826 }
3827 3838
3828 fcport->stats_busy = BFA_TRUE; 3839 if (!list_empty(&fcport->statsclr_pending_q))
3829 fcport->stats_ret = stats; 3840 return BFA_STATUS_DEVBUSY;
3830 fcport->stats_cbfn = cbfn;
3831 fcport->stats_cbarg = cbarg;
3832 3841
3833 bfa_fcport_send_stats_get(fcport); 3842 if (list_empty(&fcport->stats_pending_q)) {
3843 list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
3844 bfa_fcport_send_stats_get(fcport);
3845 bfa_timer_start(bfa, &fcport->timer,
3846 bfa_fcport_stats_get_timeout,
3847 fcport, BFA_FCPORT_STATS_TOV);
3848 } else
3849 list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
3834 3850
3835 bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
3836 fcport, BFA_FCPORT_STATS_TOV);
3837 return BFA_STATUS_OK; 3851 return BFA_STATUS_OK;
3838} 3852}
3839 3853
@@ -3841,27 +3855,25 @@ bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
3841 * Reset port statistics (FCQoS or FCoE). 3855 * Reset port statistics (FCQoS or FCoE).
3842 */ 3856 */
3843bfa_status_t 3857bfa_status_t
3844bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) 3858bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
3845{ 3859{
3846 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); 3860 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3847 3861
3848 if (fcport->stats_busy) { 3862 if (!list_empty(&fcport->stats_pending_q))
3849 bfa_trc(bfa, fcport->stats_busy);
3850 return BFA_STATUS_DEVBUSY; 3863 return BFA_STATUS_DEVBUSY;
3851 }
3852 3864
3853 fcport->stats_busy = BFA_TRUE; 3865 if (list_empty(&fcport->statsclr_pending_q)) {
3854 fcport->stats_cbfn = cbfn; 3866 list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
3855 fcport->stats_cbarg = cbarg; 3867 bfa_fcport_send_stats_clear(fcport);
3868 bfa_timer_start(bfa, &fcport->timer,
3869 bfa_fcport_stats_clr_timeout,
3870 fcport, BFA_FCPORT_STATS_TOV);
3871 } else
3872 list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
3856 3873
3857 bfa_fcport_send_stats_clear(fcport);
3858
3859 bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
3860 fcport, BFA_FCPORT_STATS_TOV);
3861 return BFA_STATUS_OK; 3874 return BFA_STATUS_OK;
3862} 3875}
3863 3876
3864
3865/* 3877/*
3866 * Fetch port attributes. 3878 * Fetch port attributes.
3867 */ 3879 */
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index fbe513a671b5..01db3520070f 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -441,7 +441,6 @@ void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
441 */ 441 */
442 442
443#define BFA_FCPORT(_bfa) (&((_bfa)->modules.port)) 443#define BFA_FCPORT(_bfa) (&((_bfa)->modules.port))
444typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);
445 444
446/* 445/*
447 * Link notification data structure 446 * Link notification data structure
@@ -495,13 +494,11 @@ struct bfa_fcport_s {
495 u8 *stats_kva; 494 u8 *stats_kva;
496 u64 stats_pa; 495 u64 stats_pa;
497 union bfa_fcport_stats_u *stats; 496 union bfa_fcport_stats_u *stats;
498 union bfa_fcport_stats_u *stats_ret; /* driver stats location */
499 bfa_status_t stats_status; /* stats/statsclr status */ 497 bfa_status_t stats_status; /* stats/statsclr status */
500 bfa_boolean_t stats_busy; /* outstanding stats/statsclr */ 498 struct list_head stats_pending_q;
499 struct list_head statsclr_pending_q;
501 bfa_boolean_t stats_qfull; 500 bfa_boolean_t stats_qfull;
502 u32 stats_reset_time; /* stats reset time stamp */ 501 u32 stats_reset_time; /* stats reset time stamp */
503 bfa_cb_port_t stats_cbfn; /* driver callback function */
504 void *stats_cbarg; /* *!< user callback arg */
505 bfa_boolean_t diag_busy; /* diag busy status */ 502 bfa_boolean_t diag_busy; /* diag busy status */
506 bfa_boolean_t beacon; /* port beacon status */ 503 bfa_boolean_t beacon; /* port beacon status */
507 bfa_boolean_t link_e2e_beacon; /* link beacon status */ 504 bfa_boolean_t link_e2e_beacon; /* link beacon status */
@@ -552,10 +549,9 @@ void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
552 bfa_boolean_t link_e2e_beacon); 549 bfa_boolean_t link_e2e_beacon);
553bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa); 550bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
554bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, 551bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
555 union bfa_fcport_stats_u *stats, 552 struct bfa_cb_pending_q_s *cb);
556 bfa_cb_port_t cbfn, void *cbarg); 553bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa,
557bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, 554 struct bfa_cb_pending_q_s *cb);
558 void *cbarg);
559bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); 555bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
560bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa); 556bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
561bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa); 557bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 26def664cb83..0d920edebac9 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -2023,6 +2023,55 @@ bfad_iocmd_itnim_get_ioprofile(struct bfad_s *bfad, void *cmd)
2023 return 0; 2023 return 0;
2024} 2024}
2025 2025
2026int
2027bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd)
2028{
2029 struct bfa_bsg_fcport_stats_s *iocmd =
2030 (struct bfa_bsg_fcport_stats_s *)cmd;
2031 struct bfad_hal_comp fcomp;
2032 unsigned long flags;
2033 struct bfa_cb_pending_q_s cb_qe;
2034
2035 init_completion(&fcomp.comp);
2036 bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
2037 &fcomp, &iocmd->stats);
2038 spin_lock_irqsave(&bfad->bfad_lock, flags);
2039 iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
2040 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
2041 if (iocmd->status != BFA_STATUS_OK) {
2042 bfa_trc(bfad, iocmd->status);
2043 goto out;
2044 }
2045 wait_for_completion(&fcomp.comp);
2046 iocmd->status = fcomp.status;
2047out:
2048 return 0;
2049}
2050
2051int
2052bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd)
2053{
2054 struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
2055 struct bfad_hal_comp fcomp;
2056 unsigned long flags;
2057 struct bfa_cb_pending_q_s cb_qe;
2058
2059 init_completion(&fcomp.comp);
2060 bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, &fcomp, NULL);
2061
2062 spin_lock_irqsave(&bfad->bfad_lock, flags);
2063 iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
2064 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
2065 if (iocmd->status != BFA_STATUS_OK) {
2066 bfa_trc(bfad, iocmd->status);
2067 goto out;
2068 }
2069 wait_for_completion(&fcomp.comp);
2070 iocmd->status = fcomp.status;
2071out:
2072 return 0;
2073}
2074
2026static int 2075static int
2027bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, 2076bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
2028 unsigned int payload_len) 2077 unsigned int payload_len)
@@ -2291,6 +2340,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
2291 case IOCMD_ITNIM_GET_IOPROFILE: 2340 case IOCMD_ITNIM_GET_IOPROFILE:
2292 rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd); 2341 rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd);
2293 break; 2342 break;
2343 case IOCMD_FCPORT_GET_STATS:
2344 rc = bfad_iocmd_fcport_get_stats(bfad, iocmd);
2345 break;
2346 case IOCMD_FCPORT_RESET_STATS:
2347 rc = bfad_iocmd_fcport_reset_stats(bfad, iocmd);
2348 break;
2294 default: 2349 default:
2295 rc = -EINVAL; 2350 rc = -EINVAL;
2296 break; 2351 break;
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index 91cb2123dec0..f64f3eee6dbf 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -119,6 +119,8 @@ enum {
119 IOCMD_FCPIM_PROFILE_ON, 119 IOCMD_FCPIM_PROFILE_ON,
120 IOCMD_FCPIM_PROFILE_OFF, 120 IOCMD_FCPIM_PROFILE_OFF,
121 IOCMD_ITNIM_GET_IOPROFILE, 121 IOCMD_ITNIM_GET_IOPROFILE,
122 IOCMD_FCPORT_GET_STATS,
123 IOCMD_FCPORT_RESET_STATS,
122}; 124};
123 125
124struct bfa_bsg_gen_s { 126struct bfa_bsg_gen_s {
@@ -150,6 +152,13 @@ struct bfa_bsg_itnim_ioprofile_s {
150 struct bfa_itnim_ioprofile_s ioprofile; 152 struct bfa_itnim_ioprofile_s ioprofile;
151}; 153};
152 154
155struct bfa_bsg_fcport_stats_s {
156 bfa_status_t status;
157 u16 bfad_num;
158 u16 rsvd;
159 union bfa_fcport_stats_u stats;
160};
161
153struct bfa_bsg_ioc_name_s { 162struct bfa_bsg_ioc_name_s {
154 bfa_status_t status; 163 bfa_status_t status;
155 u16 bfad_num; 164 u16 bfad_num;