diff options
Diffstat (limited to 'drivers/base')
58 files changed, 974 insertions, 493 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 1786d87b29e2..f7d385cbd3ba 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -73,6 +73,15 @@ config DEVTMPFS_SAFE with the PROT_EXEC flag. This can break, for example, non-KMS video drivers. +config DRIVER_DEFERRED_PROBE_TIMEOUT + int "Default value for deferred_probe_timeout" + default 0 if !MODULES + default 10 if MODULES + help + Set the default value for the deferred_probe_timeout kernel parameter. + See Documentation/admin-guide/kernel-parameters.txt for a description + of the deferred_probe_timeout kernel parameter. + config STANDALONE bool "Select only drivers that don't need compile-time external firmware" default y diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 84ec92bff642..8c5e47c28d9a 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -34,7 +34,14 @@ EXPORT_PER_CPU_SYMBOL_GPL(capacity_freq_ref); static bool supports_scale_freq_counters(const struct cpumask *cpus) { - return cpumask_subset(cpus, &scale_freq_counters_mask); + int i; + + for_each_cpu(i, cpus) { + if (cpumask_test_cpu(i, &scale_freq_counters_mask)) + return true; + } + + return false; } bool topology_scale_freq_invariant(void) @@ -885,7 +892,7 @@ __weak int __init parse_acpi_topology(void) hetero_id = find_acpi_cpu_topology_hetero_id(cpu); entry = xa_load(&hetero_cpu, hetero_id); if (!entry) { - entry = kzalloc(sizeof(*entry), GFP_KERNEL); + entry = kzalloc_obj(*entry); WARN_ON_ONCE(!entry); if (entry) { diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index b6f941a6ab69..4ad26b8dd6a5 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -69,7 +69,7 @@ static DEFINE_MUTEX(attribute_container_mutex); * @cont: The container to register. This must be allocated by the * callee and should also be zeroed by it. */ -int +void attribute_container_register(struct attribute_container *cont) { INIT_LIST_HEAD(&cont->node); @@ -79,8 +79,6 @@ attribute_container_register(struct attribute_container *cont) mutex_lock(&attribute_container_mutex); list_add_tail(&cont->node, &attribute_container_list); mutex_unlock(&attribute_container_mutex); - - return 0; } EXPORT_SYMBOL_GPL(attribute_container_register); @@ -155,7 +153,7 @@ attribute_container_add_device(struct device *dev, if (!cont->match(cont, dev)) continue; - ic = kzalloc(sizeof(*ic), GFP_KERNEL); + ic = kzalloc_obj(*ic); if (!ic) { dev_err(dev, "failed to allocate class container\n"); continue; diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c index 04bdbff4dbe5..e129bbcbefc7 100644 --- a/drivers/base/auxiliary.c +++ b/drivers/base/auxiliary.c @@ -207,11 +207,6 @@ static int auxiliary_uevent(const struct device *dev, struct kobj_uevent_env *en (int)(p - name), name); } -static const struct dev_pm_ops auxiliary_dev_pm_ops = { - SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume) -}; - static int auxiliary_bus_probe(struct device *dev) { const struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); @@ -258,7 +253,6 @@ static const struct bus_type auxiliary_bus_type = { .shutdown = auxiliary_bus_shutdown, .match = auxiliary_match, .uevent = auxiliary_uevent, - .pm = &auxiliary_dev_pm_ops, }; /** @@ -420,7 +414,7 @@ struct auxiliary_device *auxiliary_device_create(struct device *dev, struct auxiliary_device *auxdev; int ret; - auxdev = kzalloc(sizeof(*auxdev), GFP_KERNEL); + auxdev = kzalloc_obj(*auxdev); if (!auxdev) return NULL; @@ -502,6 +496,16 @@ struct auxiliary_device *__devm_auxiliary_device_create(struct device *dev, } EXPORT_SYMBOL_GPL(__devm_auxiliary_device_create); +/** + * dev_is_auxiliary - check if the device is an auxiliary one + * @dev: device to check + */ +bool dev_is_auxiliary(struct device *dev) +{ + return dev->bus == &auxiliary_bus_type; +} +EXPORT_SYMBOL_GPL(dev_is_auxiliary); + void __init auxiliary_bus_init(void) { WARN_ON(bus_register(&auxiliary_bus_type)); diff --git a/drivers/base/auxiliary_sysfs.c b/drivers/base/auxiliary_sysfs.c index 754f21730afd..dea7f46f7dd0 100644 --- a/drivers/base/auxiliary_sysfs.c +++ b/drivers/base/auxiliary_sysfs.c @@ -63,7 +63,7 @@ int auxiliary_device_sysfs_irq_add(struct auxiliary_device *auxdev, int irq) if (ret) return ret; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc_obj(*info); if (!info) return -ENOMEM; diff --git a/drivers/base/base.h b/drivers/base/base.h index 430cbefbc97f..30b416588617 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -13,27 +13,28 @@ #include <linux/notifier.h> /** - * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure. - * - * @subsys - the struct kset that defines this subsystem - * @devices_kset - the subsystem's 'devices' directory - * @interfaces - list of subsystem interfaces associated - * @mutex - protect the devices, and interfaces lists. - * - * @drivers_kset - the list of drivers associated - * @klist_devices - the klist to iterate over the @devices_kset - * @klist_drivers - the klist to iterate over the @drivers_kset - * @bus_notifier - the bus notifier list for anything that cares about things - * on this bus. - * @bus - pointer back to the struct bus_type that this structure is associated - * with. + * struct subsys_private - structure to hold the private to the driver core + * portions of the bus_type/class structure. + * @subsys: the struct kset that defines this subsystem + * @devices_kset: the subsystem's 'devices' directory + * @interfaces: list of subsystem interfaces associated + * @mutex: protect the devices, and interfaces lists. + * @drivers_kset: the list of drivers associated + * @klist_devices: the klist to iterate over the @devices_kset + * @klist_drivers: the klist to iterate over the @drivers_kset + * @bus_notifier: the bus notifier list for anything that cares about things + * on this bus. + * @drivers_autoprobe: gate whether new devices are automatically attached to + * registered drivers, or new drivers automatically attach + * to existing devices. + * @bus: pointer back to the struct bus_type that this structure is associated + * with. * @dev_root: Default device to use as the parent. - * - * @glue_dirs - "glue" directory to put in-between the parent device to - * avoid namespace conflicts - * @class - pointer back to the struct class that this structure is associated - * with. - * @lock_key: Lock class key for use by the lock validator + * @glue_dirs: "glue" directory to put in-between the parent device to + * avoid namespace conflicts + * @class: pointer back to the struct class that this structure is associated + * with. + * @lock_key: Lock class key for use by the lock validator * * This structure is the one that is the actual kobject allowing struct * bus_type/class to be statically allocated safely. Nothing outside of the @@ -98,24 +99,26 @@ struct driver_type { #endif /** - * struct device_private - structure to hold the private to the driver core portions of the device structure. - * - * @klist_children - klist containing all children of this device - * @knode_parent - node in sibling list - * @knode_driver - node in driver list - * @knode_bus - node in bus list - * @knode_class - node in class list - * @deferred_probe - entry in deferred_probe_list which is used to retry the - * binding of drivers which were unable to get all the resources needed by - * the device; typically because it depends on another driver getting - * probed first. - * @async_driver - pointer to device driver awaiting probe via async_probe - * @device - pointer back to the struct device that this structure is - * associated with. - * @driver_type - The type of the bound Rust driver. - * @dead - This device is currently either in the process of or has been - * removed from the system. Any asynchronous events scheduled for this - * device should exit without taking any action. + * struct device_private - structure to hold the private to the driver core + * portions of the device structure. + * @klist_children: klist containing all children of this device + * @knode_parent: node in sibling list + * @knode_driver: node in driver list + * @knode_bus: node in bus list + * @knode_class: node in class list + * @deferred_probe: entry in deferred_probe_list which is used to retry the + * binding of drivers which were unable to get all the + * resources needed by the device; typically because it depends + * on another driver getting probed first. + * @async_driver: pointer to device driver awaiting probe via async_probe + * @deferred_probe_reason: capture the -EPROBE_DEFER message emitted with + * dev_err_probe() for later retrieval via debugfs + * @device: pointer back to the struct device that this structure is + * associated with. + * @driver_type: The type of the bound Rust driver. + * @dead: This device is currently either in the process of or has been + * removed from the system. Any asynchronous events scheduled for this + * device should exit without taking any action. * * Nothing outside of the driver core should ever touch these fields. */ @@ -213,6 +216,28 @@ static inline void device_set_driver(struct device *dev, const struct device_dri WRITE_ONCE(dev->driver, (struct device_driver *)drv); } +struct devres_node; +typedef void (*dr_node_release_t)(struct device *dev, struct devres_node *node); +typedef void (*dr_node_free_t)(struct devres_node *node); + +struct devres_node { + struct list_head entry; + dr_node_release_t release; + dr_node_free_t free_node; + const char *name; + size_t size; +}; + +void devres_node_init(struct devres_node *node, dr_node_release_t release, + dr_node_free_t free_node); +void devres_node_add(struct device *dev, struct devres_node *node); +bool devres_node_remove(struct device *dev, struct devres_node *node); +void devres_set_node_dbginfo(struct devres_node *node, const char *name, + size_t size); +void devres_for_each_res(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data, + void (*fn)(struct device *, void *, void *), + void *data); int devres_release_all(struct device *dev); void device_block_probing(void); void device_unblock_probing(void); @@ -287,5 +312,15 @@ static inline int devtmpfs_create_node(struct device *dev) { return 0; } static inline int devtmpfs_delete_node(struct device *dev) { return 0; } #endif +void software_node_init(void); void software_node_notify(struct device *dev); void software_node_notify_remove(struct device *dev); + +#ifdef CONFIG_PINCTRL +int pinctrl_bind_pins(struct device *dev); +#else +static inline int pinctrl_bind_pins(struct device *dev) +{ + return 0; +} +#endif /* CONFIG_PINCTRL */ diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 9eb7771706f0..8b6722ff8590 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -504,6 +504,36 @@ int bus_for_each_drv(const struct bus_type *bus, struct device_driver *start, } EXPORT_SYMBOL_GPL(bus_for_each_drv); +static ssize_t driver_override_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + + ret = __device_set_driver_override(dev, buf, count); + if (ret) + return ret; + + return count; +} + +static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + guard(spinlock)(&dev->driver_override.lock); + return sysfs_emit(buf, "%s\n", dev->driver_override.name); +} +static DEVICE_ATTR_RW(driver_override); + +static struct attribute *driver_override_dev_attrs[] = { + &dev_attr_driver_override.attr, + NULL, +}; + +static const struct attribute_group driver_override_dev_group = { + .attrs = driver_override_dev_attrs, +}; + /** * bus_add_device - add device to bus * @dev: device being added @@ -537,9 +567,15 @@ int bus_add_device(struct device *dev) if (error) goto out_put; + if (dev->bus->driver_override) { + error = device_add_group(dev, &driver_override_dev_group); + if (error) + goto out_groups; + } + error = sysfs_create_link(&sp->devices_kset->kobj, &dev->kobj, dev_name(dev)); if (error) - goto out_groups; + goto out_override; error = sysfs_create_link(&dev->kobj, &sp->subsys.kobj, "subsystem"); if (error) @@ -550,6 +586,9 @@ int bus_add_device(struct device *dev) out_subsys: sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); +out_override: + if (dev->bus->driver_override) + device_remove_group(dev, &driver_override_dev_group); out_groups: device_remove_groups(dev, sp->bus->dev_groups); out_put: @@ -607,6 +646,8 @@ void bus_remove_device(struct device *dev) sysfs_remove_link(&dev->kobj, "subsystem"); sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); + if (dev->bus->driver_override) + device_remove_group(dev, &driver_override_dev_group); device_remove_groups(dev, dev->bus->dev_groups); if (klist_node_attached(&dev->p->knode_bus)) klist_del(&dev->p->knode_bus); @@ -696,7 +737,7 @@ int bus_add_driver(struct device_driver *drv) */ pr_debug("bus: '%s': add driver %s\n", sp->bus->name, drv->name); - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = kzalloc_obj(*priv); if (!priv) { error = -ENOMEM; goto out_put_bus; @@ -897,7 +938,7 @@ int bus_register(const struct bus_type *bus) struct kobject *bus_kobj; struct lock_class_key *key; - priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL); + priv = kzalloc_obj(struct subsys_private); if (!priv) return -ENOMEM; @@ -1263,7 +1304,7 @@ static int subsys_register(const struct bus_type *subsys, goto err_sp; } - dev = kzalloc(sizeof(struct device), GFP_KERNEL); + dev = kzalloc_obj(struct device); if (!dev) { err = -ENOMEM; goto err_dev; diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 613410705a47..391ac5e3d2f5 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -510,7 +510,8 @@ int __weak populate_cache_leaves(unsigned int cpu) static inline int allocate_cache_info(int cpu) { - per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu), sizeof(struct cacheinfo), GFP_ATOMIC); + per_cpu_cacheinfo(cpu) = kzalloc_objs(struct cacheinfo, + cache_leaves(cpu), GFP_ATOMIC); if (!per_cpu_cacheinfo(cpu)) { cache_leaves(cpu) = 0; return -ENOMEM; @@ -882,8 +883,8 @@ static int cpu_cache_sysfs_init(unsigned int cpu) return PTR_ERR(per_cpu_cache_dev(cpu)); /* Allocate all required memory */ - per_cpu_index_dev(cpu) = kcalloc(cache_leaves(cpu), - sizeof(struct device *), GFP_KERNEL); + per_cpu_index_dev(cpu) = kzalloc_objs(struct device *, + cache_leaves(cpu)); if (unlikely(per_cpu_index_dev(cpu) == NULL)) goto err_out; diff --git a/drivers/base/class.c b/drivers/base/class.c index 2526c57d924e..ffab0a9c8ccb 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -127,7 +127,7 @@ static const struct kobj_type class_ktype = { }; int class_create_file_ns(const struct class *cls, const struct class_attribute *attr, - const void *ns) + const struct ns_common *ns) { struct subsys_private *sp = class_to_subsys(cls); int error; @@ -143,7 +143,7 @@ int class_create_file_ns(const struct class *cls, const struct class_attribute * EXPORT_SYMBOL_GPL(class_create_file_ns); void class_remove_file_ns(const struct class *cls, const struct class_attribute *attr, - const void *ns) + const struct ns_common *ns) { struct subsys_private *sp = class_to_subsys(cls); @@ -194,7 +194,7 @@ int class_register(const struct class *cls) return -EINVAL; } - cp = kzalloc(sizeof(*cp), GFP_KERNEL); + cp = kzalloc_obj(*cp); if (!cp) return -ENOMEM; klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put); @@ -268,7 +268,7 @@ struct class *class_create(const char *name) struct class *cls; int retval; - cls = kzalloc(sizeof(*cls), GFP_KERNEL); + cls = kzalloc_obj(*cls); if (!cls) { retval = -ENOMEM; goto error; @@ -573,7 +573,7 @@ struct class_compat *class_compat_register(const char *name) { struct class_compat *cls; - cls = kmalloc(sizeof(struct class_compat), GFP_KERNEL); + cls = kmalloc_obj(struct class_compat); if (!cls) return NULL; cls->kobj = kobject_create_and_add(name, &class_kset->kobj); diff --git a/drivers/base/component.c b/drivers/base/component.c index 024ad9471b8a..655d68deb590 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -363,7 +363,7 @@ static int component_match_realloc(struct component_match *match, size_t num) if (match->alloc == num) return 0; - new = kmalloc_array(num, sizeof(*new), GFP_KERNEL); + new = kmalloc_objs(*new, num); if (!new) return -ENOMEM; @@ -521,7 +521,7 @@ int component_master_add_with_match(struct device *parent, if (ret) return ret; - adev = kzalloc(sizeof(*adev), GFP_KERNEL); + adev = kzalloc_obj(*adev); if (!adev) return -ENOMEM; @@ -732,7 +732,7 @@ static int __component_add(struct device *dev, const struct component_ops *ops, struct component *component; int ret; - component = kzalloc(sizeof(*component), GFP_KERNEL); + component = kzalloc_obj(*component); if (!component) return -ENOMEM; diff --git a/drivers/base/core.c b/drivers/base/core.c index 40de2f51a1b1..bd2ddf2aab50 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -76,7 +76,7 @@ static int __fwnode_link_add(struct fwnode_handle *con, return 0; } - link = kzalloc(sizeof(*link), GFP_KERNEL); + link = kzalloc_obj(*link); if (!link) return -ENOMEM; @@ -182,7 +182,7 @@ void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode) if (fwnode->dev) return; - fwnode->flags |= FWNODE_FLAG_NOT_DEVICE; + fwnode_set_flag(fwnode, FWNODE_FLAG_NOT_DEVICE); fwnode_links_purge_consumers(fwnode); fwnode_for_each_available_child_node(fwnode, child) @@ -228,7 +228,7 @@ static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode, if (fwnode->dev && fwnode->dev->bus) return; - fwnode->flags |= FWNODE_FLAG_NOT_DEVICE; + fwnode_set_flag(fwnode, FWNODE_FLAG_NOT_DEVICE); __fwnode_links_move_consumers(fwnode, new_sup); fwnode_for_each_available_child_node(fwnode, child) @@ -844,7 +844,7 @@ struct device_link *device_link_add(struct device *consumer, goto out; } - link = kzalloc(sizeof(*link), GFP_KERNEL); + link = kzalloc_obj(*link); if (!link) goto out; @@ -1012,7 +1012,7 @@ static void device_links_missing_supplier(struct device *dev) static bool dev_is_best_effort(struct device *dev) { return (fw_devlink_best_effort && dev->can_match) || - (dev->fwnode && (dev->fwnode->flags & FWNODE_FLAG_BEST_EFFORT)); + (dev->fwnode && fwnode_test_flag(dev->fwnode, FWNODE_FLAG_BEST_EFFORT)); } static struct fwnode_handle *fwnode_links_check_suppliers( @@ -1723,11 +1723,11 @@ bool fw_devlink_is_strict(void) static void fw_devlink_parse_fwnode(struct fwnode_handle *fwnode) { - if (fwnode->flags & FWNODE_FLAG_LINKS_ADDED) + if (fwnode_test_flag(fwnode, FWNODE_FLAG_LINKS_ADDED)) return; fwnode_call_int_op(fwnode, add_links); - fwnode->flags |= FWNODE_FLAG_LINKS_ADDED; + fwnode_set_flag(fwnode, FWNODE_FLAG_LINKS_ADDED); } static void fw_devlink_parse_fwtree(struct fwnode_handle *fwnode) @@ -1885,7 +1885,7 @@ static bool fwnode_init_without_drv(struct fwnode_handle *fwnode) struct device *dev; bool ret; - if (!(fwnode->flags & FWNODE_FLAG_INITIALIZED)) + if (!fwnode_test_flag(fwnode, FWNODE_FLAG_INITIALIZED)) return false; dev = get_dev_from_fwnode(fwnode); @@ -2001,10 +2001,10 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle, * We aren't trying to find all cycles. Just a cycle between con and * sup_handle. */ - if (sup_handle->flags & FWNODE_FLAG_VISITED) + if (fwnode_test_flag(sup_handle, FWNODE_FLAG_VISITED)) return false; - sup_handle->flags |= FWNODE_FLAG_VISITED; + fwnode_set_flag(sup_handle, FWNODE_FLAG_VISITED); /* Termination condition. */ if (sup_handle == con_handle) { @@ -2074,7 +2074,7 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle, } out: - sup_handle->flags &= ~FWNODE_FLAG_VISITED; + fwnode_clear_flag(su |
