aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/usbip
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2010-08-05 17:18:03 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-05 17:18:03 -0400
commite9563355ac1175dd3440dc2ea5c28b27ed51a283 (patch)
tree8546d55832714b5d19ba4c7799266918ca04882e /drivers/staging/usbip
parentcdd854bc42b5e6c79bbbc40c6600d995ffe6e747 (diff)
parentb12d1995f650e92f26184afd28e6cf40bf64467a (diff)
Staging: Merge staging-next into Linus's tree
Conflicts: drivers/staging/Kconfig drivers/staging/batman-adv/bat_sysfs.c drivers/staging/batman-adv/device.c drivers/staging/batman-adv/hard-interface.c drivers/staging/cx25821/cx25821-audups11.c Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/usbip')
-rw-r--r--drivers/staging/usbip/stub.h17
-rw-r--r--drivers/staging/usbip/stub_dev.c101
-rw-r--r--drivers/staging/usbip/stub_main.c65
-rw-r--r--drivers/staging/usbip/stub_rx.c101
-rw-r--r--drivers/staging/usbip/usbip_common.h2
5 files changed, 220 insertions, 66 deletions
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
index 022d0649ac5..30dbfb6d16f 100644
--- a/drivers/staging/usbip/stub.h
+++ b/drivers/staging/usbip/stub.h
@@ -25,6 +25,11 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/net.h> 26#include <linux/net.h>
27 27
28#define STUB_BUSID_OTHER 0
29#define STUB_BUSID_REMOV 1
30#define STUB_BUSID_ADDED 2
31#define STUB_BUSID_ALLOC 3
32
28struct stub_device { 33struct stub_device {
29 struct usb_interface *interface; 34 struct usb_interface *interface;
30 struct list_head list; 35 struct list_head list;
@@ -72,6 +77,14 @@ struct stub_unlink {
72 __u32 status; 77 __u32 status;
73}; 78};
74 79
80#define BUSID_SIZE 20
81struct bus_id_priv {
82 char name[BUSID_SIZE];
83 char status;
84 int interf_count;
85 struct stub_device *sdev;
86 char shutdown_busid;
87};
75 88
76extern struct kmem_cache *stub_priv_cache; 89extern struct kmem_cache *stub_priv_cache;
77 90
@@ -91,5 +104,7 @@ void stub_rx_loop(struct usbip_task *);
91void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32); 104void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32);
92 105
93/* stub_main.c */ 106/* stub_main.c */
94int match_busid(const char *busid); 107struct bus_id_priv *get_busid_priv(const char *busid);
108int del_match_busid(char *busid);
109
95void stub_device_cleanup_urbs(struct stub_device *sdev); 110void stub_device_cleanup_urbs(struct stub_device *sdev);
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index 3f95605427a..b6b753a4934 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -393,11 +393,14 @@ static int stub_probe(struct usb_interface *interface,
393 struct stub_device *sdev = NULL; 393 struct stub_device *sdev = NULL;
394 const char *udev_busid = dev_name(interface->dev.parent); 394 const char *udev_busid = dev_name(interface->dev.parent);
395 int err = 0; 395 int err = 0;
396 struct bus_id_priv *busid_priv;
396 397
397 dev_dbg(&interface->dev, "Enter\n"); 398 dev_dbg(&interface->dev, "Enter\n");
398 399
399 /* check we should claim or not by busid_table */ 400 /* check we should claim or not by busid_table */
400 if (match_busid(udev_busid)) { 401 busid_priv = get_busid_priv(udev_busid);
402 if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
403 (busid_priv->status == STUB_BUSID_OTHER)) {
401 dev_info(&interface->dev, 404 dev_info(&interface->dev,
402 "this device %s is not in match_busid table. skip!\n", 405 "this device %s is not in match_busid table. skip!\n",
403 udev_busid); 406 udev_busid);
@@ -422,28 +425,80 @@ static int stub_probe(struct usb_interface *interface,
422 return -ENODEV; 425 return -ENODEV;
423 } 426 }
424 427
428
429 if (busid_priv->status == STUB_BUSID_ALLOC) {
430 busid_priv->interf_count++;
431 sdev = busid_priv->sdev;
432 if (!sdev)
433 return -ENODEV;
434
435 dev_info(&interface->dev,
436 "USB/IP Stub: register a new interface "
437 "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum,
438 interface->cur_altsetting->desc.bInterfaceNumber);
439
440 /* set private data to usb_interface */
441 usb_set_intfdata(interface, sdev);
442
443 err = stub_add_files(&interface->dev);
444 if (err) {
445 dev_err(&interface->dev, "create sysfs files for %s\n",
446 udev_busid);
447 usb_set_intfdata(interface, NULL);
448 busid_priv->interf_count--;
449
450 return err;
451 }
452
453 return 0;
454 }
455
425 /* ok. this is my device. */ 456 /* ok. this is my device. */
426 sdev = stub_device_alloc(interface); 457 sdev = stub_device_alloc(interface);
427 if (!sdev) 458 if (!sdev)
428 return -ENOMEM; 459 return -ENOMEM;
429 460
430 dev_info(&interface->dev, "USB/IP Stub: register a new interface " 461 dev_info(&interface->dev, "USB/IP Stub: register a new device "
431 "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum, 462 "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum,
432 interface->cur_altsetting->desc.bInterfaceNumber); 463 interface->cur_altsetting->desc.bInterfaceNumber);
433 464
465 busid_priv->interf_count = 0;
466 busid_priv->shutdown_busid = 0;
467
434 /* set private data to usb_interface */ 468 /* set private data to usb_interface */
435 usb_set_intfdata(interface, sdev); 469 usb_set_intfdata(interface, sdev);
470 busid_priv->interf_count++;
471
472 busid_priv->sdev = sdev;
436 473
437 err = stub_add_files(&interface->dev); 474 err = stub_add_files(&interface->dev);
438 if (err) { 475 if (err) {
439 dev_err(&interface->dev, "create sysfs files for %s\n", 476 dev_err(&interface->dev, "create sysfs files for %s\n",
440 udev_busid); 477 udev_busid);
478 usb_set_intfdata(interface, NULL);
479 busid_priv->interf_count = 0;
480
481 busid_priv->sdev = NULL;
482 stub_device_free(sdev);
441 return err; 483 return err;
442 } 484 }
485 busid_priv->status = STUB_BUSID_ALLOC;
443 486
444 return 0; 487 return 0;
445} 488}
446 489
490static void shutdown_busid(struct bus_id_priv *busid_priv)
491{
492 if (busid_priv->sdev && !busid_priv->shutdown_busid) {
493 busid_priv->shutdown_busid = 1;
494 usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
495
496 /* 2. wait for the stop of the event handler */
497 usbip_stop_eh(&busid_priv->sdev->ud);
498 }
499
500}
501
447 502
448/* 503/*
449 * called in usb_disconnect() or usb_deregister() 504 * called in usb_disconnect() or usb_deregister()
@@ -451,10 +506,21 @@ static int stub_probe(struct usb_interface *interface,
451 */ 506 */
452static void stub_disconnect(struct usb_interface *interface) 507static void stub_disconnect(struct usb_interface *interface)
453{ 508{
454 struct stub_device *sdev = usb_get_intfdata(interface); 509 struct stub_device *sdev;
510 const char *udev_busid = dev_name(interface->dev.parent);
511 struct bus_id_priv *busid_priv;
512
513 busid_priv = get_busid_priv(udev_busid);
455 514
456 usbip_udbg("Enter\n"); 515 usbip_udbg("Enter\n");
457 516
517 if (!busid_priv) {
518 BUG();
519 return;
520 }
521
522 sdev = usb_get_intfdata(interface);
523
458 /* get stub_device */ 524 /* get stub_device */
459 if (!sdev) { 525 if (!sdev) {
460 err(" could not get device from inteface data"); 526 err(" could not get device from inteface data");
@@ -464,22 +530,39 @@ static void stub_disconnect(struct usb_interface *interface)
464 530
465 usb_set_intfdata(interface, NULL); 531 usb_set_intfdata(interface, NULL);
466 532
467
468 /* 533 /*
469 * NOTE: 534 * NOTE:
470 * rx/tx threads are invoked for each usb_device. 535 * rx/tx threads are invoked for each usb_device.
471 */ 536 */
472 stub_remove_files(&interface->dev); 537 stub_remove_files(&interface->dev);
473 538
474 /* 1. shutdown the current connection */ 539 /*If usb reset called from event handler*/
475 usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED); 540 if (busid_priv->sdev->ud.eh.thread == current) {
541 busid_priv->interf_count--;
542 return;
543 }
544
545 if (busid_priv->interf_count > 1) {
546 busid_priv->interf_count--;
547 shutdown_busid(busid_priv);
548 return;
549 }
550
551 busid_priv->interf_count = 0;
476 552
477 /* 2. wait for the stop of the event handler */ 553
478 usbip_stop_eh(&sdev->ud); 554 /* 1. shutdown the current connection */
555 shutdown_busid(busid_priv);
479 556
480 /* 3. free sdev */ 557 /* 3. free sdev */
558 busid_priv->sdev = NULL;
481 stub_device_free(sdev); 559 stub_device_free(sdev);
482 560
483 561 if (busid_priv->status == STUB_BUSID_ALLOC) {
562 busid_priv->status = STUB_BUSID_ADDED;
563 } else {
564 busid_priv->status = STUB_BUSID_OTHER;
565 del_match_busid((char *)udev_busid);
566 }
484 usbip_udbg("bye\n"); 567 usbip_udbg("bye\n");
485} 568}
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
index 6665cefe573..f3a40968aae 100644
--- a/drivers/staging/usbip/stub_main.c
+++ b/drivers/staging/usbip/stub_main.c
@@ -41,8 +41,7 @@ struct kmem_cache *stub_priv_cache;
41 * remote host. 41 * remote host.
42 */ 42 */
43#define MAX_BUSID 16 43#define MAX_BUSID 16
44#define BUSID_SIZE 20 44static struct bus_id_priv busid_table[MAX_BUSID];
45static char busid_table[MAX_BUSID][BUSID_SIZE];
46static spinlock_t busid_table_lock; 45static spinlock_t busid_table_lock;
47 46
48 47
@@ -53,8 +52,8 @@ int match_busid(const char *busid)
53 spin_lock(&busid_table_lock); 52 spin_lock(&busid_table_lock);
54 53
55 for (i = 0; i < MAX_BUSID; i++) 54 for (i = 0; i < MAX_BUSID; i++)
56 if (busid_table[i][0]) 55 if (busid_table[i].name[0])
57 if (!strncmp(busid_table[i], busid, BUSID_SIZE)) { 56 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
58 /* already registerd */ 57 /* already registerd */
59 spin_unlock(&busid_table_lock); 58 spin_unlock(&busid_table_lock);
60 return 0; 59 return 0;
@@ -65,6 +64,25 @@ int match_busid(const char *busid)
65 return 1; 64 return 1;
66} 65}
67 66
67struct bus_id_priv *get_busid_priv(const char *busid)
68{
69 int i;
70
71 spin_lock(&busid_table_lock);
72
73 for (i = 0; i < MAX_BUSID; i++)
74 if (busid_table[i].name[0])
75 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
76 /* already registerd */
77 spin_unlock(&busid_table_lock);
78 return &(busid_table[i]);
79 }
80
81 spin_unlock(&busid_table_lock);
82
83 return NULL;
84}
85
68static ssize_t show_match_busid(struct device_driver *drv, char *buf) 86static ssize_t show_match_busid(struct device_driver *drv, char *buf)
69{ 87{
70 int i; 88 int i;
@@ -73,8 +91,8 @@ static ssize_t show_match_busid(struct device_driver *drv, char *buf)
73 spin_lock(&busid_table_lock); 91 spin_lock(&busid_table_lock);
74 92
75 for (i = 0; i < MAX_BUSID; i++) 93 for (i = 0; i < MAX_BUSID; i++)
76 if (busid_table[i][0]) 94 if (busid_table[i].name[0])
77 out += sprintf(out, "%s ", busid_table[i]); 95 out += sprintf(out, "%s ", busid_table[i].name);
78 96
79 spin_unlock(&busid_table_lock); 97 spin_unlock(&busid_table_lock);
80 98
@@ -93,8 +111,11 @@ static int add_match_busid(char *busid)
93 spin_lock(&busid_table_lock); 111 spin_lock(&busid_table_lock);
94 112
95 for (i = 0; i < MAX_BUSID; i++) 113 for (i = 0; i < MAX_BUSID; i++)
96 if (!busid_table[i][0]) { 114 if (!busid_table[i].name[0]) {
97 strncpy(busid_table[i], busid, BUSID_SIZE); 115 strncpy(busid_table[i].name, busid, BUSID_SIZE);
116 if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
117 (busid_table[i].status != STUB_BUSID_REMOV))
118 busid_table[i].status = STUB_BUSID_ADDED;
98 spin_unlock(&busid_table_lock); 119 spin_unlock(&busid_table_lock);
99 return 0; 120 return 0;
100 } 121 }
@@ -104,16 +125,21 @@ static int add_match_busid(char *busid)
104 return -1; 125 return -1;
105} 126}
106 127
107static int del_match_busid(char *busid) 128int del_match_busid(char *busid)
108{ 129{
109 int i; 130 int i;
110 131
111 spin_lock(&busid_table_lock); 132 spin_lock(&busid_table_lock);
112 133
113 for (i = 0; i < MAX_BUSID; i++) 134 for (i = 0; i < MAX_BUSID; i++)
114 if (!strncmp(busid_table[i], busid, BUSID_SIZE)) { 135 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
115 /* found */ 136 /* found */
116 memset(busid_table[i], 0, BUSID_SIZE); 137 if (busid_table[i].status == STUB_BUSID_OTHER)
138 memset(busid_table[i].name, 0, BUSID_SIZE);
139 if ((busid_table[i].status != STUB_BUSID_OTHER) &&
140 (busid_table[i].status != STUB_BUSID_ADDED)) {
141 busid_table[i].status = STUB_BUSID_REMOV;
142 }
117 spin_unlock(&busid_table_lock); 143 spin_unlock(&busid_table_lock);
118 return 0; 144 return 0;
119 } 145 }
@@ -122,6 +148,20 @@ static int del_match_busid(char *busid)
122 148
123 return -1; 149 return -1;
124} 150}
151static void init_busid_table(void)
152{
153 int i;
154
155
156 for (i = 0; i < MAX_BUSID; i++) {
157 memset(busid_table[i].name, 0, BUSID_SIZE);
158 busid_table[i].status = STUB_BUSID_OTHER;
159 busid_table[i].interf_count = 0;
160 busid_table[i].sdev = NULL;
161 busid_table[i].shutdown_busid = 0;
162 }
163 spin_lock_init(&busid_table_lock);
164}
125 165
126static ssize_t store_match_busid(struct device_driver *dev, const char *buf, 166static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
127 size_t count) 167 size_t count)
@@ -261,8 +301,7 @@ static int __init usb_stub_init(void)
261 printk(KERN_INFO KBUILD_MODNAME ":" 301 printk(KERN_INFO KBUILD_MODNAME ":"
262 DRIVER_DESC ":" DRIVER_VERSION "\n"); 302 DRIVER_DESC ":" DRIVER_VERSION "\n");
263 303
264 memset(busid_table, 0, sizeof(busid_table)); 304 init_busid_table();
265 spin_lock_init(&busid_table_lock);
266 305
267 ret = driver_create_file(&stub_driver.drvwrap.driver, 306 ret = driver_create_file(&stub_driver.drvwrap.driver,
268 &driver_attr_match_busid); 307 &driver_attr_match_busid);
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index 5972ae70e38..3de6fd2539d 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -362,54 +362,16 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
362 return priv; 362 return priv;
363} 363}
364 364
365
366static struct usb_host_endpoint *get_ep_from_epnum(struct usb_device *udev,
367 int epnum0)
368{
369 struct usb_host_config *config;
370 int i = 0, j = 0;
371 struct usb_host_endpoint *ep = NULL;
372 int epnum;
373 int found = 0;
374
375 if (epnum0 == 0)
376 return &udev->ep0;
377
378 config = udev->actconfig;
379 if (!config)
380 return NULL;
381
382 for (i = 0; i < config->desc.bNumInterfaces; i++) {
383 struct usb_host_interface *setting;
384
385 setting = config->interface[i]->cur_altsetting;
386
387 for (j = 0; j < setting->desc.bNumEndpoints; j++) {
388 ep = &setting->endpoint[j];
389 epnum = (ep->desc.bEndpointAddress & 0x7f);
390
391 if (epnum == epnum0) {
392 /* usbip_uinfo("found epnum %d\n", epnum0);*/
393 found = 1;
394 break;
395 }
396 }
397 }
398
399 if (found)
400 return ep;
401 else
402 return NULL;
403}
404
405
406static int get_pipe(struct stub_device *sdev, int epnum, int dir) 365static int get_pipe(struct stub_device *sdev, int epnum, int dir)
407{ 366{
408 struct usb_device *udev = interface_to_usbdev(sdev->interface); 367 struct usb_device *udev = interface_to_usbdev(sdev->interface);
409 struct usb_host_endpoint *ep; 368 struct usb_host_endpoint *ep;
410 struct usb_endpoint_descriptor *epd = NULL; 369 struct usb_endpoint_descriptor *epd = NULL;
411 370
412 ep = get_ep_from_epnum(udev, epnum); 371 if (dir == USBIP_DIR_IN)
372 ep = udev->ep_in[epnum & 0x7f];
373 else
374 ep = udev->ep_out[epnum & 0x7f];
413 if (!ep) { 375 if (!ep) {
414 dev_err(&sdev->interface->dev, "no such endpoint?, %d\n", 376 dev_err(&sdev->interface->dev, "no such endpoint?, %d\n",
415 epnum); 377 epnum);
@@ -462,6 +424,60 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir)
462 return 0; 424 return 0;
463} 425}
464 426
427static void masking_bogus_flags(struct urb *urb)
428{
429 int xfertype;
430 struct usb_device *dev;
431 struct usb_host_endpoint *ep;
432 int is_out;
433 unsigned int allowed;
434
435 if (!urb || urb->hcpriv || !urb->complete)
436 return;
437 dev = urb->dev;
438 if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
439 return;
440
441 ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
442 [usb_pipeendpoint(urb->pipe)];
443 if (!ep)
444 return;
445
446 xfertype = usb_endpoint_type(&ep->desc);
447 if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
448 struct usb_ctrlrequest *setup =
449 (struct usb_ctrlrequest *) urb->setup_packet;
450
451 if (!setup)
452 return;
453 is_out = !(setup->bRequestType & USB_DIR_IN) ||
454 !setup->wLength;
455 } else {
456 is_out = usb_endpoint_dir_out(&ep->desc);
457 }
458
459 /* enforce simple/standard policy */
460 allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT |
461 URB_DIR_MASK | URB_FREE_BUFFER);
462 switch (xfertype) {
463 case USB_ENDPOINT_XFER_BULK:
464 if (is_out)
465 allowed |= URB_ZERO_PACKET;
466 /* FALLTHROUGH */
467 case USB_ENDPOINT_XFER_CONTROL:
468 allowed |= URB_NO_FSBR; /* only affects UHCI */
469 /* FALLTHROUGH */
470 default: /* all non-iso endpoints */
471 if (!is_out)
472 allowed |= URB_SHORT_NOT_OK;
473 break;
474 case USB_ENDPOINT_XFER_ISOC:
475 allowed |= URB_ISO_ASAP;
476 break;
477 }
478 urb->transfer_flags &= allowed;
479}
480
465static void stub_recv_cmd_submit(struct stub_device *sdev, 481static void stub_recv_cmd_submit(struct stub_device *sdev,
466 struct usbip_header *pdu) 482 struct usbip_header *pdu)
467{ 483{
@@ -528,6 +544,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
528 /* no need to submit an intercepted request, but harmless? */ 544 /* no need to submit an intercepted request, but harmless? */
529 tweak_special_requests(priv->urb); 545 tweak_special_requests(priv->urb);
530 546
547 masking_bogus_flags(priv->urb);
531 /* urb is now ready to submit */ 548 /* urb is now ready to submit */
532 ret = usb_submit_urb(priv->urb, GFP_KERNEL); 549 ret = usb_submit_urb(priv->urb, GFP_KERNEL);
533 550
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index e1bbd1287e2..d280e234e06 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -172,7 +172,7 @@ struct usbip_header_basic {
172#define USBIP_RET_UNLINK 0x0004 172#define USBIP_RET_UNLINK 0x0004
173 __u32 command; 173 __u32 command;
174 174
175 /* sequencial number which identifies requests. 175 /* sequential number which identifies requests.
176 * incremented per connections */ 176 * incremented per connections */
177 __u32 seqnum; 177 __u32 seqnum;
178 178