aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index b2ab9cc33fec..b17618a55f1b 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -255,11 +255,13 @@ struct dummy {
255 */ 255 */
256 struct dummy_ep ep[DUMMY_ENDPOINTS]; 256 struct dummy_ep ep[DUMMY_ENDPOINTS];
257 int address; 257 int address;
258 int callback_usage;
258 struct usb_gadget gadget; 259 struct usb_gadget gadget;
259 struct usb_gadget_driver *driver; 260 struct usb_gadget_driver *driver;
260 struct dummy_request fifo_req; 261 struct dummy_request fifo_req;
261 u8 fifo_buf[FIFO_SIZE]; 262 u8 fifo_buf[FIFO_SIZE];
262 u16 devstatus; 263 u16 devstatus;
264 unsigned ints_enabled:1;
263 unsigned udc_suspended:1; 265 unsigned udc_suspended:1;
264 unsigned pullup:1; 266 unsigned pullup:1;
265 267
@@ -441,18 +443,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
441 (~dum_hcd->old_status) & dum_hcd->port_status; 443 (~dum_hcd->old_status) & dum_hcd->port_status;
442 444
443 /* Report reset and disconnect events to the driver */ 445 /* Report reset and disconnect events to the driver */
444 if (dum->driver && (disconnect || reset)) { 446 if (dum->ints_enabled && (disconnect || reset)) {
445 stop_activity(dum); 447 stop_activity(dum);
448 ++dum->callback_usage;
449 spin_unlock(&dum->lock);
446 if (reset) 450 if (reset)
447 usb_gadget_udc_reset(&dum->gadget, dum->driver); 451 usb_gadget_udc_reset(&dum->gadget, dum->driver);
448 else 452 else
449 dum->driver->disconnect(&dum->gadget); 453 dum->driver->disconnect(&dum->gadget);
454 spin_lock(&dum->lock);
455 --dum->callback_usage;
450 } 456 }
451 } else if (dum_hcd->active != dum_hcd->old_active) { 457 } else if (dum_hcd->active != dum_hcd->old_active &&
458 dum->ints_enabled) {
459 ++dum->callback_usage;
460 spin_unlock(&dum->lock);
452 if (dum_hcd->old_active && dum->driver->suspend) 461 if (dum_hcd->old_active && dum->driver->suspend)
453 dum->driver->suspend(&dum->gadget); 462 dum->driver->suspend(&dum->gadget);
454 else if (!dum_hcd->old_active && dum->driver->resume) 463 else if (!dum_hcd->old_active && dum->driver->resume)
455 dum->driver->resume(&dum->gadget); 464 dum->driver->resume(&dum->gadget);
465 spin_lock(&dum->lock);
466 --dum->callback_usage;
456 } 467 }
457 468
458 dum_hcd->old_status = dum_hcd->port_status; 469 dum_hcd->old_status = dum_hcd->port_status;
@@ -973,8 +984,11 @@ static int dummy_udc_start(struct usb_gadget *g,
973 * can't enumerate without help from the driver we're binding. 984 * can't enumerate without help from the driver we're binding.
974 */ 985 */
975 986
987 spin_lock_irq(&dum->lock);
976 dum->devstatus = 0; 988 dum->devstatus = 0;
977 dum->driver = driver; 989 dum->driver = driver;
990 dum->ints_enabled = 1;
991 spin_unlock_irq(&dum->lock);
978 992
979 return 0; 993 return 0;
980} 994}
@@ -985,6 +999,16 @@ static int dummy_udc_stop(struct usb_gadget *g)
985 struct dummy *dum = dum_hcd->dum; 999 struct dummy *dum = dum_hcd->dum;
986 1000
987 spin_lock_irq(&dum->lock); 1001 spin_lock_irq(&dum->lock);
1002 dum->ints_enabled = 0;
1003 stop_activity(dum);
1004
1005 /* emulate synchronize_irq(): wait for callbacks to finish */
1006 while (dum->callback_usage > 0) {
1007 spin_unlock_irq(&dum->lock);
1008 usleep_range(1000, 2000);
1009 spin_lock_irq(&dum->lock);
1010 }
1011
988 dum->driver = NULL; 1012 dum->driver = NULL;
989 spin_unlock_irq(&dum->lock); 1013 spin_unlock_irq(&dum->lock);
990 1014
@@ -1529,6 +1553,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
1529 if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ? 1553 if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
1530 dum->ss_hcd : dum->hs_hcd))) 1554 dum->ss_hcd : dum->hs_hcd)))
1531 return NULL; 1555 return NULL;
1556 if (!dum->ints_enabled)
1557 return NULL;
1532 if ((address & ~USB_DIR_IN) == 0) 1558 if ((address & ~USB_DIR_IN) == 0)
1533 return &dum->ep[0]; 1559 return &dum->ep[0];
1534 for (i = 1; i < DUMMY_ENDPOINTS; i++) { 1560 for (i = 1; i < DUMMY_ENDPOINTS; i++) {
@@ -1870,10 +1896,12 @@ restart:
1870 * until setup() returns; no reentrancy issues etc. 1896 * until setup() returns; no reentrancy issues etc.
1871 */ 1897 */
1872 if (value > 0) { 1898 if (value > 0) {
1899 ++dum->callback_usage;
1873 spin_unlock(&dum->lock); 1900 spin_unlock(&dum->lock);
1874 value = dum->driver->setup(&dum->gadget, 1901 value = dum->driver->setup(&dum->gadget,
1875 &setup); 1902 &setup);
1876 spin_lock(&dum->lock); 1903 spin_lock(&dum->lock);
1904 --dum->callback_usage;
1877 1905
1878 if (value >= 0) { 1906 if (value >= 0) {
1879 /* no delays (max 64KB data stage) */ 1907 /* no delays (max 64KB data stage) */