aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorTatyana Brokhman <tlinder@codeaurora.org>2011-06-29 09:41:52 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-07-01 17:27:06 -0400
commit1cd8fd2887e162ad3d067150962cc3d32dcf3150 (patch)
treebb7515fee46e29cff3d3cf2671b21e15aab4eec8 /drivers/usb/gadget
parentcdfcbd2c4a9e866c19bf8fe2b4e011a12441c32a (diff)
usb: gadget: dummy_hcd: add SuperSpeed support
This patch adds SS support to the dummy hcd module. It may be used to test SS device when no (SS) HW is available. USB 3.0 hub includes 2 hubs - one HS and one SS. This patch adds support for a SS root hub in the dummy_hcd module. A new module parameter was added: is_super_speed. When set to true, a SS root hub will also be registered and the connected device will be enumerated over the SS root hub. The default of this parameter is false. Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org> [ balbi@ti.com : slight change to commit log fixed one coding style issue ] Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/Kconfig1
-rw-r--r--drivers/usb/gadget/dummy_hcd.c564
2 files changed, 477 insertions, 88 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index a23e291f07c8..86f64caeafc1 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -631,6 +631,7 @@ config USB_GADGET_DUMMY_HCD
631 boolean "Dummy HCD (DEVELOPMENT)" 631 boolean "Dummy HCD (DEVELOPMENT)"
632 depends on USB=y || (USB=m && USB_GADGET=m) 632 depends on USB=y || (USB=m && USB_GADGET=m)
633 select USB_GADGET_DUALSPEED 633 select USB_GADGET_DUALSPEED
634 select USB_GADGET_SUPERSPEED
634 help 635 help
635 This host controller driver emulates USB, looping all data transfer 636 This host controller driver emulates USB, looping all data transfer
636 requests back to a USB "gadget driver" in the same host. The host 637 requests back to a USB "gadget driver" in the same host. The host
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index fcbff1cd180c..a4896df3296c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -70,6 +70,15 @@ MODULE_DESCRIPTION (DRIVER_DESC);
70MODULE_AUTHOR ("David Brownell"); 70MODULE_AUTHOR ("David Brownell");
71MODULE_LICENSE ("GPL"); 71MODULE_LICENSE ("GPL");
72 72
73struct dummy_hcd_module_parameters {
74 bool is_super_speed;
75};
76
77static struct dummy_hcd_module_parameters mod_data = {
78 .is_super_speed = false
79};
80module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
81MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
73/*-------------------------------------------------------------------------*/ 82/*-------------------------------------------------------------------------*/
74 83
75/* gadget side driver data structres */ 84/* gadget side driver data structres */
@@ -188,6 +197,7 @@ struct dummy {
188 * MASTER/HOST side support 197 * MASTER/HOST side support
189 */ 198 */
190 struct dummy_hcd *hs_hcd; 199 struct dummy_hcd *hs_hcd;
200 struct dummy_hcd *ss_hcd;
191}; 201};
192 202
193static inline struct dummy_hcd *hcd_to_dummy_hcd(struct usb_hcd *hcd) 203static inline struct dummy_hcd *hcd_to_dummy_hcd(struct usb_hcd *hcd)
@@ -218,7 +228,10 @@ static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)
218static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget) 228static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
219{ 229{
220 struct dummy *dum = container_of(gadget, struct dummy, gadget); 230 struct dummy *dum = container_of(gadget, struct dummy, gadget);
221 return dum->hs_hcd; 231 if (dum->gadget.speed == USB_SPEED_SUPER)
232 return dum->ss_hcd;
233 else
234 return dum->hs_hcd;
222} 235}
223 236
224static inline struct dummy *gadget_dev_to_dummy (struct device *dev) 237static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
@@ -266,60 +279,117 @@ stop_activity (struct dummy *dum)
266 /* driver now does any non-usb quiescing necessary */ 279 /* driver now does any non-usb quiescing necessary */
267} 280}
268 281
282/**
283 * set_link_state_by_speed() - Sets the current state of the link according to
284 * the hcd speed
285 * @dum_hcd: pointer to the dummy_hcd structure to update the link state for
286 *
287 * This function updates the port_status according to the link state and the
288 * speed of the hcd.
289 */
290static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
291{
292 struct dummy *dum = dum_hcd->dum;
293
294 if (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3) {
295 if ((dum_hcd->port_status & USB_SS_PORT_STAT_POWER) == 0) {
296 dum_hcd->port_status = 0;
297 } else if (!dum->pullup || dum->udc_suspended) {
298 /* UDC suspend must cause a disconnect */
299 dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
300 USB_PORT_STAT_ENABLE);
301 if ((dum_hcd->old_status &
302 USB_PORT_STAT_CONNECTION) != 0)
303 dum_hcd->port_status |=
304 (USB_PORT_STAT_C_CONNECTION << 16);
305 } else {
306 /* device is connected and not suspended */
307 dum_hcd->port_status |= (USB_PORT_STAT_CONNECTION |
308 USB_PORT_STAT_SPEED_5GBPS) ;
309 if ((dum_hcd->old_status &
310 USB_PORT_STAT_CONNECTION) == 0)
311 dum_hcd->port_status |=
312 (USB_PORT_STAT_C_CONNECTION << 16);
313 if ((dum_hcd->port_status &
314 USB_PORT_STAT_ENABLE) == 1 &&
315 (dum_hcd->port_status &
316 USB_SS_PORT_LS_U0) == 1 &&
317 dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
318 dum_hcd->active = 1;
319 }
320 } else {
321 if ((dum_hcd->port_status & USB_PORT_STAT_POWER) == 0) {
322 dum_hcd->port_status = 0;
323 } else if (!dum->pullup || dum->udc_suspended) {
324 /* UDC suspend must cause a disconnect */
325 dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
326 USB_PORT_STAT_ENABLE |
327 USB_PORT_STAT_LOW_SPEED |
328 USB_PORT_STAT_HIGH_SPEED |
329 USB_PORT_STAT_SUSPEND);
330 if ((dum_hcd->old_status &
331 USB_PORT_STAT_CONNECTION) != 0)
332 dum_hcd->port_status |=
333 (USB_PORT_STAT_C_CONNECTION << 16);
334 } else {
335 dum_hcd->port_status |= USB_PORT_STAT_CONNECTION;
336 if ((dum_hcd->old_status &
337 USB_PORT_STAT_CONNECTION) == 0)
338 dum_hcd->port_status |=
339 (USB_PORT_STAT_C_CONNECTION << 16);
340 if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0)
341 dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
342 else if ((dum_hcd->port_status &
343 USB_PORT_STAT_SUSPEND) == 0 &&
344 dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
345 dum_hcd->active = 1;
346 }
347 }
348}
349
269/* caller must hold lock */ 350/* caller must hold lock */
270static void set_link_state(struct dummy_hcd *dum_hcd) 351static void set_link_state(struct dummy_hcd *dum_hcd)
271{ 352{
272 struct dummy *dum = dum_hcd->dum; 353 struct dummy *dum = dum_hcd->dum;
273 354
274 dum_hcd->active = 0; 355 dum_hcd->active = 0;
275 if ((dum_hcd->port_status & USB_PORT_STAT_POWER) == 0) 356 if (dum->pullup)
276 dum_hcd->port_status = 0; 357 if ((dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 &&
277 358 dum->gadget.speed != USB_SPEED_SUPER) ||
278 /* UDC suspend must cause a disconnect */ 359 (dummy_hcd_to_hcd(dum_hcd)->speed != HCD_USB3 &&
279 else if (!dum->pullup || dum->udc_suspended) { 360 dum->gadget.speed == USB_SPEED_SUPER))
280 dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION | 361 return;
281 USB_PORT_STAT_ENABLE | 362
282 USB_PORT_STAT_LOW_SPEED | 363 set_link_state_by_speed(dum_hcd);
283 USB_PORT_STAT_HIGH_SPEED |
284 USB_PORT_STAT_SUSPEND);
285 if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0)
286 dum_hcd->port_status |=
287 (USB_PORT_STAT_C_CONNECTION << 16);
288 } else {
289 dum_hcd->port_status |= USB_PORT_STAT_CONNECTION;
290 if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) == 0)
291 dum_hcd->port_status |=
292 (USB_PORT_STAT_C_CONNECTION << 16);
293 if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0)
294 dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
295 else if ((dum_hcd->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
296 dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
297 dum_hcd->active = 1;
298 }
299 364
300 if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 || 365 if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
301 dum_hcd->active) 366 dum_hcd->active)
302 dum_hcd->resuming = 0; 367 dum_hcd->resuming = 0;
303 368
369 /* if !connected or reset */
304 if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 || 370 if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
305 (dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) { 371 (dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
372 /*
373 * We're connected and not reset (reset occurred now),
374 * and driver attached - disconnect!
375 */
306 if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0 && 376 if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
307 (dum_hcd->old_status & USB_PORT_STAT_RESET) == 0 && 377 (dum_hcd->old_status & USB_PORT_STAT_RESET) == 0 &&
308 dum->driver) { 378 dum->driver) {
309 stop_activity (dum); 379 stop_activity(dum);
310 spin_unlock (&dum->lock); 380 spin_unlock(&dum->lock);
311 dum->driver->disconnect (&dum->gadget); 381 dum->driver->disconnect(&dum->gadget);
312 spin_lock (&dum->lock); 382 spin_lock(&dum->lock);
313 } 383 }
314 } else if (dum_hcd->active != dum_hcd->old_active) { 384 } else if (dum_hcd->active != dum_hcd->old_active) {
315 if (dum_hcd->old_active && dum->driver->suspend) { 385 if (dum_hcd->old_active && dum->driver->suspend) {
316 spin_unlock (&dum->lock); 386 spin_unlock(&dum->lock);
317 dum->driver->suspend (&dum->gadget); 387 dum->driver->suspend(&dum->gadget);
318 spin_lock (&dum->lock); 388 spin_lock(&dum->lock);
319 } else if (!dum_hcd->old_active && dum->driver->resume) { 389 } else if (!dum_hcd->old_active && dum->driver->resume) {
320 spin_unlock (&dum->lock); 390 spin_unlock(&dum->lock);
321 dum->driver->resume (&dum->gadget); 391 dum->driver->resume(&dum->gadget);
322 spin_lock (&dum->lock); 392 spin_lock(&dum->lock);
323 } 393 }
324 } 394 }
325 395
@@ -355,13 +425,17 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
355 dum = ep_to_dummy (ep); 425 dum = ep_to_dummy (ep);
356 if (!dum->driver) 426 if (!dum->driver)
357 return -ESHUTDOWN; 427 return -ESHUTDOWN;
358 dum_hcd = dum->hs_hcd; 428 if (dum->gadget.speed == USB_SPEED_SUPER)
429 dum_hcd = dum->ss_hcd;
430 else
431 dum_hcd = dum->hs_hcd;
359 if (!is_enabled(dum_hcd)) 432 if (!is_enabled(dum_hcd))
360 return -ESHUTDOWN; 433 return -ESHUTDOWN;
361 434
362 /* 435 /*
363 * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the 436 * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the
364 * maximum packet size. 437 * maximum packet size.
438 * For SS devices the wMaxPacketSize is limited by 1024.
365 */ 439 */
366 max = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff; 440 max = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff;
367 441
@@ -381,6 +455,10 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
381 goto done; 455 goto done;
382 } 456 }
383 switch (dum->gadget.speed) { 457 switch (dum->gadget.speed) {
458 case USB_SPEED_SUPER:
459 if (max == 1024)
460 break;
461 goto done;
384 case USB_SPEED_HIGH: 462 case USB_SPEED_HIGH:
385 if (max == 512) 463 if (max == 512)
386 break; 464 break;
@@ -399,6 +477,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
399 goto done; 477 goto done;
400 /* real hardware might not handle all packet sizes */ 478 /* real hardware might not handle all packet sizes */
401 switch (dum->gadget.speed) { 479 switch (dum->gadget.speed) {
480 case USB_SPEED_SUPER:
402 case USB_SPEED_HIGH: 481 case USB_SPEED_HIGH:
403 if (max <= 1024) 482 if (max <= 1024)
404 break; 483 break;
@@ -419,6 +498,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
419 goto done; 498 goto done;
420 /* real hardware might not handle all packet sizes */ 499 /* real hardware might not handle all packet sizes */
421 switch (dum->gadget.speed) { 500 switch (dum->gadget.speed) {
501 case USB_SPEED_SUPER:
422 case USB_SPEED_HIGH: 502 case USB_SPEED_HIGH:
423 if (max <= 1024) 503 if (max <= 1024)
424 break; 504 break;
@@ -547,7 +627,10 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
547 return -EINVAL; 627 return -EINVAL;
548 628
549 dum = ep_to_dummy (ep); 629 dum = ep_to_dummy (ep);
550 dum_hcd = dum->hs_hcd; 630 if (dum->gadget.speed == USB_SPEED_SUPER)
631 dum_hcd = dum->ss_hcd;
632 else
633 dum_hcd = dum->hs_hcd;
551 if (!dum->driver || !is_enabled(dum_hcd)) 634 if (!dum->driver || !is_enabled(dum_hcd))
552 return -ESHUTDOWN; 635 return -ESHUTDOWN;
553 636
@@ -733,9 +816,12 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value)
733 dum = gadget_to_dummy_hcd(_gadget)->dum; 816 dum = gadget_to_dummy_hcd(_gadget)->dum;
734 spin_lock_irqsave (&dum->lock, flags); 817 spin_lock_irqsave (&dum->lock, flags);
735 dum->pullup = (value != 0); 818 dum->pullup = (value != 0);
736 set_link_state(dum->hs_hcd); 819 set_link_state((dum->gadget.speed == USB_SPEED_SUPER ?
820 dum->ss_hcd : dum->hs_hcd));
737 spin_unlock_irqrestore (&dum->lock, flags); 821 spin_unlock_irqrestore (&dum->lock, flags);
738 usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum->hs_hcd)); 822 usb_hcd_poll_rh_status((dum->gadget.speed == USB_SPEED_SUPER ?
823 dummy_hcd_to_hcd(dum->ss_hcd) :
824 dummy_hcd_to_hcd(dum->hs_hcd)));
739 return 0; 825 return 0;
740} 826}
741 827
@@ -821,8 +907,21 @@ static int dummy_udc_start(struct usb_gadget_driver *driver,
821 } 907 }
822 908
823 dum->gadget.ep0 = &dum->ep [0].ep; 909 dum->gadget.ep0 = &dum->ep [0].ep;
824 dum->gadget.speed = min((u8)driver->speed, (u8)USB_SPEED_HIGH) ; 910 if (mod_data.is_super_speed)
825 dum->ep[0].ep.maxpacket = 64; 911 dum->gadget.speed = driver->speed;
912 else
913 dum->gadget.speed = min((u8)USB_SPEED_HIGH, (u8)driver->speed);
914 if (dum->gadget.speed < driver->speed)
915 dev_dbg(udc_dev(dum), "This device can perform faster if"
916 " you connect it to a "
917 "SupeSpeed port...\n");
918
919 if (dum->gadget.speed == USB_SPEED_SUPER) {
920 for (i = 0; i < DUMMY_ENDPOINTS; i++)
921 dum->ep[i].ep.max_streams = 0x10;
922 dum->ep[0].ep.maxpacket = 9;
923 } else
924 dum->ep[0].ep.maxpacket = 64;
826 list_del_init (&dum->ep [0].ep.ep_list); 925 list_del_init (&dum->ep [0].ep.ep_list);
827 INIT_LIST_HEAD(&dum->fifo_req.queue); 926 INIT_LIST_HEAD(&dum->fifo_req.queue);
828 927
@@ -841,12 +940,21 @@ static int dummy_udc_start(struct usb_gadget_driver *driver,
841 /* khubd will enumerate this in a while */ 940 /* khubd will enumerate this in a while */
842 spin_lock_irq (&dum->lock); 941 spin_lock_irq (&dum->lock);
843 dum->pullup = 1; 942 dum->pullup = 1;
844 dum->gadget.is_otg = 943 if (dum->gadget.speed == USB_SPEED_SUPER) {
845 (dummy_hcd_to_hcd(dum->hs_hcd)->self.otg_port != 0); 944 dum->gadget.is_otg =
846 set_link_state(dum->hs_hcd); 945 (dummy_hcd_to_hcd(dum->ss_hcd)->self.otg_port != 0);
946 set_link_state(dum->ss_hcd);
947 } else {
948 dum->gadget.is_otg =
949 (dummy_hcd_to_hcd(dum->hs_hcd)->self.otg_port != 0);
950 set_link_state(dum->hs_hcd);
951 }
952
847 spin_unlock_irq (&dum->lock); 953 spin_unlock_irq (&dum->lock);
848 954
849 usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum->hs_hcd)); 955 usb_hcd_poll_rh_status((dum->gadget.speed == USB_SPEED_SUPER ?
956 dummy_hcd_to_hcd(dum->ss_hcd) :
957 dummy_hcd_to_hcd(dum->hs_hcd)));
850 return 0; 958 return 0;
851} 959}
852 960
@@ -865,18 +973,21 @@ static int dummy_udc_stop(struct usb_gadget_driver *driver)
865 973
866 spin_lock_irqsave (&dum->lock, flags); 974 spin_lock_irqsave (&dum->lock, flags);
867 dum->pullup = 0; 975 dum->pullup = 0;
868 set_link_state(dum->hs_hcd); 976 set_link_state((dum->gadget.speed == USB_SPEED_SUPER ?
977 dum->ss_hcd : dum->hs_hcd));
869 spin_unlock_irqrestore (&dum->lock, flags); 978 spin_unlock_irqrestore (&dum->lock, flags);
870 979
871 driver->unbind (&dum->gadget); 980 driver->unbind (&dum->gadget);
872 dum->gadget.dev.driver = NULL; 981 dum->gadget.dev.driver = NULL;
873 dum->driver = NULL; 982 dum->driver = NULL;
874
875 spin_lock_irqsave (&dum->lock, flags); 983 spin_lock_irqsave (&dum->lock, flags);
876 dum->pullup = 0; 984 dum->pullup = 0;
877 set_link_state(dum->hs_hcd); 985 set_link_state((dum->gadget.speed == USB_SPEED_SUPER ?
986 dum->ss_hcd : dum->hs_hcd));
878 spin_unlock_irqrestore (&dum->lock, flags); 987 spin_unlock_irqrestore (&dum->lock, flags);
879 usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum->hs_hcd)); 988 usb_hcd_poll_rh_status((dum->gadget.speed == USB_SPEED_SUPER ?
989 dummy_hcd_to_hcd(dum->ss_hcd) :
990 dummy_hcd_to_hcd(dum->hs_hcd)));
880 return 0; 991 return 0;
881} 992}
882 993
@@ -953,10 +1064,13 @@ static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
953 dev_dbg (&pdev->dev, "%s\n", __func__); 1064 dev_dbg (&pdev->dev, "%s\n", __func__);
954 spin_lock_irq (&dum->lock); 1065 spin_lock_irq (&dum->lock);
955 dum->udc_suspended = 1; 1066 dum->udc_suspended = 1;
956 set_link_state(dum->hs_hcd); 1067 set_link_state((dum->gadget.speed == USB_SPEED_SUPER ?
1068 dum->ss_hcd : dum->hs_hcd));
957 spin_unlock_irq (&dum->lock); 1069 spin_unlock_irq (&dum->lock);
958 1070
959 usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum->hs_hcd)); 1071 usb_hcd_poll_rh_status((dum->gadget.speed == USB_SPEED_SUPER ?
1072 dummy_hcd_to_hcd(dum->ss_hcd) :
1073 dummy_hcd_to_hcd(dum->hs_hcd)));
960 return 0; 1074 return 0;
961} 1075}
962 1076
@@ -967,10 +1081,13 @@ static int dummy_udc_resume (struct platform_device *pdev)
967 dev_dbg (&pdev->dev, "%s\n", __func__); 1081 dev_dbg (&pdev->dev, "%s\n", __func__);
968 spin_lock_irq (&dum->lock); 1082 spin_lock_irq (&dum->lock);
969 dum->udc_suspended = 0; 1083 dum->udc_suspended = 0;
970 set_link_state(dum->hs_hcd); 1084 set_link_state((dum->gadget.speed == USB_SPEED_SUPER ?
1085 dum->ss_hcd : dum->hs_hcd));
971 spin_unlock_irq (&dum->lock); 1086 spin_unlock_irq (&dum->lock);
972 1087
973 usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum->hs_hcd)); 1088 usb_hcd_poll_rh_status((dum->gadget.speed == USB_SPEED_SUPER ?
1089 dummy_hcd_to_hcd(dum->ss_hcd) :
1090 dummy_hcd_to_hcd(dum->hs_hcd)));
974 return 0; 1091 return 0;
975} 1092}
976 1093
@@ -1198,6 +1315,21 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
1198 tmp *= 8 /* applies to entire frame */; 1315 tmp *= 8 /* applies to entire frame */;
1199 limit += limit * tmp; 1316 limit += limit * tmp;
1200 } 1317 }
1318 if (dum->gadget.speed == USB_SPEED_SUPER) {
1319 switch (ep->desc->bmAttributes & 0x03) {
1320 case USB_ENDPOINT_XFER_ISOC:
1321 /* Sec. 4.4.8.2 USB3.0 Spec */
1322 limit = 3 * 16 * 1024 * 8;
1323 break;
1324 case USB_ENDPOINT_XFER_INT:
1325 /* Sec. 4.4.7.2 USB3.0 Spec */
1326 limit = 3 * 1024 * 8;
1327 break;
1328 case USB_ENDPOINT_XFER_BULK:
1329 default:
1330 break;
1331 }
1332 }
1201 return limit; 1333 return limit;
1202} 1334}
1203 1335
@@ -1210,7 +1342,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
1210{ 1342{
1211 int i; 1343 int i;
1212 1344
1213 if (!is_active(dum->hs_hcd)) 1345 if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
1346 dum->ss_hcd : dum->hs_hcd)))
1214 return NULL; 1347 return NULL;
1215 if ((address & ~USB_DIR_IN) == 0) 1348 if ((address & ~USB_DIR_IN) == 0)
1216 return &dum->ep [0]; 1349 return &dum->ep [0];
@@ -1284,6 +1417,27 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
1284 case USB_DEVICE_A_ALT_HNP_SUPPORT: 1417 case USB_DEVICE_A_ALT_HNP_SUPPORT:
1285 dum->gadget.a_alt_hnp_support = 1; 1418 dum->gadget.a_alt_hnp_support = 1;
1286 break; 1419 break;
1420 case USB_DEVICE_U1_ENABLE:
1421 if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1422 HCD_USB3)
1423 w_value = USB_DEV_STAT_U1_ENABLED;
1424 else
1425 ret_val = -EOPNOTSUPP;
1426 break;
1427 case USB_DEVICE_U2_ENABLE:
1428 if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1429 HCD_USB3)
1430 w_value = USB_DEV_STAT_U2_ENABLED;
1431 else
1432 ret_val = -EOPNOTSUPP;
1433 break;
1434 case USB_DEVICE_LTM_ENABLE:
1435 if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1436 HCD_USB3)
1437 w_value = USB_DEV_STAT_LTM_ENABLED;
1438 else
1439 ret_val = -EOPNOTSUPP;
1440 break;
1287 default: 1441 default:
1288 ret_val = -EOPNOTSUPP; 1442 ret_val = -EOPNOTSUPP;
1289 } 1443 }
@@ -1310,6 +1464,27 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
1310 case USB_DEVICE_REMOTE_WAKEUP: 1464 case USB_DEVICE_REMOTE_WAKEUP:
1311 w_value = USB_DEVICE_REMOTE_WAKEUP; 1465 w_value = USB_DEVICE_REMOTE_WAKEUP;
1312 break; 1466 break;
1467 case USB_DEVICE_U1_ENABLE:
1468 if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1469 HCD_USB3)
1470 w_value = USB_DEV_STAT_U1_ENABLED;
1471 else
1472 ret_val = -EOPNOTSUPP;
1473 break;
1474 case USB_DEVICE_U2_ENABLE:
1475 if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1476 HCD_USB3)
1477 w_value = USB_DEV_STAT_U2_ENABLED;
1478 else
1479 ret_val = -EOPNOTSUPP;
1480 break;
1481 case USB_DEVICE_LTM_ENABLE:
1482 if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1483 HCD_USB3)
1484 w_value = USB_DEV_STAT_LTM_ENABLED;
1485 else
1486 ret_val = -EOPNOTSUPP;
1487 break;
1313 default: 1488 default:
1314 ret_val = -EOPNOTSUPP; 1489 ret_val = -EOPNOTSUPP;
1315 break; 1490 break;
@@ -1391,6 +1566,10 @@ static void dummy_timer(unsigned long _dum_hcd)
1391 case USB_SPEED_HIGH: 1566 case USB_SPEED_HIGH:
1392 total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/; 1567 total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/;
1393 break; 1568 break;
1569 case USB_SPEED_SUPER:
1570 /* Bus speed is 500000 bytes/ms, so use a little less */
1571 total = 490000;
1572 break;
1394 default: 1573 default:
1395 dev_err(dummy_dev(dum_hcd), "bogus device speed\n"); 1574 dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
1396 return; 1575 return;
@@ -1625,6 +1804,18 @@ done:
1625} 1804}
1626 1805
1627static inline void 1806static inline void
1807ss_hub_descriptor(struct usb_hub_descriptor *desc)
1808{
1809 memset(desc, 0, sizeof *desc);
1810 desc->bDescriptorType = 0x2a;
1811 desc->bDescLength = 12;
1812 desc->wHubCharacteristics = cpu_to_le16(0x0001);
1813 desc->bNbrPorts = 1;
1814 desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
1815 desc->u.ss.DeviceRemovable = 0xffff;
1816}
1817
1818static inline void
1628hub_descriptor (struct usb_hub_descriptor *desc) 1819hub_descriptor (struct usb_hub_descriptor *desc)
1629{ 1820{
1630 memset (desc, 0, sizeof *desc); 1821 memset (desc, 0, sizeof *desc);
@@ -1660,6 +1851,12 @@ static int dummy_hub_control (
1660 case ClearPortFeature: 1851 case ClearPortFeature:
1661 switch (wValue) { 1852 switch (wValue) {
1662 case USB_PORT_FEAT_SUSPEND: 1853 case USB_PORT_FEAT_SUSPEND:
1854 if (hcd->speed == HCD_USB3) {
1855 dev_dbg(dummy_dev(dum_hcd),
1856 "USB_PORT_FEAT_SUSPEND req not "
1857 "supported for USB 3.0 roothub\n");
1858 goto error;
1859 }
1663 if (dum_hcd->port_status & USB_PORT_STAT_SUSPEND) { 1860 if (dum_hcd->port_status & USB_PORT_STAT_SUSPEND) {
1664 /* 20msec resume signaling */ 1861 /* 20msec resume signaling */
1665 dum_hcd->resuming = 1; 1862 dum_hcd->resuming = 1;
@@ -1668,8 +1865,15 @@ static int dummy_hub_control (
1668 } 1865 }
1669 break; 1866 break;
1670 case USB_PORT_FEAT_POWER: 1867 case USB_PORT_FEAT_POWER:
1671 if (dum_hcd->port_status & USB_PORT_STAT_POWER) 1868 if (hcd->speed == HCD_USB3) {
1672 dev_dbg(dummy_dev(dum_hcd), "power-off\n"); 1869 if (dum_hcd->port_status & USB_PORT_STAT_POWER)
1870 dev_dbg(dummy_dev(dum_hcd),
1871 "power-off\n");
1872 } else
1873 if (dum_hcd->port_status &
1874 USB_SS_PORT_STAT_POWER)
1875 dev_dbg(dummy_dev(dum_hcd),
1876 "power-off\n");
1673 /* FALLS THROUGH */ 1877 /* FALLS THROUGH */
1674 default: 1878 default:
1675 dum_hcd->port_status &= ~(1 << wValue); 1879 dum_hcd->port_status &= ~(1 << wValue);
@@ -1677,7 +1881,18 @@ static int dummy_hub_control (
1677 } 1881 }
1678 break; 1882 break;
1679 case GetHubDescriptor: 1883 case GetHubDescriptor:
1680 hub_descriptor((struct usb_hub_descriptor *) buf); 1884 if (hcd->speed == HCD_USB3 &&
1885 (wLength < USB_DT_SS_HUB_SIZE ||
1886 wValue != (USB_DT_SS_HUB << 8))) {
1887 dev_dbg(dummy_dev(dum_hcd),
1888 "Wrong hub descriptor type for "
1889 "USB 3.0 roothub.\n");
1890 goto error;
1891 }
1892 if (hcd->speed == HCD_USB3)
1893 ss_hub_descriptor((struct usb_hub_descriptor *) buf);
1894 else
1895 hub_descriptor((struct usb_hub_descriptor *) buf);
1681 break; 1896 break;
1682 case GetHubStatus: 1897 case GetHubStatus:
1683 *(__le32 *) buf = cpu_to_le32 (0); 1898 *(__le32 *) buf = cpu_to_le32 (0);
@@ -1700,21 +1915,24 @@ static int dummy_hub_control (
1700 dum_hcd->port_status &= ~USB_PORT_STAT_RESET; 1915 dum_hcd->port_status &= ~USB_PORT_STAT_RESET;
1701 if (dum_hcd->dum->pullup) { 1916 if (dum_hcd->dum->pullup) {
1702 dum_hcd->port_status |= USB_PORT_STAT_ENABLE; 1917 dum_hcd->port_status |= USB_PORT_STAT_ENABLE;
1703 switch (dum_hcd->dum->gadget.speed) { 1918
1704 case USB_SPEED_HIGH: 1919 if (hcd->speed < HCD_USB3) {
1705 dum_hcd->port_status |= 1920 switch (dum_hcd->dum->gadget.speed) {
1706 USB_PORT_STAT_HIGH_SPEED; 1921 case USB_SPEED_HIGH:
1707 break; 1922 dum_hcd->port_status |=
1708 case USB_SPEED_LOW: 1923 USB_PORT_STAT_HIGH_SPEED;
1709 dum_hcd->dum->gadget.ep0-> 1924 break;
1710 maxpacket = 8; 1925 case USB_SPEED_LOW:
1711 dum_hcd->port_status |= 1926 dum_hcd->dum->gadget.ep0->
1712 USB_PORT_STAT_LOW_SPEED; 1927 maxpacket = 8;
1713 break; 1928 dum_hcd->port_status |=
1714 default: 1929 USB_PORT_STAT_LOW_SPEED;
1715 dum_hcd->dum->gadget.speed = 1930 break;
1716 USB_SPEED_FULL; 1931 default:
1717 break; 1932 dum_hcd->dum->gadget.speed =
1933 USB_SPEED_FULL;
1934 break;
1935 }
1718 } 1936 }
1719 } 1937 }
1720 } 1938 }
@@ -1727,7 +1945,36 @@ static int dummy_hub_control (
1727 break; 1945 break;
1728 case SetPortFeature: 1946 case SetPortFeature:
1729 switch (wValue) { 1947 switch (wValue) {
1948 case USB_PORT_FEAT_LINK_STATE:
1949 if (hcd->speed != HCD_USB3) {
1950 dev_dbg(dummy_dev(dum_hcd),
1951 "USB_PORT_FEAT_LINK_STATE req not "
1952 "supported for USB 2.0 roothub\n");
1953 goto error;
1954 }
1955 /*
1956 * Since this is dummy we don't have an actual link so
1957 * there is nothing to do for the SET_LINK_STATE cmd
1958 */
1959 break;
1960 case USB_PORT_FEAT_U1_TIMEOUT:
1961 case USB_PORT_FEAT_U2_TIMEOUT:
1962 /* TODO: add suspend/resume support! */
1963 if (hcd->speed != HCD_USB3) {
1964 dev_dbg(dummy_dev(dum_hcd),
1965 "USB_PORT_FEAT_U1/2_TIMEOUT req not "
1966 "supported for USB 2.0 roothub\n");
1967 goto error;
1968 }
1969 break;
1730 case USB_PORT_FEAT_SUSPEND: 1970 case USB_PORT_FEAT_SUSPEND:
1971 /* Applicable only for USB2.0 hub */
1972 if (hcd->speed == HCD_USB3) {
1973 dev_dbg(dummy_dev(dum_hcd),
1974 "USB_PORT_FEAT_SUSPEND req not "
1975 "supported for USB 3.0 roothub\n");
1976 goto error;
1977 }
1731 if (dum_hcd->active) { 1978 if (dum_hcd->active) {
1732 dum_hcd->port_status |= USB_PORT_STAT_SUSPEND; 1979 dum_hcd->port_status |= USB_PORT_STAT_SUSPEND;
1733 1980
@@ -1742,12 +1989,31 @@ static int dummy_hub_control (
1742 } 1989 }
1743 break; 1990 break;
1744 case USB_PORT_FEAT_POWER: 1991 case USB_PORT_FEAT_POWER:
1745 dum_hcd->port_status |= USB_PORT_STAT_POWER; 1992 if (hcd->speed == HCD_USB3)
1993 dum_hcd->port_status |= USB_SS_PORT_STAT_POWER;
1994 else
1995 dum_hcd->port_status |= USB_PORT_STAT_POWER;
1746 set_link_state(dum_hcd); 1996 set_link_state(dum_hcd);
1747 break; 1997 break;
1998 case USB_PORT_FEAT_BH_PORT_RESET:
1999 /* Applicable only for USB3.0 hub */
2000 if (hcd->speed != HCD_USB3) {
2001 dev_dbg(dummy_dev(dum_hcd),
2002 "USB_PORT_FEAT_BH_PORT_RESET req not "
2003 "supported for USB 2.0 roothub\n");
2004 goto error;
2005 }
2006 /* FALLS THROUGH */
1748 case USB_PORT_FEAT_RESET: 2007 case USB_PORT_FEAT_RESET:
1749 /* if it's already enabled, disable */ 2008 /* if it's already enabled, disable */
1750 dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE 2009 if (hcd->speed == HCD_USB3) {
2010 dum_hcd->port_status = 0;
2011 dum_hcd->port_status =
2012 (USB_SS_PORT_STAT_POWER |
2013 USB_PORT_STAT_CONNECTION |
2014 USB_PORT_STAT_RESET);
2015 } else
2016 dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE
1751 | USB_PORT_STAT_LOW_SPEED 2017 | USB_PORT_STAT_LOW_SPEED
1752 | USB_PORT_STAT_HIGH_SPEED); 2018 | USB_PORT_STAT_HIGH_SPEED);
1753 /* 2019 /*
@@ -1756,21 +2022,50 @@ static int dummy_hub_control (
1756 */ 2022 */
1757 dum_hcd->dum->devstatus &= 2023 dum_hcd->dum->devstatus &=
1758 (1 << USB_DEVICE_SELF_POWERED); 2024 (1 << USB_DEVICE_SELF_POWERED);
2025 /*
2026 * FIXME USB3.0: what is the correct reset signaling
2027 * interval? Is it still 50msec as for HS?
2028 */
1759 dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50); 2029 dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
1760 /* FALLS THROUGH */ 2030 /* FALLS THROUGH */
1761 default: 2031 default:
1762 if ((dum_hcd->port_status & 2032 if (hcd->speed == HCD_USB3) {
1763 USB_PORT_STAT_POWER) != 0) { 2033 if ((dum_hcd->port_status &
1764 dum_hcd->port_status |= (1 << wValue); 2034 USB_SS_PORT_STAT_POWER) != 0) {
1765 set_link_state(dum_hcd); 2035 dum_hcd->port_status |= (1 << wValue);
1766 } 2036 set_link_state(dum_hcd);
2037 }
2038 } else
2039 if ((dum_hcd->port_status &
2040 USB_PORT_STAT_POWER) != 0) {
2041 dum_hcd->port_status |= (1 << wValue);
2042 set_link_state(dum_hcd);
2043 }
2044 }
2045 break;
2046 case GetPortErrorCount:
2047 if (hcd->speed != HCD_USB3) {
2048 dev_dbg(dummy_dev(dum_hcd),
2049 "GetPortErrorCount req not "
2050 "supported for USB 2.0 roothub\n");
2051 goto error;
2052 }
2053 /* We'll always return 0 since this is a dummy hub */
2054 *(__le32 *) buf = cpu_to_le32(0);
2055 break;
2056 case SetHubDepth:
2057 if (hcd->speed != HCD_USB3) {
2058 dev_dbg(dummy_dev(dum_hcd),
2059 "SetHubDepth req not supported for "
2060 "USB 2.0 roothub\n");
2061 goto error;
1767 } 2062 }
1768 break; 2063 break;
1769
1770 default: 2064 default:
1771 dev_dbg(dummy_dev(dum_hcd), 2065 dev_dbg(dummy_dev(dum_hcd),
1772 "hub control req%04x v%04x i%04x l%d\n", 2066 "hub control req%04x v%04x i%04x l%d\n",
1773 typeReq, wValue, wIndex, wLength); 2067 typeReq, wValue, wIndex, wLength);
2068error:
1774 /* "protocol stall" on error */ 2069 /* "protocol stall" on error */
1775 retval = -EPIPE; 2070 retval = -EPIPE;
1776 } 2071 }
@@ -1837,6 +2132,9 @@ show_urb (char *buf, size_t size, struct urb *urb)
1837 case USB_SPEED_HIGH: 2132 case USB_SPEED_HIGH:
1838 s = "hs"; 2133 s = "hs";
1839 break; 2134 break;
2135 case USB_SPEED_SUPER:
2136 s = "ss";
2137 break;
1840 default: 2138 default:
1841 s = "?"; 2139 s = "?";
1842 break; 2140 break;
@@ -1883,6 +2181,25 @@ show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
1883} 2181}
1884static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); 2182static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL);
1885 2183
2184static int dummy_start_ss(struct dummy_hcd *dum_hcd)
2185{
2186 init_timer(&dum_hcd->timer);
2187 dum_hcd->timer.function = dummy_timer;
2188 dum_hcd->timer.data = (unsigned long)dum_hcd;
2189 dum_hcd->rh_state = DUMMY_RH_RUNNING;
2190 INIT_LIST_HEAD(&dum_hcd->urbp_list);
2191 dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET;
2192 dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
2193 dummy_hcd_to_hcd(dum_hcd)->uses_new_polling = 1;
2194#ifdef CONFIG_USB_OTG
2195 dummy_hcd_to_hcd(dum_hcd)->self.otg_port = 1;
2196#endif
2197 return 0;
2198
2199 /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
2200 return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
2201}
2202
1886static int dummy_start(struct usb_hcd *hcd) 2203static int dummy_start(struct usb_hcd *hcd)
1887{ 2204{
1888 struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); 2205 struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
@@ -1892,6 +2209,9 @@ static int dummy_start(struct usb_hcd *hcd)
1892 * talk to one device (the slave side). Also appears in sysfs, 2209 * talk to one device (the slave side). Also appears in sysfs,
1893 * just like more familiar pci-based HCDs. 2210 * just like more familiar pci-based HCDs.
1894 */ 2211 */
2212 if (!usb_hcd_is_primary_hcd(hcd))
2213 return dummy_start_ss(dum_hcd);
2214
1895 spin_lock_init(&dum_hcd->dum->lock); 2215 spin_lock_init(&dum_hcd->dum->lock);
1896 init_timer(&dum_hcd->timer); 2216 init_timer(&dum_hcd->timer);
1897 dum_hcd->timer.function = dummy_timer; 2217 dum_hcd->timer.function = dummy_timer;
@@ -1934,19 +2254,52 @@ static int dummy_setup(struct usb_hcd *hcd)
1934 if (usb_hcd_is_primary_hcd(hcd)) { 2254 if (usb_hcd_is_primary_hcd(hcd)) {
1935 the_controller.hs_hcd = hcd_to_dummy_hcd(hcd); 2255 the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
1936 the_controller.hs_hcd->dum = &the_controller; 2256 the_controller.hs_hcd->dum = &the_controller;
1937 /* Mark the first roothub as being USB 2.0. */ 2257 /*
2258 * Mark the first roothub as being USB 2.0.
2259 * The USB 3.0 roothub will be registered later by
2260 * dummy_hcd_probe()
2261 */
1938 hcd->speed = HCD_USB2; 2262 hcd->speed = HCD_USB2;
1939 hcd->self.root_hub->speed = USB_SPEED_HIGH; 2263 hcd->self.root_hub->speed = USB_SPEED_HIGH;
2264 } else {
2265 the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
2266 the_controller.ss_hcd->dum = &the_controller;
2267 hcd->speed = HCD_USB3;
2268 hcd->self.root_hub->speed = USB_SPEED_SUPER;
1940 } 2269 }
1941 return 0; 2270 return 0;
1942} 2271}
1943 2272
1944static const struct hc_driver dummy_hcd = { 2273/* Change a group of bulk endpoints to support multiple stream IDs */
2274int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
2275 struct usb_host_endpoint **eps, unsigned int num_eps,
2276 unsigned int num_streams, gfp_t mem_flags)
2277{
2278 if (hcd->speed != HCD_USB3)
2279 dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
2280 "%s() - ERROR! Not supported for USB2.0 roothub\n",
2281 __func__);
2282 return 0;
2283}
2284
2285/* Reverts a group of bulk endpoints back to not using stream IDs. */
2286int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
2287 struct usb_host_endpoint **eps, unsigned int num_eps,
2288 gfp_t mem_flags)
2289{
2290 if (hcd->speed != HCD_USB3)
2291 dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
2292 "%s() - ERROR! Not supported for USB2.0 roothub\n",
2293 __func__);
2294 return 0;
2295}
2296
2297static struct hc_driver dummy_hcd = {
1945 .description = (char *) driver_name, 2298 .description = (char *) driver_name,
1946 .product_desc = "Dummy host controller", 2299 .product_desc = "Dummy host controller",
1947 .hcd_priv_size = sizeof(struct dummy_hcd), 2300 .hcd_priv_size = sizeof(struct dummy_hcd),
1948 2301
1949 .flags = HCD_USB2, 2302 .flags = HCD_USB3 | HCD_SHARED,
1950 2303
1951 .reset = dummy_setup, 2304 .reset = dummy_setup,
1952 .start = dummy_start, 2305 .start = dummy_start,
@@ -1961,15 +2314,21 @@ static const struct hc_driver dummy_hcd = {
1961 .hub_control = dummy_hub_control, 2314 .hub_control = dummy_hub_control,
1962 .bus_suspend = dummy_bus_suspend, 2315 .bus_suspend = dummy_bus_suspend,
1963 .bus_resume = dummy_bus_resume, 2316 .bus_resume = dummy_bus_resume,
2317
2318 .alloc_streams = dummy_alloc_streams,
2319 .free_streams = dummy_free_streams,
1964}; 2320};
1965 2321
1966static int dummy_hcd_probe(struct platform_device *pdev) 2322static int dummy_hcd_probe(struct platform_device *pdev)
1967{ 2323{
1968 struct usb_hcd *hs_hcd; 2324 struct usb_hcd *hs_hcd;
2325 struct usb_hcd *ss_hcd;
1969 int retval; 2326 int retval;
1970 2327
1971 dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); 2328 dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
1972 2329
2330 if (!mod_data.is_super_speed)
2331 dummy_hcd.flags = HCD_USB2;
1973 hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); 2332 hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
1974 if (!hs_hcd) 2333 if (!hs_hcd)
1975 return -ENOMEM; 2334 return -ENOMEM;
@@ -1978,8 +2337,28 @@ static int dummy_hcd_probe(struct platform_device *pdev)
1978 retval = usb_add_hcd(hs_hcd, 0, 0); 2337 retval = usb_add_hcd(hs_hcd, 0, 0);
1979 if (retval != 0) { 2338 if (retval != 0) {
1980 usb_put_hcd(hs_hcd); 2339 usb_put_hcd(hs_hcd);
1981 the_controller.hs_hcd = NULL; 2340 return retval;
1982 } 2341 }
2342
2343 if (mod_data.is_super_speed) {
2344 ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
2345 dev_name(&pdev->dev), hs_hcd);
2346 if (!ss_hcd) {
2347 retval = -ENOMEM;
2348 goto dealloc_usb2_hcd;
2349 }
2350
2351 retval = usb_add_hcd(ss_hcd, 0, 0);
2352 if (retval)
2353 goto put_usb3_hcd;
2354 }
2355 return 0;
2356
2357put_usb3_hcd:
2358 usb_put_hcd(ss_hcd);
2359dealloc_usb2_hcd:
2360 usb_put_hcd(hs_hcd);
2361 the_controller.hs_hcd = the_controller.ss_hcd = NULL;
1983 return retval; 2362 return retval;
1984} 2363}
1985 2364
@@ -1988,9 +2367,17 @@ static int dummy_hcd_remove(struct platform_device *pdev)
1988 struct dummy *dum; 2367 struct dummy *dum;
1989 2368
1990 dum = (hcd_to_dummy_hcd(platform_get_drvdata(pdev)))->dum; 2369 dum = (hcd_to_dummy_hcd(platform_get_drvdata(pdev)))->dum;
2370
2371 if (dum->ss_hcd) {
2372 usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
2373 usb_put_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
2374 }
2375
1991 usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd)); 2376 usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
1992 usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd)); 2377 usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
2378
1993 the_controller.hs_hcd = NULL; 2379 the_controller.hs_hcd = NULL;
2380 the_controller.ss_hcd = NULL;
1994 2381
1995 return 0; 2382 return 0;
1996} 2383}
@@ -2065,7 +2452,8 @@ static int __init init (void)
2065 retval = platform_device_add(the_hcd_pdev); 2452 retval = platform_device_add(the_hcd_pdev);
2066 if (retval < 0) 2453 if (retval < 0)
2067 goto err_add_hcd; 2454 goto err_add_hcd;
2068 if (!the_controller.hs_hcd) { 2455 if (!the_controller.hs_hcd ||
2456 (!the_controller.ss_hcd && mod_data.is_super_speed)) {
2069 /* 2457 /*
2070 * The hcd was added successfully but its probe function failed 2458 * The hcd was added successfully but its probe function failed
2071 * for some reason. 2459 * for some reason.