From: Bharat Bhushan <bharat.bhushan@xxxxxxxxxxxxx> This patch is required for vfio-fsl-mc meta driver to successfully bind layerscape container devices for device passthrough. This patch adds a mechanism to allow a layerscape device to specify a driver rather than a layerscape driver provide a device match. This patch is based on following proposed patches for PCI and platform devices - https://lkml.org/lkml/2014/4/8/571 :- For Platform devices - http://lists-archives.com/linux-kernel/28030441-pci-introduce-new-device-binding-path-using-pci_dev-driver_override.html :- For PCI devices Example to allow a device (dprc.1) to specifically bind with driver (vfio-fsl-mc):- - echo vfio-fsl-mc > /sys/bus/fsl-mc/devices/dprc.1/driver_override - echo dprc.1 > /sys/bus/fsl-mc/drivers/fsl_mc_dprc/unbind - echo dprc.1 > /sys/bus/fsl-mc/drivers/vfio-fsl-mc/bind Signed-off-by: J. German Rivera <German.Rivera@xxxxxxxxxxxxx> Reviewed-by: Stuart Yoder <stuart.yoder@xxxxxxxxxxxxx> Tested-by: Stuart Yoder <stuart.yoder@xxxxxxxxxxxxx> --- drivers/staging/fsl-mc/bus/mc-bus.c | 67 +++++++++++++++++++++++++++++++++++++ drivers/staging/fsl-mc/include/mc.h | 2 ++ 2 files changed, 69 insertions(+) diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index 9d98828..fdd3d17 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -58,6 +58,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) if (WARN_ON(!fsl_mc_bus_type.dev_root)) goto out; + /* When driver_override is set, only bind to the matching driver */ + if (mc_dev->driver_override) { + found = !strcmp(mc_dev->driver_override, mc_drv->driver.name); + goto out; + } + if (!mc_drv->match_id_table) goto out; @@ -116,10 +122,69 @@ static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static ssize_t driver_override_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + const char *driver_override, *old = mc_dev->driver_override; + char *cp; + + if (WARN_ON(dev->bus != &fsl_mc_bus_type)) + return -EINVAL; + + if (count > PATH_MAX) + return -EINVAL; + + driver_override = kstrndup(buf, count, GFP_KERNEL); + if (!driver_override) + return -ENOMEM; + + cp = strchr(driver_override, '\n'); + if (cp) + *cp = '\0'; + + if (strlen(driver_override)) { + mc_dev->driver_override = driver_override; + } else { + kfree(driver_override); + mc_dev->driver_override = NULL; + } + + kfree(old); + + return count; +} + +static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + + return sprintf(buf, "%s\n", mc_dev->driver_override); +} + +static DEVICE_ATTR_RW(driver_override); + +static struct attribute *fsl_mc_dev_attrs[] = { + &dev_attr_driver_override.attr, + NULL, +}; + +static const struct attribute_group fsl_mc_dev_group = { + .attrs = fsl_mc_dev_attrs, +}; + +static const struct attribute_group *fsl_mc_dev_groups[] = { + &fsl_mc_dev_group, + NULL, +}; + struct bus_type fsl_mc_bus_type = { .name = "fsl-mc", .match = fsl_mc_bus_match, .uevent = fsl_mc_bus_uevent, + .dev_groups = fsl_mc_dev_groups, }; EXPORT_SYMBOL_GPL(fsl_mc_bus_type); @@ -492,6 +557,8 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) fsl_mc_bus_type.dev_root = NULL; } + kfree(mc_dev->driver_override); + mc_dev->driver_override = NULL; if (!mc_bus) kmem_cache_free(mc_dev_cache, mc_dev); else diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index c543a84..322b594 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -145,6 +145,7 @@ struct fsl_mc_device_irq { * @regions: pointer to array of MMIO region entries * @irqs: pointer to array of pointers to interrupts allocated to this device * @resource: generic resource associated with this MC object device, if any. + * @driver_override: Driver name to force a match * * Generic device object for MC object devices that are "attached" to a * MC bus. @@ -177,6 +178,7 @@ struct fsl_mc_device { struct resource *regions; struct fsl_mc_device_irq **irqs; struct fsl_mc_resource *resource; + const char *driver_override; }; #define to_fsl_mc_device(_dev) \ -- 2.3.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel