Skip to content

Commit

Permalink
Merge tag 'driver-core-5.8-rc1' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here is the set of driver core patches for 5.8-rc1.

  Not all that huge this release, just a number of small fixes and
  updates:

   - software node fixes

   - kobject now sends KOBJ_REMOVE when it is removed from sysfs, not
     when it is removed from memory (which could come much later)

   - device link additions and fixes based on testing on more devices

   - firmware core cleanups

   - other minor changes, full details in the shortlog

  All have been in linux-next for a while with no reported issues"

* tag 'driver-core-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (23 commits)
  driver core: Update device link status correctly for SYNC_STATE_ONLY links
  firmware_loader: change enum fw_opt to u32
  software node: implement software_node_unregister()
  kobject: send KOBJ_REMOVE uevent when the object is removed from sysfs
  driver core: Remove unnecessary is_fwnode_dev variable in device_add()
  drivers property: When no children in primary, try secondary
  driver core: platform: Fix spelling errors in platform.c
  driver core: Remove check in driver_deferred_probe_force_trigger()
  of: platform: Batch fwnode parsing when adding all top level devices
  driver core: fw_devlink: Add support for batching fwnode parsing
  driver core: Look for waiting consumers only for a fwnode's primary device
  driver core: Move code to the right part of the file
  Revert "Revert "driver core: Set fw_devlink to "permissive" behavior by default""
  drivers: base: Fix NULL pointer exception in __platform_driver_probe() if a driver developer is foolish
  firmware_loader: move fw_fallback_config to a private kernel symbol namespace
  driver core: Add missing '\n' in log messages
  driver/base/soc: Use kobj_to_dev() API
  Add documentation on meaning of -EPROBE_DEFER
  driver core: platform: remove redundant assignment to variable ret
  debugfs: Use the correct style for SPDX License Identifier
  ...
  • Loading branch information
torvalds committed Jun 7, 2020
2 parents 80ef846 + 8c3e315 commit f558b83
Show file tree
Hide file tree
Showing 23 changed files with 303 additions and 144 deletions.
32 changes: 27 additions & 5 deletions Documentation/driver-api/driver-model/driver.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Device Drivers

See the kerneldoc for the struct device_driver.


Allocation
~~~~~~~~~~

Expand Down Expand Up @@ -167,9 +166,26 @@ the driver to that device.

A driver's probe() may return a negative errno value to indicate that
the driver did not bind to this device, in which case it should have
released all resources it allocated::
released all resources it allocated.

Optionally, probe() may return -EPROBE_DEFER if the driver depends on
resources that are not yet available (e.g., supplied by a driver that
hasn't initialized yet). The driver core will put the device onto the
deferred probe list and will try to call it again later. If a driver
must defer, it should return -EPROBE_DEFER as early as possible to
reduce the amount of time spent on setup work that will need to be
unwound and reexecuted at a later time.

.. warning::
-EPROBE_DEFER must not be returned if probe() has already created
child devices, even if those child devices are removed again
in a cleanup path. If -EPROBE_DEFER is returned after a child
device has been registered, it may result in an infinite loop of
.probe() calls to the same driver.

::

void (*sync_state)(struct device *dev);
void (*sync_state) (struct device *dev);

sync_state is called only once for a device. It's called when all the consumer
devices of the device have successfully probed. The list of consumers of the
Expand Down Expand Up @@ -212,6 +228,8 @@ over management of devices from the bootloader, the usage of sync_state() is
not restricted to that. Use it whenever it makes sense to take an action after
all the consumers of a device have probed::

::

int (*remove) (struct device *dev);

remove is called to unbind a driver from a device. This may be
Expand All @@ -224,11 +242,15 @@ not. It should free any resources allocated specifically for the
device; i.e. anything in the device's driver_data field.

If the device is still present, it should quiesce the device and place
it into a supported low-power state::
it into a supported low-power state.

::

int (*suspend) (struct device *dev, pm_message_t state);

suspend is called to put the device in a low power state::
suspend is called to put the device in a low power state.

::

int (*resume) (struct device *dev);

Expand Down
1 change: 1 addition & 0 deletions drivers/base/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
extern int devres_release_all(struct device *dev);
extern void device_block_probing(void);
extern void device_unblock_probing(void);
extern void driver_deferred_probe_force_trigger(void);

/* /sys/devices directory */
extern struct kset *devices_kset;
Expand Down
235 changes: 179 additions & 56 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ static LIST_HEAD(wait_for_suppliers);
static DEFINE_MUTEX(wfs_lock);
static LIST_HEAD(deferred_sync);
static unsigned int defer_sync_state_count = 1;
static unsigned int defer_fw_devlink_count;
static DEFINE_MUTEX(defer_fw_devlink_lock);
static bool fw_devlink_is_permissive(void);

#ifdef CONFIG_SRCU
static DEFINE_MUTEX(device_links_lock);
Expand Down Expand Up @@ -529,7 +532,7 @@ static void device_link_add_missing_supplier_links(void)
int ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
if (!ret)
list_del_init(&dev->links.needs_suppliers);
else if (ret != -ENODEV)
else if (ret != -ENODEV || fw_devlink_is_permissive())
dev->links.need_for_probe = false;
}
mutex_unlock(&wfs_lock);
Expand Down Expand Up @@ -643,9 +646,17 @@ static void device_links_missing_supplier(struct device *dev)
{
struct device_link *link;

list_for_each_entry(link, &dev->links.suppliers, c_node)
if (link->status == DL_STATE_CONSUMER_PROBE)
list_for_each_entry(link, &dev->links.suppliers, c_node) {
if (link->status != DL_STATE_CONSUMER_PROBE)
continue;

if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
} else {
WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
WRITE_ONCE(link->status, DL_STATE_DORMANT);
}
}
}

/**
Expand Down Expand Up @@ -684,11 +695,11 @@ int device_links_check_suppliers(struct device *dev)
device_links_write_lock();

list_for_each_entry(link, &dev->links.suppliers, c_node) {
if (!(link->flags & DL_FLAG_MANAGED) ||
link->flags & DL_FLAG_SYNC_STATE_ONLY)
if (!(link->flags & DL_FLAG_MANAGED))
continue;

if (link->status != DL_STATE_AVAILABLE) {
if (link->status != DL_STATE_AVAILABLE &&
!(link->flags & DL_FLAG_SYNC_STATE_ONLY)) {
device_links_missing_supplier(dev);
ret = -EPROBE_DEFER;
break;
Expand Down Expand Up @@ -949,11 +960,21 @@ static void __device_links_no_driver(struct device *dev)
if (!(link->flags & DL_FLAG_MANAGED))
continue;

if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
device_link_drop_managed(link);
else if (link->status == DL_STATE_CONSUMER_PROBE ||
link->status == DL_STATE_ACTIVE)
continue;
}

if (link->status != DL_STATE_CONSUMER_PROBE &&
link->status != DL_STATE_ACTIVE)
continue;

if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
} else {
WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
WRITE_ONCE(link->status, DL_STATE_DORMANT);
}
}

dev->links.status = DL_DEV_NO_DRIVER;
Expand Down Expand Up @@ -1162,6 +1183,150 @@ static void device_links_purge(struct device *dev)
device_links_write_unlock();
}

static u32 fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY;
static int __init fw_devlink_setup(char *arg)
{
if (!arg)
return -EINVAL;

if (strcmp(arg, "off") == 0) {
fw_devlink_flags = 0;
} else if (strcmp(arg, "permissive") == 0) {
fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY;
} else if (strcmp(arg, "on") == 0) {
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER;
} else if (strcmp(arg, "rpm") == 0) {
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER |
DL_FLAG_PM_RUNTIME;
}
return 0;
}
early_param("fw_devlink", fw_devlink_setup);

u32 fw_devlink_get_flags(void)
{
return fw_devlink_flags;
}

static bool fw_devlink_is_permissive(void)
{
return fw_devlink_flags == DL_FLAG_SYNC_STATE_ONLY;
}

static void fw_devlink_link_device(struct device *dev)
{
int fw_ret;

if (!fw_devlink_flags)
return;

mutex_lock(&defer_fw_devlink_lock);
if (!defer_fw_devlink_count)
device_link_add_missing_supplier_links();

/*
* The device's fwnode not having add_links() doesn't affect if other
* consumers can find this device as a supplier. So, this check is
* intentionally placed after device_link_add_missing_supplier_links().
*/
if (!fwnode_has_op(dev->fwnode, add_links))
goto out;

/*
* If fw_devlink is being deferred, assume all devices have mandatory
* suppliers they need to link to later. Then, when the fw_devlink is
* resumed, all these devices will get a chance to try and link to any
* suppliers they have.
*/
if (!defer_fw_devlink_count) {
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
if (fw_ret == -ENODEV && fw_devlink_is_permissive())
fw_ret = -EAGAIN;
} else {
fw_ret = -ENODEV;
}

if (fw_ret == -ENODEV)
device_link_wait_for_mandatory_supplier(dev);
else if (fw_ret)
device_link_wait_for_optional_supplier(dev);

out:
mutex_unlock(&defer_fw_devlink_lock);
}

/**
* fw_devlink_pause - Pause parsing of fwnode to create device links
*
* Calling this function defers any fwnode parsing to create device links until
* fw_devlink_resume() is called. Both these functions are ref counted and the
* caller needs to match the calls.
*
* While fw_devlink is paused:
* - Any device that is added won't have its fwnode parsed to create device
* links.
* - The probe of the device will also be deferred during this period.
* - Any devices that were already added, but waiting for suppliers won't be
* able to link to newly added devices.
*
* Once fw_devlink_resume():
* - All the fwnodes that was not parsed will be parsed.
* - All the devices that were deferred probing will be reattempted if they
* aren't waiting for any more suppliers.
*
* This pair of functions, is mainly meant to optimize the parsing of fwnodes
* when a lot of devices that need to link to each other are added in a short
* interval of time. For example, adding all the top level devices in a system.
*
* For example, if N devices are added and:
* - All the consumers are added before their suppliers
* - All the suppliers of the N devices are part of the N devices
*
* Then:
*
* - With the use of fw_devlink_pause() and fw_devlink_resume(), each device
* will only need one parsing of its fwnode because it is guaranteed to find
* all the supplier devices already registered and ready to link to. It won't
* have to do another pass later to find one or more suppliers it couldn't
* find in the first parse of the fwnode. So, we'll only need O(N) fwnode
* parses.
*
* - Without the use of fw_devlink_pause() and fw_devlink_resume(), we would
* end up doing O(N^2) parses of fwnodes because every device that's added is
* guaranteed to trigger a parse of the fwnode of every device added before
* it. This O(N^2) parse is made worse by the fact that when a fwnode of a
* device is parsed, all it descendant devices might need to have their
* fwnodes parsed too (even if the devices themselves aren't added).
*/
void fw_devlink_pause(void)
{
mutex_lock(&defer_fw_devlink_lock);
defer_fw_devlink_count++;
mutex_unlock(&defer_fw_devlink_lock);
}

/** fw_devlink_resume - Resume parsing of fwnode to create device links
*
* This function is used in conjunction with fw_devlink_pause() and is ref
* counted. See documentation for fw_devlink_pause() for more details.
*/
void fw_devlink_resume(void)
{
mutex_lock(&defer_fw_devlink_lock);
if (!defer_fw_devlink_count) {
WARN(true, "Unmatched fw_devlink pause/resume!");
goto out;
}

defer_fw_devlink_count--;
if (defer_fw_devlink_count)
goto out;

device_link_add_missing_supplier_links();
driver_deferred_probe_force_trigger();
out:
mutex_unlock(&defer_fw_devlink_lock);
}
/* Device links support end. */

int (*platform_notify)(struct device *dev) = NULL;
Expand Down Expand Up @@ -2364,36 +2529,6 @@ static int device_private_init(struct device *dev)
return 0;
}

static u32 fw_devlink_flags;
static int __init fw_devlink_setup(char *arg)
{
if (!arg)
return -EINVAL;

if (strcmp(arg, "off") == 0) {
fw_devlink_flags = 0;
} else if (strcmp(arg, "permissive") == 0) {
fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY;
} else if (strcmp(arg, "on") == 0) {
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER;
} else if (strcmp(arg, "rpm") == 0) {
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER |
DL_FLAG_PM_RUNTIME;
}
return 0;
}
early_param("fw_devlink", fw_devlink_setup);

u32 fw_devlink_get_flags(void)
{
return fw_devlink_flags;
}

static bool fw_devlink_is_permissive(void)
{
return fw_devlink_flags == DL_FLAG_SYNC_STATE_ONLY;
}

/**
* device_add - add device to device hierarchy.
* @dev: device.
Expand Down Expand Up @@ -2426,9 +2561,8 @@ int device_add(struct device *dev)
struct device *parent;
struct kobject *kobj;
struct class_interface *class_intf;
int error = -EINVAL, fw_ret;
int error = -EINVAL;
struct kobject *glue_dir = NULL;
bool is_fwnode_dev = false;

dev = get_device(dev);
if (!dev)
Expand Down Expand Up @@ -2526,11 +2660,6 @@ int device_add(struct device *dev)

kobject_uevent(&dev->kobj, KOBJ_ADD);

if (dev->fwnode && !dev->fwnode->dev) {
dev->fwnode->dev = dev;
is_fwnode_dev = true;
}

/*
* Check if any of the other devices (consumers) have been waiting for
* this device (supplier) to be added so that they can create a device
Expand All @@ -2539,19 +2668,13 @@ int device_add(struct device *dev)
* This needs to happen after device_pm_add() because device_link_add()
* requires the supplier be registered before it's called.
*
* But this also needs to happe before bus_probe_device() to make sure
* But this also needs to happen before bus_probe_device() to make sure
* waiting consumers can link to it before the driver is bound to the
* device and the driver sync_state callback is called for this device.
*/
device_link_add_missing_supplier_links();

if (fw_devlink_flags && is_fwnode_dev &&
fwnode_has_op(dev->fwnode, add_links)) {
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
if (fw_ret == -ENODEV && !fw_devlink_is_permissive())
device_link_wait_for_mandatory_supplier(dev);
else if (fw_ret)
device_link_wait_for_optional_supplier(dev);
if (dev->fwnode && !dev->fwnode->dev) {
dev->fwnode->dev = dev;
fw_devlink_link_device(dev);
}

bus_probe_device(dev);
Expand Down
Loading

0 comments on commit f558b83

Please sign in to comment.