summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjay Agarwal <ajaya@codeaurora.org>2017-12-11 14:09:17 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2017-12-23 18:33:57 -0800
commit24ecfd64c77d6f8ffbfac6d2ba784382dd7745e7 (patch)
tree921136048534fa7459c43f5b7e8a1d33d336508e
parent8ed108c9770aa1fb055f8129121e60a708067f3f (diff)
gpio: usbdetect: Avoid threaded IRQ handling if no change in ID
It is observed that the hard ID IRQ is enabled when the threaded IRQ handler for the same is still running. In that case, there are two issues. The ID LOW IRQ can come consecutively which will increase the disable count of vbus_irq. Then ID HIGH IRQ will not enable the vbus_irq and peripheral mode detection will not work anymore. The second issue is that ID HIGH IRQ is fired just before ID LOW IRQ. This will mark usb->id_state from HIGH to LOW even while threaded IRQ is running which will lead to host not getting stopped and peripheral mode not working. Fix both issues by maintaning a local copy of ID IRQ in threaded IRQ handler and comparing it with previous ID state. If same, then bail out. Change-Id: If5da1f91ece9d1751d7002e64bab0e145623a92e Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
-rw-r--r--drivers/platform/msm/gpio-usbdetect.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/platform/msm/gpio-usbdetect.c b/drivers/platform/msm/gpio-usbdetect.c
index 1628253fb545..97682436f92c 100644
--- a/drivers/platform/msm/gpio-usbdetect.c
+++ b/drivers/platform/msm/gpio-usbdetect.c
@@ -77,8 +77,16 @@ static irqreturn_t gpio_usbdetect_id_irq(int irq, void *data)
static irqreturn_t gpio_usbdetect_id_irq_thread(int irq, void *data)
{
struct gpio_usbdetect *usb = data;
+ bool curr_id_state;
+ static int prev_id_state = -EINVAL;
- if (usb->id_state) {
+ curr_id_state = usb->id_state;
+ if (curr_id_state == prev_id_state) {
+ dev_dbg(&usb->pdev->dev, "no change in ID state\n");
+ return IRQ_HANDLED;
+ }
+
+ if (curr_id_state) {
dev_dbg(&usb->pdev->dev, "stopping usb host\n");
extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 0);
enable_irq(usb->vbus_det_irq);
@@ -88,6 +96,8 @@ static irqreturn_t gpio_usbdetect_id_irq_thread(int irq, void *data)
extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_SPEED, 1);
extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 1);
}
+
+ prev_id_state = curr_id_state;
return IRQ_HANDLED;
}