diff options
author | Matthew Wilcox <matthew@wil.cx> | 2007-09-09 10:56:31 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:47:44 -0400 |
commit | b66229258f88a06ecdb8998066861b3ad8ad6a2a (patch) | |
tree | 04bccc41fe172c9035b9e0d7bf1804b5d2865eb2 /drivers/scsi/advansys.c | |
parent | c2dce2fabc7f0b559e920890d13e7b8ecfc91e13 (diff) |
[SCSI] advansys: Remove `waiting' queue
If the adapter is busy, return the request to the midlayer rather than
queueing it in the driver. asc_execute_queue() and asc_dequeue() become
unused, and we don't need to print out stats on the waiting queue any more.
Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/advansys.c')
-rw-r--r-- | drivers/scsi/advansys.c | 186 |
1 files changed, 9 insertions, 177 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index fe289b1d7ddb..526239a21332 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -2852,7 +2852,6 @@ typedef struct asc_board { | |||
2852 | } dvc_cfg; | 2852 | } dvc_cfg; |
2853 | ushort asc_n_io_port; /* Number I/O ports. */ | 2853 | ushort asc_n_io_port; /* Number I/O ports. */ |
2854 | asc_queue_t active; /* Active command queue */ | 2854 | asc_queue_t active; /* Active command queue */ |
2855 | asc_queue_t waiting; /* Waiting command queue */ | ||
2856 | asc_queue_t done; /* Done command queue */ | 2855 | asc_queue_t done; /* Done command queue */ |
2857 | ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ | 2856 | ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ |
2858 | struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ | 2857 | struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ |
@@ -2922,10 +2921,8 @@ static int asc_build_req(asc_board_t *, struct scsi_cmnd *); | |||
2922 | static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); | 2921 | static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); |
2923 | static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); | 2922 | static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); |
2924 | static void asc_enqueue(asc_queue_t *, REQP, int); | 2923 | static void asc_enqueue(asc_queue_t *, REQP, int); |
2925 | static REQP asc_dequeue(asc_queue_t *, int); | ||
2926 | static REQP asc_dequeue_list(asc_queue_t *, REQP *, int); | 2924 | static REQP asc_dequeue_list(asc_queue_t *, REQP *, int); |
2927 | static int asc_rmqueue(asc_queue_t *, REQP); | 2925 | static int asc_rmqueue(asc_queue_t *, REQP); |
2928 | static void asc_execute_queue(asc_queue_t *); | ||
2929 | #ifdef CONFIG_PROC_FS | 2926 | #ifdef CONFIG_PROC_FS |
2930 | static int asc_proc_copy(off_t, off_t, char *, int, char *, int); | 2927 | static int asc_proc_copy(off_t, off_t, char *, int, char *, int); |
2931 | static int asc_prt_board_devices(struct Scsi_Host *, char *, int); | 2928 | static int asc_prt_board_devices(struct Scsi_Host *, char *, int); |
@@ -3274,6 +3271,7 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) | |||
3274 | asc_board_t *boardp; | 3271 | asc_board_t *boardp; |
3275 | ulong flags; | 3272 | ulong flags; |
3276 | struct scsi_cmnd *done_scp; | 3273 | struct scsi_cmnd *done_scp; |
3274 | int asc_res, result = 0; | ||
3277 | 3275 | ||
3278 | shost = scp->device->host; | 3276 | shost = scp->device->host; |
3279 | boardp = ASC_BOARDP(shost); | 3277 | boardp = ASC_BOARDP(shost); |
@@ -3302,37 +3300,13 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) | |||
3302 | return 0; | 3300 | return 0; |
3303 | } | 3301 | } |
3304 | 3302 | ||
3305 | /* | ||
3306 | * Attempt to execute any waiting commands for the board. | ||
3307 | */ | ||
3308 | if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { | ||
3309 | ASC_DBG(1, | ||
3310 | "advansys_queuecommand: before asc_execute_queue() waiting\n"); | ||
3311 | asc_execute_queue(&boardp->waiting); | ||
3312 | } | ||
3313 | |||
3314 | /* | ||
3315 | * Save the function pointer to Linux mid-level 'done' function | ||
3316 | * and attempt to execute the command. | ||
3317 | * | ||
3318 | * If ASC_NOERROR is returned the request has been added to the | ||
3319 | * board's 'active' queue and will be completed by the interrupt | ||
3320 | * handler. | ||
3321 | * | ||
3322 | * If ASC_BUSY is returned add the request to the board's per | ||
3323 | * target waiting list. This is the first time the request has | ||
3324 | * been tried. Add it to the back of the waiting list. It will be | ||
3325 | * retried later. | ||
3326 | * | ||
3327 | * If an error occurred, the request will have been placed on the | ||
3328 | * board's 'done' queue and must be completed before returning. | ||
3329 | */ | ||
3330 | scp->scsi_done = done; | 3303 | scp->scsi_done = done; |
3331 | switch (asc_execute_scsi_cmnd(scp)) { | 3304 | asc_res = asc_execute_scsi_cmnd(scp); |
3305 | switch (asc_res) { | ||
3332 | case ASC_NOERROR: | 3306 | case ASC_NOERROR: |
3333 | break; | 3307 | break; |
3334 | case ASC_BUSY: | 3308 | case ASC_BUSY: |
3335 | asc_enqueue(&boardp->waiting, scp, ASC_BACK); | 3309 | result = SCSI_MLQUEUE_HOST_BUSY; |
3336 | break; | 3310 | break; |
3337 | case ASC_ERROR: | 3311 | case ASC_ERROR: |
3338 | default: | 3312 | default: |
@@ -3343,7 +3317,7 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) | |||
3343 | } | 3317 | } |
3344 | spin_unlock_irqrestore(&boardp->lock, flags); | 3318 | spin_unlock_irqrestore(&boardp->lock, flags); |
3345 | 3319 | ||
3346 | return 0; | 3320 | return result; |
3347 | } | 3321 | } |
3348 | 3322 | ||
3349 | /* | 3323 | /* |
@@ -3488,33 +3462,6 @@ static int advansys_reset(struct scsi_cmnd *scp) | |||
3488 | } | 3462 | } |
3489 | } | 3463 | } |
3490 | 3464 | ||
3491 | /* | ||
3492 | * Dequeue all 'waiting' requests and set the request status | ||
3493 | * to DID_RESET. | ||
3494 | */ | ||
3495 | if (done_scp == NULL) { | ||
3496 | done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, | ||
3497 | ASC_TID_ALL); | ||
3498 | for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { | ||
3499 | tscp->result = HOST_BYTE(DID_RESET); | ||
3500 | } | ||
3501 | } else { | ||
3502 | /* Append to 'done_scp' at the end with 'last_scp'. */ | ||
3503 | ASC_ASSERT(last_scp != NULL); | ||
3504 | last_scp->host_scribble = | ||
3505 | (unsigned char *)asc_dequeue_list(&boardp->waiting, | ||
3506 | &new_last_scp, | ||
3507 | ASC_TID_ALL); | ||
3508 | if (new_last_scp != NULL) { | ||
3509 | ASC_ASSERT(REQPNEXT(last_scp) != NULL); | ||
3510 | for (tscp = REQPNEXT(last_scp); tscp; | ||
3511 | tscp = REQPNEXT(tscp)) { | ||
3512 | tscp->result = HOST_BYTE(DID_RESET); | ||
3513 | } | ||
3514 | last_scp = new_last_scp; | ||
3515 | } | ||
3516 | } | ||
3517 | |||
3518 | /* Save the time of the most recently completed reset. */ | 3465 | /* Save the time of the most recently completed reset. */ |
3519 | boardp->last_reset = jiffies; | 3466 | boardp->last_reset = jiffies; |
3520 | 3467 | ||
@@ -3650,7 +3597,7 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id) | |||
3650 | } | 3597 | } |
3651 | 3598 | ||
3652 | /* | 3599 | /* |
3653 | * Start waiting requests and create a list of completed requests. | 3600 | * Create a list of completed requests. |
3654 | * | 3601 | * |
3655 | * If a reset request is being performed for the board, the reset | 3602 | * If a reset request is being performed for the board, the reset |
3656 | * handler will complete pending requests after it has completed. | 3603 | * handler will complete pending requests after it has completed. |
@@ -3659,13 +3606,6 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id) | |||
3659 | ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, " | 3606 | ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, " |
3660 | "last_scp 0x%p\n", done_scp, last_scp); | 3607 | "last_scp 0x%p\n", done_scp, last_scp); |
3661 | 3608 | ||
3662 | /* Start any waiting commands for the board. */ | ||
3663 | if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { | ||
3664 | ASC_DBG(1, "advansys_interrupt: before " | ||
3665 | "asc_execute_queue()\n"); | ||
3666 | asc_execute_queue(&boardp->waiting); | ||
3667 | } | ||
3668 | |||
3669 | /* | 3609 | /* |
3670 | * Add to the list of requests that must be completed. | 3610 | * Add to the list of requests that must be completed. |
3671 | * | 3611 | * |
@@ -3986,8 +3926,8 @@ static void asc_scsi_done_list(struct scsi_cmnd *scp) | |||
3986 | * If this function returns ASC_NOERROR the request has been enqueued | 3926 | * If this function returns ASC_NOERROR the request has been enqueued |
3987 | * on the board's 'done' queue and must be completed by the caller. | 3927 | * on the board's 'done' queue and must be completed by the caller. |
3988 | * | 3928 | * |
3989 | * If ASC_BUSY is returned the request will be enqueued by the | 3929 | * If ASC_BUSY is returned the request will be returned to the midlayer |
3990 | * caller on the target's waiting queue and re-tried later. | 3930 | * and re-tried later. |
3991 | */ | 3931 | */ |
3992 | static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | 3932 | static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) |
3993 | { | 3933 | { |
@@ -4043,10 +3983,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
4043 | "ASC_NOERROR\n"); | 3983 | "ASC_NOERROR\n"); |
4044 | break; | 3984 | break; |
4045 | case ASC_BUSY: | 3985 | case ASC_BUSY: |
4046 | /* | ||
4047 | * Caller will enqueue request on the target's waiting | ||
4048 | * queue and retry later. | ||
4049 | */ | ||
4050 | ASC_STATS(scp->device->host, exe_busy); | 3986 | ASC_STATS(scp->device->host, exe_busy); |
4051 | break; | 3987 | break; |
4052 | case ASC_ERROR: | 3988 | case ASC_ERROR: |
@@ -4087,10 +4023,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
4087 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " | 4023 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " |
4088 | "ASC_BUSY\n"); | 4024 | "ASC_BUSY\n"); |
4089 | /* | 4025 | /* |
4090 | * If busy is returned the request has not been | ||
4091 | * enqueued. It will be enqueued by the caller on the | ||
4092 | * target's waiting queue and retried later. | ||
4093 | * | ||
4094 | * The asc_stats fields 'adv_build_noreq' and | 4026 | * The asc_stats fields 'adv_build_noreq' and |
4095 | * 'adv_build_nosg' count wide board busy conditions. | 4027 | * 'adv_build_nosg' count wide board busy conditions. |
4096 | * They are updated in adv_build_req and | 4028 | * They are updated in adv_build_req and |
@@ -4127,10 +4059,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
4127 | "ASC_NOERROR\n"); | 4059 | "ASC_NOERROR\n"); |
4128 | break; | 4060 | break; |
4129 | case ASC_BUSY: | 4061 | case ASC_BUSY: |
4130 | /* | ||
4131 | * Caller will enqueue request on the target's waiting | ||
4132 | * queue and retry later. | ||
4133 | */ | ||
4134 | ASC_STATS(scp->device->host, exe_busy); | 4062 | ASC_STATS(scp->device->host, exe_busy); |
4135 | break; | 4063 | break; |
4136 | case ASC_ERROR: | 4064 | case ASC_ERROR: |
@@ -5005,39 +4933,6 @@ static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) | |||
5005 | } | 4933 | } |
5006 | 4934 | ||
5007 | /* | 4935 | /* |
5008 | * Return first queued 'REQP' on the specified queue for | ||
5009 | * the specified target device. Clear the 'tidmask' bit for | ||
5010 | * the device if no more commands are left queued for it. | ||
5011 | * | ||
5012 | * 'REQPNEXT(reqp)' returns reqp's next pointer. | ||
5013 | */ | ||
5014 | static REQP asc_dequeue(asc_queue_t *ascq, int tid) | ||
5015 | { | ||
5016 | REQP reqp; | ||
5017 | |||
5018 | ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid); | ||
5019 | ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); | ||
5020 | if ((reqp = ascq->q_first[tid]) != NULL) { | ||
5021 | ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); | ||
5022 | ascq->q_first[tid] = REQPNEXT(reqp); | ||
5023 | /* If the queue is empty, clear its bit and the last pointer. */ | ||
5024 | if (ascq->q_first[tid] == NULL) { | ||
5025 | ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); | ||
5026 | ASC_ASSERT(ascq->q_last[tid] == reqp); | ||
5027 | ascq->q_last[tid] = NULL; | ||
5028 | } | ||
5029 | #ifdef ADVANSYS_STATS | ||
5030 | /* Maintain request queue statistics. */ | ||
5031 | ascq->q_cur_cnt[tid]--; | ||
5032 | ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); | ||
5033 | REQTIMESTAT("asc_dequeue", ascq, reqp, tid); | ||
5034 | #endif /* ADVANSYS_STATS */ | ||
5035 | } | ||
5036 | ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp); | ||
5037 | return reqp; | ||
5038 | } | ||
5039 | |||
5040 | /* | ||
5041 | * Return a pointer to a singly linked list of all the requests queued | 4936 | * Return a pointer to a singly linked list of all the requests queued |
5042 | * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'. | 4937 | * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'. |
5043 | * | 4938 | * |
@@ -5202,45 +5097,6 @@ static int asc_rmqueue(asc_queue_t *ascq, REQP reqp) | |||
5202 | return ret; | 5097 | return ret; |
5203 | } | 5098 | } |
5204 | 5099 | ||
5205 | /* | ||
5206 | * Execute as many queued requests as possible for the specified queue. | ||
5207 | * | ||
5208 | * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd. | ||
5209 | */ | ||
5210 | static void asc_execute_queue(asc_queue_t *ascq) | ||
5211 | { | ||
5212 | ADV_SCSI_BIT_ID_TYPE scan_tidmask; | ||
5213 | REQP reqp; | ||
5214 | int i; | ||
5215 | |||
5216 | ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq); | ||
5217 | /* | ||
5218 | * Execute queued commands for devices attached to | ||
5219 | * the current board in round-robin fashion. | ||
5220 | */ | ||
5221 | scan_tidmask = ascq->q_tidmask; | ||
5222 | do { | ||
5223 | for (i = 0; i <= ADV_MAX_TID; i++) { | ||
5224 | if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) { | ||
5225 | if ((reqp = asc_dequeue(ascq, i)) == NULL) { | ||
5226 | scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); | ||
5227 | } else | ||
5228 | if (asc_execute_scsi_cmnd | ||
5229 | ((struct scsi_cmnd *)reqp) | ||
5230 | == ASC_BUSY) { | ||
5231 | scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); | ||
5232 | /* | ||
5233 | * The request returned ASC_BUSY. Enqueue at the front of | ||
5234 | * target's waiting list to maintain correct ordering. | ||
5235 | */ | ||
5236 | asc_enqueue(ascq, reqp, ASC_FRONT); | ||
5237 | } | ||
5238 | } | ||
5239 | } | ||
5240 | } while (scan_tidmask); | ||
5241 | return; | ||
5242 | } | ||
5243 | |||
5244 | #ifdef CONFIG_PROC_FS | 5100 | #ifdef CONFIG_PROC_FS |
5245 | /* | 5101 | /* |
5246 | * asc_prt_board_devices() | 5102 | * asc_prt_board_devices() |
@@ -6723,7 +6579,6 @@ asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) | |||
6723 | ushort chip_scsi_id; | 6579 | ushort chip_scsi_id; |
6724 | asc_board_t *boardp; | 6580 | asc_board_t *boardp; |
6725 | asc_queue_t *active; | 6581 | asc_queue_t *active; |
6726 | asc_queue_t *waiting; | ||
6727 | 6582 | ||
6728 | leftlen = cplen; | 6583 | leftlen = cplen; |
6729 | totlen = len = 0; | 6584 | totlen = len = 0; |
@@ -6732,7 +6587,6 @@ asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) | |||
6732 | s = &boardp->asc_stats; | 6587 | s = &boardp->asc_stats; |
6733 | 6588 | ||
6734 | active = &ASC_BOARDP(shost)->active; | 6589 | active = &ASC_BOARDP(shost)->active; |
6735 | waiting = &ASC_BOARDP(shost)->waiting; | ||
6736 | 6590 | ||
6737 | if (ASC_NARROW_BOARD(boardp)) { | 6591 | if (ASC_NARROW_BOARD(boardp)) { |
6738 | chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; | 6592 | chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; |
@@ -6746,8 +6600,7 @@ asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) | |||
6746 | } | 6600 | } |
6747 | 6601 | ||
6748 | do { | 6602 | do { |
6749 | if (active->q_tot_cnt[tgt_id] > 0 | 6603 | if (active->q_tot_cnt[tgt_id] > 0) { |
6750 | || waiting->q_tot_cnt[tgt_id] > 0) { | ||
6751 | len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id); | 6604 | len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id); |
6752 | ASC_PRT_NEXT(); | 6605 | ASC_PRT_NEXT(); |
6753 | 6606 | ||
@@ -6771,27 +6624,6 @@ asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) | |||
6771 | q_tot_cnt | 6624 | q_tot_cnt |
6772 | [tgt_id])); | 6625 | [tgt_id])); |
6773 | ASC_PRT_NEXT(); | 6626 | ASC_PRT_NEXT(); |
6774 | |||
6775 | len = asc_prt_line(cp, leftlen, | ||
6776 | " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", | ||
6777 | waiting->q_cur_cnt[tgt_id], | ||
6778 | waiting->q_max_cnt[tgt_id], | ||
6779 | waiting->q_tot_cnt[tgt_id], | ||
6780 | waiting->q_min_tim[tgt_id], | ||
6781 | waiting->q_max_tim[tgt_id], | ||
6782 | (waiting->q_tot_cnt[tgt_id] == | ||
6783 | 0) ? 0 : (waiting-> | ||
6784 | q_tot_tim[tgt_id] / | ||
6785 | waiting-> | ||
6786 | q_tot_cnt[tgt_id]), | ||
6787 | (waiting->q_tot_cnt[tgt_id] == | ||
6788 | 0) ? 0 : ASC_TENTHS(waiting-> | ||
6789 | q_tot_tim | ||
6790 | [tgt_id], | ||
6791 | waiting-> | ||
6792 | q_tot_cnt | ||
6793 | [tgt_id])); | ||
6794 | ASC_PRT_NEXT(); | ||
6795 | } | 6627 | } |
6796 | } while (0); | 6628 | } while (0); |
6797 | 6629 | ||