scsi: introduce scsi_req_continue

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Paolo Bonzini 2011-04-18 15:28:11 +02:00
parent 43a2b33957
commit ad3376cc55
7 changed files with 47 additions and 60 deletions

View file

@ -253,11 +253,10 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
s->dma_counter = 0; s->dma_counter = 0;
if (datalen > 0) { if (datalen > 0) {
s->rregs[ESP_RSTAT] |= STAT_DI; s->rregs[ESP_RSTAT] |= STAT_DI;
s->current_dev->info->read_data(s->current_req);
} else { } else {
s->rregs[ESP_RSTAT] |= STAT_DO; s->rregs[ESP_RSTAT] |= STAT_DO;
s->current_dev->info->write_data(s->current_req);
} }
scsi_req_continue(s->current_req);
} }
s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
s->rregs[ESP_RSEQ] = SEQ_CD; s->rregs[ESP_RSEQ] = SEQ_CD;
@ -383,22 +382,17 @@ static void esp_do_dma(ESPState *s)
else else
s->ti_size -= len; s->ti_size -= len;
if (s->async_len == 0) { if (s->async_len == 0) {
if (to_device) { scsi_req_continue(s->current_req);
// ti_size is negative
s->current_dev->info->write_data(s->current_req);
} else {
s->current_dev->info->read_data(s->current_req);
/* If there is still data to be read from the device then /* If there is still data to be read from the device then
complete the DMA operation immediately. Otherwise defer complete the DMA operation immediately. Otherwise defer
until the scsi layer has completed. */ until the scsi layer has completed. */
if (s->dma_left == 0 && s->ti_size > 0) { if (to_device || s->dma_left != 0 || s->ti_size == 0) {
esp_dma_done(s); return;
} }
} }
} else {
/* Partially filled a scsi buffer. Complete immediately. */ /* Partially filled a scsi buffer. Complete immediately. */
esp_dma_done(s); esp_dma_done(s);
}
} }
static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg) static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg)

View file

@ -580,13 +580,7 @@ static void lsi_do_dma(LSIState *s, int out)
s->current->dma_len -= count; s->current->dma_len -= count;
if (s->current->dma_len == 0) { if (s->current->dma_len == 0) {
s->current->dma_buf = NULL; s->current->dma_buf = NULL;
if (out) { scsi_req_continue(s->current->req);
/* Write the data. */
dev->info->write_data(s->current->req);
} else {
/* Request any remaining data. */
dev->info->read_data(s->current->req);
}
} else { } else {
s->current->dma_buf += count; s->current->dma_buf += count;
lsi_resume_script(s); lsi_resume_script(s);
@ -791,14 +785,14 @@ static void lsi_do_command(LSIState *s)
s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun); s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun);
n = scsi_req_enqueue(s->current->req, buf); n = scsi_req_enqueue(s->current->req, buf);
if (n) {
if (n > 0) { if (n > 0) {
lsi_set_phase(s, PHASE_DI); lsi_set_phase(s, PHASE_DI);
dev->info->read_data(s->current->req);
} else if (n < 0) { } else if (n < 0) {
lsi_set_phase(s, PHASE_DO); lsi_set_phase(s, PHASE_DO);
dev->info->write_data(s->current->req);
} }
scsi_req_continue(s->current->req);
}
if (!s->command_complete) { if (!s->command_complete) {
if (n) { if (n) {
/* Command did not complete immediately so disconnect. */ /* Command did not complete immediately so disconnect. */

View file

@ -602,11 +602,21 @@ void scsi_req_unref(SCSIRequest *req)
} }
} }
/* Tell the device that we finished processing this chunk of I/O. It
will start the next chunk or complete the command. */
void scsi_req_continue(SCSIRequest *req)
{
trace_scsi_req_continue(req->dev->id, req->lun, req->tag);
if (req->cmd.mode == SCSI_XFER_TO_DEV) {
req->dev->info->write_data(req);
} else {
req->dev->info->read_data(req);
}
}
/* Called by the devices when data is ready for the HBA. The HBA should /* Called by the devices when data is ready for the HBA. The HBA should
start a DMA operation to read or fill the device's data buffer. start a DMA operation to read or fill the device's data buffer.
Once it completes, calling one of req->dev->info->read_data or Once it completes, calling scsi_req_continue will restart I/O. */
req->dev->info->write_data (depending on the direction of the
transfer) will restart I/O. */
void scsi_req_data(SCSIRequest *req, int len) void scsi_req_data(SCSIRequest *req, int len)
{ {
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len); trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);

View file

@ -151,6 +151,7 @@ void scsi_req_unref(SCSIRequest *req);
int scsi_req_parse(SCSIRequest *req, uint8_t *buf); int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
void scsi_req_print(SCSIRequest *req); void scsi_req_print(SCSIRequest *req);
void scsi_req_continue(SCSIRequest *req);
void scsi_req_data(SCSIRequest *req, int len); void scsi_req_data(SCSIRequest *req, int len);
void scsi_req_complete(SCSIRequest *req); void scsi_req_complete(SCSIRequest *req);
void scsi_req_abort(SCSIRequest *req, int status); void scsi_req_abort(SCSIRequest *req, int status);

View file

@ -448,7 +448,6 @@ static int vscsi_preprocess_desc(vscsi_req *req)
static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req) static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
{ {
SCSIDevice *sdev = req->sdev;
uint8_t *cdb = req->iu.srp.cmd.cdb; uint8_t *cdb = req->iu.srp.cmd.cdb;
int n; int n;
@ -469,7 +468,7 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
} else if (n == 0) { } else if (n == 0) {
return; return;
} }
sdev->info->read_data(req->sreq); scsi_req_continue(req->sreq);
} }
/* Callback to indicate that the SCSI layer has completed a transfer. */ /* Callback to indicate that the SCSI layer has completed a transfer. */
@ -508,7 +507,7 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
buf[12], buf[13], buf[14], buf[15]); buf[12], buf[13], buf[14], buf[15]);
memcpy(req->sense, buf, len); memcpy(req->sense, buf, len);
req->senselen = len; req->senselen = len;
sdev->info->read_data(sreq); scsi_req_continue(req->sreq);
} }
return; return;
} }
@ -552,11 +551,7 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
/* Start next chunk */ /* Start next chunk */
req->data_len -= rc; req->data_len -= rc;
if (req->writing) { scsi_req_continue(sreq);
sdev->info->write_data(sreq);
} else {
sdev->info->read_data(sreq);
}
} }
static void vscsi_request_cancelled(SCSIRequest *sreq) static void vscsi_request_cancelled(SCSIRequest *sreq)
@ -667,15 +662,14 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
/* Preprocess RDMA descriptors */ /* Preprocess RDMA descriptors */
vscsi_preprocess_desc(req); vscsi_preprocess_desc(req);
}
/* Get transfer direction and initiate transfer */ /* Get transfer direction and initiate transfer */
if (n > 0) { if (n > 0) {
req->data_len = n; req->data_len = n;
sdev->info->read_data(req->sreq);
} else if (n < 0) { } else if (n < 0) {
req->data_len = -n; req->data_len = -n;
sdev->info->write_data(req->sreq); }
scsi_req_continue(req->sreq);
} }
/* Don't touch req here, it may have been recycled already */ /* Don't touch req here, it may have been recycled already */

View file

@ -190,11 +190,7 @@ static void usb_msd_copy_data(MSDState *s)
s->scsi_buf += len; s->scsi_buf += len;
s->data_len -= len; s->data_len -= len;
if (s->scsi_len == 0 || s->data_len == 0) { if (s->scsi_len == 0 || s->data_len == 0) {
if (s->mode == USB_MSDM_DATAIN) { scsi_req_continue(s->req);
s->scsi_dev->info->read_data(s->req);
} else if (s->mode == USB_MSDM_DATAOUT) {
s->scsi_dev->info->write_data(s->req);
}
} }
} }
@ -249,6 +245,7 @@ static void usb_msd_command_complete(SCSIRequest *req, int reason, uint32_t arg)
s->req = NULL; s->req = NULL;
return; return;
} }
assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
s->scsi_len = arg; s->scsi_len = arg;
s->scsi_buf = s->scsi_dev->info->get_buf(req); s->scsi_buf = s->scsi_dev->info->get_buf(req);
if (p) { if (p) {
@ -381,12 +378,8 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
scsi_req_enqueue(s->req, cbw.cmd); scsi_req_enqueue(s->req, cbw.cmd);
/* ??? Should check that USB and SCSI data transfer /* ??? Should check that USB and SCSI data transfer
directions match. */ directions match. */
if (s->residue == 0) { if (s->mode != USB_MSDM_CSW && s->residue == 0) {
if (s->mode == USB_MSDM_DATAIN) { scsi_req_continue(s->req);
s->scsi_dev->info->read_data(s->req);
} else if (s->mode == USB_MSDM_DATAOUT) {
s->scsi_dev->info->write_data(s->req);
}
} }
ret = len; ret = len;
break; break;

View file

@ -209,6 +209,7 @@ disable usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature
disable scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d" disable scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d"
disable scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d" disable scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d"
disable scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d" disable scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d"
disable scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d"
disable scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer, uint64_t lba) "target %d lun %d tag %d command %d dir %d length %d lba %"PRIu64"" disable scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer, uint64_t lba) "target %d lun %d tag %d command %d dir %d length %d lba %"PRIu64""
disable scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d" disable scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d"