diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2011-07-20 20:02:11 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-27 06:48:52 -0400 |
commit | 37ea0558b87abb151245bc750070a4dcda490aca (patch) | |
tree | 352d00d22b8f9c91ace2dc8d72dc465deb6ffa7b /drivers/scsi/bfa/bfa_svc.c | |
parent | 42a8e6e298f39518445785c53a16357267db37ef (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/bfa_svc.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_svc.c | 130 |
1 files changed, 71 insertions, 59 deletions
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 | */ |