diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2011-04-18 15:28:11 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2011-05-26 12:14:16 +0200 |
commit | ad3376cc558f69606ac25ab6d597db71c969d8b6 (patch) | |
tree | 38da81601cf2cd632179134480d4c5d3aeaad09b /hw | |
parent | 43a2b33957697347e4e6d00557221538231bfe4d (diff) |
scsi: introduce scsi_req_continue
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/esp.c | 26 | ||||
-rw-r--r-- | hw/lsi53c895a.c | 22 | ||||
-rw-r--r-- | hw/scsi-bus.c | 16 | ||||
-rw-r--r-- | hw/scsi.h | 1 | ||||
-rw-r--r-- | hw/spapr_vscsi.c | 26 | ||||
-rw-r--r-- | hw/usb-msd.c | 15 |
6 files changed, 46 insertions, 60 deletions
@@ -253,11 +253,10 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid) s->dma_counter = 0; if (datalen > 0) { s->rregs[ESP_RSTAT] |= STAT_DI; - s->current_dev->info->read_data(s->current_req); } else { 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_RSEQ] = SEQ_CD; @@ -383,22 +382,17 @@ static void esp_do_dma(ESPState *s) else s->ti_size -= len; if (s->async_len == 0) { - if (to_device) { - // 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 - complete the DMA operation immediately. Otherwise defer - until the scsi layer has completed. */ - if (s->dma_left == 0 && s->ti_size > 0) { - esp_dma_done(s); - } + scsi_req_continue(s->current_req); + /* If there is still data to be read from the device then + complete the DMA operation immediately. Otherwise defer + until the scsi layer has completed. */ + if (to_device || s->dma_left != 0 || s->ti_size == 0) { + return; } - } else { - /* Partially filled a scsi buffer. Complete immediately. */ - esp_dma_done(s); } + + /* Partially filled a scsi buffer. Complete immediately. */ + esp_dma_done(s); } static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg) diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 6b78f2aaf..e8409b720 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -580,13 +580,7 @@ static void lsi_do_dma(LSIState *s, int out) s->current->dma_len -= count; if (s->current->dma_len == 0) { s->current->dma_buf = NULL; - if (out) { - /* Write the data. */ - dev->info->write_data(s->current->req); - } else { - /* Request any remaining data. */ - dev->info->read_data(s->current->req); - } + scsi_req_continue(s->current->req); } else { s->current->dma_buf += count; 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); n = scsi_req_enqueue(s->current->req, buf); - if (n > 0) { - lsi_set_phase(s, PHASE_DI); - dev->info->read_data(s->current->req); - } else if (n < 0) { - lsi_set_phase(s, PHASE_DO); - dev->info->write_data(s->current->req); + if (n) { + if (n > 0) { + lsi_set_phase(s, PHASE_DI); + } else if (n < 0) { + lsi_set_phase(s, PHASE_DO); + } + scsi_req_continue(s->current->req); } - if (!s->command_complete) { if (n) { /* Command did not complete immediately so disconnect. */ diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 6ac265022..fb96bdee5 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -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 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 - req->dev->info->write_data (depending on the direction of the - transfer) will restart I/O. */ + Once it completes, calling scsi_req_continue will restart I/O. */ void scsi_req_data(SCSIRequest *req, int len) { trace_scsi_req_data(req->dev->id, req->lun, req->tag, len); @@ -151,6 +151,7 @@ void scsi_req_unref(SCSIRequest *req); int scsi_req_parse(SCSIRequest *req, uint8_t *buf); void scsi_req_print(SCSIRequest *req); +void scsi_req_continue(SCSIRequest *req); void scsi_req_data(SCSIRequest *req, int len); void scsi_req_complete(SCSIRequest *req); void scsi_req_abort(SCSIRequest *req, int status); diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c index fcdfad405..1e47fb912 100644 --- a/hw/spapr_vscsi.c +++ b/hw/spapr_vscsi.c @@ -448,7 +448,6 @@ static int vscsi_preprocess_desc(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; int n; @@ -469,7 +468,7 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req) } else if (n == 0) { return; } - sdev->info->read_data(req->sreq); + scsi_req_continue(req->sreq); } /* 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]); memcpy(req->sense, buf, len); req->senselen = len; - sdev->info->read_data(sreq); + scsi_req_continue(req->sreq); } return; } @@ -552,11 +551,7 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg) /* Start next chunk */ req->data_len -= rc; - if (req->writing) { - sdev->info->write_data(sreq); - } else { - sdev->info->read_data(sreq); - } + scsi_req_continue(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 */ vscsi_preprocess_desc(req); - } - /* Get transfer direction and initiate transfer */ - if (n > 0) { - req->data_len = n; - sdev->info->read_data(req->sreq); - } else if (n < 0) { - req->data_len = -n; - sdev->info->write_data(req->sreq); + /* Get transfer direction and initiate transfer */ + if (n > 0) { + req->data_len = n; + } else if (n < 0) { + req->data_len = -n; + } + scsi_req_continue(req->sreq); } /* Don't touch req here, it may have been recycled already */ diff --git a/hw/usb-msd.c b/hw/usb-msd.c index efb15b00a..d4c2234e8 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -190,11 +190,7 @@ static void usb_msd_copy_data(MSDState *s) s->scsi_buf += len; s->data_len -= len; if (s->scsi_len == 0 || s->data_len == 0) { - if (s->mode == USB_MSDM_DATAIN) { - s->scsi_dev->info->read_data(s->req); - } else if (s->mode == USB_MSDM_DATAOUT) { - s->scsi_dev->info->write_data(s->req); - } + scsi_req_continue(s->req); } } @@ -249,6 +245,7 @@ static void usb_msd_command_complete(SCSIRequest *req, int reason, uint32_t arg) s->req = NULL; return; } + assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV)); s->scsi_len = arg; s->scsi_buf = s->scsi_dev->info->get_buf(req); if (p) { @@ -381,12 +378,8 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) scsi_req_enqueue(s->req, cbw.cmd); /* ??? Should check that USB and SCSI data transfer directions match. */ - if (s->residue == 0) { - if (s->mode == USB_MSDM_DATAIN) { - s->scsi_dev->info->read_data(s->req); - } else if (s->mode == USB_MSDM_DATAOUT) { - s->scsi_dev->info->write_data(s->req); - } + if (s->mode != USB_MSDM_CSW && s->residue == 0) { + scsi_req_continue(s->req); } ret = len; break; |