Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/kernel_linaro/drivers/usb/gadget/android.c b/kernel/drivers/usb/gadget/android.c
- index b13633b..2b76310 100644
- --- a/kernel_linaro/drivers/usb/gadget/android.c
- +++ b/kernel/drivers/usb/gadget/android.c
- @@ -87,8 +87,7 @@ struct android_usb_function {
- /* Optional: called when the configuration is removed */
- void (*unbind_config)(struct android_usb_function *, struct usb_configuration *);
- - /* Optional: handle ctrl requests before the device is configured
- - * and/or before the function is enabled */
- + /* Optional: handle ctrl requests before the device is configured */
- int (*ctrlrequest)(struct android_usb_function *,
- struct usb_composite_dev *,
- const struct usb_ctrlrequest *);
- @@ -164,22 +163,23 @@ static void android_work(struct work_struct *data)
- char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
- char *connected[2] = { "USB_STATE=CONNECTED", NULL };
- char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
- + char **uevent_envp = NULL;
- unsigned long flags;
- spin_lock_irqsave(&cdev->lock, flags);
- - if (cdev->config) {
- - spin_unlock_irqrestore(&cdev->lock, flags);
- - kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE,
- - configured);
- - return;
- - }
- - if (dev->connected != dev->sw_connected) {
- - dev->sw_connected = dev->connected;
- - spin_unlock_irqrestore(&cdev->lock, flags);
- - kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE,
- - dev->sw_connected ? connected : disconnected);
- + if (cdev->config)
- + uevent_envp = configured;
- + else if (dev->connected != dev->sw_connected)
- + uevent_envp = dev->connected ? connected : disconnected;
- + dev->sw_connected = dev->connected;
- + spin_unlock_irqrestore(&cdev->lock, flags);
- +
- + if (uevent_envp) {
- + kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
- + pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
- } else {
- - spin_unlock_irqrestore(&cdev->lock, flags);
- + pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
- + dev->connected, dev->sw_connected, cdev->config);
- }
- }
- @@ -823,6 +823,7 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
- sscanf(buff, "%d", &enabled);
- if (enabled && !dev->enabled) {
- + cdev->next_string_id = 0;
- /* update values in composite driver's copy of device descriptor */
- cdev->desc.idVendor = device_desc.idVendor;
- cdev->desc.idProduct = device_desc.idProduct;
- @@ -836,6 +837,8 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
- dev->enabled = true;
- } else if (!enabled && dev->enabled) {
- usb_gadget_disconnect(cdev->gadget);
- + /* Cancel pending control requests */
- + usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
- usb_remove_config(cdev, &android_config_driver);
- dev->enabled = false;
- } else {
- @@ -1057,6 +1060,12 @@ android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
- }
- }
- + /* Special case the accessory function.
- + * It needs to handle control requests before it is enabled.
- + */
- + if (value < 0)
- + value = acc_ctrlrequest(cdev, c);
- +
- if (value < 0)
- value = composite_setup(gadget, c);
- @@ -1076,9 +1085,15 @@ android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
- static void android_disconnect(struct usb_gadget *gadget)
- {
- struct android_dev *dev = _android_dev;
- + struct usb_composite_dev *cdev = get_gadget_data(gadget);
- + unsigned long flags;
- +
- + composite_disconnect(gadget);
- +
- + spin_lock_irqsave(&cdev->lock, flags);
- dev->connected = 0;
- schedule_work(&dev->work);
- - composite_disconnect(gadget);
- + spin_unlock_irqrestore(&cdev->lock, flags);
- }
- static int android_create_device(struct android_dev *dev)
- diff --git a/kernel_linaro/drivers/usb/host/ehci-hub.c b/kernel/drivers/usb/host/ehci-hub.c
- index 88cfb8f..0f3a724 100644
- --- a/kernel_linaro/drivers/usb/host/ehci-hub.c
- +++ b/kernel/drivers/usb/host/ehci-hub.c
- @@ -343,7 +343,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
- u32 temp;
- u32 power_okay;
- int i;
- - u8 resume_needed = 0;
- + unsigned long resume_needed = 0;
- if (time_before (jiffies, ehci->next_statechange))
- msleep(5);
- @@ -416,7 +416,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
- if (test_bit(i, &ehci->bus_suspended) &&
- (temp & PORT_SUSPEND)) {
- temp |= PORT_RESUME;
- - resume_needed = 1;
- + set_bit(i, &resume_needed);
- }
- ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
- }
- @@ -431,8 +431,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
- i = HCS_N_PORTS (ehci->hcs_params);
- while (i--) {
- temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
- - if (test_bit(i, &ehci->bus_suspended) &&
- - (temp & PORT_SUSPEND)) {
- + if (test_bit(i, &resume_needed)) {
- temp &= ~(PORT_RWC_BITS | PORT_RESUME);
- ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
- ehci_vdbg (ehci, "resumed port %d\n", i + 1);
- diff --git a/kernel_linaro/drivers/usb/host/ehci-omap.c b/kernel/drivers/usb/host/ehci-omap.c
- index 55a57c2..d534fa6 100644
- --- a/kernel_linaro/drivers/usb/host/ehci-omap.c
- +++ b/kernel/drivers/usb/host/ehci-omap.c
- @@ -39,8 +39,13 @@
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include <linux/usb/ulpi.h>
- -#include <plat/usb.h>
- #include <linux/regulator/consumer.h>
- +#include <linux/pm_runtime.h>
- +#include <linux/clk.h>
- +
- +#include <plat/omap_hwmod.h>
- +#include <plat/usb.h>
- +#include <plat/clock.h>
- /* EHCI Register Set */
- #define EHCI_INSNREG04 (0xA0)
- @@ -178,11 +183,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
- }
- }
- - ret = omap_usbhs_enable(dev);
- - if (ret) {
- - dev_err(dev, "failed to start usbhs with err %d\n", ret);
- - goto err_enable;
- - }
- + pm_runtime_get_sync(dev->parent);
- /*
- * An undocumented "feature" in the OMAP3 EHCI controller,
- @@ -228,10 +229,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
- return 0;
- err_add_hcd:
- - omap_usbhs_disable(dev);
- -
- -err_enable:
- - usb_put_hcd(hcd);
- + pm_runtime_put_sync(dev->parent);
- err_io:
- return ret;
- @@ -252,25 +250,87 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
- struct usb_hcd *hcd = dev_get_drvdata(dev);
- usb_remove_hcd(hcd);
- - omap_usbhs_disable(dev);
- + pm_runtime_put_sync(dev->parent);
- usb_put_hcd(hcd);
- return 0;
- }
- static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
- {
- + struct device *dev = &pdev->dev;
- struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
- - if (hcd->driver->shutdown)
- + if (hcd->driver->shutdown) {
- + pm_runtime_get_sync(dev->parent);
- hcd->driver->shutdown(hcd);
- + pm_runtime_put(dev->parent);
- + }
- +}
- +
- +static int ehci_omap_bus_suspend(struct usb_hcd *hcd)
- +{
- + struct device *dev = hcd->self.controller;
- + struct ehci_hcd_omap_platform_data *pdata;
- + struct omap_hwmod *oh;
- + struct clk *clk;
- + int ret = 0;
- + int i;
- +
- + dev_dbg(dev, "ehci_omap_bus_suspend\n");
- +
- + ret = ehci_bus_suspend(hcd);
- +
- + if (ret != 0) {
- + dev_dbg(dev, "ehci_omap_bus_suspend failed %d\n", ret);
- + return ret;
- + }
- +
- + oh = omap_hwmod_lookup(USBHS_EHCI_HWMODNAME);
- +
- + omap_hwmod_enable_ioring_wakeup(oh);
- +
- + if (dev->parent)
- + pm_runtime_put_sync(dev->parent);
- +
- + /* At the end, disable any external transceiver clocks */
- + pdata = dev->platform_data;
- + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
- + clk = pdata->transceiver_clk[i];
- + if (clk)
- + clk_disable(clk);
- + }
- +
- + return ret;
- +}
- +
- +static int ehci_omap_bus_resume(struct usb_hcd *hcd)
- +{
- + struct device *dev = hcd->self.controller;
- + struct ehci_hcd_omap_platform_data *pdata;
- + struct clk *clk;
- + int i;
- +
- + dev_dbg(dev, "ehci_omap_bus_resume\n");
- +
- + /* Re-enable any external transceiver clocks first */
- + pdata = dev->platform_data;
- + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
- + clk = pdata->transceiver_clk[i];
- + if (clk)
- + clk_enable(clk);
- + }
- +
- + if (dev->parent) {
- + pm_runtime_get_sync(dev->parent);
- + }
- +
- + return ehci_bus_resume(hcd);
- }
- static struct platform_driver ehci_hcd_omap_driver = {
- .probe = ehci_hcd_omap_probe,
- .remove = ehci_hcd_omap_remove,
- .shutdown = ehci_hcd_omap_shutdown,
- - /*.suspend = ehci_hcd_omap_suspend, */
- - /*.resume = ehci_hcd_omap_resume, */
- .driver = {
- .name = "ehci-omap",
- }
- @@ -315,8 +375,8 @@ static const struct hc_driver ehci_omap_hc_driver = {
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- - .bus_suspend = ehci_bus_suspend,
- - .bus_resume = ehci_bus_resume,
- + .bus_suspend = ehci_omap_bus_suspend,
- + .bus_resume = ehci_omap_bus_resume,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
- };
- diff --git a/kernel_linaro/drivers/usb/host/ehci-q.c b/kernel/drivers/usb/host/ehci-q.c
- index b7f9496..6c6013c 100644
- --- a/kernel_linaro/drivers/usb/host/ehci-q.c
- +++ b/kernel/drivers/usb/host/ehci-q.c
- @@ -498,6 +498,11 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
- last = list_entry (qtd->qtd_list.prev,
- struct ehci_qtd, qtd_list);
- last->hw_next = qtd->hw_next;
- + /*
- + * Make sure the new hw_next pointer is visible
- + * to the HW before freeing the old one
- + */
- + wmb();
- }
- /* remove qtd; it's recycled after possible urb completion */
- @@ -998,7 +1003,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
- /*
- * flush qh descriptor into memory immediately,
- * see comments in qh_append_tds.
- - */
- + * */
- ehci_sync_mem();
- qh_get(qh);
- @@ -1097,7 +1102,7 @@ static struct ehci_qh *qh_append_tds (
- * is added to flush 'token' immediatelly into
- * memory, so that ehci can execute the transaction
- * ASAP.
- - */
- + * */
- ehci_sync_mem();
- urb->hcpriv = qh_get (qh);
- diff --git a/kernel_linaro/drivers/usb/host/ehci-s5p.c b/kernel/drivers/usb/host/ehci-s5p.c
- index e3374c8..491a209 100644
- --- a/kernel_linaro/drivers/usb/host/ehci-s5p.c
- +++ b/kernel/drivers/usb/host/ehci-s5p.c
- @@ -86,6 +86,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
- goto fail_hcd;
- }
- + s5p_ehci->hcd = hcd;
- s5p_ehci->clk = clk_get(&pdev->dev, "usbhost");
- if (IS_ERR(s5p_ehci->clk)) {
- diff --git a/kernel_linaro/drivers/usb/host/ehci.h b/kernel/drivers/usb/host/ehci.h
- index 6fb0de8..9706c2b 100644
- --- a/kernel_linaro/drivers/usb/host/ehci.h
- +++ b/kernel/drivers/usb/host/ehci.h
- @@ -741,7 +741,7 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
- * writing buffer, so introduce the helper which can flush L2 writing
- * buffer into memory immediately, especially used to flush ehci
- * descriptor to memory.
- - */
- + * */
- #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
- static inline void ehci_sync_mem()
- {
- diff --git a/kernel_linaro/drivers/usb/host/ohci-omap3.c b/kernel/drivers/usb/host/ohci-omap3.c
- index 6048f2f..875a837 100644
- --- a/kernel_linaro/drivers/usb/host/ohci-omap3.c
- +++ b/kernel/drivers/usb/host/ohci-omap3.c
- @@ -31,6 +31,8 @@
- #include <linux/platform_device.h>
- #include <plat/usb.h>
- +#include <plat/omap_hwmod.h>
- +#include <linux/pm_runtime.h>
- /*-------------------------------------------------------------------------*/
- @@ -41,6 +43,51 @@ static int ohci_omap3_init(struct usb_hcd *hcd)
- return ohci_init(hcd_to_ohci(hcd));
- }
- +static int ohci_omap3_bus_suspend(struct usb_hcd *hcd)
- +{
- + struct device *dev = hcd->self.controller;
- + struct omap_hwmod *oh;
- + int ret = 0;
- +
- + dev_dbg(dev, "ohci_omap3_bus_suspend\n");
- +
- + ret = ohci_bus_suspend(hcd);
- +
- + /* Delay required so that after ohci suspend
- + * smart stand by can be set in the driver.
- + * required for power mangament
- + */
- + msleep(5);
- +
- + if (ret != 0) {
- + dev_dbg(dev, "ohci_omap3_bus_suspend failed %d\n", ret);
- + return ret;
- + }
- +
- + oh = omap_hwmod_lookup(USBHS_OHCI_HWMODNAME);
- +
- + omap_hwmod_enable_ioring_wakeup(oh);
- +
- + if (dev->parent)
- + pm_runtime_put_sync(dev->parent);
- +
- + return ret;
- +}
- +
- +
- +static int ohci_omap3_bus_resume(struct usb_hcd *hcd)
- +{
- + struct device *dev = hcd->self.controller;
- +
- + dev_dbg(dev, "ohci_omap3_bus_resume\n");
- +
- + if (dev->parent)
- + pm_runtime_get_sync(dev->parent);
- +
- + return ohci_bus_resume(hcd);
- +}
- +
- +
- /*-------------------------------------------------------------------------*/
- static int ohci_omap3_start(struct usb_hcd *hcd)
- @@ -104,8 +151,8 @@ static const struct hc_driver ohci_omap3_hc_driver = {
- .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,
- + .bus_suspend = ohci_omap3_bus_suspend,
- + .bus_resume = ohci_omap3_bus_resume,
- #endif
- .start_port_reset = ohci_start_port_reset,
- };
- @@ -172,11 +219,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
- hcd->rsrc_len = resource_size(res);
- hcd->regs = regs;
- - ret = omap_usbhs_enable(dev);
- - if (ret) {
- - dev_dbg(dev, "failed to start ohci\n");
- - goto err_end;
- - }
- + pm_runtime_get_sync(dev->parent);
- ohci_hcd_init(hcd_to_ohci(hcd));
- @@ -189,7 +232,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
- return 0;
- err_add_hcd:
- - omap_usbhs_disable(dev);
- + pm_runtime_get_sync(dev->parent);
- err_end:
- usb_put_hcd(hcd);
- @@ -220,9 +263,8 @@ static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
- iounmap(hcd->regs);
- usb_remove_hcd(hcd);
- - omap_usbhs_disable(dev);
- + pm_runtime_put_sync(dev->parent);
- usb_put_hcd(hcd);
- -
- return 0;
- }
- diff --git a/kernel_linaro/drivers/usb/host/pci-quirks.c b/kernel/drivers/usb/host/pci-quirks.c
- index e9f004e..629a968 100644
- --- a/kernel_linaro/drivers/usb/host/pci-quirks.c
- +++ b/kernel/drivers/usb/host/pci-quirks.c
- @@ -535,20 +535,34 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
- iounmap(base);
- }
- +static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
- + {
- + /* Pegatron Lucid (ExoPC) */
- + .matches = {
- + DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"),
- + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"),
- + },
- + },
- + {
- + /* Pegatron Lucid (Ordissimo AIRIS) */
- + .matches = {
- + DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
- + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
- + },
- + },
- + { }
- +};
- +
- static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
- void __iomem *op_reg_base,
- u32 cap, u8 offset)
- {
- int try_handoff = 1, tried_handoff = 0;
- - /* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90
- - * seconds trying the handoff on its unused controller. Skip
- - * it. */
- + /* The Pegatron Lucid tablet sporadically waits for 98 seconds trying
- + * the handoff on its unused controller. Skip it. */
- if (pdev->vendor == 0x8086 && pdev->device == 0x283a) {
- - const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME);
- - const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION);
- - if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") &&
- - dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133"))
- + if (dmi_check_system(ehci_dmi_nohandoff_table))
- try_handoff = 0;
- }
- diff --git a/kernel_linaro/drivers/usb/host/xhci-hub.c b/kernel/drivers/usb/host/xhci-hub.c
- index 0be788c..723f823 100644
- --- a/kernel_linaro/drivers/usb/host/xhci-hub.c
- +++ b/kernel/drivers/usb/host/xhci-hub.c
- @@ -463,11 +463,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
- && (temp & PORT_POWER))
- status |= USB_PORT_STAT_SUSPEND;
- }
- - if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
- + if ((temp & PORT_PLS_MASK) == XDEV_RESUME &&
- + !DEV_SUPERSPEED(temp)) {
- if ((temp & PORT_RESET) || !(temp & PORT_PE))
- goto error;
- - if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
- - bus_state->resume_done[wIndex])) {
- + if (time_after_eq(jiffies,
- + bus_state->resume_done[wIndex])) {
- xhci_dbg(xhci, "Resume USB2 port %d\n",
- wIndex + 1);
- bus_state->resume_done[wIndex] = 0;
- @@ -487,6 +488,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
- xhci_ring_device(xhci, slot_id);
- bus_state->port_c_suspend |= 1 << wIndex;
- bus_state->suspended_ports &= ~(1 << wIndex);
- + } else {
- + /*
- + * The resume has been signaling for less than
- + * 20ms. Report the port status as SUSPEND,
- + * let the usbcore check port status again
- + * and clear resume signaling later.
- + */
- + status |= USB_PORT_STAT_SUSPEND;
- }
- }
- if ((temp & PORT_PLS_MASK) == XDEV_U0
- @@ -664,7 +673,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
- xhci_dbg(xhci, "PORTSC %04x\n", temp);
- if (temp & PORT_RESET)
- goto error;
- - if (temp & XDEV_U3) {
- + if ((temp & PORT_PLS_MASK) == XDEV_U3) {
- if ((temp & PORT_PE) == 0)
- goto error;
- @@ -752,7 +761,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
- memset(buf, 0, retval);
- status = 0;
- - mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC;
- + mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC;
- spin_lock_irqsave(&xhci->lock, flags);
- /* For each port, did anything change? If so, set that bit in buf. */
- diff --git a/kernel_linaro/drivers/usb/host/xhci-ring.c b/kernel/drivers/usb/host/xhci-ring.c
- index 70cacbb..d0871ea 100644
- --- a/kernel_linaro/drivers/usb/host/xhci-ring.c
- +++ b/kernel/drivers/usb/host/xhci-ring.c
- @@ -516,8 +516,12 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
- (unsigned long long) addr);
- }
- +/* flip_cycle means flip the cycle bit of all but the first and last TRB.
- + * (The last TRB actually points to the ring enqueue pointer, which is not part
- + * of this TD.) This is used to remove partially enqueued isoc TDs from a ring.
- + */
- static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
- - struct xhci_td *cur_td)
- + struct xhci_td *cur_td, bool flip_cycle)
- {
- struct xhci_segment *cur_seg;
- union xhci_trb *cur_trb;
- @@ -531,6 +535,12 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
- * leave the pointers intact.
- */
- cur_trb->generic.field[3] &= cpu_to_le32(~TRB_CHAIN);
- + /* Flip the cycle bit (link TRBs can't be the first
- + * or last TRB).
- + */
- + if (flip_cycle)
- + cur_trb->generic.field[3] ^=
- + cpu_to_le32(TRB_CYCLE);
- xhci_dbg(xhci, "Cancel (unchain) link TRB\n");
- xhci_dbg(xhci, "Address = %p (0x%llx dma); "
- "in seg %p (0x%llx dma)\n",
- @@ -544,6 +554,11 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
- cur_trb->generic.field[2] = 0;
- /* Preserve only the cycle bit of this TRB */
- cur_trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
- + /* Flip the cycle bit except on the first or last TRB */
- + if (flip_cycle && cur_trb != cur_td->first_trb &&
- + cur_trb != cur_td->last_trb)
- + cur_trb->generic.field[3] ^=
- + cpu_to_le32(TRB_CYCLE);
- cur_trb->generic.field[3] |= cpu_to_le32(
- TRB_TYPE(TRB_TR_NOOP));
- xhci_dbg(xhci, "Cancel TRB %p (0x%llx dma) "
- @@ -722,14 +737,14 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
- cur_td->urb->stream_id,
- cur_td, &deq_state);
- else
- - td_to_noop(xhci, ep_ring, cur_td);
- + td_to_noop(xhci, ep_ring, cur_td, false);
- remove_finished_td:
- /*
- * The event handler won't see a completion for this TD anymore,
- * so remove it from the endpoint ring's TD list. Keep it in
- * the cancelled TD list for URB completion later.
- */
- - list_del(&cur_td->td_list);
- + list_del_init(&cur_td->td_list);
- }
- last_unlinked_td = cur_td;
- xhci_stop_watchdog_timer_in_irq(xhci, ep);
- @@ -757,7 +772,7 @@ remove_finished_td:
- do {
- cur_td = list_entry(ep->cancelled_td_list.next,
- struct xhci_td, cancelled_td_list);
- - list_del(&cur_td->cancelled_td_list);
- + list_del_init(&cur_td->cancelled_td_list);
- /* Clean up the cancelled URB */
- /* Doesn't matter what we pass for status, since the core will
- @@ -865,9 +880,9 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
- cur_td = list_first_entry(&ring->td_list,
- struct xhci_td,
- td_list);
- - list_del(&cur_td->td_list);
- + list_del_init(&cur_td->td_list);
- if (!list_empty(&cur_td->cancelled_td_list))
- - list_del(&cur_td->cancelled_td_list);
- + list_del_init(&cur_td->cancelled_td_list);
- xhci_giveback_urb_in_irq(xhci, cur_td,
- -ESHUTDOWN, "killed");
- }
- @@ -876,7 +891,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
- &temp_ep->cancelled_td_list,
- struct xhci_td,
- cancelled_td_list);
- - list_del(&cur_td->cancelled_td_list);
- + list_del_init(&cur_td->cancelled_td_list);
- xhci_giveback_urb_in_irq(xhci, cur_td,
- -ESHUTDOWN, "killed");
- }
- @@ -1567,10 +1582,10 @@ td_cleanup:
- else
- *status = 0;
- }
- - list_del(&td->td_list);
- + list_del_init(&td->td_list);
- /* Was this TD slated to be cancelled but completed anyway? */
- if (!list_empty(&td->cancelled_td_list))
- - list_del(&td->cancelled_td_list);
- + list_del_init(&td->cancelled_td_list);
- urb_priv->td_cnt++;
- /* Giveback the urb when all the tds are completed */
- @@ -2508,11 +2523,8 @@ static int prepare_transfer(struct xhci_hcd *xhci,
- if (td_index == 0) {
- ret = usb_hcd_link_urb_to_ep(bus_to_hcd(urb->dev->bus), urb);
- - if (unlikely(ret)) {
- - xhci_urb_free_priv(xhci, urb_priv);
- - urb->hcpriv = NULL;
- + if (unlikely(ret))
- return ret;
- - }
- }
- td->urb = urb;
- @@ -2680,6 +2692,10 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
- {
- int packets_transferred;
- + /* One TRB with a zero-length data packet. */
- + if (running_total == 0 && trb_buff_len == 0)
- + return 0;
- +
- /* All the TRB queueing functions don't count the current TRB in
- * running_total.
- */
- @@ -3121,20 +3137,15 @@ static int count_isoc_trbs_needed(struct xhci_hcd *xhci,
- struct urb *urb, int i)
- {
- int num_trbs = 0;
- - u64 addr, td_len, running_total;
- + u64 addr, td_len;
- addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset);
- td_len = urb->iso_frame_desc[i].length;
- - running_total = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1));
- - running_total &= TRB_MAX_BUFF_SIZE - 1;
- - if (running_total != 0)
- - num_trbs++;
- -
- - while (running_total < td_len) {
- + num_trbs = DIV_ROUND_UP(td_len + (addr & (TRB_MAX_BUFF_SIZE - 1)),
- + TRB_MAX_BUFF_SIZE);
- + if (num_trbs == 0)
- num_trbs++;
- - running_total += TRB_MAX_BUFF_SIZE;
- - }
- return num_trbs;
- }
- @@ -3234,6 +3245,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
- start_trb = &ep_ring->enqueue->generic;
- start_cycle = ep_ring->cycle_state;
- + urb_priv = urb->hcpriv;
- /* Queue the first TRB, even if it's zero-length */
- for (i = 0; i < num_tds; i++) {
- unsigned int total_packet_count;
- @@ -3245,9 +3257,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
- addr = start_addr + urb->iso_frame_desc[i].offset;
- td_len = urb->iso_frame_desc[i].length;
- td_remain_len = td_len;
- - /* FIXME: Ignoring zero-length packets, can those happen? */
- total_packet_count = roundup(td_len,
- le16_to_cpu(urb->ep->desc.wMaxPacketSize));
- + /* A zero-length transfer still involves at least one packet. */
- + if (total_packet_count == 0)
- + total_packet_count++;
- burst_count = xhci_get_burst_count(xhci, urb->dev, urb,
- total_packet_count);
- residue = xhci_get_last_burst_packet_count(xhci,
- @@ -3257,12 +3271,13 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
- ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
- urb->stream_id, trbs_per_td, urb, i, mem_flags);
- - if (ret < 0)
- - return ret;
- + if (ret < 0) {
- + if (i == 0)
- + return ret;
- + goto cleanup;
- + }
- - urb_priv = urb->hcpriv;
- td = urb_priv->td[i];
- -
- for (j = 0; j < trbs_per_td; j++) {
- u32 remainder = 0;
- field = TRB_TBC(burst_count) | TRB_TLBPC(residue);
- @@ -3352,6 +3367,27 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
- giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
- start_cycle, start_trb);
- return 0;
- +cleanup:
- + /* Clean up a partially enqueued isoc transfer. */
- +
- + for (i--; i >= 0; i--)
- + list_del_init(&urb_priv->td[i]->td_list);
- +
- + /* Use the first TD as a temporary variable to turn the TDs we've queued
- + * into No-ops with a software-owned cycle bit. That way the hardware
- + * won't accidentally start executing bogus TDs when we partially
- + * overwrite them. td->first_trb and td->start_seg are already set.
- + */
- + urb_priv->td[0]->last_trb = ep_ring->enqueue;
- + /* Every TRB except the first & last will have its cycle bit flipped. */
- + td_to_noop(xhci, ep_ring, urb_priv->td[0], true);
- +
- + /* Reset the ring enqueue back to the first TRB and its cycle bit. */
- + ep_ring->enqueue = urb_priv->td[0]->first_trb;
- + ep_ring->enq_seg = urb_priv->td[0]->start_seg;
- + ep_ring->cycle_state = start_cycle;
- + usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
- + return ret;
- }
- /*
- diff --git a/kernel_linaro/drivers/usb/host/xhci.c b/kernel/drivers/usb/host/xhci.c
- index 9824761..7ea48b3 100644
- --- a/kernel_linaro/drivers/usb/host/xhci.c
- +++ b/kernel/drivers/usb/host/xhci.c
- @@ -1085,8 +1085,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
- if (urb->dev->speed == USB_SPEED_FULL) {
- ret = xhci_check_maxpacket(xhci, slot_id,
- ep_index, urb);
- - if (ret < 0)
- + if (ret < 0) {
- + xhci_urb_free_priv(xhci, urb_priv);
- + urb->hcpriv = NULL;
- return ret;
- + }
- }
- /* We have a spinlock and interrupts disabled, so we must pass
- @@ -1097,6 +1100,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
- goto dying;
- ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
- slot_id, ep_index);
- + if (ret)
- + goto free_priv;
- spin_unlock_irqrestore(&xhci->lock, flags);
- } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {
- spin_lock_irqsave(&xhci->lock, flags);
- @@ -1117,6 +1122,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
- ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
- slot_id, ep_index);
- }
- + if (ret)
- + goto free_priv;
- spin_unlock_irqrestore(&xhci->lock, flags);
- } else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
- spin_lock_irqsave(&xhci->lock, flags);
- @@ -1124,6 +1131,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
- goto dying;
- ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
- slot_id, ep_index);
- + if (ret)
- + goto free_priv;
- spin_unlock_irqrestore(&xhci->lock, flags);
- } else {
- spin_lock_irqsave(&xhci->lock, flags);
- @@ -1131,18 +1140,22 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
- goto dying;
- ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,
- slot_id, ep_index);
- + if (ret)
- + goto free_priv;
- spin_unlock_irqrestore(&xhci->lock, flags);
- }
- exit:
- return ret;
- dying:
- - xhci_urb_free_priv(xhci, urb_priv);
- - urb->hcpriv = NULL;
- xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for "
- "non-responsive xHCI host.\n",
- urb->ep->desc.bEndpointAddress, urb);
- + ret = -ESHUTDOWN;
- +free_priv:
- + xhci_urb_free_priv(xhci, urb_priv);
- + urb->hcpriv = NULL;
- spin_unlock_irqrestore(&xhci->lock, flags);
- - return -ESHUTDOWN;
- + return ret;
- }
- /* Get the right ring for the given URB.
- @@ -1239,6 +1252,13 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
- if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
- xhci_dbg(xhci, "HW died, freeing TD.\n");
- urb_priv = urb->hcpriv;
- + for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
- + td = urb_priv->td[i];
- + if (!list_empty(&td->td_list))
- + list_del_init(&td->td_list);
- + if (!list_empty(&td->cancelled_td_list))
- + list_del_init(&td->cancelled_td_list);
- + }
- usb_hcd_unlink_urb_from_ep(hcd, urb);
- spin_unlock_irqrestore(&xhci->lock, flags);
- diff --git a/kernel_linaro/drivers/usb/musb/cppi_dma.c b/kernel/drivers/usb/musb/cppi_dma.c
- index 149f3f3..318fb4e 100644
- --- a/kernel_linaro/drivers/usb/musb/cppi_dma.c
- +++ b/kernel/drivers/usb/musb/cppi_dma.c
- @@ -226,8 +226,10 @@ static int cppi_controller_stop(struct dma_controller *c)
- struct cppi *controller;
- void __iomem *tibase;
- int i;
- + struct musb *musb;
- controller = container_of(c, struct cppi, controller);
- + musb = controller->musb;
- tibase = controller->tibase;
- /* DISABLE INDIVIDUAL CHANNEL Interrupts */
- @@ -289,9 +291,11 @@ cppi_channel_allocate(struct dma_controller *c,
- u8 index;
- struct cppi_channel *cppi_ch;
- void __iomem *tibase;
- + struct musb *musb;
- controller = container_of(c, struct cppi, controller);
- tibase = controller->tibase;
- + musb = controller->musb;
- /* ep0 doesn't use DMA; remember cppi indices are 0..N-1 */
- index = ep->epnum - 1;
- @@ -339,7 +343,8 @@ static void cppi_channel_release(struct dma_channel *channel)
- c = container_of(channel, struct cppi_channel, channel);
- tibase = c->controller->tibase;
- if (!c->hw_ep)
- - dev_dbg(musb->controller, "releasing idle DMA channel %p\n", c);
- + dev_dbg(c->controller->musb->controller,
- + "releasing idle DMA channel %p\n", c);
- else if (!c->transmit)
- core_rxirq_enable(tibase, c->index + 1);
- @@ -357,10 +362,11 @@ cppi_dump_rx(int level, struct cppi_channel *c, const char *tag)
- musb_ep_select(base, c->index + 1);
- - DBG(level, "RX DMA%d%s: %d left, csr %04x, "
- - "%08x H%08x S%08x C%08x, "
- - "B%08x L%08x %08x .. %08x"
- - "\n",
- + dev_dbg(c->controller->musb->controller,
- + "RX DMA%d%s: %d left, csr %04x, "
- + "%08x H%08x S%08x C%08x, "
- + "B%08x L%08x %08x .. %08x"
- + "\n",
- c->index, tag,
- musb_readl(c->controller->tibase,
- DAVINCI_RXCPPI_BUFCNT0_REG + 4 * c->index),
- @@ -387,10 +393,11 @@ cppi_dump_tx(int level, struct cppi_channel *c, const char *tag)
- musb_ep_select(base, c->index + 1);
- - DBG(level, "TX DMA%d%s: csr %04x, "
- - "H%08x S%08x C%08x %08x, "
- - "F%08x L%08x .. %08x"
- - "\n",
- + dev_dbg(c->controller->musb->controller,
- + "TX DMA%d%s: csr %04x, "
- + "H%08x S%08x C%08x %08x, "
- + "F%08x L%08x .. %08x"
- + "\n",
- c->index, tag,
- musb_readw(c->hw_ep->regs, MUSB_TXCSR),
- @@ -1022,6 +1029,7 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
- int i;
- dma_addr_t safe2ack;
- void __iomem *regs = rx->hw_ep->regs;
- + struct musb *musb = cppi->musb;
- cppi_dump_rx(6, rx, "/K");
- diff --git a/kernel_linaro/drivers/usb/musb/musb_core.c b/kernel/drivers/usb/musb/musb_core.c
- index dce7182..e2648ff 100644
- --- a/kernel_linaro/drivers/usb/musb/musb_core.c
- +++ b/kernel/drivers/usb/musb/musb_core.c
- @@ -2214,6 +2214,7 @@ static void musb_save_context(struct musb *musb)
- musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
- for (i = 0; i < musb->config->num_eps; ++i) {
- + musb_writeb(musb_base, MUSB_INDEX, i);
- epio = musb->endpoints[i].regs;
- musb->context.index_regs[i].txmaxp =
- musb_readw(epio, MUSB_TXMAXP);
- @@ -2280,6 +2281,7 @@ static void musb_restore_context(struct musb *musb)
- musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
- for (i = 0; i < musb->config->num_eps; ++i) {
- + musb_writeb(musb_base, MUSB_INDEX, i);
- epio = musb->endpoints[i].regs;
- musb_writew(epio, MUSB_TXMAXP,
- musb->context.index_regs[i].txmaxp);
- @@ -2337,7 +2339,8 @@ static int musb_suspend(struct device *dev)
- struct platform_device *pdev = to_platform_device(dev);
- unsigned long flags;
- struct musb *musb = dev_to_musb(&pdev->dev);
- -
- + if (pm_runtime_suspended(dev))
- + return 0;
- spin_lock_irqsave(&musb->lock, flags);
- if (is_peripheral_active(musb)) {
- @@ -2349,7 +2352,6 @@ static int musb_suspend(struct device *dev)
- * they will even be wakeup-enabled.
- */
- }
- -
- musb_save_context(musb);
- spin_unlock_irqrestore(&musb->lock, flags);
- @@ -2360,7 +2362,8 @@ static int musb_resume_noirq(struct device *dev)
- {
- struct platform_device *pdev = to_platform_device(dev);
- struct musb *musb = dev_to_musb(&pdev->dev);
- -
- + if (pm_runtime_suspended(dev))
- + return 0;
- musb_restore_context(musb);
- /* for static cmos like DaVinci, register values were preserved
- diff --git a/kernel_linaro/drivers/usb/musb/musb_core.h b/kernel/drivers/usb/musb/musb_core.h
- index 0e053b5..263d31c 100644
- --- a/kernel_linaro/drivers/usb/musb/musb_core.h
- +++ b/kernel/drivers/usb/musb/musb_core.h
- @@ -370,6 +370,7 @@ struct musb_context_registers {
- u8 index, testmode;
- u8 devctl, busctl, misc;
- + u32 otg_interfsel;
- struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
- };
- @@ -386,6 +387,7 @@ struct musb {
- irqreturn_t (*isr)(int, void *);
- struct work_struct irq_work;
- + struct workqueue_struct *otg_notifier_wq;
- u16 hwvers;
- /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
- @@ -497,6 +499,7 @@ struct musb {
- struct usb_gadget g; /* the gadget */
- struct usb_gadget_driver *gadget_driver; /* its driver */
- #endif
- + bool is_ac_charger:1;
- /*
- * FIXME: Remove this flag.
- @@ -518,6 +521,12 @@ struct musb {
- #endif
- };
- +struct musb_otg_work {
- + struct work_struct work;
- + enum usb_xceiv_events xceiv_event;
- + struct musb *musb;
- +};
- +
- #ifdef CONFIG_USB_GADGET_MUSB_HDRC
- static inline struct musb *gadget_to_musb(struct usb_gadget *g)
- {
- diff --git a/kernel_linaro/drivers/usb/musb/omap2430.c b/kernel/drivers/usb/musb/omap2430.c
- index c5d4c44..e685787 100644
- --- a/kernel_linaro/drivers/usb/musb/omap2430.c
- +++ b/kernel/drivers/usb/musb/omap2430.c
- @@ -230,15 +230,37 @@ static inline void omap2430_low_level_init(struct musb *musb)
- }
- /* blocking notifier support */
- +static void musb_otg_notifier_work(struct work_struct *data_notifier_work);
- +
- static int musb_otg_notifications(struct notifier_block *nb,
- unsigned long event, void *unused)
- {
- struct musb *musb = container_of(nb, struct musb, nb);
- + struct musb_otg_work *otg_work;
- +
- + otg_work = kmalloc(sizeof(struct musb_otg_work), GFP_ATOMIC);
- + if (!otg_work)
- + return notifier_from_errno(-ENOMEM);
- + INIT_WORK(&otg_work->work, musb_otg_notifier_work);
- + otg_work->xceiv_event = event;
- + otg_work->musb = musb;
- + queue_work(musb->otg_notifier_wq, &otg_work->work);
- + return 0;
- +}
- +
- +static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
- +{
- + struct musb_otg_work *otg_work =
- + container_of(data_notifier_work, struct musb_otg_work, work);
- + struct musb *musb = otg_work->musb;
- struct device *dev = musb->controller;
- struct musb_hdrc_platform_data *pdata = dev->platform_data;
- struct omap_musb_board_data *data = pdata->board_data;
- + enum usb_xceiv_events xceiv_event = otg_work->xceiv_event;
- - switch (event) {
- + kfree(otg_work);
- +
- + switch (xceiv_event) {
- case USB_EVENT_ID:
- dev_dbg(musb->controller, "ID GND\n");
- @@ -257,6 +279,11 @@ static int musb_otg_notifications(struct notifier_block *nb,
- }
- break;
- + case USB_EVENT_CHARGER:
- + dev_dbg(musb->controller, "Dedicated charger connect\n");
- + musb->is_ac_charger = true;
- + break;
- +
- case USB_EVENT_VBUS:
- dev_dbg(musb->controller, "VBUS Connect\n");
- @@ -268,6 +295,13 @@ static int musb_otg_notifications(struct notifier_block *nb,
- break;
- case USB_EVENT_NONE:
- + if (musb->is_ac_charger) {
- + dev_dbg(musb->controller,
- + "Dedicated charger disconnect\n");
- + musb->is_ac_charger = false;
- + break;
- + }
- +
- dev_dbg(musb->controller, "VBUS Disconnect\n");
- #ifdef CONFIG_USB_GADGET_MUSB_HDRC
- @@ -295,7 +329,8 @@ static int musb_otg_notifications(struct notifier_block *nb,
- static int omap2430_musb_init(struct musb *musb)
- {
- - u32 l, status = 0;
- + u32 l;
- + int status = 0;
- struct device *dev = musb->controller;
- struct musb_hdrc_platform_data *plat = dev->platform_data;
- struct omap_musb_board_data *data = plat->board_data;
- @@ -310,10 +345,17 @@ static int omap2430_musb_init(struct musb *musb)
- return -ENODEV;
- }
- + musb->otg_notifier_wq = create_singlethread_workqueue("musb-otg");
- + if (!musb->otg_notifier_wq) {
- + pr_err("HS USB OTG: cannot allocate otg event wq\n");
- + status = -ENOMEM;
- + goto err1;
- + }
- +
- status = pm_runtime_get_sync(dev);
- if (status < 0) {
- dev_err(dev, "pm_runtime_get_sync FAILED");
- - goto err1;
- + goto err2;
- }
- l = musb_readl(musb->mregs, OTG_INTERFSEL);
- @@ -346,7 +388,10 @@ static int omap2430_musb_init(struct musb *musb)
- return 0;
- +err2:
- + destroy_workqueue(musb->otg_notifier_wq);
- err1:
- + otg_put_transceiver(musb->xceiv);
- pm_runtime_disable(dev);
- return status;
- }
- @@ -400,6 +445,8 @@ static int omap2430_musb_exit(struct musb *musb)
- {
- del_timer_sync(&musb_idle_timer);
- + otg_unregister_notifier(musb->xceiv, &musb->nb);
- + destroy_workqueue(musb->otg_notifier_wq);
- omap2430_low_level_exit(musb);
- otg_put_transceiver(musb->xceiv);
- @@ -504,6 +551,9 @@ static int omap2430_runtime_suspend(struct device *dev)
- struct omap2430_glue *glue = dev_get_drvdata(dev);
- struct musb *musb = glue_to_musb(glue);
- + musb->context.otg_interfsel = musb_readl(musb->mregs,
- + OTG_INTERFSEL);
- +
- omap2430_low_level_exit(musb);
- otg_set_suspend(musb->xceiv, 1);
- @@ -516,6 +566,9 @@ static int omap2430_runtime_resume(struct device *dev)
- struct musb *musb = glue_to_musb(glue);
- omap2430_low_level_init(musb);
- + musb_writel(musb->mregs, OTG_INTERFSEL,
- + musb->context.otg_interfsel);
- +
- otg_set_suspend(musb->xceiv, 0);
- return 0;
- diff --git a/kernel_linaro/drivers/usb/otg/otg-wakelock.c b/kernel/drivers/usb/otg/otg-wakelock.c
- index 9931626..2f11472 100644
- --- a/kernel_linaro/drivers/usb/otg/otg-wakelock.c
- +++ b/kernel/drivers/usb/otg/otg-wakelock.c
- @@ -21,13 +21,15 @@
- #include <linux/spinlock.h>
- #include <linux/usb/otg.h>
- +#define TEMPORARY_HOLD_TIME 2000
- +
- static bool enabled = true;
- static struct otg_transceiver *otgwl_xceiv;
- static struct notifier_block otgwl_nb;
- /*
- * otgwl_spinlock is held while the VBUS lock is grabbed or dropped and the
- - * locked field is updated to match.
- + * held field is updated to match.
- */
- static DEFINE_SPINLOCK(otgwl_spinlock);
- @@ -39,51 +41,62 @@ static DEFINE_SPINLOCK(otgwl_spinlock);
- struct otgwl_lock {
- char name[40];
- struct wake_lock wakelock;
- - bool locked;
- + bool held;
- };
- /*
- - * VBUS present lock.
- + * VBUS present lock. Also used as a timed lock on charger
- + * connect/disconnect and USB host disconnect, to allow the system
- + * to react to the change in power.
- */
- static struct otgwl_lock vbus_lock;
- -static void otgwl_grab(struct otgwl_lock *lock)
- +static void otgwl_hold(struct otgwl_lock *lock)
- {
- - if (!lock->locked) {
- + if (!lock->held) {
- wake_lock(&lock->wakelock);
- - lock->locked = true;
- + lock->held = true;
- }
- }
- +static void otgwl_temporary_hold(struct otgwl_lock *lock)
- +{
- + wake_lock_timeout(&lock->wakelock,
- + msecs_to_jiffies(TEMPORARY_HOLD_TIME));
- + lock->held = false;
- +}
- +
- static void otgwl_drop(struct otgwl_lock *lock)
- {
- - if (lock->locked) {
- + if (lock->held) {
- wake_unlock(&lock->wakelock);
- - lock->locked = false;
- + lock->held = false;
- }
- }
- -static int otgwl_otg_notifications(struct notifier_block *nb,
- - unsigned long event, void *unused)
- +static void otgwl_handle_event(unsigned long event)
- {
- unsigned long irqflags;
- - if (!enabled)
- - return NOTIFY_OK;
- -
- spin_lock_irqsave(&otgwl_spinlock, irqflags);
- + if (!enabled) {
- + otgwl_drop(&vbus_lock);
- + spin_unlock_irqrestore(&otgwl_spinlock, irqflags);
- + return;
- + }
- +
- switch (event) {
- case USB_EVENT_VBUS:
- case USB_EVENT_ENUMERATED:
- - otgwl_grab(&vbus_lock);
- + otgwl_hold(&vbus_lock);
- break;
- case USB_EVENT_NONE:
- case USB_EVENT_ID:
- case USB_EVENT_CHARGER:
- - otgwl_drop(&vbus_lock);
- + otgwl_temporary_hold(&vbus_lock);
- break;
- default:
- @@ -91,71 +104,25 @@ static int otgwl_otg_notifications(struct notifier_block *nb,
- }
- spin_unlock_irqrestore(&otgwl_spinlock, irqflags);
- - return NOTIFY_OK;
- -}
- -
- -static void sync_with_xceiv_state(void)
- -{
- - if ((otgwl_xceiv->last_event == USB_EVENT_VBUS) ||
- - (otgwl_xceiv->last_event == USB_EVENT_ENUMERATED))
- - otgwl_grab(&vbus_lock);
- - else
- - otgwl_drop(&vbus_lock);
- }
- -static int init_for_xceiv(void)
- +static int otgwl_otg_notifications(struct notifier_block *nb,
- + unsigned long event, void *unused)
- {
- - int rv;
- -
- - if (!otgwl_xceiv) {
- - otgwl_xceiv = otg_get_transceiver();
- -
- - if (!otgwl_xceiv) {
- - pr_err("%s: No OTG transceiver found\n", __func__);
- - return -ENODEV;
- - }
- -
- - snprintf(vbus_lock.name, sizeof(vbus_lock.name), "vbus-%s",
- - dev_name(otgwl_xceiv->dev));
- - wake_lock_init(&vbus_lock.wakelock, WAKE_LOCK_SUSPEND,
- - vbus_lock.name);
- -
- - rv = otg_register_notifier(otgwl_xceiv, &otgwl_nb);
- -
- - if (rv) {
- - pr_err("%s: otg_register_notifier on transceiver %s"
- - " failed\n", __func__,
- - dev_name(otgwl_xceiv->dev));
- - otgwl_xceiv = NULL;
- - wake_lock_destroy(&vbus_lock.wakelock);
- - return rv;
- - }
- - }
- -
- - return 0;
- + otgwl_handle_event(event);
- + return NOTIFY_OK;
- }
- static int set_enabled(const char *val, const struct kernel_param *kp)
- {
- - unsigned long irqflags;
- int rv = param_set_bool(val, kp);
- if (rv)
- return rv;
- - rv = init_for_xceiv();
- -
- - if (rv)
- - return rv;
- -
- - spin_lock_irqsave(&otgwl_spinlock, irqflags);
- -
- - if (enabled)
- - sync_with_xceiv_state();
- - else
- - otgwl_drop(&vbus_lock);
- + if (otgwl_xceiv)
- + otgwl_handle_event(otgwl_xceiv->last_event);
- - spin_unlock_irqrestore(&otgwl_spinlock, irqflags);
- return 0;
- }
- @@ -169,22 +136,34 @@ MODULE_PARM_DESC(enabled, "enable wakelock when VBUS present");
- static int __init otg_wakelock_init(void)
- {
- - unsigned long irqflags;
- + int ret;
- - otgwl_nb.notifier_call = otgwl_otg_notifications;
- + otgwl_xceiv = otg_get_transceiver();
- - if (!init_for_xceiv()) {
- - spin_lock_irqsave(&otgwl_spinlock, irqflags);
- + if (!otgwl_xceiv) {
- + pr_err("%s: No OTG transceiver found\n", __func__);
- + return -ENODEV;
- + }
- - if (enabled)
- - sync_with_xceiv_state();
- + snprintf(vbus_lock.name, sizeof(vbus_lock.name), "vbus-%s",
- + dev_name(otgwl_xceiv->dev));
- + wake_lock_init(&vbus_lock.wakelock, WAKE_LOCK_SUSPEND,
- + vbus_lock.name);
- - spin_unlock_irqrestore(&otgwl_spinlock, irqflags);
- - } else {
- - enabled = false;
- + otgwl_nb.notifier_call = otgwl_otg_notifications;
- + ret = otg_register_notifier(otgwl_xceiv, &otgwl_nb);
- +
- + if (ret) {
- + pr_err("%s: otg_register_notifier on transceiver %s"
- + " failed\n", __func__,
- + dev_name(otgwl_xceiv->dev));
- + otgwl_xceiv = NULL;
- + wake_lock_destroy(&vbus_lock.wakelock);
- + return ret;
- }
- - return 0;
- + otgwl_handle_event(otgwl_xceiv->last_event);
- + return ret;
- }
- late_initcall(otg_wakelock_init);
- diff --git a/kernel_linaro/drivers/usb/otg/otg_id.c b/kernel/drivers/usb/otg/otg_id.c
- index ce22b46..8037edb 100644
- --- a/kernel_linaro/drivers/usb/otg/otg_id.c
- +++ b/kernel/drivers/usb/otg/otg_id.c
- @@ -26,6 +26,8 @@ static struct plist_head otg_id_plist =
- static struct otg_id_notifier_block *otg_id_active;
- static bool otg_id_cancelling;
- static bool otg_id_inited;
- +static int otg_id_suspended;
- +static bool otg_id_pending;
- static void otg_id_cancel(void)
- {
- @@ -139,8 +141,65 @@ void otg_id_notify(void)
- if (otg_id_cancelling)
- goto out;
- + if (otg_id_suspended != 0) {
- + otg_id_pending = true;
- + goto out;
- + }
- +
- __otg_id_notify();
- +out:
- + mutex_unlock(&otg_id_lock);
- +}
- +
- +/**
- + * otg_id_suspend
- + *
- + * Mark the otg_id subsystem as going into suspend. From here on out,
- + * any notifications will be deferred until the last otg_id client resumes.
- + * If there is a pending notification when calling this function, it will
- + * return a negative errno and expects that the caller will abort suspend.
- + * Returs 0 on success.
- + */
- +int otg_id_suspend(void)
- +{
- + int ret = 0;
- +
- + mutex_lock(&otg_id_lock);
- +
- + /*
- + * if there's a pending notification, tell the caller to abort suspend
- + */
- + if (otg_id_suspended != 0 && otg_id_pending) {
- + pr_info("otg_id: pending notification, should abort suspend\n");
- + ret = -EBUSY;
- + goto out;
- + }
- + otg_id_suspended++;
- +out:
- + mutex_unlock(&otg_id_lock);
- + return ret;
- +}
- +
- +/**
- + * otg_id_resume
- + *
- + * Inform the otg_id subsystem that a client is resuming. If this is the
- + * last client to be resumed and there's a pending notification,
- + * otg_id_notify() is called.
- + */
- +void otg_id_resume(void)
- +{
- + mutex_lock(&otg_id_lock);
- + if (WARN(!otg_id_suspended, "unbalanced otg_id_resume\n"))
- + goto out;
- + if (--otg_id_suspended == 0) {
- + if (otg_id_pending) {
- + pr_info("otg_id: had pending notification\n");
- + otg_id_pending = false;
- + __otg_id_notify();
- + }
- + }
- out:
- mutex_unlock(&otg_id_lock);
- }
- diff --git a/kernel_linaro/drivers/usb/otg/twl6030-usb.c b/kernel/drivers/usb/otg/twl6030-usb.c
- index cfb5aa7..9f51eaf 100644
- --- a/kernel_linaro/drivers/usb/otg/twl6030-usb.c
- +++ b/kernel/drivers/usb/otg/twl6030-usb.c
- @@ -63,9 +63,6 @@
- #define USB_OTG_ADP_RISE 0x19
- #define USB_OTG_REVISION 0x1A
- -/* to be moved to LDO */
- -#define TWL6030_MISC2 0xE5
- -#define TWL6030_CFG_LDO_PD2 0xF5
- #define TWL6030_BACKUP_REG 0xFA
- #define STS_HW_CONDITIONS 0x21
- @@ -95,11 +92,15 @@ struct twl6030_usb {
- struct regulator *usb3v3;
- + /* used to set vbus, in atomic path */
- + struct work_struct set_vbus_work;
- +
- int irq1;
- int irq2;
- u8 linkstat;
- u8 asleep;
- bool irq_enabled;
- + bool vbus_enable;
- unsigned long features;
- };
- @@ -215,12 +216,6 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
- /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
- twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
- - /* Program CFG_LDO_PD2 register and set VUSB bit */
- - twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
- -
- - /* Program MISC2 register and set bit VUSB_IN_VBAT */
- - twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
- -
- twl->usb3v3 = regulator_get(twl->dev, regulator_name);
- if (IS_ERR(twl->usb3v3))
- return -ENODEV;
- @@ -370,20 +365,28 @@ static int twl6030_enable_irq(struct otg_transceiver *x)
- return 0;
- }
- -static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
- +static void otg_set_vbus_work(struct work_struct *data)
- {
- - struct twl6030_usb *twl = xceiv_to_twl(x);
- -
- + struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
- + set_vbus_work);
- /*
- * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
- * register. This enables boost mode.
- */
- - if (enabled)
- + if (twl->vbus_enable)
- twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
- CHARGERUSB_CTRL1);
- - else
- + else
- twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
- CHARGERUSB_CTRL1);
- +}
- +
- +static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
- +{
- + struct twl6030_usb *twl = xceiv_to_twl(x);
- +
- + twl->vbus_enable = enabled;
- + schedule_work(&twl->set_vbus_work);
- return 0;
- }
- @@ -444,6 +447,9 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
- ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
- + INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
- +
- + twl->vbus_enable = false;
- twl->irq_enabled = true;
- status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- @@ -494,6 +500,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
- regulator_put(twl->usb3v3);
- pdata->phy_exit(twl->dev);
- device_remove_file(twl->dev, &dev_attr_vbus);
- + cancel_work_sync(&twl->set_vbus_work);
- kfree(twl);
- return 0;
- diff --git a/kernel_linaro/drivers/usb/serial/ftdi_sio.c b/kernel/drivers/usb/serial/ftdi_sio.c
- index 9afb361..f968a3d 100644
- --- a/kernel_linaro/drivers/usb/serial/ftdi_sio.c
- +++ b/kernel/drivers/usb/serial/ftdi_sio.c
- @@ -101,6 +101,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial);
- static int ftdi_mtxorb_hack_setup(struct usb_serial *serial);
- static int ftdi_NDI_device_setup(struct usb_serial *serial);
- static int ftdi_stmclite_probe(struct usb_serial *serial);
- +static int ftdi_8u2232c_probe(struct usb_serial *serial);
- static void ftdi_USB_UIRT_setup(struct ftdi_private *priv);
- static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
- @@ -128,6 +129,10 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
- .probe = ftdi_stmclite_probe,
- };
- +static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
- + .probe = ftdi_8u2232c_probe,
- +};
- +
- /*
- * The 8U232AM has the same API as the sio except for:
- * - it can support MUCH higher baudrates; up to:
- @@ -177,7 +182,8 @@ static struct usb_device_id id_table_combined [] = {
- { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
- { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
- { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
- - { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
- + { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) ,
- + .driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
- { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
- { USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
- { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
- @@ -1733,6 +1739,18 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
- return 0;
- }
- +static int ftdi_8u2232c_probe(struct usb_serial *serial)
- +{
- + struct usb_device *udev = serial->dev;
- +
- + dbg("%s", __func__);
- +
- + if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
- + return ftdi_jtag_probe(serial);
- +
- + return 0;
- +}
- +
- /*
- * First and second port on STMCLiteadaptors is reserved for JTAG interface
- * and the forth port for pio
- diff --git a/kernel_linaro/drivers/usb/serial/option.c b/kernel/drivers/usb/serial/option.c
- index 8156561..fe22e90 100644
- --- a/kernel_linaro/drivers/usb/serial/option.c
- +++ b/kernel/drivers/usb/serial/option.c
- @@ -148,6 +148,8 @@ static void option_instat_callback(struct urb *urb);
- #define HUAWEI_PRODUCT_K4505 0x1464
- #define HUAWEI_PRODUCT_K3765 0x1465
- #define HUAWEI_PRODUCT_E14AC 0x14AC
- +#define HUAWEI_PRODUCT_K3806 0x14AE
- +#define HUAWEI_PRODUCT_K4605 0x14C6
- #define HUAWEI_PRODUCT_K3770 0x14C9
- #define HUAWEI_PRODUCT_K3771 0x14CA
- #define HUAWEI_PRODUCT_K4510 0x14CB
- @@ -416,6 +418,56 @@ static void option_instat_callback(struct urb *urb);
- #define SAMSUNG_VENDOR_ID 0x04e8
- #define SAMSUNG_PRODUCT_GT_B3730 0x6889
- +/* YUGA products www.yuga-info.com*/
- +#define YUGA_VENDOR_ID 0x257A
- +#define YUGA_PRODUCT_CEM600 0x1601
- +#define YUGA_PRODUCT_CEM610 0x1602
- +#define YUGA_PRODUCT_CEM500 0x1603
- +#define YUGA_PRODUCT_CEM510 0x1604
- +#define YUGA_PRODUCT_CEM800 0x1605
- +#define YUGA_PRODUCT_CEM900 0x1606
- +
- +#define YUGA_PRODUCT_CEU818 0x1607
- +#define YUGA_PRODUCT_CEU816 0x1608
- +#define YUGA_PRODUCT_CEU828 0x1609
- +#define YUGA_PRODUCT_CEU826 0x160A
- +#define YUGA_PRODUCT_CEU518 0x160B
- +#define YUGA_PRODUCT_CEU516 0x160C
- +#define YUGA_PRODUCT_CEU528 0x160D
- +#define YUGA_PRODUCT_CEU526 0x160F
- +
- +#define YUGA_PRODUCT_CWM600 0x2601
- +#define YUGA_PRODUCT_CWM610 0x2602
- +#define YUGA_PRODUCT_CWM500 0x2603
- +#define YUGA_PRODUCT_CWM510 0x2604
- +#define YUGA_PRODUCT_CWM800 0x2605
- +#define YUGA_PRODUCT_CWM900 0x2606
- +
- +#define YUGA_PRODUCT_CWU718 0x2607
- +#define YUGA_PRODUCT_CWU716 0x2608
- +#define YUGA_PRODUCT_CWU728 0x2609
- +#define YUGA_PRODUCT_CWU726 0x260A
- +#define YUGA_PRODUCT_CWU518 0x260B
- +#define YUGA_PRODUCT_CWU516 0x260C
- +#define YUGA_PRODUCT_CWU528 0x260D
- +#define YUGA_PRODUCT_CWU526 0x260F
- +
- +#define YUGA_PRODUCT_CLM600 0x2601
- +#define YUGA_PRODUCT_CLM610 0x2602
- +#define YUGA_PRODUCT_CLM500 0x2603
- +#define YUGA_PRODUCT_CLM510 0x2604
- +#define YUGA_PRODUCT_CLM800 0x2605
- +#define YUGA_PRODUCT_CLM900 0x2606
- +
- +#define YUGA_PRODUCT_CLU718 0x2607
- +#define YUGA_PRODUCT_CLU716 0x2608
- +#define YUGA_PRODUCT_CLU728 0x2609
- +#define YUGA_PRODUCT_CLU726 0x260A
- +#define YUGA_PRODUCT_CLU518 0x260B
- +#define YUGA_PRODUCT_CLU516 0x260C
- +#define YUGA_PRODUCT_CLU528 0x260D
- +#define YUGA_PRODUCT_CLU526 0x260F
- +
- /* some devices interfaces need special handling due to a number of reasons */
- enum option_blacklist_reason {
- OPTION_BLACKLIST_NONE = 0,
- @@ -551,6 +603,8 @@ static const struct usb_device_id option_ids[] = {
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
- + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },
- + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
- @@ -1005,6 +1059,48 @@ static const struct usb_device_id option_ids[] = {
- { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
- { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
- { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM500) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM510) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM800) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM900) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU818) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU816) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU828) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU826) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU518) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU516) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU528) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU526) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM600) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM610) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM500) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM510) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM800) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM900) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU718) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU716) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU728) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU726) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU518) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU516) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU528) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU526) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM600) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM610) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM500) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM510) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM800) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM900) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU718) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU716) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU728) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU726) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU518) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
- + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
- { } /* Terminating entry */
- };
- MODULE_DEVICE_TABLE(usb, option_ids);
- @@ -1134,11 +1230,13 @@ static int option_probe(struct usb_serial *serial,
- serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
- return -ENODEV;
- - /* Don't bind network interfaces on Huawei K3765 & K4505 */
- + /* Don't bind network interfaces on Huawei K3765, K4505 & K4605 */
- if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID &&
- (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 ||
- - serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) &&
- - serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
- + serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505 ||
- + serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4605) &&
- + (serial->interface->cur_altsetting->desc.bInterfaceNumber == 1 ||
- + serial->interface->cur_altsetting->desc.bInterfaceNumber == 2))
- return -ENODEV;
- /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
- diff --git a/kernel_linaro/drivers/usb/serial/pl2303.c b/kernel/drivers/usb/serial/pl2303.c
- index 0c20831..1d33260 100644
- --- a/kernel_linaro/drivers/usb/serial/pl2303.c
- +++ b/kernel/drivers/usb/serial/pl2303.c
- @@ -343,10 +343,28 @@ static void pl2303_set_termios(struct tty_struct *tty,
- baud = 6000000;
- }
- dbg("%s - baud set = %d", __func__, baud);
- - buf[0] = baud & 0xff;
- - buf[1] = (baud >> 8) & 0xff;
- - buf[2] = (baud >> 16) & 0xff;
- - buf[3] = (baud >> 24) & 0xff;
- + if (baud <= 115200) {
- + buf[0] = baud & 0xff;
- + buf[1] = (baud >> 8) & 0xff;
- + buf[2] = (baud >> 16) & 0xff;
- + buf[3] = (baud >> 24) & 0xff;
- + } else {
- + /* apparently the formula for higher speeds is:
- + * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
- + */
- + unsigned tmp = 12*1000*1000*32 / baud;
- + buf[3] = 0x80;
- + buf[2] = 0;
- + buf[1] = (tmp >= 256);
- + while (tmp >= 256) {
- + tmp >>= 2;
- + buf[1] <<= 1;
- + }
- + if (tmp > 256) {
- + tmp %= 256;
- + }
- + buf[0] = tmp;
- + }
- }
- /* For reference buf[4]=0 is 1 stop bits */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement