aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/mdm_ctrl_bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc/mdm_ctrl_bridge.c')
-rw-r--r--drivers/usb/misc/mdm_ctrl_bridge.c115
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);