From 6988cc853bc47ccb8fb7e6e4e8ed3367cfd9edb8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Dec 2012 21:42:03 +0200 Subject: [PATCH] --- yaml --- r: 354598 b: refs/heads/master c: 5da93478251cf0dd6b34874c7c1c24a4a52eabc1 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/ABI/testing/sysfs-bus-usb | 9 - .../devicetree/bindings/usb/usb3503.txt | 20 - trunk/drivers/usb/c67x00/c67x00-ll-hpi.c | 2 +- trunk/drivers/usb/chipidea/core.c | 2 +- trunk/drivers/usb/core/Makefile | 1 - trunk/drivers/usb/core/devices.c | 13 +- trunk/drivers/usb/core/generic.c | 2 +- trunk/drivers/usb/core/hcd.c | 5 +- trunk/drivers/usb/core/hub.c | 442 +++++++++--------- trunk/drivers/usb/core/hub.h | 97 ---- trunk/drivers/usb/core/message.c | 2 +- trunk/drivers/usb/core/port.c | 111 ----- trunk/drivers/usb/core/sysfs.c | 31 +- trunk/drivers/usb/core/usb.h | 12 - trunk/drivers/usb/dwc3/core.h | 4 +- trunk/drivers/usb/host/ehci-mxc.c | 20 + trunk/drivers/usb/host/ehci-s5p.c | 2 +- trunk/drivers/usb/host/ohci-exynos.c | 2 +- trunk/drivers/usb/host/ohci-q.c | 1 - trunk/drivers/usb/host/uhci-debug.c | 178 +++---- trunk/drivers/usb/host/uhci-hcd.c | 31 +- trunk/drivers/usb/host/uhci-hcd.h | 4 + trunk/drivers/usb/host/uhci-hub.c | 4 +- trunk/drivers/usb/host/uhci-q.c | 2 +- trunk/drivers/usb/host/xhci-ring.c | 2 + trunk/drivers/usb/misc/Kconfig | 6 - trunk/drivers/usb/misc/Makefile | 1 - trunk/drivers/usb/misc/usb3503.c | 325 ------------- trunk/drivers/usb/musb/am35x.c | 2 +- trunk/drivers/usb/musb/blackfin.c | 2 +- trunk/drivers/usb/musb/da8xx.c | 7 +- trunk/drivers/usb/musb/davinci.c | 7 +- trunk/drivers/usb/musb/musb_core.c | 1 - trunk/drivers/usb/musb/musb_dsps.c | 3 +- trunk/drivers/usb/musb/musb_gadget.c | 22 +- trunk/drivers/usb/musb/musb_host.c | 44 +- trunk/drivers/usb/musb/omap2430.c | 16 +- trunk/drivers/usb/musb/tusb6010.c | 2 +- trunk/drivers/usb/musb/ux500.c | 12 +- trunk/drivers/usb/serial/io_ti.c | 86 +++- trunk/drivers/usb/serial/keyspan.c | 4 +- trunk/drivers/usb/serial/option.c | 10 +- trunk/drivers/usb/serial/usb-serial.c | 14 +- trunk/drivers/usb/storage/uas.c | 122 +---- trunk/drivers/usb/storage/usb.c | 3 - trunk/include/linux/platform_data/usb3503.h | 19 - trunk/tools/usb/testusb.c | 4 +- 48 files changed, 478 insertions(+), 1235 deletions(-) delete mode 100644 trunk/Documentation/devicetree/bindings/usb/usb3503.txt delete mode 100644 trunk/drivers/usb/core/hub.h delete mode 100644 trunk/drivers/usb/core/port.c delete mode 100644 trunk/drivers/usb/misc/usb3503.c delete mode 100644 trunk/include/linux/platform_data/usb3503.h diff --git a/[refs] b/[refs] index 655c524d2d45..9980d38dd0cf 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 468234984f7bce270484d833899cd8ed4d61e885 +refs/heads/master: 5da93478251cf0dd6b34874c7c1c24a4a52eabc1 diff --git a/trunk/Documentation/ABI/testing/sysfs-bus-usb b/trunk/Documentation/ABI/testing/sysfs-bus-usb index c8baaf53594a..b6fbe514a869 100644 --- a/trunk/Documentation/ABI/testing/sysfs-bus-usb +++ b/trunk/Documentation/ABI/testing/sysfs-bus-usb @@ -227,12 +227,3 @@ Contact: Lan Tianyu Description: The /sys/bus/usb/devices/.../(hub interface)/portX is usb port device's sysfs directory. - -What: /sys/bus/usb/devices/.../(hub interface)/portX/connect_type -Date: January 2013 -Contact: Lan Tianyu -Description: - Some platforms provide usb port connect types through ACPI. - This attribute is to expose these information to user space. - The file will read "hotplug", "wired" and "not used" if the - information is available, and "unknown" otherwise. diff --git a/trunk/Documentation/devicetree/bindings/usb/usb3503.txt b/trunk/Documentation/devicetree/bindings/usb/usb3503.txt deleted file mode 100644 index 6813a715fc7d..000000000000 --- a/trunk/Documentation/devicetree/bindings/usb/usb3503.txt +++ /dev/null @@ -1,20 +0,0 @@ -SMSC USB3503 High-Speed Hub Controller - -Required properties: -- compatible: Should be "smsc,usb3503". -- reg: Specifies the i2c slave address, it should be 0x08. -- connect-gpios: Should specify GPIO for connect. -- intn-gpios: Should specify GPIO for interrupt. -- reset-gpios: Should specify GPIO for reset. -- initial-mode: Should specify initial mode. - (1 for HUB mode, 2 for STANDBY mode) - -Examples: - usb3503@08 { - compatible = "smsc,usb3503"; - reg = <0x08>; - connect-gpios = <&gpx3 0 1>; - intn-gpios = <&gpx3 4 1>; - reset-gpios = <&gpx3 5 1>; - initial-mode = <1>; - }; diff --git a/trunk/drivers/usb/c67x00/c67x00-ll-hpi.c b/trunk/drivers/usb/c67x00/c67x00-ll-hpi.c index 3a1ca4dfc83a..a9636f43bca2 100644 --- a/trunk/drivers/usb/c67x00/c67x00-ll-hpi.c +++ b/trunk/drivers/usb/c67x00/c67x00-ll-hpi.c @@ -237,7 +237,7 @@ void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie) /* -------------------------------------------------------------------------- */ /* Transactions */ -static inline int ll_recv_msg(struct c67x00_device *dev) +static inline u16 ll_recv_msg(struct c67x00_device *dev) { u16 res; diff --git a/trunk/drivers/usb/chipidea/core.c b/trunk/drivers/usb/chipidea/core.c index 57cae1f897b2..aebf695a9344 100644 --- a/trunk/drivers/usb/chipidea/core.c +++ b/trunk/drivers/usb/chipidea/core.c @@ -411,7 +411,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) } base = devm_request_and_ioremap(dev, res); - if (!base) { + if (!res) { dev_err(dev, "can't request and ioremap resource\n"); return -ENOMEM; } diff --git a/trunk/drivers/usb/core/Makefile b/trunk/drivers/usb/core/Makefile index 5e847ad2f58a..26059b93dbf4 100644 --- a/trunk/drivers/usb/core/Makefile +++ b/trunk/drivers/usb/core/Makefile @@ -7,7 +7,6 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o usbcore-y += devio.o notify.o generic.o quirks.o devices.o -usbcore-y += port.o usbcore-$(CONFIG_PCI) += hcd-pci.o usbcore-$(CONFIG_ACPI) += usb-acpi.o diff --git a/trunk/drivers/usb/core/devices.c b/trunk/drivers/usb/core/devices.c index e33224e23770..cbacea933b18 100644 --- a/trunk/drivers/usb/core/devices.c +++ b/trunk/drivers/usb/core/devices.c @@ -316,23 +316,17 @@ static char *usb_dump_iad_descriptor(char *start, char *end, */ static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, - int active, int speed) + int active) { - int mul; - if (start > end) return start; - if (speed == USB_SPEED_SUPER) - mul = 8; - else - mul = 2; start += sprintf(start, format_config, /* mark active/actual/current cfg. */ active ? '*' : ' ', desc->bNumInterfaces, desc->bConfigurationValue, desc->bmAttributes, - desc->bMaxPower * mul); + desc->bMaxPower * 2); return start; } @@ -348,8 +342,7 @@ static char *usb_dump_config(int speed, char *start, char *end, if (!config) /* getting these some in 2.3.7; none in 2.3.6 */ return start + sprintf(start, "(null Cfg. desc.)\n"); - start = usb_dump_config_descriptor(start, end, &config->desc, active, - speed); + start = usb_dump_config_descriptor(start, end, &config->desc, active); for (i = 0; i < USB_MAXIADS; i++) { if (config->intf_assoc[i] == NULL) break; diff --git a/trunk/drivers/usb/core/generic.c b/trunk/drivers/usb/core/generic.c index 271e761f563e..eff2010eb63f 100644 --- a/trunk/drivers/usb/core/generic.c +++ b/trunk/drivers/usb/core/generic.c @@ -100,7 +100,7 @@ int usb_choose_configuration(struct usb_device *udev) */ /* Rule out configs that draw too much bus current */ - if (usb_get_max_power(udev, c) > udev->bus_mA) { + if (c->desc.bMaxPower * 2 > udev->bus_mA) { insufficient_power++; continue; } diff --git a/trunk/drivers/usb/core/hcd.c b/trunk/drivers/usb/core/hcd.c index 2459896d040a..4225d5e72131 100644 --- a/trunk/drivers/usb/core/hcd.c +++ b/trunk/drivers/usb/core/hcd.c @@ -619,10 +619,6 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) status = hcd->driver->hub_control (hcd, typeReq, wValue, wIndex, tbuf, wLength); - - if (typeReq == GetHubDescriptor) - usb_hub_adjust_deviceremovable(hcd->self.root_hub, - (struct usb_hub_descriptor *)tbuf); break; error: /* "protocol stall" on error */ @@ -2510,6 +2506,7 @@ int usb_add_hcd(struct usb_hcd *hcd, } /* starting here, usbcore will pay attention to this root hub */ + rhdev->bus_mA = min(500u, hcd->power_budget); if ((retval = register_root_hub(hcd)) != 0) goto err_register_root_hub; diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 29ca6ed3bea8..957ed2c41482 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -30,7 +30,7 @@ #include #include -#include "hub.h" +#include "usb.h" /* if we are in debug mode, always announce new devices */ #ifdef DEBUG @@ -42,6 +42,62 @@ #define USB_VENDOR_GENESYS_LOGIC 0x05e3 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 +struct usb_port { + struct usb_device *child; + struct device dev; + struct dev_state *port_owner; + enum usb_port_connect_type connect_type; +}; + +struct usb_hub { + struct device *intfdev; /* the "interface" device */ + struct usb_device *hdev; + struct kref kref; + struct urb *urb; /* for interrupt polling pipe */ + + /* buffer for urb ... with extra space in case of babble */ + char (*buffer)[8]; + union { + struct usb_hub_status hub; + struct usb_port_status port; + } *status; /* buffer for status reports */ + struct mutex status_mutex; /* for the status buffer */ + + int error; /* last reported error */ + int nerrors; /* track consecutive errors */ + + struct list_head event_list; /* hubs w/data or errs ready */ + unsigned long event_bits[1]; /* status change bitmask */ + unsigned long change_bits[1]; /* ports with logical connect + status change */ + unsigned long busy_bits[1]; /* ports being reset or + resumed */ + unsigned long removed_bits[1]; /* ports with a "removed" + device present */ + unsigned long wakeup_bits[1]; /* ports that have signaled + remote wakeup */ +#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ +#error event_bits[] is too short! +#endif + + struct usb_hub_descriptor *descriptor; /* class descriptor */ + struct usb_tt tt; /* Transaction Translator */ + + unsigned mA_per_port; /* current for each child */ + + unsigned limited_power:1; + unsigned quiescing:1; + unsigned disconnected:1; + + unsigned quirk_check_port_auto_suspend:1; + + unsigned has_indicators:1; + u8 indicator[USB_MAXCHILDREN]; + struct delayed_work leds; + struct delayed_work init_work; + struct usb_port **ports; +}; + static inline int hub_is_superspeed(struct usb_device *hdev) { return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS); @@ -112,6 +168,9 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); #define HUB_DEBOUNCE_STEP 25 #define HUB_DEBOUNCE_STABLE 100 +#define to_usb_port(_dev) \ + container_of(_dev, struct usb_port, dev) + static int usb_reset_and_verify_device(struct usb_device *udev); static inline char *portspeed(struct usb_hub *hub, int portstatus) @@ -1235,6 +1294,52 @@ static int hub_post_reset(struct usb_interface *intf) return 0; } +static void usb_port_device_release(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + + kfree(port_dev); +} + +static void usb_hub_remove_port_device(struct usb_hub *hub, + int port1) +{ + device_unregister(&hub->ports[port1 - 1]->dev); +} + +struct device_type usb_port_device_type = { + .name = "usb_port", + .release = usb_port_device_release, +}; + +static int usb_hub_create_port_device(struct usb_hub *hub, + int port1) +{ + struct usb_port *port_dev = NULL; + int retval; + + port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); + if (!port_dev) { + retval = -ENOMEM; + goto exit; + } + + hub->ports[port1 - 1] = port_dev; + port_dev->dev.parent = hub->intfdev; + port_dev->dev.type = &usb_port_device_type; + dev_set_name(&port_dev->dev, "port%d", port1); + + retval = device_register(&port_dev->dev); + if (retval) + goto error_register; + return 0; + +error_register: + put_device(&port_dev->dev); +exit: + return retval; +} + static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { @@ -1246,8 +1351,6 @@ static int hub_configure(struct usb_hub *hub, unsigned int pipe; int maxp, ret, i; char *message = "out of memory"; - unsigned unit_load; - unsigned full_load; hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); if (!hub->buffer) { @@ -1294,13 +1397,6 @@ static int hub_configure(struct usb_hub *hub, } wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); - if (hub_is_superspeed(hdev)) { - unit_load = 150; - full_load = 900; - } else { - unit_load = 100; - full_load = 500; - } /* FIXME for USB 3.0, skip for now */ if ((wHubCharacteristics & HUB_CHAR_COMPOUND) && @@ -1420,44 +1516,40 @@ static int hub_configure(struct usb_hub *hub, goto fail; } le16_to_cpus(&hubstatus); - hcd = bus_to_hcd(hdev->bus); if (hdev == hdev->bus->root_hub) { - if (hcd->power_budget > 0) - hdev->bus_mA = hcd->power_budget; - else - hdev->bus_mA = full_load * hdev->maxchild; - if (hdev->bus_mA >= full_load) - hub->mA_per_port = full_load; + if (hdev->bus_mA == 0 || hdev->bus_mA >= 500) + hub->mA_per_port = 500; else { hub->mA_per_port = hdev->bus_mA; hub->limited_power = 1; } } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { - int remaining = hdev->bus_mA - - hub->descriptor->bHubContrCurrent; - dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", hub->descriptor->bHubContrCurrent); hub->limited_power = 1; + if (hdev->maxchild > 0) { + int remaining = hdev->bus_mA - + hub->descriptor->bHubContrCurrent; - if (remaining < hdev->maxchild * unit_load) - dev_warn(hub_dev, + if (remaining < hdev->maxchild * 100) + dev_warn(hub_dev, "insufficient power available " "to use all downstream ports\n"); - hub->mA_per_port = unit_load; /* 7.2.1 */ - + hub->mA_per_port = 100; /* 7.2.1.1 */ + } } else { /* Self-powered external hub */ /* FIXME: What about battery-powered external hubs that * provide less current per port? */ - hub->mA_per_port = full_load; + hub->mA_per_port = 500; } - if (hub->mA_per_port < full_load) + if (hub->mA_per_port < 500) dev_dbg(hub_dev, "%umA bus power budget for each child\n", hub->mA_per_port); /* Update the HCD's internal representation of this hub before khubd * starts getting port status changes for devices under the hub. */ + hcd = bus_to_hcd(hdev->bus); if (hcd->driver->update_hub_device) { ret = hcd->driver->update_hub_device(hcd, hdev, &hub->tt, GFP_KERNEL); @@ -1513,8 +1605,6 @@ static int hub_configure(struct usb_hub *hub, dev_err(hub->intfdev, "couldn't create port%d device.\n", i + 1); - usb_hub_adjust_deviceremovable(hdev, hub->descriptor); - hub_activate(hub, HUB_INIT); return 0; @@ -1991,14 +2081,6 @@ void usb_disconnect(struct usb_device **pdev) usb_disable_device(udev, 0); usb_hcd_synchronize_unlinks(udev); - if (udev->parent) { - struct usb_port *port_dev = - hdev_to_hub(udev->parent)->ports[udev->portnum - 1]; - - sysfs_remove_link(&udev->dev.kobj, "port"); - sysfs_remove_link(&port_dev->dev.kobj, "device"); - } - usb_remove_ep_devs(&udev->ep0); usb_unlock_device(udev); @@ -2291,24 +2373,6 @@ int usb_new_device(struct usb_device *udev) goto fail; } - /* Create link files between child device and usb port device. */ - if (udev->parent) { - struct usb_port *port_dev = - hdev_to_hub(udev->parent)->ports[udev->portnum - 1]; - - err = sysfs_create_link(&udev->dev.kobj, - &port_dev->dev.kobj, "port"); - if (err) - goto fail; - - err = sysfs_create_link(&port_dev->dev.kobj, - &udev->dev.kobj, "device"); - if (err) { - sysfs_remove_link(&udev->dev.kobj, "port"); - goto fail; - } - } - (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); usb_mark_last_busy(udev); pm_runtime_put_sync_autosuspend(&udev->dev); @@ -2471,9 +2535,77 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, return ret; /* The port state is unknown until the reset completes. */ - if (!(portstatus & USB_PORT_STAT_RESET)) - break; + if ((portstatus & USB_PORT_STAT_RESET)) + goto delay; + /* + * Some buggy devices require a warm reset to be issued even + * when the port appears not to be connected. + */ + if (!warm) { + /* + * Some buggy devices can cause an NEC host controller + * to transition to the "Error" state after a hot port + * reset. This will show up as the port state in + * "Inactive", and the port may also report a + * disconnect. Forcing a warm port reset seems to make + * the device work. + * + * See https://bugzilla.kernel.org/show_bug.cgi?id=41752 + */ + if (hub_port_warm_reset_required(hub, portstatus)) { + int ret; + + if ((portchange & USB_PORT_STAT_C_CONNECTION)) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + if (portchange & USB_PORT_STAT_C_LINK_STATE) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_PORT_LINK_STATE); + if (portchange & USB_PORT_STAT_C_RESET) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_RESET); + dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", + port1); + ret = hub_port_reset(hub, port1, + udev, HUB_BH_RESET_TIME, + true); + if ((portchange & USB_PORT_STAT_C_CONNECTION)) + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + return ret; + } + /* Device went away? */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return -ENOTCONN; + + /* bomb out completely if the connection bounced */ + if ((portchange & USB_PORT_STAT_C_CONNECTION)) + return -ENOTCONN; + + if ((portstatus & USB_PORT_STAT_ENABLE)) { + if (hub_is_wusb(hub)) + udev->speed = USB_SPEED_WIRELESS; + else if (hub_is_superspeed(hub->hdev)) + udev->speed = USB_SPEED_SUPER; + else if (portstatus & USB_PORT_STAT_HIGH_SPEED) + udev->speed = USB_SPEED_HIGH; + else if (portstatus & USB_PORT_STAT_LOW_SPEED) + udev->speed = USB_SPEED_LOW; + else + udev->speed = USB_SPEED_FULL; + return 0; + } + } else { + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + hub_port_warm_reset_required(hub, + portstatus)) + return -ENOTCONN; + + return 0; + } + +delay: /* switch to the long delay after two short delay failures */ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; @@ -2483,54 +2615,20 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, port1, warm ? "warm " : "", delay); } - if ((portstatus & USB_PORT_STAT_RESET)) - return -EBUSY; - - if (hub_port_warm_reset_required(hub, portstatus)) - return -ENOTCONN; - - /* Device went away? */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return -ENOTCONN; - - /* bomb out completely if the connection bounced. A USB 3.0 - * connection may bounce if multiple warm resets were issued, - * but the device may have successfully re-connected. Ignore it. - */ - if (!hub_is_superspeed(hub->hdev) && - (portchange & USB_PORT_STAT_C_CONNECTION)) - return -ENOTCONN; - - if (!(portstatus & USB_PORT_STAT_ENABLE)) - return -EBUSY; - - if (!udev) - return 0; - - if (hub_is_wusb(hub)) - udev->speed = USB_SPEED_WIRELESS; - else if (hub_is_superspeed(hub->hdev)) - udev->speed = USB_SPEED_SUPER; - else if (portstatus & USB_PORT_STAT_HIGH_SPEED) - udev->speed = USB_SPEED_HIGH; - else if (portstatus & USB_PORT_STAT_LOW_SPEED) - udev->speed = USB_SPEED_LOW; - else - udev->speed = USB_SPEED_FULL; - return 0; + return -EBUSY; } static void hub_port_finish_reset(struct usb_hub *hub, int port1, - struct usb_device *udev, int *status) + struct usb_device *udev, int *status, bool warm) { switch (*status) { case 0: - /* TRSTRCY = 10 ms; plus some extra */ - msleep(10 + 40); - if (udev) { - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - + if (!warm) { + struct usb_hcd *hcd; + /* TRSTRCY = 10 ms; plus some extra */ + msleep(10 + 40); update_devnum(udev, 0); + hcd = bus_to_hcd(udev->bus); /* The xHC may think the device is already reset, * so ignore the status. */ @@ -2542,15 +2640,14 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, case -ENODEV: clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_RESET); + /* FIXME need disconnect() for NOTATTACHED device */ if (hub_is_superspeed(hub->hdev)) { clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_BH_PORT_RESET); clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_PORT_LINK_STATE); - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_CONNECTION); } - if (udev) + if (!warm) usb_set_device_state(udev, *status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT); @@ -2563,30 +2660,18 @@ static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm) { int i, status; - u16 portchange, portstatus; - if (!hub_is_superspeed(hub->hdev)) { - if (warm) { - dev_err(hub->intfdev, "only USB3 hub support " - "warm reset\n"); - return -EINVAL; - } + if (!warm) { /* Block EHCI CF initialization during the port reset. * Some companion controllers don't like it when they mix. */ down_read(&ehci_cf_port_reset_rwsem); - } else if (!warm) { - /* - * If the caller hasn't explicitly requested a warm reset, - * double check and see if one is needed. - */ - status = hub_port_status(hub, port1, - &portstatus, &portchange); - if (status < 0) - goto done; - - if (hub_port_warm_reset_required(hub, portstatus)) - warm = true; + } else { + if (!hub_is_superspeed(hub->hdev)) { + dev_err(hub->intfdev, "only USB3 hub support " + "warm reset\n"); + return -EINVAL; + } } /* Reset the port */ @@ -2607,33 +2692,10 @@ static int hub_port_reset(struct usb_hub *hub, int port1, status); } - /* Check for disconnect or reset */ + /* return on disconnect or reset */ if (status == 0 || status == -ENOTCONN || status == -ENODEV) { - hub_port_finish_reset(hub, port1, udev, &status); - - if (!hub_is_superspeed(hub->hdev)) - goto done; - - /* - * If a USB 3.0 device migrates from reset to an error - * state, re-issue the warm reset. - */ - if (hub_port_status(hub, port1, - &portstatus, &portchange) < 0) - goto done; - - if (!hub_port_warm_reset_required(hub, portstatus)) - goto done; - - /* - * If the port is in SS.Inactive or Compliance Mode, the - * hot or warm reset failed. Try another warm reset. - */ - if (!warm) { - dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", - port1); - warm = true; - } + hub_port_finish_reset(hub, port1, udev, &status, warm); + goto done; } dev_dbg (hub->intfdev, @@ -2647,7 +2709,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, port1); done: - if (!hub_is_superspeed(hub->hdev)) + if (!warm) up_read(&ehci_cf_port_reset_rwsem); return status; @@ -2883,7 +2945,9 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) /* see 7.1.7.6 */ if (hub_is_superspeed(hub->hdev)) - status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3); + status = set_port_feature(hub->hdev, + port1 | (USB_SS_PORT_LS_U3 << 3), + USB_PORT_FEAT_LINK_STATE); else status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND); @@ -3059,7 +3123,9 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) /* see 7.1.7.7; affects power usage, but not budgeting */ if (hub_is_superspeed(hub->hdev)) - status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0); + status = set_port_feature(hub->hdev, + port1 | (USB_SS_PORT_LS_U0 << 3), + USB_PORT_FEAT_LINK_STATE); else status = clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND); @@ -4146,23 +4212,16 @@ hub_power_remaining (struct usb_hub *hub) for (port1 = 1; port1 <= hdev->maxchild; ++port1) { struct usb_device *udev = hub->ports[port1 - 1]->child; int delta; - unsigned unit_load; if (!udev) continue; - if (hub_is_superspeed(udev)) - unit_load = 150; - else - unit_load = 100; - /* - * Unconfigured devices may not use more than one unit load, - * or 8mA for OTG ports - */ + /* Unconfigured devices may not use more than 100mA, + * or 8mA for OTG ports */ if (udev->actconfig) - delta = usb_get_max_power(udev, udev->actconfig); + delta = udev->actconfig->desc.bMaxPower * 2; else if (port1 != udev->bus->otg_port || hdev->parent) - delta = unit_load; + delta = 100; else delta = 8; if (delta > hub->mA_per_port) @@ -4197,7 +4256,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, le16_to_cpu(hub->descriptor->wHubCharacteristics); struct usb_device *udev; int status, i; - unsigned unit_load; dev_dbg (hub_dev, "port %d, status %04x, change %04x, %s\n", @@ -4287,10 +4345,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, goto done; return; } - if (hub_is_superspeed(hub->hdev)) - unit_load = 150; - else - unit_load = 100; for (i = 0; i < SET_CONFIG_TRIES; i++) { @@ -4338,7 +4392,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, * on the parent. */ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB - && udev->bus_mA <= unit_load) { + && udev->bus_mA <= 100) { u16 devstat; status = usb_get_status(udev, USB_RECIP_DEVICE, 0, @@ -4652,21 +4706,12 @@ static void hub_events(void) */ if (hub_port_warm_reset_required(hub, portstatus)) { int status; - struct usb_device *udev = - hub->ports[i - 1]->child; dev_dbg(hub_dev, "warm reset port %d\n", i); - if (!udev) { - status = hub_port_reset(hub, i, - NULL, HUB_BH_RESET_TIME, - true); - if (status < 0) - hub_port_disable(hub, i, 1); - } else { - usb_lock_device(udev); - status = usb_reset_device(udev); - usb_unlock_device(udev); - } + status = hub_port_reset(hub, i, NULL, + HUB_BH_RESET_TIME, true); + if (status < 0) + hub_port_disable(hub, i, 1); connect_change = 0; } @@ -5221,47 +5266,6 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) return hub->ports[port1 - 1]->connect_type; } -void usb_hub_adjust_deviceremovable(struct usb_device *hdev, - struct usb_hub_descriptor *desc) -{ - enum usb_port_connect_type connect_type; - int i; - - if (!hub_is_superspeed(hdev)) { - for (i = 1; i <= hdev->maxchild; i++) { - connect_type = usb_get_hub_port_connect_type(hdev, i); - - if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { - u8 mask = 1 << (i%8); - - if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) { - dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", - i); - desc->u.hs.DeviceRemovable[i/8] |= mask; - } - } - } - } else { - u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable); - - for (i = 1; i <= hdev->maxchild; i++) { - connect_type = usb_get_hub_port_connect_type(hdev, i); - - if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { - u16 mask = 1 << i; - - if (!(port_removable & mask)) { - dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", - i); - port_removable |= mask; - } - } - } - - desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); - } -} - #ifdef CONFIG_ACPI /** * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle diff --git a/trunk/drivers/usb/core/hub.h b/trunk/drivers/usb/core/hub.h deleted file mode 100644 index c472058f8f27..000000000000 --- a/trunk/drivers/usb/core/hub.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * usb hub driver head file - * - * Copyright (C) 1999 Linus Torvalds - * Copyright (C) 1999 Johannes Erdfelt - * Copyright (C) 1999 Gregory P. Smith - * Copyright (C) 2001 Brad Hards (bhards@bigpond.net.au) - * Copyright (C) 2012 Intel Corp (tianyu.lan@intel.com) - * - * move struct usb_hub to this file. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include -#include -#include -#include "usb.h" - -struct usb_hub { - struct device *intfdev; /* the "interface" device */ - struct usb_device *hdev; - struct kref kref; - struct urb *urb; /* for interrupt polling pipe */ - - /* buffer for urb ... with extra space in case of babble */ - u8 (*buffer)[8]; - union { - struct usb_hub_status hub; - struct usb_port_status port; - } *status; /* buffer for status reports */ - struct mutex status_mutex; /* for the status buffer */ - - int error; /* last reported error */ - int nerrors; /* track consecutive errors */ - - struct list_head event_list; /* hubs w/data or errs ready */ - unsigned long event_bits[1]; /* status change bitmask */ - unsigned long change_bits[1]; /* ports with logical connect - status change */ - unsigned long busy_bits[1]; /* ports being reset or - resumed */ - unsigned long removed_bits[1]; /* ports with a "removed" - device present */ - unsigned long wakeup_bits[1]; /* ports that have signaled - remote wakeup */ -#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ -#error event_bits[] is too short! -#endif - - struct usb_hub_descriptor *descriptor; /* class descriptor */ - struct usb_tt tt; /* Transaction Translator */ - - unsigned mA_per_port; /* current for each child */ - - unsigned limited_power:1; - unsigned quiescing:1; - unsigned disconnected:1; - - unsigned quirk_check_port_auto_suspend:1; - - unsigned has_indicators:1; - u8 indicator[USB_MAXCHILDREN]; - struct delayed_work leds; - struct delayed_work init_work; - struct usb_port **ports; -}; - -/** - * struct usb port - kernel's representation of a usb port - * @child: usb device attatched to the port - * @dev: generic device interface - * @port_owner: port's owner - * @connect_type: port's connect type - */ -struct usb_port { - struct usb_device *child; - struct device dev; - struct dev_state *port_owner; - enum usb_port_connect_type connect_type; -}; - -#define to_usb_port(_dev) \ - container_of(_dev, struct usb_port, dev) - -extern int usb_hub_create_port_device(struct usb_hub *hub, - int port1); -extern void usb_hub_remove_port_device(struct usb_hub *hub, - int port1); - diff --git a/trunk/drivers/usb/core/message.c b/trunk/drivers/usb/core/message.c index 444d30e3a78b..131f73649b60 100644 --- a/trunk/drivers/usb/core/message.c +++ b/trunk/drivers/usb/core/message.c @@ -1751,7 +1751,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) } } - i = dev->bus_mA - usb_get_max_power(dev, cp); + i = dev->bus_mA - cp->desc.bMaxPower * 2; if (i < 0) dev_warn(&dev->dev, "new config #%d exceeds power " "limit by %dmA\n", diff --git a/trunk/drivers/usb/core/port.c b/trunk/drivers/usb/core/port.c deleted file mode 100644 index fe5959fc021b..000000000000 --- a/trunk/drivers/usb/core/port.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * usb port device code - * - * Copyright (C) 2012 Intel Corp - * - * Author: Lan Tianyu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - */ - -#include - -#include "hub.h" - -static const struct attribute_group *port_dev_group[]; - -static ssize_t show_port_connect_type(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_port *port_dev = to_usb_port(dev); - char *result; - - switch (port_dev->connect_type) { - case USB_PORT_CONNECT_TYPE_HOT_PLUG: - result = "hotplug"; - break; - case USB_PORT_CONNECT_TYPE_HARD_WIRED: - result = "hardwired"; - break; - case USB_PORT_NOT_USED: - result = "not used"; - break; - default: - result = "unknown"; - break; - } - - return sprintf(buf, "%s\n", result); -} -static DEVICE_ATTR(connect_type, S_IRUGO, show_port_connect_type, - NULL); - -static struct attribute *port_dev_attrs[] = { - &dev_attr_connect_type.attr, - NULL, -}; - -static struct attribute_group port_dev_attr_grp = { - .attrs = port_dev_attrs, -}; - -static const struct attribute_group *port_dev_group[] = { - &port_dev_attr_grp, - NULL, -}; - -static void usb_port_device_release(struct device *dev) -{ - struct usb_port *port_dev = to_usb_port(dev); - - kfree(port_dev); -} - -struct device_type usb_port_device_type = { - .name = "usb_port", - .release = usb_port_device_release, -}; - -int usb_hub_create_port_device(struct usb_hub *hub, int port1) -{ - struct usb_port *port_dev = NULL; - int retval; - - port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); - if (!port_dev) { - retval = -ENOMEM; - goto exit; - } - - hub->ports[port1 - 1] = port_dev; - port_dev->dev.parent = hub->intfdev; - port_dev->dev.groups = port_dev_group; - port_dev->dev.type = &usb_port_device_type; - dev_set_name(&port_dev->dev, "port%d", port1); - - retval = device_register(&port_dev->dev); - if (retval) - goto error_register; - - return 0; - -error_register: - put_device(&port_dev->dev); -exit: - return retval; -} - -void usb_hub_remove_port_device(struct usb_hub *hub, - int port1) -{ - device_unregister(&hub->ports[port1 - 1]->dev); -} - diff --git a/trunk/drivers/usb/core/sysfs.c b/trunk/drivers/usb/core/sysfs.c index 3f81a3dc6867..818e4a024d0d 100644 --- a/trunk/drivers/usb/core/sysfs.c +++ b/trunk/drivers/usb/core/sysfs.c @@ -17,7 +17,7 @@ #include "usb.h" /* Active configuration fields */ -#define usb_actconfig_show(field, format_string) \ +#define usb_actconfig_show(field, multiplier, format_string) \ static ssize_t show_##field(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ @@ -28,31 +28,18 @@ static ssize_t show_##field(struct device *dev, \ actconfig = udev->actconfig; \ if (actconfig) \ return sprintf(buf, format_string, \ - actconfig->desc.field); \ + actconfig->desc.field * multiplier); \ else \ return 0; \ } \ -#define usb_actconfig_attr(field, format_string) \ - usb_actconfig_show(field, format_string) \ - static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); - -usb_actconfig_attr(bNumInterfaces, "%2d\n") -usb_actconfig_attr(bmAttributes, "%2x\n") - -static ssize_t show_bMaxPower(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_device *udev; - struct usb_host_config *actconfig; +#define usb_actconfig_attr(field, multiplier, format_string) \ +usb_actconfig_show(field, multiplier, format_string) \ +static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); - udev = to_usb_device(dev); - actconfig = udev->actconfig; - if (!actconfig) - return 0; - return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig)); -} -static DEVICE_ATTR(bMaxPower, S_IRUGO, show_bMaxPower, NULL); +usb_actconfig_attr(bNumInterfaces, 1, "%2d\n") +usb_actconfig_attr(bmAttributes, 1, "%2x\n") +usb_actconfig_attr(bMaxPower, 2, "%3dmA\n") static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf) @@ -69,7 +56,7 @@ static ssize_t show_configuration_string(struct device *dev, static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); /* configuration value is always present, and r/w */ -usb_actconfig_show(bConfigurationValue, "%u\n"); +usb_actconfig_show(bConfigurationValue, 1, "%u\n"); static ssize_t set_bConfigurationValue(struct device *dev, struct device_attribute *attr, diff --git a/trunk/drivers/usb/core/usb.h b/trunk/drivers/usb/core/usb.h index a7f20bde0e5e..1c528c1bf0be 100644 --- a/trunk/drivers/usb/core/usb.h +++ b/trunk/drivers/usb/core/usb.h @@ -1,7 +1,6 @@ #include #include -struct usb_hub_descriptor; struct dev_state; /* Functions local to drivers/usb/core/ */ @@ -39,15 +38,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_choose_configuration(struct usb_device *udev); -static inline unsigned usb_get_max_power(struct usb_device *udev, - struct usb_host_config *c) -{ - /* SuperSpeed power is in 8 mA units; others are in 2 mA units */ - unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2); - - return c->desc.bMaxPower * mul; -} - extern void usb_kick_khubd(struct usb_device *dev); extern int usb_match_one_id_intf(struct usb_device *dev, struct usb_host_interface *intf, @@ -183,8 +173,6 @@ extern enum usb_port_connect_type usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, enum usb_port_connect_type type); -extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev, - struct usb_hub_descriptor *desc); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); diff --git a/trunk/drivers/usb/dwc3/core.h b/trunk/drivers/usb/dwc3/core.h index 499956344262..5f79d9f51000 100644 --- a/trunk/drivers/usb/dwc3/core.h +++ b/trunk/drivers/usb/dwc3/core.h @@ -55,7 +55,9 @@ #define DWC3_ENDPOINTS_NUM 32 #define DWC3_XHCI_RESOURCES_NUM 2 -#define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE +#define DWC3_EVENT_SIZE 4 /* bytes */ +#define DWC3_EVENT_MAX_NUM 64 /* 2 events/endpoint */ +#define DWC3_EVENT_BUFFERS_SIZE (DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM) #define DWC3_EVENT_TYPE_MASK 0xfe #define DWC3_EVENT_TYPE_DEV 0 diff --git a/trunk/drivers/usb/host/ehci-mxc.c b/trunk/drivers/usb/host/ehci-mxc.c index 6b8c1584065f..ec7f5d2c90de 100644 --- a/trunk/drivers/usb/host/ehci-mxc.c +++ b/trunk/drivers/usb/host/ehci-mxc.c @@ -94,6 +94,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) struct usb_hcd *hcd; struct resource *res; int irq, ret; + unsigned int flags; struct ehci_mxc_priv *priv; struct device *dev = &pdev->dev; struct ehci_hcd *ehci; @@ -204,6 +205,25 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (ret) goto err_add; + if (pdata->otg) { + /* + * efikamx and efikasb have some hardware bug which is + * preventing usb to work unless CHRGVBUS is set. + * It's in violation of USB specs + */ + if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) { + flags = usb_phy_io_read(pdata->otg, + ULPI_OTG_CTRL); + flags |= ULPI_OTG_CTRL_CHRGVBUS; + ret = usb_phy_io_write(pdata->otg, flags, + ULPI_OTG_CTRL); + if (ret) { + dev_err(dev, "unable to set CHRVBUS\n"); + goto err_add; + } + } + } + return 0; err_add: diff --git a/trunk/drivers/usb/host/ehci-s5p.c b/trunk/drivers/usb/host/ehci-s5p.c index f18e6ac081aa..319dcfaa8735 100644 --- a/trunk/drivers/usb/host/ehci-s5p.c +++ b/trunk/drivers/usb/host/ehci-s5p.c @@ -266,7 +266,7 @@ static const struct dev_pm_ops s5p_ehci_pm_ops = { #ifdef CONFIG_OF static const struct of_device_id exynos_ehci_match[] = { - { .compatible = "samsung,exynos4210-ehci" }, + { .compatible = "samsung,exynos-ehci" }, {}, }; MODULE_DEVICE_TABLE(of, exynos_ehci_match); diff --git a/trunk/drivers/usb/host/ohci-exynos.c b/trunk/drivers/usb/host/ohci-exynos.c index 77f2017c33c4..aa3b8844bb9f 100644 --- a/trunk/drivers/usb/host/ohci-exynos.c +++ b/trunk/drivers/usb/host/ohci-exynos.c @@ -267,7 +267,7 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = { #ifdef CONFIG_OF static const struct of_device_id exynos_ohci_match[] = { - { .compatible = "samsung,exynos4210-ohci" }, + { .compatible = "samsung,exynos-ohci" }, {}, }; MODULE_DEVICE_TABLE(of, exynos_ohci_match); diff --git a/trunk/drivers/usb/host/ohci-q.c b/trunk/drivers/usb/host/ohci-q.c index 88731b7c5f42..7482cfbe8c5e 100644 --- a/trunk/drivers/usb/host/ohci-q.c +++ b/trunk/drivers/usb/host/ohci-q.c @@ -44,7 +44,6 @@ __acquires(ohci->lock) // ASSERT (urb->hcpriv != 0); urb_free_priv (ohci, urb->hcpriv); - urb->hcpriv = NULL; if (likely(status == -EINPROGRESS)) status = 0; diff --git a/trunk/drivers/usb/host/uhci-debug.c b/trunk/drivers/usb/host/uhci-debug.c index 455737546525..fc0b0daac93d 100644 --- a/trunk/drivers/usb/host/uhci-debug.c +++ b/trunk/drivers/usb/host/uhci-debug.c @@ -16,8 +16,6 @@ #include "uhci-hcd.h" -#define EXTRA_SPACE 1024 - static struct dentry *uhci_debugfs_root; #ifdef DEBUG @@ -46,6 +44,10 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, char *spid; u32 status, token; + /* Try to make sure there's enough memory */ + if (len < 160) + return 0; + status = td_status(uhci, td); out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, hc32_to_cpu(uhci, td->link)); @@ -62,8 +64,6 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", status & 0x7ff); - if (out - buf > len) - goto done; token = td_token(uhci, td); switch (uhci_packetid(token)) { @@ -90,9 +90,6 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, spid); out += sprintf(out, "(buf=%08x)\n", hc32_to_cpu(uhci, td->buffer)); -done: - if (out - buf > len) - out += sprintf(out, " ...\n"); return out - buf; } @@ -104,6 +101,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, int i, nactive, ninactive; char *ptype; + if (len < 200) + return 0; out += sprintf(out, "urb_priv [%p] ", urbp); out += sprintf(out, "urb [%p] ", urbp->urb); @@ -111,8 +110,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); - if (out - buf > len) - goto done; switch (usb_pipetype(urbp->urb->pipe)) { case PIPE_ISOCHRONOUS: ptype = "ISO"; break; @@ -131,9 +128,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); out += sprintf(out, "\n"); - if (out - buf > len) - goto done; - i = nactive = ninactive = 0; list_for_each_entry(td, &urbp->td_list, list) { if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC && @@ -141,8 +135,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, "%*s%d: ", space + 2, "", i); out += uhci_show_td(uhci, td, out, len - (out - buf), 0); - if (out - buf > len) - goto tail; } else { if (td_status(uhci, td) & TD_CTRL_ACTIVE) ++nactive; @@ -151,13 +143,10 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, } } if (nactive + ninactive > 0) - out += sprintf(out, - "%*s[skipped %d inactive and %d active TDs]\n", + out += sprintf(out, "%*s[skipped %d inactive and %d active " + "TDs]\n", space, "", ninactive, nactive); -done: - if (out - buf > len) - out += sprintf(out, " ...\n"); -tail: + return out - buf; } @@ -169,6 +158,10 @@ static int uhci_show_qh(struct uhci_hcd *uhci, __hc32 element = qh_element(qh); char *qtype; + /* Try to make sure there's enough memory */ + if (len < 80 * 7) + return 0; + switch (qh->type) { case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break; case USB_ENDPOINT_XFER_INT: qtype = "INT"; break; @@ -182,15 +175,13 @@ static int uhci_show_qh(struct uhci_hcd *uhci, hc32_to_cpu(uhci, qh->link), hc32_to_cpu(uhci, element)); if (qh->type == USB_ENDPOINT_XFER_ISOC) - out += sprintf(out, - "%*s period %d phase %d load %d us, frame %x desc [%p]\n", + out += sprintf(out, "%*s period %d phase %d load %d us, " + "frame %x desc [%p]\n", space, "", qh->period, qh->phase, qh->load, qh->iso_frame, qh->iso_packet_desc); else if (qh->type == USB_ENDPOINT_XFER_INT) out += sprintf(out, "%*s period %d phase %d load %d us\n", space, "", qh->period, qh->phase, qh->load); - if (out - buf > len) - goto done; if (element & UHCI_PTR_QH(uhci)) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); @@ -204,17 +195,11 @@ static int uhci_show_qh(struct uhci_hcd *uhci, if (!(element & ~(UHCI_PTR_QH(uhci) | UHCI_PTR_DEPTH(uhci)))) out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); - if (out - buf > len) - goto done; - if (list_empty(&qh->queue)) { out += sprintf(out, "%*s queue is empty\n", space, ""); - if (qh == uhci->skel_async_qh) { + if (qh == uhci->skel_async_qh) out += uhci_show_td(uhci, uhci->term_td, out, len - (out - buf), 0); - if (out - buf > len) - goto tail; - } } else { struct urb_priv *urbp = list_entry(qh->queue.next, struct urb_priv, node); @@ -226,12 +211,9 @@ static int uhci_show_qh(struct uhci_hcd *uhci, space, ""); i = nurbs = 0; list_for_each_entry(urbp, &qh->queue, node) { - if (++i <= 10) { + if (++i <= 10) out += uhci_show_urbp(uhci, urbp, out, len - (out - buf), space + 2); - if (out - buf > len) - goto tail; - } else ++nurbs; } @@ -240,27 +222,24 @@ static int uhci_show_qh(struct uhci_hcd *uhci, space, "", nurbs); } - if (out - buf > len) - goto done; - if (qh->dummy_td) { out += sprintf(out, "%*s Dummy TD\n", space, ""); out += uhci_show_td(uhci, qh->dummy_td, out, len - (out - buf), 0); - if (out - buf > len) - goto tail; } -done: - if (out - buf > len) - out += sprintf(out, " ...\n"); -tail: return out - buf; } -static int uhci_show_sc(int port, unsigned short status, char *buf) +static int uhci_show_sc(int port, unsigned short status, char *buf, int len) { - return sprintf(buf, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", + char *out = buf; + + /* Try to make sure there's enough memory */ + if (len < 160) + return 0; + + out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", port, status, (status & USBPORTSC_SUSP) ? " Suspend" : "", @@ -273,12 +252,19 @@ static int uhci_show_sc(int port, unsigned short status, char *buf) (status & USBPORTSC_PE) ? " Enabled" : "", (status & USBPORTSC_CSC) ? " ConnectChange" : "", (status & USBPORTSC_CCS) ? " Connected" : ""); + + return out - buf; } -static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf) +static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) { + char *out = buf; char *rh_state; + /* Try to make sure there's enough memory */ + if (len < 60) + return 0; + switch (uhci->rh_state) { case UHCI_RH_RESET: rh_state = "reset"; break; @@ -297,8 +283,9 @@ static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf) default: rh_state = "?"; break; } - return sprintf(buf, "Root-hub state: %s FSBR: %d\n", + out += sprintf(out, "Root-hub state: %s FSBR: %d\n", rh_state, uhci->fsbr_is_on); + return out - buf; } static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) @@ -309,6 +296,9 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) unsigned char sof; unsigned short portsc1, portsc2; + /* Try to make sure there's enough memory */ + if (len < 80 * 9) + return 0; usbcmd = uhci_readw(uhci, 0); usbstat = uhci_readw(uhci, 2); @@ -329,8 +319,6 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) (usbcmd & USBCMD_GRESET) ? "GRESET " : "", (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", (usbcmd & USBCMD_RS) ? "RS " : ""); - if (out - buf > len) - goto done; out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n", usbstat, @@ -340,33 +328,19 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) (usbstat & USBSTS_RD) ? "ResumeDetect " : "", (usbstat & USBSTS_ERROR) ? "USBError " : "", (usbstat & USBSTS_USBINT) ? "USBINT " : ""); - if (out - buf > len) - goto done; out += sprintf(out, " usbint = %04x\n", usbint); out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, 0xfff & (4*(unsigned int)usbfrnum)); out += sprintf(out, " flbaseadd = %08x\n", flbaseadd); out += sprintf(out, " sof = %02x\n", sof); - if (out - buf > len) - goto done; - - out += uhci_show_sc(1, portsc1, out); - if (out - buf > len) - goto done; - - out += uhci_show_sc(2, portsc2, out); - if (out - buf > len) - goto done; - - out += sprintf(out, - "Most recent frame: %x (%d) Last ISO frame: %x (%d)\n", + out += uhci_show_sc(1, portsc1, out, len - (out - buf)); + out += uhci_show_sc(2, portsc2, out, len - (out - buf)); + out += sprintf(out, "Most recent frame: %x (%d) " + "Last ISO frame: %x (%d)\n", uhci->frame_number, uhci->frame_number & 1023, uhci->last_iso_frame, uhci->last_iso_frame & 1023); -done: - if (out - buf > len) - out += sprintf(out, " ...\n"); return out - buf; } @@ -386,13 +360,9 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) "int8", "int4", "int2", "async", "term" }; - out += uhci_show_root_hub_state(uhci, out); - if (out - buf > len) - goto done; + out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); out += sprintf(out, "HC status\n"); out += uhci_show_status(uhci, out, len - (out - buf)); - if (out - buf > len) - goto tail; out += sprintf(out, "Periodic load table\n"); for (i = 0; i < MAX_PHASE; ++i) { @@ -405,7 +375,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) uhci_to_hcd(uhci)->self.bandwidth_int_reqs, uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs); if (debug <= 1) - goto tail; + return out - buf; out += sprintf(out, "Frame List\n"); nframes = 10; @@ -413,8 +383,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) for (i = 0; i < UHCI_NUMFRAMES; ++i) { __hc32 qh_dma; - if (out - buf > len) - goto done; j = 0; td = uhci->frame_cpu[i]; link = uhci->frame[i]; @@ -433,20 +401,15 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) td = list_entry(tmp, struct uhci_td, fl_list); tmp = tmp->next; if (link != LINK_TO_TD(uhci, td)) { - if (nframes > 0) { - out += sprintf(out, - " link does not match list entry!\n"); - if (out - buf > len) - goto done; - } else + if (nframes > 0) + out += sprintf(out, " link does " + "not match list entry!\n"); + else ++nerrs; } - if (nframes > 0) { + if (nframes > 0) out += uhci_show_td(uhci, td, out, len - (out - buf), 4); - if (out - buf > len) - goto tail; - } link = td->link; } while (tmp != head); @@ -460,11 +423,9 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) i, hc32_to_cpu(uhci, link)); j = 1; } - out += sprintf(out, - " link does not match QH (%08x)!\n", + out += sprintf(out, " link does not match " + "QH (%08x)!\n", hc32_to_cpu(uhci, qh_dma)); - if (out - buf > len) - goto done; } else ++nerrs; } @@ -475,27 +436,18 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) out += sprintf(out, "Skeleton QHs\n"); - if (out - buf > len) - goto done; - fsbr_link = 0; for (i = 0; i < UHCI_NUM_SKELQH; ++i) { int cnt = 0; qh = uhci->skelqh[i]; - out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); + out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \ out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); - if (out - buf > len) - goto tail; /* Last QH is the Terminating QH, it's different */ if (i == SKEL_TERM) { - if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td)) { - out += sprintf(out, - " skel_term_qh element is not set to term_td!\n"); - if (out - buf > len) - goto done; - } + if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td)) + out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); link = fsbr_link; if (!link) link = LINK_TO_QH(uhci, uhci->skel_term_qh); @@ -508,12 +460,9 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) while (tmp != head) { qh = list_entry(tmp, struct uhci_qh, node); tmp = tmp->next; - if (++cnt <= 10) { + if (++cnt <= 10) out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); - if (out - buf > len) - goto tail; - } if (!fsbr_link && qh->skel >= SKEL_FSBR) fsbr_link = LINK_TO_QH(uhci, qh); } @@ -531,17 +480,9 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) link = LINK_TO_QH(uhci, uhci->skel_term_qh); check_qh_link: if (qh->link != link) - out += sprintf(out, - " last QH not linked to next skeleton!\n"); - - if (out - buf > len) - goto done; + out += sprintf(out, " last QH not linked to next skeleton!\n"); } -done: - if (out - buf > len) - out += sprintf(out, " ...\n"); -tail: return out - buf; } @@ -573,8 +514,7 @@ static int uhci_debug_open(struct inode *inode, struct file *file) up->size = 0; spin_lock_irqsave(&uhci->lock, flags); if (uhci->is_initialized) - up->size = uhci_sprint_schedule(uhci, up->data, - MAX_OUTPUT - EXTRA_SPACE); + up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); spin_unlock_irqrestore(&uhci->lock, flags); file->private_data = up; @@ -589,9 +529,7 @@ static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) up = file->private_data; - /* - * XXX: atomic 64bit seek access, but that needs to be fixed in the VFS - */ + /* XXX: atomic 64bit seek access, but that needs to be fixed in the VFS */ switch (whence) { case 0: new = off; diff --git a/trunk/drivers/usb/host/uhci-hcd.c b/trunk/drivers/usb/host/uhci-hcd.c index 01628e39cc8b..4b9e9aba2665 100644 --- a/trunk/drivers/usb/host/uhci-hcd.c +++ b/trunk/drivers/usb/host/uhci-hcd.c @@ -449,20 +449,21 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { if (status & USBSTS_HSE) - dev_err(uhci_dev(uhci), - "host system error, PCI problems?\n"); + dev_err(uhci_dev(uhci), "host system error, " + "PCI problems?\n"); if (status & USBSTS_HCPE) - dev_err(uhci_dev(uhci), - "host controller process error, something bad happened!\n"); + dev_err(uhci_dev(uhci), "host controller process " + "error, something bad happened!\n"); if (status & USBSTS_HCH) { spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), - "host controller halted, very bad!\n"); + "host controller halted, " + "very bad!\n"); if (debug > 1 && errbuf) { /* Print the schedule for debugging */ - uhci_sprint_schedule(uhci, errbuf, - ERRBUF_LEN - EXTRA_SPACE); + uhci_sprint_schedule(uhci, + errbuf, ERRBUF_LEN); lprintk(errbuf); } uhci_hc_died(uhci); @@ -588,8 +589,8 @@ static int uhci_start(struct usb_hcd *hcd) UHCI_NUMFRAMES * sizeof(*uhci->frame), &uhci->frame_dma_handle, 0); if (!uhci->frame) { - dev_err(uhci_dev(uhci), - "unable to allocate consistent memory for frame list\n"); + dev_err(uhci_dev(uhci), "unable to allocate " + "consistent memory for frame list\n"); goto err_alloc_frame; } memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame)); @@ -597,8 +598,8 @@ static int uhci_start(struct usb_hcd *hcd) uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu), GFP_KERNEL); if (!uhci->frame_cpu) { - dev_err(uhci_dev(uhci), - "unable to allocate memory for frame pointers\n"); + dev_err(uhci_dev(uhci), "unable to allocate " + "memory for frame pointers\n"); goto err_alloc_frame_cpu; } @@ -733,8 +734,8 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) */ else if (hcd->self.root_hub->do_remote_wakeup && uhci->resuming_ports) { - dev_dbg(uhci_dev(uhci), - "suspend failed because a port is resuming\n"); + dev_dbg(uhci_dev(uhci), "suspend failed because a port " + "is resuming\n"); rc = -EBUSY; } else suspend_rh(uhci, UHCI_RH_SUSPENDED); @@ -825,8 +826,8 @@ static int uhci_count_ports(struct usb_hcd *hcd) /* Anything greater than 7 is weird so we'll ignore it. */ if (port > UHCI_RH_MAXCHILD) { - dev_info(uhci_dev(uhci), - "port count misdetected? forcing to 2 ports\n"); + dev_info(uhci_dev(uhci), "port count misdetected? " + "forcing to 2 ports\n"); port = 2; } diff --git a/trunk/drivers/usb/host/uhci-hcd.h b/trunk/drivers/usb/host/uhci-hcd.h index 6f986d82472d..7af2b7052047 100644 --- a/trunk/drivers/usb/host/uhci-hcd.h +++ b/trunk/drivers/usb/host/uhci-hcd.h @@ -212,6 +212,10 @@ struct uhci_qh { #define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ #define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | \ + TD_CTRL_BITSTUFF) + #define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) #define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000) #define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & \ diff --git a/trunk/drivers/usb/host/uhci-hub.c b/trunk/drivers/usb/host/uhci-hub.c index 533b864f2e67..768d54295a20 100644 --- a/trunk/drivers/usb/host/uhci-hub.c +++ b/trunk/drivers/usb/host/uhci-hub.c @@ -21,8 +21,8 @@ static const __u8 root_hub_hub_des[] = 0x00, /* (per-port OC, no power switching) */ 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0x00, /* __u8 DeviceRemovable; *** 7 Ports max */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ }; #define UHCI_RH_MAXCHILD 7 diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index f0976d8190bc..15921fd55048 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -1200,7 +1200,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) if (debug > 1 && errbuf) { /* Print the chain for debugging */ uhci_show_qh(uhci, urbp->qh, errbuf, - ERRBUF_LEN - EXTRA_SPACE, 0); + ERRBUF_LEN, 0); lprintk(errbuf); } } diff --git a/trunk/drivers/usb/host/xhci-ring.c b/trunk/drivers/usb/host/xhci-ring.c index f69720983fc7..59fb5c677dbe 100644 --- a/trunk/drivers/usb/host/xhci-ring.c +++ b/trunk/drivers/usb/host/xhci-ring.c @@ -2706,11 +2706,13 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); u32 status; + union xhci_trb *trb; u64 temp_64; union xhci_trb *event_ring_deq; dma_addr_t deq; spin_lock(&xhci->lock); + trb = xhci->event_ring->dequeue; /* Check if the xHC generated the interrupt, or the irq is shared */ status = xhci_readl(xhci, &xhci->op_regs->status); if (status == 0xffffffff) diff --git a/trunk/drivers/usb/misc/Kconfig b/trunk/drivers/usb/misc/Kconfig index 3b1a3f4ec5e9..fecde69bfa7d 100644 --- a/trunk/drivers/usb/misc/Kconfig +++ b/trunk/drivers/usb/misc/Kconfig @@ -250,9 +250,3 @@ config USB_EZUSB_FX2 help Say Y here if you need EZUSB device support. (Cypress FX/FX2/FX2LP microcontrollers) - -config USB_HSIC_USB3503 - tristate "USB3503 HSIC to USB20 Driver" - depends on I2C - help - This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver. diff --git a/trunk/drivers/usb/misc/Makefile b/trunk/drivers/usb/misc/Makefile index 3e1bd70b06ea..3e99a643294b 100644 --- a/trunk/drivers/usb/misc/Makefile +++ b/trunk/drivers/usb/misc/Makefile @@ -26,6 +26,5 @@ obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o obj-$(CONFIG_USB_YUREX) += yurex.o -obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/trunk/drivers/usb/misc/usb3503.c b/trunk/drivers/usb/misc/usb3503.c deleted file mode 100644 index 471218aea7b3..000000000000 --- a/trunk/drivers/usb/misc/usb3503.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Driver for SMSC USB3503 USB 2.0 hub controller driver - * - * Copyright (c) 2012-2013 Dongjin Kim (tobetter@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define USB3503_VIDL 0x00 -#define USB3503_VIDM 0x01 -#define USB3503_PIDL 0x02 -#define USB3503_PIDM 0x03 -#define USB3503_DIDL 0x04 -#define USB3503_DIDM 0x05 - -#define USB3503_CFG1 0x06 -#define USB3503_SELF_BUS_PWR (1 << 7) - -#define USB3503_CFG2 0x07 -#define USB3503_CFG3 0x08 -#define USB3503_NRD 0x09 - -#define USB3503_PDS 0x0a -#define USB3503_PORT1 (1 << 1) -#define USB3503_PORT2 (1 << 2) -#define USB3503_PORT3 (1 << 3) - -#define USB3503_SP_ILOCK 0xe7 -#define USB3503_SPILOCK_CONNECT (1 << 1) -#define USB3503_SPILOCK_CONFIG (1 << 0) - -#define USB3503_CFGP 0xee -#define USB3503_CLKSUSP (1 << 7) - -struct usb3503 { - enum usb3503_mode mode; - struct i2c_client *client; - int gpio_intn; - int gpio_reset; - int gpio_connect; -}; - -static int usb3503_write_register(struct i2c_client *client, - char reg, char data) -{ - return i2c_smbus_write_byte_data(client, reg, data); -} - -static int usb3503_read_register(struct i2c_client *client, char reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int usb3503_set_bits(struct i2c_client *client, char reg, char req) -{ - int err; - - err = usb3503_read_register(client, reg); - if (err < 0) - return err; - - err = usb3503_write_register(client, reg, err | req); - if (err < 0) - return err; - - return 0; -} - -static int usb3503_clear_bits(struct i2c_client *client, char reg, char req) -{ - int err; - - err = usb3503_read_register(client, reg); - if (err < 0) - return err; - - err = usb3503_write_register(client, reg, err & ~req); - if (err < 0) - return err; - - return 0; -} - -static int usb3503_reset(int gpio_reset, int state) -{ - if (gpio_is_valid(gpio_reset)) - gpio_set_value(gpio_reset, state); - - /* Wait RefClk when RESET_N is released, otherwise Hub will - * not transition to Hub Communication Stage. - */ - if (state) - msleep(100); - - return 0; -} - -static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) -{ - struct i2c_client *i2c = hub->client; - int err = 0; - - switch (mode) { - case USB3503_MODE_HUB: - usb3503_reset(hub->gpio_reset, 1); - - /* SP_ILOCK: set connect_n, config_n for config */ - err = usb3503_write_register(i2c, USB3503_SP_ILOCK, - (USB3503_SPILOCK_CONNECT - | USB3503_SPILOCK_CONFIG)); - if (err < 0) { - dev_err(&i2c->dev, "SP_ILOCK failed (%d)\n", err); - goto err_hubmode; - } - - /* PDS : Port2,3 Disable For Self Powered Operation */ - err = usb3503_set_bits(i2c, USB3503_PDS, - (USB3503_PORT2 | USB3503_PORT3)); - if (err < 0) { - dev_err(&i2c->dev, "PDS failed (%d)\n", err); - goto err_hubmode; - } - - /* CFG1 : SELF_BUS_PWR -> Self-Powerd operation */ - err = usb3503_set_bits(i2c, USB3503_CFG1, USB3503_SELF_BUS_PWR); - if (err < 0) { - dev_err(&i2c->dev, "CFG1 failed (%d)\n", err); - goto err_hubmode; - } - - /* SP_LOCK: clear connect_n, config_n for hub connect */ - err = usb3503_clear_bits(i2c, USB3503_SP_ILOCK, - (USB3503_SPILOCK_CONNECT - | USB3503_SPILOCK_CONFIG)); - if (err < 0) { - dev_err(&i2c->dev, "SP_ILOCK failed (%d)\n", err); - goto err_hubmode; - } - - hub->mode = mode; - dev_info(&i2c->dev, "switched to HUB mode\n"); - break; - - case USB3503_MODE_STANDBY: - usb3503_reset(hub->gpio_reset, 0); - - hub->mode = mode; - dev_info(&i2c->dev, "switched to STANDBY mode\n"); - break; - - default: - dev_err(&i2c->dev, "unknown mode is request\n"); - err = -EINVAL; - break; - } - -err_hubmode: - return err; -} - -static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) -{ - struct usb3503_platform_data *pdata = i2c->dev.platform_data; - struct device_node *np = i2c->dev.of_node; - struct usb3503 *hub; - int err = -ENOMEM; - u32 mode; - - hub = kzalloc(sizeof(struct usb3503), GFP_KERNEL); - if (!hub) { - dev_err(&i2c->dev, "private data alloc fail\n"); - return err; - } - - i2c_set_clientdata(i2c, hub); - hub->client = i2c; - - if (pdata) { - hub->gpio_intn = pdata->gpio_intn; - hub->gpio_connect = pdata->gpio_connect; - hub->gpio_reset = pdata->gpio_reset; - hub->mode = pdata->initial_mode; - } else if (np) { - hub->gpio_intn = of_get_named_gpio(np, "connect-gpios", 0); - if (hub->gpio_intn == -EPROBE_DEFER) - return -EPROBE_DEFER; - hub->gpio_connect = of_get_named_gpio(np, "intn-gpios", 0); - if (hub->gpio_connect == -EPROBE_DEFER) - return -EPROBE_DEFER; - hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0); - if (hub->gpio_reset == -EPROBE_DEFER) - return -EPROBE_DEFER; - of_property_read_u32(np, "initial-mode", &mode); - hub->mode = mode; - } - - if (gpio_is_valid(hub->gpio_intn)) { - err = gpio_request_one(hub->gpio_intn, - GPIOF_OUT_INIT_HIGH, "usb3503 intn"); - if (err) { - dev_err(&i2c->dev, - "unable to request GPIO %d as connect pin (%d)\n", - hub->gpio_intn, err); - goto err_out; - } - } - - if (gpio_is_valid(hub->gpio_connect)) { - err = gpio_request_one(hub->gpio_connect, - GPIOF_OUT_INIT_HIGH, "usb3503 connect"); - if (err) { - dev_err(&i2c->dev, - "unable to request GPIO %d as connect pin (%d)\n", - hub->gpio_connect, err); - goto err_gpio_connect; - } - } - - if (gpio_is_valid(hub->gpio_reset)) { - err = gpio_request_one(hub->gpio_reset, - GPIOF_OUT_INIT_LOW, "usb3503 reset"); - if (err) { - dev_err(&i2c->dev, - "unable to request GPIO %d as reset pin (%d)\n", - hub->gpio_reset, err); - goto err_gpio_reset; - } - } - - usb3503_switch_mode(hub, hub->mode); - - dev_info(&i2c->dev, "%s: probed on %s mode\n", __func__, - (hub->mode == USB3503_MODE_HUB) ? "hub" : "standby"); - - return 0; - -err_gpio_reset: - if (gpio_is_valid(hub->gpio_connect)) - gpio_free(hub->gpio_connect); -err_gpio_connect: - if (gpio_is_valid(hub->gpio_intn)) - gpio_free(hub->gpio_intn); -err_out: - kfree(hub); - - return err; -} - -static int usb3503_remove(struct i2c_client *i2c) -{ - struct usb3503 *hub = i2c_get_clientdata(i2c); - - if (gpio_is_valid(hub->gpio_intn)) - gpio_free(hub->gpio_intn); - if (gpio_is_valid(hub->gpio_connect)) - gpio_free(hub->gpio_connect); - if (gpio_is_valid(hub->gpio_reset)) - gpio_free(hub->gpio_reset); - - kfree(hub); - - return 0; -} - -static const struct i2c_device_id usb3503_id[] = { - { USB3503_I2C_NAME, 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, usb3503_id); - -#ifdef CONFIG_OF -static const struct of_device_id usb3503_of_match[] = { - { .compatible = "smsc,usb3503", }, - {}, -}; -MODULE_DEVICE_TABLE(of, usb3503_of_match); -#endif - -static struct i2c_driver usb3503_driver = { - .driver = { - .name = USB3503_I2C_NAME, - .of_match_table = of_match_ptr(usb3503_of_match), - }, - .probe = usb3503_probe, - .remove = usb3503_remove, - .id_table = usb3503_id, -}; - -static int __init usb3503_init(void) -{ - return i2c_add_driver(&usb3503_driver); -} - -static void __exit usb3503_exit(void) -{ - i2c_del_driver(&usb3503_driver); -} - -module_init(usb3503_init); -module_exit(usb3503_exit); - -MODULE_AUTHOR("Dongjin Kim "); -MODULE_DESCRIPTION("USB3503 USB HUB driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/musb/am35x.c b/trunk/drivers/usb/musb/am35x.c index 59eea219034a..c107d7cdfa69 100644 --- a/trunk/drivers/usb/musb/am35x.c +++ b/trunk/drivers/usb/musb/am35x.c @@ -365,7 +365,7 @@ static int am35x_musb_init(struct musb *musb) usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) - return -EPROBE_DEFER; + return -ENODEV; setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); diff --git a/trunk/drivers/usb/musb/blackfin.c b/trunk/drivers/usb/musb/blackfin.c index dbb31b30c7fa..14dab9f9b3d0 100644 --- a/trunk/drivers/usb/musb/blackfin.c +++ b/trunk/drivers/usb/musb/blackfin.c @@ -406,7 +406,7 @@ static int bfin_musb_init(struct musb *musb) musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { gpio_free(musb->config->gpio_vrsel); - return -EPROBE_DEFER; + return -ENODEV; } bfin_musb_reg_init(musb); diff --git a/trunk/drivers/usb/musb/da8xx.c b/trunk/drivers/usb/musb/da8xx.c index 7c71769d71ff..97996af2646e 100644 --- a/trunk/drivers/usb/musb/da8xx.c +++ b/trunk/drivers/usb/musb/da8xx.c @@ -410,7 +410,6 @@ static int da8xx_musb_init(struct musb *musb) { void __iomem *reg_base = musb->ctrl_base; u32 rev; - int ret = -ENODEV; musb->mregs += DA8XX_MENTOR_CORE_OFFSET; @@ -421,10 +420,8 @@ static int da8xx_musb_init(struct musb *musb) usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(musb->xceiv)) { - ret = -EPROBE_DEFER; + if (IS_ERR_OR_NULL(musb->xceiv)) goto fail; - } setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); @@ -444,7 +441,7 @@ static int da8xx_musb_init(struct musb *musb) musb->isr = da8xx_musb_interrupt; return 0; fail: - return ret; + return -ENODEV; } static int da8xx_musb_exit(struct musb *musb) diff --git a/trunk/drivers/usb/musb/davinci.c b/trunk/drivers/usb/musb/davinci.c index e040d9103735..b1c01cad28b2 100644 --- a/trunk/drivers/usb/musb/davinci.c +++ b/trunk/drivers/usb/musb/davinci.c @@ -380,14 +380,11 @@ static int davinci_musb_init(struct musb *musb) { void __iomem *tibase = musb->ctrl_base; u32 revision; - int ret = -ENODEV; usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(musb->xceiv)) { - ret = -EPROBE_DEFER; + if (IS_ERR_OR_NULL(musb->xceiv)) goto unregister; - } musb->mregs += DAVINCI_BASE_OFFSET; @@ -441,7 +438,7 @@ static int davinci_musb_init(struct musb *musb) usb_put_phy(musb->xceiv); unregister: usb_nop_xceiv_unregister(); - return ret; + return -ENODEV; } static int davinci_musb_exit(struct musb *musb) diff --git a/trunk/drivers/usb/musb/musb_core.c b/trunk/drivers/usb/musb/musb_core.c index 60b41cc28da4..fd3486745e64 100644 --- a/trunk/drivers/usb/musb/musb_core.c +++ b/trunk/drivers/usb/musb/musb_core.c @@ -1993,7 +1993,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_platform_exit(musb); fail1: - pm_runtime_disable(musb->controller); dev_err(musb->controller, "musb_init_controller failed with status %d\n", status); diff --git a/trunk/drivers/usb/musb/musb_dsps.c b/trunk/drivers/usb/musb/musb_dsps.c index 7f5c215e560c..f7d764de6fda 100644 --- a/trunk/drivers/usb/musb/musb_dsps.c +++ b/trunk/drivers/usb/musb/musb_dsps.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -418,7 +419,7 @@ static int dsps_musb_init(struct musb *musb) usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) - return -EPROBE_DEFER; + return -ENODEV; /* Returns zero if e.g. not clocked */ rev = dsps_readl(reg_base, wrp->revision); diff --git a/trunk/drivers/usb/musb/musb_gadget.c b/trunk/drivers/usb/musb/musb_gadget.c index be18537c5f14..876787438c2f 100644 --- a/trunk/drivers/usb/musb/musb_gadget.c +++ b/trunk/drivers/usb/musb/musb_gadget.c @@ -408,19 +408,7 @@ static void txstate(struct musb *musb, struct musb_request *req) csr |= (MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); - /* - * Enable Autoset according to table - * below - * bulk_split hb_mult Autoset_Enable - * 0 0 Yes(Normal) - * 0 >0 No(High BW ISO) - * 1 0 Yes(HS bulk) - * 1 >0 Yes(FS bulk) - */ - if (!musb_ep->hb_mult || - (musb_ep->hb_mult && - can_bulk_split(musb, - musb_ep->type))) + if (!musb_ep->hb_mult) csr |= MUSB_TXCSR_AUTOSET; } csr &= ~MUSB_TXCSR_P_UNDERRUN; @@ -1122,15 +1110,11 @@ static int musb_gadget_enable(struct usb_ep *ep, /* Set TXMAXP with the FIFO size of the endpoint * to disable double buffering mode. */ - if (musb->double_buffer_not_ok) { + if (musb->double_buffer_not_ok) musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); - } else { - if (can_bulk_split(musb, musb_ep->type)) - musb_ep->hb_mult = (hw_ep->max_packet_sz_tx / - musb_ep->packet_sz) - 1; + else musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); - } csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; if (musb_readw(regs, MUSB_TXCSR) diff --git a/trunk/drivers/usb/musb/musb_host.c b/trunk/drivers/usb/musb/musb_host.c index 1ce1fcf3f3e7..e9f0fd9ddd2d 100644 --- a/trunk/drivers/usb/musb/musb_host.c +++ b/trunk/drivers/usb/musb/musb_host.c @@ -634,17 +634,7 @@ static bool musb_tx_dma_program(struct dma_controller *dma, mode = 1; csr |= MUSB_TXCSR_DMAMODE | MUSB_TXCSR_DMAENAB; /* autoset shouldn't be set in high bandwidth */ - /* - * Enable Autoset according to table - * below - * bulk_split hb_mult Autoset_Enable - * 0 1 Yes(Normal) - * 0 >1 No(High BW ISO) - * 1 1 Yes(HS bulk) - * 1 >1 Yes(FS bulk) - */ - if (qh->hb_mult == 1 || (qh->hb_mult > 1 && - can_bulk_split(hw_ep->musb, qh->type))) + if (qh->hb_mult == 1) csr |= MUSB_TXCSR_AUTOSET; } else { mode = 0; @@ -756,13 +746,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, /* general endpoint setup */ if (epnum) { /* flush all old state, set default */ - /* - * We could be flushing valid - * packets in double buffering - * case - */ - if (!hw_ep->tx_double_buffered) - musb_h_tx_flush_fifo(hw_ep); + musb_h_tx_flush_fifo(hw_ep); /* * We must not clear the DMAMODE bit before or in @@ -779,13 +763,11 @@ static void musb_ep_program(struct musb *musb, u8 epnum, ); csr |= MUSB_TXCSR_MODE; - if (!hw_ep->tx_double_buffered) { - if (usb_gettoggle(urb->dev, qh->epnum, 1)) - csr |= MUSB_TXCSR_H_WR_DATATOGGLE - | MUSB_TXCSR_H_DATATOGGLE; - else - csr |= MUSB_TXCSR_CLRDATATOG; - } + if (usb_gettoggle(urb->dev, qh->epnum, 1)) + csr |= MUSB_TXCSR_H_WR_DATATOGGLE + | MUSB_TXCSR_H_DATATOGGLE; + else + csr |= MUSB_TXCSR_CLRDATATOG; musb_writew(epio, MUSB_TXCSR, csr); /* REVISIT may need to clear FLUSHFIFO ... */ @@ -809,19 +791,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, /* protocol/endpoint/interval/NAKlimit */ if (epnum) { musb_writeb(epio, MUSB_TXTYPE, qh->type_reg); - if (musb->double_buffer_not_ok) { + if (musb->double_buffer_not_ok) musb_writew(epio, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); - } else if (can_bulk_split(musb, qh->type)) { - qh->hb_mult = hw_ep->max_packet_sz_tx - / packet_sz; + else if (can_bulk_split(musb, qh->type)) musb_writew(epio, MUSB_TXMAXP, packet_sz - | ((qh->hb_mult) - 1) << 11); - } else { + | ((hw_ep->max_packet_sz_tx / + packet_sz) - 1) << 11); + else musb_writew(epio, MUSB_TXMAXP, qh->maxpacket | ((qh->hb_mult - 1) << 11)); - } musb_writeb(epio, MUSB_TXINTERVAL, qh->intv_reg); } else { musb_writeb(epio, MUSB_NAKLIMIT0, qh->intv_reg); diff --git a/trunk/drivers/usb/musb/omap2430.c b/trunk/drivers/usb/musb/omap2430.c index bb48796e5213..da00af460794 100644 --- a/trunk/drivers/usb/musb/omap2430.c +++ b/trunk/drivers/usb/musb/omap2430.c @@ -255,11 +255,11 @@ static inline void omap2430_low_level_init(struct musb *musb) void omap_musb_mailbox(enum omap_musb_vbus_id_status status) { struct omap2430_glue *glue = _glue; + struct musb *musb = glue_to_musb(glue); - if (glue && glue_to_musb(glue)) { - glue->status = status; - } else { - pr_err("%s: musb core is not yet ready\n", __func__); + glue->status = status; + if (!musb) { + dev_err(glue->dev, "musb core is not yet ready\n"); return; } @@ -369,7 +369,7 @@ static int omap2430_musb_init(struct musb *musb) musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { pr_err("HS USB OTG: no transceiver configured\n"); - return -EPROBE_DEFER; + return -ENODEV; } musb->isr = omap2430_musb_interrupt; @@ -532,18 +532,20 @@ static int omap2430_probe(struct platform_device *pdev) if (!pdata) { dev_err(&pdev->dev, "failed to allocate musb platfrom data\n"); + ret = -ENOMEM; goto err2; } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) { dev_err(&pdev->dev, - "failed to allocate musb board data\n"); + "failed to allocate musb board data\n"); + ret = -ENOMEM; goto err2; } config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); - if (!config) { + if (!data) { dev_err(&pdev->dev, "failed to allocate musb hdrc config\n"); goto err2; diff --git a/trunk/drivers/usb/musb/tusb6010.c b/trunk/drivers/usb/musb/tusb6010.c index 464bd23cccda..3969813c217d 100644 --- a/trunk/drivers/usb/musb/tusb6010.c +++ b/trunk/drivers/usb/musb/tusb6010.c @@ -1069,7 +1069,7 @@ static int tusb_musb_init(struct musb *musb) usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) - return -EPROBE_DEFER; + return -ENODEV; pdev = to_platform_device(musb->controller); diff --git a/trunk/drivers/usb/musb/ux500.c b/trunk/drivers/usb/musb/ux500.c index 13a392913769..a27ca1a9c994 100644 --- a/trunk/drivers/usb/musb/ux500.c +++ b/trunk/drivers/usb/musb/ux500.c @@ -61,7 +61,7 @@ static int ux500_musb_init(struct musb *musb) musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { pr_err("HS USB OTG: no transceiver configured\n"); - return -EPROBE_DEFER; + return -ENODEV; } musb->isr = ux500_musb_interrupt; @@ -108,7 +108,7 @@ static int ux500_probe(struct platform_device *pdev) goto err3; } - ret = clk_prepare_enable(clk); + ret = clk_enable(clk); if (ret) { dev_err(&pdev->dev, "failed to enable clock\n"); goto err4; @@ -148,7 +148,7 @@ static int ux500_probe(struct platform_device *pdev) return 0; err5: - clk_disable_unprepare(clk); + clk_disable(clk); err4: clk_put(clk); @@ -168,7 +168,7 @@ static int ux500_remove(struct platform_device *pdev) struct ux500_glue *glue = platform_get_drvdata(pdev); platform_device_unregister(glue->musb); - clk_disable_unprepare(glue->clk); + clk_disable(glue->clk); clk_put(glue->clk); kfree(glue); @@ -182,7 +182,7 @@ static int ux500_suspend(struct device *dev) struct musb *musb = glue_to_musb(glue); usb_phy_set_suspend(musb->xceiv, 1); - clk_disable_unprepare(glue->clk); + clk_disable(glue->clk); return 0; } @@ -193,7 +193,7 @@ static int ux500_resume(struct device *dev) struct musb *musb = glue_to_musb(glue); int ret; - ret = clk_prepare_enable(glue->clk); + ret = clk_enable(glue->clk); if (ret) { dev_err(dev, "failed to enable clock\n"); return ret; diff --git a/trunk/drivers/usb/serial/io_ti.c b/trunk/drivers/usb/serial/io_ti.c index 641ab3da2d83..58184f3de686 100644 --- a/trunk/drivers/usb/serial/io_ti.c +++ b/trunk/drivers/usb/serial/io_ti.c @@ -521,6 +521,62 @@ static int tx_active(struct edgeport_port *port) return bytes_left; } +static void chase_port(struct edgeport_port *port, unsigned long timeout, + int flush) +{ + int baud_rate; + struct tty_struct *tty = tty_port_tty_get(&port->port->port); + struct usb_serial *serial = port->port->serial; + wait_queue_t wait; + unsigned long flags; + + if (!timeout) + timeout = (HZ * EDGE_CLOSING_WAIT)/100; + + /* wait for data to drain from the buffer */ + spin_lock_irqsave(&port->ep_lock, flags); + init_waitqueue_entry(&wait, current); + add_wait_queue(&tty->write_wait, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (kfifo_len(&port->write_fifo) == 0 + || timeout == 0 || signal_pending(current) + || serial->disconnected) + /* disconnect */ + break; + spin_unlock_irqrestore(&port->ep_lock, flags); + timeout = schedule_timeout(timeout); + spin_lock_irqsave(&port->ep_lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&tty->write_wait, &wait); + if (flush) + kfifo_reset_out(&port->write_fifo); + spin_unlock_irqrestore(&port->ep_lock, flags); + tty_kref_put(tty); + + /* wait for data to drain from the device */ + timeout += jiffies; + while ((long)(jiffies - timeout) < 0 && !signal_pending(current) + && !serial->disconnected) { + /* not disconnected */ + if (!tx_active(port)) + break; + msleep(10); + } + + /* disconnected */ + if (serial->disconnected) + return; + + /* wait one more character time, based on baud rate */ + /* (tx_active doesn't seem to wait for the last byte) */ + baud_rate = port->baud_rate; + if (baud_rate == 0) + baud_rate = 50; + msleep(max(1, DIV_ROUND_UP(10000, baud_rate))); +} + static int choose_config(struct usb_device *dev) { /* @@ -1885,8 +1941,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ++edge_serial->num_ports_open; - port->port.drain_delay = 1; - goto release_es_lock; unlink_int_urb: @@ -1902,7 +1956,6 @@ static void edge_close(struct usb_serial_port *port) struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; struct usb_serial *serial = port->serial; - unsigned long flags; int port_number; edge_serial = usb_get_serial_data(port->serial); @@ -1914,12 +1967,12 @@ static void edge_close(struct usb_serial_port *port) * this flag and dump add read data */ edge_port->close_pending = 1; + /* chase the port close and flush */ + chase_port(edge_port, (HZ * closing_wait) / 100, 1); + usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); edge_port->ep_write_urb_in_use = 0; - spin_lock_irqsave(&edge_port->ep_lock, flags); - kfifo_reset_out(&edge_port->write_fifo); - spin_unlock_irqrestore(&edge_port->ep_lock, flags); /* assuming we can still talk to the device, * send a close port command to it */ @@ -2045,21 +2098,16 @@ static int edge_chars_in_buffer(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; - int ret; if (edge_port == NULL) return 0; + if (edge_port->close_pending == 1) + return 0; spin_lock_irqsave(&edge_port->ep_lock, flags); chars = kfifo_len(&edge_port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - if (!chars) { - ret = tx_active(edge_port); - if (ret > 0) - chars = ret; - } - dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -2397,15 +2445,10 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { struct serial_struct tmp; - unsigned cwait; if (!retinfo) return -EFAULT; - cwait = edge_port->port->port.closing_wait; - if (cwait != ASYNC_CLOSING_WAIT_NONE) - cwait = jiffies_to_msecs(closing_wait) / 10; - memset(&tmp, 0, sizeof(tmp)); tmp.type = PORT_16550A; @@ -2416,7 +2459,7 @@ static int get_serial_info(struct edgeport_port *edge_port, tmp.xmit_fifo_size = edge_port->port->bulk_out_size; tmp.baud_base = 9600; tmp.close_delay = 5*HZ; - tmp.closing_wait = cwait; + tmp.closing_wait = closing_wait; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -2471,7 +2514,8 @@ static void edge_break(struct tty_struct *tty, int break_state) int status; int bv = 0; /* Off */ - tty_wait_until_sent(tty, 0); + /* chase the port close */ + chase_port(edge_port, 0, 0); if (break_state == -1) bv = 1; /* On */ @@ -2544,8 +2588,6 @@ static int edge_port_probe(struct usb_serial_port *port) return ret; } - port->port.closing_wait = msecs_to_jiffies(closing_wait * 10); - return 0; } diff --git a/trunk/drivers/usb/serial/keyspan.c b/trunk/drivers/usb/serial/keyspan.c index 3d95637f3d68..97bc49f68efd 100644 --- a/trunk/drivers/usb/serial/keyspan.c +++ b/trunk/drivers/usb/serial/keyspan.c @@ -298,7 +298,7 @@ static void usa26_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", + dev_dbg(&urb->dev->dev,"%s - nonzero status: %x on endpoint %d.\n", __func__, status, endpoint); return; } @@ -532,7 +532,7 @@ static void usa28_instat_callback(struct urb *urb) /* dev_dbg(&urb->dev->dev, - "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__, + "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]); */ diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index 4d21789e1ba4..478adcfcdf26 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -470,7 +470,6 @@ static const struct option_blacklist_info four_g_w14_blacklist = { static const struct option_blacklist_info alcatel_x200_blacklist = { .sendsetup = BIT(0) | BIT(1), - .reserved = BIT(4), }; static const struct option_blacklist_info zte_0037_blacklist = { @@ -1199,14 +1198,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, - { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D), - .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, - { USB_DEVICE(ALCATEL_VENDOR_ID, 0x0052), - .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, - { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b6), - .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, - { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b7), - .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, diff --git a/trunk/drivers/usb/serial/usb-serial.c b/trunk/drivers/usb/serial/usb-serial.c index 0a17f5942552..64bda135ba7e 100644 --- a/trunk/drivers/usb/serial/usb-serial.c +++ b/trunk/drivers/usb/serial/usb-serial.c @@ -361,21 +361,15 @@ static int serial_write_room(struct tty_struct *tty) static int serial_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - struct usb_serial *serial = port->serial; - int count = 0; dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); - mutex_lock(&serial->disc_mutex); /* if the device was unplugged then any remaining characters fell out of the connector ;) */ - if (serial->disconnected) - count = 0; - else - count = serial->type->chars_in_buffer(tty); - mutex_unlock(&serial->disc_mutex); - - return count; + if (port->serial->disconnected) + return 0; + /* pass on to the driver specific version of this function */ + return port->serial->type->chars_in_buffer(tty); } static void serial_throttle(struct tty_struct *tty) diff --git a/trunk/drivers/usb/storage/uas.c b/trunk/drivers/usb/storage/uas.c index ebb99728551c..98b98eef7527 100644 --- a/trunk/drivers/usb/storage/uas.c +++ b/trunk/drivers/usb/storage/uas.c @@ -66,8 +66,6 @@ enum { DATA_OUT_URB_INFLIGHT = (1 << 10), COMMAND_COMPLETED = (1 << 11), COMMAND_ABORTED = (1 << 12), - UNLINK_DATA_URBS = (1 << 13), - IS_IN_WORK_LIST = (1 << 14), }; /* Overrides scsi_pointer */ @@ -84,36 +82,11 @@ struct uas_cmd_info { static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_dev_info *devinfo, gfp_t gfp); static void uas_do_work(struct work_struct *work); -static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller); static DECLARE_WORK(uas_work, uas_do_work); static DEFINE_SPINLOCK(uas_work_lock); static LIST_HEAD(uas_work_list); -static void uas_unlink_data_urbs(struct uas_dev_info *devinfo, - struct uas_cmd_info *cmdinfo) -{ - unsigned long flags; - - /* - * The UNLINK_DATA_URBS flag makes sure uas_try_complete - * (called by urb completion) doesn't release cmdinfo - * underneath us. - */ - spin_lock_irqsave(&devinfo->lock, flags); - cmdinfo->state |= UNLINK_DATA_URBS; - spin_unlock_irqrestore(&devinfo->lock, flags); - - if (cmdinfo->data_in_urb) - usb_unlink_urb(cmdinfo->data_in_urb); - if (cmdinfo->data_out_urb) - usb_unlink_urb(cmdinfo->data_out_urb); - - spin_lock_irqsave(&devinfo->lock, flags); - cmdinfo->state &= ~UNLINK_DATA_URBS; - spin_unlock_irqrestore(&devinfo->lock, flags); -} - static void uas_do_work(struct work_struct *work) { struct uas_cmd_info *cmdinfo; @@ -133,8 +106,6 @@ static void uas_do_work(struct work_struct *work) struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; spin_lock_irqsave(&devinfo->lock, flags); err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); - if (!err) - cmdinfo->state &= ~IS_IN_WORK_LIST; spin_unlock_irqrestore(&devinfo->lock, flags); if (err) { list_del(&cmdinfo->list); @@ -146,45 +117,6 @@ static void uas_do_work(struct work_struct *work) } } -static void uas_abort_work(struct uas_dev_info *devinfo) -{ - struct uas_cmd_info *cmdinfo; - struct uas_cmd_info *temp; - struct list_head list; - unsigned long flags; - - spin_lock_irq(&uas_work_lock); - list_replace_init(&uas_work_list, &list); - spin_unlock_irq(&uas_work_lock); - - spin_lock_irqsave(&devinfo->lock, flags); - list_for_each_entry_safe(cmdinfo, temp, &list, list) { - struct scsi_pointer *scp = (void *)cmdinfo; - struct scsi_cmnd *cmnd = container_of(scp, - struct scsi_cmnd, SCp); - struct uas_dev_info *di = (void *)cmnd->device->hostdata; - - if (di == devinfo) { - cmdinfo->state |= COMMAND_ABORTED; - cmdinfo->state &= ~IS_IN_WORK_LIST; - if (devinfo->resetting) { - /* uas_stat_cmplt() will not do that - * when a device reset is in - * progress */ - cmdinfo->state &= ~COMMAND_INFLIGHT; - } - uas_try_complete(cmnd, __func__); - } else { - /* not our uas device, relink into list */ - list_del(&cmdinfo->list); - spin_lock_irq(&uas_work_lock); - list_add_tail(&cmdinfo->list, &uas_work_list); - spin_unlock_irq(&uas_work_lock); - } - } - spin_unlock_irqrestore(&devinfo->lock, flags); -} - static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer; @@ -236,7 +168,7 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) struct uas_cmd_info *ci = (void *)&cmnd->SCp; scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:" - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + "%s%s%s%s%s%s%s%s%s%s%s%s\n", caller, cmnd, cmnd->request->tag, (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "", (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "", @@ -249,9 +181,7 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) (ci->state & DATA_IN_URB_INFLIGHT) ? " IN" : "", (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT" : "", (ci->state & COMMAND_COMPLETED) ? " done" : "", - (ci->state & COMMAND_ABORTED) ? " abort" : "", - (ci->state & UNLINK_DATA_URBS) ? " unlink": "", - (ci->state & IS_IN_WORK_LIST) ? " work" : ""); + (ci->state & COMMAND_ABORTED) ? " abort" : ""); } static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) @@ -262,8 +192,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) WARN_ON(!spin_is_locked(&devinfo->lock)); if (cmdinfo->state & (COMMAND_INFLIGHT | DATA_IN_URB_INFLIGHT | - DATA_OUT_URB_INFLIGHT | - UNLINK_DATA_URBS)) + DATA_OUT_URB_INFLIGHT)) return -EBUSY; BUG_ON(cmdinfo->state & COMMAND_COMPLETED); cmdinfo->state |= COMMAND_COMPLETED; @@ -288,7 +217,6 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, if (err) { spin_lock(&uas_work_lock); list_add_tail(&cmdinfo->list, &uas_work_list); - cmdinfo->state |= IS_IN_WORK_LIST; spin_unlock(&uas_work_lock); schedule_work(&uas_work); } @@ -346,9 +274,16 @@ static void uas_stat_cmplt(struct urb *urb) uas_sense(urb, cmnd); if (cmnd->result != 0) { /* cancel data transfers on error */ - spin_unlock_irqrestore(&devinfo->lock, flags); - uas_unlink_data_urbs(devinfo, cmdinfo); - spin_lock_irqsave(&devinfo->lock, flags); + if (cmdinfo->state & DATA_IN_URB_INFLIGHT) { + spin_unlock_irqrestore(&devinfo->lock, flags); + usb_unlink_urb(cmdinfo->data_in_urb); + spin_lock_irqsave(&devinfo->lock, flags); + } + if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) { + spin_unlock_irqrestore(&devinfo->lock, flags); + usb_unlink_urb(cmdinfo->data_out_urb); + spin_lock_irqsave(&devinfo->lock, flags); + } } cmdinfo->state &= ~COMMAND_INFLIGHT; uas_try_complete(cmnd, __func__); @@ -644,12 +579,6 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); - if (devinfo->resetting) { - cmnd->result = DID_ERROR << 16; - cmnd->scsi_done(cmnd); - return 0; - } - spin_lock_irqsave(&devinfo->lock, flags); if (devinfo->cmnd) { spin_unlock_irqrestore(&devinfo->lock, flags); @@ -694,7 +623,6 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, } spin_lock(&uas_work_lock); list_add_tail(&cmdinfo->list, &uas_work_list); - cmdinfo->state |= IS_IN_WORK_LIST; spin_unlock(&uas_work_lock); schedule_work(&uas_work); } @@ -761,23 +689,8 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) uas_log_cmd_state(cmnd, __func__); spin_lock_irqsave(&devinfo->lock, flags); cmdinfo->state |= COMMAND_ABORTED; - if (cmdinfo->state & IS_IN_WORK_LIST) { - spin_lock(&uas_work_lock); - list_del(&cmdinfo->list); - cmdinfo->state &= ~IS_IN_WORK_LIST; - spin_unlock(&uas_work_lock); - } - if (cmdinfo->state & COMMAND_INFLIGHT) { - spin_unlock_irqrestore(&devinfo->lock, flags); - ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK); - } else { - spin_unlock_irqrestore(&devinfo->lock, flags); - uas_unlink_data_urbs(devinfo, cmdinfo); - spin_lock_irqsave(&devinfo->lock, flags); - uas_try_complete(cmnd, __func__); - spin_unlock_irqrestore(&devinfo->lock, flags); - ret = SUCCESS; - } + spin_unlock_irqrestore(&devinfo->lock, flags); + ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK); return ret; } @@ -796,7 +709,6 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) int err; devinfo->resetting = 1; - uas_abort_work(devinfo); usb_kill_anchored_urbs(&devinfo->cmd_urbs); usb_kill_anchored_urbs(&devinfo->sense_urbs); usb_kill_anchored_urbs(&devinfo->data_urbs); @@ -1042,12 +954,10 @@ static void uas_disconnect(struct usb_interface *intf) struct Scsi_Host *shost = usb_get_intfdata(intf); struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; - devinfo->resetting = 1; - uas_abort_work(devinfo); + scsi_remove_host(shost); usb_kill_anchored_urbs(&devinfo->cmd_urbs); usb_kill_anchored_urbs(&devinfo->sense_urbs); usb_kill_anchored_urbs(&devinfo->data_urbs); - scsi_remove_host(shost); uas_free_streams(devinfo); kfree(devinfo); } diff --git a/trunk/drivers/usb/storage/usb.c b/trunk/drivers/usb/storage/usb.c index 07b3e5406f48..31b3e1a61bbd 100644 --- a/trunk/drivers/usb/storage/usb.c +++ b/trunk/drivers/usb/storage/usb.c @@ -976,9 +976,6 @@ int usb_stor_probe2(struct us_data *us) if (us->fflags & US_FL_SINGLE_LUN) us->max_lun = 0; - if (!(us->fflags & US_FL_SCM_MULT_TARG)) - us_to_host(us)->max_id = 1; - /* Find the endpoints and calculate pipe values */ result = get_pipes(us); if (result) diff --git a/trunk/include/linux/platform_data/usb3503.h b/trunk/include/linux/platform_data/usb3503.h deleted file mode 100644 index 85dcc709f7e9..000000000000 --- a/trunk/include/linux/platform_data/usb3503.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __USB3503_H__ -#define __USB3503_H__ - -#define USB3503_I2C_NAME "usb3503" - -enum usb3503_mode { - USB3503_MODE_UNKNOWN, - USB3503_MODE_HUB, - USB3503_MODE_STANDBY, -}; - -struct usb3503_platform_data { - enum usb3503_mode initial_mode; - int gpio_intn; - int gpio_connect; - int gpio_reset; -}; - -#endif diff --git a/trunk/tools/usb/testusb.c b/trunk/tools/usb/testusb.c index 643cd77fa980..68d0734b2081 100644 --- a/trunk/tools/usb/testusb.c +++ b/trunk/tools/usb/testusb.c @@ -507,8 +507,10 @@ int main (int argc, char **argv) return handle_testdev (entry) != entry; } status = pthread_create (&entry->thread, 0, handle_testdev, entry); - if (status) + if (status) { perror ("pthread_create"); + continue; + } } if (device) { struct testdev dev;