diff options
-rw-r--r-- | arch/mips64/sgi-ip27/ip27-irq.c | 100 | ||||
-rw-r--r-- | arch/mips64/sgi-ip27/ip27-pci.c | 50 | ||||
-rw-r--r-- | drivers/net/Space.c | 4 | ||||
-rw-r--r-- | drivers/net/ioc3-eth.c | 112 |
4 files changed, 131 insertions, 135 deletions
diff --git a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c index 7de2b8549..d1c38430c 100644 --- a/arch/mips64/sgi-ip27/ip27-irq.c +++ b/arch/mips64/sgi-ip27/ip27-irq.c @@ -83,12 +83,9 @@ unsigned long spurious_count = 0; * from the irq value */ #define IRQ_TO_BUS(i) irq_to_bus[(i)] -#define IRQ_TO_CPU(i) \ - ((i) == IOC3_ETH_INT ? 0 : bus_to_cpu[IRQ_TO_BUS(i)]) -#define NASID_FROM_PCI_IRQ(i) \ - (((i) == IOC3_ETH_INT) ? 0 : bus_to_nid[IRQ_TO_BUS(i)]) -#define WID_FROM_PCI_IRQ(i) \ - (((i) == IOC3_ETH_INT) ? 8 : bus_to_wid[IRQ_TO_BUS(i)]) +#define IRQ_TO_CPU(i) bus_to_cpu[IRQ_TO_BUS(i)] +#define NASID_FROM_PCI_IRQ(i) bus_to_nid[IRQ_TO_BUS(i)] +#define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)] #define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] void disable_irq(unsigned int irq_nr) @@ -221,8 +218,9 @@ void ip27_do_irq(struct pt_regs *regs) /* Startup one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int bridge_startup(unsigned int irq) { - bridge_t *bridge; - int pin, swlevel; + bridgereg_t device; + bridge_t *bridge; + int pin, swlevel; cpuid_t cpu; nasid_t master = NASID_FROM_PCI_IRQ(irq); @@ -230,46 +228,28 @@ static unsigned int bridge_startup(unsigned int irq) pin = SLOT_FROM_PCI_IRQ(irq); cpu = IRQ_TO_CPU(irq); - DBG("bridge_startup(): irq= 0x%x real_irq= %d pin=%d\n", irq, real_irq, pin); - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = IRQ_TO_SWLEVEL(cpu, irq); - intr_connect_level(cpu, swlevel); - - bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); - bridge->b_int_enable |= (1 << pin); - /* set more stuff in int_enable reg */ + DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = IRQ_TO_SWLEVEL(cpu, irq); + intr_connect_level(cpu, swlevel); + + bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); + bridge->b_int_enable |= (1 << pin); + /* more stuff in int_enable reg */ bridge->b_int_enable |= 0x7ffffe00; - if (irq != IOC3_ETH_INT) { - bridgereg_t device; -#if 0 - /* - * Allocate enough RRBs on the bridge for the DMAs. - * Right now allocating 2 RRBs on the normal channel - * and 2 on the virtual channel for slot 0 on the bus. - * And same for slot 1, to get ioc3 eth working. - */ - Not touching b_even_resp /* boot doesn't go far */ - bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */ - bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */ - bridge->b_even_resp = 0xcc88; /* breaks eth0 */ -#endif - /* Turn on bridge swapping */ - device = bridge->b_device[pin].reg; - device |= BRIDGE_DEV_SWAP_DIR; - bridge->b_device[pin].reg = device; - /* - * XXX This only works if b_int_device is initialized to 0! - * We program the bridge to have a 1:1 mapping between devices - * (slots) and intr pins. - */ - device = bridge->b_int_device; - device |= (pin << (pin*3)); - bridge->b_int_device = device; - } + /* + * XXX This only works if b_int_device is initialized to 0! + * We program the bridge to have a 1:1 mapping between devices + * (slots) and intr pins. + */ + device = bridge->b_int_device; + device |= (pin << (pin*3)); + bridge->b_int_device = device; + bridge->b_widget.w_tflush; /* Flush */ return 0; /* Never anything pending. */ @@ -278,25 +258,25 @@ static unsigned int bridge_startup(unsigned int irq) /* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int bridge_shutdown(unsigned int irq) { - bridge_t *bridge; - int pin, swlevel; + bridge_t *bridge; + int pin, swlevel; - bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), - WID_FROM_PCI_IRQ(irq)); + bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), + WID_FROM_PCI_IRQ(irq)); DBG("bridge_shutdown: irq 0x%x\n", irq); pin = SLOT_FROM_PCI_IRQ(irq); - /* - * map irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = IRQ_TO_SWLEVEL(cpu, irq); - intr_disconnect_level(smp_processor_id(), swlevel); + /* + * map irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = IRQ_TO_SWLEVEL(cpu, irq); + intr_disconnect_level(smp_processor_id(), swlevel); - bridge->b_int_enable &= ~(1 << pin); - bridge->b_widget.w_tflush; /* Flush */ + bridge->b_int_enable &= ~(1 << pin); + bridge->b_widget.w_tflush; /* Flush */ - return 0; /* Never anything pending. */ + return 0; /* Never anything pending. */ } void irq_debug(void) @@ -726,7 +706,7 @@ void install_cpuintr(cpuid_t cpu) done = 1; /* HACK ENDS */ #else /* CPUS_PER_NODE */ - << Bomb! Must redefine this for more than 2 CPUS. >> +#error Must redefine this for more than 2 CPUS. #endif /* CPUS_PER_NODE */ #endif /* CONFIG_SMP */ } diff --git a/arch/mips64/sgi-ip27/ip27-pci.c b/arch/mips64/sgi-ip27/ip27-pci.c index 4892fa1ec..c0a88050d 100644 --- a/arch/mips64/sgi-ip27/ip27-pci.c +++ b/arch/mips64/sgi-ip27/ip27-pci.c @@ -148,11 +148,6 @@ void __init pcibios_init(void) int i; ioport_resource.end = ~0UL; - /* - * Hacks for ioc3 eth. Make sure we associate IOC3_ETH_INT - * with nasid 0, widget 8, slot 2. - */ - irq_to_slot[IOC3_ETH_INT] = 2; for (i=0; i<num_bridges; i++) { printk("PCI: Probing PCI hardware on host bus %2d.\n", i); @@ -271,6 +266,38 @@ pcibios_setup(char *str) } static void __init +pci_disable_swapping(struct pci_dev *dev) +{ + unsigned int bus_id = (unsigned) dev->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + int slot = PCI_SLOT(dev->devfn); + bridgereg_t devreg; + + devreg = bridge->b_device[slot].reg; + devreg &= ~BRIDGE_DEV_SWAP_DIR; /* turn off byte swapping */ + bridge->b_device[slot].reg = devreg; + + bridge->b_widget.w_tflush; /* Flush */ +} + +static void __init +pci_enable_swapping(struct pci_dev *dev) +{ + unsigned int bus_id = (unsigned) dev->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + int slot = PCI_SLOT(dev->devfn); + bridgereg_t devreg; + + devreg = bridge->b_device[slot].reg; + devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */ + bridge->b_device[slot].reg = devreg; + + bridge->b_widget.w_tflush; /* Flush */ +} + +static void __init pci_fixup_ioc3(struct pci_dev *d) { int i; @@ -289,6 +316,8 @@ pci_fixup_ioc3(struct pci_dev *d) d->subsystem_vendor = 0; d->subsystem_device = 0; d->irq = 1; + + pci_disable_swapping(d); } static void __init @@ -311,6 +340,8 @@ pci_fixup_isp1020(struct pci_dev *d) command |= PCI_COMMAND_IO; pci_write_config_word(d, PCI_COMMAND, command); d->resource[1].flags |= 1; + + pci_enable_swapping(d); } static void __init @@ -346,12 +377,10 @@ pci_fixup_isp2x00(struct pci_dev *d) /* point device(x) to it appropriate small window */ devreg &= ~BRIDGE_DEV_OFF_MASK; devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; - - /* turn on byte swapping in direct map mode (how we currently run dma's) */ - devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */ - bridge->b_device[slot].reg = devreg; + pci_enable_swapping(d); + /* set card's base addr reg */ //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); @@ -365,7 +394,6 @@ pci_fixup_isp2x00(struct pci_dev *d) pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start); //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); - /* set cache line size */ pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); @@ -377,7 +405,7 @@ pci_fixup_isp2x00(struct pci_dev *d) /* set host error field */ bridge->b_int_host_err = 0x44; bridge->b_wid_tflush; - + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ for (i=0; i<8; i++) printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg); diff --git a/drivers/net/Space.c b/drivers/net/Space.c index ee728a86c..e93a9f70d 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -79,7 +79,6 @@ extern int ni5010_probe(struct net_device *); extern int ni52_probe(struct net_device *); extern int ni65_probe(struct net_device *); extern int sonic_probe(struct net_device *); -extern int ioc3_probe(struct net_device *); extern int SK_init(struct net_device *); extern int seeq8005_probe(struct net_device *); extern int smc_init( struct net_device * ); @@ -388,9 +387,6 @@ struct devprobe mips_probes[] __initdata = { #ifdef CONFIG_MIPS_JAZZ_SONIC {sonic_probe, 0}, #endif -#ifdef CONFIG_SGI_IOC3_ETH - {ioc3_probe, 0}, -#endif #ifdef CONFIG_BAGETLANCE /* Lance-based Baget ethernet boards */ {bagetlance_probe, 0}, #endif diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index c55dc5d8f..4f33bf1ca 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -54,6 +54,7 @@ #include <linux/errno.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/pci_ids.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -107,6 +108,7 @@ struct ioc3_private { int rx_pi; /* RX producer index */ int tx_ci; /* TX consumer index */ int tx_pi; /* TX producer index */ + int txqlen; spinlock_t ioc3_lock; }; @@ -134,15 +136,6 @@ struct ioc3_private { #define BARRIER() \ __asm__("sync" ::: "memory") -/* This El Cheapo implementatin of TX_BUFFS_AVAIL may leave on entry unused. - Since the TX ring has 128 entries which is fairly large we don't care and - use this, more efficient implementation. */ -#define TX_BUFFS_AVAIL(ip) \ -({ \ - struct ioc3_private *_ip = (ip); \ - ((512 + _ip->tx_ci + 1) - _ip->tx_pi) & 511; \ -}) - #define IOC3_SIZE 0x100000 @@ -240,7 +233,7 @@ static void nic_show_regnr(struct ioc3 *ioc3) for (i = 0; i < 8; i++) regnr[i] = nic_read_byte(ioc3); - switch(regnr[0]) { + switch (regnr[0]) { case 0x01: type = "DS1990A"; break; case 0x91: type = "DS1981U"; break; default: type = "unknown"; break; @@ -395,8 +388,9 @@ next: } static inline void -ioc3_tx(struct ioc3_private *ip, struct ioc3 *ioc3) +ioc3_tx(struct net_device *dev, struct ioc3_private *ip, struct ioc3 *ioc3) { + unsigned long packets, bytes; int tx_entry, o_entry; struct sk_buff *skb; u32 etcir; @@ -405,14 +399,16 @@ ioc3_tx(struct ioc3_private *ip, struct ioc3 *ioc3) etcir = ioc3->etcir; tx_entry = (etcir >> 7) & 127; o_entry = ip->tx_ci; + packets = 0; + bytes = 0; while (o_entry != tx_entry) { ioc3->eisr = EISR_TXEXPLICIT; /* Ack */ ioc3->eisr; /* Flush */ + packets++; + bytes += skb->len; skb = ip->tx_skbs[o_entry]; - ip->stats.tx_packets++; - ip->stats.tx_bytes += skb->len; dev_kfree_skb_irq(skb); ip->tx_skbs[o_entry] = NULL; @@ -421,6 +417,14 @@ ioc3_tx(struct ioc3_private *ip, struct ioc3 *ioc3) etcir = ioc3->etcir; /* More pkts sent? */ tx_entry = (etcir >> 7) & 127; } + + ip->stats.tx_packets += packets; + ip->stats.tx_bytes += bytes; + ip->txqlen -= packets; + + if (ip->txqlen < 128) + netif_wake_queue(dev); + ip->tx_ci = o_entry; spin_unlock(&ip->ioc3_lock); } @@ -464,16 +468,12 @@ static void ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs) ioc3_rx(dev, ip, ioc3); } if (eisr & EISR_TXEXPLICIT) { - ioc3_tx(ip, ioc3); + ioc3_tx(dev, ip, ioc3); } if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR)) { ioc3_error(dev, ip, ioc3, eisr); } - if ((TX_BUFFS_AVAIL(ip) >= 0) && netif_queue_stopped(dev)) { - netif_wake_queue(dev); - } - __cli(); ioc3->eier = eier; @@ -620,9 +620,12 @@ ioc3_ssram_disc(struct ioc3_private *ip) } } -static void ioc3_probe1(struct net_device *dev, struct ioc3 *ioc3) +static void ioc3_init(struct pci_dev *pdev) { + struct net_device *dev = NULL; // XXX struct ioc3_private *ip; + struct ioc3 *ioc3; + unsigned long ioc3_base, ioc3_size; dev = init_etherdev(dev, 0); @@ -636,8 +639,11 @@ static void ioc3_probe1(struct net_device *dev, struct ioc3 *ioc3) ip = (struct ioc3_private *) kmalloc(sizeof(*ip), GFP_KERNEL); memset(ip, 0, sizeof(*ip)); dev->priv = ip; - dev->irq = IOC3_ETH_INT; + dev->irq = pdev->irq; + ioc3_base = pdev->resource[0].start; + ioc3_size = pdev->resource[0].end - ioc3_base; + ioc3 = (struct ioc3 *) ioremap(ioc3_base, ioc3_size); ip->regs = ioc3; ioc3_eth_init(dev, ip, ioc3); @@ -646,6 +652,7 @@ static void ioc3_probe1(struct net_device *dev, struct ioc3 *ioc3) ioc3_init_rings(dev, ip, ioc3); spin_lock_init(&ip->ioc3_lock); + ip->txqlen = 0; /* Misc registers */ ioc3->erbar = 0; @@ -671,26 +678,26 @@ static void ioc3_probe1(struct net_device *dev, struct ioc3 *ioc3) dev->set_multicast_list = ioc3_set_multicast_list; } -int -ioc3_probe(struct net_device *dev) +static int __init ioc3_probe(void) { - static int initialized; + static int called = 0; struct ioc3 *ioc3; - nasid_t nid; + int cards; - if (initialized) /* Only initialize once ... */ - return 0; - initialized++; + if (called) + return -ENODEV; + called = 1; -#if 0 - nid = get_nasid(); /* Never assume we are on master cpu */ -#else - nid = 0; -#endif - ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; - ioc3_probe1(dev, ioc3); + if (pci_present()) { + struct pci_dev *pdev = NULL; - return 0; + while ((pdev = pci_find_device(PCI_VENDOR_ID_SGI, + PCI_DEVICE_ID_SGI_IOC3, pdev))) { + ioc3_init(pdev); + } + } + + return cards ? -ENODEV : 0; } static int @@ -715,7 +722,7 @@ ioc3_open(struct net_device *dev) ioc3->eier = EISR_RXTIMERINT | EISR_TXEXPLICIT | /* Interrupts ... */ EISR_RXMEMERR | EISR_TXMEMERR; - netif_wake_queue(dev); + netif_start_queue(dev); restore_flags(flags); MOD_INC_USE_COUNT; @@ -733,11 +740,8 @@ ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) struct ioc3_etxd *desc; int produce; - if (!TX_BUFFS_AVAIL(ip)) { - return 1; - } - spin_lock_irq(&ip->ioc3_lock); + data = (unsigned long) skb->data; len = skb->len; @@ -781,8 +785,11 @@ ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) ip->tx_pi = produce; ioc3->etpir = produce << 7; /* Fire ... */ - if (TX_BUFFS_AVAIL(ip)) - netif_wake_queue(dev); + ip->txqlen++; + + if (ip->txqlen > 127) + netif_stop_queue(dev); + spin_unlock_irq(&ip->ioc3_lock); return 0; @@ -954,22 +961,7 @@ static void ioc3_set_multicast_list(struct net_device *dev) #ifdef MODULE MODULE_AUTHOR("Ralf Baechle <ralf@oss.sgi.com>"); MODULE_DESCRIPTION("SGI IOC3 Ethernet driver"); - -int -init_module(void) -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_VENDOR_ID_SGI, 0x0003, dev))) { - ioc3_init(&p, dev); - } - - return -EBUSY; -} - -void -cleanup_module(void) -{ - printk("cleanup_module called\n"); -} #endif /* MODULE */ + +module_init(ioc3_probe); +//module_exit(ioc3_cleanup_module); /* Not yet ... */ |