Skip to content

Commit 3ae7f50

Browse files
committed
Merge tag 'driver-core-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core fixes from Greg KH: "Here are some small driver core fixes to resolve a number of reported problems. Included in here are: - driver core sync fix revert to resolve a much reported problem, hopefully this is finally resolved - MAINTAINERS file update, documenting that the driver-core tree is now under a "shared" maintainership model, thanks to Rafael and Danilo for offering to do this! - auxbus documentation and MAINTAINERS file update - MAINTAINERS file update for Rust PCI code - firmware rust binding fixup - software node link fix All of these have been in linux-next for over a week with no reported issues" * tag 'driver-core-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: drivers/base/memory: Avoid overhead from for_each_present_section_nr() software node: Prevent link creation failure from causing kobj reference count imbalance device property: Add a note to the fwnode.h drivers/base: Add myself as auxiliary bus reviewer drivers/base: Extend documentation with preferred way to use auxbus driver core: fix potential NULL pointer dereference in dev_uevent() driver core: introduce device_set_driver() helper Revert "drivers: core: synchronize really_probe() and dev_uevent()" MAINTAINERS: update the location of the driver-core git tree rust: firmware: Use `ffi::c_char` type in `FwFunc` MAINTAINERS: pci: add entry for Rust PCI code
2 parents 882cd65 + b9792ab commit 3ae7f50

File tree

10 files changed

+106
-42
lines changed

10 files changed

+106
-42
lines changed

MAINTAINERS

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3873,8 +3873,9 @@ AUXILIARY BUS DRIVER
38733873
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
38743874
R: Dave Ertman <david.m.ertman@intel.com>
38753875
R: Ira Weiny <ira.weiny@intel.com>
3876+
R: Leon Romanovsky <leon@kernel.org>
38763877
S: Supported
3877-
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
3878+
T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
38783879
F: Documentation/driver-api/auxiliary_bus.rst
38793880
F: drivers/base/auxiliary.c
38803881
F: include/linux/auxiliary_bus.h
@@ -7233,7 +7234,7 @@ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
72337234
M: "Rafael J. Wysocki" <rafael@kernel.org>
72347235
M: Danilo Krummrich <dakr@kernel.org>
72357236
S: Supported
7236-
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
7237+
T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
72377238
F: Documentation/core-api/kobject.rst
72387239
F: drivers/base/
72397240
F: fs/debugfs/
@@ -13118,7 +13119,7 @@ KERNFS
1311813119
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1311913120
M: Tejun Heo <tj@kernel.org>
1312013121
S: Supported
13121-
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
13122+
T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
1312213123
F: fs/kernfs/
1312313124
F: include/linux/kernfs.h
1312413125

@@ -18750,6 +18751,16 @@ F: include/asm-generic/pci*
1875018751
F: include/linux/of_pci.h
1875118752
F: include/linux/pci*
1875218753
F: include/uapi/linux/pci*
18754+
18755+
PCI SUBSYSTEM [RUST]
18756+
M: Danilo Krummrich <dakr@kernel.org>
18757+
R: Bjorn Helgaas <bhelgaas@google.com>
18758+
R: Krzysztof Wilczyński <kwilczynski@kernel.org>
18759+
L: linux-pci@vger.kernel.org
18760+
S: Maintained
18761+
C: irc://irc.oftc.net/linux-pci
18762+
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
18763+
F: rust/helpers/pci.c
1875318764
F: rust/kernel/pci.rs
1875418765
F: samples/rust/rust_driver_pci.rs
1875518766

drivers/base/auxiliary.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@
156156
* },
157157
* .ops = my_custom_ops,
158158
* };
159+
*
160+
* Please note that such custom ops approach is valid, but it is hard to implement
161+
* it right without global locks per-device to protect from auxiliary_drv removal
162+
* during call to that ops. In addition, this implementation lacks proper module
163+
* dependency, which causes to load/unload races between auxiliary parent and devices
164+
* modules.
165+
*
166+
* The most easiest way to provide these ops reliably without needing to
167+
* have a lock is to EXPORT_SYMBOL*() them and rely on already existing
168+
* modules infrastructure for validity and correct dependencies chains.
159169
*/
160170

161171
static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id,

drivers/base/base.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static inline void subsys_put(struct subsys_private *sp)
7373
kset_put(&sp->subsys);
7474
}
7575

76+
struct subsys_private *bus_to_subsys(const struct bus_type *bus);
7677
struct subsys_private *class_to_subsys(const struct class *class);
7778

7879
struct driver_private {
@@ -180,6 +181,22 @@ int driver_add_groups(const struct device_driver *drv, const struct attribute_gr
180181
void driver_remove_groups(const struct device_driver *drv, const struct attribute_group **groups);
181182
void device_driver_detach(struct device *dev);
182183

184+
static inline void device_set_driver(struct device *dev, const struct device_driver *drv)
185+
{
186+
/*
187+
* Majority (all?) read accesses to dev->driver happens either
188+
* while holding device lock or in bus/driver code that is only
189+
* invoked when the device is bound to a driver and there is no
190+
* concern of the pointer being changed while it is being read.
191+
* However when reading device's uevent file we read driver pointer
192+
* without taking device lock (so we do not block there for
193+
* arbitrary amount of time). We use WRITE_ONCE() here to prevent
194+
* tearing so that READ_ONCE() can safely be used in uevent code.
195+
*/
196+
// FIXME - this cast should not be needed "soon"
197+
WRITE_ONCE(dev->driver, (struct device_driver *)drv);
198+
}
199+
183200
int devres_release_all(struct device *dev);
184201
void device_block_probing(void);
185202
void device_unblock_probing(void);

drivers/base/bus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
5757
* NULL. A call to subsys_put() must be done when finished with the pointer in
5858
* order for it to be properly freed.
5959
*/
60-
static struct subsys_private *bus_to_subsys(const struct bus_type *bus)
60+
struct subsys_private *bus_to_subsys(const struct bus_type *bus)
6161
{
6262
struct subsys_private *sp = NULL;
6363
struct kobject *kobj;

drivers/base/core.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2624,6 +2624,35 @@ static const char *dev_uevent_name(const struct kobject *kobj)
26242624
return NULL;
26252625
}
26262626

2627+
/*
2628+
* Try filling "DRIVER=<name>" uevent variable for a device. Because this
2629+
* function may race with binding and unbinding the device from a driver,
2630+
* we need to be careful. Binding is generally safe, at worst we miss the
2631+
* fact that the device is already bound to a driver (but the driver
2632+
* information that is delivered through uevents is best-effort, it may
2633+
* become obsolete as soon as it is generated anyways). Unbinding is more
2634+
* risky as driver pointer is transitioning to NULL, so READ_ONCE() should
2635+
* be used to make sure we are dealing with the same pointer, and to
2636+
* ensure that driver structure is not going to disappear from under us
2637+
* we take bus' drivers klist lock. The assumption that only registered
2638+
* driver can be bound to a device, and to unregister a driver bus code
2639+
* will take the same lock.
2640+
*/
2641+
static void dev_driver_uevent(const struct device *dev, struct kobj_uevent_env *env)
2642+
{
2643+
struct subsys_private *sp = bus_to_subsys(dev->bus);
2644+
2645+
if (sp) {
2646+
scoped_guard(spinlock, &sp->klist_drivers.k_lock) {
2647+
struct device_driver *drv = READ_ONCE(dev->driver);
2648+
if (drv)
2649+
add_uevent_var(env, "DRIVER=%s", drv->name);
2650+
}
2651+
2652+
subsys_put(sp);
2653+
}
2654+
}
2655+
26272656
static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)
26282657
{
26292658
const struct device *dev = kobj_to_dev(kobj);
@@ -2655,8 +2684,8 @@ static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)
26552684
if (dev->type && dev->type->name)
26562685
add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
26572686

2658-
if (dev->driver)
2659-
add_uevent_var(env, "DRIVER=%s", dev->driver->name);
2687+
/* Add "DRIVER=%s" variable if the device is bound to a driver */
2688+
dev_driver_uevent(dev, env);
26602689

26612690
/* Add common DT information about the device */
26622691
of_device_uevent(dev, env);
@@ -2726,11 +2755,8 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
27262755
if (!env)
27272756
return -ENOMEM;
27282757

2729-
/* Synchronize with really_probe() */
2730-
device_lock(dev);
27312758
/* let the kset specific function add its keys */
27322759
retval = kset->uevent_ops->uevent(&dev->kobj, env);
2733-
device_unlock(dev);
27342760
if (retval)
27352761
goto out;
27362762

@@ -3700,7 +3726,7 @@ int device_add(struct device *dev)
37003726
device_pm_remove(dev);
37013727
dpm_sysfs_remove(dev);
37023728
DPMError:
3703-
dev->driver = NULL;
3729+
device_set_driver(dev, NULL);
37043730
bus_remove_device(dev);
37053731
BusError:
37063732
device_remove_attrs(dev);

drivers/base/dd.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ static void device_unbind_cleanup(struct device *dev)
550550
arch_teardown_dma_ops(dev);
551551
kfree(dev->dma_range_map);
552552
dev->dma_range_map = NULL;
553-
dev->driver = NULL;
553+
device_set_driver(dev, NULL);
554554
dev_set_drvdata(dev, NULL);
555555
if (dev->pm_domain && dev->pm_domain->dismiss)
556556
dev->pm_domain->dismiss(dev);
@@ -629,8 +629,7 @@ static int really_probe(struct device *dev, const struct device_driver *drv)
629629
}
630630

631631
re_probe:
632-
// FIXME - this cast should not be needed "soon"
633-
dev->driver = (struct device_driver *)drv;
632+
device_set_driver(dev, drv);
634633

635634
/* If using pinctrl, bind pins now before probing */
636635
ret = pinctrl_bind_pins(dev);
@@ -1014,7 +1013,7 @@ static int __device_attach(struct device *dev, bool allow_async)
10141013
if (ret == 0)
10151014
ret = 1;
10161015
else {
1017-
dev->driver = NULL;
1016+
device_set_driver(dev, NULL);
10181017
ret = 0;
10191018
}
10201019
} else {

drivers/base/memory.c

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -816,21 +816,6 @@ static int add_memory_block(unsigned long block_id, unsigned long state,
816816
return 0;
817817
}
818818

819-
static int __init add_boot_memory_block(unsigned long base_section_nr)
820-
{
821-
unsigned long nr;
822-
823-
for_each_present_section_nr(base_section_nr, nr) {
824-
if (nr >= (base_section_nr + sections_per_block))
825-
break;
826-
827-
return add_memory_block(memory_block_id(base_section_nr),
828-
MEM_ONLINE, NULL, NULL);
829-
}
830-
831-
return 0;
832-
}
833-
834819
static int add_hotplug_memory_block(unsigned long block_id,
835820
struct vmem_altmap *altmap,
836821
struct memory_group *group)
@@ -957,7 +942,7 @@ static const struct attribute_group *memory_root_attr_groups[] = {
957942
void __init memory_dev_init(void)
958943
{
959944
int ret;
960-
unsigned long block_sz, nr;
945+
unsigned long block_sz, block_id, nr;
961946

962947
/* Validate the configured memory block size */
963948
block_sz = memory_block_size_bytes();
@@ -970,15 +955,23 @@ void __init memory_dev_init(void)
970955
panic("%s() failed to register subsystem: %d\n", __func__, ret);
971956

972957
/*
973-
* Create entries for memory sections that were found
974-
* during boot and have been initialized
958+
* Create entries for memory sections that were found during boot
959+
* and have been initialized. Use @block_id to track the last
960+
* handled block and initialize it to an invalid value (ULONG_MAX)
961+
* to bypass the block ID matching check for the first present
962+
* block so that it can be covered.
975963
*/
976-
for (nr = 0; nr <= __highest_present_section_nr;
977-
nr += sections_per_block) {
978-
ret = add_boot_memory_block(nr);
979-
if (ret)
980-
panic("%s() failed to add memory block: %d\n", __func__,
981-
ret);
964+
block_id = ULONG_MAX;
965+
for_each_present_section_nr(0, nr) {
966+
if (block_id != ULONG_MAX && memory_block_id(nr) == block_id)
967+
continue;
968+
969+
block_id = memory_block_id(nr);
970+
ret = add_memory_block(block_id, MEM_ONLINE, NULL, NULL);
971+
if (ret) {
972+
panic("%s() failed to add memory block: %d\n",
973+
__func__, ret);
974+
}
982975
}
983976
}
984977

drivers/base/swnode.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,7 @@ void software_node_notify(struct device *dev)
10801080
if (!swnode)
10811081
return;
10821082

1083+
kobject_get(&swnode->kobj);
10831084
ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node");
10841085
if (ret)
10851086
return;
@@ -1089,8 +1090,6 @@ void software_node_notify(struct device *dev)
10891090
sysfs_remove_link(&dev->kobj, "software_node");
10901091
return;
10911092
}
1092-
1093-
kobject_get(&swnode->kobj);
10941093
}
10951094

10961095
void software_node_notify_remove(struct device *dev)

include/linux/fwnode.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
/*
33
* fwnode.h - Firmware device node object handle type definition.
44
*
5+
* This header file provides low-level data types and definitions for firmware
6+
* and device property providers. The respective API header files supplied by
7+
* them should contain all of the requisite data types and definitions for end
8+
* users, so including it directly should not be necessary.
9+
*
510
* Copyright (C) 2015, Intel Corporation
611
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
712
*/

rust/kernel/firmware.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
//!
55
//! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.h)
66
7-
use crate::{bindings, device::Device, error::Error, error::Result, str::CStr};
7+
use crate::{bindings, device::Device, error::Error, error::Result, ffi, str::CStr};
88
use core::ptr::NonNull;
99

1010
/// # Invariants
1111
///
1212
/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,
1313
/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`.
1414
struct FwFunc(
15-
unsafe extern "C" fn(*mut *const bindings::firmware, *const u8, *mut bindings::device) -> i32,
15+
unsafe extern "C" fn(
16+
*mut *const bindings::firmware,
17+
*const ffi::c_char,
18+
*mut bindings::device,
19+
) -> i32,
1620
);
1721

1822
impl FwFunc {

0 commit comments

Comments
 (0)