Patchwork [05/11] scsi: pass residual amount to command_complete

login
register
mail settings
Submitter Paolo Bonzini
Date Dec. 6, 2011, 11:01 a.m.
Message ID <1323169292-21661-6-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/129653/
State New
Headers show

Comments

Paolo Bonzini - Dec. 6, 2011, 11:01 a.m.
With the upcoming sglist support, HBAs will not see any transfer_data
call and will not have a way to detect short transfers.  So pass the
residual amount of data upon command completion.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/esp.c         |    3 ++-
 hw/lsi53c895a.c  |    2 +-
 hw/scsi-bus.c    |   12 ++++++++----
 hw/scsi.h        |    3 ++-
 hw/spapr_vscsi.c |    2 +-
 hw/usb-msd.c     |    2 +-
 6 files changed, 15 insertions(+), 9 deletions(-)

Patch

diff --git a/hw/esp.c b/hw/esp.c
index b698a43..8516db5 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -389,7 +389,8 @@  static void esp_do_dma(ESPState *s)
     esp_dma_done(s);
 }
 
-static void esp_command_complete(SCSIRequest *req, uint32_t status)
+static void esp_command_complete(SCSIRequest *req, uint32_t status,
+                                 int32_t resid)
 {
     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index fcc27d7..c53760b 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -699,7 +699,7 @@  static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
 }
 
  /* Callback to indicate that the SCSI layer has completed a command.  */
-static void lsi_command_complete(SCSIRequest *req, uint32_t status)
+static void lsi_command_complete(SCSIRequest *req, uint32_t status, int32_t resid)
 {
     LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
     int out;
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 64e709e..aa811f4 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -512,6 +512,8 @@  SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
     }
 
     req->cmd = cmd;
+    req->resid = req->cmd.xfer;
+
     switch (buf[0]) {
     case INQUIRY:
         trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]);
@@ -1256,10 +1258,12 @@  void scsi_req_data(SCSIRequest *req, int len)
 {
     if (req->io_canceled) {
         trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len);
-    } else {
-        trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
-        req->bus->info->transfer_data(req, len);
+        return;
     }
+    trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
+    assert(req->cmd.mode != SCSI_XFER_NONE);
+    req->resid -= len;
+    req->bus->info->transfer_data(req, len);
 }
 
 void scsi_req_print(SCSIRequest *req)
@@ -1318,7 +1322,7 @@  void scsi_req_complete(SCSIRequest *req, int status)
 
     scsi_req_ref(req);
     scsi_req_dequeue(req);
-    req->bus->info->complete(req, req->status);
+    req->bus->info->complete(req, req->status, req->resid);
     scsi_req_unref(req);
 }
 
diff --git a/hw/scsi.h b/hw/scsi.h
index ab6e952..27ca087 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -47,6 +47,7 @@  struct SCSIRequest {
     uint32_t          tag;
     uint32_t          lun;
     uint32_t          status;
+    size_t            resid;
     SCSICommand       cmd;
     BlockDriverAIOCB  *aiocb;
     uint8_t sense[SCSI_SENSE_BUF_SIZE];
@@ -107,7 +108,7 @@  struct SCSIBusInfo {
     int tcq;
     int max_channel, max_target, max_lun;
     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
-    void (*complete)(SCSIRequest *req, uint32_t arg);
+    void (*complete)(SCSIRequest *req, uint32_t arg, int32_t len);
     void (*cancel)(SCSIRequest *req);
 };
 
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 00e2d2d..c28bba9 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -494,7 +494,7 @@  static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
 }
 
 /* Callback to indicate that the SCSI layer has completed a transfer.  */
-static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
+static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, int32_t resid)
 {
     VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
     vscsi_req *req = sreq->hba_private;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 4c06950..1c7bc82 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -223,7 +223,7 @@  static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
     }
 }
 
-static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
+static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, int32_t resid)
 {
     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
     USBPacket *p = s->packet;