Skip to content

Commit

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

Pull driver core updates from Greg KH:
 "Here are all of the driver core and related patches for 4.19-rc1.

  Nothing huge here, just a number of small cleanups and the ability to
  now stop the deferred probing after init happens.

  All of these have been in linux-next for a while with only a merge
  issue reported"

* tag 'driver-core-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (21 commits)
  base: core: Remove WARN_ON from link dependencies check
  drivers/base: stop new probing during shutdown
  drivers: core: Remove glue dirs from sysfs earlier
  driver core: remove unnecessary function extern declare
  sysfs.h: fix non-kernel-doc comment
  PM / Domains: Stop deferring probe at the end of initcall
  iommu: Remove IOMMU_OF_DECLARE
  iommu: Stop deferring probe at end of initcalls
  pinctrl: Support stopping deferred probe after initcalls
  dt-bindings: pinctrl: add a 'pinctrl-use-default' property
  driver core: allow stopping deferred probe after init
  driver core: add a debugfs entry to show deferred devices
  sysfs: Fix internal_create_group() for named group updates
  base: fix order of OF initialization
  linux/device.h: fix kernel-doc notation warning
  Documentation: update firmware loader fallback reference
  kobject: Replace strncpy with memcpy
  drivers: base: cacheinfo: use OF property_read_u32 instead of get_property,read_number
  kernfs: Replace strncpy with memcpy
  device: Add #define dev_fmt similar to #define pr_fmt
  ...
  • Loading branch information
torvalds committed Aug 18, 2018
2 parents d5acba2 + d2fc88a commit a18d783
Show file tree
Hide file tree
Showing 26 changed files with 272 additions and 161 deletions.
9 changes: 9 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,15 @@
Defaults to the default architecture's huge page size
if not specified.

deferred_probe_timeout=
[KNL] Debugging option to set a timeout in seconds for
deferred probe to give up waiting on dependencies to
probe. Only specific dependencies (subsystems or
drivers) that have opted in will be ignored. A timeout of 0
will timeout at the end of initcalls. This option will also
dump out devices still on the deferred probe list after
retrying.

dhash_entries= [KNL]
Set number of hash buckets for dentry cache.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ Optional properties:
#pinctrl-cells: Number of pin control cells in addition to the index within the
pin controller device instance

pinctrl-use-default: Boolean. Indicates that the OS can use the boot default
pin configuration. This allows using an OS that does not have a
driver for the pin controller. This property can be set either
globally for the pin controller or in child nodes for individual
pin group control.

Pin controller devices should contain the pin configuration nodes that client
devices reference.

Expand Down
7 changes: 6 additions & 1 deletion Documentation/driver-api/firmware/fallback-mechanisms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ the loading file.

The firmware device used to help load firmware using sysfs is only created if
direct firmware loading fails and if the fallback mechanism is enabled for your
firmware request, this is set up with fw_load_from_user_helper(). It is
firmware request, this is set up with :c:func:`firmware_fallback_sysfs`. It is
important to re-iterate that no device is created if a direct filesystem lookup
succeeded.

Expand All @@ -108,6 +108,11 @@ firmware_data_read() and firmware_loading_show() are just provided for the
test_firmware driver for testing, they are not called in normal use or
expected to be used regularly by userspace.

firmware_fallback_sysfs
-----------------------
.. kernel-doc:: drivers/base/firmware_loader/fallback.c
:functions: firmware_fallback_sysfs

Firmware kobject uevent fallback mechanism
==========================================

Expand Down
2 changes: 0 additions & 2 deletions drivers/base/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ struct device_private {
#define to_device_private_bus(obj) \
container_of(obj, struct device_private, knode_bus)

extern int device_private_init(struct device *dev);

/* initialisation functions */
extern int devices_init(void);
extern int buses_init(void);
Expand Down
24 changes: 10 additions & 14 deletions drivers/base/cacheinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,52 +74,48 @@ static inline int get_cacheinfo_idx(enum cache_type type)
static void cache_size(struct cacheinfo *this_leaf, struct device_node *np)
{
const char *propname;
const __be32 *cache_size;
int ct_idx;

ct_idx = get_cacheinfo_idx(this_leaf->type);
propname = cache_type_info[ct_idx].size_prop;

cache_size = of_get_property(np, propname, NULL);
if (cache_size)
this_leaf->size = of_read_number(cache_size, 1);
if (of_property_read_u32(np, propname, &this_leaf->size))
this_leaf->size = 0;
}

/* not cache_line_size() because that's a macro in include/linux/cache.h */
static void cache_get_line_size(struct cacheinfo *this_leaf,
struct device_node *np)
{
const __be32 *line_size;
int i, lim, ct_idx;

ct_idx = get_cacheinfo_idx(this_leaf->type);
lim = ARRAY_SIZE(cache_type_info[ct_idx].line_size_props);

for (i = 0; i < lim; i++) {
int ret;
u32 line_size;
const char *propname;

propname = cache_type_info[ct_idx].line_size_props[i];
line_size = of_get_property(np, propname, NULL);
if (line_size)
ret = of_property_read_u32(np, propname, &line_size);
if (!ret) {
this_leaf->coherency_line_size = line_size;
break;
}
}

if (line_size)
this_leaf->coherency_line_size = of_read_number(line_size, 1);
}

static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np)
{
const char *propname;
const __be32 *nr_sets;
int ct_idx;

ct_idx = get_cacheinfo_idx(this_leaf->type);
propname = cache_type_info[ct_idx].nr_sets_prop;

nr_sets = of_get_property(np, propname, NULL);
if (nr_sets)
this_leaf->number_of_sets = of_read_number(nr_sets, 1);
if (of_property_read_u32(np, propname, &this_leaf->number_of_sets))
this_leaf->number_of_sets = 0;
}

static void cache_associativity(struct cacheinfo *this_leaf)
Expand Down
23 changes: 14 additions & 9 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,15 @@ static int device_is_dependent(struct device *dev, void *target)
struct device_link *link;
int ret;

if (WARN_ON(dev == target))
if (dev == target)
return 1;

ret = device_for_each_child(dev, target, device_is_dependent);
if (ret)
return ret;

list_for_each_entry(link, &dev->links.consumers, s_node) {
if (WARN_ON(link->consumer == target))
if (link->consumer == target)
return 1;

ret = device_is_dependent(link->consumer, target);
Expand Down Expand Up @@ -1647,6 +1647,8 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
return;

mutex_lock(&gdp_mutex);
if (!kobject_has_children(glue_dir))
kobject_del(glue_dir);
kobject_put(glue_dir);
mutex_unlock(&gdp_mutex);
}
Expand Down Expand Up @@ -1786,7 +1788,7 @@ static void device_remove_sys_dev_entry(struct device *dev)
}
}

int device_private_init(struct device *dev)
static int device_private_init(struct device *dev)
{
dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
if (!dev->p)
Expand Down Expand Up @@ -2859,6 +2861,9 @@ void device_shutdown(void)
{
struct device *dev, *parent;

wait_for_device_probe();
device_block_probing();

spin_lock(&devices_kset->list_lock);
/*
* Walk the devices list backward, shutting down each in turn.
Expand Down Expand Up @@ -3052,12 +3057,12 @@ void func(const struct device *dev, const char *fmt, ...) \
} \
EXPORT_SYMBOL(func);

define_dev_printk_level(dev_emerg, KERN_EMERG);
define_dev_printk_level(dev_alert, KERN_ALERT);
define_dev_printk_level(dev_crit, KERN_CRIT);
define_dev_printk_level(dev_err, KERN_ERR);
define_dev_printk_level(dev_warn, KERN_WARNING);
define_dev_printk_level(dev_notice, KERN_NOTICE);
define_dev_printk_level(_dev_emerg, KERN_EMERG);
define_dev_printk_level(_dev_alert, KERN_ALERT);
define_dev_printk_level(_dev_crit, KERN_CRIT);
define_dev_printk_level(_dev_err, KERN_ERR);
define_dev_printk_level(_dev_warn, KERN_WARNING);
define_dev_printk_level(_dev_notice, KERN_NOTICE);
define_dev_printk_level(_dev_info, KERN_INFO);

#endif
Expand Down
134 changes: 108 additions & 26 deletions drivers/base/dd.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* Copyright (c) 2007-2009 Novell Inc.
*/

#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
Expand Down Expand Up @@ -53,6 +54,7 @@ static DEFINE_MUTEX(deferred_probe_mutex);
static LIST_HEAD(deferred_probe_pending_list);
static LIST_HEAD(deferred_probe_active_list);
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
static struct dentry *deferred_devices;
static bool initcalls_done;

/*
Expand All @@ -62,26 +64,6 @@ static bool initcalls_done;
*/
static bool defer_all_probes;

/*
* For initcall_debug, show the deferred probes executed in late_initcall
* processing.
*/
static void deferred_probe_debug(struct device *dev)
{
ktime_t calltime, delta, rettime;
unsigned long long duration;

printk(KERN_DEBUG "deferred probe %s @ %i\n", dev_name(dev),
task_pid_nr(current));
calltime = ktime_get();
bus_probe_device(dev);
rettime = ktime_get();
delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
printk(KERN_DEBUG "deferred probe %s returned after %lld usecs\n",
dev_name(dev), duration);
}

/*
* deferred_probe_work_func() - Retry probing devices in the active list.
*/
Expand Down Expand Up @@ -125,11 +107,7 @@ static void deferred_probe_work_func(struct work_struct *work)
device_pm_move_to_tail(dev);

dev_dbg(dev, "Retrying from deferred list\n");
if (initcall_debug && !initcalls_done)
deferred_probe_debug(dev);
else
bus_probe_device(dev);

bus_probe_device(dev);
mutex_lock(&deferred_probe_mutex);

put_device(dev);
Expand Down Expand Up @@ -224,6 +202,69 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
}

/*
* deferred_devs_show() - Show the devices in the deferred probe pending list.
*/
static int deferred_devs_show(struct seq_file *s, void *data)
{
struct device_private *curr;

mutex_lock(&deferred_probe_mutex);

list_for_each_entry(curr, &deferred_probe_pending_list, deferred_probe)
seq_printf(s, "%s\n", dev_name(curr->device));

mutex_unlock(&deferred_probe_mutex);

return 0;
}
DEFINE_SHOW_ATTRIBUTE(deferred_devs);

static int deferred_probe_timeout = -1;
static int __init deferred_probe_timeout_setup(char *str)
{
deferred_probe_timeout = simple_strtol(str, NULL, 10);
return 1;
}
__setup("deferred_probe_timeout=", deferred_probe_timeout_setup);

/**
* driver_deferred_probe_check_state() - Check deferred probe state
* @dev: device to check
*
* Returns -ENODEV if init is done and all built-in drivers have had a chance
* to probe (i.e. initcalls are done), -ETIMEDOUT if deferred probe debug
* timeout has expired, or -EPROBE_DEFER if none of those conditions are met.
*
* Drivers or subsystems can opt-in to calling this function instead of directly
* returning -EPROBE_DEFER.
*/
int driver_deferred_probe_check_state(struct device *dev)
{
if (initcalls_done) {
if (!deferred_probe_timeout) {
dev_WARN(dev, "deferred probe timeout, ignoring dependency");
return -ETIMEDOUT;
}
dev_warn(dev, "ignoring dependency for device, assuming no driver");
return -ENODEV;
}
return -EPROBE_DEFER;
}

static void deferred_probe_timeout_work_func(struct work_struct *work)
{
struct device_private *private, *p;

deferred_probe_timeout = 0;
driver_deferred_probe_trigger();
flush_work(&deferred_probe_work);

list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe)
dev_info(private->device, "deferred probe pending");
}
static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func);

/**
* deferred_probe_initcall() - Enable probing of deferred devices
*
Expand All @@ -233,15 +274,36 @@ void device_unblock_probing(void)
*/
static int deferred_probe_initcall(void)
{
deferred_devices = debugfs_create_file("devices_deferred", 0444, NULL,
NULL, &deferred_devs_fops);

driver_deferred_probe_enable = true;
driver_deferred_probe_trigger();
/* Sort as many dependencies as possible before exiting initcalls */
flush_work(&deferred_probe_work);
initcalls_done = true;

/*
* Trigger deferred probe again, this time we won't defer anything
* that is optional
*/
driver_deferred_probe_trigger();
flush_work(&deferred_probe_work);

if (deferred_probe_timeout > 0) {
schedule_delayed_work(&deferred_probe_timeout_work,
deferred_probe_timeout * HZ);
}
return 0;
}
late_initcall(deferred_probe_initcall);

static void __exit deferred_probe_exit(void)
{
debugfs_remove_recursive(deferred_devices);
}
__exitcall(deferred_probe_exit);

/**
* device_is_bound() - Check if device is bound to a driver
* @dev: device to check
Expand Down Expand Up @@ -519,6 +581,23 @@ static int really_probe(struct device *dev, struct device_driver *drv)
return ret;
}

/*
* For initcall_debug, show the driver probe time.
*/
static int really_probe_debug(struct device *dev, struct device_driver *drv)
{
ktime_t calltime, delta, rettime;
int ret;

calltime = ktime_get();
ret = really_probe(dev, drv);
rettime = ktime_get();
delta = ktime_sub(rettime, calltime);
printk(KERN_DEBUG "probe of %s returned %d after %lld usecs\n",
dev_name(dev), ret, (s64) ktime_to_us(delta));
return ret;
}

/**
* driver_probe_done
* Determine if the probe sequence is finished or not.
Expand Down Expand Up @@ -577,7 +656,10 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
pm_runtime_get_sync(dev->parent);

pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
if (initcall_debug)
ret = really_probe_debug(dev, drv);
else
ret = really_probe(dev, drv);
pm_request_idle(dev);

if (dev->parent)
Expand Down
2 changes: 1 addition & 1 deletion drivers/base/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ void __init driver_init(void)
/* These are also core pieces, but must come after the
* core core pieces.
*/
of_core_init();
platform_bus_init();
cpu_dev_init();
memory_dev_init();
container_dev_init();
of_core_init();
}
Loading

0 comments on commit a18d783

Please sign in to comment.