[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFCv4,12/35] plat/platform_bus: Add probe/match interface for platform devices
I've found some minor typos and I have some questions regarding the pf_find_driver() function from "platform_bus.c". I'll let them here, as inline comments. diff --git a/plat/common/platform_bus.c b/plat/common/platform_bus.c index 1410e71..fecb389 100644 --- a/plat/common/platform_bus.c +++ b/plat/common/platform_bus.c @@ -52,8 +52,10 @@ struct pf_bus_handler { }; static struct pf_bus_handler pfh; -static const char * const pf_device_list[] = { Typo: "*pf_device_compatible_list[]" +static const char *pf_device_compatilbe_list[] = { "virtio,mmio", + "pci-host-ecam-generic", + NULL }; static inline int pf_device_id_match(const struct pf_device_id *id0, @@ -67,14 +69,22 @@ static inline int pf_device_id_match(const struct pf_device_id *id0, return rc; } -static inline struct pf_driver *pf_find_driver(struct pf_device_id *id) +static inline struct pf_driver *pf_find_driver(const char *compatible) { struct pf_driver *drv; + struct pf_device_id id; UK_TAILQ_FOREACH(drv, &pfh.drv_list, next) { - if (pf_device_id_match(id, drv->device_ids)) { - uk_pr_debug("pf driver found devid=%d\n", drv->device_ids->device_id); - return drv; /* driver found */ + if (!drv->match) + continue; + + id.device_id = (uint16_t)drv->match(compatible); In both the virtio_mmio and pci_ecam implementations, driver match() function returns -1 when the "compatible" parameter isn't found in the driver's match table. Therefore, I think the condition in this statement should be "if (id.device_id > 0)". + if (id.device_id) { What would happen if a platform driver would support more than one device? For example, the implementation of "virtio_mmio_match_table[]" from "virtio_mmio.c" would allow, theoretically, more than one supported devices. If that would happen, I think "drv->device_ids" should become an array of ids and we should call "pf_device_id_match()" on all of it's elements. Would it be possible to need a platform driver like that in the future? (if it would be possible, I think we should adapt the implementation) + if (pf_device_id_match(&id, drv->device_ids)) { + uk_pr_debug("pf driver found devid(0x%x)\n", id.device_id); + + return drv; + } } } @@ -84,104 +94,96 @@ static inline struct pf_driver *pf_find_driver(struct pf_device_id *id) } static inline int pf_driver_add_device(struct pf_driver *drv, - struct pf_device_id *devid, - __u64 dev_base, - int dev_irq) + struct pf_device *dev) { - struct pf_device *dev; int ret; UK_ASSERT(drv != NULL); UK_ASSERT(drv->add_dev != NULL); + UK_ASSERT(dev != NULL); - dev = (struct pf_device *) uk_calloc(pfh.a, 1, sizeof(*dev)); - if (!dev) { - uk_pr_err("Platform : Failed to initialize: Out of memory!\n"); - return -ENOMEM; - } - - memcpy(&dev->id, devid, sizeof(dev->id)); - uk_pr_debug("pf_driver_add_device dev->id=%d\n", dev->id.device_id); - - dev->base = dev_base; - dev->irq = dev_irq; + uk_pr_debug("pf_driver_add_device devid=%d\n", dev->id.device_id); ret = drv->add_dev(dev); if (ret < 0) { uk_pr_err("Platform Failed to initialize device driver\n"); - uk_free(pfh.a, dev); } return ret; } +static inline int pf_driver_probe_device(struct pf_driver *drv, + struct pf_device *dev) +{ + int ret; + + UK_ASSERT(drv != NULL && dev != NULL); + UK_ASSERT(drv->probe != NULL); + + uk_pr_info("pf_driver_probe_device devid=%d\n", dev->id.device_id); + + ret = drv->probe(dev); + if (ret < 0) { + uk_pr_err("Platform Failed to probe device driver\n"); + + return ret; + } + + return 0; +} + static int pf_probe(void) { - struct pf_device_id devid; struct pf_driver *drv; - int i; - int end_offset = -1; + int idx = 0; int ret = -ENODEV; - const fdt32_t *prop; - int type, hwirq, prop_len; - __u64 reg_base; - __phys_addr dev_base; - int dev_irq; + struct pf_device *dev; + int fdt_pf = -1; uk_pr_info("Probe PF\n"); - /* We only support virtio_mmio as a platform device here. - * A loop here is needed for finding drivers if more devices - */ - devid.device_id = VIRTIO_MMIO_ID; + /* Search all the platform bus devices provided by fdt */ + do { Typo: "pf_device_compatible_list" + fdt_pf = fdt_node_offset_idx_by_compatible_list(_libkvmplat_cfg.dtb, + fdt_pf, pf_device_compatilbe_list, &idx); + if (fdt_pf < 0) { + uk_pr_info("End of searching platform devices\n"); + break; + } - drv = pf_find_driver(&devid); - if (!drv) { - uk_pr_info("<no driver>\n"); - return -ENODEV; - } + /* Alloc dev */ + dev = (struct pf_device *) uk_calloc(pfh.a, 1, sizeof(*dev)); + if (!dev) { + uk_pr_err("Platform : Failed to initialize: Out of memory!\n"); + return -ENOMEM; + } - uk_pr_info("driver %p\n", drv); - - /* qemu creates virtio devices in reverse order */ - for (i = 0; i < UK_MAX_VIRTIO_MMIO_DEVICE; i++) { - end_offset = fdt_node_offset_by_compatible_list(fdt_start, - end_offset, - pf_device_list); - if (end_offset == -FDT_ERR_NOTFOUND) { - uk_pr_info("device not found in fdt\n"); - goto error_exit; - } else { - prop = fdt_getprop(fdt_start, end_offset, "interrupts", &prop_len); - if (!prop) { - uk_pr_err("irq of device not found in fdt\n"); - goto error_exit; - } + dev->fdt_offset = fdt_pf; - type = fdt32_to_cpu(prop[0]); - hwirq = fdt32_to_cpu(prop[1]); + /* Find drv with compatible-id match table */ Typo: "pf_device_compatible_list" + drv = pf_find_driver(pf_device_compatilbe_list[idx]); + if (!drv) { + uk_free(pfh.a, dev); + continue; + } - prop = fdt_getprop(fdt_start, end_offset, "reg", &prop_len); - if (!prop) { - uk_pr_err("reg of device not found in fdt\n"); - goto error_exit; - } + dev->id = *(struct pf_device_id *)drv->device_ids; + uk_pr_info("driver %p\n", drv); - /* only care about base addr, ignore the size */ - reg_base = fdt32_to_cpu(prop[0]); - reg_base = reg_base << 32 | fdt32_to_cpu(prop[1]); + ret = pf_driver_probe_device(drv, dev); + if (ret < 0) { + uk_free(pfh.a, dev); + continue; } - dev_base = reg_base; - dev_irq = gic_irq_translate(type, hwirq); - - ret = pf_driver_add_device(drv, &devid, dev_base, dev_irq); - } + ret = pf_driver_add_device(drv, dev); + if (ret < 0) { + uk_pr_err("Platform Failed to initialize device driver, ret(%d)\n",ret); + uk_free(pfh.a, dev); + } + } while (1); return ret; - -error_exit: - return -ENODEV; } @@ -232,4 +234,4 @@ static struct pf_bus_handler pfh = { .b.init = pf_init, .b.probe = pf_probe }; -UK_BUS_REGISTER(&pfh.b); +UK_BUS_REGISTER_PRIORITY(&pfh.b, 1); Reviewed-by: Razvan Virtan <virtanrazvan@xxxxxxxxx>
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |