diff options
Diffstat (limited to 'drivers/net/pcmcia/smc91c92_cs.c')
| -rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 56 | 
1 files changed, 34 insertions, 22 deletions
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 5adc662c4bf..ccc553782a0 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -493,13 +493,14 @@ static int pcmcia_get_versmac(struct pcmcia_device *p_dev,  {  	struct net_device *dev = priv;  	cisparse_t parse; +	u8 *buf;  	if (pcmcia_parse_tuple(tuple, &parse))  		return -EINVAL; -	if ((parse.version_1.ns > 3) && -	    (cvt_ascii_address(dev, -			       (parse.version_1.str + parse.version_1.ofs[3])))) +	buf = parse.version_1.str + parse.version_1.ofs[3]; + +	if ((parse.version_1.ns > 3) && (cvt_ascii_address(dev, buf) == 0))  		return 0;  	return -EINVAL; @@ -528,7 +529,7 @@ static int mhz_setup(struct pcmcia_device *link)      len = pcmcia_get_tuple(link, 0x81, &buf);      if (buf && len >= 13) {  	    buf[12] = '\0'; -	    if (cvt_ascii_address(dev, buf)) +	    if (cvt_ascii_address(dev, buf) == 0)  		    rc = 0;      }      kfree(buf); @@ -910,7 +911,7 @@ static int smc91c92_config(struct pcmcia_device *link)      if (i != 0) {  	printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n"); -	goto config_undo; +	goto config_failed;      }      smc->duplex = 0; @@ -998,6 +999,7 @@ config_undo:      unregister_netdev(dev);  config_failed:      smc91c92_release(link); +    free_netdev(dev);      return -ENODEV;  } /* smc91c92_config */ @@ -1606,9 +1608,12 @@ static void set_rx_mode(struct net_device *dev)  {      unsigned int ioaddr = dev->base_addr;      struct smc_private *smc = netdev_priv(dev); -    u_int multicast_table[ 2 ] = { 0, }; +    unsigned char multicast_table[8];      unsigned long flags;      u_short rx_cfg_setting; +    int i; + +    memset(multicast_table, 0, sizeof(multicast_table));      if (dev->flags & IFF_PROMISC) {  	rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; @@ -1620,10 +1625,6 @@ static void set_rx_mode(struct net_device *dev)  	    netdev_for_each_mc_addr(mc_addr, dev) {  		u_int position = ether_crc(6, mc_addr->dmi_addr); -#ifndef final_version		/* Verify multicast address. */ -		if ((mc_addr->dmi_addr[0] & 1) == 0) -		    continue; -#endif  		multicast_table[position >> 29] |= 1 << ((position >> 26) & 7);  	    }  	} @@ -1633,8 +1634,8 @@ static void set_rx_mode(struct net_device *dev)      /* Load MC table and Rx setting into the chip without interrupts. */      spin_lock_irqsave(&smc->lock, flags);      SMC_SELECT_BANK(3); -    outl(multicast_table[0], ioaddr + MULTICAST0); -    outl(multicast_table[1], ioaddr + MULTICAST4); +    for (i = 0; i < 8; i++) +	outb(multicast_table[i], ioaddr + MULTICAST0 + i);      SMC_SELECT_BANK(0);      outw(rx_cfg_setting, ioaddr + RCR);      SMC_SELECT_BANK(2); @@ -1803,23 +1804,30 @@ static void media_check(u_long arg)      SMC_SELECT_BANK(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         this, we can limp along even if the interrupt is blocked */      if (smc->watchdog++ && ((i>>8) & i)) {  	if (!smc->fast_poll)  	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); +	local_irq_save(flags);  	smc_interrupt(dev->irq, dev); +	local_irq_restore(flags);  	smc->fast_poll = HZ;      }      if (smc->fast_poll) {  	smc->fast_poll--;  	smc->media.expires = jiffies + HZ/100;  	add_timer(&smc->media); -	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irqrestore(&smc->lock, flags);  	return;      } +    spin_lock_irqsave(&smc->lock, flags); + +    saved_bank = inw(ioaddr + BANK_SELECT); +      if (smc->cfg & CFG_MII_SELECT) {  	if (smc->mii_if.phy_id < 0)  	    goto reschedule; @@ -1977,15 +1985,16 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  	unsigned int ioaddr = dev->base_addr;  	u16 saved_bank = inw(ioaddr + BANK_SELECT);  	int ret; +	unsigned long flags; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	SMC_SELECT_BANK(3);  	if (smc->cfg & CFG_MII_SELECT)  		ret = mii_ethtool_gset(&smc->mii_if, ecmd);  	else  		ret = smc_netdev_get_ecmd(dev, ecmd);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return ret;  } @@ -1995,15 +2004,16 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  	unsigned int ioaddr = dev->base_addr;  	u16 saved_bank = inw(ioaddr + BANK_SELECT);  	int ret; +	unsigned long flags; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	SMC_SELECT_BANK(3);  	if (smc->cfg & CFG_MII_SELECT)  		ret = mii_ethtool_sset(&smc->mii_if, ecmd);  	else  		ret = smc_netdev_set_ecmd(dev, ecmd);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return ret;  } @@ -2013,12 +2023,13 @@ static u32 smc_get_link(struct net_device *dev)  	unsigned int ioaddr = dev->base_addr;  	u16 saved_bank = inw(ioaddr + BANK_SELECT);  	u32 ret; +	unsigned long flags; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	SMC_SELECT_BANK(3);  	ret = smc_link_ok(dev);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return ret;  } @@ -2055,16 +2066,17 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)  	int rc = 0;  	u16 saved_bank;  	unsigned int ioaddr = dev->base_addr; +	unsigned long flags;  	if (!netif_running(dev))  		return -EINVAL; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	saved_bank = inw(ioaddr + BANK_SELECT);  	SMC_SELECT_BANK(3);  	rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return rc;  }  |