* [Qemu-devel] [PATCH 1/6] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo)
2011-09-30 16:36 [Qemu-devel] [PATCH 0/6] introduce SCSI channel/target/LUN addressing Paolo Bonzini
@ 2011-09-30 16:36 ` Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 2/6] qdev: switch children device list to QTAILQ Paolo Bonzini
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2011-09-30 16:36 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/esp.c | 7 +++++--
hw/lsi53c895a.c | 9 ++++++---
hw/scsi-bus.c | 27 ++++++++++++---------------
hw/scsi-disk.c | 2 +-
hw/scsi.h | 11 +++++------
hw/spapr_vscsi.c | 8 +++++---
hw/usb-msd.c | 7 +++++--
7 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/hw/esp.c b/hw/esp.c
index ca41f80..9e1c230 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -730,7 +730,10 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
*dma_enable = qdev_get_gpio_in(dev, 1);
}
-static const struct SCSIBusOps esp_scsi_ops = {
+static const struct SCSIBusInfo esp_scsi_info = {
+ .tcq = false,
+ .ndev = ESP_MAX_DEVS,
+
.transfer_data = esp_transfer_data,
.complete = esp_command_complete,
.cancel = esp_request_cancelled
@@ -750,7 +753,7 @@ static int esp_init1(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
- scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
+ scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
return scsi_bus_legacy_handle_cmdline(&s->bus);
}
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 75a03a7..e3f92c2 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1686,7 +1686,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
DeviceState *dev;
int id;
- for (id = 0; id < s->bus.ndev; id++) {
+ for (id = 0; id < LSI_MAX_DEVS; id++) {
if (s->bus.devs[id]) {
dev = &s->bus.devs[id]->qdev;
dev->info->reset(dev);
@@ -2091,7 +2091,10 @@ static int lsi_scsi_uninit(PCIDevice *d)
return 0;
}
-static const struct SCSIBusOps lsi_scsi_ops = {
+static const struct SCSIBusInfo lsi_scsi_info = {
+ .tcq = true,
+ .ndev = LSI_MAX_DEVS,
+
.transfer_data = lsi_transfer_data,
.complete = lsi_command_complete,
.cancel = lsi_request_cancelled
@@ -2118,7 +2121,7 @@ static int lsi_scsi_init(PCIDevice *dev)
pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
QTAILQ_INIT(&s->queue);
- scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, &lsi_scsi_ops);
+ scsi_bus_new(&s->bus, &dev->qdev, &lsi_scsi_info);
if (!dev->qdev.hotplugged) {
return scsi_bus_legacy_handle_cmdline(&s->bus);
}
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 867b1a8..d9d4e18 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -24,14 +24,11 @@ static struct BusInfo scsi_bus_info = {
static int next_scsi_bus;
/* Create a scsi bus, and attach devices to it. */
-void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
- const SCSIBusOps *ops)
+void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
{
qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
bus->busnr = next_scsi_bus++;
- bus->tcq = tcq;
- bus->ndev = ndev;
- bus->ops = ops;
+ bus->info = info;
bus->qbus.allow_hotplug = 1;
}
@@ -43,12 +40,12 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
int rc = -1;
if (dev->id == -1) {
- for (dev->id = 0; dev->id < bus->ndev; dev->id++) {
+ for (dev->id = 0; dev->id < bus->info->ndev; dev->id++) {
if (bus->devs[dev->id] == NULL)
break;
}
}
- if (dev->id >= bus->ndev) {
+ if (dev->id >= bus->info->ndev) {
error_report("bad scsi device id: %d", dev->id);
goto err;
}
@@ -120,7 +117,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
int res = 0, unit;
loc_push_none(&loc);
- for (unit = 0; unit < bus->ndev; unit++) {
+ for (unit = 0; unit < bus->info->ndev; unit++) {
dinfo = drive_get(IF_SCSI, bus->busnr, unit);
if (dinfo == NULL) {
continue;
@@ -265,7 +262,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
r->buf[2] = 5; /* Version */
r->buf[3] = 2 | 0x10; /* HiSup, response data format */
r->buf[4] = r->len - 5; /* Additional Length = (Len - 1) - 4 */
- r->buf[7] = 0x10 | (r->req.bus->tcq ? 0x02 : 0); /* Sync, TCQ. */
+ r->buf[7] = 0x10 | (r->req.bus->info->tcq ? 0x02 : 0); /* Sync, TCQ. */
memcpy(&r->buf[8], "QEMU ", 8);
memcpy(&r->buf[16], "QEMU TARGET ", 16);
strncpy((char *) &r->buf[32], QEMU_VERSION, 4);
@@ -1062,7 +1059,7 @@ void scsi_req_continue(SCSIRequest *req)
void scsi_req_data(SCSIRequest *req, int len)
{
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
- req->bus->ops->transfer_data(req, len);
+ req->bus->info->transfer_data(req, len);
}
void scsi_req_print(SCSIRequest *req)
@@ -1121,7 +1118,7 @@ void scsi_req_complete(SCSIRequest *req, int status)
scsi_req_ref(req);
scsi_req_dequeue(req);
- req->bus->ops->complete(req, req->status);
+ req->bus->info->complete(req, req->status);
scsi_req_unref(req);
}
@@ -1132,8 +1129,8 @@ void scsi_req_cancel(SCSIRequest *req)
}
scsi_req_ref(req);
scsi_req_dequeue(req);
- if (req->bus->ops->cancel) {
- req->bus->ops->cancel(req);
+ if (req->bus->info->cancel) {
+ req->bus->info->cancel(req);
}
scsi_req_unref(req);
}
@@ -1164,13 +1161,13 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
char path[100];
int i;
- for (i = 0; i < bus->ndev; i++) {
+ for (i = 0; i < bus->info->ndev; i++) {
if (bus->devs[i] == d) {
break;
}
}
- assert(i != bus->ndev);
+ assert(i != bus->info->ndev);
snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 8ca75e0..d9fa8f7 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -559,7 +559,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
}
/* Sync data transfer and TCQ. */
- outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
+ outbuf[7] = 0x10 | (req->bus->info->tcq ? 0x02 : 0);
return buflen;
}
diff --git a/hw/scsi.h b/hw/scsi.h
index 7004aaa..b76c4ee 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -9,7 +9,7 @@
#define SCSI_CMD_BUF_SIZE 16
typedef struct SCSIBus SCSIBus;
-typedef struct SCSIBusOps SCSIBusOps;
+typedef struct SCSIBusInfo SCSIBusInfo;
typedef struct SCSICommand SCSICommand;
typedef struct SCSIDevice SCSIDevice;
typedef struct SCSIDeviceInfo SCSIDeviceInfo;
@@ -97,7 +97,8 @@ struct SCSIDeviceInfo {
SCSIReqOps reqops;
};
-struct SCSIBusOps {
+struct SCSIBusInfo {
+ int tcq, ndev;
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
void (*complete)(SCSIRequest *req, uint32_t arg);
void (*cancel)(SCSIRequest *req);
@@ -108,14 +109,12 @@ struct SCSIBus {
int busnr;
SCSISense unit_attention;
- int tcq, ndev;
- const SCSIBusOps *ops;
+ const SCSIBusInfo *info;
SCSIDevice *devs[MAX_SCSI_DEVS];
};
-void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
- const SCSIBusOps *ops);
+void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
void scsi_qdev_register(SCSIDeviceInfo *info);
static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index e8426d7..6c5faf2 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -862,7 +862,10 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
return 0;
}
-static const struct SCSIBusOps vscsi_scsi_ops = {
+static const struct SCSIBusInfo vscsi_scsi_info = {
+ .tcq = true,
+ .ndev = 63, /* logical unit addressing format */
+
.transfer_data = vscsi_transfer_data,
.complete = vscsi_command_complete,
.cancel = vscsi_request_cancelled
@@ -883,8 +886,7 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev)
dev->crq.SendFunc = vscsi_do_crq;
- scsi_bus_new(&s->bus, &dev->qdev, 1, VSCSI_REQ_LIMIT,
- &vscsi_scsi_ops);
+ scsi_bus_new(&s->bus, &dev->qdev, &vscsi_scsi_info);
if (!dev->qdev.hotplugged) {
scsi_bus_legacy_handle_cmdline(&s->bus);
}
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index e92434c..d0e0cd3 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -492,7 +492,10 @@ static void usb_msd_password_cb(void *opaque, int err)
qdev_unplug(&s->dev.qdev);
}
-static const struct SCSIBusOps usb_msd_scsi_ops = {
+static const struct SCSIBusInfo usb_msd_scsi_info = {
+ .tcq = false,
+ .ndev = 1,
+
.transfer_data = usb_msd_transfer_data,
.complete = usb_msd_command_complete,
.cancel = usb_msd_request_cancelled
@@ -533,7 +536,7 @@ static int usb_msd_initfn(USBDevice *dev)
}
usb_desc_init(dev);
- scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, &usb_msd_scsi_ops);
+ scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
if (!s->scsi_dev) {
return -1;
--
1.7.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 2/6] qdev: switch children device list to QTAILQ
2011-09-30 16:36 [Qemu-devel] [PATCH 0/6] introduce SCSI channel/target/LUN addressing Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 1/6] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo) Paolo Bonzini
@ 2011-09-30 16:36 ` Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 3/6] scsi: remove devs array from SCSIBus Paolo Bonzini
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2011-09-30 16:36 UTC (permalink / raw)
To: qemu-devel
SCSI buses will need to read the children list first-to-last. This
requires using a QTAILQ, because hell breaks loose if you just try
inserting at the tail (thus reversing the order of all existing
visits from last-to-first to first-to-tail).
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/acpi_piix4.c | 4 ++--
hw/i2c.c | 2 +-
hw/intel-hda.c | 6 +++---
hw/qdev.c | 24 ++++++++++++------------
hw/qdev.h | 4 ++--
hw/s390-virtio-bus.c | 4 ++--
hw/spapr_vio.c | 6 +++---
hw/ssi.c | 6 +++---
8 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 29f0f76..d9075e6 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -276,7 +276,7 @@ static void piix4_update_hotplug(PIIX4PMState *s)
s->pci0_hotplug_enable = ~0;
- QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+ QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev);
PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
int slot = PCI_SLOT(pdev->devfn);
@@ -486,7 +486,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
PCIDeviceInfo *info;
int slot = ffs(val) - 1;
- QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+ QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
dev = DO_UPCAST(PCIDevice, qdev, qdev);
info = container_of(qdev->info, PCIDeviceInfo, qdev);
if (PCI_SLOT(dev->devfn) == slot && !info->no_hotplug) {
diff --git a/hw/i2c.c b/hw/i2c.c
index 49b9ecb..9bcf3e1 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -84,7 +84,7 @@ int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
DeviceState *qdev;
i2c_slave *slave = NULL;
- QLIST_FOREACH(qdev, &bus->qbus.children, sibling) {
+ QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
i2c_slave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
if (candidate->address == address) {
slave = candidate;
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 4272204..c4e8c51 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -86,7 +86,7 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
DeviceState *qdev;
HDACodecDevice *cdev;
- QLIST_FOREACH(qdev, &bus->qbus.children, sibling) {
+ QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
if (cdev->cad == cad) {
return cdev;
@@ -489,7 +489,7 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
DeviceState *qdev;
HDACodecDevice *cdev;
- QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+ QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
if (cdev->info->stream) {
cdev->info->stream(cdev, stream, running);
@@ -1112,7 +1112,7 @@ static void intel_hda_reset(DeviceState *dev)
d->wall_base_ns = qemu_get_clock_ns(vm_clock);
/* reset codecs */
- QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+ QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
if (qdev->info->reset) {
qdev->info->reset(qdev);
diff --git a/hw/qdev.c b/hw/qdev.c
index a223d41..50976dd 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -91,7 +91,7 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
qdev_prop_set_defaults(dev, dev->info->props);
qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
qdev_prop_set_globals(dev);
- QLIST_INSERT_HEAD(&bus->children, dev, sibling);
+ QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
if (qdev_hotplug) {
assert(bus->allow_hotplug);
dev->hotplugged = 1;
@@ -408,7 +408,7 @@ void qdev_free(DeviceState *dev)
if (dev->opts)
qemu_opts_del(dev->opts);
}
- QLIST_REMOVE(dev, sibling);
+ QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
for (prop = dev->info->props; prop && prop->name; prop++) {
if (prop->info->free) {
prop->info->free(dev, prop);
@@ -510,7 +510,7 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
}
}
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
err = qdev_walk_children(dev, devfn, busfn, opaque);
if (err < 0) {
return err;
@@ -560,7 +560,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
return bus;
}
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
QLIST_FOREACH(child, &dev->child_bus, sibling) {
ret = qbus_find_recursive(child, name, info);
if (ret) {
@@ -576,7 +576,7 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
DeviceState *dev, *ret;
BusState *child;
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
if (dev->id && strcmp(dev->id, id) == 0)
return dev;
QLIST_FOREACH(child, &dev->child_bus, sibling) {
@@ -609,7 +609,7 @@ static void qbus_list_dev(BusState *bus)
const char *sep = " ";
error_printf("devices at \"%s\":", bus->name);
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
error_printf("%s\"%s\"", sep, dev->info->name);
if (dev->id)
error_printf("/\"%s\"", dev->id);
@@ -640,17 +640,17 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
* (2) driver name
* (3) driver alias, if present
*/
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
if (dev->id && strcmp(dev->id, elem) == 0) {
return dev;
}
}
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
if (strcmp(dev->info->name, elem) == 0) {
return dev;
}
}
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
return dev;
}
@@ -774,7 +774,7 @@ void qbus_create_inplace(BusState *bus, BusInfo *info,
bus->name = buf;
}
- QLIST_INIT(&bus->children);
+ QTAILQ_INIT(&bus->children);
if (parent) {
QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
parent->num_child_bus++;
@@ -809,7 +809,7 @@ void qbus_free(BusState *bus)
{
DeviceState *dev;
- while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
+ while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
qdev_free(dev);
}
if (bus->parent) {
@@ -878,7 +878,7 @@ static void qbus_print(Monitor *mon, BusState *bus, int indent)
qdev_printf("bus: %s\n", bus->name);
indent += 2;
qdev_printf("type %s\n", bus->info->name);
- QLIST_FOREACH(dev, &bus->children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
qdev_print(mon, dev, indent);
}
}
diff --git a/hw/qdev.h b/hw/qdev.h
index 8a13ec9..ff524cb 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -42,7 +42,7 @@ struct DeviceState {
qemu_irq *gpio_in;
QLIST_HEAD(, BusState) child_bus;
int num_child_bus;
- QLIST_ENTRY(DeviceState) sibling;
+ QTAILQ_ENTRY(DeviceState) sibling;
int instance_id_alias;
int alias_required_for_version;
};
@@ -73,7 +73,7 @@ struct BusState {
const char *name;
int allow_hotplug;
int qdev_allocated;
- QLIST_HEAD(, DeviceState) children;
+ QTAILQ_HEAD(, DeviceState) children;
QLIST_ENTRY(BusState) sibling;
};
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index e2f3e32..0ce6406 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -274,7 +274,7 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
DeviceState *dev;
int i;
- QLIST_FOREACH(dev, &bus->bus.children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
_dev = (VirtIOS390Device *)dev;
for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
if (!virtio_queue_get_addr(_dev->vdev, i))
@@ -297,7 +297,7 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
VirtIOS390Device *_dev;
DeviceState *dev;
- QLIST_FOREACH(dev, &bus->bus.children, sibling) {
+ QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
_dev = (VirtIOS390Device *)dev;
if (_dev->dev_offs == mem) {
return _dev;
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index ad5b30d..4cb645f 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -63,7 +63,7 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
DeviceState *qdev;
VIOsPAPRDevice *dev = NULL;
- QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+ QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)qdev;
if (dev->reg == reg) {
break;
@@ -588,7 +588,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
return;
}
- QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+ QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)qdev;
spapr_vio_quiesce_one(dev);
}
@@ -725,7 +725,7 @@ int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
DeviceState *qdev;
int ret = 0;
- QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+ QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
ret = vio_make_devnode(dev, fdt);
diff --git a/hw/ssi.c b/hw/ssi.c
index 3f4c5f9..9842fe7 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -25,8 +25,8 @@ static int ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
SSIBus *bus;
bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
- if (QLIST_FIRST(&bus->qbus.children) != dev
- || QLIST_NEXT(dev, sibling) != NULL) {
+ if (QTAILQ_FIRST(&bus->qbus.children) != dev
+ || QTAILQ_NEXT(dev, sibling) != NULL) {
hw_error("Too many devices on SSI bus");
}
@@ -61,7 +61,7 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
{
DeviceState *dev;
SSISlave *slave;
- dev = QLIST_FIRST(&bus->qbus.children);
+ dev = QTAILQ_FIRST(&bus->qbus.children);
if (!dev) {
return 0;
}
--
1.7.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 3/6] scsi: remove devs array from SCSIBus
2011-09-30 16:36 [Qemu-devel] [PATCH 0/6] introduce SCSI channel/target/LUN addressing Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 1/6] scsi: move tcq/ndev to SCSIBusOps (now SCSIBusInfo) Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 2/6] qdev: switch children device list to QTAILQ Paolo Bonzini
@ 2011-09-30 16:36 ` Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 4/6] scsi: implement REPORT LUNS for arbitrary LUNs Paolo Bonzini
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2011-09-30 16:36 UTC (permalink / raw)
To: qemu-devel
Change the devs array into a linked list, and add a scsi_device_find
function to navigate the children list instead. This lets the SCSI
bus use more complex addressing.
scsi_device_find may return another LUN on the same target if none is
found that matches exactly.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/esp.c | 5 +++--
hw/lsi53c895a.c | 22 +++++++---------------
hw/qdev.h | 2 +-
hw/scsi-bus.c | 53 ++++++++++++++++++++++++++++++-----------------------
hw/scsi.h | 3 +--
hw/spapr_vscsi.c | 14 ++++++--------
6 files changed, 48 insertions(+), 51 deletions(-)
diff --git a/hw/esp.c b/hw/esp.c
index 9e1c230..66e0387 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -226,7 +226,8 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
s->async_len = 0;
}
- if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
+ s->current_dev = scsi_device_find(&s->bus, target, 0);
+ if (!s->current_dev) {
// No such drive
s->rregs[ESP_RSTAT] = 0;
s->rregs[ESP_RINTR] = INTR_DC;
@@ -234,7 +235,6 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
esp_raise_irq(s);
return 0;
}
- s->current_dev = s->bus.devs[target];
return dmalen;
}
@@ -245,6 +245,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
lun = busid & 7;
+ s->current_dev = scsi_device_find(&s->bus, s->current_dev->id, lun);
s->current_req = scsi_req_new(s->current_dev, 0, lun, buf, NULL);
datalen = scsi_req_enqueue(s->current_req);
s->ti_size = datalen;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index e3f92c2..419d982 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -531,7 +531,7 @@ static void lsi_bad_selection(LSIState *s, uint32_t id)
/* Initiate a SCSI layer data transfer. */
static void lsi_do_dma(LSIState *s, int out)
{
- uint32_t count, id;
+ uint32_t count;
target_phys_addr_t addr;
SCSIDevice *dev;
@@ -542,12 +542,8 @@ static void lsi_do_dma(LSIState *s, int out)
return;
}
- id = (s->current->tag >> 8) & 0xf;
- dev = s->bus.devs[id];
- if (!dev) {
- lsi_bad_selection(s, id);
- return;
- }
+ dev = s->current->req->dev;
+ assert(dev);
count = s->dbc;
if (count > s->current->dma_len)
@@ -771,7 +767,7 @@ static void lsi_do_command(LSIState *s)
s->command_complete = 0;
id = (s->select_tag >> 8) & 0xf;
- dev = s->bus.devs[id];
+ dev = scsi_device_find(&s->bus, id, s->current_lun);
if (!dev) {
lsi_bad_selection(s, id);
return;
@@ -1202,7 +1198,7 @@ again:
}
s->sstat0 |= LSI_SSTAT0_WOA;
s->scntl1 &= ~LSI_SCNTL1_IARB;
- if (id >= LSI_MAX_DEVS || !s->bus.devs[id]) {
+ if (!scsi_device_find(&s->bus, id, 0)) {
lsi_bad_selection(s, id);
break;
}
@@ -1684,13 +1680,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
if (val & LSI_SCNTL1_RST) {
if (!(s->sstat0 & LSI_SSTAT0_RST)) {
DeviceState *dev;
- int id;
- for (id = 0; id < LSI_MAX_DEVS; id++) {
- if (s->bus.devs[id]) {
- dev = &s->bus.devs[id]->qdev;
- dev->info->reset(dev);
- }
+ QTAILQ_FOREACH(dev, &s->bus.qbus.children, sibling) {
+ dev->info->reset(dev);
}
s->sstat0 |= LSI_SSTAT0_RST;
lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
diff --git a/hw/qdev.h b/hw/qdev.h
index ff524cb..e5ad781 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -73,7 +73,7 @@ struct BusState {
const char *name;
int allow_hotplug;
int qdev_allocated;
- QTAILQ_HEAD(, DeviceState) children;
+ QTAILQ_HEAD(ChildrenHead, DeviceState) children;
QLIST_ENTRY(BusState) sibling;
};
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index d9d4e18..c0da8c7 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -37,12 +37,16 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
+ SCSIDevice *olddev;
int rc = -1;
if (dev->id == -1) {
- for (dev->id = 0; dev->id < bus->info->ndev; dev->id++) {
- if (bus->devs[dev->id] == NULL)
+ int id;
+ for (id = 0; id < bus->info->ndev; id++) {
+ if (!scsi_device_find(bus, id, 0)) {
+ dev->id = id;
break;
+ }
}
}
if (dev->id >= bus->info->ndev) {
@@ -50,17 +54,14 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
goto err;
}
- if (bus->devs[dev->id]) {
- qdev_free(&bus->devs[dev->id]->qdev);
+ olddev = scsi_device_find(bus, dev->id, dev->lun);
+ if (olddev && dev->lun == olddev->lun) {
+ qdev_free(&olddev->qdev);
}
- bus->devs[dev->id] = dev;
dev->info = info;
QTAILQ_INIT(&dev->requests);
rc = dev->info->init(dev);
- if (rc != 0) {
- bus->devs[dev->id] = NULL;
- }
err:
return rc;
@@ -69,13 +70,10 @@ err:
static int scsi_qdev_exit(DeviceState *qdev)
{
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
- assert(bus->devs[dev->id] != NULL);
- if (bus->devs[dev->id]->info->destroy) {
- bus->devs[dev->id]->info->destroy(bus->devs[dev->id]);
+ if (dev->info->destroy) {
+ dev->info->destroy(dev);
}
- bus->devs[dev->id] = NULL;
return 0;
}
@@ -1157,19 +1155,28 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
static char *scsibus_get_fw_dev_path(DeviceState *dev)
{
SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
- SCSIBus *bus = scsi_bus_from_device(d);
char path[100];
- int i;
- for (i = 0; i < bus->info->ndev; i++) {
- if (bus->devs[i] == d) {
- break;
- }
- }
+ snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
+ 0, d->id, d->lun);
- assert(i != bus->info->ndev);
+ return strdup(path);
+}
+
+SCSIDevice *scsi_device_find(SCSIBus *bus, int id, int lun)
+{
+ DeviceState *qdev;
+ SCSIDevice *target_dev = NULL;
- snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
+ QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
+ SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- return strdup(path);
+ if (dev->id == id) {
+ if (dev->lun == lun) {
+ return dev;
+ }
+ target_dev = dev;
+ }
+ }
+ return target_dev;
}
diff --git a/hw/scsi.h b/hw/scsi.h
index b76c4ee..add3d2d 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -110,8 +110,6 @@ struct SCSIBus {
SCSISense unit_attention;
const SCSIBusInfo *info;
-
- SCSIDevice *devs[MAX_SCSI_DEVS];
};
void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
@@ -195,5 +193,6 @@ void scsi_req_abort(SCSIRequest *req, int status);
void scsi_req_cancel(SCSIRequest *req);
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
+SCSIDevice *scsi_device_find(SCSIBus *bus, int target, int lun);
#endif
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 6c5faf2..aae845a 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -129,11 +129,12 @@ static void vscsi_put_req(vscsi_req *req)
req->active = 0;
}
-static void vscsi_decode_id_lun(uint64_t srp_lun, int *id, int *lun)
+static SCSIDevice *vscsi_device_find(SCSIBus *bus, uint64_t srp_lun, int *lun)
{
/* XXX Figure that one out properly ! This is crackpot */
- *id = (srp_lun >> 56) & 0x7f;
+ int id = (srp_lun >> 56) & 0x7f;
*lun = (srp_lun >> 48) & 0xff;
+ return scsi_device_find (bus, id, *lun);
}
static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
@@ -582,14 +583,11 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
{
union srp_iu *srp = &req->iu.srp;
SCSIDevice *sdev;
- int n, id, lun;
+ int n, lun;
- vscsi_decode_id_lun(be64_to_cpu(srp->cmd.lun), &id, &lun);
-
- /* Qemu vs. linux issue with LUNs to be sorted out ... */
- sdev = (id < 8 && lun < 16) ? s->bus.devs[id] : NULL;
+ sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
if (!sdev) {
- dprintf("VSCSI: Command for id %d with no drive\n", id);
+ dprintf("VSCSI: Command for lun %08" PRIx64 " with no drive\n", be64_to_cpu(srp->cmd.lun));
if (srp->cmd.cdb[0] == INQUIRY) {
vscsi_inquiry_no_target(s, req);
} else {
--
1.7.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 4/6] scsi: implement REPORT LUNS for arbitrary LUNs
2011-09-30 16:36 [Qemu-devel] [PATCH 0/6] introduce SCSI channel/target/LUN addressing Paolo Bonzini
` (2 preceding siblings ...)
2011-09-30 16:36 ` [Qemu-devel] [PATCH 3/6] scsi: remove devs array from SCSIBus Paolo Bonzini
@ 2011-09-30 16:36 ` Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 5/6] scsi: allow " Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 6/6] scsi: add channel to addressing Paolo Bonzini
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2011-09-30 16:36 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi-bus.c | 49 +++++++++++++++++++++++++++++++++++++++----------
1 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index c0da8c7..17acf48 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -170,7 +170,7 @@ typedef struct SCSITargetReq SCSITargetReq;
struct SCSITargetReq {
SCSIRequest req;
int len;
- uint8_t buf[64];
+ uint8_t buf[2056];
};
static void store_lun(uint8_t *outbuf, int lun)
@@ -185,23 +185,52 @@ static void store_lun(uint8_t *outbuf, int lun)
static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
{
- int len;
+ DeviceState *qdev;
+ int i, len, n;
+ int id;
+ bool found_lun0;
+
if (r->req.cmd.xfer < 16) {
return false;
}
if (r->req.cmd.buf[2] > 2) {
return false;
}
- len = MIN(sizeof r->buf, r->req.cmd.xfer);
+ id = r->req.dev->id;
+ found_lun0 = false;
+ n = 0;
+ QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+ SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+
+ if (dev->id == id) {
+ if (dev->lun == 0) {
+ found_lun0 = true;
+ }
+ n += 8;
+ }
+ }
+ if (!found_lun0) {
+ n += 8;
+ }
+ len = MIN(n + 8, r->req.cmd.xfer & ~7);
+ if (len > sizeof(r->buf)) {
+ /* TODO: > 256 LUNs? */
+ return false;
+ }
+
memset(r->buf, 0, len);
- if (r->req.dev->lun != 0) {
- r->buf[3] = 16;
- r->len = 24;
- store_lun(&r->buf[16], r->req.dev->lun);
- } else {
- r->buf[3] = 8;
- r->len = 16;
+ stl_be_p(&r->buf, n);
+ i = found_lun0 ? 8 : 16;
+ QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+ SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+
+ if (dev->id == id) {
+ store_lun(&r->buf[i], dev->lun);
+ i += 8;
+ }
}
+ assert(i == n + 8);
+ r->len = len;
return true;
}
--
1.7.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 5/6] scsi: allow arbitrary LUNs
2011-09-30 16:36 [Qemu-devel] [PATCH 0/6] introduce SCSI channel/target/LUN addressing Paolo Bonzini
` (3 preceding siblings ...)
2011-09-30 16:36 ` [Qemu-devel] [PATCH 4/6] scsi: implement REPORT LUNS for arbitrary LUNs Paolo Bonzini
@ 2011-09-30 16:36 ` Paolo Bonzini
2011-09-30 16:36 ` [Qemu-devel] [PATCH 6/6] scsi: add channel to addressing Paolo Bonzini
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2011-09-30 16:36 UTC (permalink / raw)
To: qemu-devel
This only requires changes in two places: in SCSIBus, we need to look
for a free LUN if somebody creates a device with a pre-existing scsi-id
but the default LUN (-1, meaning "search for a free spot"); in vSCSI,
we need to actually parse the LUN according to the SCSI spec.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/esp.c | 3 ++-
hw/lsi53c895a.c | 3 ++-
hw/scsi-bus.c | 48 ++++++++++++++++++++++++++++++++----------------
hw/scsi.h | 3 ++-
hw/spapr_vscsi.c | 39 +++++++++++++++++++++++++++++++++++++-----
hw/usb-msd.c | 3 ++-
6 files changed, 75 insertions(+), 24 deletions(-)
diff --git a/hw/esp.c b/hw/esp.c
index 66e0387..2fe1d93 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -733,7 +733,8 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
static const struct SCSIBusInfo esp_scsi_info = {
.tcq = false,
- .ndev = ESP_MAX_DEVS,
+ .max_target = ESP_MAX_DEVS,
+ .max_lun = 7,
.transfer_data = esp_transfer_data,
.complete = esp_command_complete,
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 419d982..5fb4ab1 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2085,7 +2085,8 @@ static int lsi_scsi_uninit(PCIDevice *d)
static const struct SCSIBusInfo lsi_scsi_info = {
.tcq = true,
- .ndev = LSI_MAX_DEVS,
+ .max_target = LSI_MAX_DEVS,
+ .max_lun = 0, /* LUN support is buggy */
.transfer_data = lsi_transfer_data,
.complete = lsi_command_complete,
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 17acf48..cec06db 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -17,7 +17,7 @@ static struct BusInfo scsi_bus_info = {
.get_fw_dev_path = scsibus_get_fw_dev_path,
.props = (Property[]) {
DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
- DEFINE_PROP_UINT32("lun", SCSIDevice, lun, 0),
+ DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
DEFINE_PROP_END_OF_LIST(),
},
};
@@ -37,26 +37,42 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
- SCSIDevice *olddev;
+ SCSIDevice *d;
int rc = -1;
- if (dev->id == -1) {
- int id;
- for (id = 0; id < bus->info->ndev; id++) {
- if (!scsi_device_find(bus, id, 0)) {
- dev->id = id;
- break;
- }
- }
- }
- if (dev->id >= bus->info->ndev) {
+ if (dev->id != -1 && dev->id > bus->info->max_target) {
error_report("bad scsi device id: %d", dev->id);
goto err;
}
- olddev = scsi_device_find(bus, dev->id, dev->lun);
- if (olddev && dev->lun == olddev->lun) {
- qdev_free(&olddev->qdev);
+ if (dev->id == -1) {
+ int id = -1;
+ if (dev->lun == -1) {
+ dev->lun = 0;
+ }
+ do {
+ d = scsi_device_find(bus, ++id, dev->lun);
+ } while (d && d->lun == dev->lun && id <= bus->info->max_target);
+ if (id > bus->info->max_target) {
+ error_report("no free target");
+ goto err;
+ }
+ dev->id = id;
+ } else if (dev->lun == -1) {
+ int lun = -1;
+ do {
+ d = scsi_device_find(bus, dev->id, ++lun);
+ } while (d && d->lun == lun && lun < bus->info->max_lun);
+ if (lun > bus->info->max_lun) {
+ error_report("no free lun");
+ goto err;
+ }
+ dev->lun = lun;
+ } else {
+ d = scsi_device_find(bus, dev->id, dev->lun);
+ if (dev->lun == d->lun && dev != d) {
+ qdev_free(&d->qdev);
+ }
}
dev->info = info;
@@ -115,7 +131,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
int res = 0, unit;
loc_push_none(&loc);
- for (unit = 0; unit < bus->info->ndev; unit++) {
+ for (unit = 0; unit < bus->info->max_target; unit++) {
dinfo = drive_get(IF_SCSI, bus->busnr, unit);
if (dinfo == NULL) {
continue;
diff --git a/hw/scsi.h b/hw/scsi.h
index add3d2d..401d8d3 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -98,7 +98,8 @@ struct SCSIDeviceInfo {
};
struct SCSIBusInfo {
- int tcq, ndev;
+ int tcq;
+ int max_target, max_lun;
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
void (*complete)(SCSIRequest *req, uint32_t arg);
void (*cancel)(SCSIRequest *req);
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index aae845a..69d98d3 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -131,9 +131,39 @@ static void vscsi_put_req(vscsi_req *req)
static SCSIDevice *vscsi_device_find(SCSIBus *bus, uint64_t srp_lun, int *lun)
{
- /* XXX Figure that one out properly ! This is crackpot */
- int id = (srp_lun >> 56) & 0x7f;
- *lun = (srp_lun >> 48) & 0xff;
+ int channel = 0, id = 0;
+
+retry:
+ switch (srp_lun >> 62) {
+ case 0:
+ if ((srp_lun >> 56) != 0) {
+ channel = (srp_lun >> 56) & 0x3f;
+ id = (srp_lun >> 48) & 0xff;
+ srp_lun <<= 16;
+ goto retry;
+ }
+ *lun = (srp_lun >> 48) & 0xff;
+ break;
+
+ case 1:
+ *lun = (srp_lun >> 48) & 0x3fff;
+ break;
+ case 2:
+ channel = (srp_lun >> 53) & 0x7;
+ id = (srp_lun >> 56) & 0x3f;
+ *lun = (srp_lun >> 48) & 0x1f;
+ break;
+ case 3:
+ *lun = -1;
+ return NULL;
+ default:
+ abort();
+ }
+
+ if (channel) {
+ *lun = -1;
+ return NULL;
+ }
return scsi_device_find (bus, id, *lun);
}
@@ -862,7 +893,8 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
static const struct SCSIBusInfo vscsi_scsi_info = {
.tcq = true,
- .ndev = 63, /* logical unit addressing format */
+ .max_target = 63, /* logical unit addressing format */
+ .max_lun = 31,
.transfer_data = vscsi_transfer_data,
.complete = vscsi_command_complete,
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index d0e0cd3..2d88596 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -494,7 +494,8 @@ static void usb_msd_password_cb(void *opaque, int err)
static const struct SCSIBusInfo usb_msd_scsi_info = {
.tcq = false,
- .ndev = 1,
+ .max_target = 0,
+ .max_lun = 0,
.transfer_data = usb_msd_transfer_data,
.complete = usb_msd_command_complete,
--
1.7.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 6/6] scsi: add channel to addressing
2011-09-30 16:36 [Qemu-devel] [PATCH 0/6] introduce SCSI channel/target/LUN addressing Paolo Bonzini
` (4 preceding siblings ...)
2011-09-30 16:36 ` [Qemu-devel] [PATCH 5/6] scsi: allow " Paolo Bonzini
@ 2011-09-30 16:36 ` Paolo Bonzini
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2011-09-30 16:36 UTC (permalink / raw)
To: qemu-devel
This also requires little more than adding the new argument to
scsi_device_find, and the qdev property. All devices by default
end up on channel 0.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/esp.c | 4 ++--
hw/lsi53c895a.c | 4 ++--
hw/scsi-bus.c | 24 +++++++++++++++---------
hw/scsi.h | 5 +++--
hw/spapr_vscsi.c | 9 +++-------
5 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/hw/esp.c b/hw/esp.c
index 2fe1d93..f59bb72 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -226,7 +226,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
s->async_len = 0;
}
- s->current_dev = scsi_device_find(&s->bus, target, 0);
+ s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
if (!s->current_dev) {
// No such drive
s->rregs[ESP_RSTAT] = 0;
@@ -245,7 +245,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
lun = busid & 7;
- s->current_dev = scsi_device_find(&s->bus, s->current_dev->id, lun);
+ s->current_dev = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
s->current_req = scsi_req_new(s->current_dev, 0, lun, buf, NULL);
datalen = scsi_req_enqueue(s->current_req);
s->ti_size = datalen;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 5fb4ab1..2b24b7c 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -767,7 +767,7 @@ static void lsi_do_command(LSIState *s)
s->command_complete = 0;
id = (s->select_tag >> 8) & 0xf;
- dev = scsi_device_find(&s->bus, id, s->current_lun);
+ dev = scsi_device_find(&s->bus, 0, id, s->current_lun);
if (!dev) {
lsi_bad_selection(s, id);
return;
@@ -1198,7 +1198,7 @@ again:
}
s->sstat0 |= LSI_SSTAT0_WOA;
s->scntl1 &= ~LSI_SCNTL1_IARB;
- if (!scsi_device_find(&s->bus, id, 0)) {
+ if (!scsi_device_find(&s->bus, 0, id, 0)) {
lsi_bad_selection(s, id);
break;
}
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index cec06db..bdd6e94 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -16,6 +16,7 @@ static struct BusInfo scsi_bus_info = {
.size = sizeof(SCSIBus),
.get_fw_dev_path = scsibus_get_fw_dev_path,
.props = (Property[]) {
+ DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1),
DEFINE_PROP_END_OF_LIST(),
@@ -40,6 +41,10 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
SCSIDevice *d;
int rc = -1;
+ if (dev->channel > bus->info->max_channel) {
+ error_report("bad scsi channel id: %d", dev->channel);
+ goto err;
+ }
if (dev->id != -1 && dev->id > bus->info->max_target) {
error_report("bad scsi device id: %d", dev->id);
goto err;
@@ -51,7 +56,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
dev->lun = 0;
}
do {
- d = scsi_device_find(bus, ++id, dev->lun);
+ d = scsi_device_find(bus, dev->channel, ++id, dev->lun);
} while (d && d->lun == dev->lun && id <= bus->info->max_target);
if (id > bus->info->max_target) {
error_report("no free target");
@@ -61,7 +66,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
} else if (dev->lun == -1) {
int lun = -1;
do {
- d = scsi_device_find(bus, dev->id, ++lun);
+ d = scsi_device_find(bus, dev->channel, dev->id, ++lun);
} while (d && d->lun == lun && lun < bus->info->max_lun);
if (lun > bus->info->max_lun) {
error_report("no free lun");
@@ -69,7 +74,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
}
dev->lun = lun;
} else {
- d = scsi_device_find(bus, dev->id, dev->lun);
+ d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
if (dev->lun == d->lun && dev != d) {
qdev_free(&d->qdev);
}
@@ -203,7 +208,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
{
DeviceState *qdev;
int i, len, n;
- int id;
+ int channel, id;
bool found_lun0;
if (r->req.cmd.xfer < 16) {
@@ -212,13 +217,14 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
if (r->req.cmd.buf[2] > 2) {
return false;
}
+ channel = r->req.dev->channel;
id = r->req.dev->id;
found_lun0 = false;
n = 0;
QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- if (dev->id == id) {
+ if (dev->channel == channel && dev->id == id) {
if (dev->lun == 0) {
found_lun0 = true;
}
@@ -240,7 +246,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- if (dev->id == id) {
+ if (dev->channel == channel && dev->id == id) {
store_lun(&r->buf[i], dev->lun);
i += 8;
}
@@ -1203,12 +1209,12 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
char path[100];
snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
- 0, d->id, d->lun);
+ d->channel, d->id, d->lun);
return strdup(path);
}
-SCSIDevice *scsi_device_find(SCSIBus *bus, int id, int lun)
+SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
{
DeviceState *qdev;
SCSIDevice *target_dev = NULL;
@@ -1216,7 +1222,7 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int id, int lun)
QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- if (dev->id == id) {
+ if (dev->channel == channel && dev->id == id) {
if (dev->lun == lun) {
return dev;
}
diff --git a/hw/scsi.h b/hw/scsi.h
index 401d8d3..c8649cf 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -66,6 +66,7 @@ struct SCSIDevice
uint8_t sense[SCSI_SENSE_BUF_SIZE];
uint32_t sense_len;
QTAILQ_HEAD(, SCSIRequest) requests;
+ uint32_t channel;
uint32_t lun;
int blocksize;
int type;
@@ -99,7 +100,7 @@ struct SCSIDeviceInfo {
struct SCSIBusInfo {
int tcq;
- int max_target, max_lun;
+ int max_channel, max_target, max_lun;
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
void (*complete)(SCSIRequest *req, uint32_t arg);
void (*cancel)(SCSIRequest *req);
@@ -194,6 +195,6 @@ void scsi_req_abort(SCSIRequest *req, int status);
void scsi_req_cancel(SCSIRequest *req);
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
-SCSIDevice *scsi_device_find(SCSIBus *bus, int target, int lun);
+SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
#endif
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 69d98d3..2f9cbc8 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -160,11 +160,7 @@ retry:
abort();
}
- if (channel) {
- *lun = -1;
- return NULL;
- }
- return scsi_device_find (bus, id, *lun);
+ return scsi_device_find (bus, channel, id, *lun);
}
static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
@@ -893,7 +888,8 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
static const struct SCSIBusInfo vscsi_scsi_info = {
.tcq = true,
- .max_target = 63, /* logical unit addressing format */
+ .max_channel = 7, /* logical unit addressing format */
+ .max_target = 63,
.max_lun = 31,
.transfer_data = vscsi_transfer_data,
--
1.7.6
^ permalink raw reply related [flat|nested] 7+ messages in thread