mirror of https://gitee.com/openkylin/qemu.git
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:
parent
da22132752
commit
01e9545588
3
hw/esp.c
3
hw/esp.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue