Skip to content

Commit

Permalink
bna: fix interrupt handling
Browse files Browse the repository at this point in the history
This fix handles the case when IRQ handler is called (for shared IRQs)
even before the driver is ready to handle interrupts.

Signed-off-by: Debashis Dutt <ddutt@brocade.com>
Signed-off-by: Rasesh Mody <rmody@brocade.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rasesh Mody authored and David S. Miller committed Oct 6, 2010
1 parent ebc0ffa commit e2fa6f2
Showing 1 changed file with 27 additions and 21 deletions.
48 changes: 27 additions & 21 deletions drivers/net/bna/bnad.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,9 +564,11 @@ bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
static void
bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
{
spin_lock_irq(&bnad->bna_lock); /* Because of polling context */
unsigned long flags;

spin_lock_irqsave(&bnad->bna_lock, flags); /* Because of polling context */
bnad_enable_rx_irq_unsafe(ccb);
spin_unlock_irq(&bnad->bna_lock);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}

static void
Expand Down Expand Up @@ -599,7 +601,7 @@ static irqreturn_t
bnad_msix_mbox_handler(int irq, void *data)
{
u32 intr_status;
unsigned long flags;
unsigned long flags;
struct net_device *netdev = data;
struct bnad *bnad;

Expand Down Expand Up @@ -630,13 +632,15 @@ bnad_isr(int irq, void *data)
struct bnad_rx_info *rx_info;
struct bnad_rx_ctrl *rx_ctrl;

spin_lock_irqsave(&bnad->bna_lock, flags);
if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
return IRQ_NONE;

bna_intr_status_get(&bnad->bna, intr_status);
if (!intr_status) {
spin_unlock_irqrestore(&bnad->bna_lock, flags);

if (unlikely(!intr_status))
return IRQ_NONE;
}

spin_lock_irqsave(&bnad->bna_lock, flags);

if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
bna_mbox_handler(&bnad->bna, intr_status);
Expand Down Expand Up @@ -672,11 +676,10 @@ bnad_enable_mbox_irq(struct bnad *bnad)
{
int irq = BNAD_GET_MBOX_IRQ(bnad);

if (!(bnad->cfg_flags & BNAD_CF_MSIX))
return;

if (test_and_clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
enable_irq(irq);
if (bnad->cfg_flags & BNAD_CF_MSIX)
enable_irq(irq);

BNAD_UPDATE_CTR(bnad, mbox_intr_enabled);
}

Expand All @@ -689,11 +692,11 @@ bnad_disable_mbox_irq(struct bnad *bnad)
{
int irq = BNAD_GET_MBOX_IRQ(bnad);

if (!(bnad->cfg_flags & BNAD_CF_MSIX))
return;

if (!test_and_set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
disable_irq_nosync(irq);
if (bnad->cfg_flags & BNAD_CF_MSIX)
disable_irq_nosync(irq);

BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
}

Expand Down Expand Up @@ -1045,14 +1048,12 @@ bnad_mbox_irq_free(struct bnad *bnad,
return;

spin_lock_irqsave(&bnad->bna_lock, flags);

bnad_disable_mbox_irq(bnad);
spin_unlock_irqrestore(&bnad->bna_lock, flags);

irq = BNAD_GET_MBOX_IRQ(bnad);
free_irq(irq, bnad->netdev);

spin_unlock_irqrestore(&bnad->bna_lock, flags);

kfree(intr_info->idl);
}

Expand Down Expand Up @@ -1094,16 +1095,24 @@ bnad_mbox_irq_alloc(struct bnad *bnad,

sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);

/*
* Set the Mbox IRQ disable flag, so that the IRQ handler
* called from request_irq() for SHARED IRQs do not execute
*/
set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);

err = request_irq(irq, irq_handler, flags,
bnad->mbox_irq_name, bnad->netdev);

if (err) {
kfree(intr_info->idl);
intr_info->idl = NULL;
return err;
}

spin_lock_irqsave(&bnad->bna_lock, flags);
bnad_disable_mbox_irq(bnad);
if (bnad->cfg_flags & BNAD_CF_MSIX)
disable_irq_nosync(irq);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
return 0;
}
Expand Down Expand Up @@ -1485,7 +1494,6 @@ bnad_stats_timer_start(struct bnad *bnad)
jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
}
spin_unlock_irqrestore(&bnad->bna_lock, flags);

}

/*
Expand Down Expand Up @@ -2170,7 +2178,6 @@ bnad_device_disable(struct bnad *bnad)
spin_unlock_irqrestore(&bnad->bna_lock, flags);

wait_for_completion(&bnad->bnad_completions.ioc_comp);

}

static int
Expand Down Expand Up @@ -3108,7 +3115,6 @@ bnad_pci_probe(struct pci_dev *pdev,

spin_lock_irqsave(&bnad->bna_lock, flags);
bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);

spin_unlock_irqrestore(&bnad->bna_lock, flags);

bnad->stats.bna_stats = &bna->stats;
Expand Down

0 comments on commit e2fa6f2

Please sign in to comment.