15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
296c27377SValentina Manea /*
396c27377SValentina Manea * Copyright (C) 2003-2008 Takahiro Hirofuchi
496c27377SValentina Manea */
596c27377SValentina Manea
696c27377SValentina Manea #include <linux/string.h>
796c27377SValentina Manea #include <linux/module.h>
896c27377SValentina Manea #include <linux/device.h>
9ea44d190SSuwan Kim #include <linux/scatterlist.h>
1096c27377SValentina Manea
1196c27377SValentina Manea #include "usbip_common.h"
1296c27377SValentina Manea #include "stub.h"
1396c27377SValentina Manea
1496c27377SValentina Manea #define DRIVER_AUTHOR "Takahiro Hirofuchi"
1596c27377SValentina Manea #define DRIVER_DESC "USB/IP Host Driver"
1696c27377SValentina Manea
1796c27377SValentina Manea struct kmem_cache *stub_priv_cache;
187510df3fSShuah Khan (Samsung OSG)
1996c27377SValentina Manea /*
2096c27377SValentina Manea * busid_tables defines matching busids that usbip can grab. A user can change
2196c27377SValentina Manea * dynamically what device is locally used and what device is exported to a
2296c27377SValentina Manea * remote host.
2396c27377SValentina Manea */
2496c27377SValentina Manea #define MAX_BUSID 16
2596c27377SValentina Manea static struct bus_id_priv busid_table[MAX_BUSID];
26841081d8SZheng Yongjun static DEFINE_SPINLOCK(busid_table_lock);
2796c27377SValentina Manea
init_busid_table(void)2896c27377SValentina Manea static void init_busid_table(void)
2996c27377SValentina Manea {
3022076557SShuah Khan (Samsung OSG) int i;
3122076557SShuah Khan (Samsung OSG)
3296c27377SValentina Manea /*
3396c27377SValentina Manea * This also sets the bus_table[i].status to
3496c27377SValentina Manea * STUB_BUSID_OTHER, which is 0.
3596c27377SValentina Manea */
3696c27377SValentina Manea memset(busid_table, 0, sizeof(busid_table));
3796c27377SValentina Manea
3822076557SShuah Khan (Samsung OSG) for (i = 0; i < MAX_BUSID; i++)
3922076557SShuah Khan (Samsung OSG) spin_lock_init(&busid_table[i].busid_lock);
4096c27377SValentina Manea }
4196c27377SValentina Manea
4296c27377SValentina Manea /*
4396c27377SValentina Manea * Find the index of the busid by name.
4496c27377SValentina Manea * Must be called with busid_table_lock held.
4596c27377SValentina Manea */
get_busid_idx(const char * busid)4696c27377SValentina Manea static int get_busid_idx(const char *busid)
4796c27377SValentina Manea {
4896c27377SValentina Manea int i;
4996c27377SValentina Manea int idx = -1;
5096c27377SValentina Manea
5122076557SShuah Khan (Samsung OSG) for (i = 0; i < MAX_BUSID; i++) {
5222076557SShuah Khan (Samsung OSG) spin_lock(&busid_table[i].busid_lock);
5396c27377SValentina Manea if (busid_table[i].name[0])
5496c27377SValentina Manea if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
5596c27377SValentina Manea idx = i;
5622076557SShuah Khan (Samsung OSG) spin_unlock(&busid_table[i].busid_lock);
5796c27377SValentina Manea break;
5896c27377SValentina Manea }
5922076557SShuah Khan (Samsung OSG) spin_unlock(&busid_table[i].busid_lock);
6022076557SShuah Khan (Samsung OSG) }
6196c27377SValentina Manea return idx;
6296c27377SValentina Manea }
6396c27377SValentina Manea
6422076557SShuah Khan (Samsung OSG) /* Returns holding busid_lock. Should call put_busid_priv() to unlock */
get_busid_priv(const char * busid)6596c27377SValentina Manea struct bus_id_priv *get_busid_priv(const char *busid)
6696c27377SValentina Manea {
6796c27377SValentina Manea int idx;
6896c27377SValentina Manea struct bus_id_priv *bid = NULL;
6996c27377SValentina Manea
7096c27377SValentina Manea spin_lock(&busid_table_lock);
7196c27377SValentina Manea idx = get_busid_idx(busid);
7222076557SShuah Khan (Samsung OSG) if (idx >= 0) {
7396c27377SValentina Manea bid = &(busid_table[idx]);
7422076557SShuah Khan (Samsung OSG) /* get busid_lock before returning */
7522076557SShuah Khan (Samsung OSG) spin_lock(&bid->busid_lock);
7622076557SShuah Khan (Samsung OSG) }
7796c27377SValentina Manea spin_unlock(&busid_table_lock);
7896c27377SValentina Manea
7996c27377SValentina Manea return bid;
8096c27377SValentina Manea }
8196c27377SValentina Manea
put_busid_priv(struct bus_id_priv * bid)8222076557SShuah Khan (Samsung OSG) void put_busid_priv(struct bus_id_priv *bid)
8322076557SShuah Khan (Samsung OSG) {
84c171654cSShuah Khan (Samsung OSG) if (bid)
8522076557SShuah Khan (Samsung OSG) spin_unlock(&bid->busid_lock);
8622076557SShuah Khan (Samsung OSG) }
8722076557SShuah Khan (Samsung OSG)
add_match_busid(char * busid)8896c27377SValentina Manea static int add_match_busid(char *busid)
8996c27377SValentina Manea {
9096c27377SValentina Manea int i;
9196c27377SValentina Manea int ret = -1;
9296c27377SValentina Manea
9396c27377SValentina Manea spin_lock(&busid_table_lock);
9496c27377SValentina Manea /* already registered? */
9596c27377SValentina Manea if (get_busid_idx(busid) >= 0) {
9696c27377SValentina Manea ret = 0;
9796c27377SValentina Manea goto out;
9896c27377SValentina Manea }
9996c27377SValentina Manea
10022076557SShuah Khan (Samsung OSG) for (i = 0; i < MAX_BUSID; i++) {
10122076557SShuah Khan (Samsung OSG) spin_lock(&busid_table[i].busid_lock);
10296c27377SValentina Manea if (!busid_table[i].name[0]) {
103b7db5733SWolfram Sang strscpy(busid_table[i].name, busid, BUSID_SIZE);
10496c27377SValentina Manea if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
10596c27377SValentina Manea (busid_table[i].status != STUB_BUSID_REMOV))
10696c27377SValentina Manea busid_table[i].status = STUB_BUSID_ADDED;
10796c27377SValentina Manea ret = 0;
10822076557SShuah Khan (Samsung OSG) spin_unlock(&busid_table[i].busid_lock);
10996c27377SValentina Manea break;
11096c27377SValentina Manea }
11122076557SShuah Khan (Samsung OSG) spin_unlock(&busid_table[i].busid_lock);
11222076557SShuah Khan (Samsung OSG) }
11396c27377SValentina Manea
11496c27377SValentina Manea out:
11596c27377SValentina Manea spin_unlock(&busid_table_lock);
11696c27377SValentina Manea
11796c27377SValentina Manea return ret;
11896c27377SValentina Manea }
11996c27377SValentina Manea
del_match_busid(char * busid)12096c27377SValentina Manea int del_match_busid(char *busid)
12196c27377SValentina Manea {
12296c27377SValentina Manea int idx;
12396c27377SValentina Manea int ret = -1;
12496c27377SValentina Manea
12596c27377SValentina Manea spin_lock(&busid_table_lock);
12696c27377SValentina Manea idx = get_busid_idx(busid);
12796c27377SValentina Manea if (idx < 0)
12896c27377SValentina Manea goto out;
12996c27377SValentina Manea
13096c27377SValentina Manea /* found */
13196c27377SValentina Manea ret = 0;
13296c27377SValentina Manea
13322076557SShuah Khan (Samsung OSG) spin_lock(&busid_table[idx].busid_lock);
13422076557SShuah Khan (Samsung OSG)
13596c27377SValentina Manea if (busid_table[idx].status == STUB_BUSID_OTHER)
13696c27377SValentina Manea memset(busid_table[idx].name, 0, BUSID_SIZE);
13796c27377SValentina Manea
13896c27377SValentina Manea if ((busid_table[idx].status != STUB_BUSID_OTHER) &&
13996c27377SValentina Manea (busid_table[idx].status != STUB_BUSID_ADDED))
14096c27377SValentina Manea busid_table[idx].status = STUB_BUSID_REMOV;
14196c27377SValentina Manea
14222076557SShuah Khan (Samsung OSG) spin_unlock(&busid_table[idx].busid_lock);
14396c27377SValentina Manea out:
14496c27377SValentina Manea spin_unlock(&busid_table_lock);
14596c27377SValentina Manea
14696c27377SValentina Manea return ret;
14796c27377SValentina Manea }
14896c27377SValentina Manea
match_busid_show(struct device_driver * drv,char * buf)149cc3d53deSGreg Kroah-Hartman static ssize_t match_busid_show(struct device_driver *drv, char *buf)
15096c27377SValentina Manea {
15196c27377SValentina Manea int i;
15296c27377SValentina Manea char *out = buf;
15396c27377SValentina Manea
15496c27377SValentina Manea spin_lock(&busid_table_lock);
15522076557SShuah Khan (Samsung OSG) for (i = 0; i < MAX_BUSID; i++) {
15622076557SShuah Khan (Samsung OSG) spin_lock(&busid_table[i].busid_lock);
15796c27377SValentina Manea if (busid_table[i].name[0])
15896c27377SValentina Manea out += sprintf(out, "%s ", busid_table[i].name);
15922076557SShuah Khan (Samsung OSG) spin_unlock(&busid_table[i].busid_lock);
16022076557SShuah Khan (Samsung OSG) }
16196c27377SValentina Manea spin_unlock(&busid_table_lock);
16296c27377SValentina Manea out += sprintf(out, "\n");
16396c27377SValentina Manea
16496c27377SValentina Manea return out - buf;
16596c27377SValentina Manea }
16696c27377SValentina Manea
match_busid_store(struct device_driver * dev,const char * buf,size_t count)167cc3d53deSGreg Kroah-Hartman static ssize_t match_busid_store(struct device_driver *dev, const char *buf,
16896c27377SValentina Manea size_t count)
16996c27377SValentina Manea {
17096c27377SValentina Manea char busid[BUSID_SIZE];
17196c27377SValentina Manea
17296c27377SValentina Manea if (count < 5)
17396c27377SValentina Manea return -EINVAL;
17496c27377SValentina Manea
17596c27377SValentina Manea /* busid needs to include \0 termination */
176*61d52f64SAzeem Shaikh if (strscpy(busid, buf + 4, BUSID_SIZE) < 0)
17796c27377SValentina Manea return -EINVAL;
17896c27377SValentina Manea
17996c27377SValentina Manea if (!strncmp(buf, "add ", 4)) {
18096c27377SValentina Manea if (add_match_busid(busid) < 0)
18196c27377SValentina Manea return -ENOMEM;
18296c27377SValentina Manea
18396c27377SValentina Manea pr_debug("add busid %s\n", busid);
18496c27377SValentina Manea return count;
18596c27377SValentina Manea }
18696c27377SValentina Manea
18796c27377SValentina Manea if (!strncmp(buf, "del ", 4)) {
18896c27377SValentina Manea if (del_match_busid(busid) < 0)
18996c27377SValentina Manea return -ENODEV;
19096c27377SValentina Manea
19196c27377SValentina Manea pr_debug("del busid %s\n", busid);
19296c27377SValentina Manea return count;
19396c27377SValentina Manea }
19496c27377SValentina Manea
19596c27377SValentina Manea return -EINVAL;
19696c27377SValentina Manea }
197cc3d53deSGreg Kroah-Hartman static DRIVER_ATTR_RW(match_busid);
19896c27377SValentina Manea
do_rebind(char * busid,struct bus_id_priv * busid_priv)1997510df3fSShuah Khan (Samsung OSG) static int do_rebind(char *busid, struct bus_id_priv *busid_priv)
2007510df3fSShuah Khan (Samsung OSG) {
2013a38e874SShuah Khan int ret = 0;
2027510df3fSShuah Khan (Samsung OSG)
2037510df3fSShuah Khan (Samsung OSG) /* device_attach() callers should hold parent lock for USB */
2047510df3fSShuah Khan (Samsung OSG) if (busid_priv->udev->dev.parent)
2057510df3fSShuah Khan (Samsung OSG) device_lock(busid_priv->udev->dev.parent);
2067510df3fSShuah Khan (Samsung OSG) ret = device_attach(&busid_priv->udev->dev);
2077510df3fSShuah Khan (Samsung OSG) if (busid_priv->udev->dev.parent)
2087510df3fSShuah Khan (Samsung OSG) device_unlock(busid_priv->udev->dev.parent);
2093a38e874SShuah Khan if (ret < 0)
2107510df3fSShuah Khan (Samsung OSG) dev_err(&busid_priv->udev->dev, "rebind failed\n");
2117510df3fSShuah Khan (Samsung OSG) return ret;
2127510df3fSShuah Khan (Samsung OSG) }
2137510df3fSShuah Khan (Samsung OSG)
stub_device_rebind(void)2147510df3fSShuah Khan (Samsung OSG) static void stub_device_rebind(void)
2157510df3fSShuah Khan (Samsung OSG) {
2167510df3fSShuah Khan (Samsung OSG) #if IS_MODULE(CONFIG_USBIP_HOST)
2177510df3fSShuah Khan (Samsung OSG) struct bus_id_priv *busid_priv;
2187510df3fSShuah Khan (Samsung OSG) int i;
2197510df3fSShuah Khan (Samsung OSG)
2207510df3fSShuah Khan (Samsung OSG) /* update status to STUB_BUSID_OTHER so probe ignores the device */
2217510df3fSShuah Khan (Samsung OSG) spin_lock(&busid_table_lock);
2227510df3fSShuah Khan (Samsung OSG) for (i = 0; i < MAX_BUSID; i++) {
2237510df3fSShuah Khan (Samsung OSG) if (busid_table[i].name[0] &&
2247510df3fSShuah Khan (Samsung OSG) busid_table[i].shutdown_busid) {
2257510df3fSShuah Khan (Samsung OSG) busid_priv = &(busid_table[i]);
2267510df3fSShuah Khan (Samsung OSG) busid_priv->status = STUB_BUSID_OTHER;
2277510df3fSShuah Khan (Samsung OSG) }
2287510df3fSShuah Khan (Samsung OSG) }
2297510df3fSShuah Khan (Samsung OSG) spin_unlock(&busid_table_lock);
2307510df3fSShuah Khan (Samsung OSG)
23122076557SShuah Khan (Samsung OSG) /* now run rebind - no need to hold locks. driver files are removed */
2327510df3fSShuah Khan (Samsung OSG) for (i = 0; i < MAX_BUSID; i++) {
2337510df3fSShuah Khan (Samsung OSG) if (busid_table[i].name[0] &&
2347510df3fSShuah Khan (Samsung OSG) busid_table[i].shutdown_busid) {
2357510df3fSShuah Khan (Samsung OSG) busid_priv = &(busid_table[i]);
2367510df3fSShuah Khan (Samsung OSG) do_rebind(busid_table[i].name, busid_priv);
2377510df3fSShuah Khan (Samsung OSG) }
2387510df3fSShuah Khan (Samsung OSG) }
2397510df3fSShuah Khan (Samsung OSG) #endif
2407510df3fSShuah Khan (Samsung OSG) }
2417510df3fSShuah Khan (Samsung OSG)
rebind_store(struct device_driver * dev,const char * buf,size_t count)24296c27377SValentina Manea static ssize_t rebind_store(struct device_driver *dev, const char *buf,
24396c27377SValentina Manea size_t count)
24496c27377SValentina Manea {
24596c27377SValentina Manea int ret;
24696c27377SValentina Manea int len;
24796c27377SValentina Manea struct bus_id_priv *bid;
24896c27377SValentina Manea
24996c27377SValentina Manea /* buf length should be less that BUSID_SIZE */
25096c27377SValentina Manea len = strnlen(buf, BUSID_SIZE);
25196c27377SValentina Manea
25296c27377SValentina Manea if (!(len < BUSID_SIZE))
25396c27377SValentina Manea return -EINVAL;
25496c27377SValentina Manea
25596c27377SValentina Manea bid = get_busid_priv(buf);
25696c27377SValentina Manea if (!bid)
25796c27377SValentina Manea return -ENODEV;
25896c27377SValentina Manea
2591e180f16SShuah Khan (Samsung OSG) /* mark the device for deletion so probe ignores it during rescan */
2601e180f16SShuah Khan (Samsung OSG) bid->status = STUB_BUSID_OTHER;
26122076557SShuah Khan (Samsung OSG) /* release the busid lock */
26222076557SShuah Khan (Samsung OSG) put_busid_priv(bid);
2631e180f16SShuah Khan (Samsung OSG)
2647510df3fSShuah Khan (Samsung OSG) ret = do_rebind((char *) buf, bid);
2657510df3fSShuah Khan (Samsung OSG) if (ret < 0)
26696c27377SValentina Manea return ret;
26796c27377SValentina Manea
2681e180f16SShuah Khan (Samsung OSG) /* delete device from busid_table */
2691e180f16SShuah Khan (Samsung OSG) del_match_busid((char *) buf);
2701e180f16SShuah Khan (Samsung OSG)
27196c27377SValentina Manea return count;
27296c27377SValentina Manea }
27396c27377SValentina Manea
27496c27377SValentina Manea static DRIVER_ATTR_WO(rebind);
27596c27377SValentina Manea
stub_priv_pop_from_listhead(struct list_head * listhead)27696c27377SValentina Manea static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
27796c27377SValentina Manea {
27896c27377SValentina Manea struct stub_priv *priv, *tmp;
27996c27377SValentina Manea
28096c27377SValentina Manea list_for_each_entry_safe(priv, tmp, listhead, list) {
281ea44d190SSuwan Kim list_del_init(&priv->list);
28296c27377SValentina Manea return priv;
28396c27377SValentina Manea }
28496c27377SValentina Manea
28596c27377SValentina Manea return NULL;
28696c27377SValentina Manea }
28796c27377SValentina Manea
stub_free_priv_and_urb(struct stub_priv * priv)288ea44d190SSuwan Kim void stub_free_priv_and_urb(struct stub_priv *priv)
289ea44d190SSuwan Kim {
290ea44d190SSuwan Kim struct urb *urb;
291ea44d190SSuwan Kim int i;
292ea44d190SSuwan Kim
293ea44d190SSuwan Kim for (i = 0; i < priv->num_urbs; i++) {
294ea44d190SSuwan Kim urb = priv->urbs[i];
295ea44d190SSuwan Kim
296ea44d190SSuwan Kim if (!urb)
297ea44d190SSuwan Kim return;
298ea44d190SSuwan Kim
299ea44d190SSuwan Kim kfree(urb->setup_packet);
300ea44d190SSuwan Kim urb->setup_packet = NULL;
301ea44d190SSuwan Kim
302ea44d190SSuwan Kim
303ea44d190SSuwan Kim if (urb->transfer_buffer && !priv->sgl) {
304ea44d190SSuwan Kim kfree(urb->transfer_buffer);
305ea44d190SSuwan Kim urb->transfer_buffer = NULL;
306ea44d190SSuwan Kim }
307ea44d190SSuwan Kim
308ea44d190SSuwan Kim if (urb->num_sgs) {
309ea44d190SSuwan Kim sgl_free(urb->sg);
310ea44d190SSuwan Kim urb->sg = NULL;
311ea44d190SSuwan Kim urb->num_sgs = 0;
312ea44d190SSuwan Kim }
313ea44d190SSuwan Kim
314ea44d190SSuwan Kim usb_free_urb(urb);
315ea44d190SSuwan Kim }
316ea44d190SSuwan Kim if (!list_empty(&priv->list))
317ea44d190SSuwan Kim list_del(&priv->list);
318ea44d190SSuwan Kim if (priv->sgl)
319ea44d190SSuwan Kim sgl_free(priv->sgl);
320ea44d190SSuwan Kim kfree(priv->urbs);
321ea44d190SSuwan Kim kmem_cache_free(stub_priv_cache, priv);
322ea44d190SSuwan Kim }
323ea44d190SSuwan Kim
stub_priv_pop(struct stub_device * sdev)32496c27377SValentina Manea static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
32596c27377SValentina Manea {
32696c27377SValentina Manea unsigned long flags;
32796c27377SValentina Manea struct stub_priv *priv;
32896c27377SValentina Manea
32996c27377SValentina Manea spin_lock_irqsave(&sdev->priv_lock, flags);
33096c27377SValentina Manea
33196c27377SValentina Manea priv = stub_priv_pop_from_listhead(&sdev->priv_init);
33296c27377SValentina Manea if (priv)
33396c27377SValentina Manea goto done;
33496c27377SValentina Manea
33596c27377SValentina Manea priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
33696c27377SValentina Manea if (priv)
33796c27377SValentina Manea goto done;
33896c27377SValentina Manea
33996c27377SValentina Manea priv = stub_priv_pop_from_listhead(&sdev->priv_free);
34096c27377SValentina Manea
34196c27377SValentina Manea done:
34296c27377SValentina Manea spin_unlock_irqrestore(&sdev->priv_lock, flags);
34396c27377SValentina Manea
34496c27377SValentina Manea return priv;
34596c27377SValentina Manea }
34696c27377SValentina Manea
stub_device_cleanup_urbs(struct stub_device * sdev)34796c27377SValentina Manea void stub_device_cleanup_urbs(struct stub_device *sdev)
34896c27377SValentina Manea {
34996c27377SValentina Manea struct stub_priv *priv;
350ea44d190SSuwan Kim int i;
35196c27377SValentina Manea
352248a2204SShuah Khan dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n");
35396c27377SValentina Manea
35496c27377SValentina Manea while ((priv = stub_priv_pop(sdev))) {
355ea44d190SSuwan Kim for (i = 0; i < priv->num_urbs; i++)
356ea44d190SSuwan Kim usb_kill_urb(priv->urbs[i]);
35796c27377SValentina Manea
358ea44d190SSuwan Kim stub_free_priv_and_urb(priv);
35996c27377SValentina Manea }
36096c27377SValentina Manea }
36196c27377SValentina Manea
usbip_host_init(void)36296c27377SValentina Manea static int __init usbip_host_init(void)
36396c27377SValentina Manea {
36496c27377SValentina Manea int ret;
36596c27377SValentina Manea
36696c27377SValentina Manea init_busid_table();
36796c27377SValentina Manea
36896c27377SValentina Manea stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
36996c27377SValentina Manea if (!stub_priv_cache) {
37096c27377SValentina Manea pr_err("kmem_cache_create failed\n");
37196c27377SValentina Manea return -ENOMEM;
37296c27377SValentina Manea }
37396c27377SValentina Manea
37496c27377SValentina Manea ret = usb_register_device_driver(&stub_driver, THIS_MODULE);
37596c27377SValentina Manea if (ret) {
37696c27377SValentina Manea pr_err("usb_register failed %d\n", ret);
37796c27377SValentina Manea goto err_usb_register;
37896c27377SValentina Manea }
37996c27377SValentina Manea
38096c27377SValentina Manea ret = driver_create_file(&stub_driver.drvwrap.driver,
38196c27377SValentina Manea &driver_attr_match_busid);
38296c27377SValentina Manea if (ret) {
38396c27377SValentina Manea pr_err("driver_create_file failed\n");
38496c27377SValentina Manea goto err_create_file;
38596c27377SValentina Manea }
38696c27377SValentina Manea
38796c27377SValentina Manea ret = driver_create_file(&stub_driver.drvwrap.driver,
38896c27377SValentina Manea &driver_attr_rebind);
38996c27377SValentina Manea if (ret) {
39096c27377SValentina Manea pr_err("driver_create_file failed\n");
39196c27377SValentina Manea goto err_create_file;
39296c27377SValentina Manea }
39396c27377SValentina Manea
39496c27377SValentina Manea return ret;
39596c27377SValentina Manea
39696c27377SValentina Manea err_create_file:
39796c27377SValentina Manea usb_deregister_device_driver(&stub_driver);
39896c27377SValentina Manea err_usb_register:
39996c27377SValentina Manea kmem_cache_destroy(stub_priv_cache);
40096c27377SValentina Manea return ret;
40196c27377SValentina Manea }
40296c27377SValentina Manea
usbip_host_exit(void)40396c27377SValentina Manea static void __exit usbip_host_exit(void)
40496c27377SValentina Manea {
40596c27377SValentina Manea driver_remove_file(&stub_driver.drvwrap.driver,
40696c27377SValentina Manea &driver_attr_match_busid);
40796c27377SValentina Manea
40896c27377SValentina Manea driver_remove_file(&stub_driver.drvwrap.driver,
40996c27377SValentina Manea &driver_attr_rebind);
41096c27377SValentina Manea
41196c27377SValentina Manea /*
41296c27377SValentina Manea * deregister() calls stub_disconnect() for all devices. Device
41396c27377SValentina Manea * specific data is cleared in stub_disconnect().
41496c27377SValentina Manea */
41596c27377SValentina Manea usb_deregister_device_driver(&stub_driver);
41696c27377SValentina Manea
4177510df3fSShuah Khan (Samsung OSG) /* initiate scan to attach devices */
4187510df3fSShuah Khan (Samsung OSG) stub_device_rebind();
4197510df3fSShuah Khan (Samsung OSG)
42096c27377SValentina Manea kmem_cache_destroy(stub_priv_cache);
42196c27377SValentina Manea }
42296c27377SValentina Manea
42396c27377SValentina Manea module_init(usbip_host_init);
42496c27377SValentina Manea module_exit(usbip_host_exit);
42596c27377SValentina Manea
42696c27377SValentina Manea MODULE_AUTHOR(DRIVER_AUTHOR);
42796c27377SValentina Manea MODULE_DESCRIPTION(DRIVER_DESC);
42896c27377SValentina Manea MODULE_LICENSE("GPL");
429