Message ID | 20200319154051.30609-4-diana.craciun@oss.nxp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | bus/fsl-mc: Extend mc-bus driver functionalities in preparation for mc-bus VFIO support | expand |
On 3/19/2020 5:40 PM, Diana Craciun wrote: > From: Bharat Bhushan <Bharat.Bhushan@nxp.com> > > 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. > > 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: Bharat Bhushan <Bharat.Bhushan@nxp.com> > Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com> > Signed-off-by: Diana Craciun <diana.craciun@oss.nxp.com> > --- > drivers/bus/fsl-mc/fsl-mc-bus.c | 54 +++++++++++++++++++++++++++++++++ > include/linux/fsl/mc.h | 1 + > 2 files changed, 55 insertions(+) > > diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c > index c78d10ea641f..baf8259262a9 100644 > --- a/drivers/bus/fsl-mc/fsl-mc-bus.c > +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c > @@ -3,6 +3,7 @@ > * Freescale Management Complex (MC) bus driver > * > * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. > + * Copyright 2019-2020 NXP > * Author: German Rivera <German.Rivera@freescale.com> > * > */ > @@ -83,6 +84,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) > struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); > bool found = false; > > + /* 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); I think we can use sysfs_streq() here and ... > + goto out; > + } > + > if (!mc_drv->match_id_table) > goto out; > > @@ -147,8 +154,52 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, > } > static DEVICE_ATTR_RO(modalias); > > +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 >= (PAGE_SIZE - 1)) > + return -EINVAL; > + > + driver_override = kstrndup(buf, count, GFP_KERNEL); > + if (!driver_override) > + return -ENOMEM; > + > + cp = strchr(driver_override, '\n'); > + if (cp) > + *cp = '\0'; drop this strchr() ... > + 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 snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); and also the terminating '\n' here. > +} > +static DEVICE_ATTR_RW(driver_override); > + > static struct attribute *fsl_mc_dev_attrs[] = { > &dev_attr_modalias.attr, > + &dev_attr_driver_override.attr, > NULL, > }; > > @@ -704,6 +755,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_add); > */ > void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) > { > + kfree(mc_dev->driver_override); > + mc_dev->driver_override = NULL; > + > /* > * The device-specific remove callback will get invoked by device_del() > */ > diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h > index 54d9436600c7..88095fd30c80 100644 > --- a/include/linux/fsl/mc.h > +++ b/include/linux/fsl/mc.h > @@ -194,6 +194,7 @@ struct fsl_mc_device { > struct fsl_mc_device_irq **irqs; > struct fsl_mc_resource *resource; > struct device_link *consumer_link; > + const char *driver_override; We probably don't want const here. --- Best Regards, Laurentiu > }; > > #define to_fsl_mc_device(_dev) \ >
On 3/23/2020 2:30 PM, Laurentiu Tudor wrote: > > On 3/19/2020 5:40 PM, Diana Craciun wrote: >> From: Bharat Bhushan <Bharat.Bhushan@nxp.com> >> >> 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. >> >> 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: Bharat Bhushan <Bharat.Bhushan@nxp.com> >> Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com> >> Signed-off-by: Diana Craciun <diana.craciun@oss.nxp.com> >> --- >> drivers/bus/fsl-mc/fsl-mc-bus.c | 54 +++++++++++++++++++++++++++++++++ >> include/linux/fsl/mc.h | 1 + >> 2 files changed, 55 insertions(+) >> >> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c >> index c78d10ea641f..baf8259262a9 100644 >> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c >> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c >> @@ -3,6 +3,7 @@ >> * Freescale Management Complex (MC) bus driver >> * >> * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. >> + * Copyright 2019-2020 NXP >> * Author: German Rivera <German.Rivera@freescale.com> >> * >> */ >> @@ -83,6 +84,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) >> struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); >> bool found = false; >> >> + /* 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); > I think we can use sysfs_streq() here and ... I would prefer to maintain consistency with other buses and store the driver_override string without the terminating newline. > > >> + goto out; >> + } >> + >> if (!mc_drv->match_id_table) >> goto out; >> >> @@ -147,8 +154,52 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, >> } >> static DEVICE_ATTR_RO(modalias); >> >> +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 >= (PAGE_SIZE - 1)) >> + return -EINVAL; >> + >> + driver_override = kstrndup(buf, count, GFP_KERNEL); >> + if (!driver_override) >> + return -ENOMEM; >> + >> + cp = strchr(driver_override, '\n'); >> + if (cp) >> + *cp = '\0'; > drop this strchr() ... > >> + 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 snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); > and also the terminating '\n' here. > >> +} >> +static DEVICE_ATTR_RW(driver_override); >> + >> static struct attribute *fsl_mc_dev_attrs[] = { >> &dev_attr_modalias.attr, >> + &dev_attr_driver_override.attr, >> NULL, >> }; >> >> @@ -704,6 +755,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_add); >> */ >> void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) >> { >> + kfree(mc_dev->driver_override); >> + mc_dev->driver_override = NULL; >> + >> /* >> * The device-specific remove callback will get invoked by device_del() >> */ >> diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h >> index 54d9436600c7..88095fd30c80 100644 >> --- a/include/linux/fsl/mc.h >> +++ b/include/linux/fsl/mc.h >> @@ -194,6 +194,7 @@ struct fsl_mc_device { >> struct fsl_mc_device_irq **irqs; >> struct fsl_mc_resource *resource; >> struct device_link *consumer_link; >> + const char *driver_override; > We probably don't want const here. OK > > --- > Best Regards, Laurentiu > >> }; >> >> #define to_fsl_mc_device(_dev) \ >> Diana
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index c78d10ea641f..baf8259262a9 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -3,6 +3,7 @@ * Freescale Management Complex (MC) bus driver * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. + * Copyright 2019-2020 NXP * Author: German Rivera <German.Rivera@freescale.com> * */ @@ -83,6 +84,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); bool found = false; + /* 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; @@ -147,8 +154,52 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(modalias); +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 >= (PAGE_SIZE - 1)) + 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 snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); +} +static DEVICE_ATTR_RW(driver_override); + static struct attribute *fsl_mc_dev_attrs[] = { &dev_attr_modalias.attr, + &dev_attr_driver_override.attr, NULL, }; @@ -704,6 +755,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_add); */ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) { + kfree(mc_dev->driver_override); + mc_dev->driver_override = NULL; + /* * The device-specific remove callback will get invoked by device_del() */ diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h index 54d9436600c7..88095fd30c80 100644 --- a/include/linux/fsl/mc.h +++ b/include/linux/fsl/mc.h @@ -194,6 +194,7 @@ struct fsl_mc_device { struct fsl_mc_device_irq **irqs; struct fsl_mc_resource *resource; struct device_link *consumer_link; + const char *driver_override; }; #define to_fsl_mc_device(_dev) \