Skip to content

Commit

Permalink
spidernet: improve interrupt handling
Browse files Browse the repository at this point in the history
We intend this patch to improve spidernet interrupt handling to be
more strict.  We had following problem and this patch solves it.

 -when CONFIG_DEBUG_SHIRQ=y, request_irq() calls handler().
 -when spider_net_open() is called, it calls request_irq() which calls
  spider_net_interrupt().
 -if some specific interrupt bit is set at this timing, it calls
  netif_rx_schedule() and spider_net_poll() is scheduled.
 -spider_net_open() calls netif_poll_enable() which clears the bit
  __LINK_STATE_RX_SCHED.
 -when spider_net_poll() is called, it calls netif_rx_complete() which
  causes BUG_ON() because __LINK_STATE_RX_SCHED is not set.

Signed-off-by: Kou Ishizaki <[email protected]>
Signed-off-by: Linas Vepstas <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
  • Loading branch information
kouishizaki authored and Jeff Garzik committed Jul 10, 2007
1 parent b8a1fce commit 7a62755
Showing 1 changed file with 45 additions and 14 deletions.
59 changes: 45 additions & 14 deletions drivers/net/spider_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -1441,11 +1441,17 @@ static void
spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
{
u32 error_reg1, error_reg2;
u32 mask_reg1, mask_reg2;
u32 i;
int show_error = 1;

error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
mask_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1MSK);
mask_reg2 = spider_net_read_reg(card,SPIDER_NET_GHIINT2MSK);

error_reg1 &= mask_reg1;
error_reg2 &= mask_reg2;

/* check GHIINT0STS ************************************/
if (status_reg)
Expand Down Expand Up @@ -1673,9 +1679,11 @@ spider_net_interrupt(int irq, void *ptr)
{
struct net_device *netdev = ptr;
struct spider_net_card *card = netdev_priv(netdev);
u32 status_reg;
u32 status_reg, mask_reg;

status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
status_reg &= mask_reg;

if (!status_reg)
return IRQ_NONE;
Expand Down Expand Up @@ -1716,6 +1724,38 @@ spider_net_poll_controller(struct net_device *netdev)
}
#endif /* CONFIG_NET_POLL_CONTROLLER */

/**
* spider_net_enable_interrupts - enable interrupts
* @card: card structure
*
* spider_net_enable_interrupt enables several interrupts
*/
static void
spider_net_enable_interrupts(struct spider_net_card *card)
{
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
SPIDER_NET_INT0_MASK_VALUE);
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
SPIDER_NET_INT1_MASK_VALUE);
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
SPIDER_NET_INT2_MASK_VALUE);
}

/**
* spider_net_disable_interrupts - disable interrupts
* @card: card structure
*
* spider_net_disable_interrupts disables all the interrupts
*/
static void
spider_net_disable_interrupts(struct spider_net_card *card)
{
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
}

/**
* spider_net_init_card - initializes the card
* @card: card structure
Expand All @@ -1736,6 +1776,7 @@ spider_net_init_card(struct spider_net_card *card)
spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4);

spider_net_disable_interrupts(card);
}

/**
Expand Down Expand Up @@ -1823,14 +1864,6 @@ spider_net_enable_card(struct spider_net_card *card)
spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
SPIDER_NET_OPMODE_VALUE);

/* set interrupt mask registers */
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
SPIDER_NET_INT0_MASK_VALUE);
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
SPIDER_NET_INT1_MASK_VALUE);
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
SPIDER_NET_INT2_MASK_VALUE);

spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
SPIDER_NET_GDTBSTA);
}
Expand Down Expand Up @@ -2007,6 +2040,8 @@ spider_net_open(struct net_device *netdev)
netif_carrier_on(netdev);
netif_poll_enable(netdev);

spider_net_enable_interrupts(card);

return 0;

register_int_failed:
Expand Down Expand Up @@ -2179,11 +2214,7 @@ spider_net_stop(struct net_device *netdev)
del_timer_sync(&card->tx_timer);
del_timer_sync(&card->aneg_timer);

/* disable/mask all interrupts */
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
spider_net_disable_interrupts(card);

free_irq(netdev->irq, netdev);

Expand Down

0 comments on commit 7a62755

Please sign in to comment.