summaryrefslogtreecommitdiff
path: root/hw/scsi-bus.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2009-09-25 21:42:36 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-10-05 09:32:48 -0500
commit01985dcf38a94d0db35f54315ba2454e68f16175 (patch)
tree83a90b7164f8a7b6a60a3dfe45845970416795a9 /hw/scsi-bus.c
parentd29275f10382844e000ddaafaddc6780555e8d83 (diff)
Implement scsi device destruction
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/scsi-bus.c')
-rw-r--r--hw/scsi-bus.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 881e36320a..27defc4109 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -30,6 +30,7 @@ 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);
+ int rc = -1;
if (dev->id == -1) {
for (dev->id = 0; dev->id < bus->ndev; dev->id++) {
@@ -43,21 +44,38 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
}
if (bus->devs[dev->id]) {
- bus->devs[dev->id]->info->destroy(bus->devs[dev->id]);
+ qdev_free(&bus->devs[dev->id]->qdev);
}
bus->devs[dev->id] = dev;
dev->info = info;
- return dev->info->init(dev);
+ rc = dev->info->init(dev);
+ if (rc != 0) {
+ bus->devs[dev->id] = NULL;
+ }
err:
- return -1;
+ return rc;
+}
+
+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]);
+ }
+ bus->devs[dev->id] = NULL;
+ return 0;
}
void scsi_qdev_register(SCSIDeviceInfo *info)
{
info->qdev.bus_info = &scsi_bus_info;
info->qdev.init = scsi_qdev_init;
+ info->qdev.exit = scsi_qdev_exit;
qdev_register(&info->qdev);
}