From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53308) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XBmXs-0000YK-65 for qemu-devel@nongnu.org; Mon, 28 Jul 2014 11:09:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XBmXh-0008WI-NC for qemu-devel@nongnu.org; Mon, 28 Jul 2014 11:09:00 -0400 Received: from mail-qa0-x22f.google.com ([2607:f8b0:400d:c00::22f]:36671) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XBmXh-0008WE-Hd for qemu-devel@nongnu.org; Mon, 28 Jul 2014 11:08:49 -0400 Received: by mail-qa0-f47.google.com with SMTP id i13so7910824qae.6 for ; Mon, 28 Jul 2014 08:08:49 -0700 (PDT) Received: from yakj.usersys.redhat.com (net-37-117-143-217.cust.vodafonedsl.it. [37.117.143.217]) by mx.google.com with ESMTPSA id i2sm22891723qge.27.2014.07.28.08.08.47 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Jul 2014 08:08:48 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Mon, 28 Jul 2014 17:08:34 +0200 Message-Id: <1406560119-22362-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH for-2.2 v2 0/5] scsi: enable passthrough of vendor-specific commands List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Right now scsi-generic is parsing the CDB, in order to compute the expected number of bytes to be transferred. This is necessary if DMA is done by the HBA via scsi_req_data, but it prevents executing vendor-specific commands via scsi-generic because we don't know how to parse them. If DMA is delegated to the SCSI layer via get_sg_list, we know in advance how many bytes the guest will want to receive and we can pass the information straight from the guest to SG_IO. In this case, it is unnecessary to parse the CDB to get the same information. scsi-disk needs it to detect underruns and overruns, but scsi-generic and scsi-block can just ask the HBA about the transfer direction and size. This series introduces a new parse_cdb callback in both the device and the HBA. The latter is called by scsi_bus_parse_cdb, which devices can call for passthrough requests in their implementation of parse_cdb. Paolo v1->v2: use the "right" CDB size for non-vendor-specific commands, as some drivers and/or firmware expect that and complain if you pass a READ(10) command in a 16-byte CDB. Interdiff here. diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index f999bfa..6f4462b 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -57,12 +57,14 @@ int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, void *hba_private) { SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); + int rc; + assert(cmd->len == 0); + rc = scsi_req_parse_cdb(dev, cmd, buf); if (bus->info->parse_cdb) { - return bus->info->parse_cdb(dev, cmd, buf, hba_private); - } else { - return scsi_req_parse_cdb(dev, cmd, buf); + rc = bus->info->parse_cdb(dev, cmd, buf, hba_private); } + return rc; } static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t lun, @@ -575,7 +577,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, const SCSIReqOps *ops; SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(d); SCSIRequest *req; - SCSICommand cmd; + SCSICommand cmd = { .len = 0 }; int ret; if ((d->unit_attention.key == UNIT_ATTENTION || @@ -609,6 +611,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]); req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private); } else { + assert(cmd.len != 0); trace_scsi_req_parsed(d->id, lun, tag, buf[0], cmd.mode, cmd.xfer); if (cmd.lba != -1) { @@ -1210,6 +1213,7 @@ int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf) { int rc; + cmd->lba = -1; switch (buf[0] >> 5) { case 0: cmd->len = 6; diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index e8f4c0c..2dd9255 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -411,9 +411,10 @@ static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, { VirtIOSCSIReq *req = hba_private; - cmd->lba = -1; - cmd->len = MIN(VIRTIO_SCSI_CDB_SIZE, SCSI_CMD_BUF_SIZE); - memcpy(cmd->buf, buf, cmd->len); + if (cmd->len == 0) { + cmd->len = MIN(VIRTIO_SCSI_CDB_SIZE, SCSI_CMD_BUF_SIZE); + memcpy(cmd->buf, buf, cmd->len); + } /* Extract the direction and mode directly from the request, for * host device passthrough. Paolo Bonzini (5): scsi-bus: prepare scsi_req_new for introduction of parse_cdb scsi-bus: introduce parse_cdb in SCSIDeviceClass and SCSIBusInfo scsi-block: extract scsi_block_is_passthrough scsi-block, scsi-generic: implement parse_cdb virtio-scsi: implement parse_cdb hw/scsi/scsi-bus.c | 74 ++++++++++++++++++++++++++++++++++---------------- hw/scsi/scsi-disk.c | 52 +++++++++++++++++++++++++++-------- hw/scsi/scsi-generic.c | 7 +++++ hw/scsi/virtio-scsi.c | 25 +++++++++++++++++ include/hw/scsi/scsi.h | 7 +++++ 5 files changed, 130 insertions(+), 35 deletions(-) -- 1.9.3