diff options
Diffstat (limited to 'drivers/usb')
155 files changed, 2705 insertions, 5642 deletions
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 1ea932a..608a2ae 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC config USB_CHIPIDEA_HOST bool "ChipIdea host controller" depends on USB=y || USB=USB_CHIPIDEA + depends on USB_EHCI_HCD select USB_EHCI_ROOT_HUB_TT help Say Y here to enable host controller functionality of the diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index ebff9f4..fed97d3 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -20,78 +20,24 @@ */ #include <linux/kernel.h> +#include <linux/io.h> #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/usb/chipidea.h> #define CHIPIDEA_EHCI -#include "../host/ehci-hcd.c" +#include "../host/ehci.h" #include "ci.h" #include "bits.h" #include "host.h" -static int ci_ehci_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int ret; - - hcd->has_tt = 1; - - ret = ehci_setup(hcd); - if (ret) - return ret; - - ehci_port_power(ehci, 0); - - return ret; -} - -static const struct hc_driver ci_ehci_hc_driver = { - .description = "ehci_hcd", - .product_desc = "ChipIdea HDRC EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ci_ehci_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +static const struct ehci_driver_overrides ci_overrides = { + .product_desc = "ChipIdea HDRC EHCI host controller", }; +static struct hc_driver __read_mostly ci_ehci_hc_driver; + static irqreturn_t host_irq(struct ci13xxx *ci) { return usb_hcd_irq(ci->irq, ci->hcd); @@ -157,5 +103,7 @@ int ci_hdrc_host_init(struct ci13xxx *ci) rdrv->name = "host"; ci->roles[CI_ROLE_HOST] = rdrv; + ehci_init_driver(&ci_ehci_hc_driver, &ci_overrides); + return 0; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 981f213..6e49ec6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -817,10 +817,6 @@ static const __u32 acm_tty_speed[] = { 2500000, 3000000, 3500000, 4000000 }; -static const __u8 acm_tty_size[] = { - 5, 6, 7, 8 -}; - static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { @@ -834,7 +830,21 @@ static void acm_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; + switch (termios->c_cflag & CSIZE) { + case CS5: + newline.bDataBits = 5; + break; + case CS6: + newline.bDataBits = 6; + break; + case CS7: + newline.bDataBits = 7; + break; + case CS8: + default: + newline.bDataBits = 8; + break; + } /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); @@ -1233,7 +1243,7 @@ made_compressed_probe: if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, - usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + usb_sndintpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); else usb_fill_bulk_urb(snd->urb, usb_dev, diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index f460de3..cbacea9 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -591,16 +591,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, /* Now look at all of this device's children. */ usb_hub_for_each_child(usbdev, chix, childdev) { - if (childdev) { - usb_lock_device(childdev); - ret = usb_device_dump(buffer, nbytes, skip_bytes, - file_offset, childdev, bus, - level + 1, chix - 1, ++cnt); - usb_unlock_device(childdev); - if (ret == -EFAULT) - return total_written; - total_written += ret; - } + usb_lock_device(childdev); + ret = usb_device_dump(buffer, nbytes, skip_bytes, + file_offset, childdev, bus, + level + 1, chix - 1, ++cnt); + usb_unlock_device(childdev); + if (ret == -EFAULT) + return total_written; + total_written += ret; } return total_written; } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e0356cb..b78fbe2 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1348,6 +1348,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ret = -EFAULT; goto error; } + uurb->buffer += u; } totlen -= u; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ddd820d..6056db7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -367,6 +367,10 @@ static int usb_probe_interface(struct device *dev) intf->condition = USB_INTERFACE_UNBOUND; usb_cancel_queued_reset(intf); + /* If the LPM disable succeeded, balance the ref counts. */ + if (!lpm_disable_error) + usb_unlocked_enable_lpm(udev); + /* Unbound interfaces are always runtime-PM-disabled and -suspended */ if (driver->supports_autosuspend) pm_runtime_disable(dev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 1e741bc..eaa1451 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) status = hcd->driver->bus_resume(hcd); clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); if (status == 0) { - /* TRSMRCY = 10 msec */ - msleep(10); + struct usb_device *udev; + int port1; + spin_lock_irq(&hcd_root_hub_lock); if (!HCD_DEAD(hcd)) { usb_set_device_state(rhdev, rhdev->actconfig @@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) hcd->state = HC_STATE_RUNNING; } spin_unlock_irq(&hcd_root_hub_lock); + + /* + * Check whether any of the enabled ports on the root hub are + * unsuspended. If they are then a TRSMRCY delay is needed + * (this is what the USB-2 spec calls a "global resume"). + * Otherwise we can skip the delay. + */ + usb_hub_for_each_child(rhdev, port1, udev) { + if (udev->state != USB_STATE_NOTATTACHED && + !udev->port_is_suspended) { + usleep_range(10000, 11000); /* TRSMRCY */ + break; + } + } } else { hcd->state = old_state; dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 673ee46..90accde 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -39,6 +39,9 @@ #endif #endif +#define USB_VENDOR_GENESYS_LOGIC 0x05e3 +#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 + struct usb_port { struct usb_device *child; struct device dev; @@ -86,6 +89,8 @@ struct usb_hub { 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; @@ -736,10 +741,9 @@ static void hub_tt_work(struct work_struct *work) struct usb_hub *hub = container_of(work, struct usb_hub, tt.clear_work); unsigned long flags; - int limit = 100; spin_lock_irqsave (&hub->tt.lock, flags); - while (--limit && !list_empty (&hub->tt.clear_list)) { + while (!list_empty(&hub->tt.clear_list)) { struct list_head *next; struct usb_tt_clear *clear; struct usb_device *hdev = hub->hdev; @@ -1210,7 +1214,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); if (hub->tt.hub) - cancel_work_sync(&hub->tt.clear_work); + flush_work(&hub->tt.clear_work); } /* caller has locked the hub device */ @@ -1609,6 +1613,41 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); + /* + * Set default autosuspend delay as 0 to speedup bus suspend, + * based on the below considerations: + * + * - Unlike other drivers, the hub driver does not rely on the + * autosuspend delay to provide enough time to handle a wakeup + * event, and the submitted status URB is just to check future + * change on hub downstream ports, so it is safe to do it. + * + * - The patch might cause one or more auto supend/resume for + * below very rare devices when they are plugged into hub + * first time: + * + * devices having trouble initializing, and disconnect + * themselves from the bus and then reconnect a second + * or so later + * + * devices just for downloading firmware, and disconnects + * themselves after completing it + * + * For these quite rare devices, their drivers may change the + * autosuspend delay of their parent hub in the probe() to one + * appropriate value to avoid the subtle problem if someone + * does care it. + * + * - The patch may cause one or more auto suspend/resume on + * hub during running 'lsusb', but it is probably too + * infrequent to worry about. + * + * - Change autosuspend delay of hub can avoid unnecessary auto + * suspend timer for hub, also may decrease power consumption + * of USB bus. + */ + pm_runtime_set_autosuspend_delay(&hdev->dev, 0); + /* Hubs have proper suspend/resume support. */ usb_enable_autosuspend(hdev); @@ -1667,6 +1706,9 @@ descriptor_error: if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs++; + if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) + hub->quirk_check_port_auto_suspend = 1; + if (hub_configure(hub, endpoint) >= 0) return 0; @@ -2009,7 +2051,7 @@ static void show_string(struct usb_device *udev, char *id, char *string) { if (!string) return; - dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string); + dev_info(&udev->dev, "%s: %s\n", id, string); } static void announce_device(struct usb_device *udev) @@ -2876,6 +2918,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) (PMSG_IS_AUTO(msg) ? "auto-" : ""), udev->do_remote_wakeup); usb_set_device_state(udev, USB_STATE_SUSPENDED); + udev->port_is_suspended = 1; msleep(10); } usb_mark_last_busy(hub->hdev); @@ -3040,6 +3083,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) SuspendCleared: if (status == 0) { + udev->port_is_suspended = 0; if (hub_is_superspeed(hub->hdev)) { if (portchange & USB_PORT_STAT_C_LINK_STATE) clear_port_feature(hub->hdev, port1, @@ -3123,6 +3167,21 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) #endif +static int check_ports_changed(struct usb_hub *hub) +{ + int port1; + + for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) { + u16 portstatus, portchange; + int status; + + status = hub_port_status(hub, port1, &portstatus, &portchange); + if (!status && portchange) + return 1; + } + return 0; +} + static int hub_suspend(struct usb_interface *intf, pm_message_t msg) { struct usb_hub *hub = usb_get_intfdata (intf); @@ -3141,6 +3200,16 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) return -EBUSY; } } + + if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) { + /* check if there are changes pending on hub ports */ + if (check_ports_changed(hub)) { + if (PMSG_IS_AUTO(msg)) + return -EBUSY; + pm_wakeup_event(&hdev->dev, 2000); + } + } + if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) { /* Enable hub to send remote wakeup for all ports. */ for (port1 = 1; port1 <= hdev->maxchild; port1++) { @@ -3241,8 +3310,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) (state == USB3_LPM_U2 && (u2_sel > USB3_LPM_MAX_U2_SEL_PEL || u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) { - dev_dbg(&udev->dev, "Device-initiated %s disabled due " - "to long SEL %llu ms or PEL %llu ms\n", + dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n", usb3_lpm_names[state], u1_sel, u1_pel); return -EINVAL; } @@ -3320,16 +3388,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev, if (enable) { /* - * First, let the device know about the exit latencies - * associated with the link state we're about to enable. - */ - ret = usb_req_set_sel(udev, state); - if (ret < 0) { - dev_warn(&udev->dev, "Set SEL for device-initiated " - "%s failed.\n", usb3_lpm_names[state]); - return -EBUSY; - } - /* * Now send the control transfer to enable device-initiated LPM * for either U1 or U2. */ @@ -3414,7 +3472,28 @@ static int usb_set_lpm_timeout(struct usb_device *udev, static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { - int timeout; + int timeout, ret; + __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; + __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; + + /* If the device says it doesn't have *any* exit latency to come out of + * U1 or U2, it's probably lying. Assume it doesn't implement that link + * state. + */ + if ((state == USB3_LPM_U1 && u1_mel == 0) || + (state == USB3_LPM_U2 && u2_mel == 0)) + return; + + /* + * First, let the device know about the exit latencies + * associated with the link state we're about to enable. + */ + ret = usb_req_set_sel(udev, state); + if (ret < 0) { + dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n", + usb3_lpm_names[state]); + return; + } /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the @@ -4635,6 +4714,11 @@ static int hub_thread(void *__unused) } static const struct usb_device_id hub_id_table[] = { + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_CLASS, + .idVendor = USB_VENDOR_GENESYS_LOGIC, + .bInterfaceClass = USB_CLASS_HUB, + .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND}, { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, .bDeviceClass = USB_CLASS_HUB}, { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 9d912bf..3662287 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -214,9 +214,25 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); * urb->interval is modified to reflect the actual transfer period used * (normally some power of two units). And for isochronous urbs, * urb->start_frame is modified to reflect when the URB's transfers were - * scheduled to start. Not all isochronous transfer scheduling policies - * will work, but most host controller drivers should easily handle ISO - * queues going from now until 10-200 msec into the future. + * scheduled to start. + * + * Not all isochronous transfer scheduling policies will work, but most + * host controller drivers should easily handle ISO queues going from now + * until 10-200 msec into the future. Drivers should try to keep at + * least one or two msec of data in the queue; many controllers require + * that new transfers start at least 1 msec in the future when they are + * added. If the driver is unable to keep up and the queue empties out, + * the behavior for new submissions is governed by the URB_ISO_ASAP flag. + * If the flag is set, or if the queue is idle, then the URB is always + * assigned to the first available (and not yet expired) slot in the + * endpoint's schedule. If the flag is not set and the queue is active + * then the URB is always assigned to the next slot in the schedule + * following the end of the endpoint's previous URB, even if that slot is + * in the past. When a packet is assigned in this way to a slot that has + * already expired, the packet is not transmitted and the corresponding + * usb_iso_packet_descriptor's status field will return -EXDEV. If this + * would happen to all the packets in the URB, submission fails with a + * -EXDEV error code. * * For control endpoints, the synchronous usb_control_msg() call is * often used (in non-interrupt context) instead of this call. diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index cd8fb44..7d3de09 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -370,14 +370,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) { struct usb_device *dev; - struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self); + struct usb_hcd *usb_hcd = bus_to_hcd(bus); unsigned root_hub = 0; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; - if (!usb_get_hcd(bus_to_hcd(bus))) { + if (!usb_get_hcd(usb_hcd)) { kfree(dev); return NULL; } diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index d441fe4..4502648 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -27,19 +27,7 @@ endif ## obj-$(CONFIG_USB_DWC3) += dwc3-omap.o - -## -# REVISIT Samsung Exynos platform needs the clk API which isn't -# defined on all architectures. If we allow dwc3-exynos.c compile -# always we will fail the linking phase on those architectures -# which don't provide clk api implementation and that's unnaceptable. -# -# When Samsung's platform start supporting pm_runtime, this check -# for HAVE_CLK should be removed. -## -ifneq ($(CONFIG_HAVE_CLK),) - obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o -endif +obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o ifneq ($(CONFIG_PCI),) obj-$(CONFIG_USB_DWC3) += dwc3-pci.o diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b415c0c..e71a62a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -66,45 +66,6 @@ MODULE_PARM_DESC(maximum_speed, "Maximum supported speed."); /* -------------------------------------------------------------------------- */ -#define DWC3_DEVS_POSSIBLE 32 - -static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE); - -int dwc3_get_device_id(void) -{ - int id; - -again: - id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE); - if (id < DWC3_DEVS_POSSIBLE) { - int old; - - old = test_and_set_bit(id, dwc3_devs); - if (old) - goto again; - } else { - pr_err("dwc3: no space for new device\n"); - id = -ENOMEM; - } - - return id; -} -EXPORT_SYMBOL_GPL(dwc3_get_device_id); - -void dwc3_put_device_id(int id) -{ - int ret; - - if (id < 0) - return; - - ret = test_bit(id, dwc3_devs); - WARN(!ret, "dwc3: ID %d not in use\n", id); - smp_mb__before_clear_bit(); - clear_bit(id, dwc3_devs); -} -EXPORT_SYMBOL_GPL(dwc3_put_device_id); - void dwc3_set_mode(struct dwc3 *dwc, u32 mode) { u32 reg; @@ -169,7 +130,6 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc, struct dwc3_event_buffer *evt) { dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); - kfree(evt); } /** @@ -185,7 +145,7 @@ dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) { struct dwc3_event_buffer *evt; - evt = kzalloc(sizeof(*evt), GFP_KERNEL); + evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); if (!evt) return ERR_PTR(-ENOMEM); @@ -193,10 +153,8 @@ dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) evt->length = length; evt->buf = dma_alloc_coherent(dwc->dev, length, &evt->dma, GFP_KERNEL); - if (!evt->buf) { - kfree(evt); + if (!evt->buf) return ERR_PTR(-ENOMEM); - } return evt; } @@ -215,8 +173,6 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) if (evt) dwc3_free_one_event_buffer(dwc, evt); } - - kfree(dwc->ev_buffs); } /** @@ -235,7 +191,8 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) num = DWC3_NUM_INT(dwc->hwparams.hwparams1); dwc->num_event_buffers = num; - dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL); + dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, + GFP_KERNEL); if (!dwc->ev_buffs) { dev_err(dwc->dev, "can't allocate event buffers array\n"); return -ENOMEM; @@ -383,24 +340,14 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GCTL, reg); - ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); - if (ret) { - dev_err(dwc->dev, "failed to allocate event buffers\n"); - ret = -ENOMEM; - goto err1; - } - ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); - goto err1; + goto err0; } return 0; -err1: - dwc3_free_event_buffers(dwc); - err0: return ret; } @@ -408,7 +355,9 @@ err0: static void dwc3_core_exit(struct dwc3 *dwc) { dwc3_event_buffers_cleanup(dwc); - dwc3_free_event_buffers(dwc); + + usb_phy_shutdown(dwc->usb2_phy); + usb_phy_shutdown(dwc->usb3_phy); } #define DWC3_ALIGN_MASK (16 - 1) @@ -511,10 +460,17 @@ static int __devinit dwc3_probe(struct platform_device *pdev) pm_runtime_get_sync(dev); pm_runtime_forbid(dev); + ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); + if (ret) { + dev_err(dwc->dev, "failed to allocate event buffers\n"); + ret = -ENOMEM; + goto err0; + } + ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); - return ret; + goto err0; } mode = DWC3_MODE(dwc->hwparams.hwparams0); @@ -586,6 +542,9 @@ err2: err1: dwc3_core_exit(dwc); +err0: + dwc3_free_event_buffers(dwc); + return ret; } diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 243affc..4999563 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -868,7 +868,4 @@ void dwc3_host_exit(struct dwc3 *dwc); int dwc3_gadget_init(struct dwc3 *dwc); void dwc3_gadget_exit(struct dwc3 *dwc); -extern int dwc3_get_device_id(void); -extern void dwc3_put_device_id(int id); - #endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index ca65978..dc35c54 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/usb/otg.h> #include <linux/usb/nop-usb-xceiv.h> +#include <linux/of.h> #include "core.h" @@ -87,14 +88,14 @@ err1: return ret; } +static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32); + static int __devinit dwc3_exynos_probe(struct platform_device *pdev) { - struct dwc3_exynos_data *pdata = pdev->dev.platform_data; struct platform_device *dwc3; struct dwc3_exynos *exynos; struct clk *clk; - int devid; int ret = -ENOMEM; exynos = kzalloc(sizeof(*exynos), GFP_KERNEL); @@ -103,11 +104,15 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev) goto err0; } - platform_set_drvdata(pdev, exynos); + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we move to full device tree support this will vanish off. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &dwc3_exynos_dma_mask; - devid = dwc3_get_device_id(); - if (devid < 0) - goto err1; + platform_set_drvdata(pdev, exynos); ret = dwc3_exynos_register_phys(exynos); if (ret) { @@ -115,10 +120,10 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev) goto err1; } - dwc3 = platform_device_alloc("dwc3", devid); + dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); if (!dwc3) { dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); - goto err2; + goto err1; } clk = clk_get(&pdev->dev, "usbdrd30"); @@ -139,14 +144,6 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev) clk_enable(exynos->clk); - /* PHY initialization */ - if (!pdata) { - dev_dbg(&pdev->dev, "missing platform data\n"); - } else { - if (pdata->phy_init) - pdata->phy_init(pdev, pdata->phy_type); - } - ret = platform_device_add_resources(dwc3, pdev->resource, pdev->num_resources); if (ret) { @@ -163,15 +160,10 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev) return 0; err4: - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, pdata->phy_type); - clk_disable(clk); clk_put(clk); err3: platform_device_put(dwc3); -err2: - dwc3_put_device_id(devid); err1: kfree(exynos); err0: @@ -181,17 +173,11 @@ err0: static int __devexit dwc3_exynos_remove(struct platform_device *pdev) { struct dwc3_exynos *exynos = platform_get_drvdata(pdev); - struct dwc3_exynos_data *pdata = pdev->dev.platform_data; platform_device_unregister(exynos->dwc3); platform_device_unregister(exynos->usb2_phy); platform_device_unregister(exynos->usb3_phy); - dwc3_put_device_id(exynos->dwc3->id); - - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, pdata->phy_type); - clk_disable(exynos->clk); clk_put(exynos->clk); @@ -200,11 +186,20 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id exynos_dwc3_match[] = { + { .compatible = "samsung,exynos-dwc3" }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_dwc3_match); +#endif + static struct platform_driver dwc3_exynos_driver = { .probe = dwc3_exynos_probe, .remove = __devexit_p(dwc3_exynos_remove), .driver = { .name = "exynos-dwc3", + .of_match_table = of_match_ptr(exynos_dwc3_match), }, }; diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index ee57a10..900d435 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -272,7 +272,6 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) struct resource *res; struct device *dev = &pdev->dev; - int devid; int size; int ret = -ENOMEM; int irq; @@ -315,14 +314,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) return ret; } - devid = dwc3_get_device_id(); - if (devid < 0) - return -ENODEV; - - dwc3 = platform_device_alloc("dwc3", devid); + dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); if (!dwc3) { dev_err(dev, "couldn't allocate dwc3 device\n"); - goto err1; + return -ENOMEM; } context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL); @@ -423,10 +418,6 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) err2: platform_device_put(dwc3); - -err1: - dwc3_put_device_id(devid); - return ret; } @@ -437,9 +428,6 @@ static int __devexit dwc3_omap_remove(struct platform_device *pdev) platform_device_unregister(omap->dwc3); platform_device_unregister(omap->usb2_phy); platform_device_unregister(omap->usb3_phy); - - dwc3_put_device_id(omap->dwc3->id); - return 0; } diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 94f550e..1396259 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -119,7 +119,6 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, struct platform_device *dwc3; struct dwc3_pci *glue; int ret = -ENOMEM; - int devid; struct device *dev = &pci->dev; glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); @@ -145,13 +144,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, return ret; } - devid = dwc3_get_device_id(); - if (devid < 0) { - ret = -ENOMEM; - goto err1; - } - - dwc3 = platform_device_alloc("dwc3", devid); + dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); if (!dwc3) { dev_err(dev, "couldn't allocate dwc3 device\n"); ret = -ENOMEM; @@ -172,7 +165,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); if (ret) { dev_err(dev, "couldn't add resources to dwc3 device\n"); - goto err2; + goto err1; } pci_set_drvdata(pci, glue); @@ -195,10 +188,6 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, err3: pci_set_drvdata(pci, NULL); platform_device_put(dwc3); - -err2: - dwc3_put_device_id(devid); - err1: pci_disable_device(pci); @@ -211,7 +200,6 @@ static void __devexit dwc3_pci_remove(struct pci_dev *pci) platform_device_unregister(glue->usb2_phy); platform_device_unregister(glue->usb3_phy); - dwc3_put_device_id(glue->dwc3->id); platform_device_unregister(glue->dwc3); pci_set_drvdata(pci, NULL); pci_disable_device(pci); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c9e729a..7b7dedd 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1904,7 +1904,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); WARN_ON_ONCE(ret); dep->resource_index = 0; - + dep->flags &= ~DWC3_EP_BUSY; udelay(100); } diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index e426ad6..5e29dde 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -20,6 +20,7 @@ #include <linux/usb/ehci_def.h> #include <linux/delay.h> #include <linux/serial_core.h> +#include <linux/kconfig.h> #include <linux/kgdb.h> #include <linux/kthread.h> #include <asm/io.h> @@ -614,12 +615,6 @@ err: return -ENODEV; } -int dbgp_external_startup(struct usb_hcd *hcd) -{ - return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); -} -EXPORT_SYMBOL_GPL(dbgp_external_startup); - static int ehci_reset_port(int port) { u32 portsc; @@ -979,6 +974,7 @@ struct console early_dbgp_console = { .index = -1, }; +#if IS_ENABLED(CONFIG_USB) int dbgp_reset_prep(struct usb_hcd *hcd) { int ret = xen_dbgp_reset_prep(hcd); @@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd) } EXPORT_SYMBOL_GPL(dbgp_reset_prep); +int dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); +} +EXPORT_SYMBOL_GPL(dbgp_external_startup); +#endif /* USB */ + #ifdef CONFIG_KGDB static char kgdbdbgp_buf[DBGP_MAX_PACKET]; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 63b5869..14625fd 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -927,6 +927,7 @@ endif config USB_G_WEBCAM tristate "USB Webcam Gadget" depends on VIDEO_DEV + select USB_LIBCOMPOSITE help The Webcam Gadget acts as a composite USB Audio and Video Class device. It provides a userspace API to process UVC control requests diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index ba18b47..d1cf1f4 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -2930,10 +2930,10 @@ static void vbus_work(struct work_struct *work) /* Get the VBUS status from the transceiver */ value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client, - ISP1301_I2C_OTG_CONTROL_2); + ISP1301_I2C_INTERRUPT_SOURCE); /* VBUS on or off? */ - if (value & OTG_B_SESS_VLD) + if (value & INT_SESS_VLD) udc->vbus = 1; else udc->vbus = 0; diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 43ac748..c009263 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev) #if defined(PLX_PCI_RDK2) /* see if PCI int for us by checking irqstat */ intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT); - if (!intcsr & (1 << NET2272_PCI_IRQ)) + if (!intcsr & (1 << NET2272_PCI_IRQ)) { + spin_unlock(&dev->lock); return IRQ_NONE; + } /* check dma interrupts */ #endif /* Platform/devcice interrupt handler */ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 3f1431d..d6bb128 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -95,6 +95,11 @@ config USB_EHCI_TT_NEWSCHED If unsure, say Y. +config USB_EHCI_PCI + tristate + depends on USB_EHCI_HCD && PCI + default y + config USB_EHCI_HCD_PMC_MSP tristate "EHCI support for on-chip PMC MSP71xx USB controller" depends on USB_EHCI_HCD && MSP_HAS_USB @@ -215,9 +220,13 @@ config USB_W90X900_EHCI Enables support for the W90X900 USB controller config USB_CNS3XXX_EHCI - bool "Cavium CNS3XXX EHCI Module" + bool "Cavium CNS3XXX EHCI Module (DEPRECATED)" depends on USB_EHCI_HCD && ARCH_CNS3XXX + select USB_EHCI_HCD_PLATFORM ---help--- + This option is deprecated now and the driver was removed, use + USB_EHCI_HCD_PLATFORM instead. + Enable support for the CNS3XXX SOC's on-chip EHCI controller. It is needed for high-speed (480Mbit/sec) USB 2.0 device support. @@ -333,16 +342,6 @@ config USB_OHCI_ATH79 Enables support for the built-in OHCI controller present on the Atheros AR71XX/AR7240 SoCs. -config USB_OHCI_HCD_PPC_SOC - bool "OHCI support for on-chip PPC USB controller" - depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) - default y - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO - ---help--- - Enables support for the USB controller on the MPC52xx or - STB03xxx processor chip. If unsure, say Y. - config USB_OHCI_HCD_PPC_OF_BE bool "OHCI support for OF platform bus (big endian)" depends on USB_OHCI_HCD && PPC_OF @@ -393,9 +392,13 @@ config USB_OHCI_HCD_SSB If unsure, say N. config USB_OHCI_SH - bool "OHCI support for SuperH USB controller" + bool "OHCI support for SuperH USB controller (DEPRECATED)" depends on USB_OHCI_HCD && SUPERH + select USB_OHCI_HCD_PLATFORM ---help--- + This option is deprecated now and the driver was removed, use + USB_OHCI_HCD_PLATFORM instead. + Enables support for the on-chip OHCI controller on the SuperH. If you use the PCI OHCI controller, this option is not necessary. @@ -406,9 +409,13 @@ config USB_OHCI_EXYNOS Enable support for the Samsung Exynos SOC's on-chip OHCI controller. config USB_CNS3XXX_OHCI - bool "Cavium CNS3XXX OHCI Module" + bool "Cavium CNS3XXX OHCI Module (DEPRECATED)" depends on USB_OHCI_HCD && ARCH_CNS3XXX + select USB_OHCI_HCD_PLATFORM ---help--- + This option is deprecated now and the driver was removed, use + USB_OHCI_HCD_PLATFORM instead. + Enable support for the CNS3XXX SOC's on-chip OHCI controller. It is needed for low-speed USB 1.0 device support. @@ -423,7 +430,7 @@ config USB_OHCI_HCD_PLATFORM If unsure, say N. config USB_EHCI_HCD_PLATFORM - bool "Generic EHCI driver for a platform device" + tristate "Generic EHCI driver for a platform device" depends on USB_EHCI_HCD default n ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 9e0a89c..1eb4c30 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -24,6 +24,9 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/ obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o +obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o +obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o + obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o @@ -40,6 +43,5 @@ obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o -obj-$(CONFIG_MIPS_ALCHEMY) += alchemy-common.o obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o diff --git a/drivers/usb/host/alchemy-common.c b/drivers/usb/host/alchemy-common.c deleted file mode 100644 index 936af83..0000000 --- a/drivers/usb/host/alchemy-common.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * USB block power/access management abstraction. - * - * Au1000+: The OHCI block control register is at the far end of the OHCI memory - * area. Au1550 has OHCI on different base address. No need to handle - * UDC here. - * Au1200: one register to control access and clocks to O/EHCI, UDC and OTG - * as well as the PHY for EHCI and UDC. - * - */ - -#include <linux/init.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/syscore_ops.h> -#include <asm/mach-au1x00/au1000.h> - -/* control register offsets */ -#define AU1000_OHCICFG 0x7fffc -#define AU1550_OHCICFG 0x07ffc -#define AU1200_USBCFG 0x04 - -/* Au1000 USB block config bits */ -#define USBHEN_RD (1 << 4) /* OHCI reset-done indicator */ -#define USBHEN_CE (1 << 3) /* OHCI block clock enable */ -#define USBHEN_E (1 << 2) /* OHCI block enable */ -#define USBHEN_C (1 << 1) /* OHCI block coherency bit */ -#define USBHEN_BE (1 << 0) /* OHCI Big-Endian */ - -/* Au1200 USB config bits */ -#define USBCFG_PFEN (1 << 31) /* prefetch enable (undoc) */ -#define USBCFG_RDCOMB (1 << 30) /* read combining (undoc) */ -#define USBCFG_UNKNOWN (5 << 20) /* unknown, leave this way */ -#define USBCFG_SSD (1 << 23) /* serial short detect en */ -#define USBCFG_PPE (1 << 19) /* HS PHY PLL */ -#define USBCFG_UCE (1 << 18) /* UDC clock enable */ -#define USBCFG_ECE (1 << 17) /* EHCI clock enable */ -#define USBCFG_OCE (1 << 16) /* OHCI clock enable */ -#define USBCFG_FLA(x) (((x) & 0x3f) << 8) -#define USBCFG_UCAM (1 << 7) /* coherent access (undoc) */ -#define USBCFG_GME (1 << 6) /* OTG mem access */ -#define USBCFG_DBE (1 << 5) /* UDC busmaster enable */ -#define USBCFG_DME (1 << 4) /* UDC mem enable */ -#define USBCFG_EBE (1 << 3) /* EHCI busmaster enable */ -#define USBCFG_EME (1 << 2) /* EHCI mem enable */ -#define USBCFG_OBE (1 << 1) /* OHCI busmaster enable */ -#define USBCFG_OME (1 << 0) /* OHCI mem enable */ -#define USBCFG_INIT_AU1200 (USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\ - USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \ - USBCFG_GME | USBCFG_DBE | USBCFG_DME | \ - USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \ - USBCFG_OME) - -/* Au1300 USB config registers */ -#define USB_DWC_CTRL1 0x00 -#define USB_DWC_CTRL2 0x04 -#define USB_VBUS_TIMER 0x10 -#define USB_SBUS_CTRL 0x14 -#define USB_MSR_ERR 0x18 -#define USB_DWC_CTRL3 0x1C -#define USB_DWC_CTRL4 0x20 -#define USB_OTG_STATUS 0x28 -#define USB_DWC_CTRL5 0x2C -#define USB_DWC_CTRL6 0x30 -#define USB_DWC_CTRL7 0x34 -#define USB_PHY_STATUS 0xC0 -#define USB_INT_STATUS 0xC4 -#define USB_INT_ENABLE 0xC8 - -#define USB_DWC_CTRL1_OTGD 0x04 /* set to DISable OTG */ -#define USB_DWC_CTRL1_HSTRS 0x02 /* set to ENable EHCI */ -#define USB_DWC_CTRL1_DCRS 0x01 /* set to ENable UDC */ - -#define USB_DWC_CTRL2_PHY1RS 0x04 /* set to enable PHY1 */ -#define USB_DWC_CTRL2_PHY0RS 0x02 /* set to enable PHY0 */ -#define USB_DWC_CTRL2_PHYRS 0x01 /* set to enable PHY */ - -#define USB_DWC_CTRL3_OHCI1_CKEN (1 << 19) -#define USB_DWC_CTRL3_OHCI0_CKEN (1 << 18) -#define USB_DWC_CTRL3_EHCI0_CKEN (1 << 17) -#define USB_DWC_CTRL3_OTG0_CKEN (1 << 16) - -#define USB_SBUS_CTRL_SBCA 0x04 /* coherent access */ - -#define USB_INTEN_FORCE 0x20 -#define USB_INTEN_PHY 0x10 -#define USB_INTEN_UDC 0x08 -#define USB_INTEN_EHCI 0x04 -#define USB_INTEN_OHCI1 0x02 -#define USB_INTEN_OHCI0 0x01 - -static DEFINE_SPINLOCK(alchemy_usb_lock); - -static inline void __au1300_usb_phyctl(void __iomem *base, int enable) -{ - unsigned long r, s; - - r = __raw_readl(base + USB_DWC_CTRL2); - s = __raw_readl(base + USB_DWC_CTRL3); - - s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN | - USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN; - - if (enable) { - /* simply enable all PHYs */ - r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS | - USB_DWC_CTRL2_PHYRS; - __raw_writel(r, base + USB_DWC_CTRL2); - wmb(); - } else if (!s) { - /* no USB block active, do disable all PHYs */ - r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS | - USB_DWC_CTRL2_PHYRS); - __raw_writel(r, base + USB_DWC_CTRL2); - wmb(); - } -} - -static inline void __au1300_ohci_control(void __iomem *base, int enable, int id) -{ - unsigned long r; - - if (enable) { - __raw_writel(1, base + USB_DWC_CTRL7); /* start OHCI clock */ - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL3); /* enable OHCI block */ - r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN - : USB_DWC_CTRL3_OHCI1_CKEN; - __raw_writel(r, base + USB_DWC_CTRL3); - wmb(); - - __au1300_usb_phyctl(base, enable); /* power up the PHYs */ - - r = __raw_readl(base + USB_INT_ENABLE); - r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1; - __raw_writel(r, base + USB_INT_ENABLE); - wmb(); - - /* reset the OHCI start clock bit */ - __raw_writel(0, base + USB_DWC_CTRL7); - wmb(); - } else { - r = __raw_readl(base + USB_INT_ENABLE); - r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1); - __raw_writel(r, base + USB_INT_ENABLE); - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL3); - r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN - : USB_DWC_CTRL3_OHCI1_CKEN); - __raw_writel(r, base + USB_DWC_CTRL3); - wmb(); - - __au1300_usb_phyctl(base, enable); - } -} - -static inline void __au1300_ehci_control(void __iomem *base, int enable) -{ - unsigned long r; - - if (enable) { - r = __raw_readl(base + USB_DWC_CTRL3); - r |= USB_DWC_CTRL3_EHCI0_CKEN; - __raw_writel(r, base + USB_DWC_CTRL3); - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL1); - r |= USB_DWC_CTRL1_HSTRS; - __raw_writel(r, base + USB_DWC_CTRL1); - wmb(); - - __au1300_usb_phyctl(base, enable); - - r = __raw_readl(base + USB_INT_ENABLE); - r |= USB_INTEN_EHCI; - __raw_writel(r, base + USB_INT_ENABLE); - wmb(); - } else { - r = __raw_readl(base + USB_INT_ENABLE); - r &= ~USB_INTEN_EHCI; - __raw_writel(r, base + USB_INT_ENABLE); - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL1); - r &= ~USB_DWC_CTRL1_HSTRS; - __raw_writel(r, base + USB_DWC_CTRL1); - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL3); - r &= ~USB_DWC_CTRL3_EHCI0_CKEN; - __raw_writel(r, base + USB_DWC_CTRL3); - wmb(); - - __au1300_usb_phyctl(base, enable); - } -} - -static inline void __au1300_udc_control(void __iomem *base, int enable) -{ - unsigned long r; - - if (enable) { - r = __raw_readl(base + USB_DWC_CTRL1); - r |= USB_DWC_CTRL1_DCRS; - __raw_writel(r, base + USB_DWC_CTRL1); - wmb(); - - __au1300_usb_phyctl(base, enable); - - r = __raw_readl(base + USB_INT_ENABLE); - r |= USB_INTEN_UDC; - __raw_writel(r, base + USB_INT_ENABLE); - wmb(); - } else { - r = __raw_readl(base + USB_INT_ENABLE); - r &= ~USB_INTEN_UDC; - __raw_writel(r, base + USB_INT_ENABLE); - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL1); - r &= ~USB_DWC_CTRL1_DCRS; - __raw_writel(r, base + USB_DWC_CTRL1); - wmb(); - - __au1300_usb_phyctl(base, enable); - } -} - -static inline void __au1300_otg_control(void __iomem *base, int enable) -{ - unsigned long r; - if (enable) { - r = __raw_readl(base + USB_DWC_CTRL3); - r |= USB_DWC_CTRL3_OTG0_CKEN; - __raw_writel(r, base + USB_DWC_CTRL3); - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL1); - r &= ~USB_DWC_CTRL1_OTGD; - __raw_writel(r, base + USB_DWC_CTRL1); - wmb(); - - __au1300_usb_phyctl(base, enable); - } else { - r = __raw_readl(base + USB_DWC_CTRL1); - r |= USB_DWC_CTRL1_OTGD; - __raw_writel(r, base + USB_DWC_CTRL1); - wmb(); - - r = __raw_readl(base + USB_DWC_CTRL3); - r &= ~USB_DWC_CTRL3_OTG0_CKEN; - __raw_writel(r, base + USB_DWC_CTRL3); - wmb(); - - __au1300_usb_phyctl(base, enable); - } -} - -static inline int au1300_usb_control(int block, int enable) -{ - void __iomem *base = - (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); - int ret = 0; - - switch (block) { - case ALCHEMY_USB_OHCI0: - __au1300_ohci_control(base, enable, 0); - break; - case ALCHEMY_USB_OHCI1: - __au1300_ohci_control(base, enable, 1); - break; - case ALCHEMY_USB_EHCI0: - __au1300_ehci_control(base, enable); - break; - case ALCHEMY_USB_UDC0: - __au1300_udc_control(base, enable); - break; - case ALCHEMY_USB_OTG0: - __au1300_otg_control(base, enable); - break; - default: - ret = -ENODEV; - } - return ret; -} - -static inline void au1300_usb_init(void) -{ - void __iomem *base = - (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); - - /* set some sane defaults. Note: we don't fiddle with DWC_CTRL4 - * here at all: Port 2 routing (EHCI or UDC) must be set either - * by boot firmware or platform init code; I can't autodetect - * a sane setting. - */ - __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */ - wmb(); - __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */ - wmb(); - __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */ - wmb(); - __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */ - wmb(); - /* set coherent access bit */ - __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL); - wmb(); -} - -static inline void __au1200_ohci_control(void __iomem *base, int enable) -{ - unsigned long r = __raw_readl(base + AU1200_USBCFG); - if (enable) { - __raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG); - wmb(); - udelay(2000); - } else { - __raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG); - wmb(); - udelay(1000); - } -} - -static inline void __au1200_ehci_control(void __iomem *base, int enable) -{ - unsigned long r = __raw_readl(base + AU1200_USBCFG); - if (enable) { - __raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG); - wmb(); - udelay(1000); - } else { - if (!(r & USBCFG_UCE)) /* UDC also off? */ - r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */ - __raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG); - wmb(); - udelay(1000); - } -} - -static inline void __au1200_udc_control(void __iomem *base, int enable) -{ - unsigned long r = __raw_readl(base + AU1200_USBCFG); - if (enable) { - __raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG); - wmb(); - } else { - if (!(r & USBCFG_ECE)) /* EHCI also off? */ - r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */ - __raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG); - wmb(); - } -} - -static inline int au1200_coherency_bug(void) -{ -#if defined(CONFIG_DMA_COHERENT) - /* Au1200 AB USB does not support coherent memory */ - if (!(read_c0_prid() & 0xff)) { - printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n"); - printk(KERN_INFO "Au1200 USB: update your board or re-configure" - " the kernel\n"); - return -ENODEV; - } -#endif - return 0; -} - -static inline int au1200_usb_control(int block, int enable) -{ - void __iomem *base = - (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); - int ret = 0; - - switch (block) { - case ALCHEMY_USB_OHCI0: - ret = au1200_coherency_bug(); - if (ret && enable) - goto out; - __au1200_ohci_control(base, enable); - break; - case ALCHEMY_USB_UDC0: - __au1200_udc_control(base, enable); - break; - case ALCHEMY_USB_EHCI0: - ret = au1200_coherency_bug(); - if (ret && enable) - goto out; - __au1200_ehci_control(base, enable); - break; - default: - ret = -ENODEV; - } -out: - return ret; -} - - -/* initialize USB block(s) to a known working state */ -static inline void au1200_usb_init(void) -{ - void __iomem *base = - (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); - __raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG); - wmb(); - udelay(1000); -} - -static inline void au1000_usb_init(unsigned long rb, int reg) -{ - void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg); - unsigned long r = __raw_readl(base); - -#if defined(__BIG_ENDIAN) - r |= USBHEN_BE; -#endif - r |= USBHEN_C; - - __raw_writel(r, base); - wmb(); - udelay(1000); -} - - -static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg) -{ - void __iomem *base = (void __iomem *)KSEG1ADDR(rb); - unsigned long r = __raw_readl(base + creg); - - if (enable) { - __raw_writel(r | USBHEN_CE, base + creg); - wmb(); - udelay(1000); - __raw_writel(r | USBHEN_CE | USBHEN_E, base + creg); - wmb(); - udelay(1000); - - /* wait for reset complete (read reg twice: au1500 erratum) */ - while (__raw_readl(base + creg), - !(__raw_readl(base + creg) & USBHEN_RD)) - udelay(1000); - } else { - __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg); - wmb(); - } -} - -static inline int au1000_usb_control(int block, int enable, unsigned long rb, - int creg) -{ - int ret = 0; - - switch (block) { - case ALCHEMY_USB_OHCI0: - __au1xx0_ohci_control(enable, rb, creg); - break; - default: - ret = -ENODEV; - } - return ret; -} - -/* - * alchemy_usb_control - control Alchemy on-chip USB blocks - * @block: USB block to target - * @enable: set 1 to enable a block, 0 to disable - */ -int alchemy_usb_control(int block, int enable) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&alchemy_usb_lock, flags); - switch (alchemy_get_cputype()) { - case ALCHEMY_CPU_AU1000: - case ALCHEMY_CPU_AU1500: - case ALCHEMY_CPU_AU1100: - ret = au1000_usb_control(block, enable, - AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); - break; - case ALCHEMY_CPU_AU1550: - ret = au1000_usb_control(block, enable, - AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); - break; - case ALCHEMY_CPU_AU1200: - ret = au1200_usb_control(block, enable); - break; - case ALCHEMY_CPU_AU1300: - ret = au1300_usb_control(block, enable); - break; - default: - ret = -ENODEV; - } - spin_unlock_irqrestore(&alchemy_usb_lock, flags); - return ret; -} -EXPORT_SYMBOL_GPL(alchemy_usb_control); - - -static unsigned long alchemy_usb_pmdata[2]; - -static void au1000_usb_pm(unsigned long br, int creg, int susp) -{ - void __iomem *base = (void __iomem *)KSEG1ADDR(br); - - if (susp) { - alchemy_usb_pmdata[0] = __raw_readl(base + creg); - /* There appears to be some undocumented reset register.... */ - __raw_writel(0, base + 0x04); - wmb(); - __raw_writel(0, base + creg); - wmb(); - } else { - __raw_writel(alchemy_usb_pmdata[0], base + creg); - wmb(); - } -} - -static void au1200_usb_pm(int susp) -{ - void __iomem *base = - (void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR); - if (susp) { - /* save OTG_CAP/MUX registers which indicate port routing */ - /* FIXME: write an OTG driver to do that */ - alchemy_usb_pmdata[0] = __raw_readl(base + 0x00); - alchemy_usb_pmdata[1] = __raw_readl(base + 0x04); - } else { - /* restore access to all MMIO areas */ - au1200_usb_init(); - - /* restore OTG_CAP/MUX registers */ - __raw_writel(alchemy_usb_pmdata[0], base + 0x00); - __raw_writel(alchemy_usb_pmdata[1], base + 0x04); - wmb(); - } -} - -static void au1300_usb_pm(int susp) -{ - void __iomem *base = - (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); - /* remember Port2 routing */ - if (susp) { - alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4); - } else { - au1300_usb_init(); - __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4); - wmb(); - } -} - -static void alchemy_usb_pm(int susp) -{ - switch (alchemy_get_cputype()) { - case ALCHEMY_CPU_AU1000: - case ALCHEMY_CPU_AU1500: - case ALCHEMY_CPU_AU1100: - au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp); - break; - case ALCHEMY_CPU_AU1550: - au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp); - break; - case ALCHEMY_CPU_AU1200: - au1200_usb_pm(susp); - break; - case ALCHEMY_CPU_AU1300: - au1300_usb_pm(susp); - break; - } -} - -static int alchemy_usb_suspend(void) -{ - alchemy_usb_pm(1); - return 0; -} - -static void alchemy_usb_resume(void) -{ - alchemy_usb_pm(0); -} - -static struct syscore_ops alchemy_usb_pm_ops = { - .suspend = alchemy_usb_suspend, - .resume = alchemy_usb_resume, -}; - -static int __init alchemy_usb_init(void) -{ - switch (alchemy_get_cputype()) { - case ALCHEMY_CPU_AU1000: - case ALCHEMY_CPU_AU1500: - case ALCHEMY_CPU_AU1100: - au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); - break; - case ALCHEMY_CPU_AU1550: - au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); - break; - case ALCHEMY_CPU_AU1200: - au1200_usb_init(); - break; - case ALCHEMY_CPU_AU1300: - au1300_usb_init(); - break; - } - - register_syscore_ops(&alchemy_usb_pm_ops); - - return 0; -} -arch_initcall(alchemy_usb_init); diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 411bb74..d23321e 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -53,18 +53,11 @@ static void atmel_stop_ehci(struct platform_device *pdev) static int ehci_atmel_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; /* registers start at offset 0x0 */ ehci->caps = hcd->regs; - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; + return ehci_setup(hcd); } static const struct hc_driver ehci_atmel_hc_driver = { diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c deleted file mode 100644 index 65c945e..0000000 --- a/drivers/usb/host/ehci-au1xxx.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) for USB. - * - * Bus Glue for AMD Alchemy Au1xxx - * - * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org> - * - * Modified for AMD Alchemy Au1200 EHC - * by K.Boge <karsten.boge@amd.com> - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> -#include <asm/mach-au1x00/au1000.h> - - -extern int usb_disabled(void); - -static int au1xxx_ehci_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int ret; - - ehci->caps = hcd->regs; - ret = ehci_setup(hcd); - - ehci->need_io_watchdog = 0; - return ret; -} - -static const struct hc_driver ehci_au1xxx_hc_driver = { - .description = hcd_name, - .product_desc = "Au1xxx EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - * - * FIXME -- ehci_init() doesn't do enough here. - * See ehci-ppc-soc for a complete implementation. - */ - .reset = au1xxx_ehci_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct resource *res; - int ret; - - if (usb_disabled()) - return -ENODEV; - - if (pdev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug("resource[1] is not IORESOURCE_IRQ"); - return -ENOMEM; - } - hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx"); - if (!hcd) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - hcd->regs = devm_request_and_ioremap(&pdev->dev, res); - if (!hcd->regs) { - pr_debug("devm_request_and_ioremap failed"); - ret = -ENOMEM; - goto err1; - } - - if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) { - printk(KERN_INFO "%s: controller init failed!\n", pdev->name); - ret = -ENODEV; - goto err1; - } - - ret = usb_add_hcd(hcd, pdev->resource[1].start, - IRQF_SHARED); - if (ret == 0) { - platform_set_drvdata(pdev, hcd); - return ret; - } - - alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); -err1: - usb_put_hcd(hcd); - return ret; -} - -static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); - usb_put_hcd(hcd); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -#ifdef CONFIG_PM -static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - bool do_wakeup = device_may_wakeup(dev); - int rc; - - rc = ehci_suspend(hcd, do_wakeup); - alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); - - return rc; -} - -static int ehci_hcd_au1xxx_drv_resume(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - - alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); - ehci_resume(hcd, false); - - return 0; -} - -static const struct dev_pm_ops au1xxx_ehci_pmops = { - .suspend = ehci_hcd_au1xxx_drv_suspend, - .resume = ehci_hcd_au1xxx_drv_resume, -}; - -#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops - -#else -#define AU1XXX_EHCI_PMOPS NULL -#endif - -static struct platform_driver ehci_hcd_au1xxx_driver = { - .probe = ehci_hcd_au1xxx_drv_probe, - .remove = ehci_hcd_au1xxx_drv_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "au1xxx-ehci", - .owner = THIS_MODULE, - .pm = AU1XXX_EHCI_PMOPS, - } -}; - -MODULE_ALIAS("platform:au1xxx-ehci"); diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c deleted file mode 100644 index d91708d..0000000 --- a/drivers/usb/host/ehci-cns3xxx.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2008 Cavium Networks - * - * This file 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. - */ - -#include <linux/platform_device.h> -#include <linux/atomic.h> -#include <mach/cns3xxx.h> -#include <mach/pm.h> - -static int cns3xxx_ehci_init(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - /* - * EHCI and OHCI share the same clock and power, - * resetting twice would cause the 1st controller been reset. - * Therefore only do power up at the first up device, and - * power down at the last down device. - * - * Set USB AHB INCR length to 16 - */ - if (atomic_inc_return(&usb_pwr_ref) == 1) { - cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB); - cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); - cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST); - __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)), - MISC_CHIP_CONFIG_REG); - } - - ehci->caps = hcd->regs; - - hcd->has_tt = 0; - - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; -} - -static const struct hc_driver cns3xxx_ehci_hc_driver = { - .description = hcd_name, - .product_desc = "CNS3XXX EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - .reset = cns3xxx_ehci_init, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - .get_frame_number = ehci_get_frame, - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -#endif - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int cns3xxx_ehci_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct usb_hcd *hcd; - const struct hc_driver *driver = &cns3xxx_ehci_hc_driver; - struct resource *res; - int irq; - int retval; - - if (usb_disabled()) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "Found HC with no IRQ.\n"); - return -ENODEV; - } - irq = res->start; - - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "Found HC with no register addr.\n"); - retval = -ENODEV; - goto err1; - } - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - hcd->regs = devm_request_and_ioremap(&pdev->dev, res); - if (hcd->regs == NULL) { - dev_dbg(dev, "error mapping memory\n"); - retval = -EFAULT; - goto err1; - } - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval == 0) - return retval; - -err1: - usb_put_hcd(hcd); - - return retval; -} - -static int cns3xxx_ehci_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - - /* - * EHCI and OHCI share the same clock and power, - * resetting twice would cause the 1st controller been reset. - * Therefore only do power up at the first up device, and - * power down at the last down device. - */ - if (atomic_dec_return(&usb_pwr_ref) == 0) - cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); - - usb_put_hcd(hcd); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -MODULE_ALIAS("platform:cns3xxx-ehci"); - -static struct platform_driver cns3xxx_ehci_driver = { - .probe = cns3xxx_ehci_probe, - .remove = cns3xxx_ehci_remove, - .driver = { - .name = "cns3xxx-ehci", - }, -}; diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 1599806..70b496d 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -18,21 +18,6 @@ /* this file is part of ehci-hcd.c */ -#define ehci_dbg(ehci, fmt, args...) \ - dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_err(ehci, fmt, args...) \ - dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_info(ehci, fmt, args...) \ - dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_warn(ehci, fmt, args...) \ - dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) - -#ifdef VERBOSE_DEBUG -# define ehci_vdbg ehci_dbg -#else - static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {} -#endif - #ifdef DEBUG /* check the values in the HCSPARAMS register @@ -352,11 +337,6 @@ static int debug_async_open(struct inode *, struct file *); static int debug_periodic_open(struct inode *, struct file *); static int debug_registers_open(struct inode *, struct file *); static int debug_async_open(struct inode *, struct file *); -static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -static ssize_t debug_lpm_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos); -static int debug_lpm_close(struct inode *inode, struct file *file); static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); static int debug_close(struct inode *, struct file *); @@ -382,14 +362,6 @@ static const struct file_operations debug_registers_fops = { .release = debug_close, .llseek = default_llseek, }; -static const struct file_operations debug_lpm_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = debug_lpm_read, - .write = debug_lpm_write, - .release = debug_lpm_close, - .llseek = noop_llseek, -}; static struct dentry *ehci_debug_root; @@ -971,86 +943,6 @@ static int debug_registers_open(struct inode *inode, struct file *file) return file->private_data ? 0 : -ENOMEM; } -static int debug_lpm_close(struct inode *inode, struct file *file) -{ - return 0; -} - -static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - /* TODO: show lpm stats */ - return 0; -} - -static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - char buf[50]; - size_t len; - u32 temp; - unsigned long port; - u32 __iomem *portsc ; - u32 params; - - hcd = bus_to_hcd(file->private_data); - ehci = hcd_to_ehci(hcd); - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - buf[len] = '\0'; - if (len > 0 && buf[len - 1] == '\n') - buf[len - 1] = '\0'; - - if (strncmp(buf, "enable", 5) == 0) { - if (strict_strtoul(buf + 7, 10, &port)) - return -EINVAL; - params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (port > HCS_N_PORTS(params)) { - ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port); - return -ENODEV; - } - portsc = &ehci->regs->port_status[port-1]; - temp = ehci_readl(ehci, portsc); - if (!(temp & PORT_DEV_ADDR)) { - ehci_dbg(ehci, "LPM: no device attached\n"); - return -ENODEV; - } - temp |= PORT_LPM; - ehci_writel(ehci, temp, portsc); - printk(KERN_INFO "force enable LPM for port %lu\n", port); - } else if (strncmp(buf, "hird=", 5) == 0) { - unsigned long hird; - if (strict_strtoul(buf + 5, 16, &hird)) - return -EINVAL; - printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird); - ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24); - ehci_writel(ehci, ehci->command, &ehci->regs->command); - } else if (strncmp(buf, "disable", 7) == 0) { - if (strict_strtoul(buf + 8, 10, &port)) - return -EINVAL; - params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (port > HCS_N_PORTS(params)) { - ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port); - return -ENODEV; - } - portsc = &ehci->regs->port_status[port-1]; - temp = ehci_readl(ehci, portsc); - if (!(temp & PORT_DEV_ADDR)) { - ehci_dbg(ehci, "ERR: no device attached\n"); - return -ENODEV; - } - temp &= ~PORT_LPM; - ehci_writel(ehci, temp, portsc); - printk(KERN_INFO "disabled LPM for port %lu\n", port); - } else - return -EOPNOTSUPP; - return count; -} - static inline void create_debug_files (struct ehci_hcd *ehci) { struct usb_bus *bus = &ehci_to_hcd(ehci)->self; @@ -1071,10 +963,6 @@ static inline void create_debug_files (struct ehci_hcd *ehci) &debug_registers_fops)) goto file_error; - if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus, - &debug_lpm_fops)) - goto file_error; - return; file_error: diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 9bfde82..fd9b542 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -222,7 +222,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, if (pdata->controller_ver < 0) { dev_warn(hcd->self.controller, "Could not get controller version\n"); - return; + return -ENODEV; } portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); @@ -349,7 +349,6 @@ static int ehci_fsl_reinit(struct ehci_hcd *ehci) { if (ehci_fsl_usb_setup(ehci)) return -EINVAL; - ehci_port_power(ehci, 0); return 0; } diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index 3180cb3..da42695 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -34,22 +34,6 @@ #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */ -/* called during probe() after chip reset completes */ -static int ehci_grlib_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 1); - - return retval; -} - - static const struct hc_driver ehci_grlib_hc_driver = { .description = hcd_name, .product_desc = "GRLIB GRUSBHC EHCI", @@ -64,7 +48,7 @@ static const struct hc_driver ehci_grlib_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_grlib_setup, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 6bf6c42..28f694e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -39,7 +39,6 @@ #include <linux/dma-mapping.h> #include <linux/debugfs.h> #include <linux/slab.h> -#include <linux/uaccess.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -108,19 +107,39 @@ static bool ignore_oc = 0; module_param (ignore_oc, bool, S_IRUGO); MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); -/* for link power management(LPM) feature */ -static unsigned int hird; -module_param(hird, int, S_IRUGO); -MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); - #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) /*-------------------------------------------------------------------------*/ #include "ehci.h" -#include "ehci-dbg.c" #include "pci-quirks.h" +/* + * The MosChip MCS9990 controller updates its microframe counter + * a little before the frame counter, and occasionally we will read + * the invalid intermediate value. Avoid problems by checking the + * microframe number (the low-order 3 bits); if they are 0 then + * re-read the register to get the correct value. + */ +static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci) +{ + unsigned uf; + + uf = ehci_readl(ehci, &ehci->regs->frame_index); + if (unlikely((uf & 7) == 0)) + uf = ehci_readl(ehci, &ehci->regs->frame_index); + return uf; +} + +static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) +{ + if (ehci->frame_index_bug) + return ehci_moschip_read_frame_index(ehci); + return ehci_readl(ehci, &ehci->regs->frame_index); +} + +#include "ehci-dbg.c" + /*-------------------------------------------------------------------------*/ /* @@ -293,7 +312,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); #include "ehci-timer.c" #include "ehci-hub.c" -#include "ehci-lpm.c" #include "ehci-mem.c" #include "ehci-q.c" #include "ehci-sched.c" @@ -353,24 +371,6 @@ static void ehci_shutdown(struct usb_hcd *hcd) hrtimer_cancel(&ehci->hrtimer); } -static void ehci_port_power (struct ehci_hcd *ehci, int is_on) -{ - unsigned port; - - if (!HCS_PPC (ehci->hcs_params)) - return; - - ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down"); - for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) - (void) ehci_hub_control(ehci_to_hcd(ehci), - is_on ? SetPortFeature : ClearPortFeature, - USB_PORT_FEAT_POWER, - port--, NULL, 0); - /* Flush those writes */ - ehci_readl(ehci, &ehci->regs->command); - msleep(20); -} - /*-------------------------------------------------------------------------*/ /* @@ -503,7 +503,7 @@ static int ehci_init(struct usb_hcd *hcd) /* controllers may cache some of the periodic schedule ... */ if (HCC_ISOC_CACHE(hcc_params)) // full frame cache - ehci->i_thresh = 2 + 8; + ehci->i_thresh = 0; else // N microframes cached ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); @@ -555,17 +555,6 @@ static int ehci_init(struct usb_hcd *hcd) temp &= ~(3 << 2); temp |= (EHCI_TUNE_FLS << 2); } - if (HCC_LPM(hcc_params)) { - /* support link power management EHCI 1.1 addendum */ - ehci_dbg(ehci, "support lpm\n"); - ehci->has_lpm = 1; - if (hird > 0xf) { - ehci_dbg(ehci, "hird %d invalid, use default 0", - hird); - hird = 0; - } - temp |= hird << 24; - } ehci->command = temp; /* Accept arbitrarily long scatter-gather lists */ @@ -660,7 +649,7 @@ static int ehci_run (struct usb_hcd *hcd) return 0; } -static int ehci_setup(struct usb_hcd *hcd) +int ehci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; @@ -691,6 +680,7 @@ static int ehci_setup(struct usb_hcd *hcd) return 0; } +EXPORT_SYMBOL_GPL(ehci_setup); /*-------------------------------------------------------------------------*/ @@ -1096,7 +1086,7 @@ static int ehci_get_frame (struct usb_hcd *hcd) /* These routines handle the generic parts of controller suspend/resume */ -static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) +int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1119,9 +1109,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) return 0; } +EXPORT_SYMBOL_GPL(ehci_suspend); /* Returns 0 if power was preserved, 1 if power was lost */ -static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) +int ehci_resume(struct usb_hcd *hcd, bool hibernated) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1177,33 +1168,82 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) ehci->rh_state = EHCI_RH_SUSPENDED; spin_unlock_irq(&ehci->lock); - /* here we "know" root ports should always stay powered */ - ehci_port_power(ehci, 1); - return 1; } +EXPORT_SYMBOL_GPL(ehci_resume); #endif /*-------------------------------------------------------------------------*/ /* - * The EHCI in ChipIdea HDRC cannot be a separate module or device, - * because its registers (and irq) are shared between host/gadget/otg - * functions and in order to facilitate role switching we cannot - * give the ehci driver exclusive access to those. + * Generic structure: This gets copied for platform drivers so that + * individual entries can be overridden as needed. */ -#ifndef CHIPIDEA_EHCI + +static const struct hc_driver ehci_hc_driver = { + .description = hcd_name, + .product_desc = "EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_setup, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + .endpoint_reset = ehci_endpoint_reset, + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, +}; + +void ehci_init_driver(struct hc_driver *drv, + const struct ehci_driver_overrides *over) +{ + /* Copy the generic table to drv and then apply the overrides */ + *drv = ehci_hc_driver; + + drv->product_desc = over->product_desc; + drv->hcd_priv_size += over->extra_priv_size; + if (over->reset) + drv->reset = over->reset; +} +EXPORT_SYMBOL_GPL(ehci_init_driver); + +/*-------------------------------------------------------------------------*/ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_LICENSE ("GPL"); -#ifdef CONFIG_PCI -#include "ehci-pci.c" -#define PCI_DRIVER ehci_pci_driver -#endif - #ifdef CONFIG_USB_EHCI_FSL #include "ehci-fsl.c" #define PLATFORM_DRIVER ehci_fsl_driver @@ -1219,11 +1259,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_sh_driver #endif -#ifdef CONFIG_MIPS_ALCHEMY -#include "ehci-au1xxx.c" -#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver -#endif - #ifdef CONFIG_USB_EHCI_HCD_OMAP #include "ehci-omap.c" #define PLATFORM_DRIVER ehci_hcd_omap_driver @@ -1249,11 +1284,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_orion_driver #endif -#ifdef CONFIG_ARCH_IXP4XX -#include "ehci-ixp4xx.c" -#define PLATFORM_DRIVER ixp4xx_ehci_driver -#endif - #ifdef CONFIG_USB_W90X900_EHCI #include "ehci-w90x900.c" #define PLATFORM_DRIVER ehci_hcd_w90x900_driver @@ -1269,11 +1299,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_octeon_driver #endif -#ifdef CONFIG_USB_CNS3XXX_EHCI -#include "ehci-cns3xxx.c" -#define PLATFORM_DRIVER cns3xxx_ehci_driver -#endif - #ifdef CONFIG_ARCH_VT8500 #include "ehci-vt8500.c" #define PLATFORM_DRIVER vt8500_ehci_driver @@ -1314,34 +1339,23 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_grlib_driver #endif -#ifdef CONFIG_CPU_XLR -#include "ehci-xls.c" -#define PLATFORM_DRIVER ehci_xls_driver -#endif - #ifdef CONFIG_USB_EHCI_MV #include "ehci-mv.c" #define PLATFORM_DRIVER ehci_mv_driver #endif -#ifdef CONFIG_MACH_LOONGSON1 -#include "ehci-ls1x.c" -#define PLATFORM_DRIVER ehci_ls1x_driver -#endif - #ifdef CONFIG_MIPS_SEAD3 #include "ehci-sead3.c" #define PLATFORM_DRIVER ehci_hcd_sead3_driver #endif -#ifdef CONFIG_USB_EHCI_HCD_PLATFORM -#include "ehci-platform.c" -#define PLATFORM_DRIVER ehci_platform_driver -#endif - -#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ - !defined(XILINX_OF_PLATFORM_DRIVER) +#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ + !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ + !defined(CONFIG_USB_CHIPIDEA_HOST) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && \ + !defined(OF_PLATFORM_DRIVER) && \ + !defined(XILINX_OF_PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" #endif @@ -1378,12 +1392,6 @@ static int __init ehci_hcd_init(void) goto clean0; #endif -#ifdef PCI_DRIVER - retval = pci_register_driver(&PCI_DRIVER); - if (retval < 0) - goto clean1; -#endif - #ifdef PS3_SYSTEM_BUS_DRIVER retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); if (retval < 0) @@ -1415,10 +1423,6 @@ clean3: ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); clean2: #endif -#ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); -clean1: -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); clean0: @@ -1444,9 +1448,6 @@ static void __exit ehci_hcd_cleanup(void) #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif -#ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); -#endif #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif @@ -1456,5 +1457,3 @@ static void __exit ehci_hcd_cleanup(void) clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); } module_exit(ehci_hcd_cleanup); - -#endif /* CHIPIDEA_EHCI */ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 914ce93..4ccb97c 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) if (!ehci->owned_ports) return; + /* Make sure the ports are powered */ + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { + if (test_bit(port, &ehci->owned_ports)) { + reg = &ehci->regs->port_status[port]; + status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; + if (!(status & PORT_POWER)) { + status |= PORT_POWER; + ehci_writel(ehci, status, reg); + } + } + } + /* Give the connections some time to appear */ msleep(20); @@ -384,11 +397,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd) ehci_writel(ehci, ehci->command, &ehci->regs->command); ehci->rh_state = EHCI_RH_RUNNING; - /* Some controller/firmware combinations need a delay during which - * they set up the port statuses. See Bugzilla #8190. */ - spin_unlock_irq(&ehci->lock); - msleep(8); - spin_lock_irq(&ehci->lock); + /* + * According to Bugzilla #8190, the port status for some controllers + * will be wrong without a delay. At their wrong status, the port + * is enabled, but not suspended neither resumed. + */ + i = HCS_N_PORTS(ehci->hcs_params); + while (i--) { + temp = ehci_readl(ehci, &ehci->regs->port_status[i]); + if ((temp & PORT_PE) && + !(temp & (PORT_SUSPEND | PORT_RESUME))) { + ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp); + spin_unlock_irq(&ehci->lock); + msleep(8); + spin_lock_irq(&ehci->lock); + break; + } + } + if (ehci->shutdown) goto shutdown; @@ -764,11 +790,6 @@ static int ehci_hub_control ( status_reg); break; case USB_PORT_FEAT_C_CONNECTION: - if (ehci->has_lpm) { - /* clear PORTSC bits on disconnect */ - temp &= ~PORT_LPM; - temp &= ~PORT_DEV_ADDR; - } ehci_writel(ehci, temp | PORT_CSC, status_reg); break; case USB_PORT_FEAT_C_OVER_CURRENT: @@ -1088,8 +1109,7 @@ error_exit: return retval; } -static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, - int portnum) +static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1098,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, set_owner(ehci, --portnum, PORT_OWNER); } -static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd, - int portnum) +static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 __iomem *reg; diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c deleted file mode 100644 index f224c0a..0000000 --- a/drivers/usb/host/ehci-ixp4xx.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * IXP4XX EHCI Host Controller Driver - * - * Author: Vladimir Barinov <vbarinov@embeddedalley.com> - * - * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com> - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include <linux/platform_device.h> - -static int ixp4xx_ehci_init(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval = 0; - - ehci->big_endian_desc = 1; - ehci->big_endian_mmio = 1; - - ehci->caps = hcd->regs + 0x100; - - hcd->has_tt = 1; - - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; -} - -static const struct hc_driver ixp4xx_ehci_hc_driver = { - .description = hcd_name, - .product_desc = "IXP4XX EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - .reset = ixp4xx_ehci_init, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - .get_frame_number = ehci_get_frame, - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, -#if defined(CONFIG_PM) - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -#endif - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int ixp4xx_ehci_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - const struct hc_driver *driver = &ixp4xx_ehci_hc_driver; - struct resource *res; - int irq; - int retval; - - if (usb_disabled()) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); - return -ENODEV; - } - irq = res->start; - - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) { - retval = -ENOMEM; - goto fail_create_hcd; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no register addr. Check %s setup!\n", - dev_name(&pdev->dev)); - retval = -ENODEV; - goto fail_request_resource; - } - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - hcd->regs = devm_request_and_ioremap(&pdev->dev, res); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - retval = -EFAULT; - goto fail_request_resource; - } - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval) - goto fail_request_resource; - - return retval; - -fail_request_resource: - usb_put_hcd(hcd); -fail_create_hcd: - dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); - return retval; -} - -static int ixp4xx_ehci_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - - return 0; -} - -MODULE_ALIAS("platform:ixp4xx-ehci"); - -static struct platform_driver ixp4xx_ehci_driver = { - .probe = ixp4xx_ehci_probe, - .remove = ixp4xx_ehci_remove, - .driver = { - .name = "ixp4xx-ehci", - }, -}; diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c deleted file mode 100644 index 2111627..0000000 --- a/drivers/usb/host/ehci-lpm.c +++ /dev/null @@ -1,84 +0,0 @@ -/* ehci-lpm.c EHCI HCD LPM support code - * Copyright (c) 2008 - 2010, Intel Corporation. - * Author: Jacob Pan <jacob.jun.pan@intel.com> - * - * 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. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* this file is part of ehci-hcd.c */ -static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci, - int dev_addr, int port_num) -{ - u32 __iomem portsc; - - ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num); - if (port_num > HCS_N_PORTS(ehci->hcs_params)) { - ehci_dbg(ehci, "invalid port number %d\n", port_num); - return -ENODEV; - } - portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]); - portsc &= ~PORT_DEV_ADDR; - portsc |= dev_addr<<25; - ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]); - return 0; -} - -/* - * this function is used to check if the device support LPM - * if yes, mark the PORTSC register with PORT_LPM bit - */ -static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port) -{ - u32 __iomem *portsc ; - u32 val32; - int retval; - - portsc = &ehci->regs->port_status[port-1]; - val32 = ehci_readl(ehci, portsc); - if (!(val32 & PORT_DEV_ADDR)) { - ehci_dbg(ehci, "LPM: no device attached\n"); - return -ENODEV; - } - val32 |= PORT_LPM; - ehci_writel(ehci, val32, portsc); - msleep(5); - val32 |= PORT_SUSPEND; - ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port); - ehci_writel(ehci, val32, portsc); - /* wait for ACK */ - msleep(10); - retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS, - PORTSC_SUSPEND_STS_ACK, 125); - dbg_port(ehci, "LPM", port, val32); - if (retval != -ETIMEDOUT) { - ehci_dbg(ehci, "LPM: device ACK for LPM\n"); - val32 |= PORT_LPM; - /* - * now device should be in L1 sleep, let's wake up the device - * so that we can complete enumeration. - */ - ehci_writel(ehci, val32, portsc); - msleep(10); - val32 |= PORT_RESUME; - ehci_writel(ehci, val32, portsc); - } else { - ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n", - retval); - val32 &= ~PORT_LPM; - retval = -ETIMEDOUT; - ehci_writel(ehci, val32, portsc); - } - - return retval; -} diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c deleted file mode 100644 index ca75965..0000000 --- a/drivers/usb/host/ehci-ls1x.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Bus Glue for Loongson LS1X built-in EHCI controller. - * - * Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com> - * - * 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. - */ - - -#include <linux/platform_device.h> - -static int ehci_ls1x_reset(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int ret; - - ehci->caps = hcd->regs; - - ret = ehci_setup(hcd); - if (ret) - return ret; - - ehci_port_power(ehci, 0); - - return 0; -} - -static const struct hc_driver ehci_ls1x_hc_driver = { - .description = hcd_name, - .product_desc = "LOONGSON1 EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ehci_ls1x_reset, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int ehci_hcd_ls1x_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct resource *res; - int irq; - int ret; - - pr_debug("initializing loongson1 ehci USB Controller\n"); - - if (usb_disabled()) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); - return -ENODEV; - } - irq = res->start; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no register addr. Check %s setup!\n", - dev_name(&pdev->dev)); - return -ENODEV; - } - - hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev, - dev_name(&pdev->dev)); - if (!hcd) - return -ENOMEM; - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - hcd->regs = devm_request_and_ioremap(&pdev->dev, res); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - ret = -EFAULT; - goto err_put_hcd; - } - - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret) - goto err_put_hcd; - - return ret; - -err_put_hcd: - usb_put_hcd(hcd); - return ret; -} - -static int ehci_hcd_ls1x_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - - return 0; -} - -static struct platform_driver ehci_ls1x_driver = { - .probe = ehci_hcd_ls1x_probe, - .remove = ehci_hcd_ls1x_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "ls1x-ehci", - .owner = THIS_MODULE, - }, -}; - -MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci"); diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 4af4dc5..7fa1ba4 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -53,7 +53,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd) /* Disable streaming mode and select host mode */ writel(0x13, USB_USBMODE); - ehci_port_power(ehci, 1); return 0; } diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 4a08fc0..a37224a 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -40,16 +40,10 @@ struct ehci_mxc_priv { static int ehci_mxc_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; hcd->has_tt = 1; - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - return 0; + return ehci_setup(hcd); } static const struct hc_driver ehci_mxc_hc_driver = { diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c index ba26957a..a89750f 100644 --- a/drivers/usb/host/ehci-octeon.c +++ b/drivers/usb/host/ehci-octeon.c @@ -159,9 +159,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hcd); - /* root ports should always stay powered */ - ehci_port_power(ehci, 1); - return 0; err3: ehci_octeon_stop(); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index d7fe287..44e7d0f 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -146,9 +146,6 @@ static int omap_ehci_init(struct usb_hcd *hcd) gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); } - /* root ports should always stay powered */ - ehci_port_power(ehci, 1); - return rc; } diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 8e7eca6..96da679 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -101,20 +101,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd) wrl(USB_MODE, 0x13); } -static int ehci_orion_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; -} - static const struct hc_driver ehci_orion_hc_driver = { .description = hcd_name, .product_desc = "Marvell Orion EHCI", @@ -129,7 +115,7 @@ static const struct hc_driver ehci_orion_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_orion_setup, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -160,7 +146,7 @@ static const struct hc_driver ehci_orion_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -static void __init +static void __devinit ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, const struct mbus_dram_target_info *dram) { diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 2cb7d37..46018e9 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -18,9 +18,18 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef CONFIG_PCI -#error "This file is PCI bus glue. CONFIG_PCI must be defined." -#endif +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ehci.h" +#include "pci-quirks.h" + +#define DRIVER_DESC "EHCI PCI platform driver" + +static const char hcd_name[] = "ehci-pci"; /* defined here to avoid adding to pci_ids.h for single instance use */ #define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70 @@ -103,7 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } break; case PCI_VENDOR_ID_INTEL: - ehci->fs_i_thresh = 1; if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) hcd->has_tt = 1; break; @@ -203,11 +211,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; case PCI_VENDOR_ID_INTEL: ehci->need_io_watchdog = 0; - if (pdev->device == 0x0806 || pdev->device == 0x0811 - || pdev->device == 0x0829) { - ehci_info(ehci, "disable lpm for langwell/penwell\n"); - ehci->has_lpm = 0; - } break; case PCI_VENDOR_ID_NVIDIA: switch (pdev->device) { @@ -217,8 +220,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) * devices with PPCD enabled. */ case 0x0d9d: - ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); - ehci->has_lpm = 0; + ehci_info(ehci, "disable ppcd for nvidia mcp89\n"); ehci->has_ppcd = 0; ehci->command &= ~CMD_PPCEE; break; @@ -304,7 +306,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); #endif - ehci_port_power(ehci, 1); retval = ehci_pci_reinit(ehci, pdev); done: return retval; @@ -323,11 +324,6 @@ done: * Also they depend on separate root hub suspend/resume. */ -static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ - return ehci_suspend(hcd, do_wakeup); -} - static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_EHCI && @@ -378,76 +374,18 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) (void) ehci_pci_reinit(ehci, pdev); return 0; } -#endif -static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int rc = 0; - - if (!udev->parent) /* udev is root hub itself, impossible */ - rc = -1; - /* we only support lpm device connected to root hub yet */ - if (ehci->has_lpm && !udev->parent->parent) { - rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); - if (!rc) - rc = ehci_lpm_check(ehci, udev->portnum); - } - return rc; -} +#else -static const struct hc_driver ehci_pci_hc_driver = { - .description = hcd_name, - .product_desc = "EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), +#define ehci_suspend NULL +#define ehci_pci_resume NULL +#endif /* CONFIG_PM */ - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, +static struct hc_driver __read_mostly ehci_pci_hc_driver; - /* - * basic lifecycle operations - */ +static const struct ehci_driver_overrides overrides = { + .product_desc = "EHCI PCI host controller", .reset = ehci_pci_setup, - .start = ehci_run, -#ifdef CONFIG_PM - .pci_suspend = ehci_pci_suspend, - .pci_resume = ehci_pci_resume, -#endif - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - /* - * call back when device connected and addressed - */ - .update_device = ehci_update_device, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; /*-------------------------------------------------------------------------*/ @@ -480,3 +418,31 @@ static struct pci_driver ehci_pci_driver = { }, #endif }; + +static int __init ehci_pci_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_pci_hc_driver, &overrides); + + /* Entries for the PCI suspend/resume callbacks are special */ + ehci_pci_hc_driver.pci_suspend = ehci_suspend; + ehci_pci_hc_driver.pci_resume = ehci_pci_resume; + + return pci_register_driver(&ehci_pci_driver); +} +module_init(ehci_pci_init); + +static void __exit ehci_pci_cleanup(void) +{ + pci_unregister_driver(&ehci_pci_driver); +} +module_exit(ehci_pci_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("David Brownell"); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 764e010..feeedf8 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -18,9 +18,21 @@ * * Licensed under the GNU/GPL. See COPYING for details. */ +#include <linux/kernel.h> +#include <linux/hrtimer.h> +#include <linux/io.h> +#include <linux/module.h> #include <linux/platform_device.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> #include <linux/usb/ehci_pdriver.h> +#include "ehci.h" + +#define DRIVER_DESC "EHCI generic platform driver" + +static const char hcd_name[] = "ehci-platform"; + static int ehci_platform_reset(struct usb_hcd *hcd) { struct platform_device *pdev = to_platform_device(hcd->self.controller); @@ -38,44 +50,16 @@ static int ehci_platform_reset(struct usb_hcd *hcd) if (retval) return retval; - if (pdata->port_power_on) - ehci_port_power(ehci, 1); - if (pdata->port_power_off) - ehci_port_power(ehci, 0); - + if (pdata->no_io_watchdog) + ehci->need_io_watchdog = 0; return 0; } -static const struct hc_driver ehci_platform_hc_driver = { - .description = hcd_name, - .product_desc = "Generic Platform EHCI Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - .reset = ehci_platform_reset, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, +static struct hc_driver __read_mostly ehci_platform_hc_driver; - .get_frame_number = ehci_get_frame, - - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, -#if defined(CONFIG_PM) - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -#endif - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +static const struct ehci_driver_overrides platform_overrides = { + .product_desc = "Generic Platform EHCI controller", + .reset = ehci_platform_reset, }; static int __devinit ehci_platform_probe(struct platform_device *dev) @@ -96,12 +80,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev) irq = platform_get_irq(dev, 0); if (irq < 0) { - pr_err("no irq provided"); + dev_err(&dev->dev, "no irq provided"); return irq; } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { - pr_err("no memory recourse provided"); + dev_err(&dev->dev, "no memory resource provided"); return -ENXIO; } @@ -121,29 +105,19 @@ static int __devinit ehci_platform_probe(struct platform_device *dev) hcd->rsrc_start = res_mem->start; hcd->rsrc_len = resource_size(res_mem); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_err("controller already in use"); - err = -EBUSY; - goto err_put_hcd; - } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem); if (!hcd->regs) { err = -ENOMEM; - goto err_release_region; + goto err_put_hcd; } err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) - goto err_iounmap; + goto err_put_hcd; platform_set_drvdata(dev, hcd); return err; -err_iounmap: - iounmap(hcd->regs); -err_release_region: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put_hcd: usb_put_hcd(hcd); err_power: @@ -159,8 +133,6 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) struct usb_ehci_pdata *pdata = dev->dev.platform_data; usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(dev, NULL); @@ -233,3 +205,26 @@ static struct platform_driver ehci_platform_driver = { .pm = &ehci_platform_pm_ops, } }; + +static int __init ehci_platform_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides); + return platform_driver_register(&ehci_platform_driver); +} +module_init(ehci_platform_init); + +static void __exit ehci_platform_cleanup(void) +{ + platform_driver_unregister(&ehci_platform_driver); +} +module_exit(ehci_platform_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Hauke Mehrtens"); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index 087aee2..363890e 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -90,7 +90,6 @@ static int ehci_msp_setup(struct usb_hcd *hcd) return retval; usb_hcd_tdi_set_mode(ehci); - ehci_port_power(ehci, 0); return retval; } diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 85b74be..abc178d 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -136,7 +136,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) goto fail_clk; } - err = clk_enable(s5p_ehci->clk); + err = clk_prepare_enable(s5p_ehci->clk); if (err) goto fail_clk; @@ -183,7 +183,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) return 0; fail_io: - clk_disable(s5p_ehci->clk); + clk_disable_unprepare(s5p_ehci->clk); fail_clk: usb_put_hcd(hcd); return err; @@ -200,7 +200,7 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); - clk_disable(s5p_ehci->clk); + clk_disable_unprepare(s5p_ehci->clk); usb_put_hcd(hcd); @@ -231,7 +231,7 @@ static int s5p_ehci_suspend(struct device *dev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); - clk_disable(s5p_ehci->clk); + clk_disable_unprepare(s5p_ehci->clk); return rc; } @@ -243,7 +243,7 @@ static int s5p_ehci_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; - clk_enable(s5p_ehci->clk); + clk_prepare_enable(s5p_ehci->clk); if (pdata && pdata->phy_init) pdata->phy_init(pdev, S5P_USB_PHY_HOST); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 7cf3da7..2e14714 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -36,29 +36,6 @@ static int ehci_get_frame (struct usb_hcd *hcd); -#ifdef CONFIG_PCI - -static unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ - unsigned uf; - - /* - * The MosChip MCS9990 controller updates its microframe counter - * a little before the frame counter, and occasionally we will read - * the invalid intermediate value. Avoid problems by checking the - * microframe number (the low-order 3 bits); if they are 0 then - * re-read the register to get the correct value. - */ - uf = ehci_readl(ehci, &ehci->regs->frame_index); - if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0))) - uf = ehci_readl(ehci, &ehci->regs->frame_index); - return uf; -} - -#endif - -/*-------------------------------------------------------------------------*/ - /* * periodic_next_shadow - return "next" pointer on shadow list * @periodic: host pointer to qh/itd/sitd @@ -1361,7 +1338,7 @@ sitd_slot_ok ( * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! */ -#define SCHEDULE_SLOP 80 /* microframes */ +#define SCHEDULING_DELAY 40 /* microframes */ static int iso_stream_schedule ( @@ -1370,7 +1347,7 @@ iso_stream_schedule ( struct ehci_iso_stream *stream ) { - u32 now, next, start, period, span; + u32 now, base, next, start, period, span; int status; unsigned mod = ehci->periodic_size << 3; struct ehci_iso_sched *sched = urb->hcpriv; @@ -1382,62 +1359,72 @@ iso_stream_schedule ( span <<= 3; } - if (span > mod - SCHEDULE_SLOP) { - ehci_dbg (ehci, "iso request %p too long\n", urb); - status = -EFBIG; - goto fail; - } - now = ehci_read_frame_index(ehci) & (mod - 1); /* Typical case: reuse current schedule, stream is still active. * Hopefully there are no gaps from the host falling behind - * (irq delays etc), but if there are we'll take the next - * slot in the schedule, implicitly assuming URB_ISO_ASAP. + * (irq delays etc). If there are, the behavior depends on + * whether URB_ISO_ASAP is set. */ if (likely (!list_empty (&stream->td_list))) { - u32 excess; - /* For high speed devices, allow scheduling within the - * isochronous scheduling threshold. For full speed devices - * and Intel PCI-based controllers, don't (work around for - * Intel ICH9 bug). - */ - if (!stream->highspeed && ehci->fs_i_thresh) - next = now + ehci->i_thresh; + /* Take the isochronous scheduling threshold into account */ + if (ehci->i_thresh) + next = now + ehci->i_thresh; /* uframe cache */ else - next = now; + next = (now + 2 + 7) & ~0x07; /* full frame cache */ - /* Fell behind (by up to twice the slop amount)? - * We decide based on the time of the last currently-scheduled - * slot, not the time of the next available slot. + /* + * Use ehci->last_iso_frame as the base. There can't be any + * TDs scheduled for earlier than that. */ - excess = (stream->next_uframe - period - next) & (mod - 1); - if (excess >= mod - 2 * SCHEDULE_SLOP) - start = next + excess - mod + period * - DIV_ROUND_UP(mod - excess, period); - else - start = next + excess + period; - if (start - now >= mod) { - ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", - urb, start - now - period, period, - mod); - status = -EFBIG; + base = ehci->last_iso_frame << 3; + next = (next - base) & (mod - 1); + start = (stream->next_uframe - base) & (mod - 1); + + /* Is the schedule already full? */ + if (unlikely(start < period)) { + ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", + urb, stream->next_uframe, base, + period, mod); + status = -ENOSPC; goto fail; } + + /* Behind the scheduling threshold? */ + if (unlikely(start < next)) { + + /* USB_ISO_ASAP: Round up to the first available slot */ + if (urb->transfer_flags & URB_ISO_ASAP) + start += (next - start + period - 1) & -period; + + /* + * Not ASAP: Use the next slot in the stream. If + * the entire URB falls before the threshold, fail. + */ + else if (start + span - period < next) { + ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n", + urb, start + base, + span - period, next + base); + status = -EXDEV; + goto fail; + } + } + + start += base; } /* need to schedule; when's the next (u)frame we could start? * this is bigger than ehci->i_thresh allows; scheduling itself - * isn't free, the slop should handle reasonably slow cpus. it + * isn't free, the delay should handle reasonably slow cpus. it * can also help high bandwidth if the dma and irq loads don't * jump until after the queue is primed. */ else { int done = 0; - start = SCHEDULE_SLOP + (now & ~0x07); - /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ + base = now & ~0x07; + start = base + SCHEDULING_DELAY; /* find a uframe slot with enough bandwidth. * Early uframes are more precious because full-speed @@ -1464,19 +1451,16 @@ iso_stream_schedule ( /* no room in the schedule */ if (!done) { - ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", - urb, now, now + mod); + ehci_dbg(ehci, "iso sched full %p", urb); status = -ENOSPC; goto fail; } } /* Tried to schedule too far into the future? */ - if (unlikely(start - now + span - period - >= mod - 2 * SCHEDULE_SLOP)) { - ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", - urb, start - now, span - period, - mod - 2 * SCHEDULE_SLOP); + if (unlikely(start - base + span - period >= mod)) { + ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", + urb, start - base, span - period, mod); status = -EFBIG; goto fail; } @@ -1490,7 +1474,7 @@ iso_stream_schedule ( /* Make sure scan_isoc() sees these */ if (ehci->isoc_count == 0) - ehci->next_frame = now >> 3; + ehci->last_iso_frame = now >> 3; return 0; fail: @@ -1708,7 +1692,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) urb->actual_length += desc->actual_length; } else { /* URB was too late */ - desc->status = -EXDEV; + urb->error_count++; } } @@ -2081,7 +2065,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) t = hc32_to_cpup(ehci, &sitd->hw_results); /* report transfer status */ - if (t & SITD_ERRS) { + if (unlikely(t & SITD_ERRS)) { urb->error_count++; if (t & SITD_STS_DBE) desc->status = usb_pipein (urb->pipe) @@ -2091,6 +2075,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) desc->status = -EOVERFLOW; else /* XACT, MMF, etc */ desc->status = -EPROTO; + } else if (unlikely(t & SITD_STS_ACTIVE)) { + /* URB was too late */ + urb->error_count++; } else { desc->status = 0; desc->actual_length = desc->length - SITD_LENGTH(t); @@ -2220,16 +2207,16 @@ static void scan_isoc(struct ehci_hcd *ehci) now_frame = (uf >> 3) & fmask; live = true; } else { - now_frame = (ehci->next_frame - 1) & fmask; + now_frame = (ehci->last_iso_frame - 1) & fmask; live = false; } ehci->now_frame = now_frame; - frame = ehci->next_frame; for (;;) { union ehci_shadow q, *q_p; __hc32 type, *hw_p; + frame = ehci->last_iso_frame; restart: /* scan each element in frame's queue for completions */ q_p = &ehci->pshadow [frame]; @@ -2334,7 +2321,6 @@ restart: /* Stop when we have reached the current frame */ if (frame == now_frame) break; - frame = (frame + 1) & fmask; + ehci->last_iso_frame = (frame + 1) & fmask; } - ehci->next_frame = now_frame; } diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index 6081e1e..0c90a24 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -21,17 +21,10 @@ struct ehci_sh_priv { static int ehci_sh_reset(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int ret; ehci->caps = hcd->regs; - ret = ehci_setup(hcd); - if (unlikely(ret)) - return ret; - - ehci_port_power(ehci, 0); - - return ret; + return ehci_setup(hcd); } static const struct hc_driver ehci_sh_hc_driver = { diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index c718a06..719ca48 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -37,18 +37,11 @@ static void spear_stop_ehci(struct spear_ehci *ehci) static int ehci_spear_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval = 0; /* registers start at offset 0x0 */ ehci->caps = hcd->regs; - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; + return ehci_setup(hcd); } static const struct hc_driver ehci_spear_hc_driver = { diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 6223d175..94ee321 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -28,7 +28,10 @@ #include <linux/pm_runtime.h> #include <linux/usb/tegra_usb_phy.h> -#include <mach/iomap.h> + +#define TEGRA_USB_BASE 0xC5000000 +#define TEGRA_USB2_BASE 0xC5004000 +#define TEGRA_USB3_BASE 0xC5008000 #define TEGRA_USB_DMA_ALIGN 32 @@ -277,7 +280,6 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd) static int tegra_ehci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; @@ -285,12 +287,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd) /* switch to host mode */ hcd->has_tt = 1; - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 1); - return retval; + return ehci_setup(hcd); } struct dma_aligned_buffer { diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index 96722bf..11695d5 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -19,22 +19,6 @@ #include <linux/of.h> #include <linux/platform_device.h> -static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int rc = 0; - - if (!udev->parent) /* udev is root hub itself, impossible */ - rc = -1; - /* we only support lpm device connected to root hub yet */ - if (ehci->has_lpm && !udev->parent->parent) { - rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); - if (!rc) - rc = ehci_lpm_check(ehci, udev->portnum); - } - return rc; -} - static const struct hc_driver vt8500_ehci_hc_driver = { .description = hcd_name, .product_desc = "VT8500 EHCI", @@ -77,14 +61,11 @@ static const struct hc_driver vt8500_ehci_hc_driver = { .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, - /* - * call back when device connected and addressed - */ - .update_device = ehci_update_device, - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32); + static int vt8500_ehci_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; @@ -95,6 +76,14 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &vt8500_ehci_dma_mask; + if (pdev->resource[1].flags != IORESOURCE_IRQ) { pr_debug("resource[1] is not IORESOURCE_IRQ"); return -ENOMEM; diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index ec59808..fdd7c48 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c @@ -13,7 +13,7 @@ #include <linux/platform_device.h> -/*ebable phy0 and phy1 for w90p910*/ +/* enable phy0 and phy1 for w90p910 */ #define ENPHY (0x01<<8) #define PHY0_CTR (0xA4) #define PHY1_CTR (0xA8) diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c deleted file mode 100644 index 8dc6a22..0000000 --- a/drivers/usb/host/ehci-xls.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * EHCI HCD for Netlogic XLS processors. - * - * (C) Copyright 2011 Netlogic Microsystems Inc. - * - * Based on various ehci-*.c drivers - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/platform_device.h> - -static int ehci_xls_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - ehci->caps = hcd->regs; - - return ehci_setup(hcd); -} - -int ehci_xls_probe_internal(const struct hc_driver *driver, - struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct resource *res; - int retval, irq; - - /* Get our IRQ from an earlier registered Platform Resource */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); - return -ENODEV; - } - - /* Get our Memory Handle */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n", - dev_name(&pdev->dev)); - return -ENODEV; - } - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) { - retval = -ENOMEM; - goto err1; - } - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - retval = -EBUSY; - goto err2; - } - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - retval = -EFAULT; - goto err3; - } - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval != 0) - goto err4; - return retval; - -err4: - iounmap(hcd->regs); -err3: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err2: - usb_put_hcd(hcd); -err1: - dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), - retval); - return retval; -} - -static struct hc_driver ehci_xls_hc_driver = { - .description = hcd_name, - .product_desc = "XLS EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY, - .reset = ehci_xls_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - .get_frame_number = ehci_get_frame, - - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int ehci_xls_probe(struct platform_device *pdev) -{ - if (usb_disabled()) - return -ENODEV; - - return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev); -} - -static int ehci_xls_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - return 0; -} - -MODULE_ALIAS("ehci-xls"); - -static struct platform_driver ehci_xls_driver = { - .probe = ehci_xls_probe, - .remove = ehci_xls_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "ehci-xls", - }, -}; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index da07d98..24a8ada 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -143,7 +143,7 @@ struct ehci_hcd { /* one per controller */ struct ehci_qh *intr_unlink_last; unsigned intr_unlink_cycle; unsigned now_frame; /* frame from HC hardware */ - unsigned next_frame; /* scan periodic, start here */ + unsigned last_iso_frame; /* last frame scanned for iso */ unsigned intr_count; /* intr activity count */ unsigned isoc_count; /* isoc activity count */ unsigned periodic_count; /* periodic activity count */ @@ -193,7 +193,6 @@ struct ehci_hcd { /* one per controller */ unsigned has_amcc_usb23:1; unsigned need_io_watchdog:1; unsigned amd_pll_fix:1; - unsigned fs_i_thresh:1; /* Intel iso scheduling */ unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ @@ -207,7 +206,6 @@ struct ehci_hcd { /* one per controller */ #define OHCI_HCCTRL_LEN 0x4 __hc32 *ohci_hcctrl_reg; unsigned has_hostpc:1; - unsigned has_lpm:1; /* support link power management */ unsigned has_ppcd:1; /* support per-port change bits */ u8 sbrn; /* packed release number */ @@ -762,26 +760,42 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_PCI - -/* For working around the MosChip frame-index-register bug */ -static unsigned ehci_read_frame_index(struct ehci_hcd *ehci); - +#define ehci_dbg(ehci, fmt, args...) \ + dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_err(ehci, fmt, args...) \ + dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_info(ehci, fmt, args...) \ + dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_warn(ehci, fmt, args...) \ + dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + +#ifdef VERBOSE_DEBUG +# define ehci_vdbg ehci_dbg #else - -static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ - return ehci_readl(ehci, &ehci->regs->frame_index); -} - + static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {} #endif -/*-------------------------------------------------------------------------*/ - #ifndef DEBUG #define STUB_DEBUG_FILES #endif /* DEBUG */ /*-------------------------------------------------------------------------*/ +/* Declarations of things exported for use by ehci platform drivers */ + +struct ehci_driver_overrides { + const char *product_desc; + size_t extra_priv_size; + int (*reset)(struct usb_hcd *hcd); +}; + +extern void ehci_init_driver(struct hc_driver *drv, + const struct ehci_driver_overrides *over); +extern int ehci_setup(struct usb_hcd *hcd); + +#ifdef CONFIG_PM +extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); +extern int ehci_resume(struct usb_hcd *hcd, bool hibernated); +#endif /* CONFIG_PM */ + #endif /* __LINUX_EHCI_HCD_H */ diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index fff114f..958379f 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -43,7 +43,6 @@ static int of_isp1760_probe(struct platform_device *dev) struct device_node *dp = dev->dev.of_node; struct resource *res; struct resource memory; - struct of_irq oirq; int virq; resource_size_t res_len; int ret; @@ -69,14 +68,12 @@ static int of_isp1760_probe(struct platform_device *dev) goto free_data; } - if (of_irq_map_one(dp, 0, &oirq)) { + virq = irq_of_parse_and_map(dp, 0); + if (!virq) { ret = -ENODEV; goto release_reg; } - virq = irq_create_of_mapping(oirq.controller, oirq.specifier, - oirq.size); - if (of_device_is_compatible(dp, "nxp,usb-isp1761")) devflags |= ISP1760_FLAG_ISP1761; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 0bf72f9..908d84a 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -705,7 +705,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) if (!clocked) at91_start_clock(); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #else diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c deleted file mode 100644 index c611699..0000000 --- a/drivers/usb/host/ohci-au1xxx.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> - * (C) Copyright 2002 Hewlett-Packard Company - * - * Bus Glue for AMD Alchemy Au1xxx - * - * Written by Christopher Hoover <ch@hpl.hp.com> - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa1111.c - * by Durgesh Pattamatta <pattamattad@sharpsec.com> - * Modified for AMD Alchemy Au1xxx - * by Matt Porter <mporter@kernel.crashing.org> - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> -#include <linux/signal.h> - -#include <asm/mach-au1x00/au1000.h> - - -extern int usb_disabled(void); - -static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci); - - if ((ret = ohci_init(ohci)) < 0) - return ret; - - if ((ret = ohci_run(ohci)) < 0) { - dev_err(hcd->self.controller, "can't start %s", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - - return 0; -} - -static const struct hc_driver ohci_au1xxx_hc_driver = { - .description = hcd_name, - .product_desc = "Au1xxx OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_au1xxx_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) -{ - int ret, unit; - struct usb_hcd *hcd; - - if (usb_disabled()) - return -ENODEV; - - if (pdev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug("resource[1] is not IORESOURCE_IRQ\n"); - return -ENOMEM; - } - - hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx"); - if (!hcd) - return -ENOMEM; - - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed\n"); - ret = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("ioremap failed\n"); - ret = -ENOMEM; - goto err2; - } - - unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ? - ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0; - if (alchemy_usb_control(unit, 1)) { - printk(KERN_INFO "%s: controller init failed!\n", pdev->name); - ret = -ENODEV; - goto err3; - } - - ohci_hcd_init(hcd_to_ohci(hcd)); - - ret = usb_add_hcd(hcd, pdev->resource[1].start, - IRQF_SHARED); - if (ret == 0) { - platform_set_drvdata(pdev, hcd); - return ret; - } - - alchemy_usb_control(unit, 0); -err3: - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: - usb_put_hcd(hcd); - return ret; -} - -static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - int unit; - - unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ? - ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0; - usb_remove_hcd(hcd); - alchemy_usb_control(unit, 0); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -#ifdef CONFIG_PM -static int ohci_hcd_au1xxx_drv_suspend(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - unsigned long flags; - int rc; - - rc = 0; - - /* Root hub was already suspended. Disable irq emission and - * mark HW unaccessible, bail out if RH has been resumed. Use - * the spinlock to properly synchronize with possible pending - * RH suspend or resume activity. - */ - spin_lock_irqsave(&ohci->lock, flags); - if (ohci->rh_state != OHCI_RH_SUSPENDED) { - rc = -EINVAL; - goto bail; - } - ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); - (void)ohci_readl(ohci, &ohci->regs->intrdisable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - alchemy_usb_control(ALCHEMY_USB_OHCI0, 0); -bail: - spin_unlock_irqrestore(&ohci->lock, flags); - - return rc; -} - -static int ohci_hcd_au1xxx_drv_resume(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - - alchemy_usb_control(ALCHEMY_USB_OHCI0, 1); - - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - ohci_finish_controller_resume(hcd); - - return 0; -} - -static const struct dev_pm_ops au1xxx_ohci_pmops = { - .suspend = ohci_hcd_au1xxx_drv_suspend, - .resume = ohci_hcd_au1xxx_drv_resume, -}; - -#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops - -#else -#define AU1XXX_OHCI_PMOPS NULL -#endif - -static struct platform_driver ohci_hcd_au1xxx_driver = { - .probe = ohci_hcd_au1xxx_drv_probe, - .remove = ohci_hcd_au1xxx_drv_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "au1xxx-ohci", - .owner = THIS_MODULE, - .pm = AU1XXX_OHCI_PMOPS, - }, -}; - -MODULE_ALIAS("platform:au1xxx-ohci"); diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c deleted file mode 100644 index 2c9f233..0000000 --- a/drivers/usb/host/ohci-cns3xxx.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2008 Cavium Networks - * - * This file 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. - */ - -#include <linux/platform_device.h> -#include <linux/atomic.h> -#include <mach/cns3xxx.h> -#include <mach/pm.h> - -static int __devinit -cns3xxx_ohci_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - /* - * EHCI and OHCI share the same clock and power, - * resetting twice would cause the 1st controller been reset. - * Therefore only do power up at the first up device, and - * power down at the last down device. - * - * Set USB AHB INCR length to 16 - */ - if (atomic_inc_return(&usb_pwr_ref) == 1) { - cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB); - cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); - cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST); - __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)), - MISC_CHIP_CONFIG_REG); - } - - ret = ohci_init(ohci); - if (ret < 0) - return ret; - - ohci->num_ports = 1; - - ret = ohci_run(ohci); - if (ret < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - return 0; -} - -static const struct hc_driver cns3xxx_ohci_hc_driver = { - .description = hcd_name, - .product_desc = "CNS3XXX OHCI Host controller", - .hcd_priv_size = sizeof(struct ohci_hcd), - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - .start = cns3xxx_ohci_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - .get_frame_number = ohci_get_frame, - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -static int cns3xxx_ohci_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct usb_hcd *hcd; - const struct hc_driver *driver = &cns3xxx_ohci_hc_driver; - struct resource *res; - int irq; - int retval; - - if (usb_disabled()) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "Found HC with no IRQ.\n"); - return -ENODEV; - } - irq = res->start; - - hcd = usb_create_hcd(driver, dev, dev_name(dev)); - if (!hcd) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "Found HC with no register addr.\n"); - retval = -ENODEV; - goto err1; - } - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(dev, "controller already in use\n"); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - dev_dbg(dev, "error mapping memory\n"); - retval = -EFAULT; - goto err2; - } - - ohci_hcd_init(hcd_to_ohci(hcd)); - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval == 0) - return retval; - - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: - usb_put_hcd(hcd); - return retval; -} - -static int cns3xxx_ohci_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - - /* - * EHCI and OHCI share the same clock and power, - * resetting twice would cause the 1st controller been reset. - * Therefore only do power up at the first up device, and - * power down at the last down device. - */ - if (atomic_dec_return(&usb_pwr_ref) == 0) - cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); - - usb_put_hcd(hcd); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -MODULE_ALIAS("platform:cns3xxx-ohci"); - -static struct platform_driver ohci_hcd_cns3xxx_driver = { - .probe = cns3xxx_ohci_probe, - .remove = cns3xxx_ohci_remove, - .driver = { - .name = "cns3xxx-ohci", - }, -}; diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index dbfbd1d..a982f04 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -194,7 +194,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) ep93xx_start_hc(&pdev->dev); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #endif diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 20a5008..6a30fc5 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -23,6 +23,11 @@ struct exynos_ohci_hcd { struct clk *clk; }; +static int ohci_exynos_reset(struct usb_hcd *hcd) +{ + return ohci_init(hcd_to_ohci(hcd)); +} + static int ohci_exynos_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -30,10 +35,6 @@ static int ohci_exynos_start(struct usb_hcd *hcd) ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); - ret = ohci_init(ohci); - if (ret < 0) - return ret; - ret = ohci_run(ohci); if (ret < 0) { dev_err(hcd->self.controller, "can't start %s\n", @@ -53,6 +54,7 @@ static const struct hc_driver exynos_ohci_hc_driver = { .irq = ohci_irq, .flags = HCD_MEMORY|HCD_USB11, + .reset = ohci_exynos_reset, .start = ohci_exynos_start, .stop = ohci_stop, .shutdown = ohci_shutdown, @@ -115,7 +117,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) } exynos_ohci->hcd = hcd; - exynos_ohci->clk = clk_get(&pdev->dev, "usbhost"); + exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); if (IS_ERR(exynos_ohci->clk)) { dev_err(&pdev->dev, "Failed to get usbhost clock\n"); @@ -123,9 +125,9 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) goto fail_clk; } - err = clk_enable(exynos_ohci->clk); + err = clk_prepare_enable(exynos_ohci->clk); if (err) - goto fail_clken; + goto fail_clk; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -167,9 +169,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) return 0; fail_io: - clk_disable(exynos_ohci->clk); -fail_clken: - clk_put(exynos_ohci->clk); + clk_disable_unprepare(exynos_ohci->clk); fail_clk: usb_put_hcd(hcd); return err; @@ -186,8 +186,7 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); - clk_disable(exynos_ohci->clk); - clk_put(exynos_ohci->clk); + clk_disable_unprepare(exynos_ohci->clk); usb_put_hcd(hcd); @@ -232,7 +231,7 @@ static int exynos_ohci_suspend(struct device *dev) if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); - clk_disable(exynos_ohci->clk); + clk_disable_unprepare(exynos_ohci->clk); fail: spin_unlock_irqrestore(&ohci->lock, flags); @@ -247,15 +246,12 @@ static int exynos_ohci_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; - clk_enable(exynos_ohci->clk); + clk_prepare_enable(exynos_ohci->clk); if (pdata && pdata->phy_init) pdata->phy_init(pdev, S5P_USB_PHY_HOST); - /* Mark hardware accessible again as we are out of D3 state by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 4a1d64d..180a2b0 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -231,13 +231,41 @@ static int ohci_urb_enqueue ( frame &= ~(ed->interval - 1); frame |= ed->branch; urb->start_frame = frame; + } + } else if (ed->type == PIPE_ISOCHRONOUS) { + u16 next = ohci_frame_no(ohci) + 2; + u16 frame = ed->last_iso + ed->interval; + + /* Behind the scheduling threshold? */ + if (unlikely(tick_before(frame, next))) { - /* yes, only URB_ISO_ASAP is supported, and - * urb->start_frame is never used as input. + /* USB_ISO_ASAP: Round up to the first available slot */ + if (urb->transfer_flags & URB_ISO_ASAP) + frame += (next - frame + ed->interval - 1) & + -ed->interval; + + /* + * Not ASAP: Use the next slot in the stream. If + * the entire URB falls before the threshold, fail. */ + else if (tick_before(frame + ed->interval * + (urb->number_of_packets - 1), next)) { + retval = -EXDEV; + usb_hcd_unlink_urb_from_ep(hcd, urb); + goto fail; + } + + /* + * Some OHCI hardware doesn't handle late TDs + * correctly. After retiring them it proceeds to + * the next ED instead of the next TD. Therefore + * we have to omit the late TDs entirely. + */ + urb_priv->td_cnt = DIV_ROUND_UP(next - frame, + ed->interval); } - } else if (ed->type == PIPE_ISOCHRONOUS) - urb->start_frame = ed->last_iso + ed->interval; + urb->start_frame = frame; + } /* fill the TDs and link them to the ed; and * enable that part of the schedule, if needed @@ -983,6 +1011,79 @@ static int ohci_restart (struct ohci_hcd *ohci) #endif +#ifdef CONFIG_PM + +static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + + /* Disable irq emission and mark HW unaccessible. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + */ + spin_lock_irqsave (&ohci->lock, flags); + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + (void)ohci_readl(ohci, &ohci->regs->intrdisable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + spin_unlock_irqrestore (&ohci->lock, flags); + + return 0; +} + + +static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int port; + bool need_reinit = false; + + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + /* Make sure resume from hibernation re-enumerates everything */ + if (hibernated) + ohci_usb_reset(ohci); + + /* See if the controller is already running or has been reset */ + ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); + if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { + need_reinit = true; + } else { + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: + case OHCI_USB_RESET: + need_reinit = true; + } + } + + /* If needed, reinitialize and suspend the root hub */ + if (need_reinit) { + spin_lock_irq(&ohci->lock); + ohci_rh_resume(ohci); + ohci_rh_suspend(ohci, 0); + spin_unlock_irq(&ohci->lock); + } + + /* Normally just turn on port power and enable interrupts */ + else { + ohci_dbg(ohci, "powerup ports\n"); + for (port = 0; port < ohci->num_ports; port++) + ohci_writel(ohci, RH_PS_PPS, + &ohci->regs->roothub.portstatus[port]); + + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); + ohci_readl(ohci, &ohci->regs->intrenable); + msleep(20); + } + + usb_hcd_resume_root_hub(hcd); + + return 0; +} + +#endif + /*-------------------------------------------------------------------------*/ MODULE_AUTHOR (DRIVER_AUTHOR); @@ -1029,21 +1130,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_ep93xx_driver #endif -#ifdef CONFIG_MIPS_ALCHEMY -#include "ohci-au1xxx.c" -#define PLATFORM_DRIVER ohci_hcd_au1xxx_driver -#endif - -#ifdef CONFIG_PNX8550 -#include "ohci-pnx8550.c" -#define PLATFORM_DRIVER ohci_hcd_pnx8550_driver -#endif - -#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC -#include "ohci-ppc-soc.c" -#define PLATFORM_DRIVER ohci_hcd_ppc_soc_driver -#endif - #ifdef CONFIG_ARCH_AT91 #include "ohci-at91.c" #define PLATFORM_DRIVER ohci_hcd_at91_driver @@ -1059,11 +1145,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_da8xx_driver #endif -#ifdef CONFIG_USB_OHCI_SH -#include "ohci-sh.c" -#define PLATFORM_DRIVER ohci_hcd_sh_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_PPC_OF #include "ohci-ppc-of.c" @@ -1105,16 +1186,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_tilegx_driver #endif -#ifdef CONFIG_USB_CNS3XXX_OHCI -#include "ohci-cns3xxx.c" -#define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver -#endif - -#ifdef CONFIG_CPU_XLR -#include "ohci-xls.c" -#define PLATFORM_DRIVER ohci_xls_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_PLATFORM #include "ohci-platform.c" #define PLATFORM_DRIVER ohci_platform_driver diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 2f3619e..db09dae 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -316,48 +316,6 @@ static int ohci_bus_resume (struct usb_hcd *hcd) return rc; } -/* Carry out the final steps of resuming the controller device */ -static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int port; - bool need_reinit = false; - - /* See if the controller is already running or has been reset */ - ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); - if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { - need_reinit = true; - } else { - switch (ohci->hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_OPER: - case OHCI_USB_RESET: - need_reinit = true; - } - } - - /* If needed, reinitialize and suspend the root hub */ - if (need_reinit) { - spin_lock_irq(&ohci->lock); - ohci_rh_resume(ohci); - ohci_rh_suspend(ohci, 0); - spin_unlock_irq(&ohci->lock); - } - - /* Normally just turn on port power and enable interrupts */ - else { - ohci_dbg(ohci, "powerup ports\n"); - for (port = 0; port < ohci->num_ports; port++) - ohci_writel(ohci, RH_PS_PPS, - &ohci->regs->roothub.portstatus[port]); - - ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); - ohci_readl(ohci, &ohci->regs->intrenable); - msleep(20); - } - - usb_hcd_resume_root_hub(hcd); -} - /* Carry out polling-, autostop-, and autoresume-related state changes */ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected, int rhsc_status) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 4531d03..733c77c 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -530,7 +530,7 @@ static int ohci_omap_resume(struct platform_device *dev) ohci->next_statechange = jiffies; omap_ohci_clock_power(1); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 1843bb6..6afa7dc 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -296,49 +296,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) return ret; } -#ifdef CONFIG_PM - -static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - unsigned long flags; - int rc = 0; - - /* Root hub was already suspended. Disable irq emission and - * mark HW unaccessible, bail out if RH has been resumed. Use - * the spinlock to properly synchronize with possible pending - * RH suspend or resume activity. - */ - spin_lock_irqsave (&ohci->lock, flags); - if (ohci->rh_state != OHCI_RH_SUSPENDED) { - rc = -EINVAL; - goto bail; - } - ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); - (void)ohci_readl(ohci, &ohci->regs->intrdisable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - bail: - spin_unlock_irqrestore (&ohci->lock, flags); - - return rc; -} - - -static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated) -{ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* Make sure resume from hibernation re-enumerates everything */ - if (hibernated) - ohci_usb_reset(hcd_to_ohci(hcd)); - - ohci_finish_controller_resume(hcd); - return 0; -} - -#endif /* CONFIG_PM */ - /*-------------------------------------------------------------------------*/ @@ -362,8 +319,8 @@ static const struct hc_driver ohci_pci_hc_driver = { .shutdown = ohci_shutdown, #ifdef CONFIG_PM - .pci_suspend = ohci_pci_suspend, - .pci_resume = ohci_pci_resume, + .pci_suspend = ohci_suspend, + .pci_resume = ohci_resume, #endif /* diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index e24ec9f..bda4e0b 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -31,6 +31,10 @@ static int ohci_platform_reset(struct usb_hcd *hcd) ohci->flags |= OHCI_QUIRK_FRAME_NO; ohci_hcd_init(ohci); + + if (pdata->num_ports) + ohci->num_ports = pdata->num_ports; + err = ohci_init(ohci); return err; @@ -97,13 +101,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev) irq = platform_get_irq(dev, 0); if (irq < 0) { - pr_err("no irq provided"); + dev_err(&dev->dev, "no irq provided"); return irq; } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { - pr_err("no memory recourse provided"); + dev_err(&dev->dev, "no memory resource provided"); return -ENXIO; } @@ -123,29 +127,19 @@ static int __devinit ohci_platform_probe(struct platform_device *dev) hcd->rsrc_start = res_mem->start; hcd->rsrc_len = resource_size(res_mem); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_err("controller already in use"); - err = -EBUSY; - goto err_put_hcd; - } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem); if (!hcd->regs) { err = -ENOMEM; - goto err_release_region; + goto err_put_hcd; } err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) - goto err_iounmap; + goto err_put_hcd; platform_set_drvdata(dev, hcd); return err; -err_iounmap: - iounmap(hcd->regs); -err_release_region: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put_hcd: usb_put_hcd(hcd); err_power: @@ -161,8 +155,6 @@ static int __devexit ohci_platform_remove(struct platform_device *dev) struct usb_ohci_pdata *pdata = dev->dev.platform_data; usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(dev, NULL); @@ -199,7 +191,7 @@ static int ohci_platform_resume(struct device *dev) return err; } - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c deleted file mode 100644 index 148d27d..0000000 --- a/drivers/usb/host/ohci-pnx8550.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> - * (C) Copyright 2002 Hewlett-Packard Company - * (C) Copyright 2005 Embedded Alley Solutions, Inc. - * - * Bus Glue for PNX8550 - * - * Written by Christopher Hoover <ch@hpl.hp.com> - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa1111.c - * by Durgesh Pattamatta <pattamattad@sharpsec.com> - * - * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c - * by Vitaly Wool <vitalywool@gmail.com> - * - * This file is licenced under the GPL. - */ - -#include <linux/device.h> -#include <linux/platform_device.h> -#include <asm/mach-pnx8550/usb.h> -#include <asm/mach-pnx8550/int.h> -#include <asm/mach-pnx8550/pci.h> - -#ifndef CONFIG_PNX8550 -#error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined." -#endif - -extern int usb_disabled(void); - -/*-------------------------------------------------------------------------*/ - -static void pnx8550_start_hc(struct platform_device *dev) -{ - /* - * Set register CLK48CTL to enable and 48MHz - */ - outl(0x00000003, PCI_BASE | 0x0004770c); - - /* - * Set register CLK12CTL to enable and 48MHz - */ - outl(0x00000003, PCI_BASE | 0x00047710); - - udelay(100); -} - -static void pnx8550_stop_hc(struct platform_device *dev) -{ - udelay(10); -} - - -/*-------------------------------------------------------------------------*/ - -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - - -/** - * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - * - */ -int usb_hcd_pnx8550_probe (const struct hc_driver *driver, - struct platform_device *dev) -{ - int retval; - struct usb_hcd *hcd; - - if (dev->resource[0].flags != IORESOURCE_MEM || - dev->resource[1].flags != IORESOURCE_IRQ) { - dev_err (&dev->dev,"invalid resource type\n"); - return -ENOMEM; - } - - hcd = usb_create_hcd (driver, &dev->dev, "pnx8550"); - if (!hcd) - return -ENOMEM; - hcd->rsrc_start = dev->resource[0].start; - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] " - "failed\n", hcd->rsrc_start, hcd->rsrc_len); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n", - hcd->rsrc_start, hcd->rsrc_len); - retval = -ENOMEM; - goto err2; - } - - pnx8550_start_hc(dev); - - ohci_hcd_init(hcd_to_ohci(hcd)); - - retval = usb_add_hcd(hcd, dev->resource[1].start, 0); - if (retval == 0) - return retval; - - pnx8550_stop_hc(dev); - iounmap(hcd->regs); - err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - err1: - usb_put_hcd(hcd); - return retval; -} - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev) -{ - usb_remove_hcd(hcd); - pnx8550_stop_hc(dev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -} - -/*-------------------------------------------------------------------------*/ - -static int __devinit -ohci_pnx8550_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci); - - if ((ret = ohci_init(ohci)) < 0) - return ret; - - if ((ret = ohci_run (ohci)) < 0) { - dev_err(hcd->self.controller, "can't start %s", - hcd->self.bus_name); - ohci_stop (hcd); - return ret; - } - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ohci_pnx8550_hc_driver = { - .description = hcd_name, - .product_desc = "PNX8550 OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_pnx8550_start, - .stop = ohci_stop, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -/*-------------------------------------------------------------------------*/ - -static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev) -{ - int ret; - - if (usb_disabled()) - return -ENODEV; - - ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev); - return ret; -} - -static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_hcd_pnx8550_remove(hcd, pdev); - return 0; -} - -MODULE_ALIAS("platform:pnx8550-ohci"); - -static struct platform_driver ohci_hcd_pnx8550_driver = { - .driver = { - .name = "pnx8550-ohci", - .owner = THIS_MODULE, - }, - .probe = ohci_hcd_pnx8550_drv_probe, - .remove = ohci_hcd_pnx8550_drv_remove, -}; - diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c deleted file mode 100644 index 185c39e..0000000 --- a/drivers/usb/host/ohci-ppc-soc.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> - * (C) Copyright 2002 Hewlett-Packard Company - * (C) Copyright 2003-2005 MontaVista Software Inc. - * - * Bus Glue for PPC On-Chip OHCI driver - * Tested on Freescale MPC5200 and IBM STB04xxx - * - * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> -#include <linux/signal.h> - -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - -/** - * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller. - * - * Store this function in the HCD's struct pci_driver as probe(). - */ -static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, - struct platform_device *pdev) -{ - int retval; - struct usb_hcd *hcd; - struct ohci_hcd *ohci; - struct resource *res; - int irq; - - pr_debug("initializing PPC-SOC USB Controller\n"); - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - pr_debug("%s: no irq\n", __FILE__); - return -ENODEV; - } - irq = res->start; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - pr_debug("%s: no reg addr\n", __FILE__); - return -ENODEV; - } - - hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB"); - if (!hcd) - return -ENOMEM; - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("%s: request_mem_region failed\n", __FILE__); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("%s: ioremap failed\n", __FILE__); - retval = -ENOMEM; - goto err2; - } - - ohci = hcd_to_ohci(hcd); - ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; - -#ifdef CONFIG_PPC_MPC52xx - /* MPC52xx doesn't need frame_no shift */ - ohci->flags |= OHCI_QUIRK_FRAME_NO; -#endif - ohci_hcd_init(ohci); - - retval = usb_add_hcd(hcd, irq, 0); - if (retval == 0) - return retval; - - pr_debug("Removing PPC-SOC USB Controller\n"); - - iounmap(hcd->regs); - err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - err1: - usb_put_hcd(hcd); - return retval; -} - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs - * @pdev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_ppc_soc_probe(). - * It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd, - struct platform_device *pdev) -{ - usb_remove_hcd(hcd); - - pr_debug("stopping PPC-SOC USB Controller\n"); - - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -} - -static int __devinit -ohci_ppc_soc_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - if ((ret = ohci_init(ohci)) < 0) - return ret; - - if ((ret = ohci_run(ohci)) < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - - return 0; -} - -static const struct hc_driver ohci_ppc_soc_hc_driver = { - .description = hcd_name, - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_ppc_soc_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) -{ - int ret; - - if (usb_disabled()) - return -ENODEV; - - ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev); - return ret; -} - -static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_hcd_ppc_soc_remove(hcd, pdev); - return 0; -} - -static struct platform_driver ohci_hcd_ppc_soc_driver = { - .probe = ohci_hcd_ppc_soc_drv_probe, - .remove = ohci_hcd_ppc_soc_drv_remove, - .shutdown = usb_hcd_platform_shutdown, -#ifdef CONFIG_PM - /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ - /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ -#endif - .driver = { - .name = "ppc-soc-ohci", - .owner = THIS_MODULE, - }, -}; - -MODULE_ALIAS("platform:ppc-soc-ohci"); diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 2bf1144..156d289 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -591,7 +591,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev) /* Select Power Management Mode */ pxa27x_ohci_select_pmm(ohci, inf->port_mode); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index c5a1ea9..177a213 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -596,7 +596,6 @@ static void td_submit_urb ( urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C); } - urb_priv->td_cnt = 0; list_add (&urb_priv->pending, &ohci->pending); if (data_len) @@ -672,7 +671,8 @@ static void td_submit_urb ( * we could often reduce the number of TDs here. */ case PIPE_ISOCHRONOUS: - for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets; + cnt++) { int frame = urb->start_frame; // FIXME scheduling should handle frame counter diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 0d2309c..e84190f 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -323,8 +323,6 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev) { usb_remove_hcd(hcd); s3c2410_stop_hc(dev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); } @@ -353,35 +351,29 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, hcd->rsrc_start = dev->resource[0].start; hcd->rsrc_len = resource_size(&dev->resource[0]); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dev_err(&dev->dev, "request_mem_region failed\n"); - retval = -EBUSY; + hcd->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]); + if (!hcd->regs) { + dev_err(&dev->dev, "devm_request_and_ioremap failed\n"); + retval = -ENOMEM; goto err_put; } - clk = clk_get(&dev->dev, "usb-host"); + clk = devm_clk_get(&dev->dev, "usb-host"); if (IS_ERR(clk)) { dev_err(&dev->dev, "cannot get usb-host clock\n"); retval = PTR_ERR(clk); - goto err_mem; + goto err_put; } - usb_clk = clk_get(&dev->dev, "usb-bus-host"); + usb_clk = devm_clk_get(&dev->dev, "usb-bus-host"); if (IS_ERR(usb_clk)) { dev_err(&dev->dev, "cannot get usb-bus-host clock\n"); retval = PTR_ERR(usb_clk); - goto err_clk; + goto err_put; } s3c2410_start_hc(dev, hcd); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - dev_err(&dev->dev, "ioremap failed\n"); - retval = -ENOMEM; - goto err_ioremap; - } - ohci_hcd_init(hcd_to_ohci(hcd)); retval = usb_add_hcd(hcd, dev->resource[1].start, 0); @@ -392,14 +384,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, err_ioremap: s3c2410_stop_hc(dev); - iounmap(hcd->regs); - clk_put(usb_clk); - - err_clk: - clk_put(clk); - - err_mem: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put: usb_put_hcd(hcd); @@ -524,8 +508,7 @@ static int ohci_hcd_s3c2410_drv_resume(struct device *dev) s3c2410_start_hc(pdev, hcd); - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c deleted file mode 100644 index 76a20c2..0000000 --- a/drivers/usb/host/ohci-sh.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * Copyright (C) 2008 Renesas Solutions Corp. - * - * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include <linux/platform_device.h> - -static int ohci_sh_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - - ohci_hcd_init(ohci); - ohci_init(ohci); - ohci_run(ohci); - return 0; -} - -static const struct hc_driver ohci_sh_hc_driver = { - .description = hcd_name, - .product_desc = "SuperH OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_sh_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -/*-------------------------------------------------------------------------*/ - -static int ohci_hcd_sh_probe(struct platform_device *pdev) -{ - struct resource *res = NULL; - struct usb_hcd *hcd = NULL; - int irq = -1; - int ret; - - if (usb_disabled()) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "platform_get_resource error.\n"); - return -ENODEV; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "platform_get_irq error.\n"); - return -ENODEV; - } - - /* initialize hcd */ - hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name); - if (!hcd) { - dev_err(&pdev->dev, "Failed to create hcd\n"); - return -ENOMEM; - } - - hcd->regs = (void __iomem *)res->start; - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to add hcd\n"); - usb_put_hcd(hcd); - return ret; - } - - return ret; -} - -static int ohci_hcd_sh_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - - return 0; -} - -static struct platform_driver ohci_hcd_sh_driver = { - .probe = ohci_hcd_sh_probe, - .remove = ohci_hcd_sh_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "sh_ohci", - .owner = THIS_MODULE, - }, -}; - -MODULE_ALIAS("platform:sh_ohci"); diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 5596ac2..3b5b908 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -238,7 +238,7 @@ static int ohci_sm501_resume(struct platform_device *pdev) ohci->next_statechange = jiffies; sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #else diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index fc7305e..d607be3 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -231,7 +231,7 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev) ohci->next_statechange = jiffies; spear_start_ohci(ohci_p); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #endif diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index 60c2b07..2c9ab8f 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -352,7 +352,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev) spin_unlock_irqrestore(&tmio->lock, flags); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c deleted file mode 100644 index 84201cd..0000000 --- a/drivers/usb/host/ohci-xls.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * OHCI HCD for Netlogic XLS processors. - * - * (C) Copyright 2011 Netlogic Microsystems Inc. - * - * Based on ohci-au1xxx.c, and other Linux OHCI drivers. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/platform_device.h> -#include <linux/signal.h> - -static int ohci_xls_probe_internal(const struct hc_driver *driver, - struct platform_device *dev) -{ - struct resource *res; - struct usb_hcd *hcd; - int retval, irq; - - /* Get our IRQ from an earlier registered Platform Resource */ - irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "Found HC with no IRQ\n"); - return -ENODEV; - } - - /* Get our Memory Handle */ - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&dev->dev, "MMIO Handle incorrect!\n"); - return -ENODEV; - } - - hcd = usb_create_hcd(driver, &dev->dev, "XLS"); - if (!hcd) { - retval = -ENOMEM; - goto err1; - } - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&dev->dev, "Controller already in use\n"); - retval = -EBUSY; - goto err2; - } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - dev_dbg(&dev->dev, "error mapping memory\n"); - retval = -EFAULT; - goto err3; - } - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval != 0) - goto err4; - return retval; - -err4: - iounmap(hcd->regs); -err3: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err2: - usb_put_hcd(hcd); -err1: - dev_err(&dev->dev, "init fail, %d\n", retval); - return retval; -} - -static int ohci_xls_reset(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - - ohci_hcd_init(ohci); - return ohci_init(ohci); -} - -static int __devinit ohci_xls_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci; - int ret; - - ohci = hcd_to_ohci(hcd); - ret = ohci_run(ohci); - if (ret < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - return 0; -} - -static struct hc_driver ohci_xls_hc_driver = { - .description = hcd_name, - .product_desc = "XLS OHCI Host Controller", - .hcd_priv_size = sizeof(struct ohci_hcd), - .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_USB11, - .reset = ohci_xls_reset, - .start = ohci_xls_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - .get_frame_number = ohci_get_frame, - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -static int ohci_xls_probe(struct platform_device *dev) -{ - int ret; - - pr_debug("In ohci_xls_probe"); - if (usb_disabled()) - return -ENODEV; - ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev); - return ret; -} - -static int ohci_xls_remove(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - return 0; -} - -static struct platform_driver ohci_xls_driver = { - .probe = ohci_xls_probe, - .remove = ohci_xls_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "ohci-xls-0", - .owner = THIS_MODULE, - }, -}; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 966d148..39f9e4a 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { /* Pegatron Lucid (Ordissimo AIRIS) */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), + }, + }, + { + /* Pegatron Lucid (Ordissimo) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, { } diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index fcc09e5..b3eea0b 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2036,10 +2036,8 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map) udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB) map[udev->devnum/32] |= (1 << (udev->devnum % 32)); - usb_hub_for_each_child(udev, chix, childdev) { - if (childdev) - collect_usb_address_map(childdev, map); - } + usb_hub_for_each_child(udev, chix, childdev) + collect_usb_address_map(childdev, map); } /* this function must be called with interrupt disabled */ diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index e478049..68ebf20 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -60,6 +60,7 @@ static const struct hc_driver uhci_platform_hc_driver = { .hub_control = uhci_hub_control, }; +static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32); static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) { @@ -71,6 +72,14 @@ static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &platform_uhci_dma_mask; + hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev, pdev->name); if (!hcd) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index d2c6f5a..15921fd 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, struct uhci_qh *qh) { struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ - int i, frame; + int i; + unsigned frame, next; unsigned long destination, status; struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; @@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, urb->number_of_packets >= UHCI_NUMFRAMES) return -EFBIG; + uhci_get_current_frame_number(uhci); + /* Check the period and figure out the starting frame number */ if (!qh->bandwidth_reserved) { qh->period = urb->interval; - if (urb->transfer_flags & URB_ISO_ASAP) { - qh->phase = -1; /* Find the best phase */ - i = uhci_check_bandwidth(uhci, qh); - if (i) - return i; - - /* Allow a little time to allocate the TDs */ - uhci_get_current_frame_number(uhci); - frame = uhci->frame_number + 10; - - /* Move forward to the first frame having the - * correct phase */ - urb->start_frame = frame + ((qh->phase - frame) & - (qh->period - 1)); - } else { - i = urb->start_frame - uhci->last_iso_frame; - if (i <= 0 || i >= UHCI_NUMFRAMES) - return -EINVAL; - qh->phase = urb->start_frame & (qh->period - 1); - i = uhci_check_bandwidth(uhci, qh); - if (i) - return i; - } + qh->phase = -1; /* Find the best phase */ + i = uhci_check_bandwidth(uhci, qh); + if (i) + return i; + + /* Allow a little time to allocate the TDs */ + next = uhci->frame_number + 10; + frame = qh->phase; + + /* Round up to the first available slot */ + frame += (next - frame + qh->period - 1) & -qh->period; } else if (qh->period != urb->interval) { return -EINVAL; /* Can't change the period */ } else { + next = uhci->frame_number + 2; + /* Find the next unused frame */ if (list_empty(&qh->queue)) { frame = qh->iso_frame; @@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, lurb->number_of_packets * lurb->interval; } - if (urb->transfer_flags & URB_ISO_ASAP) { - /* Skip some frames if necessary to insure - * the start frame is in the future. + + /* Fell behind? */ + if (uhci_frame_before_eq(frame, next)) { + + /* USB_ISO_ASAP: Round up to the first available slot */ + if (urb->transfer_flags & URB_ISO_ASAP) + frame += (next - frame + qh->period - 1) & + -qh->period; + + /* + * Not ASAP: Use the next slot in the stream. If + * the entire URB falls before the threshold, fail. */ - uhci_get_current_frame_number(uhci); - if (uhci_frame_before_eq(frame, uhci->frame_number)) { - frame = uhci->frame_number + 1; - frame += ((qh->phase - frame) & - (qh->period - 1)); - } - } /* Otherwise pick up where the last URB leaves off */ - urb->start_frame = frame; + else if (!uhci_frame_before_eq(next, + frame + (urb->number_of_packets - 1) * + qh->period)) + return -EXDEV; + } } /* Make sure we won't have to go too far into the future */ if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES, - urb->start_frame + urb->number_of_packets * - urb->interval)) + frame + urb->number_of_packets * urb->interval)) return -EFBIG; + urb->start_frame = frame; status = TD_CTRL_ACTIVE | TD_CTRL_IOS; destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 4b436f5..5f3a7c7 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, int i; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; - struct xhci_slot_ctx *slot_ctx; dma_addr_t dma = ctx->dma; int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); @@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); } - slot_ctx = xhci_get_slot_ctx(xhci, ctx); xhci_dbg_slot_ctx(xhci, ctx); xhci_dbg_ep_ctx(xhci, ctx, last_ep); } diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index aa90ad4..a686cf4 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, if (portsc & PORT_DEV_REMOVE) port_removable |= 1 << (i + 1); } - memset(&desc->u.ss.DeviceRemovable, - (__force __u16) cpu_to_le16(port_removable), - sizeof(__u16)); + + desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); } static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, @@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); + spin_unlock_irqrestore(&xhci->lock, flags); temp = usb_acpi_power_manageable(hcd->self.root_hub, wIndex); if (temp) usb_acpi_set_power_state(hcd->self.root_hub, wIndex, true); + spin_lock_irqsave(&xhci->lock, flags); break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); @@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_writel(xhci, temp & ~PORT_POWER, port_array[wIndex]); + spin_unlock_irqrestore(&xhci->lock, flags); temp = usb_acpi_power_manageable(hcd->self.root_hub, wIndex); if (temp) usb_acpi_set_power_state(hcd->self.root_hub, wIndex, false); + spin_lock_irqsave(&xhci->lock, flags); break; default: goto error; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c6ebb17..4e1a894 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, xhci->cmd_ring->dequeue, &cycle_state); + if (!cur_seg) { + xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", + xhci->cmd_ring->dequeue, + (unsigned long long) + xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, + xhci->cmd_ring->dequeue)); + xhci_debug_ring(xhci, xhci->cmd_ring); + xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); + return; + } + /* find the command trb matched by cd from command ring */ for (cmd_trb = xhci->cmd_ring->dequeue; cmd_trb != xhci->cmd_ring->enqueue; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8d7fcbb..c9e419f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -479,7 +479,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) if (strstr(dmi_product_name, "Z420") || strstr(dmi_product_name, "Z620") || - strstr(dmi_product_name, "Z820")) + strstr(dmi_product_name, "Z820") || + strstr(dmi_product_name, "Z1")) return true; return false; @@ -1626,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct xhci_hcd *xhci; struct xhci_container_ctx *in_ctx, *out_ctx; unsigned int ep_index; - struct xhci_ep_ctx *ep_ctx; struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u32 added_ctxs; @@ -1662,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, out_ctx = virt_dev->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); /* If this endpoint is already in use, and the upper layers are trying * to add it again without dropping it, reject the addition. @@ -1816,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, case COMP_EBADSLT: dev_warn(&udev->dev, "WARN: slot not enabled for" "evaluate context command.\n"); + ret = -EINVAL; + break; case COMP_CTX_STATE: dev_warn(&udev->dev, "WARN: invalid context state for " "evaluate context command.\n"); @@ -4020,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) static unsigned long long xhci_service_interval_to_ns( struct usb_endpoint_descriptor *desc) { - return (1 << (desc->bInterval - 1)) * 125 * 1000; + return (1ULL << (desc->bInterval - 1)) * 125 * 1000; } static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, @@ -4141,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev, (xhci_service_interval_to_ns(desc) > timeout_ns)) timeout_ns = xhci_service_interval_to_ns(desc); - u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000; + u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL; if (u2_del_ns > timeout_ns) timeout_ns = u2_del_ns; diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c index 4223d76..e712afe 100644 --- a/drivers/usb/misc/ezusb.c +++ b/drivers/usb/misc/ezusb.c @@ -15,6 +15,7 @@ #include <linux/usb.h> #include <linux/firmware.h> #include <linux/ihex.h> +#include <linux/usb/ezusb.h> struct ezusb_fx_type { /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ @@ -22,21 +23,16 @@ struct ezusb_fx_type { unsigned short max_internal_adress; }; -struct ezusb_fx_type ezusb_fx1 = { +static struct ezusb_fx_type ezusb_fx1 = { .cpucs_reg = 0x7F92, .max_internal_adress = 0x1B3F, }; -struct ezusb_fx_type ezusb_fx2 = { - .cpucs_reg = 0xE600, - .max_internal_adress = 0x3FFF, -}; - /* Commands for writing to memory */ #define WRITE_INT_RAM 0xA0 #define WRITE_EXT_RAM 0xA3 -int ezusb_writememory(struct usb_device *dev, int address, +static int ezusb_writememory(struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) { int result; @@ -58,10 +54,9 @@ int ezusb_writememory(struct usb_device *dev, int address, kfree(transfer_buffer); return result; } -EXPORT_SYMBOL_GPL(ezusb_writememory); -int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, - unsigned char reset_bit) +static int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, + unsigned char reset_bit) { int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM); if (response < 0) @@ -76,12 +71,6 @@ int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit) } EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset); -int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) -{ - return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); -} -EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); - static int ezusb_ihex_firmware_download(struct usb_device *dev, struct ezusb_fx_type fx, const char *firmware_path) @@ -151,10 +140,28 @@ int ezusb_fx1_ihex_firmware_download(struct usb_device *dev, } EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download); +#if 0 +/* + * Once someone one needs these fx2 functions, uncomment them + * and add them to ezusb.h and all should be good. + */ +static struct ezusb_fx_type ezusb_fx2 = { + .cpucs_reg = 0xE600, + .max_internal_adress = 0x3FFF, +}; + +int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ + return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); + int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, const char *firmware_path) { return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path); } EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); +#endif +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 457f25e..3baccf7 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ret = IRQ_HANDLED; } + /* Drop spurious RX and TX if device is disconnected */ + if (musb->int_usb & MUSB_INTR_DISCONNECT) { + musb->int_tx = 0; + musb->int_rx = 0; + } + if (musb->int_tx || musb->int_rx || musb->int_usb) ret |= musb_interrupt(musb); @@ -459,7 +465,6 @@ static int __devinit am35x_probe(struct platform_device *pdev) struct clk *clk; int ret = -ENOMEM; - int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -467,18 +472,10 @@ static int __devinit am35x_probe(struct platform_device *pdev) goto err0; } - /* get the musb id */ - musbid = musb_get_id(&pdev->dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(&pdev->dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err1; - } - - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err2; + goto err1; } phy_clk = clk_get(&pdev->dev, "fck"); @@ -507,7 +504,6 @@ static int __devinit am35x_probe(struct platform_device *pdev) goto err6; } - musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &am35x_dmamask; musb->dev.coherent_dma_mask = am35x_dmamask; @@ -557,9 +553,6 @@ err4: err3: platform_device_put(musb); -err2: - musb_put_id(&pdev->dev, musbid); - err1: kfree(glue); @@ -571,9 +564,7 @@ static int __devexit am35x_remove(struct platform_device *pdev) { struct am35x_glue *glue = platform_get_drvdata(pdev); - musb_put_id(&pdev->dev, glue->musb->id); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); clk_disable(glue->clk); clk_disable(glue->phy_clk); clk_put(glue->clk); @@ -648,15 +639,4 @@ static struct platform_driver am35x_driver = { MODULE_DESCRIPTION("AM35x MUSB Glue Layer"); MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); MODULE_LICENSE("GPL v2"); - -static int __init am35x_init(void) -{ - return platform_driver_register(&am35x_driver); -} -module_init(am35x_init); - -static void __exit am35x_exit(void) -{ - platform_driver_unregister(&am35x_driver); -} -module_exit(am35x_exit); +module_platform_driver(am35x_driver); diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index e8cff9b..7e4d60a 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -455,7 +455,6 @@ static int __devinit bfin_probe(struct platform_device *pdev) struct bfin_glue *glue; int ret = -ENOMEM; - int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -463,21 +462,12 @@ static int __devinit bfin_probe(struct platform_device *pdev) goto err0; } - /* get the musb id */ - musbid = musb_get_id(&pdev->dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(&pdev->dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err1; - } - - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err2; + goto err1; } - musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &bfin_dmamask; musb->dev.coherent_dma_mask = bfin_dmamask; @@ -513,9 +503,6 @@ static int __devinit bfin_probe(struct platform_device *pdev) err3: platform_device_put(musb); -err2: - musb_put_id(&pdev->dev, musbid); - err1: kfree(glue); @@ -527,9 +514,7 @@ static int __devexit bfin_remove(struct platform_device *pdev) { struct bfin_glue *glue = platform_get_drvdata(pdev); - musb_put_id(&pdev->dev, glue->musb->id); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); kfree(glue); return 0; @@ -585,15 +570,4 @@ static struct platform_driver bfin_driver = { MODULE_DESCRIPTION("Blackfin MUSB Glue Layer"); MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>"); MODULE_LICENSE("GPL v2"); - -static int __init bfin_init(void) -{ - return platform_driver_register(&bfin_driver); -} -module_init(bfin_init); - -static void __exit bfin_exit(void) -{ - platform_driver_unregister(&bfin_driver); -} -module_exit(bfin_exit); +module_platform_driver(bfin_driver); diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index e19da82..3a6c2fd 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1314,6 +1314,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(cppi_interrupt); /* Instantiate a software object representing a DMA controller. */ struct dma_controller *__devinit diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 8bc44b7..67b8ae7 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -480,7 +480,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev) struct clk *clk; int ret = -ENOMEM; - int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -488,18 +487,10 @@ static int __devinit da8xx_probe(struct platform_device *pdev) goto err0; } - /* get the musb id */ - musbid = musb_get_id(&pdev->dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(&pdev->dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err1; - } - - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err2; + goto err1; } clk = clk_get(&pdev->dev, "usb20"); @@ -515,7 +506,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev) goto err4; } - musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &da8xx_dmamask; musb->dev.coherent_dma_mask = da8xx_dmamask; @@ -558,9 +548,6 @@ err4: err3: platform_device_put(musb); -err2: - musb_put_id(&pdev->dev, musbid); - err1: kfree(glue); @@ -572,9 +559,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev) { struct da8xx_glue *glue = platform_get_drvdata(pdev); - musb_put_id(&pdev->dev, glue->musb->id); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); clk_disable(glue->clk); clk_put(glue->clk); kfree(glue); @@ -593,15 +578,4 @@ static struct platform_driver da8xx_driver = { MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer"); MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>"); MODULE_LICENSE("GPL v2"); - -static int __init da8xx_init(void) -{ - return platform_driver_register(&da8xx_driver); -} -module_init(da8xx_init); - -static void __exit da8xx_exit(void) -{ - platform_driver_unregister(&da8xx_driver); -} -module_exit(da8xx_exit); +module_platform_driver(da8xx_driver); diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 606bfd0..b3c0a94 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -512,7 +512,6 @@ static int __devinit davinci_probe(struct platform_device *pdev) struct clk *clk; int ret = -ENOMEM; - int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -520,18 +519,10 @@ static int __devinit davinci_probe(struct platform_device *pdev) goto err0; } - /* get the musb id */ - musbid = musb_get_id(&pdev->dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(&pdev->dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err1; - } - - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err2; + goto err1; } clk = clk_get(&pdev->dev, "usb"); @@ -547,7 +538,6 @@ static int __devinit davinci_probe(struct platform_device *pdev) goto err4; } - musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &davinci_dmamask; musb->dev.coherent_dma_mask = davinci_dmamask; @@ -590,9 +580,6 @@ err4: err3: platform_device_put(musb); -err2: - musb_put_id(&pdev->dev, musbid); - err1: kfree(glue); @@ -604,9 +591,7 @@ static int __devexit davinci_remove(struct platform_device *pdev) { struct davinci_glue *glue = platform_get_drvdata(pdev); - musb_put_id(&pdev->dev, glue->musb->id); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); clk_disable(glue->clk); clk_put(glue->clk); kfree(glue); @@ -625,15 +610,4 @@ static struct platform_driver davinci_driver = { MODULE_DESCRIPTION("DaVinci MUSB Glue Layer"); MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); MODULE_LICENSE("GPL v2"); - -static int __init davinci_init(void) -{ - return platform_driver_register(&davinci_driver); -} -module_init(davinci_init); - -static void __exit davinci_exit(void) -{ - platform_driver_unregister(&davinci_driver); -} -module_exit(davinci_exit); +module_platform_driver(davinci_driver); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index bb56a0e..774d815 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -116,7 +116,6 @@ #define MUSB_DRIVER_NAME "musb-hdrc" const char musb_driver_name[] = MUSB_DRIVER_NAME; -static DEFINE_IDA(musb_ida); MODULE_DESCRIPTION(DRIVER_INFO); MODULE_AUTHOR(DRIVER_AUTHOR); @@ -133,35 +132,6 @@ static inline struct musb *dev_to_musb(struct device *dev) /*-------------------------------------------------------------------------*/ -int musb_get_id(struct device *dev, gfp_t gfp_mask) -{ - int ret; - int id; - - ret = ida_pre_get(&musb_ida, gfp_mask); - if (!ret) { - dev_err(dev, "failed to reserve resource for id\n"); - return -ENOMEM; - } - - ret = ida_get_new(&musb_ida, &id); - if (ret < 0) { - dev_err(dev, "failed to allocate a new id\n"); - return ret; - } - - return id; -} -EXPORT_SYMBOL_GPL(musb_get_id); - -void musb_put_id(struct device *dev, int id) -{ - - dev_dbg(dev, "removing id %d\n", id); - ida_remove(&musb_ida, id); -} -EXPORT_SYMBOL_GPL(musb_put_id); - #ifndef CONFIG_BLACKFIN static int musb_ulpi_read(struct usb_phy *phy, u32 offset) { @@ -467,12 +437,12 @@ void musb_hnp_stop(struct musb *musb) */ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, - u8 devctl, u8 power) + u8 devctl) { struct usb_otg *otg = musb->xceiv->otg; irqreturn_t handled = IRQ_NONE; - dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, + dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl, int_usb); /* in host mode, the peripheral may issue remote wakeup. @@ -485,6 +455,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, if (devctl & MUSB_DEVCTL_HM) { void __iomem *mbase = musb->mregs; + u8 power; switch (musb->xceiv->state) { case OTG_STATE_A_SUSPEND: @@ -492,6 +463,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, * will stop RESUME signaling */ + power = musb_readb(musb->mregs, MUSB_POWER); if (power & MUSB_POWER_SUSPENDM) { /* spurious */ musb->int_usb &= ~MUSB_INTR_SUSPEND; @@ -655,8 +627,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, } if (int_usb & MUSB_INTR_SUSPEND) { - dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n", - otg_state_string(musb->xceiv->state), devctl, power); + dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n", + otg_state_string(musb->xceiv->state), devctl); handled = IRQ_HANDLED; switch (musb->xceiv->state) { @@ -722,8 +694,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, if (is_peripheral_active(musb)) { /* REVISIT HNP; just force disconnect */ } - musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); - musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); + musb->intrtxe = musb->epmask; + musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe); + musb->intrrxe = musb->epmask & 0xfffe; + musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED |USB_PORT_STAT_HIGH_SPEED @@ -944,8 +918,10 @@ void musb_start(struct musb *musb) dev_dbg(musb->controller, "<== devctl %02x\n", devctl); /* Set INT enable registers, enable interrupts */ - musb_writew(regs, MUSB_INTRTXE, musb->epmask); - musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe); + musb->intrtxe = musb->epmask; + musb_writew(regs, MUSB_INTRTXE, musb->intrtxe); + musb->intrrxe = musb->epmask & 0xfffe; + musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); musb_writeb(regs, MUSB_INTRUSBE, 0xf7); musb_writeb(regs, MUSB_TESTMODE, 0); @@ -983,7 +959,9 @@ static void musb_generic_disable(struct musb *musb) /* disable interrupts */ musb_writeb(mbase, MUSB_INTRUSBE, 0); + musb->intrtxe = 0; musb_writew(mbase, MUSB_INTRTXE, 0); + musb->intrrxe = 0; musb_writew(mbase, MUSB_INTRRXE, 0); /* off */ @@ -1523,33 +1501,6 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb) /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \ - defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) - -static irqreturn_t generic_interrupt(int irq, void *__hci) -{ - unsigned long flags; - irqreturn_t retval = IRQ_NONE; - struct musb *musb = __hci; - - spin_lock_irqsave(&musb->lock, flags); - - musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); - musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); - musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); - - if (musb->int_usb || musb->int_tx || musb->int_rx) - retval = musb_interrupt(musb); - - spin_unlock_irqrestore(&musb->lock, flags); - - return retval; -} - -#else -#define generic_interrupt NULL -#endif - /* * handle all the irqs defined by the HDRC core. for now we expect: other * irq sources (phy, dma, etc) will be handled first, musb->int_* values @@ -1560,12 +1511,11 @@ static irqreturn_t generic_interrupt(int irq, void *__hci) irqreturn_t musb_interrupt(struct musb *musb) { irqreturn_t retval = IRQ_NONE; - u8 devctl, power; + u8 devctl; int ep_num; u32 reg; devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - power = musb_readb(musb->mregs, MUSB_POWER); dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n", (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral", @@ -1576,7 +1526,7 @@ irqreturn_t musb_interrupt(struct musb *musb) */ if (musb->int_usb) retval |= musb_stage0_irq(musb, musb->int_usb, - devctl, power); + devctl); /* "stage 1" is handling endpoint irqs */ @@ -1919,7 +1869,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb->ops = plat->platform_ops; /* The musb_platform_init() call: - * - adjusts musb->mregs and musb->isr if needed, + * - adjusts musb->mregs + * - sets the musb->isr * - may initialize an integrated tranceiver * - initializes musb->xceiv, usually by otg_get_phy() * - stops powering VBUS @@ -1929,7 +1880,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) * external/discrete ones in various flavors (twl4030 family, * isp1504, non-OTG, etc) mostly hooking up through ULPI. */ - musb->isr = generic_interrupt; status = musb_platform_init(musb); if (status < 0) goto fail1; @@ -2120,8 +2070,6 @@ static void musb_save_context(struct musb *musb) musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); musb->context.power = musb_readb(musb_base, MUSB_POWER); - musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); - musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); musb->context.index = musb_readb(musb_base, MUSB_INDEX); musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); @@ -2194,8 +2142,8 @@ static void musb_restore_context(struct musb *musb) musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); musb_writeb(musb_base, MUSB_POWER, musb->context.power); - musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); - musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); + musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe); + musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe); musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index c158aac..7fb4819 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -288,7 +288,6 @@ struct musb_csr_regs { struct musb_context_registers { u8 power; - u16 intrtxe, intrrxe; u8 intrusbe; u16 frame; u8 index, testmode; @@ -313,6 +312,8 @@ struct musb { struct work_struct irq_work; u16 hwvers; + u16 intrrxe; + u16 intrtxe; /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ #define MUSB_PORT_STAT_RESUME (1 << 31) @@ -521,8 +522,6 @@ extern const char musb_driver_name[]; extern void musb_start(struct musb *musb); extern void musb_stop(struct musb *musb); -extern int musb_get_id(struct device *dev, gfp_t gfp_mask); -extern void musb_put_id(struct device *dev, int id); extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 2cb8780..b108473 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -124,8 +124,44 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer[2]; /* otg_workaround timer */ unsigned long last_timer[2]; /* last timer data for each instance */ + u32 __iomem *usb_ctrl[2]; }; +#define DSPS_AM33XX_CONTROL_MODULE_PHYS_0 0x44e10620 +#define DSPS_AM33XX_CONTROL_MODULE_PHYS_1 0x44e10628 + +static const resource_size_t dsps_control_module_phys[] = { + DSPS_AM33XX_CONTROL_MODULE_PHYS_0, + DSPS_AM33XX_CONTROL_MODULE_PHYS_1, +}; + +/** + * musb_dsps_phy_control - phy on/off + * @glue: struct dsps_glue * + * @id: musb instance + * @on: flag for phy to be switched on or off + * + * This is to enable the PHY using usb_ctrl register in system control + * module space. + * + * XXX: This function will be removed once we have a seperate driver for + * control module + */ +static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on) +{ + u32 usbphycfg; + + usbphycfg = readl(glue->usb_ctrl[id]); + + if (on) { + usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN); + usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN; + } else { + usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN; + } + + writel(usbphycfg, glue->usb_ctrl[id]); +} /** * dsps_musb_enable - enable interrupts */ @@ -365,11 +401,9 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) static int dsps_musb_init(struct musb *musb) { struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; - struct omap_musb_board_data *data = plat->board_data; void __iomem *reg_base = musb->ctrl_base; u32 rev, val; int status; @@ -377,7 +411,8 @@ static int dsps_musb_init(struct musb *musb) /* mentor core register starts at offset of 0x400 from musb base */ musb->mregs += wrp->musb_core_offset; - /* Get the NOP PHY */ + /* NOP driver needs change if supporting dual instance */ + usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) return -ENODEV; @@ -395,8 +430,7 @@ static int dsps_musb_init(struct musb *musb) dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); /* Start the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(1); + musb_dsps_phy_control(glue, pdev->id, 1); musb->isr = dsps_interrupt; @@ -418,16 +452,13 @@ err0: static int dsps_musb_exit(struct musb *musb) { struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); del_timer_sync(&glue->timer[pdev->id]); /* Shutdown the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(0); + musb_dsps_phy_control(glue, pdev->id, 0); /* NOP driver needs change if supporting dual instance */ usb_put_phy(musb->xceiv); @@ -458,25 +489,34 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) struct platform_device *musb; struct resource *res; struct resource resources[2]; - char res_name[10]; - int ret, musbid; + char res_name[11]; + int ret; - /* get memory resource */ - sprintf(res_name, "musb%d", id); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); + resources[0].start = dsps_control_module_phys[id]; + resources[0].end = resources[0].start + SZ_4 - 1; + resources[0].flags = IORESOURCE_MEM; + + glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, resources); + if (glue->usb_ctrl[id] == NULL) { + dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id); + ret = -ENODEV; + goto err0; + } + + /* first resource is for usbss, so start index from 1 */ + res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1); if (!res) { - dev_err(dev, "%s get mem resource failed\n", res_name); + dev_err(dev, "failed to get memory for instance %d\n", id); ret = -ENODEV; goto err0; } res->parent = NULL; resources[0] = *res; - /* get irq resource */ - sprintf(res_name, "musb%d-irq", id); - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); + /* first resource is for usbss, so start index from 1 */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1); if (!res) { - dev_err(dev, "%s get irq resource failed\n", res_name); + dev_err(dev, "failed to get irq for instance %d\n", id); ret = -ENODEV; goto err0; } @@ -484,22 +524,14 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) resources[1] = *res; resources[1].name = "mc"; - /* get the musb id */ - musbid = musb_get_id(dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err0; - } /* allocate the child platform device */ - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(dev, "failed to allocate musb device\n"); ret = -ENOMEM; - goto err1; + goto err0; } - musb->id = musbid; musb->dev.parent = dev; musb->dev.dma_mask = &musb_dmamask; musb->dev.coherent_dma_mask = musb_dmamask; @@ -530,7 +562,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); - sprintf(res_name, "port%d-mode", id); + snprintf(res_name, sizeof(res_name), "port%d-mode", id); of_property_read_u32(np, res_name, (u32 *)&pdata->mode); of_property_read_u32(np, "power", (u32 *)&pdata->power); config->multipoint = of_property_read_bool(np, "multipoint"); @@ -556,19 +588,10 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) err2: platform_device_put(musb); -err1: - musb_put_id(dev, musbid); err0: return ret; } -static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id) -{ - musb_put_id(glue->dev, glue->musb[id]->id); - platform_device_del(glue->musb[id]); - platform_device_put(glue->musb[id]); -} - static int __devinit dsps_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -628,7 +651,7 @@ static int __devinit dsps_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to create child pdev\n"); /* release resources of previously created instances */ for (i--; i >= 0 ; i--) - dsps_delete_musb_pdev(glue, i); + platform_device_unregister(glue->musb[i]); goto err3; } } @@ -653,7 +676,7 @@ static int __devexit dsps_remove(struct platform_device *pdev) /* delete the child platform device */ for (i = 0; i < wrp->instances ; i++) - dsps_delete_musb_pdev(glue, i); + platform_device_unregister(glue->musb[i]); /* disable usbss clocks */ pm_runtime_put(&pdev->dev); @@ -666,24 +689,26 @@ static int __devexit dsps_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int dsps_suspend(struct device *dev) { - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; + struct platform_device *pdev = to_platform_device(dev->parent); + struct dsps_glue *glue = platform_get_drvdata(pdev); + const struct dsps_musb_wrapper *wrp = glue->wrp; + int i; - /* Shutdown the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(0); + for (i = 0; i < wrp->instances; i++) + musb_dsps_phy_control(glue, i, 0); return 0; } static int dsps_resume(struct device *dev) { - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; + struct platform_device *pdev = to_platform_device(dev->parent); + struct dsps_glue *glue = platform_get_drvdata(pdev); + const struct dsps_musb_wrapper *wrp = glue->wrp; + int i; - /* Start the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(1); + for (i = 0; i < wrp->instances; i++) + musb_dsps_phy_control(glue, i, 1); return 0; } @@ -719,7 +744,7 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = { .rxep_bitmap = (0xfffe << 16), .musb_core_offset = 0x400, .poll_seconds = 2, - .instances = 2, + .instances = 1, }; static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d0b87e7..28b9790 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1068,7 +1068,6 @@ static int musb_gadget_enable(struct usb_ep *ep, */ musb_ep_select(mbase, epnum); if (usb_endpoint_dir_in(desc)) { - u16 int_txe = musb_readw(mbase, MUSB_INTRTXE); if (hw_ep->is_shared_fifo) musb_ep->is_in = 1; @@ -1080,8 +1079,8 @@ static int musb_gadget_enable(struct usb_ep *ep, goto fail; } - int_txe |= (1 << epnum); - musb_writew(mbase, MUSB_INTRTXE, int_txe); + musb->intrtxe |= (1 << epnum); + musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe); /* REVISIT if can_bulk_split(), use by updating "tmp"; * likewise high bandwidth periodic tx @@ -1108,7 +1107,6 @@ static int musb_gadget_enable(struct usb_ep *ep, musb_writew(regs, MUSB_TXCSR, csr); } else { - u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE); if (hw_ep->is_shared_fifo) musb_ep->is_in = 0; @@ -1120,8 +1118,8 @@ static int musb_gadget_enable(struct usb_ep *ep, goto fail; } - int_rxe |= (1 << epnum); - musb_writew(mbase, MUSB_INTRRXE, int_rxe); + musb->intrrxe |= (1 << epnum); + musb_writew(mbase, MUSB_INTRRXE, musb->intrrxe); /* REVISIT if can_bulk_combine() use by updating "tmp" * likewise high bandwidth periodic rx @@ -1209,14 +1207,12 @@ static int musb_gadget_disable(struct usb_ep *ep) /* zero the endpoint sizes */ if (musb_ep->is_in) { - u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE); - int_txe &= ~(1 << epnum); - musb_writew(musb->mregs, MUSB_INTRTXE, int_txe); + musb->intrtxe &= ~(1 << epnum); + musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe); musb_writew(epio, MUSB_TXMAXP, 0); } else { - u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE); - int_rxe &= ~(1 << epnum); - musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe); + musb->intrrxe &= ~(1 << epnum); + musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); musb_writew(epio, MUSB_RXMAXP, 0); } @@ -1532,7 +1528,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep) void __iomem *epio = musb->endpoints[epnum].regs; void __iomem *mbase; unsigned long flags; - u16 csr, int_txe; + u16 csr; mbase = musb->mregs; @@ -1540,8 +1536,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep) musb_ep_select(mbase, (u8) epnum); /* disable interrupts */ - int_txe = musb_readw(mbase, MUSB_INTRTXE); - musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum)); + musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum)); if (musb_ep->is_in) { csr = musb_readw(epio, MUSB_TXCSR); @@ -1565,7 +1560,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep) } /* re-enable interrupt */ - musb_writew(mbase, MUSB_INTRTXE, int_txe); + musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe); spin_unlock_irqrestore(&musb->lock, flags); } @@ -2154,10 +2149,9 @@ __acquires(musb->lock) u8 devctl = musb_readb(mbase, MUSB_DEVCTL); u8 power; - dev_dbg(musb->controller, "<== %s addr=%x driver '%s'\n", + dev_dbg(musb->controller, "<== %s driver '%s'\n", (devctl & MUSB_DEVCTL_BDEVICE) ? "B-Device" : "A-Device", - musb_readb(mbase, MUSB_FADDR), musb->gadget_driver ? musb->gadget_driver->driver.name : NULL diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index e40d764..c9c1ac4 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -673,10 +673,8 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) csr = musb_readw(regs, MUSB_CSR0); len = musb_readb(regs, MUSB_COUNT0); - dev_dbg(musb->controller, "csr %04x, count %d, myaddr %d, ep0stage %s\n", - csr, len, - musb_readb(mbase, MUSB_FADDR), - decode_ep0stage(musb->ep0_state)); + dev_dbg(musb->controller, "csr %04x, count %d, ep0stage %s\n", + csr, len, decode_ep0stage(musb->ep0_state)); if (csr & MUSB_CSR0_P_DATAEND) { /* diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 3df6a76..e9f0fd9 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -740,7 +740,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, csr = musb_readw(epio, MUSB_TXCSR); /* disable interrupt in case we flush */ - int_txe = musb_readw(mbase, MUSB_INTRTXE); + int_txe = musb->intrtxe; musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum)); /* general endpoint setup */ diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h index 320fd4a..f7b13fd2 100644 --- a/drivers/usb/musb/musbhsdma.h +++ b/drivers/usb/musb/musbhsdma.h @@ -31,10 +31,6 @@ * */ -#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) -#include "omap2430.h" -#endif - #ifndef CONFIG_BLACKFIN #define MUSB_HSDMA_BASE 0x200 diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index a538fe1..32f531e 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -333,6 +333,26 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work) omap_musb_set_mailbox(glue); } +static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci) +{ + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct musb *musb = __hci; + + spin_lock_irqsave(&musb->lock, flags); + + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); + + if (musb->int_usb || musb->int_tx || musb->int_rx) + retval = musb_interrupt(musb); + + spin_unlock_irqrestore(&musb->lock, flags); + + return retval; +} + static int omap2430_musb_init(struct musb *musb) { u32 l; @@ -352,6 +372,8 @@ static int omap2430_musb_init(struct musb *musb) return -ENODEV; } + musb->isr = omap2430_musb_interrupt; + status = pm_runtime_get_sync(dev); if (status < 0) { dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); @@ -478,7 +500,6 @@ static int __devinit omap2430_probe(struct platform_device *pdev) struct musb_hdrc_config *config; struct resource *res; int ret = -ENOMEM; - int musbid; glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -486,21 +507,12 @@ static int __devinit omap2430_probe(struct platform_device *pdev) goto err0; } - /* get the musb id */ - musbid = musb_get_id(&pdev->dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(&pdev->dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err0; - } - - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; + goto err0; } - musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &omap2430_dmamask; musb->dev.coherent_dma_mask = omap2430_dmamask; @@ -521,7 +533,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to allocate musb platfrom data\n"); ret = -ENOMEM; - goto err1; + goto err2; } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); @@ -529,14 +541,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to allocate musb board data\n"); ret = -ENOMEM; - goto err1; + goto err2; } config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); if (!data) { dev_err(&pdev->dev, "failed to allocate musb hdrc config\n"); - goto err1; + goto err2; } of_property_read_u32(np, "mode", (u32 *)&pdata->mode); @@ -589,9 +601,6 @@ static int __devinit omap2430_probe(struct platform_device *pdev) err2: platform_device_put(musb); -err1: - musb_put_id(&pdev->dev, musbid); - err0: return ret; } @@ -601,7 +610,6 @@ static int __devexit omap2430_remove(struct platform_device *pdev) struct omap2430_glue *glue = platform_get_drvdata(pdev); cancel_work_sync(&glue->omap_musb_mailbox_work); - musb_put_id(&pdev->dev, glue->musb->id); platform_device_unregister(glue->musb); return 0; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index dc4d75e..812719b 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1160,7 +1160,6 @@ static int __devinit tusb_probe(struct platform_device *pdev) struct tusb6010_glue *glue; int ret = -ENOMEM; - int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -1168,21 +1167,12 @@ static int __devinit tusb_probe(struct platform_device *pdev) goto err0; } - /* get the musb id */ - musbid = musb_get_id(&pdev->dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(&pdev->dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err1; - } - - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err2; + goto err1; } - musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &tusb_dmamask; musb->dev.coherent_dma_mask = tusb_dmamask; @@ -1218,9 +1208,6 @@ static int __devinit tusb_probe(struct platform_device *pdev) err3: platform_device_put(musb); -err2: - musb_put_id(&pdev->dev, musbid); - err1: kfree(glue); @@ -1232,9 +1219,7 @@ static int __devexit tusb_remove(struct platform_device *pdev) { struct tusb6010_glue *glue = platform_get_drvdata(pdev); - musb_put_id(&pdev->dev, glue->musb->id); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); kfree(glue); return 0; @@ -1251,15 +1236,4 @@ static struct platform_driver tusb_driver = { MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer"); MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); MODULE_LICENSE("GPL v2"); - -static int __init tusb_init(void) -{ - return platform_driver_register(&tusb_driver); -} -module_init(tusb_init); - -static void __exit tusb_exit(void) -{ - platform_driver_unregister(&tusb_driver); -} -module_exit(tusb_exit); +module_platform_driver(tusb_driver); diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index d62a91f..286f1be 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -36,6 +36,26 @@ struct ux500_glue { }; #define glue_to_musb(g) platform_get_drvdata(g->musb) +static irqreturn_t ux500_musb_interrupt(int irq, void *__hci) +{ + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct musb *musb = __hci; + + spin_lock_irqsave(&musb->lock, flags); + + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); + + if (musb->int_usb || musb->int_tx || musb->int_rx) + retval = musb_interrupt(musb); + + spin_unlock_irqrestore(&musb->lock, flags); + + return retval; +} + static int ux500_musb_init(struct musb *musb) { musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); @@ -44,6 +64,8 @@ static int ux500_musb_init(struct musb *musb) return -ENODEV; } + musb->isr = ux500_musb_interrupt; + return 0; } @@ -65,7 +87,6 @@ static int __devinit ux500_probe(struct platform_device *pdev) struct platform_device *musb; struct ux500_glue *glue; struct clk *clk; - int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL); @@ -74,18 +95,10 @@ static int __devinit ux500_probe(struct platform_device *pdev) goto err0; } - /* get the musb id */ - musbid = musb_get_id(&pdev->dev, GFP_KERNEL); - if (musbid < 0) { - dev_err(&pdev->dev, "failed to allocate musb id\n"); - ret = -ENOMEM; - goto err1; - } - - musb = platform_device_alloc("musb-hdrc", musbid); + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err2; + goto err1; } clk = clk_get(&pdev->dev, "usb"); @@ -101,7 +114,6 @@ static int __devinit ux500_probe(struct platform_device *pdev) goto err4; } - musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = pdev->dev.dma_mask; musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; @@ -144,9 +156,6 @@ err4: err3: platform_device_put(musb); -err2: - musb_put_id(&pdev->dev, musbid); - err1: kfree(glue); @@ -158,9 +167,7 @@ static int __devexit ux500_remove(struct platform_device *pdev) { struct ux500_glue *glue = platform_get_drvdata(pdev); - musb_put_id(&pdev->dev, glue->musb->id); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); clk_disable(glue->clk); clk_put(glue->clk); kfree(glue); @@ -219,15 +226,4 @@ static struct platform_driver ux500_driver = { MODULE_DESCRIPTION("UX500 MUSB Glue Layer"); MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>"); MODULE_LICENSE("GPL v2"); - -static int __init ux500_init(void) -{ - return platform_driver_register(&ux500_driver); -} -module_init(ux500_init); - -static void __exit ux500_exit(void) -{ - platform_driver_unregister(&ux500_driver); -} -module_exit(ux500_exit); +module_platform_driver(ux500_driver); diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index 3f124e8..1dd5750 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -958,16 +958,4 @@ static struct platform_driver mv_otg_driver = { .resume = mv_otg_resume, #endif }; - -static int __init mv_otg_init(void) -{ - return platform_driver_register(&mv_otg_driver); -} - -static void __exit mv_otg_exit(void) -{ - platform_driver_unregister(&mv_otg_driver); -} - -module_init(mv_otg_init); -module_exit(mv_otg_exit); +module_platform_driver(mv_otg_driver); diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 63c339b..7eb73c5 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -32,3 +32,15 @@ config MV_U3D_PHY help Enable this to support Marvell USB 3.0 phy controller for Marvell SoC. + +config USB_RCAR_PHY + tristate "Renesas R-Car USB phy support" + depends on USB || USB_GADGET + select USB_OTG_UTILS + help + Say Y here to add support for the Renesas R-Car USB phy driver. + This chip is typically used as USB phy for USB host, gadget. + This driver supports: R8A7779 + + To compile this driver as a module, choose M here: the + module will be called rcar-phy. diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index b069f29..1a579a8 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_OMAP_USB2) += omap-usb2.o obj-$(CONFIG_USB_ISP1301) += isp1301.o obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o +obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c new file mode 100644 index 0000000..792f505 --- /dev/null +++ b/drivers/usb/phy/rcar-phy.c @@ -0,0 +1,220 @@ +/* + * Renesas R-Car USB phy driver + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * 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. + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/usb/otg.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/module.h> + +/* USBH common register */ +#define USBPCTRL0 0x0800 +#define USBPCTRL1 0x0804 +#define USBST 0x0808 +#define USBEH0 0x080C +#define USBOH0 0x081C +#define USBCTL0 0x0858 +#define EIIBC1 0x0094 +#define EIIBC2 0x009C + +/* USBPCTRL1 */ +#define PHY_RST (1 << 2) +#define PLL_ENB (1 << 1) +#define PHY_ENB (1 << 0) + +/* USBST */ +#define ST_ACT (1 << 31) +#define ST_PLL (1 << 30) + +struct rcar_usb_phy_priv { + struct usb_phy phy; + spinlock_t lock; + + void __iomem *reg0; + void __iomem *reg1; + int counter; +}; + +#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy) + + +/* + * USB initial/install operation. + * + * This function setup USB phy. + * The used value and setting order came from + * [USB :: Initial setting] on datasheet. + */ +static int rcar_usb_phy_init(struct usb_phy *phy) +{ + struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); + struct device *dev = phy->dev; + void __iomem *reg0 = priv->reg0; + void __iomem *reg1 = priv->reg1; + int i; + u32 val; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->counter++ == 0) { + + /* + * USB phy start-up + */ + + /* (1) USB-PHY standby release */ + iowrite32(PHY_ENB, (reg0 + USBPCTRL1)); + + /* (2) start USB-PHY internal PLL */ + iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1)); + + /* (3) USB module status check */ + for (i = 0; i < 1024; i++) { + udelay(10); + val = ioread32(reg0 + USBST); + if (val == (ST_ACT | ST_PLL)) + break; + } + + if (val != (ST_ACT | ST_PLL)) { + dev_err(dev, "USB phy not ready\n"); + goto phy_init_end; + } + + /* (4) USB-PHY reset clear */ + iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1)); + + /* set platform specific port settings */ + iowrite32(0x00000000, (reg0 + USBPCTRL0)); + + /* + * EHCI IP internal buffer setting + * EHCI IP internal buffer enable + * + * These are recommended value of a datasheet + * see [USB :: EHCI internal buffer setting] + */ + iowrite32(0x00ff0040, (reg0 + EIIBC1)); + iowrite32(0x00ff0040, (reg1 + EIIBC1)); + + iowrite32(0x00000001, (reg0 + EIIBC2)); + iowrite32(0x00000001, (reg1 + EIIBC2)); + + /* + * Bus alignment settings + */ + + /* (1) EHCI bus alignment (little endian) */ + iowrite32(0x00000000, (reg0 + USBEH0)); + + /* (1) OHCI bus alignment (little endian) */ + iowrite32(0x00000000, (reg0 + USBOH0)); + } + +phy_init_end: + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static void rcar_usb_phy_shutdown(struct usb_phy *phy) +{ + struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); + void __iomem *reg0 = priv->reg0; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->counter-- == 1) { /* last user */ + iowrite32(0x00000000, (reg0 + USBPCTRL0)); + iowrite32(0x00000000, (reg0 + USBPCTRL1)); + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +static int __devinit rcar_usb_phy_probe(struct platform_device *pdev) +{ + struct rcar_usb_phy_priv *priv; + struct resource *res0, *res1; + struct device *dev = &pdev->dev; + void __iomem *reg0, *reg1; + int ret; + + res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res0 || !res1) { + dev_err(dev, "Not enough platform resources\n"); + return -EINVAL; + } + + /* + * CAUTION + * + * Because this phy address is also mapped under OHCI/EHCI address area, + * this driver can't use devm_request_and_ioremap(dev, res) here + */ + reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0)); + reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1)); + if (!reg0 || !reg1) { + dev_err(dev, "ioremap error\n"); + return -ENOMEM; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(dev, "priv data allocation error\n"); + return -ENOMEM; + } + + priv->reg0 = reg0; + priv->reg1 = reg1; + priv->counter = 0; + priv->phy.dev = dev; + priv->phy.label = dev_name(dev); + priv->phy.init = rcar_usb_phy_init; + priv->phy.shutdown = rcar_usb_phy_shutdown; + spin_lock_init(&priv->lock); + + ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2); + if (ret < 0) { + dev_err(dev, "usb phy addition error\n"); + return ret; + } + + platform_set_drvdata(pdev, priv); + + return ret; +} + +static int __devexit rcar_usb_phy_remove(struct platform_device *pdev) +{ + struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev); + + usb_remove_phy(&priv->phy); + + return 0; +} + +static struct platform_driver rcar_usb_phy_driver = { + .driver = { + .name = "rcar_usb_phy", + }, + .probe = rcar_usb_phy_probe, + .remove = __devexit_p(rcar_usb_phy_remove), +}; + +module_platform_driver(rcar_usb_phy_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Renesas R-Car USB phy"); +MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c index 987116f9..9d13c81 100644 --- a/drivers/usb/phy/tegra_usb_phy.c +++ b/drivers/usb/phy/tegra_usb_phy.c @@ -29,7 +29,9 @@ #include <linux/usb/ulpi.h> #include <asm/mach-types.h> #include <linux/usb/tegra_usb_phy.h> -#include <mach/iomap.h> + +#define TEGRA_USB_BASE 0xC5000000 +#define TEGRA_USB_SIZE SZ_16K #define ULPI_VIEWPORT 0x170 diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 72ad375..9538f0f 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -799,6 +799,7 @@ static void xfer_work(struct work_struct *work) fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); + usbhs_pipe_enable(pipe); usbhsf_dma_start(pipe, fifo); dma_async_issue_pending(chan); } diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 2672487..6a030b9 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -272,9 +272,9 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC); usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC); - usbhs_write(priv, BRDYSTS, 0); - usbhs_write(priv, NRDYSTS, 0); - usbhs_write(priv, BEMPSTS, 0); + usbhs_write(priv, BRDYSTS, ~irq_state.brdysts); + usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts); + usbhs_write(priv, BEMPSTS, ~irq_state.bempsts); /* * call irq callback functions diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 73c5039..3d3cd6c 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -342,6 +342,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv, struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; + if (unlikely(!uep)) { + dev_err(dev, "no uep\n"); + return; + } + /******************** spin lock ********************/ usbhs_lock(priv, flags); diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 01b1820..b476fde 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -54,7 +54,7 @@ struct usbhs_pipe_info { * pipe list */ #define __usbhs_for_each_pipe(start, pos, info, i) \ - for (i = start, pos = (info)->pipe; \ + for (i = start, pos = (info)->pipe + i; \ i < (info)->size; \ i++, pos = (info)->pipe + i) diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 54e1bb6..6d110a3 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -68,10 +68,6 @@ #define THROTTLED 0x01 #define ACTUALLY_THROTTLED 0x02 -/* - * Version Information - */ -#define DRIVER_VERSION "v2.0" #define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>" #define DRIVER_DESC "AIRcable USB Driver" @@ -192,5 +188,4 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index cf2522c..a88882c 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -37,11 +37,6 @@ #include <linux/mutex.h> #include <linux/spinlock.h> -/* - * Version information - */ - -#define DRIVER_VERSION "v0.7" #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>" #define DRIVER_DESC "USB ARK3116 serial/IrDA driver" #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA" @@ -125,9 +120,6 @@ static inline int calc_divisor(int bps) static int ark3116_attach(struct usb_serial *serial) { - struct usb_serial_port *port = serial->port[0]; - struct ark3116_private *priv; - /* make sure we have our end-points */ if ((serial->num_bulk_in == 0) || (serial->num_bulk_out == 0) || @@ -142,8 +134,15 @@ static int ark3116_attach(struct usb_serial *serial) return -EINVAL; } - priv = kzalloc(sizeof(struct ark3116_private), - GFP_KERNEL); + return 0; +} + +static int ark3116_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct ark3116_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -198,18 +197,15 @@ static int ark3116_attach(struct usb_serial *serial) return 0; } -static void ark3116_release(struct usb_serial *serial) +static int ark3116_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct ark3116_private *priv = usb_get_serial_port_data(port); /* device is closed, so URBs and DMA should be down */ - - usb_set_serial_port_data(port, NULL); - mutex_destroy(&priv->hw_lock); - kfree(priv); + + return 0; } static void ark3116_init_termios(struct tty_struct *tty) @@ -723,7 +719,8 @@ static struct usb_serial_driver ark3116_device = { .id_table = id_table, .num_ports = 1, .attach = ark3116_attach, - .release = ark3116_release, + .port_probe = ark3116_port_probe, + .port_remove = ark3116_port_remove, .set_termios = ark3116_set_termios, .init_termios = ark3116_init_termios, .ioctl = ark3116_ioctl, diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 9944942..b72a4c1 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -37,16 +37,12 @@ #include <linux/usb/serial.h> #include "belkin_sa.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v1.3" #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>" #define DRIVER_DESC "USB Belkin Serial converter driver" /* function prototypes for a Belkin USB Serial Adapter F5U103 */ -static int belkin_sa_startup(struct usb_serial *serial); -static void belkin_sa_release(struct usb_serial *serial); +static int belkin_sa_port_probe(struct usb_serial_port *port); +static int belkin_sa_port_remove(struct usb_serial_port *port); static int belkin_sa_open(struct tty_struct *tty, struct usb_serial_port *port); static void belkin_sa_close(struct usb_serial_port *port); @@ -88,8 +84,8 @@ static struct usb_serial_driver belkin_device = { .break_ctl = belkin_sa_break_ctl, .tiocmget = belkin_sa_tiocmget, .tiocmset = belkin_sa_tiocmset, - .attach = belkin_sa_startup, - .release = belkin_sa_release, + .port_probe = belkin_sa_port_probe, + .port_remove = belkin_sa_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -118,17 +114,15 @@ struct belkin_sa_private { (c), BELKIN_SA_SET_REQUEST_TYPE, \ (v), 0, NULL, 0, WDR_TIMEOUT) -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int belkin_sa_startup(struct usb_serial *serial) +static int belkin_sa_port_probe(struct usb_serial_port *port) { - struct usb_device *dev = serial->dev; + struct usb_device *dev = port->serial->dev; struct belkin_sa_private *priv; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL); if (!priv) - return -1; /* error */ - /* set initial values for control structures */ + return -ENOMEM; + spin_lock_init(&priv->lock); priv->control_state = 0; priv->last_lsr = 0; @@ -140,18 +134,19 @@ static int belkin_sa_startup(struct usb_serial *serial) le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control); - init_waitqueue_head(&serial->port[0]->write_wait); - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; } -static void belkin_sa_release(struct usb_serial *serial) +static int belkin_sa_port_remove(struct usb_serial_port *port) { - int i; + struct belkin_sa_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int belkin_sa_open(struct tty_struct *tty, @@ -510,5 +505,4 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index e9c7046..d255f66 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -242,13 +242,11 @@ out: kfree(buffer); return r; } -/* allocate private data */ -static int ch341_attach(struct usb_serial *serial) +static int ch341_port_probe(struct usb_serial_port *port) { struct ch341_private *priv; int r; - /* private data */ priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial) priv->baud_rate = DEFAULT_BAUD_RATE; priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; - r = ch341_configure(serial->dev, priv); + r = ch341_configure(port->serial->dev, priv); if (r < 0) goto error; - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; error: kfree(priv); return r; } +static int ch341_port_remove(struct usb_serial_port *port) +{ + struct ch341_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} + static int ch341_carrier_raised(struct usb_serial_port *port) { struct ch341_private *priv = usb_get_serial_port_data(port); @@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port) static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); + struct ch341_private *priv = usb_get_serial_port_data(port); int r; priv->baud_rate = DEFAULT_BAUD_RATE; @@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = { .tiocmget = ch341_tiocmget, .tiocmset = ch341_tiocmset, .read_int_callback = ch341_read_int_callback, - .attach = ch341_attach, + .port_probe = ch341_port_probe, + .port_remove = ch341_port_remove, .reset_resume = ch341_reset_resume, }; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 28af5ac..2858d8a 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -24,10 +24,6 @@ #include <linux/uaccess.h> #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v0.09" #define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver" /* @@ -35,8 +31,7 @@ */ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *); static void cp210x_close(struct usb_serial_port *); -static void cp210x_get_termios(struct tty_struct *, - struct usb_serial_port *port); +static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *); static void cp210x_get_termios_port(struct usb_serial_port *port, unsigned int *cflagp, unsigned int *baudp); static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, @@ -162,14 +157,14 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); -struct cp210x_port_private { +struct cp210x_serial_private { __u8 bInterfaceNumber; }; static struct usb_serial_driver cp210x_device = { .driver = { .owner = THIS_MODULE, - .name = "cp210x", + .name = "cp210x", }, .id_table = id_table, .num_ports = 1, @@ -179,7 +174,7 @@ static struct usb_serial_driver cp210x_device = { .close = cp210x_close, .break_ctl = cp210x_break_ctl, .set_termios = cp210x_set_termios, - .tiocmget = cp210x_tiocmget, + .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, .release = cp210x_release, @@ -276,12 +271,12 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; + length = (((size - 1) | 3) + 1) / 4; buf = kcalloc(length, sizeof(__le32), GFP_KERNEL); if (!buf) { @@ -292,7 +287,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_INTERFACE_TO_HOST, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_GET_TIMEOUT); /* Convert data into an array of integers */ @@ -323,17 +318,16 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; + length = (((size - 1) | 3) + 1) / 4; buf = kmalloc(length * sizeof(__le32), GFP_KERNEL); if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", - __func__); + dev_err(&port->dev, "%s - out of memory.\n", __func__); return -ENOMEM; } @@ -345,13 +339,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_SET_TIMEOUT); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, data[0], - port_priv->bInterfaceNumber, NULL, 0, + spriv->bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); } @@ -384,7 +378,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port, * cp210x_quantise_baudrate * Quantises the baud rate as per AN205 Table 1 */ -static unsigned int cp210x_quantise_baudrate(unsigned int baud) { +static unsigned int cp210x_quantise_baudrate(unsigned int baud) +{ if (baud <= 300) baud = 300; else if (baud <= 600) baud = 600; @@ -467,9 +462,7 @@ static void cp210x_get_termios(struct tty_struct *tty, cp210x_get_termios_port(tty->driver_data, &tty->termios.c_cflag, &baud); tty_encode_baud_rate(tty, baud, baud); - } - - else { + } else { unsigned int cflag; cflag = 0; cp210x_get_termios_port(port, &cflag, &baud); @@ -693,8 +686,8 @@ static void cp210x_set_termios(struct tty_struct *tty, break;*/ default: dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n"); - bits |= BITS_DATA_8; - break; + bits |= BITS_DATA_8; + break; } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dev_dbg(dev, "Number of data bits requested not supported by device\n"); @@ -767,7 +760,7 @@ static void cp210x_set_termios(struct tty_struct *tty, } -static int cp210x_tiocmset (struct tty_struct *tty, +static int cp210x_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; @@ -809,7 +802,7 @@ static void cp210x_dtr_rts(struct usb_serial_port *p, int on) cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS); } -static int cp210x_tiocmget (struct tty_struct *tty) +static int cp210x_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned int control; @@ -829,7 +822,7 @@ static int cp210x_tiocmget (struct tty_struct *tty) return result; } -static void cp210x_break_ctl (struct tty_struct *tty, int break_state) +static void cp210x_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; unsigned int state; @@ -845,40 +838,33 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) static int cp210x_startup(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct usb_host_interface *cur_altsetting; + struct cp210x_serial_private *spriv; /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); - for (i = 0; i < serial->num_ports; i++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) - return -ENOMEM; + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; - port_priv->bInterfaceNumber = - serial->interface->cur_altsetting->desc.bInterfaceNumber; + cur_altsetting = serial->interface->cur_altsetting; + spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber; - usb_set_serial_port_data(serial->port[i], port_priv); - } + usb_set_serial_data(serial, spriv); return 0; } static void cp210x_release(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct cp210x_serial_private *spriv; - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - kfree(port_priv); - usb_set_serial_port_data(serial->port[i], NULL); - } + spriv = usb_get_serial_data(serial); + kfree(spriv); } module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 2a7aecc..69a4fa1 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -43,10 +43,6 @@ #define CYBERJACK_LOCAL_BUF_SIZE 32 -/* - * Version Information - */ -#define DRIVER_VERSION "v1.01" #define DRIVER_AUTHOR "Matthias Bruestle" #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver" @@ -55,9 +51,9 @@ #define CYBERJACK_PRODUCT_ID 0x0100 /* Function prototypes */ -static int cyberjack_startup(struct usb_serial *serial); static void cyberjack_disconnect(struct usb_serial *serial); -static void cyberjack_release(struct usb_serial *serial); +static int cyberjack_port_probe(struct usb_serial_port *port); +static int cyberjack_port_remove(struct usb_serial_port *port); static int cyberjack_open(struct tty_struct *tty, struct usb_serial_port *port); static void cyberjack_close(struct usb_serial_port *port); @@ -83,9 +79,9 @@ static struct usb_serial_driver cyberjack_device = { .description = "Reiner SCT Cyberjack USB card reader", .id_table = id_table, .num_ports = 1, - .attach = cyberjack_startup, .disconnect = cyberjack_disconnect, - .release = cyberjack_release, + .port_probe = cyberjack_port_probe, + .port_remove = cyberjack_port_remove, .open = cyberjack_open, .close = cyberjack_close, .write = cyberjack_write, @@ -107,56 +103,45 @@ struct cyberjack_private { short wrsent; /* Data already sent */ }; -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int cyberjack_startup(struct usb_serial *serial) +static int cyberjack_port_probe(struct usb_serial_port *port) { struct cyberjack_private *priv; - int i; + int result; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); if (!priv) return -ENOMEM; - /* set initial values */ spin_lock_init(&priv->lock); priv->rdtodo = 0; priv->wrfilled = 0; priv->wrsent = 0; - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + usb_set_serial_port_data(port, priv); - for (i = 0; i < serial->num_ports; ++i) { - int result; - result = usb_submit_urb(serial->port[i]->interrupt_in_urb, - GFP_KERNEL); - if (result) - dev_err(&serial->dev->dev, - "usb_submit_urb(read int) failed\n"); - dev_dbg(&serial->dev->dev, "%s - usb_submit_urb(int urb)\n", - __func__); - } + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); return 0; } -static void cyberjack_disconnect(struct usb_serial *serial) +static int cyberjack_port_remove(struct usb_serial_port *port) { - int i; + struct cyberjack_private *priv; - for (i = 0; i < serial->num_ports; ++i) - usb_kill_urb(serial->port[i]->interrupt_in_urb); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } -static void cyberjack_release(struct usb_serial *serial) +static void cyberjack_disconnect(struct usb_serial *serial) { int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - kfree(usb_get_serial_port_data(serial->port[i])); - } + for (i = 0; i < serial->num_ports; ++i) + usb_kill_urb(serial->port[i]->interrupt_in_urb); } static int cyberjack_open(struct tty_struct *tty, @@ -452,5 +437,4 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 1befce2..fd8c35f 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -50,10 +50,6 @@ static bool stats; static int interval; static bool unstable_bauds; -/* - * Version Information - */ -#define DRIVER_VERSION "v1.10" #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>" #define DRIVER_DESC "Cypress USB to Serial Driver" @@ -123,10 +119,10 @@ struct cypress_private { }; /* function prototypes for the Cypress USB to serial device */ -static int cypress_earthmate_startup(struct usb_serial *serial); -static int cypress_hidcom_startup(struct usb_serial *serial); -static int cypress_ca42v2_startup(struct usb_serial *serial); -static void cypress_release(struct usb_serial *serial); +static int cypress_earthmate_port_probe(struct usb_serial_port *port); +static int cypress_hidcom_port_probe(struct usb_serial_port *port); +static int cypress_ca42v2_port_probe(struct usb_serial_port *port); +static int cypress_port_remove(struct usb_serial_port *port); static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port); static void cypress_close(struct usb_serial_port *port); static void cypress_dtr_rts(struct usb_serial_port *port, int on); @@ -156,8 +152,8 @@ static struct usb_serial_driver cypress_earthmate_device = { .description = "DeLorme Earthmate USB", .id_table = id_table_earthmate, .num_ports = 1, - .attach = cypress_earthmate_startup, - .release = cypress_release, + .port_probe = cypress_earthmate_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -182,8 +178,8 @@ static struct usb_serial_driver cypress_hidcom_device = { .description = "HID->COM RS232 Adapter", .id_table = id_table_cyphidcomrs232, .num_ports = 1, - .attach = cypress_hidcom_startup, - .release = cypress_release, + .port_probe = cypress_hidcom_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -208,8 +204,8 @@ static struct usb_serial_driver cypress_ca42v2_device = { .description = "Nokia CA-42 V2 Adapter", .id_table = id_table_nokiaca42v2, .num_ports = 1, - .attach = cypress_ca42v2_startup, - .release = cypress_release, + .port_probe = cypress_ca42v2_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -438,10 +434,10 @@ static void cypress_set_dead(struct usb_serial_port *port) *****************************************************************************/ -static int generic_startup(struct usb_serial *serial) +static int cypress_generic_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) @@ -490,14 +486,16 @@ static int generic_startup(struct usb_serial *serial) } -static int cypress_earthmate_startup(struct usb_serial *serial) +static int cypress_earthmate_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); @@ -518,56 +516,53 @@ static int cypress_earthmate_startup(struct usb_serial *serial) } return 0; -} /* cypress_earthmate_startup */ - +} -static int cypress_hidcom_startup(struct usb_serial *serial) +static int cypress_hidcom_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); priv->chiptype = CT_CYPHIDCOM; return 0; -} /* cypress_hidcom_startup */ - +} -static int cypress_ca42v2_startup(struct usb_serial *serial) +static int cypress_ca42v2_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); priv->chiptype = CT_CA42V2; return 0; -} /* cypress_ca42v2_startup */ - +} -static void cypress_release(struct usb_serial *serial) +static int cypress_port_remove(struct usb_serial_port *port) { struct cypress_private *priv; - /* all open ports are closed at this point */ - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); - if (priv) { - kfifo_free(&priv->write_fifo); - kfree(priv); - } -} + kfifo_free(&priv->write_fifo); + kfree(priv); + return 0; +} static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) { @@ -1304,7 +1299,6 @@ module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(stats, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index c86f68c..45d4af6 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -32,10 +32,6 @@ /* Defines */ -/* - * Version Information - */ -#define DRIVER_VERSION "v1.80.1.2" #define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>" #define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver" @@ -244,6 +240,8 @@ static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); static void digi_disconnect(struct usb_serial *serial); static void digi_release(struct usb_serial *serial); +static int digi_port_probe(struct usb_serial_port *port); +static int digi_port_remove(struct usb_serial_port *port); static void digi_read_bulk_callback(struct urb *urb); static int digi_read_inb_callback(struct urb *urb); static int digi_read_oob_callback(struct urb *urb); @@ -294,6 +292,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver digi_acceleport_4_device = { @@ -320,6 +320,8 @@ static struct usb_serial_driver digi_acceleport_4_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -1240,59 +1242,50 @@ static int digi_startup_device(struct usb_serial *serial) return ret; } - -static int digi_startup(struct usb_serial *serial) +static int digi_port_init(struct usb_serial_port *port, unsigned port_num) { - - int i; struct digi_port *priv; - struct digi_serial *serial_priv; - /* allocate the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) { - /* allocate port private structure */ - priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); - if (priv == NULL) { - while (--i >= 0) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* initialize port private structure */ - spin_lock_init(&priv->dp_port_lock); - priv->dp_port_num = i; - priv->dp_out_buf_len = 0; - priv->dp_write_urb_in_use = 0; - priv->dp_modem_signals = 0; - init_waitqueue_head(&priv->dp_modem_change_wait); - priv->dp_transmit_idle = 0; - init_waitqueue_head(&priv->dp_transmit_idle_wait); - priv->dp_throttled = 0; - priv->dp_throttle_restart = 0; - init_waitqueue_head(&priv->dp_flush_wait); - init_waitqueue_head(&priv->dp_close_wait); - INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); - priv->dp_port = serial->port[i]; - /* initialize write wait queue for this port */ - init_waitqueue_head(&serial->port[i]->write_wait); - - usb_set_serial_port_data(serial->port[i], priv); - } + spin_lock_init(&priv->dp_port_lock); + priv->dp_port_num = port_num; + init_waitqueue_head(&priv->dp_modem_change_wait); + init_waitqueue_head(&priv->dp_transmit_idle_wait); + init_waitqueue_head(&priv->dp_flush_wait); + init_waitqueue_head(&priv->dp_close_wait); + INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = port; - /* allocate serial private structure */ - serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL); - if (serial_priv == NULL) { - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + init_waitqueue_head(&port->write_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int digi_startup(struct usb_serial *serial) +{ + struct digi_serial *serial_priv; + int ret; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; - /* initialize serial private structure */ spin_lock_init(&serial_priv->ds_serial_lock); serial_priv->ds_oob_port_num = serial->type->num_ports; serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; - serial_priv->ds_device_started = 0; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); + if (ret) { + kfree(serial_priv); + return ret; + } + usb_set_serial_data(serial, serial_priv); return 0; @@ -1313,15 +1306,35 @@ static void digi_disconnect(struct usb_serial *serial) static void digi_release(struct usb_serial *serial) { - int i; + struct digi_serial *serial_priv; + struct digi_port *priv; + + serial_priv = usb_get_serial_data(serial); + + priv = usb_get_serial_port_data(serial_priv->ds_oob_port); + kfree(priv); + + kfree(serial_priv); +} + +static int digi_port_probe(struct usb_serial_port *port) +{ + unsigned port_num; - /* free the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - kfree(usb_get_serial_data(serial)); + port_num = port->number - port->serial->minor; + + return digi_port_init(port, port_num); } +static int digi_port_remove(struct usb_serial_port *port) +{ + struct digi_port *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static void digi_read_bulk_callback(struct urb *urb) { diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 43ede4a..0f65861 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -28,10 +28,6 @@ #include <linux/usb.h> #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v1.3" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>" #define DRIVER_DESC "USB Empeg Mark I/II Driver" diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 2444771..6e4eb57 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -318,39 +318,30 @@ static int f81232_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } -static int f81232_startup(struct usb_serial *serial) +static int f81232_port_probe(struct usb_serial_port *port) { struct f81232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[i], priv); - } - return 0; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; } -static void f81232_release(struct usb_serial *serial) +static int f81232_port_remove(struct usb_serial_port *port) { - int i; struct f81232_private *priv; - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static struct usb_serial_driver f81232_device = { @@ -373,8 +364,8 @@ static struct usb_serial_driver f81232_device = { .tiocmset = f81232_tiocmset, .process_read_urb = f81232_process_read_urb, .read_int_callback = f81232_read_int_callback, - .attach = f81232_startup, - .release = f81232_release, + .port_probe = f81232_port_probe, + .port_remove = f81232_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index be84587..8c3379b 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -73,7 +73,6 @@ struct ftdi_private { char prev_status; /* Used for TIOCMIWAIT */ bool dev_gone; /* Used to abort TIOCMIWAIT */ char transmit_empty; /* If transmitter is empty or not */ - struct usb_serial_port *port; __u16 interface; /* FT2232C, FT2232H or FT4232H port interface (0 for FT232/245) */ @@ -923,6 +922,9 @@ static int ftdi_get_icount(struct tty_struct *tty, static int ftdi_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static void ftdi_break_ctl(struct tty_struct *tty, int break_state); +static int ftdi_chars_in_buffer(struct tty_struct *tty); +static int ftdi_get_modem_status(struct tty_struct *tty, + unsigned char status[2]); static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); static unsigned short int ftdi_232am_baud_to_divisor(int baud); @@ -957,6 +959,7 @@ static struct usb_serial_driver ftdi_sio_device = { .ioctl = ftdi_ioctl, .set_termios = ftdi_set_termios, .break_ctl = ftdi_break_ctl, + .chars_in_buffer = ftdi_chars_in_buffer, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -1090,6 +1093,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, __func__, (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); + rv = usb_translate_errors(rv); } else { dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__, (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", @@ -1682,7 +1686,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) kref_init(&priv->kref); mutex_init(&priv->cfg_lock); - memset(&priv->icount, 0x00, sizeof(priv->icount)); init_waitqueue_head(&priv->delta_msr_wait); priv->flags = ASYNC_LOW_LATENCY; @@ -1691,7 +1694,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) if (quirk && quirk->port_probe) quirk->port_probe(priv); - priv->port = port; usb_set_serial_port_data(port, priv); ftdi_determine_type(port); @@ -2089,6 +2091,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) } +static int ftdi_chars_in_buffer(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + int chars; + unsigned char buf[2]; + int ret; + + chars = usb_serial_generic_chars_in_buffer(tty); + if (chars) + goto out; + + /* Check if hardware buffer is empty. */ + ret = ftdi_get_modem_status(tty, buf); + if (ret == 2) { + if (!(buf[1] & FTDI_RS_TEMT)) + chars = 1; + } +out: + dev_dbg(&port->dev, "%s - %d\n", __func__, chars); + + return chars; +} + /* old_termios contains the original termios settings and tty->termios contains * the new setting to be used * WARNING: set_termios calls this with old_termios in kernel space @@ -2272,7 +2297,14 @@ no_c_cflag_changes: } } -static int ftdi_tiocmget(struct tty_struct *tty) +/* + * Get modem-control status. + * + * Returns the number of status bytes retrieved (device dependant), or + * negative error code. + */ +static int ftdi_get_modem_status(struct tty_struct *tty, + unsigned char status[2]) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -2312,16 +2344,43 @@ static int ftdi_tiocmget(struct tty_struct *tty) FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, priv->interface, buf, len, WDR_TIMEOUT); - if (ret < 0) + if (ret < 0) { + dev_err(&port->dev, "failed to get modem status: %d\n", ret); + ret = usb_translate_errors(ret); goto out; + } - ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | - (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | - (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | - (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | - priv->last_dtr_rts; + status[0] = buf[0]; + if (ret > 1) + status[1] = buf[1]; + else + status[1] = 0; + + dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0], + status[1]); out: kfree(buf); + + return ret; +} + +static int ftdi_tiocmget(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct ftdi_private *priv = usb_get_serial_port_data(port); + unsigned char buf[2]; + int ret; + + ret = ftdi_get_modem_status(tty, buf); + if (ret < 0) + return ret; + + ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | + (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | + (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | + (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | + priv->last_dtr_rts; + return ret; } diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 3ee9264..203358d 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data) -static int garmin_attach(struct usb_serial *serial) +static int garmin_port_probe(struct usb_serial_port *port) { - int status = 0; - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = NULL; + int status; + struct garmin_data *garmin_data_p; garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { @@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial) } -static void garmin_disconnect(struct usb_serial *serial) +static int garmin_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); -} - - -static void garmin_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - kfree(garmin_data_p); + return 0; } @@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = { .close = garmin_close, .throttle = garmin_throttle, .unthrottle = garmin_unthrottle, - .attach = garmin_attach, - .disconnect = garmin_disconnect, - .release = garmin_release, + .port_probe = garmin_port_probe, + .port_remove = garmin_port_remove, .write = garmin_write, .write_room = garmin_write_room, .write_bulk_callback = garmin_write_bulk_callback, diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 2966121..2ea70a6 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -262,6 +262,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } +EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer); static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port, int index, gfp_t mem_flags) diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 0bbaf21..2cba60d 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -20,10 +20,6 @@ #include <linux/usb.h> #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v1.00" #define DRIVER_DESC "HP4x (48/49) Generic Serial driver" #define HP_VENDOR_ID 0x03f0 @@ -52,5 +48,4 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 8e6faaf..7b770c7 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -51,10 +51,6 @@ #include "io_ionsp.h" /* info for the iosp messages */ #include "io_16654.h" /* 16654 UART defines */ -/* - * Version Information - */ -#define DRIVER_VERSION "v2.7" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" #define DRIVER_DESC "Edgeport USB Serial Driver" @@ -225,6 +221,8 @@ static int edge_get_icount(struct tty_struct *tty, static int edge_startup(struct usb_serial *serial); static void edge_disconnect(struct usb_serial *serial); static void edge_release(struct usb_serial *serial); +static int edge_port_probe(struct usb_serial_port *port); +static int edge_port_remove(struct usb_serial_port *port); #include "io_tables.h" /* all of the devices that this driver supports */ @@ -2875,10 +2873,9 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; struct usb_device *dev; struct device *ddev = &serial->dev->dev; - int i, j; + int i; int response; bool interrupt_in_found; bool bulk_in_found; @@ -2961,25 +2958,6 @@ static int edge_startup(struct usb_serial *serial) /* we set up the pointers to the endpoints in the edge_open function, * as the structures aren't created yet. */ - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(ddev, "%s - Out of memory\n", __func__); - for (j = 0; j < i; ++j) { - kfree(usb_get_serial_port_data(serial->port[j])); - usb_set_serial_port_data(serial->port[j], - NULL); - } - usb_set_serial_data(serial, NULL); - kfree(edge_serial); - return -ENOMEM; - } - spin_lock_init(&edge_port->ep_lock); - edge_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], edge_port); - } - response = 0; if (edge_serial->is_epic) { @@ -3120,14 +3098,36 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); - int i; - - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); kfree(edge_serial); } +static int edge_port_probe(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + + usb_set_serial_port_data(port, edge_port); + + return 0; +} + +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + kfree(edge_port); + + return 0; +} + module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 350afdd..1511dd0 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport_4port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport_8port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -197,6 +203,8 @@ static struct usb_serial_driver epic_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a2209cd..58184f3 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -40,10 +40,6 @@ #include "io_usbvend.h" #include "io_ti.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v0.7mode043006" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" #define DRIVER_DESC "Edgeport USB Serial Driver" @@ -2532,12 +2528,7 @@ static void edge_break(struct tty_struct *tty, int break_state) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; - struct usb_device *dev; int status; - int i; - - dev = serial->dev; /* create our private serial structure */ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); @@ -2555,40 +2546,7 @@ static int edge_startup(struct usb_serial *serial) return status; } - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - goto cleanup; - } - spin_lock_init(&edge_port->ep_lock); - if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - kfree(edge_port); - goto cleanup; - } - edge_port->port = serial->port[i]; - edge_port->edge_serial = edge_serial; - usb_set_serial_port_data(serial->port[i], edge_port); - edge_port->bUartMode = default_uart_mode; - } - return 0; - -cleanup: - for (--i; i >= 0; --i) { - edge_port = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&edge_port->write_fifo); - kfree(edge_port); - usb_set_serial_port_data(serial->port[i], NULL); - } - kfree(edge_serial); - usb_set_serial_data(serial, NULL); - return -ENOMEM; } static void edge_disconnect(struct usb_serial *serial) @@ -2597,17 +2555,54 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { - int i; + kfree(usb_get_serial_data(serial)); +} + +static int edge_port_probe(struct usb_serial_port *port) +{ struct edgeport_port *edge_port; + int ret; - for (i = 0; i < serial->num_ports; ++i) { - edge_port = usb_get_serial_port_data(serial->port[i]); + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, + GFP_KERNEL); + if (ret) { + kfree(edge_port); + return -ENOMEM; + } + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + edge_port->edge_serial = usb_get_serial_data(port->serial); + edge_port->bUartMode = default_uart_mode; + + usb_set_serial_port_data(port, edge_port); + + ret = edge_create_sysfs_attrs(port); + if (ret) { kfifo_free(&edge_port->write_fifo); kfree(edge_port); + return ret; } - kfree(usb_get_serial_data(serial)); + + return 0; } +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + + edge_remove_sysfs_attrs(port); + kfifo_free(&edge_port->write_fifo); + kfree(edge_port); + + return 0; +} /* Sysfs Attributes */ @@ -2667,8 +2662,8 @@ static struct usb_serial_driver edgeport_1port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2698,8 +2693,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 1068bf2..76c9a84 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -25,11 +25,6 @@ #define KP_RETRIES 100 -/* - * Version Information - */ - -#define DRIVER_VERSION "v1.0" #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>" #define DRIVER_DESC "USB PocketPC PDA driver" diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 20a132e..155eab1 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -49,10 +49,6 @@ #include <linux/uaccess.h> #include "usb-wwan.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v0.4" #define DRIVER_AUTHOR "Roelf Diedericks" #define DRIVER_DESC "IPWireless tty driver" @@ -203,8 +199,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) return 0; } -/* fake probe - only to allocate data structures */ -static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id) +static int ipw_attach(struct usb_serial *serial) { struct usb_wwan_intf_private *data; @@ -303,9 +298,9 @@ static struct usb_serial_driver ipw_device = { .num_ports = 1, .open = ipw_open, .close = ipw_close, - .probe = ipw_probe, - .attach = usb_wwan_startup, + .attach = ipw_attach, .release = ipw_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .dtr_rts = ipw_dtr_rts, .write = usb_wwan_write, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 01da3ea..1e1fbed 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -32,10 +32,6 @@ #include "iuu_phoenix.h" #include <linux/random.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v0.12" #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" static const struct usb_device_id id_table[] = { @@ -53,6 +49,8 @@ static int iuu_cardout; static bool xmas; static int vcc_default = 5; +static int iuu_create_sysfs_attrs(struct usb_serial_port *port); +static int iuu_remove_sysfs_attrs(struct usb_serial_port *port); static void read_rxcmd_callback(struct urb *urb); struct iuu_private { @@ -72,63 +70,55 @@ struct iuu_private { u32 clk; }; - -static void iuu_free_buf(struct iuu_private *priv) -{ - kfree(priv->buf); - kfree(priv->writebuf); -} - -static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv) -{ - priv->buf = kzalloc(256, GFP_KERNEL); - priv->writebuf = kzalloc(256, GFP_KERNEL); - if (!priv->buf || !priv->writebuf) { - iuu_free_buf(priv); - dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__); - return -ENOMEM; - } - dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__); - return 0; -} - -static int iuu_startup(struct usb_serial *serial) +static int iuu_port_probe(struct usb_serial_port *port) { struct iuu_private *priv; + int ret; priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); - dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__); if (!priv) return -ENOMEM; - if (iuu_alloc_buf(serial, priv)) { + + priv->buf = kzalloc(256, GFP_KERNEL); + if (!priv->buf) { kfree(priv); return -ENOMEM; } + + priv->writebuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->buf); + kfree(priv); + return -ENOMEM; + } + priv->vcc = vcc_default; spin_lock_init(&priv->lock); init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[0], priv); + + usb_set_serial_port_data(port, priv); + + ret = iuu_create_sysfs_attrs(port); + if (ret) { + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); + return ret; + } + return 0; } -/* Release function */ -static void iuu_release(struct usb_serial *serial) +static int iuu_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct iuu_private *priv = usb_get_serial_port_data(port); - if (!port) - return; - - if (priv) { - iuu_free_buf(priv); - dev_dbg(&port->dev, "%s - I will free all\n", __func__); - usb_set_serial_port_data(port, NULL); - dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__); - kfree(priv); + iuu_remove_sysfs_attrs(port); + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); - dev_dbg(&port->dev, "%s priv is now kfree\n", __func__); - } + return 0; } static int iuu_tiocmset(struct tty_struct *tty, @@ -1170,7 +1160,7 @@ static ssize_t store_vcc_mode(struct device *dev, struct iuu_private *priv = usb_get_serial_port_data(port); unsigned long v; - if (strict_strtoul(buf, 10, &v)) { + if (kstrtoul(buf, 10, &v)) { dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n", __func__, buf); goto fail_store_vcc_mode; @@ -1215,8 +1205,6 @@ static struct usb_serial_driver iuu_device = { .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, - .port_probe = iuu_create_sysfs_attrs, - .port_remove = iuu_remove_sysfs_attrs, .open = iuu_open, .close = iuu_close, .write = iuu_uart_write, @@ -1225,8 +1213,8 @@ static struct usb_serial_driver iuu_device = { .tiocmset = iuu_tiocmset, .set_termios = iuu_set_termios, .init_termios = iuu_init_termios, - .attach = iuu_startup, - .release = iuu_release, + .port_probe = iuu_port_probe, + .port_remove = iuu_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -1240,8 +1228,6 @@ MODULE_AUTHOR("Alain Degreffe eczema@ecze.com"); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); - module_param(xmas, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(xmas, "Xmas colors enabled or not"); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 29c943d..991ca6a 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -44,10 +44,6 @@ #include <linux/usb/ezusb.h> #include "keyspan.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v1.1.5" #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" @@ -1374,13 +1370,9 @@ static struct callbacks { data in device_details */ static void keyspan_setup_urbs(struct usb_serial *serial) { - int i, j; struct keyspan_serial_private *s_priv; const struct keyspan_device_details *d_details; - struct usb_serial_port *port; - struct keyspan_port_private *p_priv; struct callbacks *cback; - int endp; s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; @@ -1404,45 +1396,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial) (serial, d_details->glocont_endpoint, USB_DIR_OUT, serial, s_priv->glocont_buf, GLOCONT_BUFLEN, cback->glocont_callback); - - /* Setup endpoints for each port specific thing */ - for (i = 0; i < d_details->num_ports; i++) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - - /* Do indat endpoints first, once for each flip */ - endp = d_details->indat_endpoints[i]; - for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { - p_priv->in_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_IN, port, - p_priv->in_buffer[j], 64, - cback->indat_callback); - } - for (; j < 2; ++j) - p_priv->in_urbs[j] = NULL; - - /* outdat endpoints also have flip */ - endp = d_details->outdat_endpoints[i]; - for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { - p_priv->out_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_OUT, port, - p_priv->out_buffer[j], 64, - cback->outdat_callback); - } - for (; j < 2; ++j) - p_priv->out_urbs[j] = NULL; - - /* inack endpoint */ - p_priv->inack_urb = keyspan_setup_urb - (serial, d_details->inack_endpoints[i], USB_DIR_IN, - port, p_priv->inack_buffer, 1, cback->inack_callback); - - /* outcont endpoint */ - p_priv->outcont_urb = keyspan_setup_urb - (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, - port, p_priv->outcont_buffer, 64, - cback->outcont_callback); - } } /* usa19 function doesn't require prescaler */ @@ -2407,9 +2360,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) static int keyspan_startup(struct usb_serial *serial) { int i, err; - struct usb_serial_port *port; struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) @@ -2432,19 +2383,6 @@ static int keyspan_startup(struct usb_serial *serial) s_priv->device_details = d_details; usb_set_serial_data(serial, s_priv); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - p_priv = kzalloc(sizeof(struct keyspan_port_private), - GFP_KERNEL); - if (!p_priv) { - dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); - return 1; - } - p_priv->device_details = d_details; - usb_set_serial_port_data(port, p_priv); - } - keyspan_setup_urbs(serial); if (s_priv->instat_urb != NULL) { @@ -2463,59 +2401,112 @@ static int keyspan_startup(struct usb_serial *serial) static void keyspan_disconnect(struct usb_serial *serial) { - int i, j; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; + struct keyspan_serial_private *s_priv; s_priv = usb_get_serial_data(serial); - /* Stop reading/writing urbs */ stop_urb(s_priv->instat_urb); stop_urb(s_priv->glocont_urb); stop_urb(s_priv->indat_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - stop_urb(p_priv->inack_urb); - stop_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - stop_urb(p_priv->in_urbs[j]); - stop_urb(p_priv->out_urbs[j]); - } - } +} + +static void keyspan_release(struct usb_serial *serial) +{ + struct keyspan_serial_private *s_priv; + + s_priv = usb_get_serial_data(serial); - /* Now free them */ usb_free_urb(s_priv->instat_urb); usb_free_urb(s_priv->indat_urb); usb_free_urb(s_priv->glocont_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - usb_free_urb(p_priv->inack_urb); - usb_free_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - usb_free_urb(p_priv->in_urbs[j]); - usb_free_urb(p_priv->out_urbs[j]); - } - } + + kfree(s_priv); } -static void keyspan_release(struct usb_serial *serial) +static int keyspan_port_probe(struct usb_serial_port *port) { - int i; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; + struct usb_serial *serial = port->serial; + struct keyspan_port_private *s_priv; + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + struct callbacks *cback; + int endp; + int port_num; + int i; s_priv = usb_get_serial_data(serial); + d_details = s_priv->device_details; - kfree(s_priv); + p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); + if (!p_priv) + return -ENOMEM; - /* Now free per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - kfree(usb_get_serial_port_data(port)); + s_priv = usb_get_serial_data(port->serial); + p_priv->device_details = d_details; + + /* Setup values for the various callback routines */ + cback = &keyspan_callbacks[d_details->msg_format]; + + port_num = port->number - port->serial->minor; + + /* Do indat endpoints first, once for each flip */ + endp = d_details->indat_endpoints[port_num]; + for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { + p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_IN, port, + p_priv->in_buffer[i], 64, + cback->indat_callback); + } + /* outdat endpoints also have flip */ + endp = d_details->outdat_endpoints[port_num]; + for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { + p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_OUT, port, + p_priv->out_buffer[i], 64, + cback->outdat_callback); + } + /* inack endpoint */ + p_priv->inack_urb = keyspan_setup_urb(serial, + d_details->inack_endpoints[port_num], + USB_DIR_IN, port, + p_priv->inack_buffer, 1, + cback->inack_callback); + /* outcont endpoint */ + p_priv->outcont_urb = keyspan_setup_urb(serial, + d_details->outcont_endpoints[port_num], + USB_DIR_OUT, port, + p_priv->outcont_buffer, 64, + cback->outcont_callback); + + usb_set_serial_port_data(port, p_priv); + + return 0; +} + +static int keyspan_port_remove(struct usb_serial_port *port) +{ + struct keyspan_port_private *p_priv; + int i; + + p_priv = usb_get_serial_port_data(port); + + stop_urb(p_priv->inack_urb); + stop_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + stop_urb(p_priv->in_urbs[i]); + stop_urb(p_priv->out_urbs[i]); + } + + usb_free_urb(p_priv->inack_urb); + usb_free_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + usb_free_urb(p_priv->in_urbs[i]); + usb_free_urb(p_priv->out_urbs[i]); } + + kfree(p_priv); + + return 0; } MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 0a8a40b..0273dda 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -42,6 +42,8 @@ static void keyspan_dtr_rts (struct usb_serial_port *port, int on); static int keyspan_startup (struct usb_serial *serial); static void keyspan_disconnect (struct usb_serial *serial); static void keyspan_release (struct usb_serial *serial); +static int keyspan_port_probe(struct usb_serial_port *port); +static int keyspan_port_remove(struct usb_serial_port *port); static int keyspan_write_room (struct tty_struct *tty); static int keyspan_write (struct tty_struct *tty, @@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_2port_device = { @@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_4port_device = { @@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index ca43ecb4..41b0109 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -42,10 +42,6 @@ #undef XIRCOM #endif -/* - * Version Information - */ -#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>" #define DRIVER_DESC "USB Keyspan PDA Converter driver" @@ -713,29 +709,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); #endif -static int keyspan_pda_startup(struct usb_serial *serial) +static int keyspan_pda_port_probe(struct usb_serial_port *port) { struct keyspan_pda_private *priv; - /* allocate the private data structures for all ports. Well, for all - one ports. */ - priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL); if (!priv) - return 1; /* error */ - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + return -ENOMEM; + INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); - priv->serial = serial; - priv->port = serial->port[0]; + priv->serial = port->serial; + priv->port = port; + + usb_set_serial_port_data(port, priv); + return 0; } -static void keyspan_pda_release(struct usb_serial *serial) +static int keyspan_pda_port_remove(struct usb_serial_port *port) { - kfree(usb_get_serial_port_data(serial->port[0])); + struct keyspan_pda_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } #ifdef KEYSPAN @@ -786,8 +786,8 @@ static struct usb_serial_driver keyspan_pda_device = { .break_ctl = keyspan_pda_break_ctl, .tiocmget = keyspan_pda_tiocmget, .tiocmset = keyspan_pda_tiocmset, - .attach = keyspan_pda_startup, - .release = keyspan_pda_release, + .port_probe = keyspan_pda_port_probe, + .port_remove = keyspan_pda_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 3f6d737..fc9e14a 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -49,10 +49,6 @@ #include <linux/usb/serial.h> #include "kl5kusb105.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v0.4" #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>" #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver" @@ -60,8 +56,8 @@ /* * Function prototypes */ -static int klsi_105_startup(struct usb_serial *serial); -static void klsi_105_release(struct usb_serial *serial); +static int klsi_105_port_probe(struct usb_serial_port *port); +static int klsi_105_port_remove(struct usb_serial_port *port); static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); static void klsi_105_close(struct usb_serial_port *port); static void klsi_105_set_termios(struct tty_struct *tty, @@ -99,8 +95,8 @@ static struct usb_serial_driver kl5kusb105d_device = { /*.break_ctl = klsi_105_break_ctl,*/ .tiocmget = klsi_105_tiocmget, .tiocmset = klsi_105_tiocmset, - .attach = klsi_105_startup, - .release = klsi_105_release, + .port_probe = klsi_105_port_probe, + .port_remove = klsi_105_port_remove, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, .process_read_urb = klsi_105_process_read_urb, @@ -223,60 +219,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, * Driver's tty interface functions */ -static int klsi_105_startup(struct usb_serial *serial) +static int klsi_105_port_probe(struct usb_serial_port *port) { struct klsi_105_private *priv; - int i; - /* check if we support the product id (see keyspan.c) - * FIXME - */ + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* allocate the private data structure */ - for (i = 0; i < serial->num_ports; i++) { - priv = kmalloc(sizeof(struct klsi_105_private), - GFP_KERNEL); - if (!priv) { - dev_dbg(&serial->interface->dev, - "%s - kmalloc for klsi_105_private failed.\n", - __func__); - i--; - goto err_cleanup; - } - /* set initial values for control structures */ - priv->cfg.pktlen = 5; - priv->cfg.baudrate = kl5kusb105a_sio_b9600; - priv->cfg.databits = kl5kusb105a_dtb_8; - priv->cfg.unknown1 = 0; - priv->cfg.unknown2 = 1; + /* set initial values for control structures */ + priv->cfg.pktlen = 5; + priv->cfg.baudrate = kl5kusb105a_sio_b9600; + priv->cfg.databits = kl5kusb105a_dtb_8; + priv->cfg.unknown1 = 0; + priv->cfg.unknown2 = 1; - priv->line_state = 0; + priv->line_state = 0; - usb_set_serial_port_data(serial->port[i], priv); + spin_lock_init(&priv->lock); - spin_lock_init(&priv->lock); + /* priv->termios is left uninitialized until port opening */ - /* priv->termios is left uninitialized until port opening */ - init_waitqueue_head(&serial->port[i]->write_wait); - } + usb_set_serial_port_data(port, priv); return 0; - -err_cleanup: - for (; i >= 0; i--) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; } -static void klsi_105_release(struct usb_serial *serial) +static int klsi_105_port_remove(struct usb_serial_port *port) { - int i; + struct klsi_105_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + return 0; } static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 5c4d2fb..b747ba6 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -38,8 +38,6 @@ #include <linux/ioctl.h> #include "kobil_sct.h" -/* Version Information */ -#define DRIVER_VERSION "21/05/2004" #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" @@ -54,8 +52,8 @@ /* Function prototypes */ -static int kobil_startup(struct usb_serial *serial); -static void kobil_release(struct usb_serial *serial); +static int kobil_port_probe(struct usb_serial_port *probe); +static int kobil_port_remove(struct usb_serial_port *probe); static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); static void kobil_close(struct usb_serial_port *port); static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -89,8 +87,8 @@ static struct usb_serial_driver kobil_device = { .description = "KOBIL USB smart card terminal", .id_table = id_table, .num_ports = 1, - .attach = kobil_startup, - .release = kobil_release, + .port_probe = kobil_port_probe, + .port_remove = kobil_port_remove, .ioctl = kobil_ioctl, .set_termios = kobil_set_termios, .init_termios = kobil_init_termios, @@ -117,9 +115,10 @@ struct kobil_private { }; -static int kobil_startup(struct usb_serial *serial) +static int kobil_port_probe(struct usb_serial_port *port) { int i; + struct usb_serial *serial = port->serial; struct kobil_private *priv; struct usb_device *pdev; struct usb_host_config *actconfig; @@ -149,7 +148,7 @@ static int kobil_startup(struct usb_serial *serial) dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n"); break; } - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); /* search for the necessary endpoints */ pdev = serial->dev; @@ -179,12 +178,14 @@ static int kobil_startup(struct usb_serial *serial) } -static void kobil_release(struct usb_serial *serial) +static int kobil_port_remove(struct usb_serial_port *port) { - int i; + struct kobil_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static void kobil_init_termios(struct tty_struct *tty) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index f394771..b691175 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -38,10 +38,6 @@ #include <linux/ioctl.h> #include "mct_u232.h" -/* - * Version Information - */ -#define DRIVER_VERSION "z2.1" /* Linux in-kernel version */ #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" @@ -49,7 +45,8 @@ * Function prototypes */ static int mct_u232_startup(struct usb_serial *serial); -static void mct_u232_release(struct usb_serial *serial); +static int mct_u232_port_probe(struct usb_serial_port *port); +static int mct_u232_port_remove(struct usb_serial_port *remove); static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port); static void mct_u232_close(struct usb_serial_port *port); static void mct_u232_dtr_rts(struct usb_serial_port *port, int on); @@ -99,7 +96,8 @@ static struct usb_serial_driver mct_u232_device = { .tiocmget = mct_u232_tiocmget, .tiocmset = mct_u232_tiocmset, .attach = mct_u232_startup, - .release = mct_u232_release, + .port_probe = mct_u232_port_probe, + .port_remove = mct_u232_port_remove, .ioctl = mct_u232_ioctl, .get_icount = mct_u232_get_icount, }; @@ -388,18 +386,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, static int mct_u232_startup(struct usb_serial *serial) { - struct mct_u232_private *priv; struct usb_serial_port *port, *rport; - priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->msr_wait); - usb_set_serial_port_data(serial->port[0], priv); - - init_waitqueue_head(&serial->port[0]->write_wait); - /* Puh, that's dirty */ port = serial->port[0]; rport = serial->port[1]; @@ -412,18 +400,31 @@ static int mct_u232_startup(struct usb_serial *serial) return 0; } /* mct_u232_startup */ +static int mct_u232_port_probe(struct usb_serial_port *port) +{ + struct mct_u232_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} -static void mct_u232_release(struct usb_serial *serial) +static int mct_u232_port_remove(struct usb_serial_port *port) { struct mct_u232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} /* mct_u232_release */ + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) { @@ -515,12 +516,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) static void mct_u232_close(struct usb_serial_port *port) { - if (port->serial->dev) { - /* shutdown our urbs */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - } + /* + * Must kill the read urb as it is actually an interrupt urb, which + * generic close thus fails to kill. + */ + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + usb_serial_generic_close(port); } /* mct_u232_close */ diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 0b257dd..3d25844 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -20,8 +20,6 @@ #include <linux/uaccess.h> #include <linux/usb/serial.h> -/* Version Information */ -#define DRIVER_VERSION "v1.2.0.0" #define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver" /* Product information. */ @@ -179,16 +177,13 @@ static void metrousb_cleanup(struct usb_serial_port *port) { dev_dbg(&port->dev, "%s\n", __func__); - if (port->serial->dev) { - /* Shutdown any interrupt in urbs. */ - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_in_urb); - } + usb_unlink_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); - /* Send deactivate cmd to device */ + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); - } + mutex_unlock(&port->serial->disc_mutex); } static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -271,51 +266,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr return retval; } -static void metrousb_shutdown(struct usb_serial *serial) +static int metrousb_port_probe(struct usb_serial_port *port) { - int i = 0; + struct metrousb_private *metro_priv; - dev_dbg(&serial->dev->dev, "%s\n", __func__); + metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL); + if (!metro_priv) + return -ENOMEM; - /* Stop reading and writing on all ports. */ - for (i = 0; i < serial->num_ports; ++i) { - /* Close any open urbs. */ - metrousb_cleanup(serial->port[i]); + spin_lock_init(&metro_priv->lock); - /* Free memory. */ - kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); + usb_set_serial_port_data(port, metro_priv); - dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", - __func__, serial->port[i]->number); - } + return 0; } -static int metrousb_startup(struct usb_serial *serial) +static int metrousb_port_remove(struct usb_serial_port *port) { struct metrousb_private *metro_priv; - struct usb_serial_port *port; - int i = 0; - dev_dbg(&serial->dev->dev, "%s\n", __func__); - - /* Loop through the serial ports setting up the private structures. - * Currently we only use one port. */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - - /* Declare memory. */ - metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); - if (!metro_priv) - return -ENOMEM; - - /* Initialize memory. */ - spin_lock_init(&metro_priv->lock); - usb_set_serial_port_data(port, metro_priv); - - dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", - __func__, port->number); - } + metro_priv = usb_get_serial_port_data(port); + kfree(metro_priv); return 0; } @@ -414,8 +385,8 @@ static struct usb_serial_driver metrousb_device = { .close = metrousb_cleanup, .read_int_callback = metrousb_read_int_callback, .write_int_callback = metrousb_write_int_callback, - .attach = metrousb_startup, - .release = metrousb_shutdown, + .port_probe = metrousb_port_probe, + .port_remove = metrousb_port_remove, .throttle = metrousb_throttle, .unthrottle = metrousb_unthrottle, .tiocmget = metrousb_tiocmget, diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 1bf1ad0..f57a6b1 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -36,10 +36,6 @@ #include <linux/uaccess.h> #include <linux/parport.h> -/* - * Version Information - */ -#define DRIVER_VERSION "2.1" #define DRIVER_AUTHOR "Aspire Communications pvt Ltd." #define DRIVER_DESC "Moschip USB Serial Driver" @@ -1966,9 +1962,7 @@ static int mos7720_ioctl(struct tty_struct *tty, static int mos7720_startup(struct usb_serial *serial) { - struct moschip_port *mos7720_port; struct usb_device *dev; - int i; char data; u16 product; int ret_val; @@ -1999,29 +1993,6 @@ static int mos7720_startup(struct usb_serial *serial) serial->port[1]->interrupt_in_buffer = NULL; } - - /* set up serial port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); - if (mos7720_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - return -ENOMEM; - } - - /* Initialize all port interrupt end point to port 0 int - * endpoint. Our device has only one interrupt endpoint - * common to all ports */ - serial->port[i]->interrupt_in_endpointAddress = - serial->port[0]->interrupt_in_endpointAddress; - - mos7720_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], mos7720_port); - - dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number); - dev_dbg(&dev->dev, "serial number is %d\n", serial->minor); - } - - /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); @@ -2049,8 +2020,6 @@ static int mos7720_startup(struct usb_serial *serial) static void mos7720_release(struct usb_serial *serial) { - int i; - #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT /* close the parallel port */ @@ -2089,9 +2058,36 @@ static void mos7720_release(struct usb_serial *serial) kref_put(&mos_parport->ref_count, destroy_mos_parport); } #endif - /* free private structure allocated for serial port */ - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); +} + +static int mos7720_port_probe(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL); + if (!mos7720_port) + return -ENOMEM; + + /* Initialize all port interrupt end point to port 0 int endpoint. + * Our device has only one interrupt endpoint common to all ports. + */ + port->interrupt_in_endpointAddress = + port->serial->port[0]->interrupt_in_endpointAddress; + mos7720_port->port = port; + + usb_set_serial_port_data(port, mos7720_port); + + return 0; +} + +static int mos7720_port_remove(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = usb_get_serial_port_data(port); + kfree(mos7720_port); + + return 0; } static struct usb_serial_driver moschip7720_2port_driver = { @@ -2109,6 +2105,8 @@ static struct usb_serial_driver moschip7720_2port_driver = { .probe = mos77xx_probe, .attach = mos7720_startup, .release = mos7720_release, + .port_probe = mos7720_port_probe, + .port_remove = mos7720_port_remove, .ioctl = mos7720_ioctl, .tiocmget = mos7720_tiocmget, .tiocmset = mos7720_tiocmset, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d6d4eec..66d9e08 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -35,10 +35,6 @@ #include <linux/usb/serial.h> #include <linux/uaccess.h> -/* - * Version Information - */ -#define DRIVER_VERSION "1.3.2" #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver" /* @@ -218,12 +214,10 @@ struct moschip_port { int port_num; /*Actual port number in the device(1,2,etc) */ struct urb *write_urb; /* write URB for this port */ struct urb *read_urb; /* read URB for this port */ - struct urb *int_urb; __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ char open; char open_ports; - char zombie; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ int delta_msr_cond; @@ -478,7 +472,6 @@ static void mos7840_control_callback(struct urb *urb) struct moschip_port *mos7840_port; struct device *dev = &urb->dev->dev; __u8 regval = 0x0; - int result = 0; int status = urb->status; mos7840_port = urb->context; @@ -495,7 +488,7 @@ static void mos7840_control_callback(struct urb *urb) return; default: dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); - goto exit; + return; } dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); @@ -508,16 +501,6 @@ static void mos7840_control_callback(struct urb *urb) mos7840_handle_new_msr(mos7840_port, regval); else if (mos7840_port->MsrLsr == 1) mos7840_handle_new_lsr(mos7840_port, regval); - -exit: - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) - result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); - spin_unlock(&mos7840_port->pool_lock); - if (result) { - dev_err(dev, "%s - Error %d submitting interrupt urb\n", - __func__, result); - } } static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, @@ -686,14 +669,7 @@ static void mos7840_interrupt_callback(struct urb *urb) wreg = MODEM_STATUS_REGISTER; break; } - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) { - rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); - } else { - spin_unlock(&mos7840_port->pool_lock); - return; - } - spin_unlock(&mos7840_port->pool_lock); + rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); } } } @@ -2347,309 +2323,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) return mos7840_num_ports; } -/**************************************************************************** - * mos7840_startup - ****************************************************************************/ - -static int mos7840_startup(struct usb_serial *serial) +static int mos7840_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct moschip_port *mos7840_port; - struct usb_device *dev; - int i, status; + int status; + int pnum; __u16 Data; - dev = serial->dev; - /* we set up the pointers to the endpoints in the mos7840_open * * function, as the structures aren't created yet. */ - /* set up port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); - mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); - if (mos7840_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - status = -ENOMEM; - i--; /* don't follow NULL pointer cleaning up */ - goto error; - } - - /* Initialize all port interrupt end point to port 0 int - * endpoint. Our device has only one interrupt end point - * common to all port */ - - mos7840_port->port = serial->port[i]; - mos7840_set_port_private(serial->port[i], mos7840_port); - spin_lock_init(&mos7840_port->pool_lock); - - /* minor is not initialised until later by - * usb-serial.c:get_free_serial() and cannot therefore be used - * to index device instances */ - mos7840_port->port_num = i + 1; - dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); - dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); - dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); - dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); - - if (mos7840_port->port_num == 1) { - mos7840_port->SpRegOffset = 0x0; - mos7840_port->ControlRegOffset = 0x1; - mos7840_port->DcrRegOffset = 0x4; - } else if ((mos7840_port->port_num == 2) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0x8; - mos7840_port->ControlRegOffset = 0x9; - mos7840_port->DcrRegOffset = 0x16; - } else if ((mos7840_port->port_num == 2) - && (serial->num_ports == 2)) { - mos7840_port->SpRegOffset = 0xa; - mos7840_port->ControlRegOffset = 0xb; - mos7840_port->DcrRegOffset = 0x19; - } else if ((mos7840_port->port_num == 3) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0xa; - mos7840_port->ControlRegOffset = 0xb; - mos7840_port->DcrRegOffset = 0x19; - } else if ((mos7840_port->port_num == 4) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0xc; - mos7840_port->ControlRegOffset = 0xd; - mos7840_port->DcrRegOffset = 0x1c; - } - mos7840_dump_serial_port(serial->port[i], mos7840_port); - mos7840_set_port_private(serial->port[i], mos7840_port); + pnum = port->number - serial->minor; - /* enable rx_disable bit in control register */ - status = mos7840_get_reg_sync(serial->port[i], - mos7840_port->ControlRegOffset, &Data); - if (status < 0) { - dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); - Data |= 0x08; /* setting driver done bit */ - Data |= 0x04; /* sp1_bit to have cts change reflect in - modem status reg */ - - /* Data |= 0x20; //rx_disable bit */ - status = mos7840_set_reg_sync(serial->port[i], - mos7840_port->ControlRegOffset, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); + dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); + mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); + if (mos7840_port == NULL) { + dev_err(&port->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; + } - /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 - and 0x24 in DCR3 */ - Data = 0x01; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + 0), Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); + /* Initialize all port interrupt end point to port 0 int + * endpoint. Our device has only one interrupt end point + * common to all port */ + + mos7840_port->port = port; + mos7840_set_port_private(port, mos7840_port); + spin_lock_init(&mos7840_port->pool_lock); + + /* minor is not initialised until later by + * usb-serial.c:get_free_serial() and cannot therefore be used + * to index device instances */ + mos7840_port->port_num = pnum + 1; + dev_dbg(&port->dev, "port->number = %d\n", port->number); + dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); + dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); + dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); + + if (mos7840_port->port_num == 1) { + mos7840_port->SpRegOffset = 0x0; + mos7840_port->ControlRegOffset = 0x1; + mos7840_port->DcrRegOffset = 0x4; + } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0x8; + mos7840_port->ControlRegOffset = 0x9; + mos7840_port->DcrRegOffset = 0x16; + } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { + mos7840_port->SpRegOffset = 0xa; + mos7840_port->ControlRegOffset = 0xb; + mos7840_port->DcrRegOffset = 0x19; + } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0xa; + mos7840_port->ControlRegOffset = 0xb; + mos7840_port->DcrRegOffset = 0x19; + } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0xc; + mos7840_port->ControlRegOffset = 0xd; + mos7840_port->DcrRegOffset = 0x1c; + } + mos7840_dump_serial_port(port, mos7840_port); + mos7840_set_port_private(port, mos7840_port); + + /* enable rx_disable bit in control register */ + status = mos7840_get_reg_sync(port, + mos7840_port->ControlRegOffset, &Data); + if (status < 0) { + dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); + Data |= 0x08; /* setting driver done bit */ + Data |= 0x04; /* sp1_bit to have cts change reflect in + modem status reg */ - Data = 0x05; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + 1), Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); + /* Data |= 0x20; //rx_disable bit */ + status = mos7840_set_reg_sync(port, + mos7840_port->ControlRegOffset, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); - Data = 0x24; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + 2), Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); + /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 + and 0x24 in DCR3 */ + Data = 0x01; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 0), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); - /* write values in clkstart0x0 and clkmulti 0x20 */ - Data = 0x0; - status = mos7840_set_reg_sync(serial->port[i], - CLK_START_VALUE_REGISTER, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); + Data = 0x05; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 1), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); - Data = 0x20; - status = mos7840_set_reg_sync(serial->port[i], - CLK_MULTI_REGISTER, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); - goto error; - } else - dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); + Data = 0x24; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 2), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); - /* write value 0x0 to scratchpad register */ - Data = 0x00; - status = mos7840_set_uart_reg(serial->port[i], - SCRATCH_PAD_REGISTER, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); + /* write values in clkstart0x0 and clkmulti 0x20 */ + Data = 0x0; + status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); - /* Zero Length flag register */ - if ((mos7840_port->port_num != 1) - && (serial->num_ports == 2)) { + Data = 0x20; + status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); + goto error; + } else + dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); - Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (ZLP_REG1 + - ((__u16)mos7840_port->port_num)), Data); - dev_dbg(&dev->dev, "ZLIP offset %x\n", + /* write value 0x0 to scratchpad register */ + Data = 0x00; + status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); + + /* Zero Length flag register */ + if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { + Data = 0xff; + status = mos7840_set_reg_sync(port, + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num)), Data); + dev_dbg(&port->dev, "ZLIP offset %x\n", (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); - break; - } else - dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); - } else { - Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (ZLP_REG1 + - ((__u16)mos7840_port->port_num) - 0x1), Data); - dev_dbg(&dev->dev, "ZLIP offset %x\n", + if (status < 0) { + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); + goto out; + } else + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); + } else { + Data = 0xff; + status = mos7840_set_reg_sync(port, + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num) - 0x1), Data); + dev_dbg(&port->dev, "ZLIP offset %x\n", (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); - break; - } else - dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); + if (status < 0) { + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); + goto out; + } else + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); - } - mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); - mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); - mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), - GFP_KERNEL); - if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || - !mos7840_port->dr) { - status = -ENOMEM; - goto error; - } + } + mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); + mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); + mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), + GFP_KERNEL); + if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || + !mos7840_port->dr) { + status = -ENOMEM; + goto error; + } - mos7840_port->has_led = false; + mos7840_port->has_led = false; - /* Initialize LED timers */ - if (device_type == MOSCHIP_DEVICE_ID_7810) { - mos7840_port->has_led = true; + /* Initialize LED timers */ + if (device_type == MOSCHIP_DEVICE_ID_7810) { + mos7840_port->has_led = true; - init_timer(&mos7840_port->led_timer1); - mos7840_port->led_timer1.function = mos7840_led_off; - mos7840_port->led_timer1.expires = - jiffies + msecs_to_jiffies(LED_ON_MS); - mos7840_port->led_timer1.data = - (unsigned long)mos7840_port; + init_timer(&mos7840_port->led_timer1); + mos7840_port->led_timer1.function = mos7840_led_off; + mos7840_port->led_timer1.expires = + jiffies + msecs_to_jiffies(LED_ON_MS); + mos7840_port->led_timer1.data = (unsigned long)mos7840_port; - init_timer(&mos7840_port->led_timer2); - mos7840_port->led_timer2.function = - mos7840_led_flag_off; - mos7840_port->led_timer2.expires = - jiffies + msecs_to_jiffies(LED_OFF_MS); - mos7840_port->led_timer2.data = - (unsigned long)mos7840_port; + init_timer(&mos7840_port->led_timer2); + mos7840_port->led_timer2.function = mos7840_led_flag_off; + mos7840_port->led_timer2.expires = + jiffies + msecs_to_jiffies(LED_OFF_MS); + mos7840_port->led_timer2.data = (unsigned long)mos7840_port; - mos7840_port->led_flag = false; + mos7840_port->led_flag = false; - /* Turn off LED */ - mos7840_set_led_sync(serial->port[i], - MODEM_CONTROL_REGISTER, 0x0300); - } + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); } +out: + if (pnum == serial->num_ports - 1) { + /* Zero Length flag enable */ + Data = 0x0f; + status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); + goto error; + } else + dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); - /* Zero Length flag enable */ - Data = 0x0f; - status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); - goto error; - } else - dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); - - /* setting configuration feature to one */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); + /* setting configuration feature to one */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + 0x03, 0x00, 0x01, 0x00, NULL, 0x00, + MOS_WDR_TIMEOUT); + } return 0; error: - for (/* nothing */; i >= 0; i--) { - mos7840_port = mos7840_get_port_private(serial->port[i]); + kfree(mos7840_port->dr); + kfree(mos7840_port->ctrl_buf); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port); - kfree(mos7840_port->dr); - kfree(mos7840_port->ctrl_buf); - usb_free_urb(mos7840_port->control_urb); - kfree(mos7840_port); - serial->port[i] = NULL; - } return status; } -/**************************************************************************** - * mos7840_disconnect - * This function is called whenever the device is removed from the usb bus. - ****************************************************************************/ - -static void mos7840_disconnect(struct usb_serial *serial) +static int mos7840_port_remove(struct usb_serial_port *port) { - int i; - unsigned long flags; struct moschip_port *mos7840_port; - /* check for the ports to be closed,close the ports and disconnect */ + mos7840_port = mos7840_get_port_private(port); - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ + if (mos7840_port->has_led) { + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - if (mos7840_port) { - spin_lock_irqsave(&mos7840_port->pool_lock, flags); - mos7840_port->zombie = 1; - spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); - usb_kill_urb(mos7840_port->control_urb); - } + del_timer_sync(&mos7840_port->led_timer1); + del_timer_sync(&mos7840_port->led_timer2); } -} - -/**************************************************************************** - * mos7840_release - * This function is called when the usb_serial structure is freed. - ****************************************************************************/ - -static void mos7840_release(struct usb_serial *serial) -{ - int i; - struct moschip_port *mos7840_port; + usb_kill_urb(mos7840_port->control_urb); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port->ctrl_buf); + kfree(mos7840_port->dr); + kfree(mos7840_port); - /* check for the ports to be closed,close the ports and disconnect */ - - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ - - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - if (mos7840_port) { - if (mos7840_port->has_led) { - /* Turn off LED */ - mos7840_set_led_sync(mos7840_port->port, - MODEM_CONTROL_REGISTER, 0x0300); - - del_timer_sync(&mos7840_port->led_timer1); - del_timer_sync(&mos7840_port->led_timer2); - } - kfree(mos7840_port->ctrl_buf); - kfree(mos7840_port->dr); - kfree(mos7840_port); - } - } + return 0; } static struct usb_serial_driver moschip7840_4port_device = { @@ -2677,9 +2593,8 @@ static struct usb_serial_driver moschip7840_4port_device = { .tiocmget = mos7840_tiocmget, .tiocmset = mos7840_tiocmset, .get_icount = mos7840_get_icount, - .attach = mos7840_startup, - .disconnect = mos7840_disconnect, - .release = mos7840_release, + .port_probe = mos7840_port_probe, + .port_remove = mos7840_port_remove, .read_bulk_callback = mos7840_bulk_in_callback, .read_int_callback = mos7840_interrupt_callback, }; diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6def58b..7818af9 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -23,10 +23,6 @@ #include <linux/usb.h> #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Alessandro Zummo" #define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver" @@ -44,8 +40,8 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static int omninet_write_room(struct tty_struct *tty); static void omninet_disconnect(struct usb_serial *serial); -static void omninet_release(struct usb_serial *serial); -static int omninet_attach(struct usb_serial *serial); +static int omninet_port_probe(struct usb_serial_port *port); +static int omninet_port_remove(struct usb_serial_port *port); static const struct usb_device_id id_table[] = { { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, @@ -62,7 +58,8 @@ static struct usb_serial_driver zyxel_omninet_device = { .description = "ZyXEL - omni.net lcd plus usb", .id_table = id_table, .num_ports = 1, - .attach = omninet_attach, + .port_probe = omninet_port_probe, + .port_remove = omninet_port_remove, .open = omninet_open, .close = omninet_close, .write = omninet_write, @@ -70,7 +67,6 @@ static struct usb_serial_driver zyxel_omninet_device = { .read_bulk_callback = omninet_read_bulk_callback, .write_bulk_callback = omninet_write_bulk_callback, .disconnect = omninet_disconnect, - .release = omninet_release, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -112,18 +108,26 @@ struct omninet_data { __u8 od_outseq; /* Sequence number for bulk_out URBs */ }; -static int omninet_attach(struct usb_serial *serial) +static int omninet_port_probe(struct usb_serial_port *port) { struct omninet_data *od; - struct usb_serial_port *port = serial->port[0]; od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); - if (!od) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", - __func__, sizeof(struct omninet_data)); + if (!od) return -ENOMEM; - } + usb_set_serial_port_data(port, od); + + return 0; +} + +static int omninet_port_remove(struct usb_serial_port *port) +{ + struct omninet_data *od; + + od = usb_get_serial_port_data(port); + kfree(od); + return 0; } @@ -279,14 +283,6 @@ static void omninet_disconnect(struct usb_serial *serial) usb_kill_urb(wport->write_urb); } - -static void omninet_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - - kfree(usb_get_serial_port_data(port)); -} - module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 41b1647..6aba731 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, { struct usb_serial *serial = port->serial; int retval; - u8 buffer[2]; + u8 *buffer; + + buffer = kzalloc(1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; buffer[0] = val; /* Send the message to the vendor control endpoint @@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, requesttype, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0, 0, buffer, 1, 0); + kfree(buffer); return retval; } @@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, if (!dr) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; - goto error; + goto error_no_dr; } dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, return count; error: + kfree(dr); +error_no_dr: usb_free_urb(urb); error_no_urb: kfree(buffer); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 30cff03..5839f4d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -28,7 +28,6 @@ device features. */ -#define DRIVER_VERSION "v0.7.2" #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" #define DRIVER_DESC "USB Driver for GSM modems" @@ -47,6 +46,7 @@ /* Function prototypes */ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id); +static int option_attach(struct usb_serial *serial); static void option_release(struct usb_serial *serial); static int option_send_setup(struct usb_serial_port *port); static void option_instat_callback(struct urb *urb); @@ -503,11 +503,19 @@ static const struct option_blacklist_info net_intf5_blacklist = { .reserved = BIT(5), }; +static const struct option_blacklist_info net_intf6_blacklist = { + .reserved = BIT(6), +}; + static const struct option_blacklist_info zte_mf626_blacklist = { .sendsetup = BIT(0) | BIT(1), .reserved = BIT(4), }; +static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -724,23 +732,23 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) }, - { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ @@ -853,13 +861,19 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, @@ -872,7 +886,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, @@ -880,13 +895,22 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */ + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1002,18 +1026,24 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_1255_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) }, @@ -1058,8 +1088,16 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, @@ -1071,15 +1109,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, @@ -1120,22 +1164,22 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, /* Pirelli */ - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) }, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) }, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) }, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) }, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, - { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012, 0xff) }, /* Cinterion */ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, @@ -1244,8 +1288,9 @@ static struct usb_serial_driver option_1port_device = { .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, - .attach = usb_wwan_startup, + .attach = option_attach, .release = option_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM @@ -1291,26 +1336,14 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; - struct option_private *priv; struct usb_interface_descriptor *iface_desc = &serial->interface->cur_altsetting->desc; struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; - /* - * D-Link DWM 652 still exposes CD-Rom emulation interface in modem - * mode. - */ - if (dev_desc->idVendor == DLINK_VENDOR_ID && - dev_desc->idProduct == DLINK_PRODUCT_DWM_652 && - iface_desc->bInterfaceClass == 0x08) + /* Never bind to the CD-Rom emulation interface */ + if (iface_desc->bInterfaceClass == 0x08) return -ENODEV; - /* Bandrich modem and AT command interface is 0xff */ - if ((dev_desc->idVendor == BANDRICH_VENDOR_ID || - dev_desc->idVendor == PIRELLI_VENDOR_ID) && - iface_desc->bInterfaceClass != 0xff) - return -ENODEV; /* * Don't bind reserved interfaces (like network ones) which often have * the same class/subclass/protocol as the serial interfaces. Look at @@ -1325,11 +1358,24 @@ static int option_probe(struct usb_serial *serial, * Don't bind network interface on Samsung GT-B3730, it is handled by * a separate module. */ - if (dev_desc->idVendor == SAMSUNG_VENDOR_ID && - dev_desc->idProduct == SAMSUNG_PRODUCT_GT_B3730 && - iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) + if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) && + dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) && + iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; + /* Store device id so we can use it during attach. */ + usb_set_serial_data(serial, (void *)id); + + return 0; +} + +static int option_attach(struct usb_serial *serial) +{ + struct usb_interface_descriptor *iface_desc; + const struct usb_device_id *id; + struct usb_wwan_intf_private *data; + struct option_private *priv; + data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1340,6 +1386,10 @@ static int option_probe(struct usb_serial *serial, return -ENOMEM; } + /* Retrieve device id stored at probe. */ + id = usb_get_serial_data(serial); + iface_desc = &serial->interface->cur_altsetting->desc; + priv->bInterfaceNumber = iface_desc->bInterfaceNumber; data->private = priv; @@ -1448,5 +1498,4 @@ static int option_send_setup(struct usb_serial_port *port) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 933241f..d217fd6 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -57,7 +57,6 @@ #define OTI6858_DESCRIPTION \ "Ours Technology Inc. OTi-6858 USB to serial adapter driver" #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>" -#define OTI6858_VERSION "0.2" static const struct usb_device_id id_table[] = { { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) }, @@ -137,8 +136,8 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int oti6858_startup(struct usb_serial *serial); -static void oti6858_release(struct usb_serial *serial); +static int oti6858_port_probe(struct usb_serial_port *port); +static int oti6858_port_remove(struct usb_serial_port *port); /* device info */ static struct usb_serial_driver oti6858_device = { @@ -161,8 +160,8 @@ static struct usb_serial_driver oti6858_device = { .write_bulk_callback = oti6858_write_bulk_callback, .write_room = oti6858_write_room, .chars_in_buffer = oti6858_chars_in_buffer, - .attach = oti6858_startup, - .release = oti6858_release, + .port_probe = oti6858_port_probe, + .port_remove = oti6858_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -331,36 +330,33 @@ static void send_data(struct work_struct *work) usb_serial_port_softint(port); } -static int oti6858_startup(struct usb_serial *serial) +static int oti6858_port_probe(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct oti6858_private *priv; - int i; - - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); - if (!priv) - break; - - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->intr_wait); -/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */ -/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */ - priv->port = port; - INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); - INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); - - usb_set_serial_port_data(serial->port[i], priv); - } - if (i == serial->num_ports) - return 0; - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->intr_wait); + priv->port = port; + INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); + INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int oti6858_port_remove(struct usb_serial_port *port) +{ + struct oti6858_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -709,15 +705,6 @@ static int oti6858_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } - -static void oti6858_release(struct usb_serial *serial) -{ - int i; - - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); -} - static void oti6858_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; @@ -911,5 +898,4 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(OTI6858_DESCRIPTION); MODULE_AUTHOR(OTI6858_AUTHOR); -MODULE_VERSION(OTI6858_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 892ebdc..6002419 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -133,12 +133,15 @@ enum pl2303_type { HX, /* HX version of the pl2303 chip */ }; +struct pl2303_serial_private { + enum pl2303_type type; +}; + struct pl2303_private { spinlock_t lock; wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; - enum pl2303_type type; }; static int pl2303_vendor_read(__u16 value, __u16 index, @@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index, static int pl2303_startup(struct usb_serial *serial) { - struct pl2303_private *priv; + struct pl2303_serial_private *spriv; enum pl2303_type type = type_0; unsigned char *buf; - int i; + + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; buf = kmalloc(10, GFP_KERNEL); - if (buf == NULL) + if (!buf) { + kfree(spriv); return -ENOMEM; + } if (serial->dev->descriptor.bDeviceClass == 0x02) type = type_0; @@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial) type = type_1; dev_dbg(&serial->interface->dev, "device type: %d\n", type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i], priv); - } + spriv->type = type; + usb_set_serial_data(serial, spriv); pl2303_vendor_read(0x8484, 0, serial, buf); pl2303_vendor_write(0x0404, 0, serial); @@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial) kfree(buf); return 0; +} -cleanup: - kfree(buf); - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; +static void pl2303_release(struct usb_serial *serial) +{ + struct pl2303_serial_private *spriv; + + spriv = usb_get_serial_data(serial); + kfree(spriv); +} + +static int pl2303_port_probe(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int pl2303_port_remove(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int set_control_lines(struct usb_device *dev, u8 value) @@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int cflag; @@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty, } if (baud > 1228800) { /* type_0, type_1 only support up to 1228800 baud */ - if (priv->type != HX) + if (spriv->type != HX) baud = 1228800; else if (baud > 6000000) baud = 6000000; @@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CRTSCTS) { - if (priv->type == HX) + if (spriv->type == HX) pl2303_vendor_write(0x0, 0x61, serial); else pl2303_vendor_write(0x0, 0x41, serial); @@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; - struct pl2303_private *priv = usb_get_serial_port_data(port); + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int result; - if (priv->type != HX) { + if (spriv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); } else { @@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) dev_err(&port->dev, "error sending break = %d\n", result); } -static void pl2303_release(struct usb_serial *serial) -{ - int i; - struct pl2303_private *priv; - - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} - static void pl2303_update_line_status(struct usb_serial_port *port, unsigned char *data, unsigned int actual_length) @@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = { .read_int_callback = pl2303_read_int_callback, .attach = pl2303_startup, .release = pl2303_release, + .port_probe = pl2303_port_probe, + .port_remove = pl2303_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index c3ddb65..aa148c2 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table); static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; struct usb_host_interface *intf = serial->interface->cur_altsetting; struct device *dev = &serial->dev->dev; int retval = -ENODEV; @@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) ifnum = intf->desc.bInterfaceNumber; dev_dbg(dev, "This Interface = %d\n", ifnum); - data = kzalloc(sizeof(struct usb_wwan_intf_private), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - spin_lock_init(&data->susp_lock); - if (nintf == 1) { /* QDL mode */ /* Gobi 2000 has a single altsetting, older ones have two */ @@ -253,20 +245,28 @@ done: } } - /* Set serial->private if not returning error */ - if (retval == 0) - usb_set_serial_data(serial, data); - else - kfree(data); - return retval; } +static int qc_attach(struct usb_serial *serial) +{ + struct usb_wwan_intf_private *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&data->susp_lock); + + usb_set_serial_data(serial, data); + + return 0; +} + static void qc_release(struct usb_serial *serial) { struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - /* Free the private data allocated in qcprobe */ usb_set_serial_data(serial, NULL); kfree(priv); } @@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, - .attach = usb_wwan_startup, + .attach = qc_attach, .release = qc_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2cdfdcc..d152be9 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -65,8 +65,6 @@ #define QT2_WRITE_BUFFER_SIZE 512 /* size of write buffer */ #define QT2_WRITE_CONTROL_SIZE 5 /* control bytes used for a write */ -/* Version Information */ -#define DRIVER_VERSION "v0.1" #define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver" #define USB_VENDOR_ID_QUATECH 0x061d @@ -143,12 +141,12 @@ static void qt2_read_bulk_callback(struct urb *urb); static void qt2_release(struct usb_serial *serial) { - int i; + struct qt2_serial_private *serial_priv; - kfree(usb_get_serial_data(serial)); + serial_priv = usb_get_serial_data(serial); - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + usb_free_urb(serial_priv->read_urb); + kfree(serial_priv); } static inline int calc_baud_divisor(int baudrate) @@ -423,11 +421,16 @@ static void qt2_close(struct usb_serial_port *port) port_priv->is_open = false; spin_lock_irqsave(&port_priv->urb_lock, flags); - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); + usb_kill_urb(port_priv->write_urb); port_priv->urb_in_use = false; spin_unlock_irqrestore(&port_priv->urb_lock, flags); + mutex_lock(&port->serial->disc_mutex); + if (port->serial->disconnected) { + mutex_unlock(&port->serial->disc_mutex); + return; + } + /* flush the port transmit buffer */ i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -459,26 +462,14 @@ static void qt2_close(struct usb_serial_port *port) dev_err(&port->dev, "%s - close port failed %i\n", __func__, i); + mutex_unlock(&port->serial->disc_mutex); } static void qt2_disconnect(struct usb_serial *serial) { struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); - struct qt2_port_private *port_priv; - int i; - - if (serial_priv->read_urb->status == -EINPROGRESS) - usb_kill_urb(serial_priv->read_urb); - - usb_free_urb(serial_priv->read_urb); - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); - usb_free_urb(port_priv->write_urb); - } + usb_kill_urb(serial_priv->read_urb); } static int get_serial_info(struct usb_serial_port *port, @@ -773,11 +764,9 @@ static void qt2_read_bulk_callback(struct urb *urb) static int qt2_setup_urbs(struct usb_serial *serial) { - struct usb_serial_port *port; struct usb_serial_port *port0; struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int pcount, status; + int status; port0 = serial->port[0]; @@ -795,46 +784,21 @@ static int qt2_setup_urbs(struct usb_serial *serial) sizeof(serial_priv->read_buffer), qt2_read_bulk_callback, serial); - /* setup write_urb for each port */ - for (pcount = 0; pcount < serial->num_ports; pcount++) { - - port = serial->port[pcount]; - port_priv = usb_get_serial_port_data(port); - - port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port_priv->write_urb) { - dev_err(&serial->dev->dev, - "failed to alloc write_urb for port %i\n", - pcount); - return -ENOMEM; - } - - usb_fill_bulk_urb(port_priv->write_urb, - serial->dev, - usb_sndbulkpipe(serial->dev, - port0-> - bulk_out_endpointAddress), - port_priv->write_buffer, - sizeof(port_priv->write_buffer), - qt2_write_bulk_callback, port); - } - status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL); if (status != 0) { dev_err(&serial->dev->dev, "%s - submit read urb failed %i\n", __func__, status); + usb_free_urb(serial_priv->read_urb); return status; } return 0; - } static int qt2_attach(struct usb_serial *serial) { struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int status, pcount; + int status; /* power on unit */ status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -854,26 +818,6 @@ static int qt2_attach(struct usb_serial *serial) usb_set_serial_data(serial, serial_priv); - for (pcount = 0; pcount < serial->num_ports; pcount++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) { - dev_err(&serial->dev->dev, - "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*port_priv)); - pcount--; - status = -ENOMEM; - goto attach_failed; - } - - spin_lock_init(&port_priv->lock); - spin_lock_init(&port_priv->urb_lock); - init_waitqueue_head(&port_priv->delta_msr_wait); - - port_priv->port = serial->port[pcount]; - - usb_set_serial_port_data(serial->port[pcount], port_priv); - } - status = qt2_setup_urbs(serial); if (status != 0) goto attach_failed; @@ -881,14 +825,53 @@ static int qt2_attach(struct usb_serial *serial) return 0; attach_failed: - for (/* empty */; pcount >= 0; pcount--) { - port_priv = usb_get_serial_port_data(serial->port[pcount]); - kfree(port_priv); - } kfree(serial_priv); return status; } +static int qt2_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct qt2_port_private *port_priv; + u8 bEndpointAddress; + + port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); + if (!port_priv) + return -ENOMEM; + + spin_lock_init(&port_priv->lock); + spin_lock_init(&port_priv->urb_lock); + init_waitqueue_head(&port_priv->delta_msr_wait); + port_priv->port = port; + + port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port_priv->write_urb) { + kfree(port_priv); + return -ENOMEM; + } + bEndpointAddress = serial->port[0]->bulk_out_endpointAddress; + usb_fill_bulk_urb(port_priv->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, bEndpointAddress), + port_priv->write_buffer, + sizeof(port_priv->write_buffer), + qt2_write_bulk_callback, port); + + usb_set_serial_port_data(port, port_priv); + + return 0; +} + +static int qt2_port_remove(struct usb_serial_port *port) +{ + struct qt2_port_private *port_priv; + + port_priv = usb_get_serial_port_data(port); + usb_free_urb(port_priv->write_urb); + kfree(port_priv); + + return 0; +} + static int qt2_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -1127,6 +1110,8 @@ static struct usb_serial_driver qt2_device = { .attach = qt2_attach, .release = qt2_release, .disconnect = qt2_disconnect, + .port_probe = qt2_port_probe, + .port_remove = qt2_port_remove, .dtr_rts = qt2_dtr_rts, .break_ctl = qt2_break_ctl, .tiocmget = qt2_tiocmget, diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index e4a1787..a76b1ae5 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -16,8 +16,6 @@ #include <linux/usb.h> #include <linux/usb/serial.h> -/* Version Information */ -#define DRIVER_VERSION "Version 0.1 09/26/2005" #define DRIVER_AUTHOR "Thomas Hergenhahn@web.de http://libnodave.sf.net" #define DRIVER_DESC "Driver for Siemens USB/MPI adapter" diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 01d882c..af06f2f 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -18,7 +18,7 @@ */ /* Uncomment to log function calls */ /* #define DEBUG */ -#define DRIVER_VERSION "v.1.7.16" + #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer" #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; @@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { - struct usb_serial_port *port; - struct sierra_port_private *portdata; - struct sierra_iface_info *himemoryp = NULL; - int i; - u8 ifnum; + struct sierra_intf_private *intfdata; + + intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + + spin_lock_init(&intfdata->susp_lock); + + usb_set_serial_data(serial, intfdata); /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial) if (nmea) sierra_vsc_set_nmea(serial->dev, 1); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for " - "sierra_port_private (%d) failed!\n", - __func__, i); - return -ENOMEM; - } - spin_lock_init(&portdata->lock); - init_usb_anchor(&portdata->active); - init_usb_anchor(&portdata->delayed); - ifnum = i; - /* Assume low memory requirements */ - portdata->num_out_urbs = N_OUT_URB; - portdata->num_in_urbs = N_IN_URB; - - /* Determine actual memory requirements */ - if (serial->num_ports == 1) { - /* Get interface number for composite device */ - ifnum = sierra_calc_interface(serial); - himemoryp = - (struct sierra_iface_info *)&typeB_interface_list; - if (is_himemory(ifnum, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - else { - himemoryp = - (struct sierra_iface_info *)&typeA_interface_list; - if (is_himemory(i, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - dev_dbg(&serial->dev->dev, - "Memory usage (urbs) interface #%d, in=%d, out=%d\n", - ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); - /* Set the port private data pointer */ - usb_set_serial_port_data(port, portdata); - } - return 0; } static void sierra_release(struct usb_serial *serial) { - int i; - struct usb_serial_port *port; + struct sierra_intf_private *intfdata; + + intfdata = usb_get_serial_data(serial); + kfree(intfdata); +} + +static int sierra_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; + const struct sierra_iface_info *himemoryp; + u8 ifnum; - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (!port) - continue; - portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - kfree(portdata); + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; + + spin_lock_init(&portdata->lock); + init_usb_anchor(&portdata->active); + init_usb_anchor(&portdata->delayed); + + /* Assume low memory requirements */ + portdata->num_out_urbs = N_OUT_URB; + portdata->num_in_urbs = N_IN_URB; + + /* Determine actual memory requirements */ + if (serial->num_ports == 1) { + /* Get interface number for composite device */ + ifnum = sierra_calc_interface(serial); + himemoryp = &typeB_interface_list; + } else { + /* This is really the usb-serial port number of the interface + * rather than the interface number. + */ + ifnum = port->number - serial->minor; + himemoryp = &typeA_interface_list; } + + if (is_himemory(ifnum, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; + } + + dev_dbg(&port->dev, + "Memory usage (urbs) interface #%d, in=%d, out=%d\n", + ifnum, portdata->num_in_urbs, portdata->num_out_urbs); + + usb_set_serial_port_data(port, portdata); + + return 0; +} + +static int sierra_port_remove(struct usb_serial_port *port) +{ + struct sierra_port_private *portdata; + + portdata = usb_get_serial_port_data(port); + kfree(portdata); + + return 0; } #ifdef CONFIG_PM @@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = { .tiocmset = sierra_tiocmset, .attach = sierra_startup, .release = sierra_release, + .port_probe = sierra_port_probe, + .port_remove = sierra_port_remove, .suspend = sierra_suspend, .resume = sierra_resume, .read_int_callback = sierra_instat_callback, @@ -1075,7 +1078,6 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(nmea, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 9716efe..a42536a 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -28,9 +28,6 @@ #include <linux/usb.h> #include <linux/usb/serial.h> - -/* Version Information */ -#define DRIVER_VERSION "v0.10" #define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" #define SPCP8x5_007_VID 0x04FC @@ -157,13 +154,10 @@ struct spcp8x5_private { u8 line_status; }; -/* desc : when device plug in,this function would be called. - * thanks to usb_serial subsystem,then do almost every things for us. And what - * we should do just alloc the buffer */ -static int spcp8x5_startup(struct usb_serial *serial) +static int spcp8x5_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct spcp8x5_private *priv; - int i; enum spcp8x5_type type = SPCP825_007_TYPE; u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); @@ -180,34 +174,27 @@ static int spcp8x5_startup(struct usb_serial *serial) type = SPCP825_PHILIP_TYPE; dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL); - if (!priv) - goto cleanup; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i] , priv); - } + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + priv->type = type; + + usb_set_serial_port_data(port , priv); return 0; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i] , NULL); - } - return -ENOMEM; } -/* call when the device plug out. free all the memory alloced by probe */ -static void spcp8x5_release(struct usb_serial *serial) +static int spcp8x5_port_remove(struct usb_serial_port *port) { - int i; + struct spcp8x5_private *priv; - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } /* set the modem control line of the device. @@ -649,8 +636,8 @@ static struct usb_serial_driver spcp8x5_device = { .ioctl = spcp8x5_ioctl, .tiocmget = spcp8x5_tiocmget, .tiocmset = spcp8x5_tiocmset, - .attach = spcp8x5_startup, - .release = spcp8x5_release, + .port_probe = spcp8x5_port_probe, + .port_remove = spcp8x5_port_remove, .process_read_urb = spcp8x5_process_read_urb, }; @@ -661,5 +648,4 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 015810b..4543ea3 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -46,8 +46,6 @@ #define FULLPWRBIT 0x00000080 #define NEXT_BOARD_POWER_BIT 0x00000004 -/* Version Information */ -#define DRIVER_VERSION "v0.1" #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver" #define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */ @@ -67,13 +65,6 @@ struct ssu100_port_private { struct async_icount icount; }; -static void ssu100_release(struct usb_serial *serial) -{ - struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); - - kfree(priv); -} - static inline int ssu100_control_msg(struct usb_device *dev, u8 request, u16 data, u16 index) { @@ -442,21 +433,33 @@ static int ssu100_ioctl(struct tty_struct *tty, static int ssu100_attach(struct usb_serial *serial) { + return ssu100_initdevice(serial->dev); +} + +static int ssu100_port_probe(struct usb_serial_port *port) +{ struct ssu100_port_private *priv; - struct usb_serial_port *port = *serial->port; priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*priv)); + if (!priv) return -ENOMEM; - } spin_lock_init(&priv->status_lock); init_waitqueue_head(&priv->delta_msr_wait); + usb_set_serial_port_data(port, priv); - return ssu100_initdevice(serial->dev); + return 0; +} + +static int ssu100_port_remove(struct usb_serial_port *port) +{ + struct ssu100_port_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int ssu100_tiocmget(struct tty_struct *tty) @@ -647,7 +650,8 @@ static struct usb_serial_driver ssu100_device = { .open = ssu100_open, .close = ssu100_close, .attach = ssu100_attach, - .release = ssu100_release, + .port_probe = ssu100_port_probe, + .port_remove = ssu100_port_remove, .dtr_rts = ssu100_dtr_rts, .process_read_urb = ssu100_process_read_urb, .tiocmget = ssu100_tiocmget, diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 6f49392..f2530d2 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -97,6 +97,8 @@ struct ti_device { static int ti_startup(struct usb_serial *serial); static void ti_release(struct usb_serial *serial); +static int ti_port_probe(struct usb_serial_port *port); +static int ti_port_remove(struct usb_serial_port *port); static int ti_open(struct tty_struct *tty, struct usb_serial_port *port); static void ti_close(struct usb_serial_port *port); static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -221,6 +223,8 @@ static struct usb_serial_driver ti_1port_device = { .num_ports = 1, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -249,6 +253,8 @@ static struct usb_serial_driver ti_2port_device = { .num_ports = 2, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -347,11 +353,8 @@ module_exit(ti_exit); static int ti_startup(struct usb_serial *serial) { struct ti_device *tdev; - struct ti_port *tport; struct usb_device *dev = serial->dev; int status; - int i; - dev_dbg(&dev->dev, "%s - product 0x%4X, num configurations %d, configuration value %d", @@ -399,42 +402,8 @@ static int ti_startup(struct usb_serial *serial) goto free_tdev; } - /* set up port structures */ - for (i = 0; i < serial->num_ports; ++i) { - tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL); - if (tport == NULL) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - status = -ENOMEM; - goto free_tports; - } - spin_lock_init(&tport->tp_lock); - tport->tp_uart_base_addr = (i == 0 ? - TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); - tport->tp_closing_wait = closing_wait; - init_waitqueue_head(&tport->tp_msr_wait); - init_waitqueue_head(&tport->tp_write_wait); - if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - kfree(tport); - status = -ENOMEM; - goto free_tports; - } - tport->tp_port = serial->port[i]; - tport->tp_tdev = tdev; - usb_set_serial_port_data(serial->port[i], tport); - tport->tp_uart_mode = 0; /* default is RS232 */ - } - return 0; -free_tports: - for (--i; i >= 0; --i) { - tport = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&tport->write_fifo); - kfree(tport); - usb_set_serial_port_data(serial->port[i], NULL); - } free_tdev: kfree(tdev); usb_set_serial_data(serial, NULL); @@ -444,21 +413,50 @@ free_tdev: static void ti_release(struct usb_serial *serial) { - int i; struct ti_device *tdev = usb_get_serial_data(serial); + + kfree(tdev); +} + +static int ti_port_probe(struct usb_serial_port *port) +{ struct ti_port *tport; - for (i = 0; i < serial->num_ports; ++i) { - tport = usb_get_serial_port_data(serial->port[i]); - if (tport) { - kfifo_free(&tport->write_fifo); - kfree(tport); - } + tport = kzalloc(sizeof(*tport), GFP_KERNEL); + if (!tport) + return -ENOMEM; + + spin_lock_init(&tport->tp_lock); + if (port == port->serial->port[0]) + tport->tp_uart_base_addr = TI_UART1_BASE_ADDR; + else + tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; + tport->tp_closing_wait = closing_wait; + init_waitqueue_head(&tport->tp_msr_wait); + init_waitqueue_head(&tport->tp_write_wait); + if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { + kfree(tport); + return -ENOMEM; } + tport->tp_port = port; + tport->tp_tdev = usb_get_serial_data(port->serial); + tport->tp_uart_mode = 0; /* default is RS232 */ - kfree(tdev); + usb_set_serial_port_data(port, tport); + + return 0; } +static int ti_port_remove(struct usb_serial_port *port) +{ + struct ti_port *tport; + + tport = usb_get_serial_port_data(port); + kfifo_free(&tport->write_fifo); + kfree(tport); + + return 0; +} static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) { diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 1f034d2..684739b 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -8,7 +8,7 @@ extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on); extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port); extern void usb_wwan_close(struct usb_serial_port *port); -extern int usb_wwan_startup(struct usb_serial *serial); +extern int usb_wwan_port_probe(struct usb_serial_port *port); extern int usb_wwan_port_remove(struct usb_serial_port *port); extern int usb_wwan_write_room(struct tty_struct *tty); extern void usb_wwan_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index e42aa39..2be2b5b 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -19,7 +19,6 @@ - controlling the baud rate doesn't make sense */ -#define DRIVER_VERSION "v0.7.2" #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" #define DRIVER_DESC "USB Driver for GSM modems" @@ -447,10 +446,12 @@ void usb_wwan_close(struct usb_serial_port *port) EXPORT_SYMBOL(usb_wwan_close); /* Helper functions used by usb_wwan_setup_urbs */ -static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, +static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, + int endpoint, int dir, void *ctx, char *buf, int len, void (*callback) (struct urb *)) { + struct usb_serial *serial = port->serial; struct urb *urb; if (endpoint == -1) @@ -472,101 +473,75 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, return urb; } -/* Setup urbs */ -static void usb_wwan_setup_urbs(struct usb_serial *serial) +int usb_wwan_port_probe(struct usb_serial_port *port) { - int i, j; - struct usb_serial_port *port; struct usb_wwan_port_private *portdata; + struct urb *urb; + u8 *buffer; + int err; + int i; - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; - /* Do indat endpoints first */ - for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_in_endpointAddress, - USB_DIR_IN, - port, - portdata-> - in_buffer[j], - IN_BUFLEN, - usb_wwan_indat_callback); - } + init_usb_anchor(&portdata->delayed); - /* outdat endpoints */ - for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_out_endpointAddress, - USB_DIR_OUT, - port, - portdata-> - out_buffer - [j], - OUT_BUFLEN, - usb_wwan_outdat_callback); - } + for (i = 0; i < N_IN_URB; i++) { + buffer = (u8 *)__get_free_page(GFP_KERNEL); + if (!buffer) + goto bail_out_error; + portdata->in_buffer[i] = buffer; + + urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress, + USB_DIR_IN, port, + buffer, IN_BUFLEN, + usb_wwan_indat_callback); + portdata->in_urbs[i] = urb; } -} - -int usb_wwan_startup(struct usb_serial *serial) -{ - int i, j, err; - struct usb_serial_port *port; - struct usb_wwan_port_private *portdata; - u8 *buffer; - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n", - __func__, i); - return 1; - } - init_usb_anchor(&portdata->delayed); + for (i = 0; i < N_OUT_URB; i++) { + if (port->bulk_out_endpointAddress == -1) + continue; - for (j = 0; j < N_IN_URB; j++) { - buffer = (u8 *) __get_free_page(GFP_KERNEL); - if (!buffer) - goto bail_out_error; - portdata->in_buffer[j] = buffer; - } + buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); + if (!buffer) + goto bail_out_error2; + portdata->out_buffer[i] = buffer; - for (j = 0; j < N_OUT_URB; j++) { - buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); - if (!buffer) - goto bail_out_error2; - portdata->out_buffer[j] = buffer; - } + urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress, + USB_DIR_OUT, port, + buffer, OUT_BUFLEN, + usb_wwan_outdat_callback); + portdata->out_urbs[i] = urb; + } - usb_set_serial_port_data(port, portdata); + usb_set_serial_port_data(port, portdata); - if (!port->interrupt_in_urb) - continue; + if (port->interrupt_in_urb) { err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (err) dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n", __func__, err); } - usb_wwan_setup_urbs(serial); + return 0; bail_out_error2: - for (j = 0; j < N_OUT_URB; j++) - kfree(portdata->out_buffer[j]); + for (i = 0; i < N_OUT_URB; i++) { + usb_free_urb(portdata->out_urbs[i]); + kfree(portdata->out_buffer[i]); + } bail_out_error: - for (j = 0; j < N_IN_URB; j++) - if (portdata->in_buffer[j]) - free_page((unsigned long)portdata->in_buffer[j]); + for (i = 0; i < N_IN_URB; i++) { + usb_free_urb(portdata->in_urbs[i]); + free_page((unsigned long)portdata->in_buffer[i]); + } kfree(portdata); - return 1; + + return -ENOMEM; } -EXPORT_SYMBOL(usb_wwan_startup); +EXPORT_SYMBOL_GPL(usb_wwan_port_probe); int usb_wwan_port_remove(struct usb_serial_port *port) { @@ -734,5 +709,4 @@ EXPORT_SYMBOL(usb_wwan_resume); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c index 0c0aa87..6299526 100644 --- a/drivers/usb/serial/vivopay-serial.c +++ b/drivers/usb/serial/vivopay-serial.c @@ -10,8 +10,6 @@ #include <linux/usb.h> #include <linux/usb/serial.h> - -#define DRIVER_VERSION "v1.0" #define DRIVER_DESC "ViVOpay USB Serial Driver" #define VIVOPAY_VENDOR_ID 0x1d5f @@ -42,5 +40,4 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>"); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 346c7ef..b9fca35 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,6 +83,8 @@ static int whiteheat_firmware_attach(struct usb_serial *serial); /* function prototypes for the Connect Tech WhiteHEAT serial converter */ static int whiteheat_attach(struct usb_serial *serial); static void whiteheat_release(struct usb_serial *serial); +static int whiteheat_port_probe(struct usb_serial_port *port); +static int whiteheat_port_remove(struct usb_serial_port *port); static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port); static void whiteheat_close(struct usb_serial_port *port); @@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = { .num_ports = 4, .attach = whiteheat_attach, .release = whiteheat_release, + .port_probe = whiteheat_port_probe, + .port_remove = whiteheat_port_remove, .open = whiteheat_open, .close = whiteheat_close, .ioctl = whiteheat_ioctl, @@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; - struct usb_serial_port *port; - struct whiteheat_private *info; struct whiteheat_hw_info *hw_info; int pipe; int ret; int alen; __u8 *command; __u8 *result; - int i; command_port = serial->port[COMMAND_PORT]; @@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial) serial->type->description, hw_info->sw_major_rev, hw_info->sw_minor_rev); - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - - info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); - if (info == NULL) { - dev_err(&port->dev, - "%s: Out of memory for port structures\n", - serial->type->description); - goto no_private; - } - - info->mcr = 0; - - usb_set_serial_port_data(port, info); - } - command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (command_info == NULL) { @@ -333,16 +318,10 @@ no_firmware: "%s: please contact support@connecttech.com\n", serial->type->description); kfree(result); + kfree(command); return -ENODEV; no_command_private: - for (i = serial->num_ports - 1; i >= 0; i--) { - port = serial->port[i]; - info = usb_get_serial_port_data(port); - kfree(info); -no_private: - ; - } kfree(result); no_result_buffer: kfree(command); @@ -350,21 +329,36 @@ no_command_buffer: return -ENOMEM; } - static void whiteheat_release(struct usb_serial *serial) { struct usb_serial_port *command_port; - struct whiteheat_private *info; - int i; /* free up our private data for our command port */ command_port = serial->port[COMMAND_PORT]; kfree(usb_get_serial_port_data(command_port)); +} - for (i = 0; i < serial->num_ports; i++) { - info = usb_get_serial_port_data(serial->port[i]); - kfree(info); - } +static int whiteheat_port_probe(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + usb_set_serial_port_data(port, info); + + return 0; +} + +static int whiteheat_port_remove(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = usb_get_serial_port_data(port); + kfree(info); + + return 0; } static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index d36446d..ea5f258 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -455,7 +455,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun) u8 buf[16]; retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len)); - if (retval < 0) + if (retval != STATUS_SUCCESS) return -EIO; US_DEBUGP("chip->status_len = %d\n", chip->status_len); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 779cd95..d305a5a 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, USB_SC_8070, USB_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, + "Casio", + "EX-N1 DigitalCamera", + USB_SC_8070, USB_PR_DEVICE, NULL, 0), + /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, "Samsung", diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 0616f23..ce31017 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -105,20 +105,15 @@ static int skel_open(struct inode *inode, struct file *file) goto exit; } - /* increment our usage count for the device */ - kref_get(&dev->kref); - - /* lock the device to allow correctly handling errors - * in resumption */ - mutex_lock(&dev->io_mutex); - retval = usb_autopm_get_interface(interface); if (retval) - goto out_err; + goto exit; + + /* increment our usage count for the device */ + kref_get(&dev->kref); /* save our object in the file's private structure */ file->private_data = dev; - mutex_unlock(&dev->io_mutex); exit: return retval; diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 231009a..1d36531 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -847,19 +847,6 @@ static void wusb_dev_bos_rm(struct wusb_dev *wusb_dev) wusb_dev->wusb_cap_descr = NULL; }; -static struct usb_wireless_cap_descriptor wusb_cap_descr_default = { - .bLength = sizeof(wusb_cap_descr_default), - .bDescriptorType = USB_DT_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_CAP_TYPE_WIRELESS_USB, - - .bmAttributes = USB_WIRELESS_BEACON_NONE, - .wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53), - .bmTFITXPowerInfo = 0, - .bmFFITXPowerInfo = 0, - .bmBandGroup = cpu_to_le16(0x0001), /* WUSB1.0[7.4.1] bottom */ - .bReserved = 0 -}; - /* * USB stack's device addition Notifier Callback * |