提交 133e9b22 编写于 作者: M Markus Armbruster 提交者: Michael S. Tsirkin

pci: Convert core to realize

Implement DeviceClass methods realize() and unrealize() instead of
init() and exit().  The core's initialization errors now get
propagated properly, and QMP sends them instead of an unspecific
"Device initialization failed" error.  Unrealize can't fail, so no
change there.

PCIDeviceClass is unchanged: it still provides init() and exit().
Therefore, device models' errors are still not propagated.
Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
Reviewed-by: NMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
Reviewed-by: NGonglei <arei.gonglei@huawei.com>
上级 661875e9
......@@ -115,7 +115,7 @@ static const TypeInfo pcie_bus_info = {
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
static void pci_update_mappings(PCIDevice *d);
static void pci_irq_handler(void *opaque, int irq_num, int level);
static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, Error **);
static void pci_del_option_rom(PCIDevice *pdev);
static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
......@@ -726,7 +726,7 @@ static void pci_init_mask_bridge(PCIDevice *d)
PCI_PREF_RANGE_TYPE_MASK);
}
static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
static void pci_init_multifunction(PCIBus *bus, PCIDevice *dev, Error **errp)
{
uint8_t slot = PCI_SLOT(dev->devfn);
uint8_t func;
......@@ -752,26 +752,25 @@ static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)];
if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) {
/* function 0 should set multifunction bit */
error_report("PCI: single function device can't be populated "
"in function %x.%x", slot, PCI_FUNC(dev->devfn));
return -1;
error_setg(errp, "PCI: single function device can't be populated "
"in function %x.%x", slot, PCI_FUNC(dev->devfn));
return;
}
return 0;
return;
}
if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
return 0;
return;
}
/* function 0 indicates single function, so function > 0 must be NULL */
for (func = 1; func < PCI_FUNC_MAX; ++func) {
if (bus->devices[PCI_DEVFN(slot, func)]) {
error_report("PCI: %x.0 indicates single function, "
"but %x.%x is already populated.",
slot, slot, func);
return -1;
error_setg(errp, "PCI: %x.0 indicates single function, "
"but %x.%x is already populated.",
slot, slot, func);
return;
}
}
return 0;
}
static void pci_config_alloc(PCIDevice *pci_dev)
......@@ -804,11 +803,13 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
/* -1 for devfn means auto assign */
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
const char *name, int devfn)
const char *name, int devfn,
Error **errp)
{
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
PCIConfigReadFunc *config_read = pc->config_read;
PCIConfigWriteFunc *config_write = pc->config_write;
Error *local_err = NULL;
AddressSpace *dma_as;
if (devfn < 0) {
......@@ -817,12 +818,15 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (!bus->devices[devfn])
goto found;
}
error_report("PCI: no slot/function available for %s, all in use", name);
error_setg(errp, "PCI: no slot/function available for %s, all in use",
name);
return NULL;
found: ;
} else if (bus->devices[devfn]) {
error_report("PCI: slot %d function %d not available for %s, in use by %s",
PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);
error_setg(errp, "PCI: slot %d function %d not available for %s,"
" in use by %s",
PCI_SLOT(devfn), PCI_FUNC(devfn), name,
bus->devices[devfn]->name);
return NULL;
}
......@@ -866,7 +870,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (pc->is_bridge) {
pci_init_mask_bridge(pci_dev);
}
if (pci_init_multifunction(bus, pci_dev)) {
pci_init_multifunction(bus, pci_dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
do_pci_unregister_device(pci_dev);
return NULL;
}
......@@ -897,7 +903,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
pci_unregister_vga(pci_dev);
}
static int pci_unregister_device(DeviceState *dev)
static void pci_qdev_unrealize(DeviceState *dev, Error **errp)
{
PCIDevice *pci_dev = PCI_DEVICE(dev);
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
......@@ -910,7 +916,6 @@ static int pci_unregister_device(DeviceState *dev)
}
do_pci_unregister_device(pci_dev);
return 0;
}
void pci_register_bar(PCIDevice *pci_dev, int region_num,
......@@ -1751,10 +1756,11 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
return bus->devices[devfn];
}
static int pci_qdev_init(DeviceState *qdev)
static void pci_qdev_realize(DeviceState *qdev, Error **errp)
{
PCIDevice *pci_dev = (PCIDevice *)qdev;
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
Error *local_err = NULL;
PCIBus *bus;
int rc;
bool is_default_rom;
......@@ -1767,15 +1773,16 @@ static int pci_qdev_init(DeviceState *qdev)
bus = PCI_BUS(qdev_get_parent_bus(qdev));
pci_dev = do_pci_register_device(pci_dev, bus,
object_get_typename(OBJECT(qdev)),
pci_dev->devfn);
pci_dev->devfn, errp);
if (pci_dev == NULL)
return -1;
return;
if (pc->init) {
rc = pc->init(pci_dev);
if (rc != 0) {
do_pci_unregister_device(pci_dev);
return rc;
error_setg(errp, "Device initialization failed");
return;
}
}
......@@ -1786,13 +1793,12 @@ static int pci_qdev_init(DeviceState *qdev)
is_default_rom = true;
}
rc = pci_add_option_rom(pci_dev, is_default_rom);
if (rc != 0) {
pci_unregister_device(DEVICE(pci_dev));
return rc;
pci_add_option_rom(pci_dev, is_default_rom, &local_err);
if (local_err) {
error_propagate(errp, local_err);
pci_qdev_unrealize(DEVICE(pci_dev), NULL);
return;
}
return 0;
}
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
......@@ -1932,7 +1938,8 @@ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size)
}
/* Add an option rom for the device */
static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
Error **errp)
{
int size;
char *path;
......@@ -1941,9 +1948,9 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
const VMStateDescription *vmsd;
if (!pdev->romfile)
return 0;
return;
if (strlen(pdev->romfile) == 0)
return 0;
return;
if (!pdev->rom_bar) {
/*
......@@ -1957,7 +1964,9 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
* if the rom bar is disabled.
*/
if (DEVICE(pdev)->hotplugged) {
return -1;
error_setg(errp, "Hot-plugged device without ROM bar"
" can't have an option ROM");
return;
}
if (class == 0x0300) {
......@@ -1965,7 +1974,7 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
} else {
rom_add_option(pdev->romfile, -1);
}
return 0;
return;
}
path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile);
......@@ -1975,15 +1984,13 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
size = get_image_size(path);
if (size < 0) {
error_report("%s: failed to find romfile \"%s\"",
__func__, pdev->romfile);
error_setg(errp, "failed to find romfile \"%s\"", pdev->romfile);
g_free(path);
return -1;
return;
} else if (size == 0) {
error_report("%s: ignoring empty romfile \"%s\"",
__func__, pdev->romfile);
error_setg(errp, "romfile \"%s\" is empty", pdev->romfile);
g_free(path);
return -1;
return;
}
if (size & (size - 1)) {
size = 1 << qemu_fls(size);
......@@ -2009,8 +2016,6 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
}
pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom);
return 0;
}
static void pci_del_option_rom(PCIDevice *pdev)
......@@ -2291,8 +2296,8 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev)
static void pci_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = pci_qdev_init;
k->exit = pci_unregister_device;
k->realize = pci_qdev_realize;
k->unrealize = pci_qdev_unrealize;
k->bus_type = TYPE_PCI_BUS;
k->props = pci_props;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册