diff options
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r-- | drivers/scsi/bfa/bfa.h | 21 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_core.c | 10 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_svc.c | 130 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_svc.h | 14 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.c | 55 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.h | 9 |
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 @@ | |||
27 | struct bfa_s; | 27 | struct bfa_s; |
28 | 28 | ||
29 | typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m); | 29 | typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m); |
30 | typedef 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 | ||
418 | struct 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, | |||
3138 | static void | 3141 | static 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 | ||
3186 | static void | 3196 | static void |
@@ -3210,7 +3220,9 @@ bfa_fcport_send_stats_get(void *cbarg) | |||
3210 | static void | 3220 | static 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 | ||
3248 | static void | 3264 | static 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 | */ |
3817 | bfa_status_t | 3831 | bfa_status_t |
3818 | bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, | 3832 | bfa_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 | */ |
3843 | bfa_status_t | 3857 | bfa_status_t |
3844 | bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) | 3858 | bfa_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)) |
444 | typedef 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); |
553 | bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa); | 550 | bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa); |
554 | bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, | 551 | bfa_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); | 553 | bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, |
557 | bfa_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); | ||
559 | bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); | 555 | bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); |
560 | bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa); | 556 | bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa); |
561 | bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa); | 557 | bfa_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 | ||
2026 | int | ||
2027 | bfad_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; | ||
2047 | out: | ||
2048 | return 0; | ||
2049 | } | ||
2050 | |||
2051 | int | ||
2052 | bfad_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; | ||
2071 | out: | ||
2072 | return 0; | ||
2073 | } | ||
2074 | |||
2026 | static int | 2075 | static int |
2027 | bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, | 2076 | bfad_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 | ||
124 | struct bfa_bsg_gen_s { | 126 | struct 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 | ||
155 | struct 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 | |||
153 | struct bfa_bsg_ioc_name_s { | 162 | struct bfa_bsg_ioc_name_s { |
154 | bfa_status_t status; | 163 | bfa_status_t status; |
155 | u16 bfad_num; | 164 | u16 bfad_num; |