From 412af3d25ba76f8dfda3bd9d2715e1119e671d32 Mon Sep 17 00:00:00 2001 From: make shi Date: Wed, 23 Jan 2013 10:36:00 +0800 Subject: ENGR00241582 MX6 USB host: USB host certification patch The patch include: - USB test mode on hub port and Root-hub port - support 3 types of message: too much hub ties for hub attachment too much power consumption for device attachment unsupported device class warning - support menuconfig select the FSL_USB_TEST_MODE, located in: -> Device Drivers -> USB support (USB_SUPPORT [=y]) -> FSL High-speed Electrical Test Mode support Signed-off-by: make shi --- drivers/usb/core/hub.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers/usb/core/hub.c') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 694476ea22ac..16a790826fbb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -165,7 +165,50 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); #define HUB_DEBOUNCE_STEP 25 #define HUB_DEBOUNCE_STABLE 100 +#ifdef CONFIG_FSL_USB_TEST_MODE +static u8 usb_device_white_list[] = { + USB_CLASS_HID, + USB_CLASS_HUB, + USB_CLASS_MASS_STORAGE +}; + +static inline int in_white_list(u8 interfaceclass) +{ + int i; + for (i = 0; i < sizeof(usb_device_white_list); i++) { + if (interfaceclass == usb_device_white_list[i]) + return 1; + } + return 0; +} + +static inline int device_in_white_list(struct usb_device *udev) +{ + int i; + int num_configs; + struct usb_host_config *c; + + /* for test fixture, we always return 1 */ + if (udev->descriptor.idVendor == 0x1A0A) + return 1; + + c = udev->config; + num_configs = udev->descriptor.bNumConfigurations; + for (i = 0; i < num_configs; (i++, c++)) { + struct usb_interface_descriptor *desc = NULL; + + /* It's possible that a config has no interfaces! */ + if (c->desc.bNumInterfaces > 0) + desc = &c->intf_cache[0]->altsetting->desc; + if (desc && !in_white_list((u8)desc->bInterfaceClass)) + continue; + + return 1; + } + return 0; +} +#endif static int usb_reset_and_verify_device(struct usb_device *udev); static inline char *portspeed(struct usb_hub *hub, int portstatus) @@ -1914,6 +1957,14 @@ int usb_new_device(struct usb_device *udev) udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); +#ifdef CONFIG_FSL_USB_TEST_MODE + if (!device_in_white_list(udev)) { + printk(KERN_ERR "unsupported device: not in white list\n"); + goto fail; + } else { + printk(KERN_DEBUG "supported device\n"); + } +#endif /* Tell the world! */ announce_device(udev); @@ -3300,6 +3351,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, usb_set_device_state(udev, USB_STATE_POWERED); udev->bus_mA = hub->mA_per_port; udev->level = hdev->level + 1; +#ifdef CONFIG_FSL_USB_TEST_MODE + printk(KERN_INFO "+++ %s:udev->level :%d", __func__, + udev->level); +#endif udev->wusb = hub_is_wusb(hub); /* Only USB 3.0 devices are connected to SuperSpeed hubs. */ @@ -3518,6 +3573,10 @@ static void hub_events(void) if (ret < 0) continue; +#ifdef CONFIG_FSL_USB_TEST_MODE + if (portstatus & USB_PORT_STAT_TEST) + continue; +#endif if (portchange & USB_PORT_STAT_C_CONNECTION) { clear_port_feature(hdev, i, USB_PORT_FEAT_C_CONNECTION); -- cgit v1.2.3 From 1aa6b2c7e4b030f5319d05aaa4de520595ed92b2 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 10 Dec 2013 17:45:44 +0800 Subject: usb: core: fix two problems for unsupported devices - NULL pointer after removing unsupported devices - only print "hub 2-0:1.0: port 1 nyet suspended" for device who has enumerated successfully Signed-off-by: Peter Chen --- drivers/usb/core/hub.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/usb/core/hub.c') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 16a790826fbb..ea6cd7feea01 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1739,7 +1739,18 @@ void usb_disconnect(struct usb_device **pdev) * for de-configuring the device and invoking the remove-device * notifier chain (used by usbfs and possibly others). */ - device_del(&udev->dev); +/* device_del(&udev->dev); */ + /* If error occur during enumeration, maybe the device_add + * will not call at all, so we need to identify whether this + * device has been added or not, here we use dev.driver to + * tell it + */ + if (udev->dev.driver) { + device_del(&udev->dev); + printk(KERN_DEBUG "device_del called\n"); + } else { + printk(KERN_DEBUG "device_del not need to call\n"); + } /* Free the device number and delete the parent's children[] * (or root_hub) pointer. @@ -2696,7 +2707,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) struct usb_device *udev; udev = hdev->children [port1-1]; - if (udev && udev->can_submit) { + if (udev && udev->can_submit && udev->dev.driver) { dev_warn(&intf->dev, "port %d nyet suspended\n", port1); if (msg.event & PM_EVENT_AUTO) return -EBUSY; -- cgit v1.2.3