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);
}
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);

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. */
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);
int out;

View File

@ -533,6 +533,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]);
@ -1275,10 +1277,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)
@ -1337,7 +1341,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);
}

View File

@ -46,6 +46,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];
@ -112,7 +113,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, size_t resid);
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. */
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);
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);
USBPacket *p = s->packet;