diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-15 12:41:17 +0530 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-15 12:41:17 +0530 |
| commit | 36808d5e983985bbda87e01059cccc071fe3ec8d (patch) | |
| tree | fe89e03319a2eeacabced24f1e6b96123ad527f9 /drivers | |
| parent | 5504ce0317f777dcf102751c3e518284226fc2e1 (diff) | |
| parent | fe221742e388bea3f5856b5d9b2cb0a037020ea4 (diff) | |
Merge tag 'driver-core-7.2-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core updates from Danilo Krummrich:
"Deferred probe:
- Fix race where deferred probe timeout work could be permanently
canceled by using mod_delayed_work()
- Fix missing jiffies conversion in deferred_probe_extend_timeout()
- Guard timeout extension with delayed_work_pending() to prevent
premature firing
- Use system_percpu_wq instead of the deprecated system_wq
- Update deferred_probe_timeout documentation
device:
- Replace direct struct device bitfield access (can_match, dma_iommu,
dma_skip_sync, dma_ops_bypass, state_synced, dma_coherent,
of_node_reused, offline, offline_disabled) with flag-based
accessors using bit operations
- Reject devices with unregistered buses
- Delete unused DEVICE_ATTR_PREALLOC()
- Add low-level device attribute macros with const show/store
callbacks, allowing device attributes to reside in read-only memory
- Move core device attributes to read-only memory
- Constify group array pointers in driver_add_groups() /
driver_remove_groups(), struct bus_type, and struct device_driver
device property:
- Fix fwnode reference leak in fwnode_graph_get_endpoint_by_id()
- Initialize all fields of fwnode_handle in fwnode_init()
- Provide swnode_get()/swnode_put() wrappers around kobject_get/put()
- Allow passing struct software_node_ref_args pointers directly to
PROPERTY_ENTRY_REF()
driver_override:
- Migrate amba, cdx, vmbus, and rpmsg to the generic driver_override
infrastructure, fixing a UAF from unsynchronized access to
driver_override in bus match() callbacks
- Remove the now-unused driver_set_override()
firmware loader:
- Fix recursive lock deadlock in device_cache_fw_images() when async
work falls back to synchronous execution
- Fix device reference leak in firmware_upload_register()
platform:
- Pass KBUILD_MODNAME through the platform driver registration macro
to create module symlinks in sysfs for built-in drivers; move
module_kset initialization to a pure_initcall and tegra cbb
registration to core_initcall to ensure correct ordering
- Pass THIS_MODULE implicitly through a coresight_init_driver() macro
sysfs:
- Upgrade OOB write detection in sysfs_kf_seq_show() from printk to
WARN
- Add return value clamping to sysfs_kf_read()
Rust:
- ACPI:
Fix missing match data for PRP0001 by exporting
acpi_of_match_device()
- Auxiliary:
Replace drvdata() with dedicated registration data on
auxiliary_device. drvdata() exposed the driver's bus device private
data beyond the driver's own scope, creating ordering constraints
and forcing the data to outlive all registrations that access it.
Registration data is instead scoped structurally to the
Registration object, making lifecycle ordering enforced by
construction rather than convention.
- Rust-native device driver lifetimes (HRT):
Allow Rust device drivers to carry a lifetime parameter on their
bus device private data, tied to the device binding scope -- the
interval during which a bus device is bound to a driver. Device
resources like pci::Bar<'a> and IoMem<'a> can be stored directly in
the driver's bus device private data with a lifetime bounded by the
binding scope, so the compiler enforces at build time that they do
not outlive the binding. This removes Devres indirection from every
access site and eliminates try_access() failure paths in
destructors.
Bus driver traits use a Generic Associated Type (GAT) Data<'bound>
to introduce the lifetime on the private data, rather than
parameterizing the Driver trait itself. Auxiliary registration
data, where the lifetime is not introduced by a trait callback but
must be threaded through Registration, uses the ForLt trait (a
type-level abstraction for types generic over a lifetime).
Misc:
- Fix DT overlayed devices not probing by reverting the broken
treewide overlay fix and re-running fw_devlink consumer pickup when
an overlay is applied to a bound device
- Use root_device_register() for faux bus root device; add sanity
check for failed bus init
- Fix dev_has_sync_state() data race with READ_ONCE() and move it to
base.h
- Avoid spurious device_links warning when removing a device while
its supplier is unbinding
- Switch ISA bus to dynamic root device
- Fix suspicious RCU usage in kernfs_put()
- Remove devcoredump exit callback
- Constify devfreq_event_class"
* tag 'driver-core-7.2-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/driver-core/driver-core: (81 commits)
software node: allow passing reference args to PROPERTY_ENTRY_REF()
driver core: platform: set mod_name in driver registration
coresight: pass THIS_MODULE implicitly through a macro
kernel: param: initialize module_kset in a pure_initcall
soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall
firmware_loader: Fix recursive lock in device_cache_fw_images()
driver core: Use system_percpu_wq instead of system_wq
driver core: remove driver_set_override()
rpmsg: use generic driver_override infrastructure
Drivers: hv: vmbus: use generic driver_override infrastructure
cdx: use generic driver_override infrastructure
amba: use generic driver_override infrastructure
rust: devres: add 'static bound to Devres<T>
samples: rust: rust_driver_auxiliary: showcase lifetime-bound registration data
rust: auxiliary: generalize Registration over ForLt
rust: types: add `ForLt` trait for higher-ranked lifetime support
gpu: nova-core: separate driver type from driver data
samples: rust: rust_driver_pci: use HRT lifetime for Bar
rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized
rust: pci: make Bar lifetime-parameterized
...
Diffstat (limited to 'drivers')
60 files changed, 385 insertions, 483 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b0e7181ae304..3b7db94b81f7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -898,9 +898,9 @@ const struct acpi_device *acpi_companion_match(const struct device *dev) * identifiers and a _DSD object with the "compatible" property, use that * property to match against the given list of identifiers. */ -static bool acpi_of_match_device(const struct acpi_device *adev, - const struct of_device_id *of_match_table, - const struct of_device_id **of_id) +bool acpi_of_match_device(const struct acpi_device *adev, + const struct of_device_id *of_match_table, + const struct of_device_id **of_id) { const union acpi_object *of_compatible, *obj; int i, nval; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 075798d70ff1..9a7ac2eb9ce0 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -122,7 +122,7 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING); list_for_each_entry(pn, &adev->physical_node_list, node) - if (device_supports_offline(pn->dev) && !pn->dev->offline) { + if (device_supports_offline(pn->dev) && !dev_offline(pn->dev)) { if (uevent) kobject_uevent_env(&pn->dev->kobj, KOBJ_CHANGE, envp); diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 6d479caf89cb..d721d64a9858 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -82,33 +82,6 @@ static void amba_put_disable_pclk(struct amba_device *pcdev) } -static ssize_t driver_override_show(struct device *_dev, - struct device_attribute *attr, char *buf) -{ - struct amba_device *dev = to_amba_device(_dev); - ssize_t len; - - device_lock(_dev); - len = sprintf(buf, "%s\n", dev->driver_override); - device_unlock(_dev); - return len; -} - -static ssize_t driver_override_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct amba_device *dev = to_amba_device(_dev); - int ret; - - ret = driver_set_override(_dev, &dev->driver_override, buf, count); - if (ret) - return ret; - - return count; -} -static DEVICE_ATTR_RW(driver_override); - #define amba_attr_func(name,fmt,arg...) \ static ssize_t name##_show(struct device *_dev, \ struct device_attribute *attr, char *buf) \ @@ -126,7 +99,6 @@ amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n", static struct attribute *amba_dev_attrs[] = { &dev_attr_id.attr, &dev_attr_resource.attr, - &dev_attr_driver_override.attr, NULL, }; ATTRIBUTE_GROUPS(amba_dev); @@ -209,10 +181,11 @@ static int amba_match(struct device *dev, const struct device_driver *drv) { struct amba_device *pcdev = to_amba_device(dev); const struct amba_driver *pcdrv = to_amba_driver(drv); + int ret; mutex_lock(&pcdev->periphid_lock); if (!pcdev->periphid) { - int ret = amba_read_periphid(pcdev); + ret = amba_read_periphid(pcdev); /* * Returning any error other than -EPROBE_DEFER from bus match @@ -230,8 +203,9 @@ static int amba_match(struct device *dev, const struct device_driver *drv) mutex_unlock(&pcdev->periphid_lock); /* When driver_override is set, only bind to the matching driver */ - if (pcdev->driver_override) - return !strcmp(pcdev->driver_override, drv->name); + ret = device_match_driver_override(dev, drv); + if (ret >= 0) + return ret; return amba_lookup(pcdrv->id_table, pcdev) != NULL; } @@ -436,6 +410,7 @@ static const struct dev_pm_ops amba_pm = { const struct bus_type amba_bustype = { .name = "amba", .dev_groups = amba_dev_groups, + .driver_override = true, .match = amba_match, .uevent = amba_uevent, .probe = amba_probe, diff --git a/drivers/base/base.h b/drivers/base/base.h index 30b416588617..a5b7abc10ff0 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -86,18 +86,6 @@ struct driver_private { }; #define to_driver(obj) container_of(obj, struct driver_private, kobj) -#ifdef CONFIG_RUST -/** - * struct driver_type - Representation of a Rust driver type. - */ -struct driver_type { - /** - * @id: Representation of core::any::TypeId. - */ - u8 id[16]; -} __packed; -#endif - /** * struct device_private - structure to hold the private to the driver core * portions of the device structure. @@ -115,7 +103,6 @@ struct driver_type { * 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. @@ -132,9 +119,6 @@ struct device_private { const struct device_driver *async_driver; char *deferred_probe_reason; struct device *device; -#ifdef CONFIG_RUST - struct driver_type driver_type; -#endif u8 dead:1; }; #define to_device_private_parent(obj) \ @@ -188,6 +172,20 @@ static inline int driver_match_device(const struct device_driver *drv, return drv->bus->match ? drv->bus->match(dev, drv) : 1; } +static inline bool dev_has_sync_state(struct device *dev) +{ + struct device_driver *drv; + + if (!dev) + return false; + drv = READ_ONCE(dev->driver); + if (drv && drv->sync_state) + return true; + if (dev->bus && dev->bus->sync_state) + return true; + return false; +} + static inline void dev_sync_state(struct device *dev) { if (dev->bus->sync_state) @@ -196,8 +194,10 @@ static inline void dev_sync_state(struct device *dev) dev->driver->sync_state(dev); } -int driver_add_groups(const struct device_driver *drv, const struct attribute_group **groups); -void driver_remove_groups(const struct device_driver *drv, const struct attribute_group **groups); +int driver_add_groups(const struct device_driver *drv, + const struct attribute_group *const *groups); +void driver_remove_groups(const struct device_driver *drv, + const struct attribute_group *const *groups); void device_driver_detach(struct device *dev); static inline void device_set_driver(struct device *dev, const struct device_driver *drv) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 8b6722ff8590..d17bd91490ee 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -544,10 +544,10 @@ static const struct attribute_group driver_override_dev_group = { */ int bus_add_device(struct device *dev) { - struct subsys_private *sp = bus_to_subsys(dev->bus); + struct subsys_private *sp; int error; - if (!sp) { + if (!dev->bus) { /* * This is a normal operation for many devices that do not * have a bus assigned to them, just say that all went @@ -556,6 +556,13 @@ int bus_add_device(struct device *dev) return 0; } + sp = bus_to_subsys(dev->bus); + if (!sp) { + pr_err("%s: cannot add device '%s' to unregistered bus '%s'\n", + __func__, dev_name(dev), dev->bus->name); + return -EINVAL; + } + /* * Reference in sp is now incremented and will be dropped when * the device is removed from the bus diff --git a/drivers/base/core.c b/drivers/base/core.c index bd2ddf2aab50..4d026682944f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -235,6 +235,79 @@ static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode, __fw_devlink_pickup_dangling_consumers(child, new_sup); } +static void fw_devlink_pickup_dangling_consumers(struct device *dev) +{ + struct fwnode_handle *child; + + guard(mutex)(&fwnode_link_lock); + + fwnode_for_each_available_child_node(dev->fwnode, child) + __fw_devlink_pickup_dangling_consumers(child, dev->fwnode); + __fw_devlink_link_to_consumers(dev); +} + +/** + * fw_devlink_refresh_fwnode - Recheck the tree under this firmware node + * @fwnode: The fwnode under which the fwnode tree has changed + * + * This function is mainly meant to adjust the supplier/consumer dependencies + * after a fwnode tree overlay has occurred. + */ +void fw_devlink_refresh_fwnode(struct fwnode_handle *fwnode) +{ + struct device *dev; + + /* + * Find the closest ancestor fwnode that has been converted to a device + * that can bind to a driver (bus device). + */ + fwnode_handle_get(fwnode); + do { + if (fwnode_test_flag(fwnode, FWNODE_FLAG_NOT_DEVICE)) + continue; + + dev = get_dev_from_fwnode(fwnode); + if (!dev) + continue; + + if (dev->bus) + break; + + put_device(dev); + } while ((fwnode = fwnode_get_next_parent(fwnode))); + + /* + * If none of the ancestor fwnodes have (yet) been converted to a device + * that can bind to a driver, there's nothing to fix up. + */ + if (!fwnode) + return; + + WARN(device_is_bound(dev) && dev->links.status != DL_DEV_DRIVER_BOUND, + "Don't multithread overlaying and probing the same device!\n"); + + /* + * If the device has already bound to a driver, then we need to redo + * some of the work that was done after the device was bound to a + * driver. If the device hasn't bound to a driver, running things too + * soon would incorrectly pick up consumers that it shouldn't. + */ + if (dev->links.status == DL_DEV_DRIVER_BOUND) { + fw_devlink_pickup_dangling_consumers(dev); + /* + * Some of dangling consumers could have been put previously in + * the deferred probe list due to the unavailability of their + * suppliers. Those consumers have been picked up and some of + * their suppliers links have been updated. Time to re-try their + * probe sequence. + */ + driver_deferred_probe_trigger(); + } + + put_device(dev); + fwnode_handle_put(fwnode); +} + static DEFINE_MUTEX(device_links_lock); DEFINE_STATIC_SRCU(device_links_srcu); @@ -422,7 +495,7 @@ void device_pm_move_to_tail(struct device *dev) #define to_devlink(dev) container_of((dev), struct device_link, link_dev) static ssize_t status_show(struct device *dev, - struct device_attribute *attr, char *buf) + const struct device_attribute *attr, char *buf) { const char *output; @@ -452,10 +525,10 @@ static ssize_t status_show(struct device *dev, return sysfs_emit(buf, "%s\n", output); } -static DEVICE_ATTR_RO(status); +static const DEVICE_ATTR_RO(status); static ssize_t auto_remove_on_show(struct device *dev, - struct device_attribute *attr, char *buf) + const struct device_attribute *attr, char *buf) { struct device_link *link = to_devlink(dev); const char *output; @@ -469,27 +542,27 @@ static ssize_t auto_remove_on_show(struct device *dev, return sysfs_emit(buf, "%s\n", output); } -static DEVICE_ATTR_RO(auto_remove_on); +static const DEVICE_ATTR_RO(auto_remove_on); static ssize_t runtime_pm_show(struct device *dev, - struct device_attribute *attr, char *buf) + const struct device_attribute *attr, char *buf) { struct device_link *link = to_devlink(dev); return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_PM_RUNTIME)); } -static DEVICE_ATTR_RO(runtime_pm); +static const DEVICE_ATTR_RO(runtime_pm); static ssize_t sync_state_only_show(struct device *dev, - struct device_attribute *attr, char *buf) + const struct device_attribute *attr, char *buf) { struct device_link *link = to_devlink(dev); return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)); } -static DEVICE_ATTR_RO(sync_state_only); +static const DEVICE_ATTR_RO(sync_state_only); -static struct attribute *devlink_attrs[] = { +static const struct attribute *const devlink_attrs[] = { &dev_attr_status.attr, &dev_attr_auto_remove_on.attr, &dev_attr_runtime_pm.attr, @@ -1011,7 +1084,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) || + return (fw_devlink_best_effort && dev_can_match(dev)) || (dev->fwnode && fwnode_test_flag(dev->fwnode, FWNODE_FLAG_BEST_EFFORT)); } @@ -1079,7 +1152,7 @@ int device_links_check_suppliers(struct device *dev) if (dev_is_best_effort(dev) && device_link_test(link, DL_FLAG_INFERRED) && - !link->supplier->can_match) { + !dev_can_match(link->supplier)) { ret = -EAGAIN; continue; } @@ -1123,7 +1196,7 @@ static void __device_links_queue_sync_state(struct device *dev, if (!dev_has_sync_state(dev)) return; - if (dev->state_synced) + if (dev_state_synced(dev)) return; list_for_each_entry(link, &dev->links.consumers, s_node) { @@ -1138,7 +1211,7 @@ static void __device_links_queue_sync_state(struct device *dev, * than once. This can happen if new consumers get added to the device * and probed before the list is flushed. */ - dev->state_synced = true; + dev_set_state_synced(dev); if (WARN_ON(!list_empty(&dev->links.defer_sync))) return; @@ -1233,7 +1306,7 @@ static void device_link_drop_managed(struct device_link *link) } static ssize_t waiting_for_supplier_show(struct device *dev, - struct device_attribute *attr, + const struct device_attribute *attr, char *buf) { bool val; @@ -1244,7 +1317,7 @@ static ssize_t waiting_for_supplier_show(struct device *dev, device_unlock(dev); return sysfs_emit(buf, "%u\n", val); } -static DEVICE_ATTR_RO(waiting_for_supplier); +static const DEVICE_ATTR_RO(waiting_for_supplier); /** * device_links_force_bind - Prepares device to be force bound @@ -1312,16 +1385,8 @@ void device_links_driver_bound(struct device *dev) * child firmware node. */ if (dev->fwnode && dev->fwnode->dev == dev) { - struct fwnode_handle *child; - fwnode_links_purge_suppliers(dev->fwnode); - - guard(mutex)(&fwnode_link_lock); - - fwnode_for_each_available_child_node(dev->fwnode, child) - __fw_devlink_pickup_dangling_consumers(child, - dev->fwnode); - __fw_devlink_link_to_consumers(dev); + fw_devlink_pickup_dangling_consumers(dev); } device_remove_file(dev, &dev_attr_waiting_for_supplier); @@ -1370,7 +1435,7 @@ void device_links_driver_bound(struct device *dev) } else if (dev_is_best_effort(dev) && device_link_test(link, DL_FLAG_INFERRED) && link->status != DL_STATE_CONSUMER_PROBE && - !link->supplier->can_match) { + !dev_can_match(link->supplier)) { /* * When dev_is_best_effort() is true, we ignore device * links to suppliers that don't have a driver. If the @@ -1435,7 +1500,8 @@ static void __device_links_no_driver(struct device *dev) if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) { WRITE_ONCE(link->status, DL_STATE_AVAILABLE); } else { - WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)); + WARN_ON(link->supplier->links.status != DL_DEV_UNBINDING && + !device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)); WRITE_ONCE(link->status, DL_STATE_DORMANT); } } @@ -1758,7 +1824,7 @@ static int fw_devlink_no_driver(struct device *dev, void *data) { struct device_link *link = to_devlink(dev); - if (!link->supplier->can_match) + if (!dev_can_match(link->supplier)) fw_devlink_relax_link(link); return 0; @@ -1779,7 +1845,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data) struct device *sup = link->supplier; if (!device_link_test(link, DL_FLAG_MANAGED) || - link->status == DL_STATE_ACTIVE || sup->state_synced || + link->status == DL_STATE_ACTIVE || dev_state_synced(sup) || !dev_has_sync_state(sup)) return 0; @@ -1793,7 +1859,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data) return 0; dev_warn(sup, "Timed out. Forcing sync_state()\n"); - sup->state_synced = true; + dev_set_state_synced(sup); get_device(sup); list_add_tail(&sup->links.defer_sync, data); @@ -2419,9 +2485,11 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, if (dev_attr->show) ret = dev_attr->show(dev, dev_attr, buf); + else if (dev_attr->show_const) + ret = dev_attr->show_const(dev, dev_attr, buf); if (ret >= (ssize_t)PAGE_SIZE) { - printk("dev_attr_show: %pS returned bad count\n", - dev_attr->show); + printk("dev_attr_show: %pS/%pS returned bad count\n", + dev_attr->show, dev_attr->show_const); } return ret; } @@ -2435,6 +2503,8 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, if (dev_attr->store) ret = dev_attr->store(dev, dev_attr, buf, count); + else if (dev_attr->store_const) + ret = dev_attr->store_const(dev, dev_attr, buf, count); return ret; } @@ -2722,7 +2792,7 @@ static const struct kset_uevent_ops device_uevent_ops = { .uevent = dev_uevent, }; -static ssize_t uevent_show(struct device *dev, struct device_attribute *attr, +static ssize_t uevent_show(struct device *dev, const struct device_attribute *attr, char *buf) { struct kobject *top_kobj; @@ -2765,7 +2835,7 @@ out: return len; } -static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, +static ssize_t uevent_store(struct device *dev, const struct device_attribute *attr, const char *buf, size_t count) { int rc; @@ -2779,20 +2849,20 @@ static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR_RW(uevent); +static const DEVICE_ATTR_RW(uevent); -static ssize_t online_show(struct device *dev, struct device_attribute *attr, +static ssize_t online_show(struct device *dev, const struct device_attribute *attr, char *buf) { bool val; device_lock(dev); - val = !dev->offline; + val = !dev_offline(dev); device_unlock(dev); return sysfs_emit(buf, "%u\n", val); } -static ssize_t online_store(struct device *dev, struct device_attribute *attr, +static ssize_t online_store(struct device *dev, const struct device_attribute *attr, const char *buf, size_t count) { bool val; @@ -2810,9 +2880,9 @@ static ssize_t online_store(struct device *dev, struct device_attribute *attr, unlock_device_hotplug(); return ret < 0 ? ret : count; } -static DEVICE_ATTR_RW(online); +static const DEVICE_ATTR_RW(online); -static ssize_t removable_show(struct device *dev, struct device_attribute *attr, +static ssize_t removable_show(struct device *dev, const struct device_attribute *attr, char *buf) { const char *loc; @@ -2829,7 +2899,7 @@ static ssize_t removable_show(struct device *dev, struct device_attribute *attr, } return sysfs_emit(buf, "%s\n", loc); } -static DEVICE_ATTR_RO(removable); +static const DEVICE_ATTR_RO(removable); int device_add_groups(struct device *dev, const struct attribute_group *const *groups) @@ -2913,7 +2983,7 @@ static int device_add_attrs(struct device *dev) if (error) goto err_remove_type_groups; - if (device_supports_offline(dev) && !dev->offline_disabled) { + if (device_supports_offline(dev) && !dev_offline_disabled(dev)) { error = device_create_file(dev, &dev_attr_online); if (error) goto err_remove_dev_groups; @@ -2980,12 +3050,12 @@ static void device_remove_attrs(struct device *dev) device_remove_groups(dev, class->dev_groups); } -static ssize_t dev_show(struct device *dev, struct device_attribute *attr, +static ssize_t dev_show(struct device *dev, const struct device_attribute *attr, char *buf) { return print_dev_t(buf, dev->devt); } -static DEVICE_ATTR_RO(dev); +static const DEVICE_ATTR_RO(dev); /* /sys/devices/ */ struct kset *devices_kset; @@ -3047,10 +3117,10 @@ int device_create_file(struct device *dev, int error = 0; if (dev) { - WARN(((attr->attr.mode & S_IWUGO) && !attr->store), + WARN(((attr->attr.mode & S_IWUGO) && !(attr->store || attr->store_const)), "Attribute %s: write permission without 'store'\n", attr->attr.name); - WARN(((attr->attr.mode & S_IRUGO) && !attr->show), + WARN(((attr->attr.mode & S_IRUGO) && !(attr->show || attr->show_const)), "Attribute %s: read permission without 'show'\n", attr->attr.name); error = sysfs_create_file(&dev->kobj, &attr->attr); @@ -3170,11 +3240,7 @@ void device_initialize(struct device *dev) INIT_LIST_HEAD(&dev->links.suppliers); INIT_LIST_HEAD(&dev->links.defer_sync); dev->links.status = DL_DEV_NO_DRIVER; -#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) - dev->dma_coherent = dma_default_coherent; -#endif + dev_assign_dma_coherent(dev, dma_default_coherent); swiotlb_dev_init(dev); } EXPORT_SYMBOL_GPL(device_initialize); @@ -3710,7 +3776,7 @@ int device_add(struct device *dev) * match with any driver, don't block its consumers from probing in * case the consumer device is able to operate without this supplier. */ - if (dev->fwnode && fw_devlink_drv_reg_done && !dev->can_match) + if (dev->fwnode && fw_devlink_drv_reg_done && !dev_can_match(dev)) fw_devlink_unblock_consumers(dev); if (parent) @@ -4180,7 +4246,7 @@ static int device_check_offline(struct device *dev, void *not_used) if (ret) return ret; - return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0; + return device_supports_offline(dev) && !dev_offline(dev) ? -EBUSY : 0; } /** @@ -4198,7 +4264,7 @@ int device_offline(struct device *dev) { int ret; - if (dev->offline_disabled) + if (dev_offline_disabled(dev)) return -EPERM; ret = device_for_each_child(dev, NULL, device_check_offline); @@ -4207,13 +4273,13 @@ int device_offline(struct device *dev) device_lock(dev); if (device_supports_offline(dev)) { - if (dev->offline) { + if (dev_offline(dev)) { ret = 1; } else { ret = dev->bus->offline(dev); if (!ret) { kobject_uevent(&dev->kobj, KOBJ_OFFLINE); - dev->offline = true; + dev_set_offline(dev); } } } @@ -4238,11 +4304,11 @@ int device_online(struct device *dev) device_lock(dev); if (device_supports_offline(dev)) { - if (dev->offline) { + if (dev_offline(dev)) { ret = dev->bus->online(dev); if (!ret) { kobject_uevent(&dev->kobj, KOBJ_ONLINE); - dev->offline = false; + dev_clear_offline(dev); } } else { ret = 1; @@ -4716,7 +4782,7 @@ static int device_attrs_change_owner(struct device *dev, kuid_t kuid, if (error) return error; - if (device_supports_offline(dev) && !dev->offline_disabled) { + if (device_supports_offline(dev) && !dev_offline_disabled(dev)) { /* Change online device attributes of @dev to @kuid/@kgid. */ error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name, kuid, kgid); @@ -5283,7 +5349,7 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2) { of_node_put(dev->of_node); dev->of_node = of_node_get(dev2->of_node); - dev->of_node_reused = true; + dev_set_of_node_reused(dev); } EXPORT_SYMBOL_GPL(device_set_of_node_from_dev); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 875abdc9942e..19d288a3c80c 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -422,8 +422,8 @@ int register_cpu(struct cpu *cpu, int num) cpu->dev.id = num; cpu->dev.bus = &cpu_subsys; cpu->dev.release = cpu_device_release; - cpu->dev.offline_disabled = !cpu->hotpluggable; - cpu->dev.offline = !cpu_online(num); + dev_assign_offline_disabled(&cpu->dev, !cpu->hotpluggable); + dev_assign_offline(&cpu->dev, !cpu_online(num)); cpu->dev.of_node = of_get_cpu_node(num, NULL); cpu->dev.groups = common_cpu_attr_groups; if (cpu->hotpluggable) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1dc1e3528043..60c005223844 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -132,7 +132,7 @@ static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func); void driver_deferred_probe_add(struct device *dev) { - if (!dev->can_match) + if (!dev_can_match(dev)) return; mutex_lock(&deferred_probe_mutex); @@ -323,12 +323,11 @@ void deferred_probe_extend_timeout(void) * If the work hasn't been queued yet or if the work expired, don't * start a new one. */ - if (cancel_delayed_work(&deferred_probe_timeout_work)) { - schedule_delayed_work(&deferred_probe_timeout_work, - driver_deferred_probe_timeout * HZ); + if (delayed_work_pending(&deferred_probe_timeout_work) && + mod_delayed_work(system_percpu_wq, &deferred_probe_timeout_work, + secs_to_jiffies(driver_deferred_probe_timeout))) pr_debug("Extended deferred probe timeout by %d secs\n", driver_deferred_probe_timeout); - } } /** @@ -569,12 +568,10 @@ static ssize_t state_synced_store(struct device *dev, return -EINVAL; device_lock(dev); - if (!dev->state_synced) { - dev->state_synced = true; + if (!dev_test_and_set_state_synced(dev)) dev_sync_state(dev); - } else { + else ret = -EINVAL; - } device_unlock(dev); return ret ? ret : count; @@ -586,7 +583,7 @@ static ssize_t state_synced_show(struct device *dev, bool val; device_lock(dev); - val = dev->state_synced; + val = dev_state_synced(dev); device_unlock(dev); return sysfs_emit(buf, "%u\n", val); @@ -595,9 +592,9 @@ static DEVICE_ATTR_RW(state_synced); static void device_unbind_cleanup(struct device *dev) { - devres_release_all(dev); if (dev->driver->p_cb.post_unbind_rust) dev->driver->p_cb.post_unbind_rust(dev); + devres_release_all(dev); arch_teardown_dma_ops(dev); kfree(dev->dma_range_map); dev->dma_range_map = NULL; @@ -849,14 +846,14 @@ static int __driver_probe_device(const struct device_driver *drv, struct device return dev_err_probe(dev, -EPROBE_DEFER, "Device not ready to probe\n"); /* - * Set can_match = true after calling dev_ready_to_probe(), so + * Call dev_set_can_match() after calling dev_ready_to_probe(), so * driver_deferred_probe_add() won't actually add the device to the * deferred probe list when dev_ready_to_probe() returns false. * * When dev_ready_to_probe() returns false, it means that device_add() * will do another probe() attempt for us. */ - dev->can_match = true; + dev_set_can_match(dev); dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n", drv->bus->name, __func__, drv->name); @@ -1002,7 +999,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data) return 0; } else if (ret == -EPROBE_DEFER) { dev_dbg(dev, "Device match requests probe deferral\n"); - dev->can_match = true; + dev_set_can_match(dev); driver_deferred_probe_add(dev); /* * Device can't match with a driver right now, so don't attempt @@ -1254,7 +1251,7 @@ static int __driver_attach(struct device *dev, void *data) return 0; } else if (ret == -EPROBE_DEFER) { dev_dbg(dev, "Device match requests probe deferral\n"); - dev->can_match = true; + dev_set_can_match(dev); driver_deferred_probe_add(dev); /* * Driver could not match with device, but may match with diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c index 7e4a491bf15e..8bb1763083dd 100644 --- a/drivers/base/devcoredump.c +++ b/drivers/base/devcoredump.c @@ -471,10 +471,3 @@ static int __init devcoredump_init(void) return class_register(&devcd_class); } __initcall(devcoredump_init); - -static void __exit devcoredump_exit(void) -{ - class_for_each_device(&devcd_class, NULL, NULL, devcd_free); - class_unregister(&devcd_class); -} -__exitcall(devcoredump_exit); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 8ab010ddf709..5d9c39081339 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -31,81 +31,6 @@ static struct device *next_device(struct klist_iter *i) } /** - * driver_set_override() - Helper to set or clear driver override. - * @dev: Device to change - * @override: Address of string to change (e.g. &device->driver_override); - * The contents will be freed and hold newly allocated override. - * @s: NUL-terminated string, new driver name to force a match, pass empty - * string to clear it ("" or "\n", where the latter is only for sysfs - * interface). - * @len: length of @s - * - * Helper to set or clear driver override in a device, intended for the cases - * when the driver_override field is allocated by driver/bus code. - * - * Returns: 0 on success or a negative error code on failure. - */ -int driver_set_override(struct device *dev, const char **override, - const char *s, size_t len) -{ - const char *new, *old; - char *cp; - - if (!override || !s) - return -EINVAL; - - /* - * The stored value will be used in sysfs show callback (sysfs_emit()), - * which has a length limit of PAGE_SIZE and adds a trailing newline. - * Thus we can store one character less to avoid truncation during sysfs - * show. - */ - if (len >= (PAGE_SIZE - 1)) - return -EINVAL; - - /* - * Compute the real length of the string in case userspace sends us a - * bunch of \0 characters like python likes to do. - */ - len = strlen(s); - - if (!len) { - /* Empty string passed - clear override */ - device_lock(dev); - old = *override; - *override = NULL; - device_unlock(dev); - kfree(old); - - return 0; - } - - cp = strnchr(s, len, '\n'); - if (cp) - len = cp - s; - - new = kstrndup(s, len, GFP_KERNEL); - if (!new) - return -ENOMEM; - - device_lock(dev); - old = *override; - if (cp != s) { - *override = new; - } else { - /* "\n" passed - clear override */ - kfree(new); - *override = NULL; - } - device_unlock(dev); - - kfree(old); - - return 0; -} -EXPORT_SYMBOL_GPL(driver_set_override); - -/** * driver_for_each_device - Iterator for devices bound to a driver. * @drv: Driver we're iterating. * @start: Device to begin with @@ -203,13 +128,13 @@ void driver_remove_file(const struct device_driver *drv, EXPORT_SYMBOL_GPL(driver_remove_file); int driver_add_groups(const struct device_driver *drv, - const struct attribute_group **groups) + const struct attribute_group *const *groups) { return sysfs_create_groups(&drv->p->kobj, groups); } void driver_remove_groups(const struct device_driver *drv, - const struct attribute_group **groups) + const struct attribute_group *const *groups) { sysfs_remove_groups(&drv->p->kobj, groups); } diff --git a/drivers/base/faux.c b/drivers/base/faux.c index fb3e42f21362..a8329f88222e 100644 --- a/drivers/base/faux.c +++ b/drivers/base/faux.c @@ -133,6 +133,9 @@ struct faux_device *faux_device_create_with_groups(const char *name, struct device *dev; int ret; + if (!faux_bus_root) + return NULL; + faux_obj = kzalloc_obj(*faux_obj); if (!faux_obj) return NULL; @@ -232,34 +235,29 @@ EXPORT_SYMBOL_GPL(faux_device_destroy); int __init faux_bus_init(void) { + struct device *root; int ret; - faux_bus_root = kzalloc_obj(*faux_bus_root); - if (!faux_bus_root) - return -ENOMEM; - - dev_set_name(faux_bus_root, "faux"); - - ret = device_register(faux_bus_root); - if (ret) { - put_device(faux_bus_root); - return ret; - } + root = root_device_register("faux"); + if (IS_ERR(root)) + return PTR_ERR(root); ret = bus_register(&faux_bus_type); if (ret) - goto error_bus; + goto err_deregister_root; ret = driver_register(&faux_driver); if (ret) - goto error_driver; + goto err_deregister_bus; - return ret; + faux_bus_root = root; + + return 0; -error_driver: +err_deregister_bus: bus_unregister(&faux_bus_type); +err_deregister_root: + root_device_unregister(root); -error_bus: - device_unregister(faux_bus_root); return ret; } diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index a11b30dda23b..c96312ac2be7 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -1503,9 +1503,10 @@ static void device_cache_fw_images(void) mutex_lock(&fw_lock); fwc->state = FW_LOADER_START_CACHE; - dpm_for_each_dev(NULL, dev_cache_fw_image); mutex_unlock(&fw_lock); + dpm_for_each_dev(NULL, dev_cache_fw_image); + /* wait for completion of caching firmware for all devices */ async_synchronize_full_domain(&fw_cache_domain); diff --git a/drivers/base/firmware_loader/sysfs_upload.c b/drivers/base/firmware_loader/sysfs_upload.c index f59a7856934c..efc33294212f 100644 --- a/drivers/base/firmware_loader/sysfs_upload.c +++ b/drivers/base/firmware_loader/sysfs_upload.c @@ -343,7 +343,6 @@ firmware_upload_register(struct module *module, struct device *parent, goto free_fw_upload_priv; } fw_upload->priv = fw_sysfs; - fw_sysfs->fw_upload_priv = fw_upload_priv; fw_dev = &fw_sysfs->dev; ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv, NULL, 0, 0, @@ -351,10 +350,12 @@ firmware_upload_register(struct module *module, struct device *parent, if (ret != 0) { if (ret > 0) ret = -EINVAL; - goto free_fw_sysfs; + put_device(fw_dev); + goto free_fw_upload_priv; } fw_priv->is_paged_buf = true; fw_sysfs->fw_priv = fw_priv; + fw_sysfs->fw_upload_priv = fw_upload_priv; ret = device_add(fw_dev); if (ret) { @@ -365,9 +366,6 @@ firmware_upload_register(struct module *module, struct device *parent, return fw_upload; -free_fw_sysfs: - kfree(fw_sysfs); - free_fw_upload_priv: kfree(fw_upload_priv); diff --git a/drivers/base/isa.c b/drivers/base/isa.c index fd076cc63cb6..5887e4211f80 100644 --- a/drivers/base/isa.c +++ b/drivers/base/isa.c @@ -11,9 +11,7 @@ #include <linux/dma-mapping.h> #include <linux/isa.h> -static struct device isa_bus = { - .init_name = "isa" -}; +static struct device *isa_bus; struct isa_dev { struct device dev; @@ -131,7 +129,7 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) break; } - isa_dev->dev.parent = &isa_bus; + isa_dev->dev.parent = isa_bus; isa_dev->dev.bus = &isa_bus_type; dev_set_name(&isa_dev->dev, "%s.%u", @@ -169,9 +167,11 @@ static int __init isa_bus_init(void) error = bus_register(&isa_bus_type); if (!error) { - error = device_register(&isa_bus); - if (error) + isa_bus = root_device_register("isa"); + if (IS_ERR(isa_bus)) { + error = PTR_ERR(isa_bus); bus_unregister(&isa_bus_type); + } } return error; } diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 6981b55d582a..11d57cfa8d72 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -697,7 +697,7 @@ static int __add_memory_block(struct memory_block *memory) memory->dev.id = memory->start_section_nr / sections_per_block; memory->dev.release = memory_block_release; memory->dev.groups = memory_memblk_attr_groups; - memory->dev.offline = memory->state == MEM_OFFLINE; + dev_assign_offline(&memory->dev, memory->state == MEM_OFFLINE); ret = device_register(&memory->dev); if (ret) { diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c index 6e250272c843..0bbc83231234 100644 --- a/drivers/base/pinctrl.c +++ b/drivers/base/pinctrl.c @@ -24,7 +24,7 @@ int pinctrl_bind_pins(struct device *dev) { int ret; - if (dev->of_node_reused) + if (dev_of_node_reused(dev)) return 0; dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index a19dd22deef2..fb9120b0bcfe 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -870,7 +870,7 @@ struct platform_device *platform_device_register_full(const struct platform_devi pdev->dev.parent = pdevinfo->parent; pdev->dev.fwnode = pdevinfo->fwnode; pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode)); - pdev->dev.of_node_reused = pdevinfo->of_node_reused; + dev_assign_of_node_reused(&pdev->dev, pdevinfo->of_node_reused); if (pdevinfo->dma_mask) { pdev->platform_dma_mask = pdevinfo->dma_mask; @@ -915,11 +915,14 @@ EXPORT_SYMBOL_GPL(platform_device_register_full); * __platform_driver_register - register a driver for platform-level devices * @drv: platform driver structure * @owner: owning module/driver + * @mod_name: module name string */ -int __platform_driver_register(struct platform_driver *drv, struct module *owner) +int __platform_driver_register(struct platform_driver *drv, struct module *owner, + const char *mod_name) { drv->driver.owner = owner; drv->driver.bus = &platform_bus_type; + drv->driver.mod_name = mod_name; return driver_register(&drv->driver); } @@ -952,6 +955,7 @@ static int is_bound_to_driver(struct device *dev, void *driver) * @drv: platform driver structure * @probe: the driver probe routine, probably from an __init section * @module: module which will be the owner of the driver + * @mod_name: module name string * * Use this instead of platform_driver_register() when you know the device * is not hotpluggable and has already been registered, and you want to @@ -969,7 +973,8 @@ static int is_bound_to_driver(struct device *dev, void *driver) */ int __init_or_module __platform_driver_probe(struct platform_driver *drv, int (*probe)(struct platform_device *), - struct module *module) + struct module *module, + const char *mod_name) { int retval; @@ -997,7 +1002,7 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv, /* temporary section violation during probe() */ drv->probe = probe; - retval = __platform_driver_register(drv, module); + retval = __platform_driver_register(drv, module, mod_name); if (retval) return retval; @@ -1025,6 +1030,7 @@ EXPORT_SYMBOL_GPL(__platform_driver_probe); * @data: platform specific data for this platform device * @size: size of platform specific data * @module: module which will be the owner of the driver + * @mod_name: module name string * * Use this in legacy-style modules that probe hardware directly and * register a single platform device and corresponding platform driver. @@ -1035,7 +1041,7 @@ struct platform_device * __init_or_module __platform_create_bundle(struct platform_driver *driver, int (*probe)(struct platform_device *), struct resource *res, unsigned int n_res, - const void *data, size_t size, struct module *module) + const void *data, size_t size, struct module *module, const char *mod_name) { struct platform_device *pdev; int error; @@ -1058,7 +1064,7 @@ __platform_create_bundle(struct platform_driver *driver, if (error) goto err_pdev_put; - error = __platform_driver_probe(driver, probe, module); + error = __platform_driver_probe(driver, probe, module, mod_name); if (error) goto err_pdev_del; @@ -1078,6 +1084,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle); * @drivers: an array of drivers to register * @count: the number of drivers to register * @owner: module owning the drivers + * @mod_name: module name string * * Registers platform drivers specified by an array. On failure to register a * driver, all previously registered drivers will be unregistered. Callers of @@ -1087,7 +1094,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle); * Returns: 0 on success or a negative error code on failure. */ int __platform_register_drivers(struct platform_driver * const *drivers, - unsigned int count, struct module *owner) + unsigned int count, struct module *owner, const char *mod_name) { unsigned int i; int err; @@ -1095,7 +1102,7 @@ int __platform_register_drivers(struct platform_driver * const *drivers, for (i = 0; i < count; i++) { pr_debug("registering platform driver %ps\n", drivers[i]); - err = __platform_driver_register(drivers[i], owner); + err = __platform_driver_register(drivers[i], owner, mod_name); if (err < 0) { pr_err("failed to register platform driver %ps: %d\n", drivers[i], err); diff --git a/drivers/base/property.c b/drivers/base/property.c index 8e0148a37fff..e08eadd66f4f 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -1277,8 +1277,10 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, if (fwnode_ep.port != port) continue; - if (fwnode_ep.id == endpoint) + if (fwnode_ep.id == endpoint) { + fwnode_handle_put(best_ep); return ep; + } if (!endpoint_next) continue; diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index a19f8f722bc8..869228a65cb3 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -374,20 +374,28 @@ EXPORT_SYMBOL_GPL(property_entries_free); /* -------------------------------------------------------------------------- */ /* fwnode operations */ -static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode) +static struct swnode *swnode_get(struct swnode *swnode) { - struct swnode *swnode = to_swnode(fwnode); - kobject_get(&swnode->kobj); + return swnode; +} + +static void swnode_put(struct swnode *swnode) +{ + kobject_put(&swnode->kobj); +} + +static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode) +{ + struct swnode *swnode = swnode_get(to_swnode(fwnode)); + return &swnode->fwnode; } static void software_node_put(struct fwnode_handle *fwnode) { - struct swnode *swnode = to_swnode(fwnode); - - kobject_put(&swnode->kobj); + swnode_put(to_swnode(fwnode)); } static bool software_node_property_present(const struct fwnode_handle *fwnode, @@ -493,7 +501,7 @@ software_node_get_named_child_node(const struct fwnode_handle *fwnode, list_for_each_entry(child, &swnode->children, entry) { if (!strcmp(childname, kobject_name(&child->kobj))) { - kobject_get(&child->kobj); + swnode_get(child); return &child->fwnode; } } @@ -737,7 +745,7 @@ software_node_find_by_name(const struct software_node *parent, const char *name) swnode = kobj_to_swnode(k); if (parent == swnode->node->parent && swnode->node->name && !strcmp(name, swnode->node->name)) { - kobject_get(&swnode->kobj); + swnode_get(swnode); break; } swnode = NULL; @@ -835,13 +843,13 @@ swnode_register(const struct software_node *node, struct swnode *parent, parent ? &parent->kobj : NULL, "node%d", swnode->id); if (ret) { - kobject_put(&swnode->kobj); + swnode_put(swnode); return ERR_PTR(ret); } /* * Assign the flag only in the successful case, so - * the above kobject_put() won't mess up with properties. + * the above swnode_put() won't mess up with properties. */ swnode->allocated = allocated; @@ -978,7 +986,7 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode) if (!swnode) return; - kobject_put(&swnode->kobj); + swnode_put(swnode); } EXPORT_SYMBOL_GPL(fwnode_remove_software_node); @@ -1002,7 +1010,7 @@ int device_add_software_node(struct device *dev, const struct software_node *nod swnode = software_node_to_swnode(node); if (swnode) { - kobject_get(&swnode->kobj); + swnode_get(swnode); } else { ret = software_node_register(node); if (ret) @@ -1044,7 +1052,7 @@ void device_remove_software_node(struct device *dev) software_node_notify_remove(dev); set_secondary_fwnode(dev, NULL); - kobject_put(&swnode->kobj); + swnode_put(swnode); } EXPORT_SYMBOL_GPL(device_remove_software_node); @@ -1097,7 +1105,7 @@ void software_node_notify(struct device *dev) if (!swnode) return; - kobject_get(&swnode->kobj); + swnode_get(swnode); ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node"); if (ret) return; @@ -1119,11 +1127,11 @@ void software_node_notify_remove(struct device *dev) sysfs_remove_link(&swnode->kobj, dev_name(dev)); sysfs_remove_link(&dev->kobj, "software_node"); - kobject_put(&swnode->kobj); + swnode_put(swnode); if (swnode->managed) { set_secondary_fwnode(dev, NULL); - kobject_put(&swnode->kobj); + swnode_put(swnode); } } diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c index f735e0462c55..87070155b057 100644 --- a/drivers/bus/imx-weim.c +++ b/drivers/bus/imx-weim.c @@ -327,12 +327,6 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action, "Failed to setup timing for '%pOF'\n", rd->dn); if (!of_node_check_flag(rd->dn, OF_POPULATED)) { - /* - * Clear the flag before adding the device so that - * fw_devlink doesn't skip adding consumers to this - * device. - */ - fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE); if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) { dev_err(&pdev->dev, "Failed to create child device '%pOF'\n", diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c index 9196dc50a48d..d3d230247262 100644 --- a/drivers/cdx/cdx.c +++ b/drivers/cdx/cdx.c @@ -156,8 +156,6 @@ static int cdx_unregister_device(struct device *dev, } else { cdx_destroy_res_attr(cdx_dev, MAX_CDX_DEV_RESOURCES); debugfs_remove_recursive(cdx_dev->debugfs_dir); - kfree(cdx_dev->driver_override); - cdx_dev->driver_override = NULL; } /* @@ -268,6 +266,7 @@ static int cdx_bus_match(struct device *dev, const struct device_driver *drv) const struct cdx_driver *cdx_drv = to_cdx_driver(drv); const struct cdx_device_id *found_id = NULL; const struct cdx_device_id *ids; + int ret; if (cdx_dev->is_bus) return false; @@ -275,7 +274,8 @@ static int cdx_bus_match(struct device *dev, const struct device_driver *drv) ids = cdx_drv->match_id_table; /* When driver_override is set, only bind to the matching driver */ - if (cdx_dev->driver_override && strcmp(cdx_dev->driver_override, drv->name)) + ret = device_match_driver_override(dev, drv); + if (ret == 0) return false; found_id = cdx_match_id(ids, cdx_dev); @@ -289,7 +289,7 @@ static int cdx_bus_match(struct device *dev, const struct device_driver *drv) */ if (!found_id->override_only) return true; - if (cdx_dev->driver_override) + if (ret > 0) return true; ids = found_id + 1; @@ -453,36 +453,6 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(modalias); -static ssize_t driver_override_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cdx_device *cdx_dev = to_cdx_device(dev); - int ret; - - if (WARN_ON(dev->bus != &cdx_bus_type)) - return -EINVAL; - - ret = driver_set_override(dev, &cdx_dev->driver_override, buf, count); - if (ret) - return ret; - - return count; -} - -static ssize_t driver_override_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cdx_device *cdx_dev = to_cdx_device(dev); - ssize_t len; - - device_lock(dev); - len = sysfs_emit(buf, "%s\n", cdx_dev->driver_override); - device_unlock(dev); - return len; -} -static DEVICE_ATTR_RW(driver_override); - static ssize_t enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -552,7 +522,6 @@ static struct attribute *cdx_dev_attrs[] = { &dev_attr_class.attr, &dev_attr_revision.attr, &dev_attr_modalias.attr, - &dev_attr_driver_override.attr, NULL, }; @@ -646,6 +615,7 @@ ATTRIBUTE_GROUPS(cdx_bus); const struct bus_type cdx_bus_type = { .name = "cdx", + .driver_override = true, .match = cdx_bus_match, .probe = cdx_probe, .remove = cdx_remove, diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index f17bf64c22e2..10106fa13095 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -201,12 +201,13 @@ kernel::of_device_table!( impl platform::Driver for CPUFreqDTDriver { type IdInfo = (); + type Data<'bound> = Self; const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); - fn probe( - pdev: &platform::Device<Core>, - _id_info: Option<&Self::IdInfo>, - ) -> impl PinInit<Self, Error> { + fn probe<'bound>( + pdev: &'bound platform::Device<Core<'_>>, + _id_info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit<Self, Error> + 'bound { cpufreq::Registration::<CPUFreqDTDriver>::new_foreign_owned(pdev.as_ref())?; Ok(Self {}) } diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c index 179de3cf6d6c..9e183cd8818c 100644 --- a/drivers/devfreq/devfreq-event.c +++ b/drivers/devfreq/devfreq-event.c @@ -17,7 +17,13 @@ #include <linux/list.h> #include <linux/of.h> -static struct class *devfreq_event_class; +static struct attribute *devfreq_event_attrs[]; +ATTRIBUTE_GROUPS(devfreq_event); + +static const struct class devfreq_event_class = { + .name = "devfreq-event", + .dev_groups = devfreq_event_groups +}; /* The list of all devfreq event list */ static LIST_HEAD(devfreq_event_list); @@ -321,7 +327,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, edev->desc = desc; edev->enable_count = 0; edev->dev.parent = dev; - edev->dev.class = devfreq_event_class; + edev->dev.class = &devfreq_event_class; edev->dev.release = devfreq_event_release_edev; dev_set_name(&edev->dev, "event%d", atomic_inc_return(&event_no)); @@ -461,18 +467,15 @@ static struct attribute *devfreq_event_attrs[] = { &dev_attr_enable_count.attr, NULL, }; -ATTRIBUTE_GROUPS(devfreq_event); static int __init devfreq_event_init(void) { - devfreq_event_class = class_create("devfreq-event"); - if (IS_ERR(devfreq_event_class)) { - pr_err("%s: couldn't create class\n", __FILE__); - return PTR_ERR(devfreq_event_class); - } + int err; - devfreq_event_class->dev_groups = devfreq_event_groups; + err = class_register(&devfreq_event_class); + if (err) + pr_err("%s: couldn't create class\n", __FILE__); - return 0; + return err; } subsys_initcall(devfreq_event_init); diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c index f87d244cc2d6..686dc140293e 100644 --- a/drivers/dma/ti/k3-udma-glue.c +++ b/drivers/dma/ti/k3-udma-glue.c @@ -312,7 +312,7 @@ k3_udma_glue_request_tx_chn_common(struct device *dev, if (xudma_is_pktdma(tx_chn->common.udmax)) { /* prepare the channel device as coherent */ - tx_chn->common.chan_dev.dma_coherent = true; + dev_set_dma_coherent(&tx_chn->common.chan_dev); dma_coerce_mask_and_coherent(&tx_chn->common.chan_dev, DMA_BIT_MASK(48)); } @@ -1003,7 +1003,7 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name, if (xudma_is_pktdma(rx_chn->common.udmax)) { /* prepare the channel device as coherent */ - rx_chn->common.chan_dev.dma_coherent = true; + dev_set_dma_coherent(&rx_chn->common.chan_dev); dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev, DMA_BIT_MASK(48)); } @@ -1104,7 +1104,7 @@ k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn if (xudma_is_pktdma(rx_chn->common.udmax)) { /* prepare the channel device as coherent */ - rx_chn->common.chan_dev.dma_coherent = true; + dev_set_dma_coherent(&rx_chn->common.chan_dev); dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev, DMA_BIT_MASK(48)); rx_chn->single_fdq = false; diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index c964ebfcf3b6..1cf158eb7bdb 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -428,18 +428,18 @@ static void k3_configure_chan_coherency(struct dma_chan *chan, u32 asel) /* No special handling for the channel */ chan->dev->chan_dma_dev = false; - chan_dev->dma_coherent = false; + dev_clear_dma_coherent(chan_dev); chan_dev->dma_parms = NULL; } else if (asel == 14 || asel == 15) { chan->dev->chan_dma_dev = true; - chan_dev->dma_coherent = true; + dev_set_dma_coherent(chan_dev); dma_coerce_mask_and_coherent(chan_dev, DMA_BIT_MASK(48)); chan_dev->dma_parms = chan_dev->parent->dma_parms; } else { dev_warn(chan->device->dev, "Invalid ASEL value: %u\n", asel); - chan_dev->dma_coherent = false; + dev_clear_dma_coherent(chan_dev); chan_dev->dma_parms = NULL; } } diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index b1af0a099551..aa08644012f7 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -51,9 +51,13 @@ kernel::auxiliary_device_table!( impl auxiliary::Driver for NovaDriver { type IdInfo = (); + type Data<'bound> = Self; const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE; - fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { + fn probe<'bound>( + adev: &'bound auxiliary::Device<Core<'_>>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit<Self, Error> + 'bound { let data = try_pin_init!(NovaData { adev: adev.into() }); let drm = drm::Device::<Self>::new(adev.as_ref(), data)?; diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index 279710b36a10..04f83fcf0937 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -37,7 +37,7 @@ use crate::{ regs, // }; -pub(crate) type IoMem = kernel::io::mem::IoMem<SZ_2M>; +pub(crate) type IoMem = kernel::io::mem::IoMem<'static, SZ_2M>; pub(crate) struct TyrDrmDriver; @@ -91,12 +91,13 @@ kernel::of_device_table!( impl platform::Driver for TyrPlatformDriverData { type IdInfo = (); + type Data<'bound> = Self; const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); - fn probe( - pdev: &platform::Device<Core>, - _info: Option<&Self::IdInfo>, - ) -> impl PinInit<Self, Error> { + fn probe<'bound>( + pdev: &'bound platform::Device<Core<'_>>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit<Self, Error> + 'bound { let core_clk = Clk::get(pdev.as_ref(), Some(c"core"))?; let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c"stacks"))?; let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c"coregroup"))?; @@ -109,7 +110,7 @@ impl platform::Driver for TyrPlatformDriverData { let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"sram")?; let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; - let iomem = Arc::pin_init(request.iomap_sized::<SZ_2M>(), GFP_KERNEL)?; + let iomem = Arc::new(request.iomap_sized::<SZ_2M>()?.into_devres()?, GFP_KERNEL)?; issue_soft_reset(pdev.as_ref(), &iomem)?; gpu::l2_power_on(pdev.as_ref(), &iomem)?; diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs index 84b0e1703150..d3f2245ba2e0 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -3,7 +3,6 @@ use kernel::{ auxiliary, device::Core, - devres::Devres, dma::Device, dma::DmaMask, pci, @@ -21,6 +20,7 @@ use kernel::{ }, Arc, }, + types::ForLt, }; use crate::gpu::Gpu; @@ -29,13 +29,15 @@ use crate::gpu::Gpu; static AUXILIARY_ID_COUNTER: Atomic<u32> = Atomic::new(0); #[pin_data] -pub(crate) struct NovaCore { +pub(crate) struct NovaCore<'bound> { #[pin] pub(crate) gpu: Gpu, - #[pin] - _reg: Devres<auxiliary::Registration>, + #[allow(clippy::type_complexity)] + _reg: auxiliary::Registration<'bound, ForLt!(())>, } +pub(crate) struct NovaCoreDriver; + const BAR0_SIZE: usize = SZ_16M; // For now we only support Ampere which can use up to 47-bit DMA addresses. @@ -46,12 +48,12 @@ const BAR0_SIZE: usize = SZ_16M; // DMA addresses. These systems should be quite rare. const GPU_DMA_BITS: u32 = 47; -pub(crate) type Bar0 = pci::Bar<BAR0_SIZE>; +pub(crate) type Bar0 = pci::Bar<'static, BAR0_SIZE>; kernel::pci_device_table!( PCI_TABLE, MODULE_PCI_TABLE, - <NovaCore as pci::Driver>::IdInfo, + <NovaCoreDriver as pci::Driver>::IdInfo, [ // Modern NVIDIA GPUs will show up as either VGA or 3D controllers. ( @@ -73,11 +75,15 @@ kernel::pci_device_table!( ] ); -impl pci::Driver for NovaCore { +impl pci::Driver for NovaCoreDriver { type IdInfo = (); + type Data<'bound> = NovaCore<'bound>; const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; - fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { + fn probe<'bound>( + pdev: &'bound pci::Device<Core<'_>>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound { pin_init::pin_init_scope(move || { dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); @@ -89,26 +95,28 @@ impl pci::Driver for NovaCore { // other threads of execution. unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? }; - let bar = Arc::pin_init( - pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0"), + let bar = Arc::new( + pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")? + .into_devres()?, GFP_KERNEL, )?; - Ok(try_pin_init!(Self { + Ok(try_pin_init!(NovaCore { gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?), - _reg <- auxiliary::Registration::new( + _reg: auxiliary::Registration::new( pdev.as_ref(), c"nova-drm", // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. For // now, use a simple atomic counter that never recycles IDs. AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed), - crate::MODULE_NAME - ), + crate::MODULE_NAME, + (), + )?, })) }) } - fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) { + fn unbind<'bound>(pdev: &'bound pci::Device<Core<'_>>, this: Pin<&Self::Data<'bound>>) { this.gpu.unbind(pdev.as_ref()); } } diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 0f6fe9a1b955..4ffb506342a9 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -278,7 +278,7 @@ impl Gpu { /// Called when the corresponding [`Device`](device::Device) is unbound. /// /// Note: This method must only be called from `Driver::unbind`. - pub(crate) fn unbind(&self, dev: &device::Device<device::Core>) { + pub(crate) fn unbind(&self, dev: &device::Device<device::Core<'_>>) { kernel::warn_on!(self .bar .access(dev) diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs index 04a1fa6b25f8..073d87714d3a 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -47,7 +47,7 @@ struct NovaCoreModule { // Fields are dropped in declaration order, so `_driver` is dropped first, // then `_debugfs_guard` clears `DEBUGFS_ROOT`. #[pin] - _driver: Registration<pci::Adapter<driver::NovaCore>>, + _driver: Registration<pci::Adapter<driver::NovaCoreDriver>>, _debugfs_guard: DebugfsRootGuard, } diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index b80a35c778ab..23206640c613 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -548,34 +548,6 @@ static ssize_t device_show(struct device *dev, } static DEVICE_ATTR_RO(device); -static ssize_t driver_override_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hv_device *hv_dev = device_to_hv_device(dev); - int ret; - - ret = driver_set_override(dev, &hv_dev->driver_override, buf, count); - if (ret) - return ret; - - return count; -} - -static ssize_t driver_override_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hv_device *hv_dev = device_to_hv_device(dev); - ssize_t len; - - device_lock(dev); - len = sysfs_emit(buf, "%s\n", hv_dev->driver_override); - device_unlock(dev); - - return len; -} -static DEVICE_ATTR_RW(driver_override); - /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */ static struct attribute *vmbus_dev_attrs[] = { &dev_attr_id.attr, @@ -606,7 +578,6 @@ static struct attribute *vmbus_dev_attrs[] = { &dev_attr_channel_vp_mapping.attr, &dev_attr_vendor.attr, &dev_attr_device.attr, - &dev_attr_driver_override.attr, NULL, }; @@ -718,9 +689,11 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(const struct hv_driver * { const guid_t *guid = &dev->dev_type; const struct hv_vmbus_device_id *id; + int ret; - /* When driver_override is set, only bind to the matching driver */ - if (dev->driver_override && strcmp(dev->driver_override, drv->name)) + /* If a driver override is set, only bind to the matching driver */ + ret = device_match_driver_override(&dev->device, &drv->driver); + if (ret == 0) return NULL; /* Look at the dynamic ids first, before the static ones */ @@ -728,8 +701,11 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(const struct hv_driver * if (!id) id = hv_vmbus_dev_match(drv->id_table, guid); - /* driver_override will always match, send a dummy id */ - if (!id && dev->driver_override) + /* + * If there's a matching driver override, this function should succeed, + * thus return a dummy device ID if no matching ID is found. + */ + if (!id && ret > 0) id = &vmbus_device_null; return id; @@ -1031,6 +1007,7 @@ static const struct dev_pm_ops vmbus_pm = { /* The one and only one */ static const struct bus_type hv_bus = { .name = "vmbus", + .driver_override = true, .match = vmbus_match, .shutdown = vmbus_shutdown, .remove = vmbus_remove, diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index ce71dcddfca2..0c8698c8fc5e 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -706,7 +706,7 @@ static int __init catu_init(void) { int ret; - ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver, THIS_MODULE); + ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver); tmc_etr_set_catu_ops(&etr_catu_buf_ops); return ret; } diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 46f247f73cf6..94ee24afdc6d 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1694,8 +1694,9 @@ static void __exit coresight_exit(void) module_init(coresight_init); module_exit(coresight_exit); -int coresight_init_driver(const char *drv, struct amba_driver *amba_drv, - struct platform_driver *pdev_drv, struct module *owner) +int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_drv, + struct platform_driver *pdev_drv, struct module *owner, + const char *mod_name) { int ret; @@ -1705,7 +1706,7 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv, return ret; } - ret = __platform_driver_register(pdev_drv, owner); + ret = __platform_driver_register(pdev_drv, owner, mod_name); if (!ret) return 0; @@ -1713,7 +1714,7 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv, amba_driver_unregister(amba_drv); return ret; } -EXPORT_SYMBOL_GPL(coresight_init_driver); +EXPORT_SYMBOL_GPL(coresight_init_driver_with_owner); void coresight_remove_driver(struct amba_driver *amba_drv, struct platform_driver *pdev_drv) diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 629614278e46..3a806c1d50ea 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -757,8 +757,7 @@ static struct platform_driver debug_platform_driver = { static int __init debug_init(void) { - return coresight_init_driver("debug", &debug_driver, &debug_platform_driver, - THIS_MODULE); + return coresight_init_driver("debug", &debug_driver, &debug_platform_driver); } static void __exit debug_exit(void) diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 3f56ceccd8c9..0abc11f0690c 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -412,8 +412,7 @@ static struct amba_driver dynamic_funnel_driver = { static int __init funnel_init(void) { - return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver, - THIS_MODULE); + return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver); } static void __exit funnel_exit(void) diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 07fc04f53b88..2f382de357ee 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -418,8 +418,7 @@ static struct amba_driver dynamic_replicator_driver = { static int __init replicator_init(void) { - return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver, - THIS_MODULE); + return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver); } static void __exit replicator_exit(void) diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index aca6cec7885a..4e860519a73f 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -1050,7 +1050,7 @@ static struct platform_driver stm_platform_driver = { static int __init stm_init(void) { - return coresight_init_driver("stm", &stm_driver, &stm_platform_driver, THIS_MODULE); + return coresight_init_driver("stm", &stm_driver, &stm_platform_driver); } static void __exit stm_exit(void) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index c89fe996af23..bc5a133ada3e 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -1046,7 +1046,7 @@ static struct platform_driver tmc_platform_driver = { static int __init tmc_init(void) { - return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver, THIS_MODULE); + return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver); } static void __exit tmc_exit(void) diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c index 96a25877b824..9e8de4323d28 100644 --- a/drivers/hwtracing/coresight/coresight-tnoc.c +++ b/drivers/hwtracing/coresight/coresight-tnoc.c @@ -344,7 +344,7 @@ static struct platform_driver itnoc_driver = { static int __init tnoc_init(void) { - return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver, THIS_MODULE); + return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver); } static void __exit tnoc_exit(void) diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index eaf7210af648..8464edbba2d4 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -1563,8 +1563,7 @@ static struct platform_driver static_tpdm_driver = { static int __init tpdm_init(void) { - return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver, - THIS_MODULE); + return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver); } static void __exit tpdm_exit(void) diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index b8560b140e0f..7b029d2eb389 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -310,7 +310,7 @@ static struct platform_driver tpiu_platform_driver = { static int __init tpiu_init(void) { - return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver, THIS_MODULE); + return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver); } static void __exit tpiu_exit(void) diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 354a88d0599e..30b48a428c0b 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -176,11 +176,6 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } - /* - * Clear the flag before adding the device so that fw_devlink - * doesn't skip adding consumers to this device. - */ - fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE); client = of_i2c_register_device(adap, rd->dn); if (IS_ERR(client)) { dev_err(&adap->dev, "failed to create client for '%pOF'\n", diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 381b60d9e7ce..9b1bf6c8c6b3 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -2149,18 +2149,21 @@ EXPORT_SYMBOL_GPL(dma_iova_destroy); void iommu_setup_dma_ops(struct device *dev, struct iommu_domain *domain) { + bool dma_iommu; + if (dev_is_pci(dev)) dev->iommu->pci_32bit_workaround = !iommu_dma_forcedac; - dev->dma_iommu = iommu_is_dma_domain(domain); - if (dev->dma_iommu && iommu_dma_init_domain(domain, dev)) + dma_iommu = iommu_is_dma_domain(domain); + dev_assign_dma_iommu(dev, dma_iommu); + if (dma_iommu && iommu_dma_init_domain(domain, dev)) goto out_err; return; out_err: pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", dev_name(dev)); - dev->dma_iommu = false; + dev_clear_dma_iommu(dev); } static bool has_msi_cookie(const struct iommu_domain *domain) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d1a9e713d3a0..e8f13dcebbde 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -611,9 +611,8 @@ static void iommu_deinit_device(struct device *dev) dev->iommu_group = NULL; module_put(ops->owner); dev_iommu_free(dev); -#ifdef CONFIG_IOMMU_DMA - dev->dma_iommu = false; -#endif + if (IS_ENABLED(CONFIG_IOMMU_DMA)) + dev_clear_dma_iommu(dev); } static struct iommu_domain *pasid_array_entry_to_domain(void *entry) diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c index b8c48f9effbf..f4b1b8246ce9 100644 --- a/drivers/net/pcs/pcs-xpcs-plat.c +++ b/drivers/net/pcs/pcs-xpcs-plat.c @@ -349,7 +349,7 @@ static int xpcs_plat_init_dev(struct dw_xpcs_plat *pxpcs) * up later. Make sure DD-core is aware of the OF-node being re-used. */ device_set_node(&mdiodev->dev, fwnode_handle_get(dev_fwnode(dev))); - mdiodev->dev.of_node_reused = true; + dev_set_of_node_reused(&mdiodev->dev); /* Pass the data further so the DW XPCS driver core could use it */ mdiodev->dev.platform_data = (void *)device_get_match_data(dev); diff --git a/drivers/of/device.c b/drivers/of/device.c index f7e75e527667..be4e1584e0af 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -26,7 +26,7 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches, const struct device *dev) { - if (!matches || !dev->of_node || dev->of_node_reused) + if (!matches || !dev->of_node || dev_of_node_reused(dev)) return NULL; return of_match_node(matches, dev->of_node); } @@ -192,7 +192,7 @@ ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) { ssize_t sl; - if (!dev || !dev->of_node || dev->of_node_reused) + if (!dev || !dev->of_node || dev_of_node_reused(dev)) return -ENODEV; sl = of_modalias(dev->of_node, str, len - 2); @@ -254,7 +254,7 @@ int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env * { int sl; - if ((!dev) || (!dev->of_node) || dev->of_node_reused) + if ((!dev) || (!dev->of_node) || dev_of_node_reused(dev)) return -ENODEV; /* Devicetree modalias is tricky, we add it in 2 steps */ diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index ade288372101..aa450425ec1e 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -225,7 +225,6 @@ static void __of_attach_node(struct device_node *np) np->sibling = np->parent->child; np->parent->child = np; of_node_clear_flag(np, OF_DETACHED); - fwnode_set_flag(&np->fwnode, FWNODE_FLAG_NOT_DEVICE); raw_spin_unlock_irqrestore(&devtree_lock, flags); diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index c1c5686fc7b1..4e45f3414c2c 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -185,6 +185,15 @@ static int overlay_notify(struct overlay_changeset *ovcs, return 0; } +static void overlay_fw_devlink_refresh(struct overlay_changeset *ovcs) +{ + for (int i = 0; i < ovcs->count; i++) { + struct device_node *np = ovcs->fragments[i].target; + + fw_devlink_refresh_fwnode(of_fwnode_handle(np)); + } +} + /* * The values of properties in the "/__symbols__" node are paths in * the ovcs->overlay_root. When duplicating the properties, the paths @@ -951,6 +960,12 @@ static int of_overlay_apply(struct overlay_changeset *ovcs, pr_err("overlay apply changeset entry notify error %d\n", ret); /* notify failure is not fatal, continue */ + /* + * Needs to happen after changeset notify to give the listeners a chance + * to finish creating all the devices they need to create. + */ + overlay_fw_devlink_refresh(ovcs); + ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY); if (ret_tmp) if (!ret) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index a42224f9d1a8..53bca8c6f781 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -744,11 +744,6 @@ static int of_platform_notify(struct notifier_block *nb, if (of_node_check_flag(rd->dn, OF_POPULATED)) return NOTIFY_OK; - /* - * Clear the flag before adding the device so that fw_devlink - * doesn't skip adding consumers to this device. - */ - fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE); /* pdev_parent may be NULL when no bus platform device */ pdev_parent = of_find_device_by_node(parent); pdev = of_platform_device_create(rd->dn, NULL, diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 6da569fd3b8f..8b18c4ba845c 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -38,7 +38,7 @@ int pci_set_of_node(struct pci_dev *dev) struct device *pdev __free(put_device) = bus_find_device_by_of_node(&platform_bus_type, node); if (pdev) - dev->bus->dev.of_node_reused = true; + dev_set_of_node_reused(&dev->bus->dev); device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node))); return 0; diff --git a/drivers/pci/pwrctrl/core.c b/drivers/pci/pwrctrl/core.c index 97cff5b8ca88..31246bac84f1 100644 --- a/drivers/pci/pwrctrl/core.c +++ b/drivers/pci/pwrctrl/core.c @@ -39,7 +39,7 @@ static int pci_pwrctrl_notify(struct notifier_block *nb, unsigned long action, * If we got here then the PCI device is the second after the * power control platform device. Mark its OF node as reused. */ - dev->of_node_reused = true; + dev_set_of_node_reused(dev); break; } diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs index ddd44a5ce497..48808cd80737 100644 --- a/drivers/pwm/pwm_th1520.rs +++ b/drivers/pwm/pwm_th1520.rs @@ -92,7 +92,7 @@ struct Th1520WfHw { #[pin_data(PinnedDrop)] struct Th1520PwmDriverData { #[pin] - iomem: devres::Devres<IoMem<TH1520_PWM_REG_SIZE>>, + iomem: devres::Devres<IoMem<'static, TH1520_PWM_REG_SIZE>>, clk: Clk, } @@ -316,12 +316,13 @@ kernel::of_device_table!( impl platform::Driver for Th1520PwmPlatformDriver { type IdInfo = (); + type Data<'bound> = Self; const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); - fn probe( - pdev: &platform::Device<Core>, - _id_info: Option<&Self::IdInfo>, - ) -> impl PinInit<Self, Error> { + fn probe<'bound>( + pdev: &'bound platform::Device<Core<'_>>, + _id_info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit<Self, Error> + 'bound { let dev = pdev.as_ref(); let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; @@ -351,7 +352,7 @@ impl platform::Driver for Th1520PwmPlatformDriver { dev, TH1520_MAX_PWM_NUM, try_pin_init!(Th1520PwmDriverData { - iomem <- request.iomap_sized::<TH1520_PWM_REG_SIZE>(), + iomem <- request.iomap_sized::<TH1520_PWM_REG_SIZE>()?.into_devres(), clk <- clk, }), )?; diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 401a4ece0c97..d9d4468e4cbd 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1626,7 +1626,6 @@ static void qcom_glink_rpdev_release(struct device *dev) { struct rpmsg_device *rpdev = to_rpmsg_device(dev); - kfree(rpdev->driver_override); kfree(rpdev); } @@ -1862,7 +1861,6 @@ static void qcom_glink_device_release(struct device *dev) /* Release qcom_glink_alloc_channel() reference */ kref_put(&channel->refcount, qcom_glink_channel_release); - kfree(rpdev->driver_override); kfree(rpdev); } diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index e7f7831d37f8..c56f69c22e42 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -358,33 +358,6 @@ rpmsg_show_attr(src, src, "0x%x\n"); rpmsg_show_attr(dst, dst, "0x%x\n"); rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); -static ssize_t driver_override_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct rpmsg_device *rpdev = to_rpmsg_device(dev); - int ret; - - ret = driver_set_override(dev, &rpdev->driver_override, buf, count); - if (ret) - return ret; - - return count; -} - -static ssize_t driver_override_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct rpmsg_device *rpdev = to_rpmsg_device(dev); - ssize_t len; - - device_lock(dev); - len = sysfs_emit(buf, "%s\n", rpdev->driver_override); - device_unlock(dev); - return len; -} -static DEVICE_ATTR_RW(driver_override); - static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -405,7 +378,6 @@ static struct attribute *rpmsg_dev_attrs[] = { &dev_attr_dst.attr, &dev_attr_src.attr, &dev_attr_announce.attr, - &dev_attr_driver_override.attr, NULL, }; ATTRIBUTE_GROUPS(rpmsg_dev); @@ -424,9 +396,11 @@ static int rpmsg_dev_match(struct device *dev, const struct device_driver *drv) const struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv); const struct rpmsg_device_id *ids = rpdrv->id_table; unsigned int i; + int ret; - if (rpdev->driver_override) - return !strcmp(rpdev->driver_override, drv->name); + ret = device_match_driver_override(dev, drv); + if (ret >= 0) + return ret; if (ids) for (i = 0; ids[i].name[0]; i++) @@ -535,6 +509,7 @@ static const struct bus_type rpmsg_bus = { .name = "rpmsg", .match = rpmsg_dev_match, .dev_groups = rpmsg_dev_groups, + .driver_override = true, .uevent = rpmsg_uevent, .probe = rpmsg_dev_probe, .remove = rpmsg_dev_remove, @@ -560,11 +535,9 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev, device_initialize(dev); if (driver_override) { - ret = driver_set_override(dev, &rpdev->driver_override, - driver_override, - strlen(driver_override)); + ret = device_set_driver_override(dev, driver_override); if (ret) { - dev_err(dev, "device_set_override failed: %d\n", ret); + dev_err(dev, "device_set_driver_override() failed: %d\n", ret); put_device(dev); return ret; } @@ -573,8 +546,6 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev, ret = device_add(dev); if (ret) { dev_err(dev, "device_add failed: %d\n", ret); - kfree(rpdev->driver_override); - rpdev->driver_override = NULL; put_device(dev); } diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 5ae15111fb4f..1b8bb05924af 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -374,7 +374,6 @@ static void virtio_rpmsg_release_device(struct device *dev) struct rpmsg_device *rpdev = to_rpmsg_device(dev); struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); - kfree(rpdev->driver_override); kfree(vch); } diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c index ab75d50cc85c..2f69e104c838 100644 --- a/drivers/soc/tegra/cbb/tegra194-cbb.c +++ b/drivers/soc/tegra/cbb/tegra194-cbb.c @@ -2342,7 +2342,7 @@ static int __init tegra194_cbb_init(void) { return platform_driver_register(&tegra194_cbb_driver); } -pure_initcall(tegra194_cbb_init); +core_initcall(tegra194_cbb_init); static void __exit tegra194_cbb_exit(void) { diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index fb26f085f691..785072fa4e85 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -1774,7 +1774,7 @@ static int __init tegra234_cbb_init(void) { return platform_driver_register(&tegra234_cbb_driver); } -pure_initcall(tegra234_cbb_init); +core_initcall(tegra234_cbb_init); static void __exit tegra234_cbb_exit(void) { diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 104279858f56..889e1eecc757 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -5003,11 +5003,6 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } - /* - * Clear the flag before adding the device so that fw_devlink - * doesn't skip adding consumers to this device. - */ - fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE); spi = of_register_spi_device(ctlr, rd->dn); put_device(&ctlr->dev); diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c index a12935f6b992..5f23284a8778 100644 --- a/drivers/tty/serial/serial_base_bus.c +++ b/drivers/tty/serial/serial_base_bus.c @@ -74,7 +74,7 @@ static int serial_base_device_init(struct uart_port *port, dev->parent = parent_dev; dev->bus = &serial_base_bus_type; dev->release = release; - dev->of_node_reused = true; + dev_set_of_node_reused(dev); device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev))); diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 2ecd049dacc2..8b9449d16324 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -593,7 +593,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) d->gadget.max_speed = USB_SPEED_HIGH; d->gadget.speed = USB_SPEED_UNKNOWN; d->gadget.dev.of_node = vhub->pdev->dev.of_node; - d->gadget.dev.of_node_reused = true; + dev_set_of_node_reused(&d->gadget.dev); rc = usb_add_gadget_udc(d->port_dev, &d->gadget); if (rc != 0) |
