mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 11:53:39 +08:00
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);
|
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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user