summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips64/sgi-ip27/ip27-irq.c100
-rw-r--r--arch/mips64/sgi-ip27/ip27-pci.c50
-rw-r--r--drivers/net/Space.c4
-rw-r--r--drivers/net/ioc3-eth.c112
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 ... */