Commit b183c19f authored by Richard Zhao's avatar Richard Zhao Committed by Greg Kroah-Hartman

USB: chipidea: re-order irq handling to avoid unhandled irqs

- let role driver handle irq before ID change check; this gives the
  role driver a chance to handle disconnect;
- disable irq during switch role; no role driver to handle irq in
  the period.
Tested-by: default avatarMichael Grzeschik <m.grzeschik@pengutronix.de>
Tested-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarRichard Zhao <richard.zhao@freescale.com>
Signed-off-by: default avatarAlexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 388ed487
...@@ -279,6 +279,7 @@ static void ci_role_work(struct work_struct *work) ...@@ -279,6 +279,7 @@ static void ci_role_work(struct work_struct *work)
ci_role_stop(ci); ci_role_stop(ci);
ci_role_start(ci, role); ci_role_start(ci, role);
enable_irq(ci->irq);
} }
} }
...@@ -318,18 +319,22 @@ static irqreturn_t ci_irq(int irq, void *data) ...@@ -318,18 +319,22 @@ static irqreturn_t ci_irq(int irq, void *data)
{ {
struct ci13xxx *ci = data; struct ci13xxx *ci = data;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
u32 otgsc = 0;
if (ci->is_otg) { if (ci->is_otg)
u32 sts = hw_read(ci, OP_OTGSC, ~0); otgsc = hw_read(ci, OP_OTGSC, ~0);
if (ci->role != CI_ROLE_END)
ret = ci_role(ci)->irq(ci);
if (sts & OTGSC_IDIS) { if (ci->is_otg && (otgsc & OTGSC_IDIS)) {
hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
queue_work(ci->wq, &ci->work); disable_irq_nosync(ci->irq);
ret = IRQ_HANDLED; queue_work(ci->wq, &ci->work);
} ret = IRQ_HANDLED;
} }
return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci); return ret;
} }
static DEFINE_IDA(ci_ida); static DEFINE_IDA(ci_ida);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment