On Thu, 13 Jun 2019 13:08:15 +0200
Cornelia Huck <[email protected]> wrote:

> Sometimes, we want to control which of the matching drivers
> binds to a subchannel device (e.g. for subchannels we want to
> handle via vfio-ccw).
> 
> For pci devices, a mechanism to do so has been introduced in
> 782a985d7af2 ("PCI: Introduce new device binding path using
> pci_dev.driver_override"). It makes sense to introduce the
> driver_override attribute for subchannel devices as well, so
> that we can easily extend the 'driverctl' tool (which makes
> use of the driver_override attribute for pci).
> 
> Note that unlike pci we still require a driver override to
> match the subchannel type; matching more than one subchannel
> type is probably not useful anyway.
> 
> Signed-off-by: Cornelia Huck <[email protected]>
> ---
> 
> Lightly tested; did not yet attempt to adapt driverctl to actually
> make use of it.

Friendly ping.

In the meanwhile, I figured out that you do not need to adapt driverctl
at all, but just need to pass it '-b css' to work on the css bus; this
seems to work just fine with this patch applied.

> 
> For some background, refer to the thread around
> https://lore.kernel.org/kvm/[email protected]/
> 
> ---
>  Documentation/ABI/testing/sysfs-bus-css | 23 +++++++++++
>  drivers/s390/cio/cio.h                  |  1 +
>  drivers/s390/cio/css.c                  | 53 +++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-css 
> b/Documentation/ABI/testing/sysfs-bus-css
> index 2979c40c10e9..966f8504bd7b 100644
> --- a/Documentation/ABI/testing/sysfs-bus-css
> +++ b/Documentation/ABI/testing/sysfs-bus-css
> @@ -33,3 +33,26 @@ Description:       Contains the PIM/PAM/POM values, as 
> reported by the
>               in sync with the values current in the channel subsystem).
>               Note: This is an I/O-subchannel specific attribute.
>  Users:               s390-tools, HAL
> +
> +What:                /sys/bus/css/devices/.../driver_override
> +Date:                June 2019
> +Contact:     Cornelia Huck <[email protected]>
> +             [email protected]
> +Description: This file allows the driver for a device to be specified. When
> +             specified, only a driver with a name matching the value written
> +             to driver_override will have an opportunity to bind to the
> +             device. The override is specified by writing a string to the
> +             driver_override file (echo vfio-ccw > driver_override) and
> +             may be cleared with an empty string (echo > driver_override).
> +             This returns the device to standard matching rules binding.
> +             Writing to driver_override does not automatically unbind the
> +             device from its current driver or make any attempt to
> +             automatically load the specified driver.  If no driver with a
> +             matching name is currently loaded in the kernel, the device
> +             will not bind to any driver.  This also allows devices to
> +             opt-out of driver binding using a driver_override name such as
> +             "none".  Only a single driver may be specified in the override,
> +             there is no support for parsing delimiters.
> +             Note that unlike the mechanism of the same name for pci, this
> +             file does not allow to override basic matching rules. I.e.,
> +             the driver must still match the subchannel type of the device.
> diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
> index 06a91743335a..8c4af88f1ac3 100644
> --- a/drivers/s390/cio/cio.h
> +++ b/drivers/s390/cio/cio.h
> @@ -113,6 +113,7 @@ struct subchannel {
>       enum sch_todo todo;
>       struct work_struct todo_work;
>       struct schib_config config;
> +     char *driver_override; /* Driver name to force a match */
>  } __attribute__ ((aligned(8)));
>  
>  DECLARE_PER_CPU_ALIGNED(struct irb, cio_irb);
> diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
> index aea502922646..f3436a17e3b5 100644
> --- a/drivers/s390/cio/css.c
> +++ b/drivers/s390/cio/css.c
> @@ -165,6 +165,7 @@ static void css_subchannel_release(struct device *dev)
>  
>       sch->config.intparm = 0;
>       cio_commit_config(sch);
> +     kfree(sch->driver_override);
>       kfree(sch->lock);
>       kfree(sch);
>  }
> @@ -315,9 +316,57 @@ 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 subchannel *sch = to_subchannel(dev);
> +     char *driver_override, *old, *cp;
> +
> +     /* We need to keep extra room for a newline */
> +     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';
> +
> +     device_lock(dev);
> +     old = sch->driver_override;
> +     if (strlen(driver_override)) {
> +             sch->driver_override = driver_override;
> +     } else {
> +             kfree(driver_override);
> +             sch->driver_override = NULL;
> +     }
> +     device_unlock(dev);
> +
> +     kfree(old);
> +
> +     return count;
> +}
> +
> +static ssize_t driver_override_show(struct device *dev,
> +                                 struct device_attribute *attr, char *buf)
> +{
> +     struct subchannel *sch = to_subchannel(dev);
> +     ssize_t len;
> +
> +     device_lock(dev);
> +     len = snprintf(buf, PAGE_SIZE, "%s\n", sch->driver_override);
> +     device_unlock(dev);
> +     return len;
> +}
> +static DEVICE_ATTR_RW(driver_override);
> +
>  static struct attribute *subch_attrs[] = {
>       &dev_attr_type.attr,
>       &dev_attr_modalias.attr,
> +     &dev_attr_driver_override.attr,
>       NULL,
>  };
>  
> @@ -1222,6 +1271,10 @@ static int css_bus_match(struct device *dev, struct 
> device_driver *drv)
>       struct css_driver *driver = to_cssdriver(drv);
>       struct css_device_id *id;
>  
> +     /* When driver_override is set, only bind to the matching driver */
> +     if (sch->driver_override && strcmp(sch->driver_override, drv->name))
> +             return 0;
> +
>       for (id = driver->subchannel_type; id->match_flags; id++) {
>               if (sch->st == id->type)
>                       return 1;

Reply via email to