Commit 2a915157 authored by Ken Kawasaki's avatar Ken Kawasaki Committed by David S. Miller

smc91c92_cs: spin_unlock_irqrestore before calling smc_interrupt()

smc91c92_cs:
  * spin_unlock_irqrestore before calling smc_interrupt() in media_check()
     to avoid lockup.
  * use spin_lock_irqsave for ethtool function.
Signed-off-by: default avatarKen Kawasaki <ken_kawasaki@spring.nifty.jp>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dacf4fc8
...@@ -1804,23 +1804,30 @@ static void media_check(u_long arg) ...@@ -1804,23 +1804,30 @@ static void media_check(u_long arg)
SMC_SELECT_BANK(1); SMC_SELECT_BANK(1);
media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1; media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1;
SMC_SELECT_BANK(saved_bank);
spin_unlock_irqrestore(&smc->lock, flags);
/* Check for pending interrupt with watchdog flag set: with /* Check for pending interrupt with watchdog flag set: with
this, we can limp along even if the interrupt is blocked */ this, we can limp along even if the interrupt is blocked */
if (smc->watchdog++ && ((i>>8) & i)) { if (smc->watchdog++ && ((i>>8) & i)) {
if (!smc->fast_poll) if (!smc->fast_poll)
printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
local_irq_save(flags);
smc_interrupt(dev->irq, dev); smc_interrupt(dev->irq, dev);
local_irq_restore(flags);
smc->fast_poll = HZ; smc->fast_poll = HZ;
} }
if (smc->fast_poll) { if (smc->fast_poll) {
smc->fast_poll--; smc->fast_poll--;
smc->media.expires = jiffies + HZ/100; smc->media.expires = jiffies + HZ/100;
add_timer(&smc->media); add_timer(&smc->media);
SMC_SELECT_BANK(saved_bank);
spin_unlock_irqrestore(&smc->lock, flags);
return; return;
} }
spin_lock_irqsave(&smc->lock, flags);
saved_bank = inw(ioaddr + BANK_SELECT);
if (smc->cfg & CFG_MII_SELECT) { if (smc->cfg & CFG_MII_SELECT) {
if (smc->mii_if.phy_id < 0) if (smc->mii_if.phy_id < 0)
goto reschedule; goto reschedule;
...@@ -1978,15 +1985,16 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -1978,15 +1985,16 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
unsigned int ioaddr = dev->base_addr; unsigned int ioaddr = dev->base_addr;
u16 saved_bank = inw(ioaddr + BANK_SELECT); u16 saved_bank = inw(ioaddr + BANK_SELECT);
int ret; int ret;
unsigned long flags;
spin_lock_irq(&smc->lock); spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
if (smc->cfg & CFG_MII_SELECT) if (smc->cfg & CFG_MII_SELECT)
ret = mii_ethtool_gset(&smc->mii_if, ecmd); ret = mii_ethtool_gset(&smc->mii_if, ecmd);
else else
ret = smc_netdev_get_ecmd(dev, ecmd); ret = smc_netdev_get_ecmd(dev, ecmd);
SMC_SELECT_BANK(saved_bank); SMC_SELECT_BANK(saved_bank);
spin_unlock_irq(&smc->lock); spin_unlock_irqrestore(&smc->lock, flags);
return ret; return ret;
} }
...@@ -1996,15 +2004,16 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -1996,15 +2004,16 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
unsigned int ioaddr = dev->base_addr; unsigned int ioaddr = dev->base_addr;
u16 saved_bank = inw(ioaddr + BANK_SELECT); u16 saved_bank = inw(ioaddr + BANK_SELECT);
int ret; int ret;
unsigned long flags;
spin_lock_irq(&smc->lock); spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
if (smc->cfg & CFG_MII_SELECT) if (smc->cfg & CFG_MII_SELECT)
ret = mii_ethtool_sset(&smc->mii_if, ecmd); ret = mii_ethtool_sset(&smc->mii_if, ecmd);
else else
ret = smc_netdev_set_ecmd(dev, ecmd); ret = smc_netdev_set_ecmd(dev, ecmd);
SMC_SELECT_BANK(saved_bank); SMC_SELECT_BANK(saved_bank);
spin_unlock_irq(&smc->lock); spin_unlock_irqrestore(&smc->lock, flags);
return ret; return ret;
} }
...@@ -2014,12 +2023,13 @@ static u32 smc_get_link(struct net_device *dev) ...@@ -2014,12 +2023,13 @@ static u32 smc_get_link(struct net_device *dev)
unsigned int ioaddr = dev->base_addr; unsigned int ioaddr = dev->base_addr;
u16 saved_bank = inw(ioaddr + BANK_SELECT); u16 saved_bank = inw(ioaddr + BANK_SELECT);
u32 ret; u32 ret;
unsigned long flags;
spin_lock_irq(&smc->lock); spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
ret = smc_link_ok(dev); ret = smc_link_ok(dev);
SMC_SELECT_BANK(saved_bank); SMC_SELECT_BANK(saved_bank);
spin_unlock_irq(&smc->lock); spin_unlock_irqrestore(&smc->lock, flags);
return ret; return ret;
} }
...@@ -2056,16 +2066,17 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2056,16 +2066,17 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
int rc = 0; int rc = 0;
u16 saved_bank; u16 saved_bank;
unsigned int ioaddr = dev->base_addr; unsigned int ioaddr = dev->base_addr;
unsigned long flags;
if (!netif_running(dev)) if (!netif_running(dev))
return -EINVAL; return -EINVAL;
spin_lock_irq(&smc->lock); spin_lock_irqsave(&smc->lock, flags);
saved_bank = inw(ioaddr + BANK_SELECT); saved_bank = inw(ioaddr + BANK_SELECT);
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);
SMC_SELECT_BANK(saved_bank); SMC_SELECT_BANK(saved_bank);
spin_unlock_irq(&smc->lock); spin_unlock_irqrestore(&smc->lock, flags);
return rc; return rc;
} }
......
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