diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 626de1f0a6d3b4bbf1b9d275226a30290bcc8ce4..bcf04cb0be4a39af0ca25773360cbb079ace3c1d 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -47,6 +47,7 @@ * flushing the Jumbo ring. * Hans Grobler <grobh@sun.ac.za>: Memory leak fixes in the * driver init path. + * Grant Grundler <grundler@cup.hp.com>: PCI write posting fixes. */ #include <linux/config.h> @@ -120,6 +121,9 @@ #ifndef PCI_DEVICE_ID_FARALLON_PN9000SX #define PCI_DEVICE_ID_FARALLON_PN9000SX 0x1a #endif +#ifndef PCI_DEVICE_ID_FARALLON_PN9100T +#define PCI_DEVICE_ID_FARALLON_PN9100T 0xfa +#endif #ifndef PCI_VENDOR_ID_SGI #define PCI_VENDOR_ID_SGI 0x10a9 #endif @@ -140,10 +144,13 @@ static struct pci_device_id acenic_pci_tbl[] __initdata = { { PCI_VENDOR_ID_NETGEAR, PCI_DEVICE_ID_NETGEAR_GA620T, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, /* - * Farallon used the DEC vendor ID on their cards incorrectly. + * Farallon used the DEC vendor ID on their cards incorrectly, + * then later Alteon's ID. */ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_FARALLON_PN9000SX, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, + { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_FARALLON_PN9100T, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_ACENIC, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { } @@ -173,15 +180,27 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); #endif #ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) {do{} while(0);} +#define SET_MODULE_OWNER(dev) do{} while(0) #define ACE_MOD_INC_USE_COUNT MOD_INC_USE_COUNT #define ACE_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT #else -#define ACE_MOD_INC_USE_COUNT {do{} while(0);} -#define ACE_MOD_DEC_USE_COUNT {do{} while(0);} +#define ACE_MOD_INC_USE_COUNT do{} while(0) +#define ACE_MOD_DEC_USE_COUNT do{} while(0) #endif +#if LINUX_VERSION_CODE >= 0x2051c +#define ace_sync_irq(irq) synchronize_irq(irq) +#else +#define ace_sync_irq(irq) synchronize_irq() +#endif + +#if LINUX_VERSION_CODE < 0x2051e +#define local_irq_save(flags) do{__save_flags(flags) ; \ + __cli();} while(0) +#define local_irq_restore(flags) __restore_flags(flags) +#endif + #if (LINUX_VERSION_CODE < 0x02030d) #define pci_resource_start(dev, bar) dev->base_address[bar] #elif (LINUX_VERSION_CODE < 0x02032c) @@ -192,6 +211,7 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); #define net_device device #endif + #if (LINUX_VERSION_CODE < 0x02032a) typedef u32 dma_addr_t; @@ -215,8 +235,6 @@ static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, (((u64)(mask) & 0xffffffff00000000) == 0 ? 0 : -EIO) #define pci_dma_supported(dev, mask) \ (((u64)(mask) & 0xffffffff00000000) == 0 ? 1 : 0) -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) #elif (LINUX_VERSION_CODE < 0x02040d) @@ -240,8 +258,15 @@ pci_map_page(struct pci_dev *cookie, struct page *page, unsigned long off, } #define pci_unmap_page(cookie, dma_addr, size, dir) \ pci_unmap_single(cookie, dma_addr, size, dir) +#endif + +#if (LINUX_VERSION_CODE < 0x020412) #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) +#define pci_unmap_addr(PTR, ADDR_NAME) 0 +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do{} while(0) +#define pci_unmap_len(PTR, LEN_NAME) 0 +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do{} while(0) #endif @@ -259,7 +284,7 @@ pci_map_page(struct pci_dev *cookie, struct page *page, unsigned long off, #define dev_kfree_skb_irq(a) dev_kfree_skb(a) #define netif_wake_queue(dev) clear_bit(0, &dev->tbusy) #define netif_stop_queue(dev) set_bit(0, &dev->tbusy) -#define late_stop_netif_stop_queue(dev) {do{} while(0);} +#define late_stop_netif_stop_queue(dev) do{} while(0) #define early_stop_netif_stop_queue(dev) test_and_set_bit(0,&dev->tbusy) #define early_stop_netif_wake_queue(dev) netif_wake_queue(dev) @@ -273,7 +298,7 @@ static inline void netif_start_queue(struct net_device *dev) #define ace_mark_net_bh() mark_bh(NET_BH) #define netif_queue_stopped(dev) dev->tbusy #define netif_running(dev) dev->start -#define ace_if_down(dev) {do{dev->start = 0;} while(0);} +#define ace_if_down(dev) do{dev->start = 0;} while(0) #define tasklet_struct tq_struct static inline void tasklet_schedule(struct tasklet_struct *tasklet) @@ -291,13 +316,13 @@ static inline void tasklet_init(struct tasklet_struct *tasklet, tasklet->routine = (void (*)(void *))func; tasklet->data = (void *)data; } -#define tasklet_kill(tasklet) {do{} while(0);} +#define tasklet_kill(tasklet) do{} while(0) #else #define late_stop_netif_stop_queue(dev) netif_stop_queue(dev) #define early_stop_netif_stop_queue(dev) 0 -#define early_stop_netif_wake_queue(dev) {do{} while(0);} -#define ace_mark_net_bh() {do{} while(0);} -#define ace_if_down(dev) {do{} while(0);} +#define early_stop_netif_wake_queue(dev) do{} while(0) +#define ace_mark_net_bh() do{} while(0) +#define ace_if_down(dev) do{} while(0) #endif #if (LINUX_VERSION_CODE >= 0x02031b) @@ -313,7 +338,7 @@ static inline void tasklet_init(struct tasklet_struct *tasklet, #ifndef ARCH_HAS_PREFETCHW #ifndef prefetchw -#define prefetchw(x) {do{} while(0);} +#define prefetchw(x) do{} while(0) #endif #endif @@ -568,7 +593,7 @@ static int tx_ratio[ACE_MAX_MOD_PARMS]; static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; static char version[] __initdata = - "acenic.c: v0.89 03/15/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" + "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; static struct net_device *root_dev; @@ -611,6 +636,8 @@ int __devinit acenic_probe (ACE_PROBE_ARG) */ !((pdev->vendor == PCI_VENDOR_ID_DEC) && (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX)) && + !((pdev->vendor == PCI_VENDOR_ID_ALTEON) && + (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T)) && !((pdev->vendor == PCI_VENDOR_ID_SGI) && (pdev->device == PCI_DEVICE_ID_SGI_ACENIC))) continue; @@ -664,6 +691,11 @@ int __devinit acenic_probe (ACE_PROBE_ARG) printk(version); } + if (pci_enable_device(pdev)) { + kfree(dev); + continue; + } + /* * Enable master mode before we start playing with the * pci_command word since pci_set_master() will modify @@ -708,9 +740,17 @@ int __devinit acenic_probe (ACE_PROBE_ARG) switch(pdev->vendor) { case PCI_VENDOR_ID_ALTEON: - strncpy(ap->name, "AceNIC Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: Alteon AceNIC ", dev->name); + if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { + strncpy(ap->name, "Farallon PN9100-T " + "Gigabit Ethernet", sizeof (ap->name)); + printk(KERN_INFO "%s: Farallon PN9100-T ", + dev->name); + } else { + strncpy(ap->name, "AceNIC Gigabit Ethernet", + sizeof (ap->name)); + printk(KERN_INFO "%s: Alteon AceNIC ", + dev->name); + } break; case PCI_VENDOR_ID_3COM: strncpy(ap->name, "3Com 3C985 Gigabit Ethernet", @@ -846,6 +886,7 @@ static void __exit ace_module_cleanup(void) * This clears any pending interrupts */ writel(1, ®s->Mb0Lo); + readl(®s->CpuCtrl); /* flush */ /* * Make sure no other CPUs are processing interrupts @@ -856,7 +897,7 @@ static void __exit ace_module_cleanup(void) * Then release the RX buffers - jumbo buffers were * already released in ace_close(). */ - synchronize_irq(); + ace_sync_irq(root_dev->irq); for (i = 0; i < RX_STD_RING_ENTRIES; i++) { struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb; @@ -1138,34 +1179,30 @@ static int __init ace_init(struct net_device *dev) * to any crashes involving the NIC */ writel(HW_RESET | (HW_RESET << 24), ®s->HostCtrl); - wmb(); + readl(®s->HostCtrl); /* PCI write posting */ + udelay(5); /* - * Don't access any other registes before this point! + * Don't access any other registers before this point! */ #ifdef __BIG_ENDIAN /* * This will most likely need BYTE_SWAP once we switch * to using __raw_writel() */ -#ifdef __parisc__ - writel((WORD_SWAP | BYTE_SWAP | CLR_INT | - ((WORD_SWAP | BYTE_SWAP | CLR_INT) << 24)), - ®s->HostCtrl); -#else writel((WORD_SWAP | CLR_INT | ((WORD_SWAP | CLR_INT) << 24)), ®s->HostCtrl); -#endif #else writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)), ®s->HostCtrl); #endif - mb(); + readl(®s->HostCtrl); /* PCI write posting */ /* * Stop the NIC CPU and clear pending interrupts */ writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); + readl(®s->CpuCtrl); /* PCI write posting */ writel(0, ®s->Mb0Lo); tig_ver = readl(®s->HostCtrl) >> 28; @@ -1186,6 +1223,7 @@ static int __init ace_init(struct net_device *dev) tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor, tigon2FwReleaseFix); writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); + readl(®s->CpuBCtrl); /* PCI write posting */ /* * The SRAM bank size does _not_ indicate the amount * of memory on the card, it controls the _bank_ size! @@ -1217,7 +1255,7 @@ static int __init ace_init(struct net_device *dev) writel(ACE_BYTE_SWAP_DMA | ACE_WARN | ACE_FATAL | ACE_WORD_SWAP_BD | ACE_NO_JUMBO_FRAG, ®s->ModeStat); #endif - mb(); + readl(®s->ModeStat); /* PCI write posting */ mac1 = 0; for(i = 0; i < 4; i++) { @@ -1355,7 +1393,7 @@ static int __init ace_init(struct net_device *dev) tmp &= ~DMA_READ_WRITE_MASK; tmp |= DMA_READ_MAX_128; /* - * All the docs sy MUST NOT. Well, I did. + * All the docs say MUST NOT. Well, I did. * Nothing terrible happens, if we load wrong size. * Bit w&i still works better! */ @@ -1364,6 +1402,13 @@ static int __init ace_init(struct net_device *dev) writel(tmp, ®s->PciState); #if 0 + /* + * The Host PCI bus controller driver has to set FBB. + * If all devices on that PCI bus support FBB, then the controller + * can enable FBB support in the Host PCI Bus controller (or on + * the PCI-PCI bridge if that applies). + * -ggg + */ /* * I have received reports from people having problems when this * bit is enabled. @@ -1445,9 +1490,9 @@ static int __init ace_init(struct net_device *dev) set_aceaddr(&info->evt_ctrl.rngptr, ap->evt_ring_dma); info->evt_ctrl.flags = 0; - set_aceaddr(&info->evt_prd_ptr, ap->evt_prd_dma); *(ap->evt_prd) = 0; wmb(); + set_aceaddr(&info->evt_prd_ptr, ap->evt_prd_dma); writel(0, ®s->EvtCsm); set_aceaddr(&info->cmd_ctrl.rngptr, 0x100); @@ -1579,7 +1624,13 @@ static int __init ace_init(struct net_device *dev) writel(0, ®s->MaskInt); writel(1, ®s->IfIdx); +#if 0 + /* + * McKinley boxes do not like us fiddling with AssistState + * this early + */ writel(1, ®s->AssistState); +#endif writel(DEF_STAT, ®s->TuneStatTicks); writel(DEF_TRACE, ®s->TuneTrace); @@ -1689,10 +1740,19 @@ static int __init ace_init(struct net_device *dev) */ memset(&ap->stats, 0, sizeof(ap->stats)); + /* + * Enable DMA engine now. + * If we do this sooner, Mckinley box pukes. + * I assume it's because Tigon II DMA engine wants to check + * *something* even before the CPU is started. + */ + writel(1, ®s->AssistState); /* enable DMA */ + /* * Start the NIC CPU */ writel(readl(®s->CpuCtrl) & ~(CPU_HALT|CPU_TRACE), ®s->CpuCtrl); + readl(®s->CpuCtrl); /* * Wait for the firmware to spin up - max 3 seconds. @@ -1705,6 +1765,7 @@ static int __init ace_init(struct net_device *dev) ace_dump_trace(ap); writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); + readl(®s->CpuCtrl); /* aman@sgi.com - account for badly behaving firmware/NIC: * - have observed that the NIC may continue to generate @@ -1719,6 +1780,7 @@ static int __init ace_init(struct net_device *dev) writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); writel(0, ®s->Mb0Lo); + readl(®s->Mb0Lo); ecode = -EBUSY; goto init_error; @@ -2393,6 +2455,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) * threads and it is wrong even for that case. */ writel(0, ®s->Mb0Lo); + readl(®s->Mb0Lo); /* * There is no conflict between transmit handling in @@ -2496,12 +2559,13 @@ static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) struct ace_private *ap = dev->priv; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); + ace_mask_irq(dev); ap->vlgrp = grp; - restore_flags(flags); + ace_unmask_irq(dev); + local_irq_restore(flags); } @@ -2510,13 +2574,14 @@ static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) struct ace_private *ap = dev->priv; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); + ace_mask_irq(dev); if (ap->vlgrp) ap->vlgrp->vlan_devices[vid] = NULL; - restore_flags(flags); + ace_unmask_irq(dev); + local_irq_restore(flags); } #endif /* ACENIC_DO_VLAN */ @@ -2620,8 +2685,9 @@ static int ace_close(struct net_device *dev) * Make sure one CPU is not processing packets while * buffers are being released by another. */ - save_flags(flags); - cli(); + + local_irq_save(flags); + ace_mask_irq(dev); for (i = 0; i < ACE_TX_RING_ENTRIES(ap); i++) { struct sk_buff *skb; @@ -2658,7 +2724,8 @@ static int ace_close(struct net_device *dev) ace_issue_cmd(regs, &cmd); } - restore_flags(flags); + ace_unmask_irq(dev); + local_irq_restore(flags); ACE_MOD_DEC_USE_COUNT; return 0; @@ -2877,7 +2944,7 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu) } } else { while (test_and_set_bit(0, &ap->jumbo_refill_busy)); - synchronize_irq(); + ace_sync_irq(dev->irq); ace_set_rxtx_parms(dev, 0); if (ap->jumbo) { struct cmd cmd; @@ -3259,22 +3326,27 @@ static void __init eeprom_start(struct ace_regs *regs) { u32 local; + readl(®s->LocalCtrl); udelay(ACE_SHORT_DELAY); local = readl(®s->LocalCtrl); local |= EEPROM_DATA_OUT | EEPROM_WRITE_ENABLE; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local |= EEPROM_CLK_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local &= ~EEPROM_DATA_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local &= ~EEPROM_CLK_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); } @@ -3289,6 +3361,7 @@ static void __init eeprom_prep(struct ace_regs *regs, u8 magic) local &= ~EEPROM_DATA_OUT; local |= EEPROM_WRITE_ENABLE; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); for (i = 0; i < 8; i++, magic <<= 1) { @@ -3298,15 +3371,18 @@ static void __init eeprom_prep(struct ace_regs *regs, u8 magic) else local &= ~EEPROM_DATA_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local |= EEPROM_CLK_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local &= ~(EEPROM_CLK_OUT | EEPROM_DATA_OUT); writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); } } @@ -3320,10 +3396,12 @@ static int __init eeprom_check_ack(struct ace_regs *regs) local = readl(®s->LocalCtrl); local &= ~EEPROM_WRITE_ENABLE; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_LONG_DELAY); local |= EEPROM_CLK_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); /* sample data in middle of high clk */ @@ -3331,6 +3409,7 @@ static int __init eeprom_check_ack(struct ace_regs *regs) udelay(ACE_SHORT_DELAY); mb(); writel(readl(®s->LocalCtrl) & ~EEPROM_CLK_OUT, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); return state; @@ -3345,18 +3424,22 @@ static void __init eeprom_stop(struct ace_regs *regs) local = readl(®s->LocalCtrl); local |= EEPROM_WRITE_ENABLE; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local &= ~EEPROM_DATA_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local |= EEPROM_CLK_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); local |= EEPROM_DATA_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_LONG_DELAY); local &= ~EEPROM_CLK_OUT; @@ -3433,10 +3516,12 @@ static int __init read_eeprom_byte(struct net_device *dev, local = readl(®s->LocalCtrl); local &= ~EEPROM_WRITE_ENABLE; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); udelay(ACE_LONG_DELAY); mb(); local |= EEPROM_CLK_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); /* sample data mid high clk */ @@ -3447,11 +3532,13 @@ static int __init read_eeprom_byte(struct net_device *dev, local = readl(®s->LocalCtrl); local &= ~EEPROM_CLK_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); udelay(ACE_SHORT_DELAY); mb(); if (i == 7) { local |= EEPROM_WRITE_ENABLE; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); } @@ -3459,11 +3546,14 @@ static int __init read_eeprom_byte(struct net_device *dev, local |= EEPROM_DATA_OUT; writel(local, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); writel(readl(®s->LocalCtrl) | EEPROM_CLK_OUT, ®s->LocalCtrl); + readl(®s->LocalCtrl); udelay(ACE_LONG_DELAY); writel(readl(®s->LocalCtrl) & ~EEPROM_CLK_OUT, ®s->LocalCtrl); + readl(®s->LocalCtrl); mb(); udelay(ACE_SHORT_DELAY); eeprom_stop(regs); diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index 61eeecf8887ace08b2b05e88eb77bea6b6fd4a63..f51cda61db0277618017fd4b8f41eb0b5bd7394e 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h @@ -748,6 +748,32 @@ static inline void ace_set_txprd(struct ace_regs *regs, } +static inline void ace_mask_irq(struct net_device *dev) +{ + struct ace_private *ap = dev->priv; + struct ace_regs *regs = ap->regs; + + if (ACE_IS_TIGON_I(ap)) + writel(1, ®s->MaskInt); + else + writel(readl(®s->HostCtrl) | MASK_INTS, ®s->HostCtrl); + + ace_sync_irq(dev->irq); +} + + +static inline void ace_unmask_irq(struct net_device *dev) +{ + struct ace_private *ap = dev->priv; + struct ace_regs *regs = ap->regs; + + if (ACE_IS_TIGON_I(ap)) + writel(0, ®s->MaskInt); + else + writel(readl(®s->HostCtrl) &= ~MASK_INTS, ®s->HostCtrl); +} + + /* * Prototypes */