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: Ken Kawasaki <ken_kawasaki@spring.nifty.jp> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
dacf4fc85b
commit
2a91515722
1 changed files with 21 additions and 10 deletions
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue