diff options
author | Takahiro Hirofuchi <hirofuchi@users.sourceforge.net> | 2008-07-09 16:56:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-10 18:31:09 -0400 |
commit | 4d7b5c7f8ad49b7f01fb8aed83c560ac43cfbda8 (patch) | |
tree | b9a643d4dd14f7048356b21fcb136293efff5b54 | |
parent | 04679b3489e048cd5dae79e050a3afed8e4e42b6 (diff) |
Staging: USB/IP: add host driver
This adds the USB IP client driver
Brian Merrell cleaned up a lot of this code and submitted it for
inclusion. Greg also did a lot of cleanup.
Signed-off-by: Brian G. Merrell <bgmerrell@novell.com>
Cc: Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/usbip/Kconfig | 11 | ||||
-rw-r--r-- | drivers/staging/usbip/Makefile | 3 | ||||
-rw-r--r-- | drivers/staging/usbip/stub.h | 95 | ||||
-rw-r--r-- | drivers/staging/usbip/stub_dev.c | 483 | ||||
-rw-r--r-- | drivers/staging/usbip/stub_main.c | 300 | ||||
-rw-r--r-- | drivers/staging/usbip/stub_rx.c | 615 | ||||
-rw-r--r-- | drivers/staging/usbip/stub_tx.c | 371 |
7 files changed, 1878 insertions, 0 deletions
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig index c4d68e1581fc..7426235ccc44 100644 --- a/drivers/staging/usbip/Kconfig +++ b/drivers/staging/usbip/Kconfig | |||
@@ -23,3 +23,14 @@ config USB_IP_VHCI_HCD | |||
23 | 23 | ||
24 | To compile this driver as a module, choose M here: the | 24 | To compile this driver as a module, choose M here: the |
25 | module will be called vhci_hcd. | 25 | module will be called vhci_hcd. |
26 | |||
27 | config USB_IP_HOST | ||
28 | tristate "USB IP host driver" | ||
29 | depends on USB_IP_COMMON | ||
30 | default N | ||
31 | ---help--- | ||
32 | This enables the USB IP device driver which will run on the | ||
33 | host machine. | ||
34 | |||
35 | To compile this driver as a module, choose M here: the | ||
36 | module will be called usbip. | ||
diff --git a/drivers/staging/usbip/Makefile b/drivers/staging/usbip/Makefile index 6ef4c3913f45..179f4211f96b 100644 --- a/drivers/staging/usbip/Makefile +++ b/drivers/staging/usbip/Makefile | |||
@@ -4,6 +4,9 @@ usbip_common_mod-objs := usbip_common.o usbip_event.o | |||
4 | obj-$(CONFIG_USB_IP_VHCI_HCD) += vhci-hcd.o | 4 | obj-$(CONFIG_USB_IP_VHCI_HCD) += vhci-hcd.o |
5 | vhci-hcd-objs := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o | 5 | vhci-hcd-objs := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o |
6 | 6 | ||
7 | obj-$(CONFIG_USB_IP_HOST) += usbip.o | ||
8 | usbip-objs := stub_dev.o stub_main.o stub_rx.o stub_tx.o | ||
9 | |||
7 | ifeq ($(CONFIG_USB_DEBUG),y) | 10 | ifeq ($(CONFIG_USB_DEBUG),y) |
8 | EXTRA_CFLAGS += -DDEBUG | 11 | EXTRA_CFLAGS += -DDEBUG |
9 | endif | 12 | endif |
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h new file mode 100644 index 000000000000..f541a3a83bd3 --- /dev/null +++ b/drivers/staging/usbip/stub.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003-2008 Takahiro Hirofuchi | ||
3 | * | ||
4 | * This is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
17 | * USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/net.h> | ||
27 | |||
28 | struct stub_device { | ||
29 | struct usb_interface *interface; | ||
30 | struct list_head list; | ||
31 | |||
32 | struct usbip_device ud; | ||
33 | __u32 devid; | ||
34 | |||
35 | /* | ||
36 | * stub_priv preserves private data of each urb. | ||
37 | * It is allocated as stub_priv_cache and assigned to urb->context. | ||
38 | * | ||
39 | * stub_priv is always linked to any one of 3 lists; | ||
40 | * priv_init: linked to this until the comletion of a urb. | ||
41 | * priv_tx : linked to this after the completion of a urb. | ||
42 | * priv_free: linked to this after the sending of the result. | ||
43 | * | ||
44 | * Any of these list operations should be locked by priv_lock. | ||
45 | */ | ||
46 | spinlock_t priv_lock; | ||
47 | struct list_head priv_init; | ||
48 | struct list_head priv_tx; | ||
49 | struct list_head priv_free; | ||
50 | |||
51 | /* see comments for unlinking in stub_rx.c */ | ||
52 | struct list_head unlink_tx; | ||
53 | struct list_head unlink_free; | ||
54 | |||
55 | |||
56 | wait_queue_head_t tx_waitq; | ||
57 | }; | ||
58 | |||
59 | /* private data into urb->priv */ | ||
60 | struct stub_priv { | ||
61 | unsigned long seqnum; | ||
62 | struct list_head list; | ||
63 | struct stub_device *sdev; | ||
64 | struct urb *urb; | ||
65 | |||
66 | int unlinking; | ||
67 | }; | ||
68 | |||
69 | struct stub_unlink { | ||
70 | unsigned long seqnum; | ||
71 | struct list_head list; | ||
72 | __u32 status; | ||
73 | }; | ||
74 | |||
75 | |||
76 | extern struct kmem_cache *stub_priv_cache; | ||
77 | |||
78 | |||
79 | /*-------------------------------------------------------------------------*/ | ||
80 | /* prototype declarations */ | ||
81 | |||
82 | /* stub_tx.c */ | ||
83 | void stub_complete(struct urb *); | ||
84 | void stub_tx_loop(struct usbip_task *); | ||
85 | |||
86 | /* stub_dev.c */ | ||
87 | extern struct usb_driver stub_driver; | ||
88 | |||
89 | /* stub_rx.c */ | ||
90 | void stub_rx_loop(struct usbip_task *); | ||
91 | void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32); | ||
92 | |||
93 | /* stub_main.c */ | ||
94 | int match_busid(char *busid); | ||
95 | void stub_device_cleanup_urbs(struct stub_device *sdev); | ||
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c new file mode 100644 index 000000000000..ee455a087eaf --- /dev/null +++ b/drivers/staging/usbip/stub_dev.c | |||
@@ -0,0 +1,483 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003-2008 Takahiro Hirofuchi | ||
3 | * | ||
4 | * This is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
17 | * USA. | ||
18 | */ | ||
19 | |||
20 | #include "usbip_common.h" | ||
21 | #include "stub.h" | ||
22 | |||
23 | |||
24 | |||
25 | static int stub_probe(struct usb_interface *interface, | ||
26 | const struct usb_device_id *id); | ||
27 | static void stub_disconnect(struct usb_interface *interface); | ||
28 | |||
29 | |||
30 | /* | ||
31 | * Define device IDs here if you want to explicitly limit exportable devices. | ||
32 | * In the most cases, wild card matching will be ok because driver binding can | ||
33 | * be changed dynamically by a userland program. | ||
34 | */ | ||
35 | static struct usb_device_id stub_table[] = { | ||
36 | #if 0 | ||
37 | /* just an example */ | ||
38 | { USB_DEVICE(0x05ac, 0x0301) }, /* Mac 1 button mouse */ | ||
39 | { USB_DEVICE(0x0430, 0x0009) }, /* Plat Home Keyboard */ | ||
40 | { USB_DEVICE(0x059b, 0x0001) }, /* Iomega USB Zip 100 */ | ||
41 | { USB_DEVICE(0x04b3, 0x4427) }, /* IBM USB CD-ROM */ | ||
42 | { USB_DEVICE(0x05a9, 0xa511) }, /* LifeView USB cam */ | ||
43 | { USB_DEVICE(0x55aa, 0x0201) }, /* Imation card reader */ | ||
44 | { USB_DEVICE(0x046d, 0x0870) }, /* Qcam Express(QV-30) */ | ||
45 | { USB_DEVICE(0x04bb, 0x0101) }, /* IO-DATA HD 120GB */ | ||
46 | { USB_DEVICE(0x04bb, 0x0904) }, /* IO-DATA USB-ET/TX */ | ||
47 | { USB_DEVICE(0x04bb, 0x0201) }, /* IO-DATA USB-ET/TX */ | ||
48 | { USB_DEVICE(0x08bb, 0x2702) }, /* ONKYO USB Speaker */ | ||
49 | { USB_DEVICE(0x046d, 0x08b2) }, /* Logicool Qcam 4000 Pro */ | ||
50 | #endif | ||
51 | /* magic for wild card */ | ||
52 | { .driver_info = 1 }, | ||
53 | { 0, } /* Terminating entry */ | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(usb, stub_table); | ||
56 | |||
57 | struct usb_driver stub_driver = { | ||
58 | .name = "usbip", | ||
59 | .probe = stub_probe, | ||
60 | .disconnect = stub_disconnect, | ||
61 | .id_table = stub_table, | ||
62 | }; | ||
63 | |||
64 | |||
65 | /*-------------------------------------------------------------------------*/ | ||
66 | |||
67 | /* Define sysfs entries for a usbip-bound device */ | ||
68 | |||
69 | |||
70 | /* | ||
71 | * usbip_status shows status of usbip as long as this driver is bound to the | ||
72 | * target device. | ||
73 | */ | ||
74 | static ssize_t show_status(struct device *dev, struct device_attribute *attr, | ||
75 | char *buf) | ||
76 | { | ||
77 | struct stub_device *sdev = dev_get_drvdata(dev); | ||
78 | int status; | ||
79 | |||
80 | if (!sdev) { | ||
81 | dev_err(dev, "sdev is null\n"); | ||
82 | return -ENODEV; | ||
83 | } | ||
84 | |||
85 | spin_lock(&sdev->ud.lock); | ||
86 | status = sdev->ud.status; | ||
87 | spin_unlock(&sdev->ud.lock); | ||
88 | |||
89 | return snprintf(buf, PAGE_SIZE, "%d\n", status); | ||
90 | } | ||
91 | static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL); | ||
92 | |||
93 | /* | ||
94 | * usbip_sockfd gets a socket descriptor of an established TCP connection that | ||
95 | * is used to transfer usbip requests by kernel threads. -1 is a magic number | ||
96 | * by which usbip connection is finished. | ||
97 | */ | ||
98 | static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, | ||
99 | const char *buf, size_t count) | ||
100 | { | ||
101 | struct stub_device *sdev = dev_get_drvdata(dev); | ||
102 | int sockfd = 0; | ||
103 | struct socket *socket; | ||
104 | |||
105 | if (!sdev) { | ||
106 | dev_err(dev, "sdev is null\n"); | ||
107 | return -ENODEV; | ||
108 | } | ||
109 | |||
110 | sscanf(buf, "%d", &sockfd); | ||
111 | |||
112 | if (sockfd != -1) { | ||
113 | dev_info(dev, "stub up\n"); | ||
114 | |||
115 | spin_lock(&sdev->ud.lock); | ||
116 | |||
117 | if (sdev->ud.status != SDEV_ST_AVAILABLE) { | ||
118 | dev_err(dev, "not ready\n"); | ||
119 | spin_unlock(&sdev->ud.lock); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | socket = sockfd_to_socket(sockfd); | ||
124 | if (!socket) { | ||
125 | spin_unlock(&sdev->ud.lock); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | #if 0 | ||
130 | setnodelay(socket); | ||
131 | setkeepalive(socket); | ||
132 | setreuse(socket); | ||
133 | #endif | ||
134 | |||
135 | sdev->ud.tcp_socket = socket; | ||
136 | |||
137 | spin_unlock(&sdev->ud.lock); | ||
138 | |||
139 | usbip_start_threads(&sdev->ud); | ||
140 | |||
141 | spin_lock(&sdev->ud.lock); | ||
142 | sdev->ud.status = SDEV_ST_USED; | ||
143 | spin_unlock(&sdev->ud.lock); | ||
144 | |||
145 | } else { | ||
146 | dev_info(dev, "stub down\n"); | ||
147 | |||
148 | spin_lock(&sdev->ud.lock); | ||
149 | if (sdev->ud.status != SDEV_ST_USED) { | ||
150 | spin_unlock(&sdev->ud.lock); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | spin_unlock(&sdev->ud.lock); | ||
154 | |||
155 | usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); | ||
156 | } | ||
157 | |||
158 | return count; | ||
159 | } | ||
160 | static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); | ||
161 | |||
162 | static int stub_add_files(struct device *dev) | ||
163 | { | ||
164 | int err = 0; | ||
165 | |||
166 | err = device_create_file(dev, &dev_attr_usbip_status); | ||
167 | if (err) | ||
168 | goto err_status; | ||
169 | |||
170 | err = device_create_file(dev, &dev_attr_usbip_sockfd); | ||
171 | if (err) | ||
172 | goto err_sockfd; | ||
173 | |||
174 | err = device_create_file(dev, &dev_attr_usbip_debug); | ||
175 | if (err) | ||
176 | goto err_debug; | ||
177 | |||
178 | return 0; | ||
179 | |||
180 | err_debug: | ||
181 | device_remove_file(dev, &dev_attr_usbip_sockfd); | ||
182 | |||
183 | err_sockfd: | ||
184 | device_remove_file(dev, &dev_attr_usbip_status); | ||
185 | |||
186 | err_status: | ||
187 | return err; | ||
188 | } | ||
189 | |||
190 | static void stub_remove_files(struct device *dev) | ||
191 | { | ||
192 | device_remove_file(dev, &dev_attr_usbip_status); | ||
193 | device_remove_file(dev, &dev_attr_usbip_sockfd); | ||
194 | device_remove_file(dev, &dev_attr_usbip_debug); | ||
195 | } | ||
196 | |||
197 | |||
198 | |||
199 | /*-------------------------------------------------------------------------*/ | ||
200 | |||
201 | /* Event handler functions called by an event handler thread */ | ||
202 | |||
203 | static void stub_shutdown_connection(struct usbip_device *ud) | ||
204 | { | ||
205 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | ||
206 | |||
207 | /* | ||
208 | * When removing an exported device, kernel panic sometimes occurred | ||
209 | * and then EIP was sk_wait_data of stub_rx thread. Is this because | ||
210 | * sk_wait_data returned though stub_rx thread was already finished by | ||
211 | * step 1? | ||
212 | */ | ||
213 | if (ud->tcp_socket) { | ||
214 | udbg("shutdown tcp_socket %p\n", ud->tcp_socket); | ||
215 | kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); | ||
216 | } | ||
217 | |||
218 | /* 1. stop threads */ | ||
219 | usbip_stop_threads(ud); | ||
220 | |||
221 | /* 2. close the socket */ | ||
222 | /* | ||
223 | * tcp_socket is freed after threads are killed. | ||
224 | * So usbip_xmit do not touch NULL socket. | ||
225 | */ | ||
226 | if (ud->tcp_socket) { | ||
227 | sock_release(ud->tcp_socket); | ||
228 | ud->tcp_socket = NULL; | ||
229 | } | ||
230 | |||
231 | /* 3. free used data */ | ||
232 | stub_device_cleanup_urbs(sdev); | ||
233 | |||
234 | /* 4. free stub_unlink */ | ||
235 | { | ||
236 | unsigned long flags; | ||
237 | struct stub_unlink *unlink, *tmp; | ||
238 | |||
239 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
240 | |||
241 | list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { | ||
242 | list_del(&unlink->list); | ||
243 | kfree(unlink); | ||
244 | } | ||
245 | |||
246 | list_for_each_entry_safe(unlink, tmp, | ||
247 | &sdev->unlink_free, list) { | ||
248 | list_del(&unlink->list); | ||
249 | kfree(unlink); | ||
250 | } | ||
251 | |||
252 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | static void stub_device_reset(struct usbip_device *ud) | ||
257 | { | ||
258 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | ||
259 | struct usb_device *udev = interface_to_usbdev(sdev->interface); | ||
260 | int ret; | ||
261 | |||
262 | udbg("device reset"); | ||
263 | ret = usb_lock_device_for_reset(udev, sdev->interface); | ||
264 | if (ret < 0) { | ||
265 | dev_err(&udev->dev, "lock for reset\n"); | ||
266 | |||
267 | spin_lock(&ud->lock); | ||
268 | ud->status = SDEV_ST_ERROR; | ||
269 | spin_unlock(&ud->lock); | ||
270 | |||
271 | return; | ||
272 | } | ||
273 | |||
274 | /* try to reset the device */ | ||
275 | ret = usb_reset_device(udev); | ||
276 | |||
277 | usb_unlock_device(udev); | ||
278 | |||
279 | spin_lock(&ud->lock); | ||
280 | if (ret) { | ||
281 | dev_err(&udev->dev, "device reset\n"); | ||
282 | ud->status = SDEV_ST_ERROR; | ||
283 | |||
284 | } else { | ||
285 | dev_info(&udev->dev, "device reset\n"); | ||
286 | ud->status = SDEV_ST_AVAILABLE; | ||
287 | |||
288 | } | ||
289 | spin_unlock(&ud->lock); | ||
290 | |||
291 | return; | ||
292 | } | ||
293 | |||
294 | static void stub_device_unusable(struct usbip_device *ud) | ||
295 | { | ||
296 | spin_lock(&ud->lock); | ||
297 | ud->status = SDEV_ST_ERROR; | ||
298 | spin_unlock(&ud->lock); | ||
299 | } | ||
300 | |||
301 | |||
302 | /*-------------------------------------------------------------------------*/ | ||
303 | |||
304 | /** | ||
305 | * stub_device_alloc - allocate a new stub_device struct | ||
306 | * @interface: usb_interface of a new device | ||
307 | * | ||
308 | * Allocates and initializes a new stub_device struct. | ||
309 | */ | ||
310 | static struct stub_device *stub_device_alloc(struct usb_interface *interface) | ||
311 | { | ||
312 | struct stub_device *sdev; | ||
313 | int busnum = interface_to_busnum(interface); | ||
314 | int devnum = interface_to_devnum(interface); | ||
315 | |||
316 | dev_dbg(&interface->dev, "allocating stub device"); | ||
317 | |||
318 | /* yes, it's a new device */ | ||
319 | sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL); | ||
320 | if (!sdev) { | ||
321 | dev_err(&interface->dev, "no memory for stub_device\n"); | ||
322 | return NULL; | ||
323 | } | ||
324 | |||
325 | sdev->interface = interface; | ||
326 | |||
327 | /* | ||
328 | * devid is defined with devnum when this driver is first allocated. | ||
329 | * devnum may change later if a device is reset. However, devid never | ||
330 | * changes during a usbip connection. | ||
331 | */ | ||
332 | sdev->devid = (busnum << 16) | devnum; | ||
333 | |||
334 | usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop); | ||
335 | usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop); | ||
336 | |||
337 | sdev->ud.side = USBIP_STUB; | ||
338 | sdev->ud.status = SDEV_ST_AVAILABLE; | ||
339 | /* sdev->ud.lock = SPIN_LOCK_UNLOCKED; */ | ||
340 | spin_lock_init(&sdev->ud.lock); | ||
341 | sdev->ud.tcp_socket = NULL; | ||
342 | |||
343 | INIT_LIST_HEAD(&sdev->priv_init); | ||
344 | INIT_LIST_HEAD(&sdev->priv_tx); | ||
345 | INIT_LIST_HEAD(&sdev->priv_free); | ||
346 | INIT_LIST_HEAD(&sdev->unlink_free); | ||
347 | INIT_LIST_HEAD(&sdev->unlink_tx); | ||
348 | /* sdev->priv_lock = SPIN_LOCK_UNLOCKED; */ | ||
349 | spin_lock_init(&sdev->priv_lock); | ||
350 | |||
351 | init_waitqueue_head(&sdev->tx_waitq); | ||
352 | |||
353 | sdev->ud.eh_ops.shutdown = stub_shutdown_connection; | ||
354 | sdev->ud.eh_ops.reset = stub_device_reset; | ||
355 | sdev->ud.eh_ops.unusable = stub_device_unusable; | ||
356 | |||
357 | usbip_start_eh(&sdev->ud); | ||
358 | |||
359 | udbg("register new interface\n"); | ||
360 | return sdev; | ||
361 | } | ||
362 | |||
363 | static int stub_device_free(struct stub_device *sdev) | ||
364 | { | ||
365 | if (!sdev) | ||
366 | return -EINVAL; | ||
367 | |||
368 | kfree(sdev); | ||
369 | udbg("kfree udev ok\n"); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | |||
375 | /*-------------------------------------------------------------------------*/ | ||
376 | |||
377 | /* | ||
378 | * If a usb device has multiple active interfaces, this driver is bound to all | ||
379 | * the active interfaces. However, usbip exports *a* usb device (i.e., not *an* | ||
380 | * active interface). Currently, a userland program must ensure that it | ||
381 | * looks at the usbip's sysfs entries of only the first active interface. | ||
382 | * | ||
383 | * TODO: use "struct usb_device_driver" to bind a usb device. | ||
384 | * However, it seems it is not fully supported in mainline kernel yet | ||
385 | * (2.6.19.2). | ||
386 | */ | ||
387 | static int stub_probe(struct usb_interface *interface, | ||
388 | const struct usb_device_id *id) | ||
389 | { | ||
390 | struct usb_device *udev = interface_to_usbdev(interface); | ||
391 | struct stub_device *sdev = NULL; | ||
392 | char *udev_busid = interface->dev.parent->bus_id; | ||
393 | int err = 0; | ||
394 | |||
395 | dev_dbg(&interface->dev, "Enter\n"); | ||
396 | |||
397 | /* check we should claim or not by busid_table */ | ||
398 | if (match_busid(udev_busid)) { | ||
399 | dev_info(&interface->dev, | ||
400 | "this device %s is not in match_busid table. skip!\n", | ||
401 | udev_busid); | ||
402 | |||
403 | /* | ||
404 | * Return value should be ENODEV or ENOXIO to continue trying | ||
405 | * other matched drivers by the driver core. | ||
406 | * See driver_probe_device() in driver/base/dd.c | ||
407 | */ | ||
408 | return -ENODEV; | ||
409 | } | ||
410 | |||
411 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { | ||
412 | udbg("this device %s is a usb hub device. skip!\n", | ||
413 | udev_busid); | ||
414 | return -ENODEV; | ||
415 | } | ||
416 | |||
417 | if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { | ||
418 | udbg("this device %s is attached on vhci_hcd. skip!\n", | ||
419 | udev_busid); | ||
420 | return -ENODEV; | ||
421 | } | ||
422 | |||
423 | /* ok. this is my device. */ | ||
424 | sdev = stub_device_alloc(interface); | ||
425 | if (!sdev) | ||
426 | return -ENOMEM; | ||
427 | |||
428 | dev_info(&interface->dev, "USB/IP Stub: register a new interface " | ||
429 | "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum, | ||
430 | interface->cur_altsetting->desc.bInterfaceNumber); | ||
431 | |||
432 | /* set private data to usb_interface */ | ||
433 | usb_set_intfdata(interface, sdev); | ||
434 | |||
435 | err = stub_add_files(&interface->dev); | ||
436 | if (err) { | ||
437 | dev_err(&interface->dev, "create sysfs files for %s\n", | ||
438 | udev_busid); | ||
439 | return err; | ||
440 | } | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | |||
446 | /* | ||
447 | * called in usb_disconnect() or usb_deregister() | ||
448 | * but only if actconfig(active configuration) exists | ||
449 | */ | ||
450 | static void stub_disconnect(struct usb_interface *interface) | ||
451 | { | ||
452 | struct stub_device *sdev = usb_get_intfdata(interface); | ||
453 | |||
454 | udbg("Enter\n"); | ||
455 | |||
456 | /* get stub_device */ | ||
457 | if (!sdev) { | ||
458 | err(" could not get device from inteface data"); | ||
459 | /* BUG(); */ | ||
460 | return; | ||
461 | } | ||
462 | |||
463 | usb_set_intfdata(interface, NULL); | ||
464 | |||
465 | |||
466 | /* | ||
467 | * NOTE: | ||
468 | * rx/tx threads are invoked for each usb_device. | ||
469 | */ | ||
470 | stub_remove_files(&interface->dev); | ||
471 | |||
472 | /* 1. shutdown the current connection */ | ||
473 | usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED); | ||
474 | |||
475 | /* 2. wait for the stop of the event handler */ | ||
476 | usbip_stop_eh(&sdev->ud); | ||
477 | |||
478 | /* 3. free sdev */ | ||
479 | stub_device_free(sdev); | ||
480 | |||
481 | |||
482 | udbg("bye\n"); | ||
483 | } | ||
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c new file mode 100644 index 000000000000..c665d7f1ca9a --- /dev/null +++ b/drivers/staging/usbip/stub_main.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003-2008 Takahiro Hirofuchi | ||
3 | * | ||
4 | * This is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
17 | * USA. | ||
18 | */ | ||
19 | |||
20 | |||
21 | #include "usbip_common.h" | ||
22 | #include "stub.h" | ||
23 | |||
24 | /* Version Information */ | ||
25 | #define DRIVER_VERSION "1.0" | ||
26 | #define DRIVER_AUTHOR "Takahiro Hirofuchi" | ||
27 | #define DRIVER_DESC "Stub Driver for USB/IP" | ||
28 | |||
29 | /* stub_priv is allocated from stub_priv_cache */ | ||
30 | struct kmem_cache *stub_priv_cache; | ||
31 | |||
32 | /*-------------------------------------------------------------------------*/ | ||
33 | |||
34 | /* Define sysfs entries for the usbip driver */ | ||
35 | |||
36 | |||
37 | /* | ||
38 | * busid_tables defines matching busids that usbip can grab. A user can change | ||
39 | * dynamically what device is locally used and what device is exported to a | ||
40 | * remote host. | ||
41 | */ | ||
42 | #define MAX_BUSID 16 | ||
43 | static char busid_table[MAX_BUSID][BUS_ID_SIZE]; | ||
44 | static spinlock_t busid_table_lock; | ||
45 | |||
46 | |||
47 | int match_busid(char *busid) | ||
48 | { | ||
49 | int i; | ||
50 | |||
51 | spin_lock(&busid_table_lock); | ||
52 | |||
53 | for (i = 0; i < MAX_BUSID; i++) | ||
54 | if (busid_table[i][0]) | ||
55 | if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { | ||
56 | /* already registerd */ | ||
57 | spin_unlock(&busid_table_lock); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | spin_unlock(&busid_table_lock); | ||
62 | |||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | static ssize_t show_match_busid(struct device_driver *drv, char *buf) | ||
67 | { | ||
68 | int i; | ||
69 | char *out = buf; | ||
70 | |||
71 | spin_lock(&busid_table_lock); | ||
72 | |||
73 | for (i = 0; i < MAX_BUSID; i++) | ||
74 | if (busid_table[i][0]) | ||
75 | out += sprintf(out, "%s ", busid_table[i]); | ||
76 | |||
77 | spin_unlock(&busid_table_lock); | ||
78 | |||
79 | out += sprintf(out, "\n"); | ||
80 | |||
81 | return out - buf; | ||
82 | } | ||
83 | |||
84 | static int add_match_busid(char *busid) | ||
85 | { | ||
86 | int i; | ||
87 | |||
88 | if (!match_busid(busid)) | ||
89 | return 0; | ||
90 | |||
91 | spin_lock(&busid_table_lock); | ||
92 | |||
93 | for (i = 0; i < MAX_BUSID; i++) | ||
94 | if (!busid_table[i][0]) { | ||
95 | strncpy(busid_table[i], busid, BUS_ID_SIZE); | ||
96 | spin_unlock(&busid_table_lock); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | spin_unlock(&busid_table_lock); | ||
101 | |||
102 | return -1; | ||
103 | } | ||
104 | |||
105 | static int del_match_busid(char *busid) | ||
106 | { | ||
107 | int i; | ||
108 | |||
109 | spin_lock(&busid_table_lock); | ||
110 | |||
111 | for (i = 0; i < MAX_BUSID; i++) | ||
112 | if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { | ||
113 | /* found */ | ||
114 | memset(busid_table[i], 0, BUS_ID_SIZE); | ||
115 | spin_unlock(&busid_table_lock); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | spin_unlock(&busid_table_lock); | ||
120 | |||
121 | return -1; | ||
122 | } | ||
123 | |||
124 | static ssize_t store_match_busid(struct device_driver *dev, const char *buf, | ||
125 | size_t count) | ||
126 | { | ||
127 | int len; | ||
128 | char busid[BUS_ID_SIZE]; | ||
129 | |||
130 | if (count < 5) | ||
131 | return -EINVAL; | ||
132 | |||
133 | /* strnlen() does not include \0 */ | ||
134 | len = strnlen(buf + 4, BUS_ID_SIZE); | ||
135 | |||
136 | /* busid needs to include \0 termination */ | ||
137 | if (!(len < BUS_ID_SIZE)) | ||
138 | return -EINVAL; | ||
139 | |||
140 | strncpy(busid, buf + 4, BUS_ID_SIZE); | ||
141 | |||
142 | |||
143 | if (!strncmp(buf, "add ", 4)) { | ||
144 | if (add_match_busid(busid) < 0) | ||
145 | return -ENOMEM; | ||
146 | else { | ||
147 | udbg("add busid %s\n", busid); | ||
148 | return count; | ||
149 | } | ||
150 | } else if (!strncmp(buf, "del ", 4)) { | ||
151 | if (del_match_busid(busid) < 0) | ||
152 | return -ENODEV; | ||
153 | else { | ||
154 | udbg("del busid %s\n", busid); | ||
155 | return count; | ||
156 | } | ||
157 | } else | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | |||
161 | static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid, | ||
162 | store_match_busid); | ||
163 | |||
164 | |||
165 | |||
166 | /*-------------------------------------------------------------------------*/ | ||
167 | |||
168 | /* Cleanup functions used to free private data */ | ||
169 | |||
170 | static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) | ||
171 | { | ||
172 | struct stub_priv *priv, *tmp; | ||
173 | |||
174 | list_for_each_entry_safe(priv, tmp, listhead, list) { | ||
175 | list_del(&priv->list); | ||
176 | return priv; | ||
177 | } | ||
178 | |||
179 | return NULL; | ||
180 | } | ||
181 | |||
182 | static struct stub_priv *stub_priv_pop(struct stub_device *sdev) | ||
183 | { | ||
184 | unsigned long flags; | ||
185 | struct stub_priv *priv; | ||
186 | |||
187 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
188 | |||
189 | priv = stub_priv_pop_from_listhead(&sdev->priv_init); | ||
190 | if (priv) { | ||
191 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
192 | return priv; | ||
193 | } | ||
194 | |||
195 | priv = stub_priv_pop_from_listhead(&sdev->priv_tx); | ||
196 | if (priv) { | ||
197 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
198 | return priv; | ||
199 | } | ||
200 | |||
201 | priv = stub_priv_pop_from_listhead(&sdev->priv_free); | ||
202 | if (priv) { | ||
203 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
204 | return priv; | ||
205 | } | ||
206 | |||
207 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
208 | return NULL; | ||
209 | } | ||
210 | |||
211 | void stub_device_cleanup_urbs(struct stub_device *sdev) | ||
212 | { | ||
213 | struct stub_priv *priv; | ||
214 | |||
215 | udbg("free sdev %p\n", sdev); | ||
216 | |||
217 | while ((priv = stub_priv_pop(sdev))) { | ||
218 | struct urb *urb = priv->urb; | ||
219 | |||
220 | udbg(" free urb %p\n", urb); | ||
221 | usb_kill_urb(urb); | ||
222 | |||
223 | kmem_cache_free(stub_priv_cache, priv); | ||
224 | |||
225 | if (urb->transfer_buffer != NULL) | ||
226 | kfree(urb->transfer_buffer); | ||
227 | |||
228 | if (urb->setup_packet != NULL) | ||
229 | kfree(urb->setup_packet); | ||
230 | |||
231 | usb_free_urb(urb); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | |||
236 | /*-------------------------------------------------------------------------*/ | ||
237 | |||
238 | static int __init usb_stub_init(void) | ||
239 | { | ||
240 | int ret; | ||
241 | |||
242 | stub_priv_cache = kmem_cache_create("stub_priv", | ||
243 | sizeof(struct stub_priv), 0, | ||
244 | SLAB_HWCACHE_ALIGN, NULL); | ||
245 | |||
246 | if (!stub_priv_cache) { | ||
247 | printk(KERN_ERR KBUILD_MODNAME | ||
248 | ": create stub_priv_cache error\n"); | ||
249 | return -ENOMEM; | ||
250 | } | ||
251 | |||
252 | ret = usb_register(&stub_driver); | ||
253 | if (ret) { | ||
254 | printk(KERN_ERR KBUILD_MODNAME ": usb_register failed %d\n", | ||
255 | ret); | ||
256 | goto error_usb_register; | ||
257 | } | ||
258 | |||
259 | printk(KERN_INFO KBUILD_MODNAME ":" | ||
260 | DRIVER_DESC ":" DRIVER_VERSION "\n"); | ||
261 | |||
262 | memset(busid_table, 0, sizeof(busid_table)); | ||
263 | spin_lock_init(&busid_table_lock); | ||
264 | |||
265 | ret = driver_create_file(&stub_driver.drvwrap.driver, | ||
266 | &driver_attr_match_busid); | ||
267 | |||
268 | if (ret) { | ||
269 | printk(KERN_ERR KBUILD_MODNAME ": create driver sysfs\n"); | ||
270 | goto error_create_file; | ||
271 | } | ||
272 | |||
273 | return ret; | ||
274 | error_create_file: | ||
275 | usb_deregister(&stub_driver); | ||
276 | error_usb_register: | ||
277 | kmem_cache_destroy(stub_priv_cache); | ||
278 | return ret; | ||
279 | } | ||
280 | |||
281 | static void __exit usb_stub_exit(void) | ||
282 | { | ||
283 | driver_remove_file(&stub_driver.drvwrap.driver, | ||
284 | &driver_attr_match_busid); | ||
285 | |||
286 | /* | ||
287 | * deregister() calls stub_disconnect() for all devices. Device | ||
288 | * specific data is cleared in stub_disconnect(). | ||
289 | */ | ||
290 | usb_deregister(&stub_driver); | ||
291 | |||
292 | kmem_cache_destroy(stub_priv_cache); | ||
293 | } | ||
294 | |||
295 | module_init(usb_stub_init); | ||
296 | module_exit(usb_stub_exit); | ||
297 | |||
298 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
299 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
300 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c new file mode 100644 index 000000000000..36ce898fced5 --- /dev/null +++ b/drivers/staging/usbip/stub_rx.c | |||
@@ -0,0 +1,615 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003-2008 Takahiro Hirofuchi | ||
3 | * | ||
4 | * This is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
17 | * USA. | ||
18 | */ | ||
19 | |||
20 | #include "usbip_common.h" | ||
21 | #include "stub.h" | ||
22 | #include "../../usb/core/hcd.h" | ||
23 | |||
24 | |||
25 | static int is_clear_halt_cmd(struct urb *urb) | ||
26 | { | ||
27 | struct usb_ctrlrequest *req; | ||
28 | |||
29 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
30 | |||
31 | return (req->bRequest == USB_REQ_CLEAR_FEATURE) && | ||
32 | (req->bRequestType == USB_RECIP_ENDPOINT) && | ||
33 | (req->wValue == USB_ENDPOINT_HALT); | ||
34 | } | ||
35 | |||
36 | static int is_set_interface_cmd(struct urb *urb) | ||
37 | { | ||
38 | struct usb_ctrlrequest *req; | ||
39 | |||
40 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
41 | |||
42 | return (req->bRequest == USB_REQ_SET_INTERFACE) && | ||
43 | (req->bRequestType == USB_RECIP_INTERFACE); | ||
44 | } | ||
45 | |||
46 | static int is_set_configuration_cmd(struct urb *urb) | ||
47 | { | ||
48 | struct usb_ctrlrequest *req; | ||
49 | |||
50 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
51 | |||
52 | return (req->bRequest == USB_REQ_SET_CONFIGURATION) && | ||
53 | (req->bRequestType == USB_RECIP_DEVICE); | ||
54 | } | ||
55 | |||
56 | static int is_reset_device_cmd(struct urb *urb) | ||
57 | { | ||
58 | struct usb_ctrlrequest *req; | ||
59 | __u16 value; | ||
60 | __u16 index; | ||
61 | |||
62 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
63 | value = le16_to_cpu(req->wValue); | ||
64 | index = le16_to_cpu(req->wIndex); | ||
65 | |||
66 | if ((req->bRequest == USB_REQ_SET_FEATURE) && | ||
67 | (req->bRequestType == USB_RT_PORT) && | ||
68 | (value = USB_PORT_FEAT_RESET)) { | ||
69 | dbg_stub_rx("reset_device_cmd, port %u\n", index); | ||
70 | return 1; | ||
71 | } else | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int tweak_clear_halt_cmd(struct urb *urb) | ||
76 | { | ||
77 | struct usb_ctrlrequest *req; | ||
78 | int target_endp; | ||
79 | int target_dir; | ||
80 | int target_pipe; | ||
81 | int ret; | ||
82 | |||
83 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
84 | |||
85 | /* | ||
86 | * The stalled endpoint is specified in the wIndex value. The endpoint | ||
87 | * of the urb is the target of this clear_halt request (i.e., control | ||
88 | * endpoint). | ||
89 | */ | ||
90 | target_endp = le16_to_cpu(req->wIndex) & 0x000f; | ||
91 | |||
92 | /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80. */ | ||
93 | target_dir = le16_to_cpu(req->wIndex) & 0x0080; | ||
94 | |||
95 | if (target_dir) | ||
96 | target_pipe = usb_rcvctrlpipe(urb->dev, target_endp); | ||
97 | else | ||
98 | target_pipe = usb_sndctrlpipe(urb->dev, target_endp); | ||
99 | |||
100 | ret = usb_clear_halt(urb->dev, target_pipe); | ||
101 | if (ret < 0) | ||
102 | uinfo("clear_halt error: devnum %d endp %d, %d\n", | ||
103 | urb->dev->devnum, target_endp, ret); | ||
104 | else | ||
105 | uinfo("clear_halt done: devnum %d endp %d\n", | ||
106 | urb->dev->devnum, target_endp); | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static int tweak_set_interface_cmd(struct urb *urb) | ||
112 | { | ||
113 | struct usb_ctrlrequest *req; | ||
114 | __u16 alternate; | ||
115 | __u16 interface; | ||
116 | int ret; | ||
117 | |||
118 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
119 | alternate = le16_to_cpu(req->wValue); | ||
120 | interface = le16_to_cpu(req->wIndex); | ||
121 | |||
122 | dbg_stub_rx("set_interface: inf %u alt %u\n", interface, alternate); | ||
123 | |||
124 | ret = usb_set_interface(urb->dev, interface, alternate); | ||
125 | if (ret < 0) | ||
126 | uinfo("set_interface error: inf %u alt %u, %d\n", | ||
127 | interface, alternate, ret); | ||
128 | else | ||
129 | uinfo("set_interface done: inf %u alt %u\n", | ||
130 | interface, | ||
131 | alternate); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | static int tweak_set_configuration_cmd(struct urb *urb) | ||
137 | { | ||
138 | struct usb_ctrlrequest *req; | ||
139 | __u16 config; | ||
140 | |||
141 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
142 | config = le16_to_cpu(req->wValue); | ||
143 | |||
144 | /* | ||
145 | * I have never seen a multi-config device. Very rare. | ||
146 | * For most devices, this will be called to choose a default | ||
147 | * configuration only once in an initialization phase. | ||
148 | * | ||
149 | * set_configuration may change a device configuration and its device | ||
150 | * drivers will be unbound and assigned for a new device configuration. | ||
151 | * This means this usbip driver will be also unbound when called, then | ||
152 | * eventually reassigned to the device as far as driver matching | ||
153 | * condition is kept. | ||
154 | * | ||
155 | * Unfortunatelly, an existing usbip connection will be dropped | ||
156 | * due to this driver unbinding. So, skip here. | ||
157 | * A user may need to set a special configuration value before | ||
158 | * exporting the device. | ||
159 | */ | ||
160 | uinfo("set_configuration (%d) to %s\n", config, urb->dev->dev.bus_id); | ||
161 | uinfo("but, skip!\n"); | ||
162 | |||
163 | return 0; | ||
164 | /* return usb_driver_set_configuration(urb->dev, config); */ | ||
165 | } | ||
166 | |||
167 | static int tweak_reset_device_cmd(struct urb *urb) | ||
168 | { | ||
169 | struct usb_ctrlrequest *req; | ||
170 | __u16 value; | ||
171 | __u16 index; | ||
172 | int ret; | ||
173 | |||
174 | req = (struct usb_ctrlrequest *) urb->setup_packet; | ||
175 | value = le16_to_cpu(req->wValue); | ||
176 | index = le16_to_cpu(req->wIndex); | ||
177 | |||
178 | uinfo("reset_device (port %d) to %s\n", index, urb->dev->dev.bus_id); | ||
179 | |||
180 | /* all interfaces should be owned by usbip driver, so just reset it. */ | ||
181 | ret = usb_lock_device_for_reset(urb->dev, NULL); | ||
182 | if (ret < 0) { | ||
183 | dev_err(&urb->dev->dev, "lock for reset\n"); | ||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | /* try to reset the device */ | ||
188 | ret = usb_reset_device(urb->dev); | ||
189 | if (ret < 0) | ||
190 | dev_err(&urb->dev->dev, "device reset\n"); | ||
191 | |||
192 | usb_unlock_device(urb->dev); | ||
193 | |||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * clear_halt, set_interface, and set_configuration require special tricks. | ||
199 | */ | ||
200 | static void tweak_special_requests(struct urb *urb) | ||
201 | { | ||
202 | if (!urb || !urb->setup_packet) | ||
203 | return; | ||
204 | |||
205 | if (usb_pipetype(urb->pipe) != PIPE_CONTROL) | ||
206 | return; | ||
207 | |||
208 | if (is_clear_halt_cmd(urb)) | ||
209 | /* tweak clear_halt */ | ||
210 | tweak_clear_halt_cmd(urb); | ||
211 | |||
212 | else if (is_set_interface_cmd(urb)) | ||
213 | /* tweak set_interface */ | ||
214 | tweak_set_interface_cmd(urb); | ||
215 | |||
216 | else if (is_set_configuration_cmd(urb)) | ||
217 | /* tweak set_configuration */ | ||
218 | tweak_set_configuration_cmd(urb); | ||
219 | |||
220 | else if (is_reset_device_cmd(urb)) | ||
221 | tweak_reset_device_cmd(urb); | ||
222 | else | ||
223 | dbg_stub_rx("no need to tweak\n"); | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb(). | ||
228 | * By unlinking the urb asynchronously, stub_rx can continuously | ||
229 | * process coming urbs. Even if the urb is unlinked, its completion | ||
230 | * handler will be called and stub_tx will send a return pdu. | ||
231 | * | ||
232 | * See also comments about unlinking strategy in vhci_hcd.c. | ||
233 | */ | ||
234 | static int stub_recv_cmd_unlink(struct stub_device *sdev, | ||
235 | struct usbip_header *pdu) | ||
236 | { | ||
237 | struct list_head *listhead = &sdev->priv_init; | ||
238 | struct list_head *ptr; | ||
239 | unsigned long flags; | ||
240 | |||
241 | struct stub_priv *priv; | ||
242 | |||
243 | |||
244 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
245 | |||
246 | for (ptr = listhead->next; ptr != listhead; ptr = ptr->next) { | ||
247 | priv = list_entry(ptr, struct stub_priv, list); | ||
248 | if (priv->seqnum == pdu->u.cmd_unlink.seqnum) { | ||
249 | int ret; | ||
250 | |||
251 | dev_info(&priv->urb->dev->dev, "unlink urb %p\n", | ||
252 | priv->urb); | ||
253 | |||
254 | /* | ||
255 | * This matched urb is not completed yet (i.e., be in | ||
256 | * flight in usb hcd hardware/driver). Now we are | ||
257 | * cancelling it. The unlinking flag means that we are | ||
258 | * now not going to return the normal result pdu of a | ||
259 | * submission request, but going to return a result pdu | ||
260 | * of the unlink request. | ||
261 | */ | ||
262 | priv->unlinking = 1; | ||
263 | |||
264 | /* | ||
265 | * In the case that unlinking flag is on, prev->seqnum | ||
266 | * is changed from the seqnum of the cancelling urb to | ||
267 | * the seqnum of the unlink request. This will be used | ||
268 | * to make the result pdu of the unlink request. | ||
269 | */ | ||
270 | priv->seqnum = pdu->base.seqnum; | ||
271 | |||
272 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
273 | |||
274 | /* | ||
275 | * usb_unlink_urb() is now out of spinlocking to avoid | ||
276 | * spinlock recursion since stub_complete() is | ||
277 | * sometimes called in this context but not in the | ||
278 | * interrupt context. If stub_complete() is executed | ||
279 | * before we call usb_unlink_urb(), usb_unlink_urb() | ||
280 | * will return an error value. In this case, stub_tx | ||
281 | * will return the result pdu of this unlink request | ||
282 | * though submission is completed and actual unlinking | ||
283 | * is not executed. OK? | ||
284 | */ | ||
285 | /* In the above case, urb->status is not -ECONNRESET, | ||
286 | * so a driver in a client host will know the failure | ||
287 | * of the unlink request ? | ||
288 | */ | ||
289 | ret = usb_unlink_urb(priv->urb); | ||
290 | if (ret != -EINPROGRESS) | ||
291 | dev_err(&priv->urb->dev->dev, | ||
292 | "failed to unlink a urb %p, ret %d\n", | ||
293 | priv->urb, ret); | ||
294 | return 0; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | dbg_stub_rx("seqnum %d is not pending\n", pdu->u.cmd_unlink.seqnum); | ||
299 | |||
300 | /* | ||
301 | * The urb of the unlink target is not found in priv_init queue. It was | ||
302 | * already completed and its results is/was going to be sent by a | ||
303 | * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only | ||
304 | * return the completeness of this unlink request to vhci_hcd. | ||
305 | */ | ||
306 | stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0); | ||
307 | |||
308 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
309 | |||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int valid_request(struct stub_device *sdev, struct usbip_header *pdu) | ||
315 | { | ||
316 | struct usbip_device *ud = &sdev->ud; | ||
317 | |||
318 | if (pdu->base.devid == sdev->devid) { | ||
319 | spin_lock(&ud->lock); | ||
320 | if (ud->status == SDEV_ST_USED) { | ||
321 | /* A request is valid. */ | ||
322 | spin_unlock(&ud->lock); | ||
323 | return 1; | ||
324 | } | ||
325 | spin_unlock(&ud->lock); | ||
326 | } | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, | ||
332 | struct usbip_header *pdu) | ||
333 | { | ||
334 | struct stub_priv *priv; | ||
335 | struct usbip_device *ud = &sdev->ud; | ||
336 | unsigned long flags; | ||
337 | |||
338 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
339 | |||
340 | priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC); | ||
341 | if (!priv) { | ||
342 | dev_err(&sdev->interface->dev, "alloc stub_priv\n"); | ||
343 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
344 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | ||
345 | return NULL; | ||
346 | } | ||
347 | |||
348 | memset(priv, 0, sizeof(struct stub_priv)); | ||
349 | |||
350 | priv->seqnum = pdu->base.seqnum; | ||
351 | priv->sdev = sdev; | ||
352 | |||
353 | /* | ||
354 | * After a stub_priv is linked to a list_head, | ||
355 | * our error handler can free allocated data. | ||
356 | */ | ||
357 | list_add_tail(&priv->list, &sdev->priv_init); | ||
358 | |||
359 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
360 | |||
361 | return priv; | ||
362 | } | ||
363 | |||
364 | |||
365 | static struct usb_host_endpoint *get_ep_from_epnum(struct usb_device *udev, | ||
366 | int epnum0) | ||
367 | { | ||
368 | struct usb_host_config *config; | ||
369 | int i = 0, j = 0; | ||
370 | struct usb_host_endpoint *ep = NULL; | ||
371 | int epnum; | ||
372 | int found = 0; | ||
373 | |||
374 | if (epnum0 == 0) | ||
375 | return &udev->ep0; | ||
376 | |||
377 | config = udev->actconfig; | ||
378 | if (!config) | ||
379 | return NULL; | ||
380 | |||
381 | for (i = 0; i < config->desc.bNumInterfaces; i++) { | ||
382 | struct usb_host_interface *setting; | ||
383 | |||
384 | setting = config->interface[i]->cur_altsetting; | ||
385 | |||
386 | for (j = 0; j < setting->desc.bNumEndpoints; j++) { | ||
387 | ep = &setting->endpoint[j]; | ||
388 | epnum = (ep->desc.bEndpointAddress & 0x7f); | ||
389 | |||
390 | if (epnum == epnum0) { | ||
391 | /* uinfo("found epnum %d\n", epnum0); */ | ||
392 | found = 1; | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | |||
398 | if (found) | ||
399 | return ep; | ||
400 | else | ||
401 | return NULL; | ||
402 | } | ||
403 | |||
404 | |||
405 | static int get_pipe(struct stub_device *sdev, int epnum, int dir) | ||
406 | { | ||
407 | struct usb_device *udev = interface_to_usbdev(sdev->interface); | ||
408 | struct usb_host_endpoint *ep; | ||
409 | struct usb_endpoint_descriptor *epd = NULL; | ||
410 | |||
411 | ep = get_ep_from_epnum(udev, epnum); | ||
412 | if (!ep) { | ||
413 | dev_err(&sdev->interface->dev, "no such endpoint?, %d\n", | ||
414 | epnum); | ||
415 | BUG(); | ||
416 | } | ||
417 | |||
418 | epd = &ep->desc; | ||
419 | |||
420 | |||
421 | #if 0 | ||
422 | /* epnum 0 is always control */ | ||
423 | if (epnum == 0) { | ||
424 | if (dir == USBIP_DIR_OUT) | ||
425 | return usb_sndctrlpipe(udev, 0); | ||
426 | else | ||
427 | return usb_rcvctrlpipe(udev, 0); | ||
428 | } | ||
429 | #endif | ||
430 | |||
431 | if (usb_endpoint_xfer_control(epd)) { | ||
432 | if (dir == USBIP_DIR_OUT) | ||
433 | return usb_sndctrlpipe(udev, epnum); | ||
434 | else | ||
435 | return usb_rcvctrlpipe(udev, epnum); | ||
436 | } | ||
437 | |||
438 | if (usb_endpoint_xfer_bulk(epd)) { | ||
439 | if (dir == USBIP_DIR_OUT) | ||
440 | return usb_sndbulkpipe(udev, epnum); | ||
441 | else | ||
442 | return usb_rcvbulkpipe(udev, epnum); | ||
443 | } | ||
444 | |||
445 | if (usb_endpoint_xfer_int(epd)) { | ||
446 | if (dir == USBIP_DIR_OUT) | ||
447 | return usb_sndintpipe(udev, epnum); | ||
448 | else | ||
449 | return usb_rcvintpipe(udev, epnum); | ||
450 | } | ||
451 | |||
452 | if (usb_endpoint_xfer_isoc(epd)) { | ||
453 | if (dir == USBIP_DIR_OUT) | ||
454 | return usb_sndisocpipe(udev, epnum); | ||
455 | else | ||
456 | return usb_rcvisocpipe(udev, epnum); | ||
457 | } | ||
458 | |||
459 | /* NOT REACHED */ | ||
460 | dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum); | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static void stub_recv_cmd_submit(struct stub_device *sdev, | ||
465 | struct usbip_header *pdu) | ||
466 | { | ||
467 | int ret; | ||
468 | struct stub_priv *priv; | ||
469 | struct usbip_device *ud = &sdev->ud; | ||
470 | struct usb_device *udev = interface_to_usbdev(sdev->interface); | ||
471 | int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); | ||
472 | |||
473 | |||
474 | priv = stub_priv_alloc(sdev, pdu); | ||
475 | if (!priv) | ||
476 | return; | ||
477 | |||
478 | /* setup a urb */ | ||
479 | if (usb_pipeisoc(pipe)) | ||
480 | priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, | ||
481 | GFP_KERNEL); | ||
482 | else | ||
483 | priv->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
484 | |||
485 | if (!priv->urb) { | ||
486 | dev_err(&sdev->interface->dev, "malloc urb\n"); | ||
487 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | /* set priv->urb->transfer_buffer */ | ||
492 | if (pdu->u.cmd_submit.transfer_buffer_length > 0) { | ||
493 | priv->urb->transfer_buffer = | ||
494 | kzalloc(pdu->u.cmd_submit.transfer_buffer_length, | ||
495 | GFP_KERNEL); | ||
496 | if (!priv->urb->transfer_buffer) { | ||
497 | dev_err(&sdev->interface->dev, "malloc x_buff\n"); | ||
498 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | ||
499 | return; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | /* set priv->urb->setup_packet */ | ||
504 | priv->urb->setup_packet = kzalloc(8, GFP_KERNEL); | ||
505 | if (!priv->urb->setup_packet) { | ||
506 | dev_err(&sdev->interface->dev, "allocate setup_packet\n"); | ||
507 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | ||
508 | return; | ||
509 | } | ||
510 | memcpy(priv->urb->setup_packet, &pdu->u.cmd_submit.setup, 8); | ||
511 | |||
512 | /* set other members from the base header of pdu */ | ||
513 | priv->urb->context = (void *) priv; | ||
514 | priv->urb->dev = udev; | ||
515 | priv->urb->pipe = pipe; | ||
516 | priv->urb->complete = stub_complete; | ||
517 | |||
518 | usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); | ||
519 | |||
520 | |||
521 | if (usbip_recv_xbuff(ud, priv->urb) < 0) | ||
522 | return; | ||
523 | |||
524 | if (usbip_recv_iso(ud, priv->urb) < 0) | ||
525 | return; | ||
526 | |||
527 | /* no need to submit an intercepted request, but harmless? */ | ||
528 | tweak_special_requests(priv->urb); | ||
529 | |||
530 | /* urb is now ready to submit */ | ||
531 | ret = usb_submit_urb(priv->urb, GFP_KERNEL); | ||
532 | |||
533 | if (ret == 0) | ||
534 | dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum); | ||
535 | else { | ||
536 | dev_err(&sdev->interface->dev, "submit_urb error, %d\n", ret); | ||
537 | usbip_dump_header(pdu); | ||
538 | usbip_dump_urb(priv->urb); | ||
539 | |||
540 | /* | ||
541 | * Pessimistic. | ||
542 | * This connection will be discarded. | ||
543 | */ | ||
544 | usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); | ||
545 | } | ||
546 | |||
547 | dbg_stub_rx("Leave\n"); | ||
548 | return; | ||
549 | } | ||
550 | |||
551 | /* recv a pdu */ | ||
552 | static void stub_rx_pdu(struct usbip_device *ud) | ||
553 | { | ||
554 | int ret; | ||
555 | struct usbip_header pdu; | ||
556 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | ||
557 | struct device *dev = &sdev->interface->dev; | ||
558 | |||
559 | dbg_stub_rx("Enter\n"); | ||
560 | |||
561 | memset(&pdu, 0, sizeof(pdu)); | ||
562 | |||
563 | /* 1. receive a pdu header */ | ||
564 | ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0); | ||
565 | if (ret != sizeof(pdu)) { | ||
566 | dev_err(dev, "recv a header, %d\n", ret); | ||
567 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | usbip_header_correct_endian(&pdu, 0); | ||
572 | |||
573 | if (dbg_flag_stub_rx) | ||
574 | usbip_dump_header(&pdu); | ||
575 | |||
576 | if (!valid_request(sdev, &pdu)) { | ||
577 | dev_err(dev, "recv invalid request\n"); | ||
578 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | ||
579 | return; | ||
580 | } | ||
581 | |||
582 | switch (pdu.base.command) { | ||
583 | case USBIP_CMD_UNLINK: | ||
584 | stub_recv_cmd_unlink(sdev, &pdu); | ||
585 | break; | ||
586 | |||
587 | case USBIP_CMD_SUBMIT: | ||
588 | stub_recv_cmd_submit(sdev, &pdu); | ||
589 | break; | ||
590 | |||
591 | default: | ||
592 | /* NOTREACHED */ | ||
593 | dev_err(dev, "unknown pdu\n"); | ||
594 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | ||
595 | return; | ||
596 | } | ||
597 | |||
598 | } | ||
599 | |||
600 | void stub_rx_loop(struct usbip_task *ut) | ||
601 | { | ||
602 | struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); | ||
603 | |||
604 | while (1) { | ||
605 | if (signal_pending(current)) { | ||
606 | dbg_stub_rx("signal caught!\n"); | ||
607 | break; | ||
608 | } | ||
609 | |||
610 | if (usbip_event_happend(ud)) | ||
611 | break; | ||
612 | |||
613 | stub_rx_pdu(ud); | ||
614 | } | ||
615 | } | ||
diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c new file mode 100644 index 000000000000..d5563cd980be --- /dev/null +++ b/drivers/staging/usbip/stub_tx.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003-2008 Takahiro Hirofuchi | ||
3 | * | ||
4 | * This is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
17 | * USA. | ||
18 | */ | ||
19 | |||
20 | #include "usbip_common.h" | ||
21 | #include "stub.h" | ||
22 | |||
23 | |||
24 | static void stub_free_priv_and_urb(struct stub_priv *priv) | ||
25 | { | ||
26 | struct urb *urb = priv->urb; | ||
27 | |||
28 | kfree(urb->setup_packet); | ||
29 | kfree(urb->transfer_buffer); | ||
30 | list_del(&priv->list); | ||
31 | kmem_cache_free(stub_priv_cache, priv); | ||
32 | usb_free_urb(urb); | ||
33 | } | ||
34 | |||
35 | /* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ | ||
36 | void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, | ||
37 | __u32 status) | ||
38 | { | ||
39 | struct stub_unlink *unlink; | ||
40 | |||
41 | unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC); | ||
42 | if (!unlink) { | ||
43 | dev_err(&sdev->interface->dev, "alloc stub_unlink\n"); | ||
44 | usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC); | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | unlink->seqnum = seqnum; | ||
49 | unlink->status = status; | ||
50 | |||
51 | list_add_tail(&unlink->list, &sdev->unlink_tx); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * stub_complete - completion handler of a usbip urb | ||
56 | * @urb: pointer to the urb completed | ||
57 | * @regs: | ||
58 | * | ||
59 | * When a urb has completed, the USB core driver calls this function mostly in | ||
60 | * the interrupt context. To return the result of a urb, the completed urb is | ||
61 | * linked to the pending list of returning. | ||
62 | * | ||
63 | */ | ||
64 | void stub_complete(struct urb *urb) | ||
65 | { | ||
66 | struct stub_priv *priv = (struct stub_priv *) urb->context; | ||
67 | struct stub_device *sdev = priv->sdev; | ||
68 | unsigned long flags; | ||
69 | |||
70 | dbg_stub_tx("complete! status %d\n", urb->status); | ||
71 | |||
72 | |||
73 | switch (urb->status) { | ||
74 | case 0: | ||
75 | /* OK */ | ||
76 | break; | ||
77 | case -ENOENT: | ||
78 | uinfo("stopped by a call of usb_kill_urb() because of" | ||
79 | "cleaning up a virtual connection\n"); | ||
80 | return; | ||
81 | case -ECONNRESET: | ||
82 | uinfo("unlinked by a call of usb_unlink_urb()\n"); | ||
83 | break; | ||
84 | case -EPIPE: | ||
85 | uinfo("endpoint %d is stalled\n", usb_pipeendpoint(urb->pipe)); | ||
86 | break; | ||
87 | case -ESHUTDOWN: | ||
88 | uinfo("device removed?\n"); | ||
89 | break; | ||
90 | default: | ||
91 | uinfo("urb completion with non-zero status %d\n", urb->status); | ||
92 | } | ||
93 | |||
94 | /* link a urb to the queue of tx. */ | ||
95 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
96 | |||
97 | if (priv->unlinking) { | ||
98 | stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status); | ||
99 | stub_free_priv_and_urb(priv); | ||
100 | } else | ||
101 | list_move_tail(&priv->list, &sdev->priv_tx); | ||
102 | |||
103 | |||
104 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
105 | |||
106 | /* wake up tx_thread */ | ||
107 | wake_up(&sdev->tx_waitq); | ||
108 | } | ||
109 | |||
110 | |||
111 | /*-------------------------------------------------------------------------*/ | ||
112 | /* fill PDU */ | ||
113 | |||
114 | static inline void setup_base_pdu(struct usbip_header_basic *base, | ||
115 | __u32 command, __u32 seqnum) | ||
116 | { | ||
117 | base->command = command; | ||
118 | base->seqnum = seqnum; | ||
119 | base->devid = 0; | ||
120 | base->ep = 0; | ||
121 | base->direction = 0; | ||
122 | } | ||
123 | |||
124 | static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb) | ||
125 | { | ||
126 | struct stub_priv *priv = (struct stub_priv *) urb->context; | ||
127 | |||
128 | setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum); | ||
129 | |||
130 | usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1); | ||
131 | } | ||
132 | |||
133 | static void setup_ret_unlink_pdu(struct usbip_header *rpdu, | ||
134 | struct stub_unlink *unlink) | ||
135 | { | ||
136 | setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum); | ||
137 | |||
138 | rpdu->u.ret_unlink.status = unlink->status; | ||
139 | } | ||
140 | |||
141 | |||
142 | /*-------------------------------------------------------------------------*/ | ||
143 | /* send RET_SUBMIT */ | ||
144 | |||
145 | static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | struct stub_priv *priv, *tmp; | ||
149 | |||
150 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
151 | |||
152 | list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) { | ||
153 | list_move_tail(&priv->list, &sdev->priv_free); | ||
154 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
155 | return priv; | ||
156 | } | ||
157 | |||
158 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
159 | |||
160 | return NULL; | ||
161 | } | ||
162 | |||
163 | static int stub_send_ret_submit(struct stub_device *sdev) | ||
164 | { | ||
165 | unsigned long flags; | ||
166 | struct stub_priv *priv, *tmp; | ||
167 | |||
168 | struct msghdr msg; | ||
169 | struct kvec iov[3]; | ||
170 | size_t txsize; | ||
171 | |||
172 | size_t total_size = 0; | ||
173 | |||
174 | while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { | ||
175 | int ret; | ||
176 | struct urb *urb = priv->urb; | ||
177 | struct usbip_header pdu_header; | ||
178 | void *iso_buffer = NULL; | ||
179 | |||
180 | txsize = 0; | ||
181 | memset(&pdu_header, 0, sizeof(pdu_header)); | ||
182 | memset(&msg, 0, sizeof(msg)); | ||
183 | memset(&iov, 0, sizeof(iov)); | ||
184 | |||
185 | dbg_stub_tx("setup txdata urb %p\n", urb); | ||
186 | |||
187 | |||
188 | /* 1. setup usbip_header */ | ||
189 | setup_ret_submit_pdu(&pdu_header, urb); | ||
190 | usbip_header_correct_endian(&pdu_header, 1); | ||
191 | |||
192 | iov[0].iov_base = &pdu_header; | ||
193 | iov[0].iov_len = sizeof(pdu_header); | ||
194 | txsize += sizeof(pdu_header); | ||
195 | |||
196 | /* 2. setup transfer buffer */ | ||
197 | if (usb_pipein(urb->pipe) && urb->actual_length > 0) { | ||
198 | iov[1].iov_base = urb->transfer_buffer; | ||
199 | iov[1].iov_len = urb->actual_length; | ||
200 | txsize += urb->actual_length; | ||
201 | } | ||
202 | |||
203 | /* 3. setup iso_packet_descriptor */ | ||
204 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { | ||
205 | ssize_t len = 0; | ||
206 | |||
207 | iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); | ||
208 | if (!iso_buffer) { | ||
209 | usbip_event_add(&sdev->ud, | ||
210 | SDEV_EVENT_ERROR_MALLOC); | ||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | iov[2].iov_base = iso_buffer; | ||
215 | iov[2].iov_len = len; | ||
216 | txsize += len; | ||
217 | } | ||
218 | |||
219 | ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, | ||
220 | 3, txsize); | ||
221 | if (ret != txsize) { | ||
222 | dev_err(&sdev->interface->dev, | ||
223 | "sendmsg failed!, retval %d for %zd\n", | ||
224 | ret, txsize); | ||
225 | kfree(iso_buffer); | ||
226 | usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); | ||
227 | return -1; | ||
228 | } | ||
229 | |||
230 | kfree(iso_buffer); | ||
231 | dbg_stub_tx("send txdata\n"); | ||
232 | |||
233 | total_size += txsize; | ||
234 | } | ||
235 | |||
236 | |||
237 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
238 | |||
239 | list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { | ||
240 | stub_free_priv_and_urb(priv); | ||
241 | } | ||
242 | |||
243 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
244 | |||
245 | return total_size; | ||
246 | } | ||
247 | |||
248 | |||
249 | /*-------------------------------------------------------------------------*/ | ||
250 | /* send RET_UNLINK */ | ||
251 | |||
252 | static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev) | ||
253 | { | ||
254 | unsigned long flags; | ||
255 | struct stub_unlink *unlink, *tmp; | ||
256 | |||
257 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
258 | |||
259 | list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { | ||
260 | list_move_tail(&unlink->list, &sdev->unlink_free); | ||
261 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
262 | return unlink; | ||
263 | } | ||
264 | |||
265 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
266 | |||
267 | return NULL; | ||
268 | } | ||
269 | |||
270 | |||
271 | static int stub_send_ret_unlink(struct stub_device *sdev) | ||
272 | { | ||
273 | unsigned long flags; | ||
274 | struct stub_unlink *unlink, *tmp; | ||
275 | |||
276 | struct msghdr msg; | ||
277 | struct kvec iov[1]; | ||
278 | size_t txsize; | ||
279 | |||
280 | size_t total_size = 0; | ||
281 | |||
282 | while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) { | ||
283 | int ret; | ||
284 | struct usbip_header pdu_header; | ||
285 | |||
286 | txsize = 0; | ||
287 | memset(&pdu_header, 0, sizeof(pdu_header)); | ||
288 | memset(&msg, 0, sizeof(msg)); | ||
289 | memset(&iov, 0, sizeof(iov)); | ||
290 | |||
291 | dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum); | ||
292 | |||
293 | /* 1. setup usbip_header */ | ||
294 | setup_ret_unlink_pdu(&pdu_header, unlink); | ||
295 | usbip_header_correct_endian(&pdu_header, 1); | ||
296 | |||
297 | iov[0].iov_base = &pdu_header; | ||
298 | iov[0].iov_len = sizeof(pdu_header); | ||
299 | txsize += sizeof(pdu_header); | ||
300 | |||
301 | ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, | ||
302 | 1, txsize); | ||
303 | if (ret != txsize) { | ||
304 | dev_err(&sdev->interface->dev, | ||
305 | "sendmsg failed!, retval %d for %zd\n", | ||
306 | ret, txsize); | ||
307 | usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); | ||
308 | return -1; | ||
309 | } | ||
310 | |||
311 | |||
312 | dbg_stub_tx("send txdata\n"); | ||
313 | |||
314 | total_size += txsize; | ||
315 | } | ||
316 | |||
317 | |||
318 | spin_lock_irqsave(&sdev->priv_lock, flags); | ||
319 | |||
320 | list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { | ||
321 | list_del(&unlink->list); | ||
322 | kfree(unlink); | ||
323 | } | ||
324 | |||
325 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | ||
326 | |||
327 | return total_size; | ||
328 | } | ||
329 | |||
330 | |||
331 | /*-------------------------------------------------------------------------*/ | ||
332 | |||
333 | void stub_tx_loop(struct usbip_task *ut) | ||
334 | { | ||
335 | struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); | ||
336 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | ||
337 | |||
338 | while (1) { | ||
339 | if (signal_pending(current)) { | ||
340 | dbg_stub_tx("signal catched\n"); | ||
341 | break; | ||
342 | } | ||
343 | |||
344 | if (usbip_event_happend(ud)) | ||
345 | break; | ||
346 | |||
347 | /* | ||
348 | * send_ret_submit comes earlier than send_ret_unlink. stub_rx | ||
349 | * looks at only priv_init queue. If the completion of a URB is | ||
350 | * earlier than the receive of CMD_UNLINK, priv is moved to | ||
351 | * priv_tx queue and stub_rx does not find the target priv. In | ||
352 | * this case, vhci_rx receives the result of the submit request | ||
353 | * and then receives the result of the unlink request. The | ||
354 | * result of the submit is given back to the usbcore as the | ||
355 | * completion of the unlink request. The request of the | ||
356 | * unlink is ignored. This is ok because a driver who calls | ||
357 | * usb_unlink_urb() understands the unlink was too late by | ||
358 | * getting the status of the given-backed URB which has the | ||
359 | * status of usb_submit_urb(). | ||
360 | */ | ||
361 | if (stub_send_ret_submit(sdev) < 0) | ||
362 | break; | ||
363 | |||
364 | if (stub_send_ret_unlink(sdev) < 0) | ||
365 | break; | ||
366 | |||
367 | wait_event_interruptible(sdev->tx_waitq, | ||
368 | (!list_empty(&sdev->priv_tx) || | ||
369 | !list_empty(&sdev->unlink_tx))); | ||
370 | } | ||
371 | } | ||