Skip to content

Commit 7510df3

Browse files
Shuah Khan (Samsung OSG)gregkh
authored andcommitted
usbip: usbip_host: run rebind from exit when module is removed
After removing usbip_host module, devices it releases are left without a driver. For example, when a keyboard or a mass storage device are bound to usbip_host when it is removed, these devices are no longer bound to any driver. Fix it to run device_attach() from the module exit routine to restore the devices to their original drivers. This includes cleanup changes and moving device_attach() code to a common routine to be called from rebind_store() and usbip_host_exit(). Signed-off-by: Shuah Khan (Samsung OSG) <[email protected]> Cc: stable <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1e180f1 commit 7510df3

File tree

2 files changed

+52
-14
lines changed

2 files changed

+52
-14
lines changed

drivers/usb/usbip/stub_dev.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,8 @@ static void stub_disconnect(struct usb_device *udev)
448448
busid_priv->sdev = NULL;
449449
stub_device_free(sdev);
450450

451-
if (busid_priv->status == STUB_BUSID_ALLOC) {
451+
if (busid_priv->status == STUB_BUSID_ALLOC)
452452
busid_priv->status = STUB_BUSID_ADDED;
453-
} else {
454-
busid_priv->status = STUB_BUSID_OTHER;
455-
del_match_busid((char *)udev_busid);
456-
}
457453
}
458454

459455
#ifdef CONFIG_PM

drivers/usb/usbip/stub_main.c

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define DRIVER_DESC "USB/IP Host Driver"
1515

1616
struct kmem_cache *stub_priv_cache;
17+
1718
/*
1819
* busid_tables defines matching busids that usbip can grab. A user can change
1920
* dynamically what device is locally used and what device is exported to a
@@ -169,6 +170,51 @@ static ssize_t match_busid_store(struct device_driver *dev, const char *buf,
169170
}
170171
static DRIVER_ATTR_RW(match_busid);
171172

173+
static int do_rebind(char *busid, struct bus_id_priv *busid_priv)
174+
{
175+
int ret;
176+
177+
/* device_attach() callers should hold parent lock for USB */
178+
if (busid_priv->udev->dev.parent)
179+
device_lock(busid_priv->udev->dev.parent);
180+
ret = device_attach(&busid_priv->udev->dev);
181+
if (busid_priv->udev->dev.parent)
182+
device_unlock(busid_priv->udev->dev.parent);
183+
if (ret < 0) {
184+
dev_err(&busid_priv->udev->dev, "rebind failed\n");
185+
return ret;
186+
}
187+
return 0;
188+
}
189+
190+
static void stub_device_rebind(void)
191+
{
192+
#if IS_MODULE(CONFIG_USBIP_HOST)
193+
struct bus_id_priv *busid_priv;
194+
int i;
195+
196+
/* update status to STUB_BUSID_OTHER so probe ignores the device */
197+
spin_lock(&busid_table_lock);
198+
for (i = 0; i < MAX_BUSID; i++) {
199+
if (busid_table[i].name[0] &&
200+
busid_table[i].shutdown_busid) {
201+
busid_priv = &(busid_table[i]);
202+
busid_priv->status = STUB_BUSID_OTHER;
203+
}
204+
}
205+
spin_unlock(&busid_table_lock);
206+
207+
/* now run rebind */
208+
for (i = 0; i < MAX_BUSID; i++) {
209+
if (busid_table[i].name[0] &&
210+
busid_table[i].shutdown_busid) {
211+
busid_priv = &(busid_table[i]);
212+
do_rebind(busid_table[i].name, busid_priv);
213+
}
214+
}
215+
#endif
216+
}
217+
172218
static ssize_t rebind_store(struct device_driver *dev, const char *buf,
173219
size_t count)
174220
{
@@ -189,16 +235,9 @@ static ssize_t rebind_store(struct device_driver *dev, const char *buf,
189235
/* mark the device for deletion so probe ignores it during rescan */
190236
bid->status = STUB_BUSID_OTHER;
191237

192-
/* device_attach() callers should hold parent lock for USB */
193-
if (bid->udev->dev.parent)
194-
device_lock(bid->udev->dev.parent);
195-
ret = device_attach(&bid->udev->dev);
196-
if (bid->udev->dev.parent)
197-
device_unlock(bid->udev->dev.parent);
198-
if (ret < 0) {
199-
dev_err(&bid->udev->dev, "rebind failed\n");
238+
ret = do_rebind((char *) buf, bid);
239+
if (ret < 0)
200240
return ret;
201-
}
202241

203242
/* delete device from busid_table */
204243
del_match_busid((char *) buf);
@@ -323,6 +362,9 @@ static void __exit usbip_host_exit(void)
323362
*/
324363
usb_deregister_device_driver(&stub_driver);
325364

365+
/* initiate scan to attach devices */
366+
stub_device_rebind();
367+
326368
kmem_cache_destroy(stub_priv_cache);
327369
}
328370

0 commit comments

Comments
 (0)