spi: imx: do not access registers while clocks disabled
[platform/kernel/linux-starfive.git] / drivers / usb / usbip / stub_main.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2003-2008 Takahiro Hirofuchi
4  */
5
6 #include <linux/string.h>
7 #include <linux/module.h>
8 #include <linux/device.h>
9
10 #include "usbip_common.h"
11 #include "stub.h"
12
13 #define DRIVER_AUTHOR "Takahiro Hirofuchi"
14 #define DRIVER_DESC "USB/IP Host Driver"
15
16 struct kmem_cache *stub_priv_cache;
17 /*
18  * busid_tables defines matching busids that usbip can grab. A user can change
19  * dynamically what device is locally used and what device is exported to a
20  * remote host.
21  */
22 #define MAX_BUSID 16
23 static struct bus_id_priv busid_table[MAX_BUSID];
24 static spinlock_t busid_table_lock;
25
26 static void init_busid_table(void)
27 {
28         /*
29          * This also sets the bus_table[i].status to
30          * STUB_BUSID_OTHER, which is 0.
31          */
32         memset(busid_table, 0, sizeof(busid_table));
33
34         spin_lock_init(&busid_table_lock);
35 }
36
37 /*
38  * Find the index of the busid by name.
39  * Must be called with busid_table_lock held.
40  */
41 static int get_busid_idx(const char *busid)
42 {
43         int i;
44         int idx = -1;
45
46         for (i = 0; i < MAX_BUSID; i++)
47                 if (busid_table[i].name[0])
48                         if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
49                                 idx = i;
50                                 break;
51                         }
52         return idx;
53 }
54
55 struct bus_id_priv *get_busid_priv(const char *busid)
56 {
57         int idx;
58         struct bus_id_priv *bid = NULL;
59
60         spin_lock(&busid_table_lock);
61         idx = get_busid_idx(busid);
62         if (idx >= 0)
63                 bid = &(busid_table[idx]);
64         spin_unlock(&busid_table_lock);
65
66         return bid;
67 }
68
69 static int add_match_busid(char *busid)
70 {
71         int i;
72         int ret = -1;
73
74         spin_lock(&busid_table_lock);
75         /* already registered? */
76         if (get_busid_idx(busid) >= 0) {
77                 ret = 0;
78                 goto out;
79         }
80
81         for (i = 0; i < MAX_BUSID; i++)
82                 if (!busid_table[i].name[0]) {
83                         strlcpy(busid_table[i].name, busid, BUSID_SIZE);
84                         if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
85                             (busid_table[i].status != STUB_BUSID_REMOV))
86                                 busid_table[i].status = STUB_BUSID_ADDED;
87                         ret = 0;
88                         break;
89                 }
90
91 out:
92         spin_unlock(&busid_table_lock);
93
94         return ret;
95 }
96
97 int del_match_busid(char *busid)
98 {
99         int idx;
100         int ret = -1;
101
102         spin_lock(&busid_table_lock);
103         idx = get_busid_idx(busid);
104         if (idx < 0)
105                 goto out;
106
107         /* found */
108         ret = 0;
109
110         if (busid_table[idx].status == STUB_BUSID_OTHER)
111                 memset(busid_table[idx].name, 0, BUSID_SIZE);
112
113         if ((busid_table[idx].status != STUB_BUSID_OTHER) &&
114             (busid_table[idx].status != STUB_BUSID_ADDED))
115                 busid_table[idx].status = STUB_BUSID_REMOV;
116
117 out:
118         spin_unlock(&busid_table_lock);
119
120         return ret;
121 }
122
123 static ssize_t match_busid_show(struct device_driver *drv, char *buf)
124 {
125         int i;
126         char *out = buf;
127
128         spin_lock(&busid_table_lock);
129         for (i = 0; i < MAX_BUSID; i++)
130                 if (busid_table[i].name[0])
131                         out += sprintf(out, "%s ", busid_table[i].name);
132         spin_unlock(&busid_table_lock);
133         out += sprintf(out, "\n");
134
135         return out - buf;
136 }
137
138 static ssize_t match_busid_store(struct device_driver *dev, const char *buf,
139                                  size_t count)
140 {
141         int len;
142         char busid[BUSID_SIZE];
143
144         if (count < 5)
145                 return -EINVAL;
146
147         /* busid needs to include \0 termination */
148         len = strlcpy(busid, buf + 4, BUSID_SIZE);
149         if (sizeof(busid) <= len)
150                 return -EINVAL;
151
152         if (!strncmp(buf, "add ", 4)) {
153                 if (add_match_busid(busid) < 0)
154                         return -ENOMEM;
155
156                 pr_debug("add busid %s\n", busid);
157                 return count;
158         }
159
160         if (!strncmp(buf, "del ", 4)) {
161                 if (del_match_busid(busid) < 0)
162                         return -ENODEV;
163
164                 pr_debug("del busid %s\n", busid);
165                 return count;
166         }
167
168         return -EINVAL;
169 }
170 static DRIVER_ATTR_RW(match_busid);
171
172 static ssize_t rebind_store(struct device_driver *dev, const char *buf,
173                                  size_t count)
174 {
175         int ret;
176         int len;
177         struct bus_id_priv *bid;
178
179         /* buf length should be less that BUSID_SIZE */
180         len = strnlen(buf, BUSID_SIZE);
181
182         if (!(len < BUSID_SIZE))
183                 return -EINVAL;
184
185         bid = get_busid_priv(buf);
186         if (!bid)
187                 return -ENODEV;
188
189         ret = device_attach(&bid->udev->dev);
190         if (ret < 0) {
191                 dev_err(&bid->udev->dev, "rebind failed\n");
192                 return ret;
193         }
194
195         return count;
196 }
197
198 static DRIVER_ATTR_WO(rebind);
199
200 static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
201 {
202         struct stub_priv *priv, *tmp;
203
204         list_for_each_entry_safe(priv, tmp, listhead, list) {
205                 list_del(&priv->list);
206                 return priv;
207         }
208
209         return NULL;
210 }
211
212 static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
213 {
214         unsigned long flags;
215         struct stub_priv *priv;
216
217         spin_lock_irqsave(&sdev->priv_lock, flags);
218
219         priv = stub_priv_pop_from_listhead(&sdev->priv_init);
220         if (priv)
221                 goto done;
222
223         priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
224         if (priv)
225                 goto done;
226
227         priv = stub_priv_pop_from_listhead(&sdev->priv_free);
228
229 done:
230         spin_unlock_irqrestore(&sdev->priv_lock, flags);
231
232         return priv;
233 }
234
235 void stub_device_cleanup_urbs(struct stub_device *sdev)
236 {
237         struct stub_priv *priv;
238         struct urb *urb;
239
240         dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev);
241
242         while ((priv = stub_priv_pop(sdev))) {
243                 urb = priv->urb;
244                 dev_dbg(&sdev->udev->dev, "free urb %p\n", urb);
245                 usb_kill_urb(urb);
246
247                 kmem_cache_free(stub_priv_cache, priv);
248
249                 kfree(urb->transfer_buffer);
250                 urb->transfer_buffer = NULL;
251
252                 kfree(urb->setup_packet);
253                 urb->setup_packet = NULL;
254
255                 usb_free_urb(urb);
256         }
257 }
258
259 static int __init usbip_host_init(void)
260 {
261         int ret;
262
263         init_busid_table();
264
265         stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
266         if (!stub_priv_cache) {
267                 pr_err("kmem_cache_create failed\n");
268                 return -ENOMEM;
269         }
270
271         ret = usb_register_device_driver(&stub_driver, THIS_MODULE);
272         if (ret) {
273                 pr_err("usb_register failed %d\n", ret);
274                 goto err_usb_register;
275         }
276
277         ret = driver_create_file(&stub_driver.drvwrap.driver,
278                                  &driver_attr_match_busid);
279         if (ret) {
280                 pr_err("driver_create_file failed\n");
281                 goto err_create_file;
282         }
283
284         ret = driver_create_file(&stub_driver.drvwrap.driver,
285                                  &driver_attr_rebind);
286         if (ret) {
287                 pr_err("driver_create_file failed\n");
288                 goto err_create_file;
289         }
290
291         return ret;
292
293 err_create_file:
294         usb_deregister_device_driver(&stub_driver);
295 err_usb_register:
296         kmem_cache_destroy(stub_priv_cache);
297         return ret;
298 }
299
300 static void __exit usbip_host_exit(void)
301 {
302         driver_remove_file(&stub_driver.drvwrap.driver,
303                            &driver_attr_match_busid);
304
305         driver_remove_file(&stub_driver.drvwrap.driver,
306                            &driver_attr_rebind);
307
308         /*
309          * deregister() calls stub_disconnect() for all devices. Device
310          * specific data is cleared in stub_disconnect().
311          */
312         usb_deregister_device_driver(&stub_driver);
313
314         kmem_cache_destroy(stub_priv_cache);
315 }
316
317 module_init(usbip_host_init);
318 module_exit(usbip_host_exit);
319
320 MODULE_AUTHOR(DRIVER_AUTHOR);
321 MODULE_DESCRIPTION(DRIVER_DESC);
322 MODULE_LICENSE("GPL");