Skip to content

Commit

Permalink
usbip: usbip_host: run rebind from exit when module is removed
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
Shuah Khan (Samsung OSG) authored and gregkh committed May 15, 2018
1 parent 1e180f1 commit 7510df3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 14 deletions.
6 changes: 1 addition & 5 deletions drivers/usb/usbip/stub_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,12 +448,8 @@ static void stub_disconnect(struct usb_device *udev)
busid_priv->sdev = NULL;
stub_device_free(sdev);

if (busid_priv->status == STUB_BUSID_ALLOC) {
if (busid_priv->status == STUB_BUSID_ALLOC)
busid_priv->status = STUB_BUSID_ADDED;
} else {
busid_priv->status = STUB_BUSID_OTHER;
del_match_busid((char *)udev_busid);
}
}

#ifdef CONFIG_PM
Expand Down
60 changes: 51 additions & 9 deletions drivers/usb/usbip/stub_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define DRIVER_DESC "USB/IP Host Driver"

struct kmem_cache *stub_priv_cache;

/*
* busid_tables defines matching busids that usbip can grab. A user can change
* dynamically what device is locally used and what device is exported to a
Expand Down Expand Up @@ -169,6 +170,51 @@ static ssize_t match_busid_store(struct device_driver *dev, const char *buf,
}
static DRIVER_ATTR_RW(match_busid);

static int do_rebind(char *busid, struct bus_id_priv *busid_priv)
{
int ret;

/* device_attach() callers should hold parent lock for USB */
if (busid_priv->udev->dev.parent)
device_lock(busid_priv->udev->dev.parent);
ret = device_attach(&busid_priv->udev->dev);
if (busid_priv->udev->dev.parent)
device_unlock(busid_priv->udev->dev.parent);
if (ret < 0) {
dev_err(&busid_priv->udev->dev, "rebind failed\n");
return ret;
}
return 0;
}

static void stub_device_rebind(void)
{
#if IS_MODULE(CONFIG_USBIP_HOST)
struct bus_id_priv *busid_priv;
int i;

/* update status to STUB_BUSID_OTHER so probe ignores the device */
spin_lock(&busid_table_lock);
for (i = 0; i < MAX_BUSID; i++) {
if (busid_table[i].name[0] &&
busid_table[i].shutdown_busid) {
busid_priv = &(busid_table[i]);
busid_priv->status = STUB_BUSID_OTHER;
}
}
spin_unlock(&busid_table_lock);

/* now run rebind */
for (i = 0; i < MAX_BUSID; i++) {
if (busid_table[i].name[0] &&
busid_table[i].shutdown_busid) {
busid_priv = &(busid_table[i]);
do_rebind(busid_table[i].name, busid_priv);
}
}
#endif
}

static ssize_t rebind_store(struct device_driver *dev, const char *buf,
size_t count)
{
Expand All @@ -189,16 +235,9 @@ static ssize_t rebind_store(struct device_driver *dev, const char *buf,
/* mark the device for deletion so probe ignores it during rescan */
bid->status = STUB_BUSID_OTHER;

/* device_attach() callers should hold parent lock for USB */
if (bid->udev->dev.parent)
device_lock(bid->udev->dev.parent);
ret = device_attach(&bid->udev->dev);
if (bid->udev->dev.parent)
device_unlock(bid->udev->dev.parent);
if (ret < 0) {
dev_err(&bid->udev->dev, "rebind failed\n");
ret = do_rebind((char *) buf, bid);
if (ret < 0)
return ret;
}

/* delete device from busid_table */
del_match_busid((char *) buf);
Expand Down Expand Up @@ -323,6 +362,9 @@ static void __exit usbip_host_exit(void)
*/
usb_deregister_device_driver(&stub_driver);

/* initiate scan to attach devices */
stub_device_rebind();

kmem_cache_destroy(stub_priv_cache);
}

Expand Down

0 comments on commit 7510df3

Please sign in to comment.