mirror of https://github.com/xqemu/xqemu.git
scsi: add scatter/gather functionality
Scatter/gather functionality uses the newly added DMA helpers. The device can choose between doing DMA itself, or calling scsi_req_data as usual, which will use the newly added DMA helpers to copy piecewise to/from the destination area(s). Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
01e9545588
commit
3d5aba97e9
|
@ -5,6 +5,7 @@
|
||||||
#include "qdev.h"
|
#include "qdev.h"
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
#include "dma.h"
|
||||||
|
|
||||||
static char *scsibus_get_fw_dev_path(DeviceState *dev);
|
static char *scsibus_get_fw_dev_path(DeviceState *dev);
|
||||||
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
|
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
|
||||||
|
@ -651,6 +652,11 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
|
||||||
|
|
||||||
assert(!req->enqueued);
|
assert(!req->enqueued);
|
||||||
scsi_req_ref(req);
|
scsi_req_ref(req);
|
||||||
|
if (req->bus->info->get_sg_list) {
|
||||||
|
req->sg = req->bus->info->get_sg_list(req);
|
||||||
|
} else {
|
||||||
|
req->sg = NULL;
|
||||||
|
}
|
||||||
req->enqueued = true;
|
req->enqueued = true;
|
||||||
QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
|
QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
|
||||||
|
|
||||||
|
@ -1275,14 +1281,32 @@ void scsi_req_continue(SCSIRequest *req)
|
||||||
Once it completes, calling scsi_req_continue will restart I/O. */
|
Once it completes, calling scsi_req_continue will restart I/O. */
|
||||||
void scsi_req_data(SCSIRequest *req, int len)
|
void scsi_req_data(SCSIRequest *req, int len)
|
||||||
{
|
{
|
||||||
|
uint8_t *buf;
|
||||||
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);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
|
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
|
||||||
assert(req->cmd.mode != SCSI_XFER_NONE);
|
assert(req->cmd.mode != SCSI_XFER_NONE);
|
||||||
req->resid -= len;
|
if (!req->sg) {
|
||||||
req->bus->info->transfer_data(req, len);
|
req->resid -= len;
|
||||||
|
req->bus->info->transfer_data(req, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the device calls scsi_req_data and the HBA specified a
|
||||||
|
* scatter/gather list, the transfer has to happen in a single
|
||||||
|
* step. */
|
||||||
|
assert(!req->dma_started);
|
||||||
|
req->dma_started = true;
|
||||||
|
|
||||||
|
buf = scsi_req_get_buf(req);
|
||||||
|
if (req->cmd.mode == SCSI_XFER_FROM_DEV) {
|
||||||
|
req->resid = dma_buf_read(buf, len, req->sg);
|
||||||
|
} else {
|
||||||
|
req->resid = dma_buf_write(buf, len, req->sg);
|
||||||
|
}
|
||||||
|
scsi_req_continue(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scsi_req_print(SCSIRequest *req)
|
void scsi_req_print(SCSIRequest *req)
|
||||||
|
|
|
@ -49,6 +49,8 @@ struct SCSIRequest {
|
||||||
size_t resid;
|
size_t resid;
|
||||||
SCSICommand cmd;
|
SCSICommand cmd;
|
||||||
BlockDriverAIOCB *aiocb;
|
BlockDriverAIOCB *aiocb;
|
||||||
|
QEMUSGList *sg;
|
||||||
|
bool dma_started;
|
||||||
uint8_t sense[SCSI_SENSE_BUF_SIZE];
|
uint8_t sense[SCSI_SENSE_BUF_SIZE];
|
||||||
uint32_t sense_len;
|
uint32_t sense_len;
|
||||||
bool enqueued;
|
bool enqueued;
|
||||||
|
@ -115,6 +117,7 @@ struct SCSIBusInfo {
|
||||||
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
||||||
void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
|
void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
|
||||||
void (*cancel)(SCSIRequest *req);
|
void (*cancel)(SCSIRequest *req);
|
||||||
|
QEMUSGList *(*get_sg_list)(SCSIRequest *req);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SCSIBus {
|
struct SCSIBus {
|
||||||
|
|
Loading…
Reference in New Issue