Commit 697d5c00 authored by Shimoda, Yoshihiro's avatar Shimoda, Yoshihiro Committed by Greg Kroah-Hartman

usb: renesas_usbhs: modify the irq handler for sharing irq

When IORESOURCE_IRQ_SHAREABLE is set, the irq handler may be called
even if the interupt of the USB module doesn't happen. So, it may
clear the interrupt flags by mistake. This patch fixes it.
Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 47c56a14
...@@ -209,14 +209,18 @@ int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state) ...@@ -209,14 +209,18 @@ int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
return (int)irq_state->intsts0 & CTSQ_MASK; return (int)irq_state->intsts0 & CTSQ_MASK;
} }
static void usbhs_status_get_each_irq(struct usbhs_priv *priv, static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
struct usbhs_irq_state *state) struct usbhs_irq_state *state)
{ {
struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv);
u16 intenb0, intenb1;
state->intsts0 = usbhs_read(priv, INTSTS0); state->intsts0 = usbhs_read(priv, INTSTS0);
state->intsts1 = usbhs_read(priv, INTSTS1); state->intsts1 = usbhs_read(priv, INTSTS1);
intenb0 = usbhs_read(priv, INTENB0);
intenb1 = usbhs_read(priv, INTENB1);
/* mask */ /* mask */
if (mod) { if (mod) {
state->brdysts = usbhs_read(priv, BRDYSTS); state->brdysts = usbhs_read(priv, BRDYSTS);
...@@ -226,6 +230,20 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv, ...@@ -226,6 +230,20 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv,
state->bempsts &= mod->irq_bempsts; state->bempsts &= mod->irq_bempsts;
state->brdysts &= mod->irq_brdysts; state->brdysts &= mod->irq_brdysts;
} }
/*
* Check whether the irq enable registers and the irq status are set
* when IRQF_SHARED is set.
*/
if (priv->irqflags & IRQF_SHARED) {
if (!(intenb0 & state->intsts0) &&
!(intenb1 & state->intsts1) &&
!(state->bempsts) &&
!(state->brdysts))
return -EIO;
}
return 0;
} }
/* /*
...@@ -238,7 +256,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) ...@@ -238,7 +256,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
struct usbhs_priv *priv = data; struct usbhs_priv *priv = data;
struct usbhs_irq_state irq_state; struct usbhs_irq_state irq_state;
usbhs_status_get_each_irq(priv, &irq_state); if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
return IRQ_NONE;
/* /*
* clear interrupt * clear interrupt
......
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