aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/usbip/stub_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/usbip/stub_dev.c')
-rw-r--r--drivers/staging/usbip/stub_dev.c101
1 files changed, 92 insertions, 9 deletions
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}