diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
commit | 95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch) | |
tree | 27a92a942821cde1edda9a1b088718d436b3efe4 /drivers/net/tokenring/olympic.c | |
parent | 45b27b0a0652331d104c953a5b192d843fff88f8 (diff) |
Merge with Linux 2.3.40.
Diffstat (limited to 'drivers/net/tokenring/olympic.c')
-rw-r--r-- | drivers/net/tokenring/olympic.c | 108 |
1 files changed, 43 insertions, 65 deletions
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 8f1f6cce0..fcb3ccd76 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -25,10 +25,11 @@ * 8/18/99 - Updated driver for 2.3.13 kernel to use new pci * resource. Driver also reports the card name returned by * the pci resource. + * 1/11/00 - Added spinlocks for smp * * To Do: * - * Sanitize for smp + * IPv6 Multicast * * If Problems do Occur * Most problems can be rectified by either closing and opening the interface @@ -69,6 +70,7 @@ #include <linux/stddef.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/spinlock.h> #include <net/checksum.h> #include <asm/io.h> @@ -86,7 +88,7 @@ */ static char *version = -"Olympic.c v0.3.0 8/18/99 - Peter De Schrijver & Mike Phillips" ; +"Olympic.c v0.3.1 1/11/00 - Peter De Schrijver & Mike Phillips" ; static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion", "Address Verification", "Neighbor Notification (Ring Poll)", @@ -202,7 +204,6 @@ static int __init olympic_scan(struct net_device *dev) olympic_priv->olympic_ring_speed = ringspeed[card_no] ; olympic_priv->olympic_message_level = message_level[card_no] ; - olympic_priv->olympic_multicast_set = 0 ; if(olympic_init(dev)==-1) { unregister_netdevice(dev); @@ -251,6 +252,8 @@ static int __init olympic_init(struct net_device *dev) } } + spin_lock_init(&olympic_priv->olympic_lock) ; + #if OLYMPIC_DEBUG printk("BCTL: %x\n",readl(olympic_mmio+BCTL)); printk("GPR: %x\n",readw(olympic_mmio+GPR)); @@ -757,6 +760,8 @@ static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ return ; + spin_lock(&olympic_priv->olympic_lock); + if (dev->interrupt) printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ; @@ -835,15 +840,20 @@ static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) dev->interrupt = 0 ; writel(SISR_MI,olympic_mmio+SISR_MASK_SUM); - + + spin_unlock(&olympic_priv->olympic_lock) ; } static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - __u8 *olympic_mmio=olympic_priv->olympic_mmio; + __u8 *olympic_mmio=olympic_priv->olympic_mmio; + unsigned long flags ; + + spin_lock_irqsave(&olympic_priv->olympic_lock, flags); if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); return 1; } @@ -860,10 +870,12 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1); dev->tbusy=0; - + spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); return 0; - } else + } else { + spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); return 1; + } } @@ -936,9 +948,11 @@ static void olympic_set_rx_mode(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; __u8 *olympic_mmio = olympic_priv->olympic_mmio ; - __u8 options = 0, set_mc_list = 0 ; - __u8 *srb, *ata ; + __u8 options = 0; + __u8 *srb; struct dev_mc_list *dmi ; + unsigned char dev_mc_address[4] ; + int i ; writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); @@ -949,10 +963,6 @@ static void olympic_set_rx_mode(struct net_device *dev) else options &= ~(3<<5) ; - if (dev->mc_count) { - set_mc_list = 1 ; - } - /* Only issue the srb if there is a change in options */ if ((options ^ olympic_priv->olympic_copy_all_options)) { @@ -975,60 +985,30 @@ static void olympic_set_rx_mode(struct net_device *dev) return ; } - if (set_mc_list ^ olympic_priv->olympic_multicast_set) { /* Multicast options have changed */ - - dmi = dev->mc_list ; + /* Set the functional addresses we need for multicast */ - if (set_mc_list) { /* Turn multicast on */ - - /* RFC 1469 Says we must support using the functional address C0 00 00 04 00 00 - * We do this with a set functional address mask. - */ - - ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ; - if (!(readb(ata+11) & 0x04)) { /* Hmmm, need to set the functional mask */ - writeb(SRB_SET_FUNC_ADDRESS,srb+0); - writeb(0,srb+1); - writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); - writeb(0,srb+3); - writeb(0,srb+4); - writeb(0,srb+5); - writeb(readb(ata+10),srb+6); - writeb(readb(ata+11)|4,srb+7); - writeb(readb(ata+12),srb+8); - writeb(readb(ata+13),srb+9); - - olympic_priv->srb_queued = 2 ; - writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); - - olympic_priv->olympic_multicast_set = 1 ; - } - - - } else { /* Turn multicast off */ - - ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ; - if ((readb(ata+11) & 0x04)) { /* Hmmm, need to reset the functional mask */ - writeb(SRB_SET_FUNC_ADDRESS,srb+0); - writeb(0,srb+1); - writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); - writeb(0,srb+3); - writeb(0,srb+4); - writeb(0,srb+5); - writeb(readb(ata+10),srb+6); - writeb(readb(ata+11) & ~4,srb+7); - writeb(readb(ata+12),srb+8); - writeb(readb(ata+13),srb+9); - - olympic_priv->srb_queued = 2 ; - writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); - - olympic_priv->olympic_multicast_set = 0 ; - } - } + dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; + for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { + dev_mc_address[0] |= dmi->dmi_addr[2] ; + dev_mc_address[1] |= dmi->dmi_addr[3] ; + dev_mc_address[2] |= dmi->dmi_addr[4] ; + dev_mc_address[3] |= dmi->dmi_addr[5] ; } + writeb(SRB_SET_FUNC_ADDRESS,srb+0); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + writeb(0,srb+3); + writeb(0,srb+4); + writeb(0,srb+5); + writeb(dev_mc_address[0],srb+6); + writeb(dev_mc_address[1],srb+7); + writeb(dev_mc_address[2],srb+8); + writeb(dev_mc_address[3],srb+9); + + olympic_priv->srb_queued = 2 ; + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); } @@ -1069,7 +1049,6 @@ static void olympic_srb_bh(struct net_device *dev) case SRB_SET_GROUP_ADDRESS: switch (readb(srb+2)) { case 0x00: - olympic_priv->olympic_multicast_set = 1 ; break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; @@ -1097,7 +1076,6 @@ static void olympic_srb_bh(struct net_device *dev) case SRB_RESET_GROUP_ADDRESS: switch (readb(srb+2)) { case 0x00: - olympic_priv->olympic_multicast_set = 0 ; break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; |