PCI: centralize parsing of device coordinates in command line options With yet another case to come in a subsequent patch, it seems time to do this in a single place rather than hand crafting it in various scattered around locations. Signed-off-by: Jan Beulich --- a/xen/drivers/char/ehci-dbgp.c +++ b/xen/drivers/char/ehci-dbgp.c @@ -1482,31 +1482,25 @@ void __init ehci_dbgp_init(void) } else if ( strncmp(opt_dbgp + 4, "@pci", 4) == 0 ) { - unsigned long val = simple_strtoul(opt_dbgp + 8, &e, 16); + unsigned int bus, slot, func; - dbgp->bus = val; - if ( dbgp->bus != val || *e != ':' ) + e = parse_pci(opt_dbgp + 8, NULL, &bus, &slot, &func); + if ( !e || *e ) return; - val = simple_strtoul(e + 1, &e, 16); - if ( PCI_SLOT(PCI_DEVFN(val, 0)) != val || *e != '.' ) - return; - dbgp->slot = val; - - val = simple_strtoul(e + 1, &e, 16); - if ( PCI_FUNC(PCI_DEVFN(0, val)) != val || *e ) - return; - dbgp->func = val; + dbgp->bus = bus; + dbgp->slot = slot; + dbgp->func = func; - if ( !pci_device_detect(0, dbgp->bus, dbgp->slot, dbgp->func) ) + if ( !pci_device_detect(0, bus, slot, func) ) return; - dbgp->cap = __find_dbgp(dbgp->bus, dbgp->slot, dbgp->func); + dbgp->cap = __find_dbgp(bus, slot, func); if ( !dbgp->cap ) return; dbgp_printk("Using EHCI debug port on %02x:%02x.%u\n", - dbgp->bus, dbgp->slot, dbgp->func); + bus, slot, func); } else return; --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -403,19 +403,6 @@ static int __init parse_parity_char(int return 0; } -static void __init parse_pci_bdf(const char **conf, unsigned int bdf[3]) -{ - bdf[0] = simple_strtoul(*conf, conf, 16); - if ( **conf != ':' ) - return; - (*conf)++; - bdf[1] = simple_strtoul(*conf, conf, 16); - if ( **conf != '.' ) - return; - (*conf)++; - bdf[2] = simple_strtoul(*conf, conf, 16); -} - static int __init check_existence(struct ns16550 *uart) { unsigned char status, scratch, scratch2, scratch3; @@ -593,14 +580,19 @@ static void __init ns16550_parse_port_co if ( *conf == ',' && *++conf != ',' ) { + conf = parse_pci(conf, NULL, &uart->ps_bdf[0], + &uart->ps_bdf[1], &uart->ps_bdf[2]); + if ( !conf ) + PARSE_ERR("Bad port PCI coordinates"); uart->ps_bdf_enable = 1; - parse_pci_bdf(&conf, &uart->ps_bdf[0]); } if ( *conf == ',' && *++conf != ',' ) { + if ( !parse_pci(conf, NULL, &uart->pb_bdf[0], + &uart->pb_bdf[1], &uart->pb_bdf[2]) ) + PARSE_ERR("Bad bridge PCI coordinates"); uart->pb_bdf_enable = 1; - parse_pci_bdf(&conf, &uart->pb_bdf[0]); } config_parsed: --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -127,29 +127,20 @@ static unsigned int nr_phantom_devs; static void __init parse_phantom_dev(char *str) { const char *s = str; + unsigned int seg, bus, slot; struct phantom_dev phantom; if ( !s || !*s || nr_phantom_devs >= ARRAY_SIZE(phantom_devs) ) return; - phantom.seg = simple_strtol(s, &s, 16); - if ( *s != ':' ) + s = parse_pci(s, &seg, &bus, &slot, NULL); + if ( !s || *s != ',' ) return; - phantom.bus = simple_strtol(s + 1, &s, 16); - if ( *s == ',' ) - { - phantom.slot = phantom.bus; - phantom.bus = phantom.seg; - phantom.seg = 0; - } - else if ( *s == ':' ) - phantom.slot = simple_strtol(s + 1, &s, 16); - else - return; + phantom.seg = seg; + phantom.bus = bus; + phantom.slot = slot; - if ( *s != ',' ) - return; switch ( phantom.stride = simple_strtol(s + 1, &s, 0) ) { case 1: case 2: case 4: --- a/xen/drivers/pci/pci.c +++ b/xen/drivers/pci/pci.c @@ -4,6 +4,7 @@ * Architecture-independent PCI access functions. */ +#include #include #include @@ -102,3 +103,44 @@ int pci_find_ext_capability(int seg, int } return 0; } + +const char *__init parse_pci(const char *s, unsigned int *seg_p, + unsigned int *bus_p, unsigned int *dev_p, + unsigned int *func_p) +{ + unsigned long seg = simple_strtoul(s, &s, 16), bus, dev, func; + + if ( *s != ':' ) + return NULL; + bus = simple_strtoul(s + 1, &s, 16); + if ( *s == ':' ) + dev = simple_strtoul(s + 1, &s, 16); + else + { + dev = bus; + bus = seg; + seg = 0; + } + if ( func_p ) + { + if ( *s != '.' ) + return NULL; + func = simple_strtoul(s + 1, &s, 0); + } + else + func = 0; + if ( seg != (seg_p ? (u16)seg : 0) || + bus != PCI_BUS(PCI_BDF2(bus, 0)) || + dev != PCI_SLOT(PCI_DEVFN(dev, 0)) || + func != PCI_FUNC(PCI_DEVFN(0, func)) ) + return NULL; + + if ( seg_p ) + *seg_p = seg; + *bus_p = bus; + *dev_p = dev; + if ( func_p ) + *func_p = func; + + return s; +} --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -139,6 +139,8 @@ int pci_mmcfg_write(unsigned int seg, un int pci_find_cap_offset(u16 seg, u8 bus, u8 dev, u8 func, u8 cap); int pci_find_next_cap(u16 seg, u8 bus, unsigned int devfn, u8 pos, int cap); int pci_find_ext_capability(int seg, int bus, int devfn, int cap); +const char *parse_pci(const char *, unsigned int *seg, unsigned int *bus, + unsigned int *dev, unsigned int *func); struct pirq; int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);