Skip to content

Commit

Permalink
usb: renesas_usbhs: modify the irq handler for sharing irq
Browse files Browse the repository at this point in the history
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: Yoshihiro Shimoda <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
shimoday authored and gregkh committed Sep 5, 2012
1 parent 47c56a1 commit 697d5c0
Showing 1 changed file with 22 additions and 3 deletions.
25 changes: 22 additions & 3 deletions drivers/usb/renesas_usbhs/mod.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,18 @@ int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
return (int)irq_state->intsts0 & CTSQ_MASK;
}

static void usbhs_status_get_each_irq(struct usbhs_priv *priv,
struct usbhs_irq_state *state)
static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
struct usbhs_irq_state *state)
{
struct usbhs_mod *mod = usbhs_mod_get_current(priv);
u16 intenb0, intenb1;

state->intsts0 = usbhs_read(priv, INTSTS0);
state->intsts1 = usbhs_read(priv, INTSTS1);

intenb0 = usbhs_read(priv, INTENB0);
intenb1 = usbhs_read(priv, INTENB1);

/* mask */
if (mod) {
state->brdysts = usbhs_read(priv, BRDYSTS);
Expand All @@ -226,6 +230,20 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv,
state->bempsts &= mod->irq_bempsts;
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;
}

/*
Expand All @@ -238,7 +256,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
struct usbhs_priv *priv = data;
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
Expand Down

0 comments on commit 697d5c0

Please sign in to comment.