On 02/03/2021 21:11, Saravana Kannan wrote:
> Device link status was not getting updated correctly when
> device_bind_driver() is called on a device. This causes a warning[1].
> Fix this by updating device links that can be updated and dropping
> device links that can't be updated to a sensible state.
> 
> [1] - 
> https://lore.kernel.org/lkml/[email protected]/
> Signed-off-by: Saravana Kannan <[email protected]>
> ---
>  drivers/base/base.h |  1 +
>  drivers/base/core.c | 35 +++++++++++++++++++++++++++++++++++
>  drivers/base/dd.c   |  4 +++-
>  3 files changed, 39 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/base/base.h b/drivers/base/base.h
> index 52b3d7b75c27..1b44ed588f66 100644
> --- a/drivers/base/base.h
> +++ b/drivers/base/base.h
> @@ -185,6 +185,7 @@ extern int device_links_read_lock(void);
>  extern void device_links_read_unlock(int idx);
>  extern int device_links_read_lock_held(void);
>  extern int device_links_check_suppliers(struct device *dev);
> +extern void device_links_force_bind(struct device *dev);
>  extern void device_links_driver_bound(struct device *dev);
>  extern void device_links_driver_cleanup(struct device *dev);
>  extern void device_links_no_driver(struct device *dev);
> diff --git a/drivers/base/core.c b/drivers/base/core.c
> index f29839382f81..45c75cc96fdc 100644
> --- a/drivers/base/core.c
> +++ b/drivers/base/core.c
> @@ -1153,6 +1153,41 @@ static ssize_t waiting_for_supplier_show(struct device 
> *dev,
>  }
>  static DEVICE_ATTR_RO(waiting_for_supplier);
>  
> +/**
> + * device_links_force_bind - Prepares device to be force bound
> + * @dev: Consumer device.
> + *
> + * device_bind_driver() force binds a device to a driver without calling any
> + * driver probe functions. So the consumer really isn't going to wait for any
> + * supplier before it's bound to the driver. We still want the device link
> + * states to be sensible when this happens.
> + *
> + * In preparation for device_bind_driver(), this function goes through each
> + * supplier device links and checks if the supplier is bound. If it is, then
> + * the device link status is set to CONSUMER_PROBE. Otherwise, the device 
> link
> + * is dropped. Links without the DL_FLAG_MANAGED flag set are ignored.
> + */
> +void device_links_force_bind(struct device *dev)
> +{
> +     struct device_link *link, *ln;
> +
> +     device_links_write_lock();
> +
> +     list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
> +             if (!(link->flags & DL_FLAG_MANAGED))
> +                     continue;
> +
> +             if (link->status != DL_STATE_AVAILABLE) {
> +                     device_link_drop_managed(link);
> +                     continue;
> +             }
> +             WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE);
> +     }
> +     dev->links.status = DL_DEV_PROBING;
> +
> +     device_links_write_unlock();
> +}
> +
>  /**
>   * device_links_driver_bound - Update device links after probing its driver.
>   * @dev: Device to update the links for.
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index f18963f42e21..eb201c6d5a6a 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -460,8 +460,10 @@ int device_bind_driver(struct device *dev)
>       int ret;
>  
>       ret = driver_sysfs_add(dev);
> -     if (!ret)
> +     if (!ret) {
> +             device_links_force_bind(dev);
>               driver_bound(dev);
> +     }
>       else if (dev->bus)
>               blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
>                                            BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
> 

Thanks, this fixes the problem I had observed.

Tested-by: Jon Hunter <[email protected]>

Cheers!
Jon

-- 
nvpublic

Reply via email to