diff options
Diffstat (limited to 'drivers/net/pcmcia/smc91c92_cs.c')
-rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index ff7eb9116b6a..ccc553782a0d 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -1608,9 +1608,12 @@ static void set_rx_mode(struct net_device *dev) | |||
1608 | { | 1608 | { |
1609 | unsigned int ioaddr = dev->base_addr; | 1609 | unsigned int ioaddr = dev->base_addr; |
1610 | struct smc_private *smc = netdev_priv(dev); | 1610 | struct smc_private *smc = netdev_priv(dev); |
1611 | u_int multicast_table[ 2 ] = { 0, }; | 1611 | unsigned char multicast_table[8]; |
1612 | unsigned long flags; | 1612 | unsigned long flags; |
1613 | u_short rx_cfg_setting; | 1613 | u_short rx_cfg_setting; |
1614 | int i; | ||
1615 | |||
1616 | memset(multicast_table, 0, sizeof(multicast_table)); | ||
1614 | 1617 | ||
1615 | if (dev->flags & IFF_PROMISC) { | 1618 | if (dev->flags & IFF_PROMISC) { |
1616 | rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; | 1619 | rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; |
@@ -1622,10 +1625,6 @@ static void set_rx_mode(struct net_device *dev) | |||
1622 | 1625 | ||
1623 | netdev_for_each_mc_addr(mc_addr, dev) { | 1626 | netdev_for_each_mc_addr(mc_addr, dev) { |
1624 | u_int position = ether_crc(6, mc_addr->dmi_addr); | 1627 | u_int position = ether_crc(6, mc_addr->dmi_addr); |
1625 | #ifndef final_version /* Verify multicast address. */ | ||
1626 | if ((mc_addr->dmi_addr[0] & 1) == 0) | ||
1627 | continue; | ||
1628 | #endif | ||
1629 | multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); | 1628 | multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); |
1630 | } | 1629 | } |
1631 | } | 1630 | } |
@@ -1635,8 +1634,8 @@ static void set_rx_mode(struct net_device *dev) | |||
1635 | /* Load MC table and Rx setting into the chip without interrupts. */ | 1634 | /* Load MC table and Rx setting into the chip without interrupts. */ |
1636 | spin_lock_irqsave(&smc->lock, flags); | 1635 | spin_lock_irqsave(&smc->lock, flags); |
1637 | SMC_SELECT_BANK(3); | 1636 | SMC_SELECT_BANK(3); |
1638 | outl(multicast_table[0], ioaddr + MULTICAST0); | 1637 | for (i = 0; i < 8; i++) |
1639 | outl(multicast_table[1], ioaddr + MULTICAST4); | 1638 | outb(multicast_table[i], ioaddr + MULTICAST0 + i); |
1640 | SMC_SELECT_BANK(0); | 1639 | SMC_SELECT_BANK(0); |
1641 | outw(rx_cfg_setting, ioaddr + RCR); | 1640 | outw(rx_cfg_setting, ioaddr + RCR); |
1642 | SMC_SELECT_BANK(2); | 1641 | SMC_SELECT_BANK(2); |
@@ -1805,23 +1804,30 @@ static void media_check(u_long arg) | |||
1805 | SMC_SELECT_BANK(1); | 1804 | SMC_SELECT_BANK(1); |
1806 | media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1; | 1805 | media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1; |
1807 | 1806 | ||
1807 | SMC_SELECT_BANK(saved_bank); | ||
1808 | spin_unlock_irqrestore(&smc->lock, flags); | ||
1809 | |||
1808 | /* Check for pending interrupt with watchdog flag set: with | 1810 | /* Check for pending interrupt with watchdog flag set: with |
1809 | this, we can limp along even if the interrupt is blocked */ | 1811 | this, we can limp along even if the interrupt is blocked */ |
1810 | if (smc->watchdog++ && ((i>>8) & i)) { | 1812 | if (smc->watchdog++ && ((i>>8) & i)) { |
1811 | if (!smc->fast_poll) | 1813 | if (!smc->fast_poll) |
1812 | printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); | 1814 | printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); |
1815 | local_irq_save(flags); | ||
1813 | smc_interrupt(dev->irq, dev); | 1816 | smc_interrupt(dev->irq, dev); |
1817 | local_irq_restore(flags); | ||
1814 | smc->fast_poll = HZ; | 1818 | smc->fast_poll = HZ; |
1815 | } | 1819 | } |
1816 | if (smc->fast_poll) { | 1820 | if (smc->fast_poll) { |
1817 | smc->fast_poll--; | 1821 | smc->fast_poll--; |
1818 | smc->media.expires = jiffies + HZ/100; | 1822 | smc->media.expires = jiffies + HZ/100; |
1819 | add_timer(&smc->media); | 1823 | add_timer(&smc->media); |
1820 | SMC_SELECT_BANK(saved_bank); | ||
1821 | spin_unlock_irqrestore(&smc->lock, flags); | ||
1822 | return; | 1824 | return; |
1823 | } | 1825 | } |
1824 | 1826 | ||
1827 | spin_lock_irqsave(&smc->lock, flags); | ||
1828 | |||
1829 | saved_bank = inw(ioaddr + BANK_SELECT); | ||
1830 | |||
1825 | if (smc->cfg & CFG_MII_SELECT) { | 1831 | if (smc->cfg & CFG_MII_SELECT) { |
1826 | if (smc->mii_if.phy_id < 0) | 1832 | if (smc->mii_if.phy_id < 0) |
1827 | goto reschedule; | 1833 | goto reschedule; |
@@ -1979,15 +1985,16 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
1979 | unsigned int ioaddr = dev->base_addr; | 1985 | unsigned int ioaddr = dev->base_addr; |
1980 | u16 saved_bank = inw(ioaddr + BANK_SELECT); | 1986 | u16 saved_bank = inw(ioaddr + BANK_SELECT); |
1981 | int ret; | 1987 | int ret; |
1988 | unsigned long flags; | ||
1982 | 1989 | ||
1983 | spin_lock_irq(&smc->lock); | 1990 | spin_lock_irqsave(&smc->lock, flags); |
1984 | SMC_SELECT_BANK(3); | 1991 | SMC_SELECT_BANK(3); |
1985 | if (smc->cfg & CFG_MII_SELECT) | 1992 | if (smc->cfg & CFG_MII_SELECT) |
1986 | ret = mii_ethtool_gset(&smc->mii_if, ecmd); | 1993 | ret = mii_ethtool_gset(&smc->mii_if, ecmd); |
1987 | else | 1994 | else |
1988 | ret = smc_netdev_get_ecmd(dev, ecmd); | 1995 | ret = smc_netdev_get_ecmd(dev, ecmd); |
1989 | SMC_SELECT_BANK(saved_bank); | 1996 | SMC_SELECT_BANK(saved_bank); |
1990 | spin_unlock_irq(&smc->lock); | 1997 | spin_unlock_irqrestore(&smc->lock, flags); |
1991 | return ret; | 1998 | return ret; |
1992 | } | 1999 | } |
1993 | 2000 | ||
@@ -1997,15 +2004,16 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
1997 | unsigned int ioaddr = dev->base_addr; | 2004 | unsigned int ioaddr = dev->base_addr; |
1998 | u16 saved_bank = inw(ioaddr + BANK_SELECT); | 2005 | u16 saved_bank = inw(ioaddr + BANK_SELECT); |
1999 | int ret; | 2006 | int ret; |
2007 | unsigned long flags; | ||
2000 | 2008 | ||
2001 | spin_lock_irq(&smc->lock); | 2009 | spin_lock_irqsave(&smc->lock, flags); |
2002 | SMC_SELECT_BANK(3); | 2010 | SMC_SELECT_BANK(3); |
2003 | if (smc->cfg & CFG_MII_SELECT) | 2011 | if (smc->cfg & CFG_MII_SELECT) |
2004 | ret = mii_ethtool_sset(&smc->mii_if, ecmd); | 2012 | ret = mii_ethtool_sset(&smc->mii_if, ecmd); |
2005 | else | 2013 | else |
2006 | ret = smc_netdev_set_ecmd(dev, ecmd); | 2014 | ret = smc_netdev_set_ecmd(dev, ecmd); |
2007 | SMC_SELECT_BANK(saved_bank); | 2015 | SMC_SELECT_BANK(saved_bank); |
2008 | spin_unlock_irq(&smc->lock); | 2016 | spin_unlock_irqrestore(&smc->lock, flags); |
2009 | return ret; | 2017 | return ret; |
2010 | } | 2018 | } |
2011 | 2019 | ||
@@ -2015,12 +2023,13 @@ static u32 smc_get_link(struct net_device *dev) | |||
2015 | unsigned int ioaddr = dev->base_addr; | 2023 | unsigned int ioaddr = dev->base_addr; |
2016 | u16 saved_bank = inw(ioaddr + BANK_SELECT); | 2024 | u16 saved_bank = inw(ioaddr + BANK_SELECT); |
2017 | u32 ret; | 2025 | u32 ret; |
2026 | unsigned long flags; | ||
2018 | 2027 | ||
2019 | spin_lock_irq(&smc->lock); | 2028 | spin_lock_irqsave(&smc->lock, flags); |
2020 | SMC_SELECT_BANK(3); | 2029 | SMC_SELECT_BANK(3); |
2021 | ret = smc_link_ok(dev); | 2030 | ret = smc_link_ok(dev); |
2022 | SMC_SELECT_BANK(saved_bank); | 2031 | SMC_SELECT_BANK(saved_bank); |
2023 | spin_unlock_irq(&smc->lock); | 2032 | spin_unlock_irqrestore(&smc->lock, flags); |
2024 | return ret; | 2033 | return ret; |
2025 | } | 2034 | } |
2026 | 2035 | ||
@@ -2057,16 +2066,17 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) | |||
2057 | int rc = 0; | 2066 | int rc = 0; |
2058 | u16 saved_bank; | 2067 | u16 saved_bank; |
2059 | unsigned int ioaddr = dev->base_addr; | 2068 | unsigned int ioaddr = dev->base_addr; |
2069 | unsigned long flags; | ||
2060 | 2070 | ||
2061 | if (!netif_running(dev)) | 2071 | if (!netif_running(dev)) |
2062 | return -EINVAL; | 2072 | return -EINVAL; |
2063 | 2073 | ||
2064 | spin_lock_irq(&smc->lock); | 2074 | spin_lock_irqsave(&smc->lock, flags); |
2065 | saved_bank = inw(ioaddr + BANK_SELECT); | 2075 | saved_bank = inw(ioaddr + BANK_SELECT); |
2066 | SMC_SELECT_BANK(3); | 2076 | SMC_SELECT_BANK(3); |
2067 | rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); | 2077 | rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); |
2068 | SMC_SELECT_BANK(saved_bank); | 2078 | SMC_SELECT_BANK(saved_bank); |
2069 | spin_unlock_irq(&smc->lock); | 2079 | spin_unlock_irqrestore(&smc->lock, flags); |
2070 | return rc; | 2080 | return rc; |
2071 | } | 2081 | } |
2072 | 2082 | ||