Revision 5e954943

b/hw/core/qdev.c
213 213
        error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
214 214
        return;
215 215
    }
216
    assert(dc->unplug != NULL);
217 216

  
218 217
    if (!dc->hotpluggable) {
219 218
        error_set(errp, QERR_DEVICE_NO_HOTPLUG,
......
223 222

  
224 223
    qdev_hot_removed = true;
225 224

  
226
    if (dc->unplug(dev) < 0) {
227
        error_set(errp, QERR_UNDEFINED_ERROR);
228
        return;
225
    if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
226
        hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp);
227
    } else {
228
        assert(dc->unplug != NULL);
229
        if (dc->unplug(dev) < 0) { /* legacy handler */
230
            error_set(errp, QERR_UNDEFINED_ERROR);
231
        }
229 232
    }
230 233
}
231 234

  
......
720 723
            dc->realize(dev, &local_err);
721 724
        }
722 725

  
726
        if (dev->parent_bus && dev->parent_bus->hotplug_handler &&
727
            local_err == NULL) {
728
            hotplug_handler_plug(dev->parent_bus->hotplug_handler,
729
                                 dev, &local_err);
730
        }
731

  
723 732
        if (qdev_get_vmsd(dev) && local_err == NULL) {
724 733
            vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
725 734
                                           dev->instance_id_alias,
b/hw/pci/pci.c
35 35
#include "hw/pci/msi.h"
36 36
#include "hw/pci/msix.h"
37 37
#include "exec/address-spaces.h"
38
#include "hw/hotplug.h"
38 39

  
39 40
//#define DEBUG_PCI
40 41
#ifdef DEBUG_PCI
......
346 347
    bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
347 348
}
348 349

  
349
void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
350
{
351
    bus->qbus.allow_hotplug = 1;
352
    bus->hotplug = hotplug;
353
    bus->hotplug_qdev = qdev;
354
}
355

  
356 350
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
357 351
                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
358 352
                         void *irq_opaque,
......
1778 1772
    }
1779 1773
    pci_add_option_rom(pci_dev, is_default_rom);
1780 1774

  
1781
    if (bus->hotplug) {
1782
        /* Let buses differentiate between hotplug and when device is
1783
         * enabled during qemu machine creation. */
1784
        rc = bus->hotplug(bus->hotplug_qdev, pci_dev,
1785
                          qdev->hotplugged ? PCI_HOTPLUG_ENABLED:
1786
                          PCI_COLDPLUG_ENABLED);
1787
        if (rc != 0) {
1788
            int r = pci_unregister_device(&pci_dev->qdev);
1789
            assert(!r);
1790
            return rc;
1791
        }
1792
    }
1793 1775
    return 0;
1794 1776
}
1795 1777

  
1796
static int pci_unplug_device(DeviceState *qdev)
1797
{
1798
    PCIDevice *dev = PCI_DEVICE(qdev);
1799

  
1800
    return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
1801
                             PCI_HOTPLUG_DISABLED);
1802
}
1803

  
1804 1778
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
1805 1779
                                    const char *name)
1806 1780
{
......
2271 2245
{
2272 2246
    DeviceClass *k = DEVICE_CLASS(klass);
2273 2247
    k->init = pci_qdev_init;
2274
    k->unplug = pci_unplug_device;
2275 2248
    k->exit = pci_unregister_device;
2276 2249
    k->bus_type = TYPE_PCI_BUS;
2277 2250
    k->props = pci_props;
b/include/hw/pci/pci.h
327 327
typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
328 328
typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
329 329

  
330
typedef enum {
331
    PCI_HOTPLUG_DISABLED,
332
    PCI_HOTPLUG_ENABLED,
333
    PCI_COLDPLUG_ENABLED,
334
} PCIHotplugState;
335

  
336
typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
337
                              PCIHotplugState state);
338

  
339 330
#define TYPE_PCI_BUS "PCI"
340 331
#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
341 332
#define TYPE_PCIE_BUS "PCIE"
......
354 345
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
355 346
                  void *irq_opaque, int nirq);
356 347
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
357
void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
358 348
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
359 349
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
360 350
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
b/include/hw/pci/pci_bus.h
16 16
    pci_set_irq_fn set_irq;
17 17
    pci_map_irq_fn map_irq;
18 18
    pci_route_irq_fn route_intx_to_irq;
19
    pci_hotplug_fn hotplug;
20
    DeviceState *hotplug_qdev;
21 19
    void *irq_opaque;
22 20
    PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
23 21
    PCIDevice *parent_dev;
b/tests/Makefile
163 163
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
164 164
tests/test-int128$(EXESUF): tests/test-int128.o
165 165
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
166
	hw/core/qdev.o hw/core/qdev-properties.o \
166
	hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
167 167
	hw/core/irq.o \
168 168
	$(qom-core-obj) \
169 169
	$(test-qapi-obj-y) \

Also available in: Unified diff