xref: /openbmc/linux/drivers/usb/usbip/stub_main.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
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