Update of /cvsroot/gc-linux/linux/drivers/net
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13964/linux/drivers/net
Modified Files:
gc-net.c
Log Message:
improofed internal structure, read comment in file
Index: gc-net.c
===================================================================
RCS file: /cvsroot/gc-linux/linux/drivers/net/gc-net.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- gc-net.c 27 Feb 2004 00:06:33 -0000 1.19
+++ gc-net.c 29 Feb 2004 08:36:29 -0000 1.20
@@ -22,6 +22,9 @@
* $Id$
*
* $Log$
+ * Revision 1.20 2004/02/29 08:36:29 hamtitampti
+ * improofed internal structure, read comment in file
+ *
* Revision 1.19 2004/02/27 00:06:33 hamtitampti
* changed IRQ timing, but .. yes, the bus is too slow it seems
*
@@ -34,6 +37,84 @@
*
*/
+/*
+ Important Notes for Developers:
+
+ currently speeds:
+ 1008 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=3.3 ms
+ 2008 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=6.0 ms
+ 5008 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=14.1 ms
+ 10008 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=27.0 ms
+ 20008 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=53.2 ms
+ 65000 bytes about 172ms (with Win2000)
+
+ As you see, the Delay increases "linear"
+ this comes due to a Bandwith Problem with the EXI bus.
+
+ note:
+ All ! i repeat ALL
+ packets are received with the
+ static void gc_input(struct net_device *dev)
+ and sent to the linux kernel then.
+
+ BUT !
+ the Transmit Back , the
+ static int gc_bba_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ As you see inside this function, i check, if the Transmit is currently in progress
+ if "yes" (priv->tx_lock)
+ i wait then a small time, and return with 1 !
+ (otherwise, the linux kernel try's to resume the packet .. about 1mill / sec or so)
+ the Return 1; indicates to the linux kernel to resume the packet tramsission.
+
+ if (priv->tx_lock) {
+ priv->stats.tx_dropped++;
+ udelay(1000);
+ netif_wake_queue(dev);
+ return 1; // This return will Resume the packet try
+ }
+
+ So it happens, that the packet wich the linux Stack wants to send , enters multiple times the Xmit thing.
+ Until it time-out in Linux Packet buffer, logically.
+
+ due to the tx_dropped, you see in ifconfig the dropped TX packets increasing.
+ Clear, there are more dropped packets then (as kernel resumes automaticall)
+ but i had no better idea.
+
+ RX packets:582 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:475 errors:0 dropped:775 overruns:0 carrier:0
+
+
+ Flood Performance:
+ 1K: 2531 packets transmitted, 2103 packets received, 16% packet loss
+ 2K: 1095 packets transmitted, 736 packets received, 32% packet loss
+ 4K: 886 packets transmitted, 472 packets received, 46% packet loss
+ 8K: 773 packets transmitted, 276 packets received, 64% packet loss
+
+ ok
+ AT last:
+
+ Even at flood, the kernel gets all RX (received frames)
+ but fails due to send back.
+
+
+ 100Mbit issue:
+ eth_outb(0x30, 0x2);
+
+ This activates 100Mbit
+ Testet and operational. (market out in source)
+
+ BAD: the ping / flood gets more worse.
+ as the packets arrive now faster, the bus almost crashes.
+
+ BOYS, Write a Faster EXI driver, this is the maximum we can do now.
+
+ hamtitampti
+
+
+
+*/
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -71,6 +152,7 @@
spinlock_t lock;
spinlock_t phylock; /* phy lock */
unsigned long lockflags; /* Lock flags */
+ int tx_lock;
// Statistical Data
struct net_device_stats stats;
@@ -157,8 +239,7 @@
while (len)
{
int tc = len;
- if (tc > 4)
- tc = 4;
+ if (tc > 4) tc = 4;
exi_imm(channel, d, tc, mode, 0);
exi_sync(channel);
len-=tc;
@@ -404,30 +485,6 @@
/*
-
-static inline u8 de600_read_status(struct net_device *dev)
-{
- u8 status;
-
- outb_p(STATUS, DATA_PORT);
- status = inb(STATUS_PORT);
- outb_p(NULL_COMMAND | HI_NIBBLE, DATA_PORT);
-
- return status;
-}
-
-static inline u8 de600_read_byte(unsigned char type, struct net_device *dev)
-{
- // dev used by macros
- u8 lo;
- outb_p((type), DATA_PORT);
- lo = ((unsigned char)inb(STATUS_PORT)) >> 4;
- outb_p((type) | HI_NIBBLE, DATA_PORT);
- return ((unsigned char)inb(STATUS_PORT) & (unsigned char)0xf0) | lo;
-}
-*/
-
-/*
* Open/initialize the board. This is called (in the current kernel)
* after booting when 'ifconfig <dev->name> $IP_ADDR' is run (in rc.inet1).
*
@@ -463,12 +520,6 @@
static int gc_bba_close(struct net_device *dev)
{
BBA_DBG("gc_bba_close\n");
-
-// //select_nic();
-// de600_put_command(RESET);
-// de600_put_command(STOP_RESET);
-// de600_put_command(0);
-// //select_prn();
free_irq(dev->irq, dev);
return 0;
}
@@ -480,15 +531,6 @@
return &priv->stats;
}
-static inline void trigger_interrupt(struct net_device *dev)
-{
-// de600_put_command(FLIP_IRQ);
-// //select_prn();
-// DE600_SLOW_DOWN;
-// //select_nic();
-// de600_put_command(0);
-}
-
/*
* Copy a buffer to the adapter transmit page memory.
* Start sending.
@@ -497,17 +539,29 @@
static int gc_bba_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct gc_private *priv = (struct gc_private *)dev->priv;
- unsigned char Reg0;
+
+ netif_stop_queue(dev);
+
+ if (priv->tx_lock) {
+ priv->stats.tx_dropped++;
+ udelay(1000);
+ netif_wake_queue(dev);
+ return 1; // This return will Resume the packet try
+ }
+
+ priv->tx_lock = 1;
- spin_lock_irqsave(&priv->lock, priv->lockflags);
- netif_stop_queue(dev);
+ netif_wake_queue(dev);
+ spin_lock_irqsave(&priv->lock, priv->lockflags);
+
//while(eth_inb(0x3a)&0x1);
// TX Fifo Page to 0
+
eth_outb(0xf, 0);
eth_outb(0xe, 0);
-
+
//printk("XMIT packet : len %d\n",skb->len);
/*
We send using the FIFO mode
@@ -516,13 +570,16 @@
BBA_DBG("gc_bba_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages);
// We set the packetbuffer to beginning...
-
+
+ eth_outb(0x3e, skb->len&0xff);
+ eth_outb(0x3f, (skb->len&0x0f00)>>8);
+
unsigned int val=0xC0004800; // register 0x48 is the output queue
exi_select(0, 2, 5);
exi_imm(0, &val, 4, EXI_WRITE, 0);
exi_sync(0);
-
+
// Send Data from skb buffer to Network Driver now
exi_imm_ex(0, skb->data, skb->len, EXI_WRITE);
@@ -544,13 +601,13 @@
val |=4;
eth_outb(0, val);
-
spin_unlock_irqrestore(&priv->lock, priv->lockflags);
+
dev->trans_start = jiffies;
- dev_kfree_skb(skb);
-
- priv->stats.tx_bytes++;
+ priv->stats.tx_bytes += skb->len;
priv->stats.tx_packets++;
+
+ dev_kfree_skb(skb);
return 0;
}
@@ -570,7 +627,7 @@
/*
Input Flow concept: Take a look to Hardware spec page 35
*/
-
+/*
eth_outb(0x3a, 2);
if (eth_inb(0x3a) & 2)
{
@@ -578,7 +635,7 @@
priv->stats.rx_missed_errors++;
return ;
}
-
+*/
/*
Receive Buffer Write Page Pointer: Current receive write page pointer. The MSB
is the Reg17h.3 bit. The LSB is the Reg16h.0 bit. This register is controlled by
@@ -597,7 +654,6 @@
p_read = eth_inb(0x18);
p_read |= (eth_inb(0x19)&0x0f) << 8;
-
if (p_read == p_write) return;
//printk("Received a packet .. (start)\n");
@@ -686,13 +742,22 @@
dev->last_rx = jiffies;
priv->stats.rx_packets ++; /* count all receives */
- priv->stats.rx_bytes ++; /* count all received bytes */
+ priv->stats.rx_bytes += skb->len; /* count all received bytes */
gc_input(dev);
return ;
}
+#define BBA_IRQ_FRAGI 0x01
+#define BBA_IRQ_RI 0x02
+#define BBA_IRQ_TI 0x04
+#define BBA_IRQ_REI 0x08
+#define BBA_IRQ_TEI 0x10
+#define BBA_IRQ_FIFOEI 0x20
+#define BBA_IRQ_BUSEI 0x40
+#define BBA_IRQ_RBFI 0x80
+
static void inline gcif_service(struct net_device *dev)
{
@@ -705,61 +770,73 @@
int status = inb9 & inb8;
BBA_DBG("gcif_service: %08x %08x status %08x\n", inb8, inb9, status);
-
+
if (!status) {
eth_outb(9, 0xff);
BBA_DBG("?? GC irq but no irq ??\n");
}
-
- if (status & 4)
+
+ if (status & BBA_IRQ_FRAGI) // 0x1
{
- eth_outb(9, 4);
- // We clear the IRQ
- netif_wake_queue(dev); /* allow more packets into adapter */
-
-
- // TX Transmisstion compleated ...
-
- /*
- int s = eth_inb(4);
- if (s) // should not occur, since 4 == TX OK
- BBA_DBG("tx error %02x\n", s);
- */
+ eth_outb(9, BBA_IRQ_FRAGI);
+ BBA_DBG("Fragmentet Interrupt\n");
}
- if (status & 2)
+ if (status & BBA_IRQ_RI) // 0x2
{
// We clear the IRQ
- eth_outb(9, 2);
+ eth_outb(9, BBA_IRQ_RI);
spin_lock_irqsave(&priv->lock, priv->lockflags);
gc_input(dev);
spin_unlock_irqrestore(&priv->lock, priv->lockflags);
}
+
+ if (status & BBA_IRQ_TI) // 0x4
+ {
+ eth_outb(9, BBA_IRQ_TI);
+ // We clear the IRQ
+ netif_wake_queue(dev); /* allow more packets into adapter */
+ priv->tx_lock = 0;
+ // TX Transmisstion compleated ...
+ }
- if (status & 8)
+ if (status & BBA_IRQ_REI) // 0x8
{
- eth_outb(9, 8);
- //printk("receive error :(\n");
+ eth_outb(9, BBA_IRQ_REI);
+ BBA_DBG("receive error :(\n");
+ priv->stats.rx_frame_errors++;
}
- if (status & 0x10)
+ if (status & BBA_IRQ_TEI) // 0x10
{
- eth_outb(9, 0x10);
+ eth_outb(9, BBA_IRQ_TEI);
netif_wake_queue(dev); /* allow more packets into adapter */
- //printk("tx error\n");
+ priv->tx_lock = 0;
+ BBA_DBG("tx error\n");
+ priv->stats.tx_errors++;
}
- if (status & 0x20)
+
+ if (status & BBA_IRQ_FIFOEI) // 0x20
{
- eth_outb(9, 0x20);
- BBA_DBG("rx fifo error\n");
+ eth_outb(9, BBA_IRQ_FIFOEI);
+ BBA_DBG("rx/tx fifo error\n");
+ adapter_init(dev);
+ priv->stats.rx_errors++;
}
- if (status & 0x80)
+
+ if (status & BBA_IRQ_BUSEI) // 0x40
{
- eth_outb(9, 0x80);
- //printk("rx overflow!\n");
- gc_input(dev);
-
+ eth_outb(9, BBA_IRQ_BUSEI);
+ BBA_DBG("Bus Error\n");
+ }
+
+ if (status & BBA_IRQ_RBFI) // 0x80
+ {
+ eth_outb(9, BBA_IRQ_RBFI);
+ BBA_DBG("rx overflow!\n");
+ //gc_input(dev);
+ priv->stats.rx_over_errors++;
// RWP
eth_outb(0x16, GBA_RX_RWP);
eth_outb(0x17, 0x0);
@@ -771,16 +848,9 @@
// RHBP
eth_outb(0x1a, GBA_RX_RHBP);
eth_outb(0x1b, 0);
-
-
- }
- if (status & ~(0xBE))
- {
- eth_outb(9, status & ~0xBE);
- BBA_DBG("status %02x\n", status & ~0xBE);
}
-// eth_outb(9, status);
+
}
@@ -795,8 +865,6 @@
struct net_device *dev = (struct net_device *)dev_id;
struct gc_private *priv = (struct gc_private *)dev->priv;
- int retrig = 0;
-
/* This might just as well be deleted now, no crummy drivers present :-) */
if ((dev == NULL) || (dev->irq != irq)) {
BBA_DBG(KERN_ERR "%s: bogus interrupt %d\n", dev?dev->name:"GC_BBA", irq);
@@ -820,9 +888,6 @@
have_irq(ch * 3 + EXI_EVENT_IRQ);
}
- if (retrig)
- trigger_interrupt(dev);
-
spin_unlock(&priv->lock);
return IRQ_HANDLED;
@@ -958,7 +1023,7 @@
BBA_DBG("initializing BBA...\n");
-
+ priv->tx_lock = 0;
eth_outb(0x60, 0); // unknown
udelay(10000);
@@ -982,7 +1047,7 @@
eth_outb(1, 0x10|PACKETS_PER_IRQ | BBA_PROMISC);
eth_outb(0x14, 0x0);
- eth_outb(0x15, 0x8);
+ eth_outb(0x15, 0x6);
eth_outb(0x50, 0x80);
@@ -1037,7 +1102,7 @@
eth_outb(8, 0xFF); // enable all IRQs
eth_outb(9, 0xFF); // clear all irqs
- //eth_outb(0x30, 0x2); // 100 Mbit ?
+ //eth_outb(0x30, 0x2); // 100 Mbit ? -- FATAL , IF speed so high, EXI totally overloaded
BBA_DBG("after all: irq mask %x %x\n", eth_inb(8), eth_inb(9));
@@ -1077,24 +1142,22 @@
eth_exi_outb(2, 0);
s = eth_exi_inb(3);
- if (s & 0x80)
+ if (s & 0x08)
{
-// BBA_DBG("GC_IRQ service.\n");
- eth_exi_outb(3, 0x80);
- gcif_service(dev);
+ BBA_DBG("GCIF - EXI - HASH function\n");
+ eth_exi_outb(3, 0x08);
eth_exi_outb(2, 0xF8);
return;
}
- if (s & 0x40)
+
+ if (s & 0x10)
{
- eth_exi_outb(3, 0x40);
+ BBA_DBG("GCIF - EXI - patchtru!\n");
+ eth_exi_outb(3, 0x10);
eth_exi_outb(2, 0xF8);
-// BBA_DBG("GCIF - EXI - 0x40!\n");
- adapter_init(dev);
return;
-
-// return;
}
+
if (s & 0x20)
{
BBA_DBG("GCIF - EXI - CMDERR!\n");
@@ -1102,20 +1165,25 @@
eth_exi_outb(2, 0xF8);
return;
}
- if (s & 0x10)
+
+ if (s & 0x40)
{
- BBA_DBG("GCIF - EXI - patchtru!\n");
- eth_exi_outb(3, 0x10);
+ eth_exi_outb(3, 0x40);
eth_exi_outb(2, 0xF8);
+ BBA_DBG("GCIF - EXI - 0x40!\n");
+ adapter_init(dev);
return;
- }
- if (s & 0x08)
+ }
+
+ if (s & 0x80)
{
- BBA_DBG("GCIF - EXI - HASH function\n");
- eth_exi_outb(3, 0x08);
+ BBA_DBG("GC_IRQ service.\n");
+ eth_exi_outb(3, 0x80);
+ gcif_service(dev);
eth_exi_outb(2, 0xF8);
return;
}
+
// printk("GCIF - EXI - ?? %02x\n", s);
eth_exi_outb(2, 0xF8);
}
|