scsi: switch to bus->check_address
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20201006123904.610658-6-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
2d24a64661
commit
42a90a899e
|
@ -22,33 +22,6 @@ static void scsi_req_dequeue(SCSIRequest *req);
|
||||||
static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
|
static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
|
||||||
static void scsi_target_free_buf(SCSIRequest *req);
|
static void scsi_target_free_buf(SCSIRequest *req);
|
||||||
|
|
||||||
static Property scsi_props[] = {
|
|
||||||
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(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void scsi_bus_class_init(ObjectClass *klass, void *data)
|
|
||||||
{
|
|
||||||
BusClass *k = BUS_CLASS(klass);
|
|
||||||
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
|
|
||||||
|
|
||||||
k->get_dev_path = scsibus_get_dev_path;
|
|
||||||
k->get_fw_dev_path = scsibus_get_fw_dev_path;
|
|
||||||
hc->unplug = qdev_simple_device_unplug_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const TypeInfo scsi_bus_info = {
|
|
||||||
.name = TYPE_SCSI_BUS,
|
|
||||||
.parent = TYPE_BUS,
|
|
||||||
.instance_size = sizeof(SCSIBus),
|
|
||||||
.class_init = scsi_bus_class_init,
|
|
||||||
.interfaces = (InterfaceInfo[]) {
|
|
||||||
{ TYPE_HOTPLUG_HANDLER },
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static int next_scsi_bus;
|
static int next_scsi_bus;
|
||||||
|
|
||||||
static void scsi_device_realize(SCSIDevice *s, Error **errp)
|
static void scsi_device_realize(SCSIDevice *s, Error **errp)
|
||||||
|
@ -160,35 +133,68 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool scsi_bus_is_address_free(SCSIBus *bus,
|
||||||
|
int channel, int target, int lun,
|
||||||
|
SCSIDevice **p_dev)
|
||||||
|
{
|
||||||
|
SCSIDevice *d = scsi_device_find(bus, channel, target, lun);
|
||||||
|
if (d && d->lun == lun) {
|
||||||
|
if (p_dev) {
|
||||||
|
*p_dev = d;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (p_dev) {
|
||||||
|
*p_dev = NULL;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool scsi_bus_check_address(BusState *qbus, DeviceState *qdev, Error **errp)
|
||||||
|
{
|
||||||
|
SCSIDevice *dev = SCSI_DEVICE(qdev);
|
||||||
|
SCSIBus *bus = SCSI_BUS(qbus);
|
||||||
|
|
||||||
|
if (dev->channel > bus->info->max_channel) {
|
||||||
|
error_setg(errp, "bad scsi channel id: %d", dev->channel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dev->id != -1 && dev->id > bus->info->max_target) {
|
||||||
|
error_setg(errp, "bad scsi device id: %d", dev->id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dev->lun != -1 && dev->lun > bus->info->max_lun) {
|
||||||
|
error_setg(errp, "bad scsi device lun: %d", dev->lun);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->id != -1 && dev->lun != -1) {
|
||||||
|
SCSIDevice *d;
|
||||||
|
if (!scsi_bus_is_address_free(bus, dev->channel, dev->id, dev->lun, &d)) {
|
||||||
|
error_setg(errp, "lun already used by '%s'", d->qdev.id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
|
static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
|
||||||
{
|
{
|
||||||
SCSIDevice *dev = SCSI_DEVICE(qdev);
|
SCSIDevice *dev = SCSI_DEVICE(qdev);
|
||||||
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
|
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
|
||||||
SCSIDevice *d;
|
bool is_free;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (dev->channel > bus->info->max_channel) {
|
|
||||||
error_setg(errp, "bad scsi channel id: %d", dev->channel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dev->id != -1 && dev->id > bus->info->max_target) {
|
|
||||||
error_setg(errp, "bad scsi device id: %d", dev->id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dev->lun != -1 && dev->lun > bus->info->max_lun) {
|
|
||||||
error_setg(errp, "bad scsi device lun: %d", dev->lun);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev->id == -1) {
|
if (dev->id == -1) {
|
||||||
int id = -1;
|
int id = -1;
|
||||||
if (dev->lun == -1) {
|
if (dev->lun == -1) {
|
||||||
dev->lun = 0;
|
dev->lun = 0;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
d = scsi_device_find(bus, dev->channel, ++id, dev->lun);
|
is_free = scsi_bus_is_address_free(bus, dev->channel, ++id, dev->lun, NULL);
|
||||||
} while (d && d->lun == dev->lun && id < bus->info->max_target);
|
} while (!is_free && id < bus->info->max_target);
|
||||||
if (d && d->lun == dev->lun) {
|
if (!is_free) {
|
||||||
error_setg(errp, "no free target");
|
error_setg(errp, "no free target");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -196,20 +202,13 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
|
||||||
} else if (dev->lun == -1) {
|
} else if (dev->lun == -1) {
|
||||||
int lun = -1;
|
int lun = -1;
|
||||||
do {
|
do {
|
||||||
d = scsi_device_find(bus, dev->channel, dev->id, ++lun);
|
is_free = scsi_bus_is_address_free(bus, dev->channel, dev->id, ++lun, NULL);
|
||||||
} while (d && d->lun == lun && lun < bus->info->max_lun);
|
} while (!is_free && lun < bus->info->max_lun);
|
||||||
if (d && d->lun == lun) {
|
if (!is_free) {
|
||||||
error_setg(errp, "no free lun");
|
error_setg(errp, "no free lun");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dev->lun = lun;
|
dev->lun = lun;
|
||||||
} else {
|
|
||||||
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
|
|
||||||
assert(d);
|
|
||||||
if (d->lun == dev->lun && dev != d) {
|
|
||||||
error_setg(errp, "lun already used by '%s'", d->qdev.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTAILQ_INIT(&dev->requests);
|
QTAILQ_INIT(&dev->requests);
|
||||||
|
@ -1723,6 +1722,13 @@ const VMStateDescription vmstate_scsi_device = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property scsi_props[] = {
|
||||||
|
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(),
|
||||||
|
};
|
||||||
|
|
||||||
static void scsi_device_class_init(ObjectClass *klass, void *data)
|
static void scsi_device_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *k = DEVICE_CLASS(klass);
|
DeviceClass *k = DEVICE_CLASS(klass);
|
||||||
|
@ -1753,6 +1759,28 @@ static const TypeInfo scsi_device_type_info = {
|
||||||
.instance_init = scsi_dev_instance_init,
|
.instance_init = scsi_dev_instance_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void scsi_bus_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
BusClass *k = BUS_CLASS(klass);
|
||||||
|
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
|
||||||
|
|
||||||
|
k->get_dev_path = scsibus_get_dev_path;
|
||||||
|
k->get_fw_dev_path = scsibus_get_fw_dev_path;
|
||||||
|
k->check_address = scsi_bus_check_address;
|
||||||
|
hc->unplug = qdev_simple_device_unplug_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo scsi_bus_info = {
|
||||||
|
.name = TYPE_SCSI_BUS,
|
||||||
|
.parent = TYPE_BUS,
|
||||||
|
.instance_size = sizeof(SCSIBus),
|
||||||
|
.class_init = scsi_bus_class_init,
|
||||||
|
.interfaces = (InterfaceInfo[]) {
|
||||||
|
{ TYPE_HOTPLUG_HANDLER },
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static void scsi_register_types(void)
|
static void scsi_register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&scsi_bus_info);
|
type_register_static(&scsi_bus_info);
|
||||||
|
|
Loading…
Reference in a new issue