Commit a46034ca authored by Valentina Manea's avatar Valentina Manea Committed by Greg Kroah-Hartman

staging: usbip: trigger driver probing after unbinding from usbip-host

A sysfs attribute is used to announce kernel space that a
new driver probing session should be triggered for the just
unbinded device.

In order to have the address of struct device associated to this
USB device, a new member has been added to struct bus_id_priv.
Signed-off-by: default avatarValentina Manea <valentina.manea.m@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2c8c9815
...@@ -86,6 +86,7 @@ struct bus_id_priv { ...@@ -86,6 +86,7 @@ struct bus_id_priv {
char status; char status;
int interf_count; int interf_count;
struct stub_device *sdev; struct stub_device *sdev;
struct usb_device *udev;
char shutdown_busid; char shutdown_busid;
}; };
......
...@@ -386,6 +386,7 @@ static int stub_probe(struct usb_device *udev) ...@@ -386,6 +386,7 @@ static int stub_probe(struct usb_device *udev)
/* set private data to usb_device */ /* set private data to usb_device */
dev_set_drvdata(&udev->dev, sdev); dev_set_drvdata(&udev->dev, sdev);
busid_priv->sdev = sdev; busid_priv->sdev = sdev;
busid_priv->udev = udev;
err = stub_add_files(&udev->dev); err = stub_add_files(&udev->dev);
if (err) { if (err) {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h>
#include "usbip_common.h" #include "usbip_common.h"
#include "stub.h" #include "stub.h"
...@@ -187,6 +188,34 @@ static ssize_t store_match_busid(struct device_driver *dev, const char *buf, ...@@ -187,6 +188,34 @@ static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid, static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid,
store_match_busid); store_match_busid);
static ssize_t rebind_store(struct device_driver *dev, const char *buf,
size_t count)
{
int ret;
int len;
struct bus_id_priv *bid;
/* buf length should be less that BUSID_SIZE */
len = strnlen(buf, BUSID_SIZE);
if (!(len < BUSID_SIZE))
return -EINVAL;
bid = get_busid_priv(buf);
if (!bid)
return -ENODEV;
ret = device_attach(&bid->udev->dev);
if (ret < 0) {
dev_err(&bid->udev->dev, "rebind failed\n");
return ret;
}
return count;
}
static DRIVER_ATTR_WO(rebind);
static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
{ {
struct stub_priv *priv, *tmp; struct stub_priv *priv, *tmp;
...@@ -267,6 +296,13 @@ static int __init usbip_host_init(void) ...@@ -267,6 +296,13 @@ static int __init usbip_host_init(void)
goto err_create_file; goto err_create_file;
} }
ret = driver_create_file(&stub_driver.drvwrap.driver,
&driver_attr_rebind);
if (ret) {
pr_err("driver_create_file failed\n");
goto err_create_file;
}
pr_info(DRIVER_DESC " v" USBIP_VERSION "\n"); pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
return ret; return ret;
...@@ -282,6 +318,9 @@ static void __exit usbip_host_exit(void) ...@@ -282,6 +318,9 @@ static void __exit usbip_host_exit(void)
driver_remove_file(&stub_driver.drvwrap.driver, driver_remove_file(&stub_driver.drvwrap.driver,
&driver_attr_match_busid); &driver_attr_match_busid);
driver_remove_file(&stub_driver.drvwrap.driver,
&driver_attr_rebind);
/* /*
* deregister() calls stub_disconnect() for all devices. Device * deregister() calls stub_disconnect() for all devices. Device
* specific data is cleared in stub_disconnect(). * specific data is cleared in stub_disconnect().
......
...@@ -44,8 +44,10 @@ static int unbind_device(char *busid) ...@@ -44,8 +44,10 @@ static int unbind_device(char *busid)
char bus_type[] = "usb"; char bus_type[] = "usb";
int rc, ret = -1; int rc, ret = -1;
char attr_name[] = "unbind"; char unbind_attr_name[] = "unbind";
char unbind_attr_path[SYSFS_PATH_MAX]; char unbind_attr_path[SYSFS_PATH_MAX];
char rebind_attr_name[] = "rebind";
char rebind_attr_path[SYSFS_PATH_MAX];
struct udev *udev; struct udev *udev;
struct udev_device *dev; struct udev_device *dev;
...@@ -71,7 +73,7 @@ static int unbind_device(char *busid) ...@@ -71,7 +73,7 @@ static int unbind_device(char *busid)
/* Unbind device from driver. */ /* Unbind device from driver. */
snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s", snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
USBIP_HOST_DRV_NAME, attr_name); USBIP_HOST_DRV_NAME, unbind_attr_name);
rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid)); rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
if (rc < 0) { if (rc < 0) {
...@@ -86,6 +88,17 @@ static int unbind_device(char *busid) ...@@ -86,6 +88,17 @@ static int unbind_device(char *busid)
goto err_close_udev; goto err_close_udev;
} }
/* Trigger new probing. */
snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
USBIP_HOST_DRV_NAME, rebind_attr_name);
rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid));
if (rc < 0) {
err("error rebinding");
goto err_close_udev;
}
ret = 0; ret = 0;
info("unbind device on busid %s: complete", busid); info("unbind device on busid %s: complete", busid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment