scsi: pass residual amount to command_complete

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>
This commit is contained in:
Paolo Bonzini 2011-07-06 11:55:37 +02:00
parent da22132752
commit 01e9545588
6 changed files with 15 additions and 9 deletions

View File

@ -390,7 +390,8 @@ static void esp_do_dma(ESPState *s)
esp_dma_done(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,
size_t resid)
{ {
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent); ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);

View File

@ -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. */ /* 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, size_t resid)
{ {
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent); LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
int out; int out;

View File

@ -533,6 +533,8 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
} }
req->cmd = cmd; req->cmd = cmd;
req->resid = req->cmd.xfer;
switch (buf[0]) { switch (buf[0]) {
case INQUIRY: case INQUIRY:
trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]); trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]);
@ -1275,10 +1277,12 @@ void scsi_req_data(SCSIRequest *req, int len)
{ {
if (req->io_canceled) { if (req->io_canceled) {
trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len); trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len);
} else { return;
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
req->bus->info->transfer_data(req, len);
} }
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) void scsi_req_print(SCSIRequest *req)
@ -1337,7 +1341,7 @@ void scsi_req_complete(SCSIRequest *req, int status)
scsi_req_ref(req); scsi_req_ref(req);
scsi_req_dequeue(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); scsi_req_unref(req);
} }

View File

@ -46,6 +46,7 @@ struct SCSIRequest {
uint32_t tag; uint32_t tag;
uint32_t lun; uint32_t lun;
uint32_t status; uint32_t status;
size_t resid;
SCSICommand cmd; SCSICommand cmd;
BlockDriverAIOCB *aiocb; BlockDriverAIOCB *aiocb;
uint8_t sense[SCSI_SENSE_BUF_SIZE]; uint8_t sense[SCSI_SENSE_BUF_SIZE];
@ -112,7 +113,7 @@ struct SCSIBusInfo {
int tcq; int tcq;
int max_channel, max_target, max_lun; int max_channel, max_target, max_lun;
void (*transfer_data)(SCSIRequest *req, uint32_t arg); void (*transfer_data)(SCSIRequest *req, uint32_t arg);
void (*complete)(SCSIRequest *req, uint32_t arg); void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
void (*cancel)(SCSIRequest *req); void (*cancel)(SCSIRequest *req);
}; };

View File

@ -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. */ /* 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, size_t resid)
{ {
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent); VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
vscsi_req *req = sreq->hba_private; vscsi_req *req = sreq->hba_private;

View File

@ -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, size_t resid)
{ {
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
USBPacket *p = s->packet; USBPacket *p = s->packet;