diff options
author | Matthew Wilcox <matthew@wil.cx> | 2007-09-09 10:56:33 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:47:52 -0400 |
commit | 6ed1ef0786094f06d2462aeeb6ad7bf9f5f9fc18 (patch) | |
tree | 5dbbceb48294b66ea0635a8717c790740d244125 /drivers/scsi | |
parent | 7686f02aa8a380b3b0322179090f3c83ee4df977 (diff) |
[SCSI] advansys: Remove `done' queue
- Move the guts of asc_scsi_done_list() into a new function, asc_scsi_done.
- Call asc_scsi_done() in asc_isr_callback() and adv_isr_callback(). The
comment was wrong; scsi_done cannot enable interrupts.
- All other places which queued an scp on the done list are error paths
for queuecommand, and so we can just call asc_scsi_done() in queuecommand
if we receive an error.
- We no longer need to keep a list of done requests in advansys_interrupt
Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/advansys.c | 120 |
1 files changed, 24 insertions, 96 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index cd17f28fd3ba..90f05c52be7e 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 done; /* Done command queue */ | ||
2856 | ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ | 2855 | ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ |
2857 | struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ | 2856 | struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ |
2858 | ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */ | 2857 | ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */ |
@@ -3258,6 +3257,23 @@ static const char *advansys_info(struct Scsi_Host *shost) | |||
3258 | return info; | 3257 | return info; |
3259 | } | 3258 | } |
3260 | 3259 | ||
3260 | static void asc_scsi_done(struct scsi_cmnd *scp) | ||
3261 | { | ||
3262 | struct asc_board *boardp = ASC_BOARDP(scp->device->host); | ||
3263 | |||
3264 | if (scp->use_sg) | ||
3265 | dma_unmap_sg(boardp->dev, | ||
3266 | (struct scatterlist *)scp->request_buffer, | ||
3267 | scp->use_sg, scp->sc_data_direction); | ||
3268 | else if (scp->request_bufflen) | ||
3269 | dma_unmap_single(boardp->dev, scp->SCp.dma_handle, | ||
3270 | scp->request_bufflen, scp->sc_data_direction); | ||
3271 | |||
3272 | ASC_STATS(scp->device->host, done); | ||
3273 | |||
3274 | scp->scsi_done(scp); | ||
3275 | } | ||
3276 | |||
3261 | /* | 3277 | /* |
3262 | * advansys_queuecommand() - interrupt-driven I/O entrypoint. | 3278 | * advansys_queuecommand() - interrupt-driven I/O entrypoint. |
3263 | * | 3279 | * |
@@ -3270,7 +3286,6 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) | |||
3270 | struct Scsi_Host *shost; | 3286 | struct Scsi_Host *shost; |
3271 | asc_board_t *boardp; | 3287 | asc_board_t *boardp; |
3272 | ulong flags; | 3288 | ulong flags; |
3273 | struct scsi_cmnd *done_scp; | ||
3274 | int asc_res, result = 0; | 3289 | int asc_res, result = 0; |
3275 | 3290 | ||
3276 | shost = scp->device->host; | 3291 | shost = scp->device->host; |
@@ -3291,9 +3306,8 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) | |||
3291 | break; | 3306 | break; |
3292 | case ASC_ERROR: | 3307 | case ASC_ERROR: |
3293 | default: | 3308 | default: |
3294 | done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); | ||
3295 | /* Interrupts could be enabled here. */ | 3309 | /* Interrupts could be enabled here. */ |
3296 | asc_scsi_done_list(done_scp); | 3310 | asc_scsi_done(scp); |
3297 | break; | 3311 | break; |
3298 | } | 3312 | } |
3299 | spin_unlock_irqrestore(&boardp->lock, flags); | 3313 | spin_unlock_irqrestore(&boardp->lock, flags); |
@@ -3410,12 +3424,6 @@ static int advansys_reset(struct scsi_cmnd *scp) | |||
3410 | /* Board lock is held. */ | 3424 | /* Board lock is held. */ |
3411 | 3425 | ||
3412 | /* | 3426 | /* |
3413 | * Dequeue all board 'done' requests. A pointer to the last request | ||
3414 | * is returned in 'last_scp'. | ||
3415 | */ | ||
3416 | done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); | ||
3417 | |||
3418 | /* | ||
3419 | * Dequeue all board 'active' requests for all devices and set | 3427 | * Dequeue all board 'active' requests for all devices and set |
3420 | * the request status to DID_RESET. A pointer to the last request | 3428 | * the request status to DID_RESET. A pointer to the last request |
3421 | * is returned in 'last_scp'. | 3429 | * is returned in 'last_scp'. |
@@ -3548,8 +3556,6 @@ static struct scsi_host_template advansys_template = { | |||
3548 | static irqreturn_t advansys_interrupt(int irq, void *dev_id) | 3556 | static irqreturn_t advansys_interrupt(int irq, void *dev_id) |
3549 | { | 3557 | { |
3550 | unsigned long flags; | 3558 | unsigned long flags; |
3551 | struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; | ||
3552 | struct scsi_cmnd *new_last_scp; | ||
3553 | struct Scsi_Host *shost = dev_id; | 3559 | struct Scsi_Host *shost = dev_id; |
3554 | asc_board_t *boardp = ASC_BOARDP(shost); | 3560 | asc_board_t *boardp = ASC_BOARDP(shost); |
3555 | irqreturn_t result = IRQ_NONE; | 3561 | irqreturn_t result = IRQ_NONE; |
@@ -3577,49 +3583,13 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id) | |||
3577 | } | 3583 | } |
3578 | } | 3584 | } |
3579 | 3585 | ||
3580 | /* | ||
3581 | * Create a list of completed requests. | ||
3582 | * | ||
3583 | * If a reset request is being performed for the board, the reset | ||
3584 | * handler will complete pending requests after it has completed. | ||
3585 | */ | ||
3586 | if ((boardp->flags & ASC_HOST_IN_RESET) == 0) { | ||
3587 | ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, " | ||
3588 | "last_scp 0x%p\n", done_scp, last_scp); | ||
3589 | |||
3590 | /* | ||
3591 | * Add to the list of requests that must be completed. | ||
3592 | * | ||
3593 | * 'done_scp' will always be NULL on the first iteration of | ||
3594 | * this loop. 'last_scp' is set at the same time as 'done_scp'. | ||
3595 | */ | ||
3596 | if (done_scp == NULL) { | ||
3597 | done_scp = asc_dequeue_list(&boardp->done, | ||
3598 | &last_scp, ASC_TID_ALL); | ||
3599 | } else { | ||
3600 | ASC_ASSERT(last_scp != NULL); | ||
3601 | last_scp->host_scribble = | ||
3602 | (unsigned char *)asc_dequeue_list(&boardp-> | ||
3603 | done, | ||
3604 | &new_last_scp, | ||
3605 | ASC_TID_ALL); | ||
3606 | if (new_last_scp != NULL) { | ||
3607 | ASC_ASSERT(REQPNEXT(last_scp) != NULL); | ||
3608 | last_scp = new_last_scp; | ||
3609 | } | ||
3610 | } | ||
3611 | } | ||
3612 | spin_unlock_irqrestore(&boardp->lock, flags); | 3586 | spin_unlock_irqrestore(&boardp->lock, flags); |
3613 | 3587 | ||
3614 | /* | 3588 | /* |
3615 | * If interrupts were enabled on entry, then they | 3589 | * If interrupts were enabled on entry, then they |
3616 | * are now enabled here. | 3590 | * are now enabled here. |
3617 | * | ||
3618 | * Complete all requests on the done list. | ||
3619 | */ | 3591 | */ |
3620 | 3592 | ||
3621 | asc_scsi_done_list(done_scp); | ||
3622 | |||
3623 | ASC_DBG(1, "advansys_interrupt: end\n"); | 3593 | ASC_DBG(1, "advansys_interrupt: end\n"); |
3624 | return result; | 3594 | return result; |
3625 | } | 3595 | } |
@@ -3836,27 +3806,11 @@ static void asc_scsi_done_list(struct scsi_cmnd *scp) | |||
3836 | 3806 | ||
3837 | ASC_DBG(2, "asc_scsi_done_list: begin\n"); | 3807 | ASC_DBG(2, "asc_scsi_done_list: begin\n"); |
3838 | while (scp != NULL) { | 3808 | while (scp != NULL) { |
3839 | asc_board_t *boardp; | ||
3840 | |||
3841 | ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp); | 3809 | ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp); |
3842 | tscp = REQPNEXT(scp); | 3810 | tscp = REQPNEXT(scp); |
3843 | scp->host_scribble = NULL; | 3811 | scp->host_scribble = NULL; |
3844 | 3812 | ||
3845 | boardp = ASC_BOARDP(scp->device->host); | 3813 | asc_scsi_done(scp); |
3846 | |||
3847 | if (scp->use_sg) | ||
3848 | dma_unmap_sg(boardp->dev, | ||
3849 | (struct scatterlist *)scp->request_buffer, | ||
3850 | scp->use_sg, scp->sc_data_direction); | ||
3851 | else if (scp->request_bufflen) | ||
3852 | dma_unmap_single(boardp->dev, scp->SCp.dma_handle, | ||
3853 | scp->request_bufflen, | ||
3854 | scp->sc_data_direction); | ||
3855 | |||
3856 | ASC_STATS(scp->device->host, done); | ||
3857 | ASC_ASSERT(scp->scsi_done != NULL); | ||
3858 | |||
3859 | scp->scsi_done(scp); | ||
3860 | 3814 | ||
3861 | scp = tscp; | 3815 | scp = tscp; |
3862 | } | 3816 | } |
@@ -3904,8 +3858,8 @@ static void asc_scsi_done_list(struct scsi_cmnd *scp) | |||
3904 | * on the board's 'active' queue and will be completed from the | 3858 | * on the board's 'active' queue and will be completed from the |
3905 | * interrupt handler. | 3859 | * interrupt handler. |
3906 | * | 3860 | * |
3907 | * If this function returns ASC_NOERROR the request has been enqueued | 3861 | * If this function returns ASC_ERROR the host error code has been set, |
3908 | * on the board's 'done' queue and must be completed by the caller. | 3862 | * and the called must call asc_scsi_done. |
3909 | * | 3863 | * |
3910 | * If ASC_BUSY is returned the request will be returned to the midlayer | 3864 | * If ASC_BUSY is returned the request will be returned to the midlayer |
3911 | * and re-tried later. | 3865 | * and re-tried later. |
@@ -3972,7 +3926,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
3972 | boardp->id, asc_dvc_varp->err_code); | 3926 | boardp->id, asc_dvc_varp->err_code); |
3973 | ASC_STATS(scp->device->host, exe_error); | 3927 | ASC_STATS(scp->device->host, exe_error); |
3974 | scp->result = HOST_BYTE(DID_ERROR); | 3928 | scp->result = HOST_BYTE(DID_ERROR); |
3975 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
3976 | break; | 3929 | break; |
3977 | default: | 3930 | default: |
3978 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | 3931 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " |
@@ -3980,7 +3933,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
3980 | boardp->id, asc_dvc_varp->err_code); | 3933 | boardp->id, asc_dvc_varp->err_code); |
3981 | ASC_STATS(scp->device->host, exe_unknown); | 3934 | ASC_STATS(scp->device->host, exe_unknown); |
3982 | scp->result = HOST_BYTE(DID_ERROR); | 3935 | scp->result = HOST_BYTE(DID_ERROR); |
3983 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
3984 | break; | 3936 | break; |
3985 | } | 3937 | } |
3986 | } else { | 3938 | } else { |
@@ -4011,11 +3963,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
4011 | */ | 3963 | */ |
4012 | return ASC_BUSY; | 3964 | return ASC_BUSY; |
4013 | case ASC_ERROR: | 3965 | case ASC_ERROR: |
4014 | /* | ||
4015 | * If an error is returned, then the request has been | ||
4016 | * queued on the board done queue. It will be completed | ||
4017 | * by the caller. | ||
4018 | */ | ||
4019 | default: | 3966 | default: |
4020 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " | 3967 | ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req " |
4021 | "ASC_ERROR\n"); | 3968 | "ASC_ERROR\n"); |
@@ -4048,7 +3995,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
4048 | boardp->id, adv_dvc_varp->err_code); | 3995 | boardp->id, adv_dvc_varp->err_code); |
4049 | ASC_STATS(scp->device->host, exe_error); | 3996 | ASC_STATS(scp->device->host, exe_error); |
4050 | scp->result = HOST_BYTE(DID_ERROR); | 3997 | scp->result = HOST_BYTE(DID_ERROR); |
4051 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4052 | break; | 3998 | break; |
4053 | default: | 3999 | default: |
4054 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " | 4000 | ASC_PRINT2("asc_execute_scsi_cmnd: board %d: " |
@@ -4056,7 +4002,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
4056 | boardp->id, adv_dvc_varp->err_code); | 4002 | boardp->id, adv_dvc_varp->err_code); |
4057 | ASC_STATS(scp->device->host, exe_unknown); | 4003 | ASC_STATS(scp->device->host, exe_unknown); |
4058 | scp->result = HOST_BYTE(DID_ERROR); | 4004 | scp->result = HOST_BYTE(DID_ERROR); |
4059 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4060 | break; | 4005 | break; |
4061 | } | 4006 | } |
4062 | } | 4007 | } |
@@ -4071,8 +4016,7 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
4071 | * The global structures 'asc_scsi_q' and 'asc_sg_head' are | 4016 | * The global structures 'asc_scsi_q' and 'asc_sg_head' are |
4072 | * used to build the request. | 4017 | * used to build the request. |
4073 | * | 4018 | * |
4074 | * If an error occurs, then queue the request on the board done | 4019 | * If an error occurs, then return ASC_ERROR. |
4075 | * queue and return ASC_ERROR. | ||
4076 | */ | 4020 | */ |
4077 | static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | 4021 | static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) |
4078 | { | 4022 | { |
@@ -4098,7 +4042,6 @@ static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | |||
4098 | "ASC_MAX_CDB_LEN %d\n", boardp->id, scp->cmd_len, | 4042 | "ASC_MAX_CDB_LEN %d\n", boardp->id, scp->cmd_len, |
4099 | ASC_MAX_CDB_LEN); | 4043 | ASC_MAX_CDB_LEN); |
4100 | scp->result = HOST_BYTE(DID_ERROR); | 4044 | scp->result = HOST_BYTE(DID_ERROR); |
4101 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4102 | return ASC_ERROR; | 4045 | return ASC_ERROR; |
4103 | } | 4046 | } |
4104 | asc_scsi_q.cdbptr = &scp->cmnd[0]; | 4047 | asc_scsi_q.cdbptr = &scp->cmnd[0]; |
@@ -4167,7 +4110,6 @@ static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | |||
4167 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, | 4110 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, |
4168 | scp->sc_data_direction); | 4111 | scp->sc_data_direction); |
4169 | scp->result = HOST_BYTE(DID_ERROR); | 4112 | scp->result = HOST_BYTE(DID_ERROR); |
4170 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4171 | return ASC_ERROR; | 4113 | return ASC_ERROR; |
4172 | } | 4114 | } |
4173 | 4115 | ||
@@ -4274,7 +4216,6 @@ adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, | |||
4274 | ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n", | 4216 | ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n", |
4275 | boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN); | 4217 | boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN); |
4276 | scp->result = HOST_BYTE(DID_ERROR); | 4218 | scp->result = HOST_BYTE(DID_ERROR); |
4277 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4278 | return ASC_ERROR; | 4219 | return ASC_ERROR; |
4279 | } | 4220 | } |
4280 | scsiqp->cdb_len = scp->cmd_len; | 4221 | scsiqp->cdb_len = scp->cmd_len; |
@@ -4342,7 +4283,6 @@ adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, | |||
4342 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, | 4283 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, |
4343 | scp->sc_data_direction); | 4284 | scp->sc_data_direction); |
4344 | scp->result = HOST_BYTE(DID_ERROR); | 4285 | scp->result = HOST_BYTE(DID_ERROR); |
4345 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4346 | 4286 | ||
4347 | /* | 4287 | /* |
4348 | * Free the 'adv_req_t' structure by adding it back | 4288 | * Free the 'adv_req_t' structure by adding it back |
@@ -4628,13 +4568,7 @@ static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) | |||
4628 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); | 4568 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); |
4629 | } | 4569 | } |
4630 | 4570 | ||
4631 | /* | 4571 | asc_scsi_done(scp); |
4632 | * Because interrupts may be enabled by the 'struct scsi_cmnd' done | ||
4633 | * function, add the command to the end of the board's done queue. | ||
4634 | * The done function for the command will be called from | ||
4635 | * advansys_interrupt(). | ||
4636 | */ | ||
4637 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4638 | 4572 | ||
4639 | return; | 4573 | return; |
4640 | } | 4574 | } |
@@ -4790,13 +4724,7 @@ static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) | |||
4790 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); | 4724 | boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); |
4791 | } | 4725 | } |
4792 | 4726 | ||
4793 | /* | 4727 | asc_scsi_done(scp); |
4794 | * Because interrupts may be enabled by the 'struct scsi_cmnd' done | ||
4795 | * function, add the command to the end of the board's done queue. | ||
4796 | * The done function for the command will be called from | ||
4797 | * advansys_interrupt(). | ||
4798 | */ | ||
4799 | asc_enqueue(&boardp->done, scp, ASC_BACK); | ||
4800 | 4728 | ||
4801 | /* | 4729 | /* |
4802 | * Free all 'adv_sgblk_t' structures allocated for the request. | 4730 | * Free all 'adv_sgblk_t' structures allocated for the request. |