Commit a18d783f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-4.19-rc1' of...

Merge tag 'driver-core-4.19-rc1' of git://git.kernel.org/pub/scm/linux/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
  ...
parents d5acba26 d2fc88a6
...@@ -812,6 +812,15 @@ ...@@ -812,6 +812,15 @@
Defaults to the default architecture's huge page size Defaults to the default architecture's huge page size
if not specified. 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] dhash_entries= [KNL]
Set number of hash buckets for dentry cache. Set number of hash buckets for dentry cache.
......
...@@ -103,6 +103,12 @@ Optional properties: ...@@ -103,6 +103,12 @@ Optional properties:
#pinctrl-cells: Number of pin control cells in addition to the index within the #pinctrl-cells: Number of pin control cells in addition to the index within the
pin controller device instance 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 Pin controller devices should contain the pin configuration nodes that client
devices reference. devices reference.
......
...@@ -92,7 +92,7 @@ the loading file. ...@@ -92,7 +92,7 @@ the loading file.
The firmware device used to help load firmware using sysfs is only created if 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 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 important to re-iterate that no device is created if a direct filesystem lookup
succeeded. succeeded.
...@@ -108,6 +108,11 @@ firmware_data_read() and firmware_loading_show() are just provided for the ...@@ -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 test_firmware driver for testing, they are not called in normal use or
expected to be used regularly by userspace. 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 Firmware kobject uevent fallback mechanism
========================================== ==========================================
......
...@@ -84,8 +84,6 @@ struct device_private { ...@@ -84,8 +84,6 @@ struct device_private {
#define to_device_private_bus(obj) \ #define to_device_private_bus(obj) \
container_of(obj, struct device_private, knode_bus) container_of(obj, struct device_private, knode_bus)
extern int device_private_init(struct device *dev);
/* initialisation functions */ /* initialisation functions */
extern int devices_init(void); extern int devices_init(void);
extern int buses_init(void); extern int buses_init(void);
......
...@@ -74,52 +74,48 @@ static inline int get_cacheinfo_idx(enum cache_type type) ...@@ -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) static void cache_size(struct cacheinfo *this_leaf, struct device_node *np)
{ {
const char *propname; const char *propname;
const __be32 *cache_size;
int ct_idx; int ct_idx;
ct_idx = get_cacheinfo_idx(this_leaf->type); ct_idx = get_cacheinfo_idx(this_leaf->type);
propname = cache_type_info[ct_idx].size_prop; propname = cache_type_info[ct_idx].size_prop;
cache_size = of_get_property(np, propname, NULL); if (of_property_read_u32(np, propname, &this_leaf->size))
if (cache_size) this_leaf->size = 0;
this_leaf->size = of_read_number(cache_size, 1);
} }
/* not cache_line_size() because that's a macro in include/linux/cache.h */ /* not cache_line_size() because that's a macro in include/linux/cache.h */
static void cache_get_line_size(struct cacheinfo *this_leaf, static void cache_get_line_size(struct cacheinfo *this_leaf,
struct device_node *np) struct device_node *np)
{ {
const __be32 *line_size;
int i, lim, ct_idx; int i, lim, ct_idx;
ct_idx = get_cacheinfo_idx(this_leaf->type); ct_idx = get_cacheinfo_idx(this_leaf->type);
lim = ARRAY_SIZE(cache_type_info[ct_idx].line_size_props); lim = ARRAY_SIZE(cache_type_info[ct_idx].line_size_props);
for (i = 0; i < lim; i++) { for (i = 0; i < lim; i++) {
int ret;
u32 line_size;
const char *propname; const char *propname;
propname = cache_type_info[ct_idx].line_size_props[i]; propname = cache_type_info[ct_idx].line_size_props[i];
line_size = of_get_property(np, propname, NULL); ret = of_property_read_u32(np, propname, &line_size);
if (line_size) if (!ret) {
this_leaf->coherency_line_size = line_size;
break; 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) static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np)
{ {
const char *propname; const char *propname;
const __be32 *nr_sets;
int ct_idx; int ct_idx;
ct_idx = get_cacheinfo_idx(this_leaf->type); ct_idx = get_cacheinfo_idx(this_leaf->type);
propname = cache_type_info[ct_idx].nr_sets_prop; propname = cache_type_info[ct_idx].nr_sets_prop;
nr_sets = of_get_property(np, propname, NULL); if (of_property_read_u32(np, propname, &this_leaf->number_of_sets))
if (nr_sets) this_leaf->number_of_sets = 0;
this_leaf->number_of_sets = of_read_number(nr_sets, 1);
} }
static void cache_associativity(struct cacheinfo *this_leaf) static void cache_associativity(struct cacheinfo *this_leaf)
......
...@@ -105,7 +105,7 @@ static int device_is_dependent(struct device *dev, void *target) ...@@ -105,7 +105,7 @@ static int device_is_dependent(struct device *dev, void *target)
struct device_link *link; struct device_link *link;
int ret; int ret;
if (WARN_ON(dev == target)) if (dev == target)
return 1; return 1;
ret = device_for_each_child(dev, target, device_is_dependent); ret = device_for_each_child(dev, target, device_is_dependent);
...@@ -113,7 +113,7 @@ static int device_is_dependent(struct device *dev, void *target) ...@@ -113,7 +113,7 @@ static int device_is_dependent(struct device *dev, void *target)
return ret; return ret;
list_for_each_entry(link, &dev->links.consumers, s_node) { list_for_each_entry(link, &dev->links.consumers, s_node) {
if (WARN_ON(link->consumer == target)) if (link->consumer == target)
return 1; return 1;
ret = device_is_dependent(link->consumer, target); ret = device_is_dependent(link->consumer, target);
...@@ -1647,6 +1647,8 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) ...@@ -1647,6 +1647,8 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
return; return;
mutex_lock(&gdp_mutex); mutex_lock(&gdp_mutex);
if (!kobject_has_children(glue_dir))
kobject_del(glue_dir);
kobject_put(glue_dir); kobject_put(glue_dir);
mutex_unlock(&gdp_mutex); mutex_unlock(&gdp_mutex);
} }
...@@ -1786,7 +1788,7 @@ static void device_remove_sys_dev_entry(struct device *dev) ...@@ -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); dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
if (!dev->p) if (!dev->p)
...@@ -2859,6 +2861,9 @@ void device_shutdown(void) ...@@ -2859,6 +2861,9 @@ void device_shutdown(void)
{ {
struct device *dev, *parent; struct device *dev, *parent;
wait_for_device_probe();
device_block_probing();
spin_lock(&devices_kset->list_lock); spin_lock(&devices_kset->list_lock);
/* /*
* Walk the devices list backward, shutting down each in turn. * Walk the devices list backward, shutting down each in turn.
...@@ -3052,12 +3057,12 @@ void func(const struct device *dev, const char *fmt, ...) \ ...@@ -3052,12 +3057,12 @@ void func(const struct device *dev, const char *fmt, ...) \
} \ } \
EXPORT_SYMBOL(func); EXPORT_SYMBOL(func);
define_dev_printk_level(dev_emerg, KERN_EMERG); define_dev_printk_level(_dev_emerg, KERN_EMERG);
define_dev_printk_level(dev_alert, KERN_ALERT); define_dev_printk_level(_dev_alert, KERN_ALERT);
define_dev_printk_level(dev_crit, KERN_CRIT); define_dev_printk_level(_dev_crit, KERN_CRIT);
define_dev_printk_level(dev_err, KERN_ERR); define_dev_printk_level(_dev_err, KERN_ERR);
define_dev_printk_level(dev_warn, KERN_WARNING); define_dev_printk_level(_dev_warn, KERN_WARNING);
define_dev_printk_level(dev_notice, KERN_NOTICE); define_dev_printk_level(_dev_notice, KERN_NOTICE);
define_dev_printk_level(_dev_info, KERN_INFO); define_dev_printk_level(_dev_info, KERN_INFO);
#endif #endif
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* Copyright (c) 2007-2009 Novell Inc. * Copyright (c) 2007-2009 Novell Inc.
*/ */
#include <linux/debugfs.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -53,6 +54,7 @@ static DEFINE_MUTEX(deferred_probe_mutex); ...@@ -53,6 +54,7 @@ static DEFINE_MUTEX(deferred_probe_mutex);
static LIST_HEAD(deferred_probe_pending_list); static LIST_HEAD(deferred_probe_pending_list);
static LIST_HEAD(deferred_probe_active_list); static LIST_HEAD(deferred_probe_active_list);
static atomic_t deferred_trigger_count = ATOMIC_INIT(0); static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
static struct dentry *deferred_devices;
static bool initcalls_done; static bool initcalls_done;
/* /*
...@@ -62,26 +64,6 @@ static bool initcalls_done; ...@@ -62,26 +64,6 @@ static bool initcalls_done;
*/ */
static bool defer_all_probes; 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. * deferred_probe_work_func() - Retry probing devices in the active list.
*/ */
...@@ -125,11 +107,7 @@ static void deferred_probe_work_func(struct work_struct *work) ...@@ -125,11 +107,7 @@ static void deferred_probe_work_func(struct work_struct *work)
device_pm_move_to_tail(dev); device_pm_move_to_tail(dev);
dev_dbg(dev, "Retrying from deferred list\n"); 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); mutex_lock(&deferred_probe_mutex);
put_device(dev); put_device(dev);
...@@ -224,6 +202,69 @@ void device_unblock_probing(void) ...@@ -224,6 +202,69 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger(); 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 * deferred_probe_initcall() - Enable probing of deferred devices
* *
...@@ -233,15 +274,36 @@ void device_unblock_probing(void) ...@@ -233,15 +274,36 @@ void device_unblock_probing(void)
*/ */
static int deferred_probe_initcall(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_enable = true;
driver_deferred_probe_trigger(); driver_deferred_probe_trigger();
/* Sort as many dependencies as possible before exiting initcalls */ /* Sort as many dependencies as possible before exiting initcalls */
flush_work(&deferred_probe_work); flush_work(&deferred_probe_work);
initcalls_done = true; 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; return 0;
} }
late_initcall(deferred_probe_initcall); 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 * device_is_bound() - Check if device is bound to a driver
* @dev: device to check * @dev: device to check
...@@ -519,6 +581,23 @@ static int really_probe(struct device *dev, struct device_driver *drv) ...@@ -519,6 +581,23 @@ static int really_probe(struct device *dev, struct device_driver *drv)
return ret; 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 * driver_probe_done
* Determine if the probe sequence is finished or not. * Determine if the probe sequence is finished or not.
...@@ -577,6 +656,9 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) ...@@ -577,6 +656,9 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
pm_runtime_get_sync(dev->parent); pm_runtime_get_sync(dev->parent);
pm_runtime_barrier(dev); pm_runtime_barrier(dev);
if (initcall_debug)
ret = really_probe_debug(dev, drv);
else
ret = really_probe(dev, drv); ret = really_probe(dev, drv);
pm_request_idle(dev); pm_request_idle(dev);
......
...@@ -30,9 +30,9 @@ void __init driver_init(void) ...@@ -30,9 +30,9 @@ void __init driver_init(void)
/* These are also core pieces, but must come after the /* These are also core pieces, but must come after the
* core core pieces. * core core pieces.
*/ */
of_core_init();
platform_bus_init(); platform_bus_init();
cpu_dev_init(); cpu_dev_init();
memory_dev_init(); memory_dev_init();
container_dev_init(); container_dev_init();
of_core_init();
} }
...@@ -2253,7 +2253,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np, ...@@ -2253,7 +2253,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
mutex_unlock(&gpd_list_lock); mutex_unlock(&gpd_list_lock);
dev_dbg(dev, "%s() failed to find PM domain: %ld\n", dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
__func__, PTR_ERR(pd)); __func__, PTR_ERR(pd));
return -EPROBE_DEFER; return driver_deferred_probe_check_state(dev);
} }
dev_dbg(dev, "adding to PM domain %s\n", pd->name); dev_dbg(dev, "adding to PM domain %s\n", pd->name);
......
...@@ -2915,8 +2915,6 @@ static struct platform_driver arm_smmu_driver = { ...@@ -2915,8 +2915,6 @@ static struct platform_driver arm_smmu_driver = {
}; };
module_platform_driver(arm_smmu_driver); module_platform_driver(arm_smmu_driver);
IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3");
MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations"); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>"); MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -2211,13 +2211,6 @@ static struct platform_driver arm_smmu_driver = { ...@@ -2211,13 +2211,6 @@ static struct platform_driver arm_smmu_driver = {
}; };
module_platform_driver(arm_smmu_driver); module_platform_driver(arm_smmu_driver);
IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1");
IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2");
IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400");
IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401");
IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500");
IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2");
MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>"); MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -1390,5 +1390,3 @@ static int __init exynos_iommu_init(void) ...@@ -1390,5 +1390,3 @@ static int __init exynos_iommu_init(void)
return ret; return ret;
} }
core_initcall(exynos_iommu_init); core_initcall(exynos_iommu_init);
IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu");
...@@ -1108,9 +1108,6 @@ static void __exit ipmmu_exit(void) ...@@ -1108,9 +1108,6 @@ static void __exit ipmmu_exit(void)
subsys_initcall(ipmmu_init); subsys_initcall(ipmmu_init);
module_exit(ipmmu_exit); module_exit(ipmmu_exit);
IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa");
IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795");
MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -877,7 +877,5 @@ static void __exit msm_iommu_driver_exit(void) ...@@ -877,7 +877,5 @@ static void __exit msm_iommu_driver_exit(void)
subsys_initcall(msm_iommu_driver_init); subsys_initcall(msm_iommu_driver_init);
module_exit(msm_iommu_driver_exit); module_exit(msm_iommu_driver_exit);
IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
...@@ -27,9 +27,6 @@ ...@@ -27,9 +27,6 @@
#define NO_IOMMU 1 #define NO_IOMMU 1
static const struct of_device_id __iommu_of_table_sentinel
__used __section(__iommu_of_table_end);
/** /**
* of_get_dma_window - Parse *dma-window property and returns 0 if found. * of_get_dma_window - Parse *dma-window property and returns 0 if found.
* *
...@@ -98,19 +95,6 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, ...@@ -98,19 +95,6 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
} }
EXPORT_SYMBOL_GPL(of_get_dma_window); EXPORT_SYMBOL_GPL(of_get_dma_window);
static bool of_iommu_driver_present(struct device_node *np)
{
/*
* If the IOMMU still isn't ready by the time we reach init, assume
* it never will be. We don't want to defer indefinitely, nor attempt
* to dereference __iommu_of_table after it's been freed.
*/
if (system_state >= SYSTEM_RUNNING)
return false;
return of_match_node(&__iommu_of_table, np);
}
static int of_iommu_xlate(struct device *dev, static int of_iommu_xlate(struct device *dev,
struct of_phandle_args *iommu_spec) struct of_phandle_args *iommu_spec)
{ {
...@@ -120,8 +104,7 @@ static int of_iommu_xlate(struct device *dev, ...@@ -120,8 +104,7 @@ static int of_iommu_xlate(struct device *dev,
ops = iommu_ops_from_fwnode(fwnode); ops = iommu_ops_from_fwnode(fwnode);
if ((ops && !ops->of_xlate) || if ((ops && !ops->of_xlate) ||
!of_device_is_available(iommu_spec->np) || !of_device_is_available(iommu_spec->np))
(!ops && !of_iommu_driver_present(iommu_spec->np)))
return NO_IOMMU; return NO_IOMMU;
err = iommu_fwspec_init(dev, &iommu_spec->np->fwnode, ops); err = iommu_fwspec_init(dev, &iommu_spec->np->fwnode, ops);
...@@ -133,7 +116,7 @@ static int of_iommu_xlate(struct device *dev, ...@@ -133,7 +116,7 @@ static int of_iommu_xlate(struct device *dev,
* a proper probe-ordering dependency mechanism in future. * a proper probe-ordering dependency mechanism in future.
*/ */
if (!ops) if (!ops)
return -EPROBE_DEFER; return driver_deferred_probe_check_state(dev);
return ops->of_xlate(dev, iommu_spec); return ops->of_xlate(dev, iommu_spec);
} }
......
...@@ -945,7 +945,5 @@ static void __exit qcom_iommu_exit(void) ...@@ -945,7 +945,5 @@ static void __exit qcom_iommu_exit(void)
module_init(qcom_iommu_init); module_init(qcom_iommu_init);
module_exit(qcom_iommu_exit); module_exit(qcom_iommu_exit);
IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1");
MODULE_DESCRIPTION("IOMMU API for QCOM IOMMU v1 implementations"); MODULE_DESCRIPTION("IOMMU API for QCOM IOMMU v1 implementations");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -1284,8 +1284,6 @@ static int __init rk_iommu_init(void) ...@@ -1284,8 +1284,6 @@ static int __init rk_iommu_init(void)
} }
subsys_initcall(rk_iommu_init); subsys_initcall(rk_iommu_init);
IOMMU_OF_DECLARE(rk_iommu_of, "rockchip,iommu");
MODULE_DESCRIPTION("IOMMU API for Rockchip"); MODULE_DESCRIPTION("IOMMU API for Rockchip");
MODULE_AUTHOR("Simon Xue <xxm@rock-chips.com> and Daniel Kurtz <djkurtz@chromium.org>"); MODULE_AUTHOR("Simon Xue <xxm@rock-chips.com> and Daniel Kurtz <djkurtz@chromium.org>");
MODULE_ALIAS("platform:rockchip-iommu"); MODULE_ALIAS("platform:rockchip-iommu");
......
...@@ -111,17 +111,24 @@ static int dt_to_map_one_config(struct pinctrl *p, ...@@ -111,17 +111,24 @@ static int dt_to_map_one_config(struct pinctrl *p,
int ret; int ret;
struct pinctrl_map *map; struct pinctrl_map *map;
unsigned num_maps; unsigned num_maps;
bool allow_default = false;
/* Find the pin controller containing np_config */ /* Find the pin controller containing np_config */
np_pctldev = of_node_get(np_config); np_pctldev = of_node_get(np_config);
for (;;) { for (;;) {
if (!allow_default)
allow_default = of_property_read_bool(np_pctldev,
"pinctrl-use-default");
np_pctldev = of_get_next_parent(np_pctldev); np_pctldev = of_get_next_parent(np_pctldev);
if (!np_pctldev || of_node_is_root(np_pctldev)) { if (!np_pctldev || of_node_is_root(np_pctldev)) {
dev_info(p->dev, "could not find pctldev for node %pOF, deferring probe\n",
np_config);
of_node_put(np_pctldev); of_node_put(np_pctldev);
/* OK let's just assume this will appear later then */ ret = driver_deferred_probe_check_state(p->dev);
return -EPROBE_DEFER; /* keep deferring if modules are enabled unless we've timed out */
if (IS_ENABLED(CONFIG_MODULES) && !allow_default && ret == -ENODEV)
ret = -EPROBE_DEFER;
return ret;
} }
/* If we're creating a hog we can use the passed pctldev */ /* If we're creating a hog we can use the passed pctldev */
if (hog_pctldev && (np_pctldev == p->dev->of_node)) { if (hog_pctldev && (np_pctldev == p->dev->of_node)) {
......
...@@ -97,7 +97,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, ...@@ -97,7 +97,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
int slen = strlen(kn->name); int slen = strlen(kn->name);
len -= slen; len -= slen;
strncpy(s + len, kn->name, slen); memcpy(s + len, kn->name, slen);
if (len) if (len)
s[--len] = '/'; s[--len] = '/';
......
...@@ -124,6 +124,14 @@ static int internal_create_group(struct kobject *kobj, int update, ...@@ -124,6 +124,14 @@ static int internal_create_group(struct kobject *kobj, int update,
} }
kobject_get_ownership(kobj, &uid, &gid); kobject_get_ownership(kobj, &uid, &gid);
if (grp->name) { if (grp->name) {
if (update) {
kn = kernfs_find_and_get(kobj->sd, grp->name);
if (!kn) {
pr_warn("Can't update unknown attr grp name: %s/%s\n",
kobj->name, grp->name);
return -EINVAL;
}
} else {
kn = kernfs_create_dir_ns(kobj->sd, grp->name, kn = kernfs_create_dir_ns(kobj->sd, grp->name,
S_IRWXU | S_IRUGO | S_IXUGO, S_IRWXU | S_IRUGO | S_IXUGO,
uid, gid, kobj, NULL); uid, gid, kobj, NULL);
...@@ -132,6 +140,7 @@ static int internal_create_group(struct kobject *kobj, int update, ...@@ -132,6 +140,7 @@ static int internal_create_group(struct kobject *kobj, int update,
sysfs_warn_dup(kobj->sd, grp->name); sysfs_warn_dup(kobj->sd, grp->name);
return PTR_ERR(kn); return PTR_ERR(kn);
} }
}
} else } else
kn = kobj->sd; kn = kobj->sd;
kernfs_get(kn); kernfs_get(kn);
...@@ -141,6 +150,10 @@ static int internal_create_group(struct kobject *kobj, int update, ...@@ -141,6 +150,10 @@ static int internal_create_group(struct kobject *kobj, int update,
kernfs_remove(kn); kernfs_remove(kn);
} }
kernfs_put(kn); kernfs_put(kn);
if (grp->name && update)
kernfs_put(kn);
return error; return error;
} }
...@@ -205,7 +218,8 @@ EXPORT_SYMBOL_GPL(sysfs_create_groups); ...@@ -205,7 +218,8 @@ EXPORT_SYMBOL_GPL(sysfs_create_groups);
* of the attribute files being created already exist. Furthermore, * of the attribute files being created already exist. Furthermore,
* if the visibility of the files has changed through the is_visible() * if the visibility of the files has changed through the is_visible()
* callback, it will update the permissions and add or remove the * callback, it will update the permissions and add or remove the
* relevant files. * relevant files. Changing a group's name (subdirectory name under
* kobj's directory in sysfs) is not allowed.
* *
* The primary use for this function is to call it after making a change * The primary use for this function is to call it after making a change
* that affects group visibility. * that affects group visibility.
......
...@@ -218,7 +218,6 @@ ...@@ -218,7 +218,6 @@
#define TIMER_OF_TABLES() OF_TABLE(CONFIG_TIMER_OF, timer) #define TIMER_OF_TABLES() OF_TABLE(CONFIG_TIMER_OF, timer)
#define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip) #define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip)
#define CLK_OF_TABLES() OF_TABLE(CONFIG_COMMON_CLK, clk) #define CLK_OF_TABLES() OF_TABLE(CONFIG_COMMON_CLK, clk)
#define IOMMU_OF_TABLES() OF_TABLE(CONFIG_OF_IOMMU, iommu)
#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem) #define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
#define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method) #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
...@@ -601,7 +600,6 @@ ...@@ -601,7 +600,6 @@
CLK_OF_TABLES() \ CLK_OF_TABLES() \
RESERVEDMEM_OF_TABLES() \ RESERVEDMEM_OF_TABLES() \
TIMER_OF_TABLES() \ TIMER_OF_TABLES() \
IOMMU_OF_TABLES() \
CPU_METHOD_OF_TABLES() \ CPU_METHOD_OF_TABLES() \
CPUIDLE_METHOD_OF_TABLES() \ CPUIDLE_METHOD_OF_TABLES() \
KERNEL_DTB() \ KERNEL_DTB() \
......
...@@ -339,6 +339,8 @@ struct device *driver_find_device(struct device_driver *drv, ...@@ -339,6 +339,8 @@ struct device *driver_find_device(struct device_driver *drv,
struct device *start, void *data, struct device *start, void *data,
int (*match)(struct device *dev, void *data)); int (*match)(struct device *dev, void *data));
int driver_deferred_probe_check_state(struct device *dev);
/** /**
* struct subsys_interface - interfaces to device functions * struct subsys_interface - interfaces to device functions
* @name: name of the device function * @name: name of the device function
...@@ -1329,30 +1331,34 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -1329,30 +1331,34 @@ struct device_link *device_link_add(struct device *consumer,
void device_link_del(struct device_link *link); void device_link_del(struct device_link *link);
void device_link_remove(void *consumer, struct device *supplier); void device_link_remove(void *consumer, struct device *supplier);
#ifndef dev_fmt
#define dev_fmt(fmt) fmt
#endif
#ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK
extern __printf(3, 0) __printf(3, 0)
int dev_vprintk_emit(int level, const struct device *dev, int dev_vprintk_emit(int level, const struct device *dev,
const char *fmt, va_list args); const char *fmt, va_list args);
extern __printf(3, 4) __printf(3, 4)
int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...); int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...);
extern __printf(3, 4) __printf(3, 4)
void dev_printk(const char *level, const struct device *dev, void dev_printk(const char *level, const struct device *dev,
const char *fmt, ...); const char *fmt, ...);
extern __printf(2, 3) __printf(2, 3)
void dev_emerg(const struct device *dev, const char *fmt, ...); void _dev_emerg(const struct device *dev, const char *fmt, ...);
extern __printf(2, 3) __printf(2, 3)
void dev_alert(const struct device *dev, const char *fmt, ...); void _dev_alert(const struct device *dev, const char *fmt, ...);
extern __printf(2, 3) __printf(2, 3)
void dev_crit(const struct device *dev, const char *fmt, ...); void _dev_crit(const struct device *dev, const char *fmt, ...);
extern __printf(2, 3) __printf(2, 3)
void dev_err(const struct device *dev, const char *fmt, ...); void _dev_err(const struct device *dev, const char *fmt, ...);
extern __printf(2, 3) __printf(2, 3)
void dev_warn(const struct device *dev, const char *fmt, ...); void _dev_warn(const struct device *dev, const char *fmt, ...);
extern __printf(2, 3) __printf(2, 3)
void dev_notice(const struct device *dev, const char *fmt, ...); void _dev_notice(const struct device *dev, const char *fmt, ...);
extern __printf(2, 3) __printf(2, 3)
void _dev_info(const struct device *dev, const char *fmt, ...); void _dev_info(const struct device *dev, const char *fmt, ...);
#else #else
...@@ -1374,22 +1380,22 @@ void dev_printk(const char *level, const struct device *dev, ...@@ -1374,22 +1380,22 @@ void dev_printk(const char *level, const struct device *dev,
{} {}
static inline __printf(2, 3) static inline __printf(2, 3)
void dev_emerg(const struct device *dev, const char *fmt, ...) void _dev_emerg(const struct device *dev, const char *fmt, ...)
{} {}
static inline __printf(2, 3) static inline __printf(2, 3)
void dev_crit(const struct device *dev, const char *fmt, ...) void _dev_crit(const struct device *dev, const char *fmt, ...)
{} {}
static inline __printf(2, 3) static inline __printf(2, 3)
void dev_alert(const struct device *dev, const char *fmt, ...) void _dev_alert(const struct device *dev, const char *fmt, ...)
{} {}
static inline __printf(2, 3) static inline __printf(2, 3)
void dev_err(const struct device *dev, const char *fmt, ...) void _dev_err(const struct device *dev, const char *fmt, ...)
{} {}
static inline __printf(2, 3) static inline __printf(2, 3)
void dev_warn(const struct device *dev, const char *fmt, ...) void _dev_warn(const struct device *dev, const char *fmt, ...)
{} {}
static inline __printf(2, 3) static inline __printf(2, 3)
void dev_notice(const struct device *dev, const char *fmt, ...) void _dev_notice(const struct device *dev, const char *fmt, ...)
{} {}
static inline __printf(2, 3) static inline __printf(2, 3)
void _dev_info(const struct device *dev, const char *fmt, ...) void _dev_info(const struct device *dev, const char *fmt, ...)
...@@ -1398,27 +1404,36 @@ void _dev_info(const struct device *dev, const char *fmt, ...) ...@@ -1398,27 +1404,36 @@ void _dev_info(const struct device *dev, const char *fmt, ...)
#endif #endif
/* /*
* Stupid hackaround for existing uses of non-printk uses dev_info * #defines for all the dev_<level> macros to prefix with whatever
* * possible use of #define dev_fmt(fmt) ...
* Note that the definition of dev_info below is actually _dev_info
* and a macro is used to avoid redefining dev_info
*/ */
#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg) #define dev_emerg(dev, fmt, ...) \
_dev_emerg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
_dev_crit(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
_dev_alert(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
_dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
_dev_warn(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
_dev_notice(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
_dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG)
#define dev_dbg(dev, format, ...) \ #define dev_dbg(dev, fmt, ...) \
do { \ dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG) #elif defined(DEBUG)
#define dev_dbg(dev, format, arg...) \ #define dev_dbg(dev, fmt, ...) \
dev_printk(KERN_DEBUG, dev, format, ##arg) dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
#else #else
#define dev_dbg(dev, format, arg...) \ #define dev_dbg(dev, fmt, ...) \
({ \ ({ \
if (0) \ if (0) \
dev_printk(KERN_DEBUG, dev, format, ##arg); \ dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
}) })
#endif #endif
...@@ -1490,7 +1505,7 @@ do { \ ...@@ -1490,7 +1505,7 @@ do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) && \ if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) && \
__ratelimit(&_rs)) \ __ratelimit(&_rs)) \
__dynamic_dev_dbg(&descriptor, dev, fmt, \ __dynamic_dev_dbg(&descriptor, dev, dev_fmt(fmt), \
##__VA_ARGS__); \ ##__VA_ARGS__); \
} while (0) } while (0)
#elif defined(DEBUG) #elif defined(DEBUG)
...@@ -1500,23 +1515,23 @@ do { \ ...@@ -1500,23 +1515,23 @@ do { \
DEFAULT_RATELIMIT_INTERVAL, \ DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \ DEFAULT_RATELIMIT_BURST); \
if (__ratelimit(&_rs)) \ if (__ratelimit(&_rs)) \
dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
} while (0) } while (0)
#else #else
#define dev_dbg_ratelimited(dev, fmt, ...) \ #define dev_dbg_ratelimited(dev, fmt, ...) \
do { \ do { \
if (0) \ if (0) \
dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
} while (0) } while (0)
#endif #endif
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
#define dev_vdbg dev_dbg #define dev_vdbg dev_dbg
#else #else
#define dev_vdbg(dev, format, arg...) \ #define dev_vdbg(dev, fmt, ...) \
({ \ ({ \
if (0) \ if (0) \
dev_printk(KERN_DEBUG, dev, format, ##arg); \ dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
}) })
#endif #endif
......
...@@ -119,6 +119,23 @@ extern void kobject_get_ownership(struct kobject *kobj, ...@@ -119,6 +119,23 @@ extern void kobject_get_ownership(struct kobject *kobj,
kuid_t *uid, kgid_t *gid); kuid_t *uid, kgid_t *gid);
extern char *kobject_get_path(struct kobject *kobj, gfp_t flag); extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
/**
* kobject_has_children - Returns whether a kobject has children.
* @kobj: the object to test
*
* This will return whether a kobject has other kobjects as children.
*
* It does NOT account for the presence of attribute files, only sub
* directories. It also assumes there is no concurrent addition or
* removal of such children, and thus relies on external locking.
*/
static inline bool kobject_has_children(struct kobject *kobj)
{
WARN_ON_ONCE(kref_read(&kobj->kref) == 0);
return kobj->sd && kobj->sd->dir.subdirs;
}
struct kobj_type { struct kobj_type {
void (*release)(struct kobject *kobj); void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops; const struct sysfs_ops *sysfs_ops;
......
...@@ -32,8 +32,4 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev, ...@@ -32,8 +32,4 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
#endif /* CONFIG_OF_IOMMU */ #endif /* CONFIG_OF_IOMMU */
extern struct of_device_id __iommu_of_table;
#define IOMMU_OF_DECLARE(name, compat) OF_DECLARE_1(iommu, name, compat, NULL)
#endif /* __OF_IOMMU_H */ #endif /* __OF_IOMMU_H */
...@@ -91,9 +91,9 @@ struct attribute_group { ...@@ -91,9 +91,9 @@ struct attribute_group {
struct bin_attribute **bin_attrs; struct bin_attribute **bin_attrs;
}; };
/** /*
* Use these macros to make defining attributes easier. See include/linux/device.h * Use these macros to make defining attributes easier.
* for examples.. * See include/linux/device.h for examples..
*/ */
#define SYSFS_PREALLOC 010000 #define SYSFS_PREALLOC 010000
......
...@@ -144,7 +144,7 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length) ...@@ -144,7 +144,7 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length)
int cur = strlen(kobject_name(parent)); int cur = strlen(kobject_name(parent));
/* back up enough to print this name with '/' */ /* back up enough to print this name with '/' */
length -= cur; length -= cur;
strncpy(path + length, kobject_name(parent), cur); memcpy(path + length, kobject_name(parent), cur);
*(path + --length) = '/'; *(path + --length) = '/';
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment