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