summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorMayank Rana <mrana@codeaurora.org>2016-05-27 14:06:29 -0700
committerHemant Kumar <hemantk@codeaurora.org>2016-08-03 16:12:26 -0700
commit541cf8b3a3970d7ec9488be1c672d2bf47a5e814 (patch)
tree2bd07d5fc9cbaf865cd5109f6f4156634a73b66d /drivers/usb
parent60aacdb787e6040d86bea2cd54897085a638a728 (diff)
usb: gadget: gsi: Use pm_runtime related API from state machine
Currently USB GSI function driver increments USB gadget device's pm usage count on set_alt() and decrements on USB bus suspend or USB cable disconnect case. Current code is not decrementing this usage count when sm_state is STATE_INITIALIZED and USB cable is disconnected (i.e. event EVT_DISCONNECTED posted). In this case, USB doesn't go into low power mode although USB cable is disconnected. Hence to handle this case make sure to increment USB device's PM usage count from state machine instead of set_alt(). Also fix one of bug where state machine is peeking event but it is not deleting same event from queue which shall result into using same event multiple time in different states. Use usb_gadget_autopm_get() instead of usb_gadget_autopm_get_noresume() as noresume variant only increment usage count which is not sufficient condition to prevent USB to go into LPM. usb_gadget_autopm_get() increments both usage count and child count. Change-Id: I667aef9208d14b2dff5944ad6ad9b053797c4ac9 Signed-off-by: Mayank Rana <mrana@codeaurora.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/function/f_gsi.c35
1 files changed, 17 insertions, 18 deletions
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 5612645d7237..05a4bbec5d02 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -571,6 +571,9 @@ static void ipa_work_handler(struct work_struct *w)
break;
case STATE_INITIALIZED:
if (event == EVT_CONNECT_IN_PROGRESS) {
+ usb_gadget_autopm_get(d_port->gadget);
+ log_event_dbg("%s: get = %d", __func__,
+ atomic_read(&gad_dev->power.usage_count));
ipa_connect_channels(d_port);
d_port->sm_state = STATE_CONNECT_IN_PROGRESS;
log_event_dbg("%s: ST_INIT_EVT_CONN_IN_PROG",
@@ -586,6 +589,9 @@ static void ipa_work_handler(struct work_struct *w)
* EVT_HOST_READY is posted to the state machine
* in the handler for this msg.
*/
+ usb_gadget_autopm_get(d_port->gadget);
+ log_event_dbg("%s: get = %d", __func__,
+ atomic_read(&gad_dev->power.usage_count));
ipa_connect_channels(d_port);
ipa_data_path_enable(d_port);
d_port->sm_state = STATE_CONNECTED;
@@ -648,6 +654,7 @@ static void ipa_work_handler(struct work_struct *w)
&gad_dev->power.usage_count));
} else if (event == EVT_SUSPEND) {
if (peek_event(d_port) == EVT_DISCONNECTED) {
+ read_event(d_port);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
usb_gadget_autopm_put_async(d_port->gadget);
@@ -718,19 +725,12 @@ static void ipa_work_handler(struct work_struct *w)
case STATE_SUSPENDED:
if (event == EVT_RESUMED) {
+ usb_gadget_autopm_get(d_port->gadget);
+ log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
+ log_event_dbg("%s: get = %d", __func__,
+ atomic_read(&gad_dev->power.usage_count));
ipa_resume_work_handler(d_port);
d_port->sm_state = STATE_CONNECTED;
- /*
- * Increment usage count here to disallow gadget
- * parent suspend. This counter will decrement
- * after IPA handshake is done in disconnect work
- * (due to cable disconnect) or in suspended state.
- */
- usb_gadget_autopm_get_noresume(d_port->gadget);
- log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
- log_event_dbg("%s: get_nores2 = %d", __func__,
- atomic_read(
- &gad_dev->power.usage_count));
} else if (event == EVT_DISCONNECTED) {
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
@@ -1826,15 +1826,14 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (gsi->prot_id == IPA_USB_ECM)
gsi->d_port.cdc_filter = DEFAULT_FILTER;
-
/*
- * Increment usage count upon cable connect. Decrement
- * after IPA disconnect is done in disconnect work
- * (due to cable disconnect) or in suspend work.
+ * For RNDIS the event is posted from the flow control
+ * handler which is invoked when the host sends the
+ * GEN_CURRENT_PACKET_FILTER message.
*/
- usb_gadget_autopm_get_noresume(gsi->d_port.gadget);
-
- post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS);
+ if (gsi->prot_id != IPA_USB_RNDIS)
+ post_event(&gsi->d_port,
+ EVT_CONNECT_IN_PROGRESS);
queue_work(gsi->d_port.ipa_usb_wq,
&gsi->d_port.usb_ipa_w);
}