diff options
Diffstat (limited to 'drivers/usb/misc/mdm_ctrl_bridge.c')
-rw-r--r-- | drivers/usb/misc/mdm_ctrl_bridge.c | 115 |
1 files changed, 92 insertions, 23 deletions
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c index 4755790..6635819 100644 --- a/drivers/usb/misc/mdm_ctrl_bridge.c +++ b/drivers/usb/misc/mdm_ctrl_bridge.c @@ -25,6 +25,12 @@ #include <linux/termios.h> #include <asm/unaligned.h> #include <mach/usb_bridge.h> +#include <linux/mdm_hsic_pm.h> + +#ifdef CONFIG_MDM_HSIC_PM +#include <linux/mdm_hsic_pm.h> +static const char rmnet_pm_dev[] = "mdm_hsic_pm0"; +#endif static const char const *ctrl_bridge_names[] = { "dun_ctrl_hsic0", @@ -132,12 +138,17 @@ static void resp_avail_cb(struct urb *urb) int status = 0; int resubmit_urb = 1; struct bridge *brdg = dev->brdg; + unsigned int iface_num; udev = interface_to_usbdev(dev->intf); + iface_num = dev->intf->cur_altsetting->desc.bInterfaceNumber; + switch (urb->status) { + case -ENOENT: case 0: /*success*/ dev->get_encap_res++; + pr_info("[RACB:%d]<\n", iface_num); if (brdg && brdg->ops.send_pkt) brdg->ops.send_pkt(brdg->ctx, urb->transfer_buffer, urb->actual_length); @@ -145,7 +156,6 @@ static void resp_avail_cb(struct urb *urb) /*do not resubmit*/ case -ESHUTDOWN: - case -ENOENT: case -ECONNRESET: /* unplug */ case -EPROTO: @@ -158,16 +168,15 @@ static void resp_avail_cb(struct urb *urb) __func__, urb->status); } - if (resubmit_urb) { + if (urb->status != -ENOENT && resubmit_urb) { /*re- submit int urb to check response available*/ - usb_anchor_urb(dev->inturb, &dev->tx_submitted); status = usb_submit_urb(dev->inturb, GFP_ATOMIC); if (status) { dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n", __func__, status); - usb_unanchor_urb(dev->inturb); } + pr_info("[CHKRA:%d]>\n", iface_num); } } @@ -180,11 +189,19 @@ static void notification_available_cb(struct urb *urb) struct bridge *brdg = dev->brdg; unsigned int ctrl_bits; unsigned char *data; + unsigned int iface_num; + + /* if this intf is already disconnected, this urb free-ed before + * calling from qh_completions. just return and do nothing */ + if (!dev->intf) + return; udev = interface_to_usbdev(dev->intf); + iface_num = dev->intf->cur_altsetting->desc.bInterfaceNumber; switch (urb->status) { case 0: + pr_info("[NACB:%d]<\n", iface_num); /*success*/ break; case -ESHUTDOWN: @@ -216,15 +233,14 @@ static void notification_available_cb(struct urb *urb) DEFAULT_READ_URB_LENGTH, resp_avail_cb, dev); - usb_anchor_urb(dev->readurb, &dev->tx_submitted); status = usb_submit_urb(dev->readurb, GFP_ATOMIC); if (status) { dev_err(&udev->dev, "%s: Error submitting Read URB %d\n", __func__, status); - usb_unanchor_urb(dev->readurb); goto resubmit_int_urb; - } + } else + pr_info("[NRA:%d]>\n", iface_num); return; case USB_CDC_NOTIFY_NETWORK_CONNECTION: dev_dbg(&udev->dev, "%s network\n", ctrl->wValue ? @@ -237,6 +253,10 @@ static void notification_available_cb(struct urb *urb) dev->cbits_tohost = ctrl_bits; if (brdg && brdg->ops.send_cbits) brdg->ops.send_cbits(brdg->ctx, ctrl_bits); +#ifdef CONFIG_MDM_HSIC_PM + pr_info("%s: set lpa handling to false\n", __func__); + lpa_handling = false; +#endif break; default: dev_err(&udev->dev, "%s: unknown notification %d received:" @@ -246,38 +266,57 @@ static void notification_available_cb(struct urb *urb) } resubmit_int_urb: - usb_anchor_urb(urb, &dev->tx_submitted); status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n", __func__, status); - usb_unanchor_urb(urb); - } + } else + pr_info("[CHKRA:%d]>\n", iface_num); } int ctrl_bridge_start_read(struct ctrl_bridge *dev) { - int retval = 0; + int retval = 0; + struct usb_device *udev; + unsigned int iface_num; + + udev = interface_to_usbdev(dev->intf); + iface_num = dev->intf->cur_altsetting->desc.bInterfaceNumber; if (!dev->inturb) { dev_err(&dev->udev->dev, "%s: inturb is NULL\n", __func__); return -ENODEV; } - if (!dev->inturb->anchor) { - usb_anchor_urb(dev->inturb, &dev->tx_submitted); - retval = usb_submit_urb(dev->inturb, GFP_KERNEL); - if (retval < 0) { - dev_err(&dev->udev->dev, - "%s error submitting int urb %d\n", - __func__, retval); - usb_unanchor_urb(dev->inturb); - } - } + retval = usb_submit_urb(dev->inturb, GFP_KERNEL); + if (retval < 0) { + dev_err(&dev->udev->dev, + "%s error submitting int urb %d\n", + __func__, retval); + + } else + pr_info("[CHKRA:%d]>\n", iface_num); return retval; } +void ctrl_bridge_stop_read(struct ctrl_bridge *dev) +{ + usb_kill_urb(dev->readurb); + usb_kill_urb(dev->inturb); +} + +void ctrl_bridge_stop_all(void) +{ + int id; + + for (id = 0; id < MAX_BRIDGE_DEVICES; id++) { + if (__dev[id]) + ctrl_bridge_stop_read(__dev[id]); + } +} +EXPORT_SYMBOL(ctrl_bridge_stop_all); + int ctrl_bridge_open(struct bridge *brdg) { struct ctrl_bridge *dev; @@ -349,7 +388,8 @@ static void ctrl_write_callback(struct urb *urb) kfree(urb->transfer_buffer); kfree(urb->setup_packet); usb_free_urb(urb); - usb_autopm_put_interface_async(dev->intf); + if (dev->intf) + usb_autopm_put_interface_async(dev->intf); } int ctrl_bridge_write(unsigned int id, char *data, size_t size) @@ -359,6 +399,7 @@ int ctrl_bridge_write(unsigned int id, char *data, size_t size) struct usb_ctrlrequest *out_ctlreq; struct usb_device *udev; struct ctrl_bridge *dev; + int spin = 50; if (id >= MAX_BRIDGE_DEVICES) { result = -EINVAL; @@ -372,6 +413,17 @@ int ctrl_bridge_write(unsigned int id, char *data, size_t size) goto free_data; } + /* move it to mdm _hsic pm .c, check return code */ + while (lpa_handling && spin--) { + pr_info("%s: lpa wake wait loop\n", __func__); + msleep(20); + } + + if (lpa_handling) { + pr_err("%s: in lpa wakeup, return EAGAIN\n", __func__); + return -EAGAIN; + } + udev = interface_to_usbdev(dev->intf); dev_dbg(&udev->dev, "%s:[id]:%u: write (%d bytes)\n", @@ -471,6 +523,7 @@ int ctrl_bridge_suspend(unsigned int id) set_bit(SUSPENDED, &dev->flags); usb_kill_anchored_urbs(&dev->tx_submitted); + ctrl_bridge_stop_read(dev); return 0; } @@ -505,9 +558,15 @@ int ctrl_bridge_resume(unsigned int id) } /* if the bridge is open, resume reading */ +#ifndef CONFIG_MDM_HSIC_PM if (dev->brdg) return ctrl_bridge_start_read(dev); - +#else + /* if the bridge is open or not, resume to consume mdm request + * because this link is not dead, it's alive + */ + return ctrl_bridge_start_read(dev); +#endif return 0; } @@ -711,6 +770,12 @@ ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in, ch_id++; +#ifdef CONFIG_MDM_HSIC_PM + /* if the bridge is open or not, resume to consume mdm request + * because this link is not dead, it's alive + */ + ctrl_bridge_start_read(dev); +#endif return retval; free_rbuf: @@ -737,6 +802,10 @@ void ctrl_bridge_disconnect(unsigned int id) platform_device_del(dev->pdev); + dev->intf = NULL; + usb_kill_urb(dev->readurb); + usb_kill_urb(dev->inturb); + kfree(dev->in_ctlreq); kfree(dev->readbuf); kfree(dev->intbuf); |