Generalize qemu_parse_pci_devaddr by two flags so that it can be used for parsing pci-devfn properties as well.
Signed-off-by: Jan Kiszka <jan.kis...@siemens.com> --- hw/pci-hotplug.c | 2 +- hw/pci.c | 3 ++- hw/qdev-properties.c | 49 ++++++++++++++++++++++++------------------------- hw/qdev.h | 2 ++ 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index 60c8989..3156e99 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -41,7 +41,7 @@ static int read_pci_devaddr(Monitor *mon, const char *addrstr, if (!strncmp(addrstr, "pci_addr=", 9)) { addrstr += 9; } - if (qemu_parse_pci_devaddr(addrstr, addr, 0)) { + if (qemu_parse_pci_devaddr(addrstr, addr, PCI_DEVADDR_WITH_DOM_BUS_OPT)) { monitor_printf(mon, "Invalid pci address\n"); return -1; } diff --git a/hw/pci.c b/hw/pci.c index 5056fc4..ccbc6aa 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -517,7 +517,8 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) return pci_find_bus_nr(pci_find_root_bus(0), 0); } - if (qemu_parse_pci_devaddr(devaddr, &addr, 0) < 0) { + if (qemu_parse_pci_devaddr(devaddr, &addr, + PCI_DEVADDR_WITH_DOM_BUS_OPT) < 0) { return NULL; } diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 14ea394..32e41f1 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -817,8 +817,11 @@ PropertyInfo qdev_prop_losttickpolicy = { /* --- pci address --- */ /* - * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if !PCI_DEVADDR_WITH_FUNC - * [[<domain>:]<bus>:]<slot>.<func>, return -1 on error + * Parse + * [[<domain>:]<bus>:]<slot>... if PCI_DEVADDR_WITH_DOM_BUS_OPT + * ...<slot>.<func> if PCI_DEVADDR_WITH_FUNC + * ...<slot>[.<func>] if PCI_DEVADDR_WITH_FUNC_OPT + * return -1 on error */ int qemu_parse_pci_devaddr(const char *addrstr, PCIDeviceAddress *addr, unsigned int flags) @@ -836,6 +839,9 @@ int qemu_parse_pci_devaddr(const char *addrstr, PCIDeviceAddress *addr, return -1; } if (*e == ':') { + if (!(flags & PCI_DEVADDR_WITH_DOM_BUS_OPT)) { + return -1; + } bus = val; p = e + 1; val = strtoul(p, &e, 16); @@ -855,16 +861,19 @@ int qemu_parse_pci_devaddr(const char *addrstr, PCIDeviceAddress *addr, slot = val; - if (flags & PCI_DEVADDR_WITH_FUNC) { + if (flags & (PCI_DEVADDR_WITH_FUNC | PCI_DEVADDR_WITH_FUNC_OPT)) { if (*e != '.') { - return -1; - } - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) { - return -1; + if (flags & PCI_DEVADDR_WITH_FUNC) { + return -1; + } + } else { + p = e + 1; + val = strtoul(p, &e, 16); + if (e == p) { + return -1; + } + func = val; } - func = val; } if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) { @@ -890,7 +899,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque, DeviceState *dev = DEVICE(obj); Property *prop = opaque; uint32_t *ptr = qdev_get_prop_ptr(dev, prop); - unsigned int slot, fn, n; + PCIDeviceAddress addr; Error *local_err = NULL; char *str; @@ -905,21 +914,11 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque, return set_int32(obj, v, opaque, name, errp); } - if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { - fn = 0; - if (sscanf(str, "%x%n", &slot, &n) != 1) { - goto invalid; - } - } - if (str[n] != '\0' || fn > 7 || slot > 31) { - goto invalid; + if (qemu_parse_pci_devaddr(str, &addr, PCI_DEVADDR_WITH_FUNC_OPT) < 0) { + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + } else { + *ptr = addr.slot << 3 | addr.function; } - *ptr = slot << 3 | fn; - g_free(str); - return; - -invalid: - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); g_free(str); } diff --git a/hw/qdev.h b/hw/qdev.h index 102550b..15acfca 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -360,7 +360,9 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus); extern int qdev_hotplug; +#define PCI_DEVADDR_WITH_DOM_BUS_OPT 1 #define PCI_DEVADDR_WITH_FUNC 2 +#define PCI_DEVADDR_WITH_FUNC_OPT 4 int qemu_parse_pci_devaddr(const char *addrstr, PCIDeviceAddress *addr, unsigned int flags); -- 1.7.3.4