} dvc_cfg;
ushort asc_n_io_port; /* Number I/O ports. */
asc_queue_t active; /* Active command queue */
- asc_queue_t done; /* Done command queue */
ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
return info;
}
+static void asc_scsi_done(struct scsi_cmnd *scp)
+{
+ struct asc_board *boardp = ASC_BOARDP(scp->device->host);
+
+ if (scp->use_sg)
+ dma_unmap_sg(boardp->dev,
+ (struct scatterlist *)scp->request_buffer,
+ scp->use_sg, scp->sc_data_direction);
+ else if (scp->request_bufflen)
+ dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
+ scp->request_bufflen, scp->sc_data_direction);
+
+ ASC_STATS(scp->device->host, done);
+
+ scp->scsi_done(scp);
+}
+
/*
* advansys_queuecommand() - interrupt-driven I/O entrypoint.
*
struct Scsi_Host *shost;
asc_board_t *boardp;
ulong flags;
- struct scsi_cmnd *done_scp;
int asc_res, result = 0;
shost = scp->device->host;
break;
case ASC_ERROR:
default:
- done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
/* Interrupts could be enabled here. */
- asc_scsi_done_list(done_scp);
+ asc_scsi_done(scp);
break;
}
spin_unlock_irqrestore(&boardp->lock, flags);
}
/* Board lock is held. */
- /*
- * Dequeue all board 'done' requests. A pointer to the last request
- * is returned in 'last_scp'.
- */
- done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL);
-
/*
* Dequeue all board 'active' requests for all devices and set
* the request status to DID_RESET. A pointer to the last request
static irqreturn_t advansys_interrupt(int irq, void *dev_id)
{
unsigned long flags;
- struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
- struct scsi_cmnd *new_last_scp;
struct Scsi_Host *shost = dev_id;
asc_board_t *boardp = ASC_BOARDP(shost);
irqreturn_t result = IRQ_NONE;
}
}
- /*
- * Create a list of completed requests.
- *
- * If a reset request is being performed for the board, the reset
- * handler will complete pending requests after it has completed.
- */
- if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
- ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, "
- "last_scp 0x%p\n", done_scp, last_scp);
-
- /*
- * Add to the list of requests that must be completed.
- *
- * 'done_scp' will always be NULL on the first iteration of
- * this loop. 'last_scp' is set at the same time as 'done_scp'.
- */
- if (done_scp == NULL) {
- done_scp = asc_dequeue_list(&boardp->done,
- &last_scp, ASC_TID_ALL);
- } else {
- ASC_ASSERT(last_scp != NULL);
- last_scp->host_scribble =
- (unsigned char *)asc_dequeue_list(&boardp->
- done,
- &new_last_scp,
- ASC_TID_ALL);
- if (new_last_scp != NULL) {
- ASC_ASSERT(REQPNEXT(last_scp) != NULL);
- last_scp = new_last_scp;
- }
- }
- }
spin_unlock_irqrestore(&boardp->lock, flags);
/*
* If interrupts were enabled on entry, then they
* are now enabled here.
- *
- * Complete all requests on the done list.
*/
- asc_scsi_done_list(done_scp);
-
ASC_DBG(1, "advansys_interrupt: end\n");
return result;
}
ASC_DBG(2, "asc_scsi_done_list: begin\n");
while (scp != NULL) {
- asc_board_t *boardp;
-
ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp);
tscp = REQPNEXT(scp);
scp->host_scribble = NULL;
- boardp = ASC_BOARDP(scp->device->host);
-
- if (scp->use_sg)
- dma_unmap_sg(boardp->dev,
- (struct scatterlist *)scp->request_buffer,
- scp->use_sg, scp->sc_data_direction);
- else if (scp->request_bufflen)
- dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
- scp->request_bufflen,
- scp->sc_data_direction);
-
- ASC_STATS(scp->device->host, done);
- ASC_ASSERT(scp->scsi_done != NULL);
-
- scp->scsi_done(scp);
+ asc_scsi_done(scp);
scp = tscp;
}
* on the board's 'active' queue and will be completed from the
* interrupt handler.
*
- * If this function returns ASC_NOERROR the request has been enqueued
- * on the board's 'done' queue and must be completed by the caller.
+ * If this function returns ASC_ERROR the host error code has been set,
+ * and the called must call asc_scsi_done.
*
* If ASC_BUSY is returned the request will be returned to the midlayer
* and re-tried later.
boardp->id, asc_dvc_varp->err_code);
ASC_STATS(scp->device->host, exe_error);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
break;
default:
ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
boardp->id, asc_dvc_varp->err_code);
ASC_STATS(scp->device->host, exe_unknown);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
break;
}
} else {
*/
return ASC_BUSY;
case ASC_ERROR:
- /*
- * If an error is returned, then the request has been
- * queued on the board done queue. It will be completed
- * by the caller.
- */
default:
ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
"ASC_ERROR\n");
boardp->id, adv_dvc_varp->err_code);
ASC_STATS(scp->device->host, exe_error);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
break;
default:
ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
boardp->id, adv_dvc_varp->err_code);
ASC_STATS(scp->device->host, exe_unknown);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
break;
}
}
* The global structures 'asc_scsi_q' and 'asc_sg_head' are
* used to build the request.
*
- * If an error occurs, then queue the request on the board done
- * queue and return ASC_ERROR.
+ * If an error occurs, then return ASC_ERROR.
*/
static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
{
"ASC_MAX_CDB_LEN %d\n", boardp->id, scp->cmd_len,
ASC_MAX_CDB_LEN);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
return ASC_ERROR;
}
asc_scsi_q.cdbptr = &scp->cmnd[0];
dma_unmap_sg(boardp->dev, slp, scp->use_sg,
scp->sc_data_direction);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
return ASC_ERROR;
}
("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n",
boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
return ASC_ERROR;
}
scsiqp->cdb_len = scp->cmd_len;
dma_unmap_sg(boardp->dev, slp, scp->use_sg,
scp->sc_data_direction);
scp->result = HOST_BYTE(DID_ERROR);
- asc_enqueue(&boardp->done, scp, ASC_BACK);
/*
* Free the 'adv_req_t' structure by adding it back
boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
}
- /*
- * Because interrupts may be enabled by the 'struct scsi_cmnd' done
- * function, add the command to the end of the board's done queue.
- * The done function for the command will be called from
- * advansys_interrupt().
- */
- asc_enqueue(&boardp->done, scp, ASC_BACK);
+ asc_scsi_done(scp);
return;
}
boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
}
- /*
- * Because interrupts may be enabled by the 'struct scsi_cmnd' done
- * function, add the command to the end of the board's done queue.
- * The done function for the command will be called from
- * advansys_interrupt().
- */
- asc_enqueue(&boardp->done, scp, ASC_BACK);
+ asc_scsi_done(scp);
/*
* Free all 'adv_sgblk_t' structures allocated for the request.