Skip to content

Commit 0b3144d

Browse files
committed
USB: make single lock for all usb dynamic id lists
There are a number of places where we accidentally pass in a constant structure to later cast it off to a dynamic one, and then attempt to grab a lock on it, which is not a good idea. To help resolve this, move the dynamic id lock out of the dynamic id structure for the driver and into one single lock for all USB dynamic ids. As this lock should never have any real contention (it's only every accessed when a device is added or removed, which is always serialized) there should not be any difference except for some memory savings. Note, this just converts the existing use of the dynamic id lock to the new static lock, there is one place that is accessing the dynamic id list without grabbing the lock, that will be fixed up in a follow-on change. Cc: Johan Hovold <[email protected]> Cc: Herve Codina <[email protected]> Cc: Rob Herring <[email protected]> Cc: Alan Stern <[email protected]> Cc: Grant Grundler <[email protected]> Cc: Oliver Neukum <[email protected]> Cc: Yajun Deng <[email protected]> Cc: Douglas Anderson <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/2024111322-kindly-finalist-d247@gregkh Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 528ea1a commit 0b3144d

File tree

5 files changed

+11
-17
lines changed

5 files changed

+11
-17
lines changed

drivers/usb/common/common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,9 @@ EXPORT_SYMBOL_GPL(usb_of_get_companion_dev);
415415
struct dentry *usb_debug_root;
416416
EXPORT_SYMBOL_GPL(usb_debug_root);
417417

418+
DEFINE_MUTEX(usb_dynids_lock);
419+
EXPORT_SYMBOL_GPL(usb_dynids_lock);
420+
418421
static int __init usb_common_init(void)
419422
{
420423
usb_debug_root = debugfs_create_dir("usb", NULL);

drivers/usb/core/driver.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
9595
}
9696
}
9797

98-
spin_lock(&dynids->lock);
98+
mutex_lock(&usb_dynids_lock);
9999
list_add_tail(&dynid->node, &dynids->list);
100-
spin_unlock(&dynids->lock);
100+
mutex_unlock(&usb_dynids_lock);
101101

102102
retval = driver_attach(driver);
103103

@@ -160,7 +160,7 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
160160
if (fields < 2)
161161
return -EINVAL;
162162

163-
spin_lock(&usb_driver->dynids.lock);
163+
guard(mutex)(&usb_dynids_lock);
164164
list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) {
165165
struct usb_device_id *id = &dynid->id;
166166

@@ -171,7 +171,6 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
171171
break;
172172
}
173173
}
174-
spin_unlock(&usb_driver->dynids.lock);
175174
return count;
176175
}
177176

@@ -220,27 +219,24 @@ static void usb_free_dynids(struct usb_driver *usb_drv)
220219
{
221220
struct usb_dynid *dynid, *n;
222221

223-
spin_lock(&usb_drv->dynids.lock);
222+
guard(mutex)(&usb_dynids_lock);
224223
list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
225224
list_del(&dynid->node);
226225
kfree(dynid);
227226
}
228-
spin_unlock(&usb_drv->dynids.lock);
229227
}
230228

231229
static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
232230
struct usb_driver *drv)
233231
{
234232
struct usb_dynid *dynid;
235233

236-
spin_lock(&drv->dynids.lock);
234+
guard(mutex)(&usb_dynids_lock);
237235
list_for_each_entry(dynid, &drv->dynids.list, node) {
238236
if (usb_match_one_id(intf, &dynid->id)) {
239-
spin_unlock(&drv->dynids.lock);
240237
return &dynid->id;
241238
}
242239
}
243-
spin_unlock(&drv->dynids.lock);
244240
return NULL;
245241
}
246242

@@ -1076,7 +1072,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
10761072
new_driver->driver.owner = owner;
10771073
new_driver->driver.mod_name = mod_name;
10781074
new_driver->driver.dev_groups = new_driver->dev_groups;
1079-
spin_lock_init(&new_driver->dynids.lock);
10801075
INIT_LIST_HEAD(&new_driver->dynids.list);
10811076

10821077
retval = driver_register(&new_driver->driver);

drivers/usb/serial/bus.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,11 @@ static void free_dynids(struct usb_serial_driver *drv)
136136
{
137137
struct usb_dynid *dynid, *n;
138138

139-
spin_lock(&drv->dynids.lock);
139+
guard(mutex)(&usb_dynids_lock);
140140
list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
141141
list_del(&dynid->node);
142142
kfree(dynid);
143143
}
144-
spin_unlock(&drv->dynids.lock);
145144
}
146145

147146
const struct bus_type usb_serial_bus_type = {
@@ -157,7 +156,6 @@ int usb_serial_bus_register(struct usb_serial_driver *driver)
157156
int retval;
158157

159158
driver->driver.bus = &usb_serial_bus_type;
160-
spin_lock_init(&driver->dynids.lock);
161159
INIT_LIST_HEAD(&driver->dynids.list);
162160

163161
retval = driver_register(&driver->driver);

drivers/usb/serial/usb-serial.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -706,14 +706,12 @@ static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
706706
{
707707
struct usb_dynid *dynid;
708708

709-
spin_lock(&drv->dynids.lock);
709+
guard(mutex)(&usb_dynids_lock);
710710
list_for_each_entry(dynid, &drv->dynids.list, node) {
711711
if (usb_match_one_id(intf, &dynid->id)) {
712-
spin_unlock(&drv->dynids.lock);
713712
return &dynid->id;
714713
}
715714
}
716-
spin_unlock(&drv->dynids.lock);
717715
return NULL;
718716
}
719717

include/linux/usb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,8 +1129,8 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
11291129
/* ----------------------------------------------------------------------- */
11301130

11311131
/* Stuff for dynamic usb ids */
1132+
extern struct mutex usb_dynids_lock;
11321133
struct usb_dynids {
1133-
spinlock_t lock;
11341134
struct list_head list;
11351135
};
11361136

0 commit comments

Comments
 (0)