Commit baf8f9bb authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] Update lp486e for 2.5

parent def3ac70
...@@ -56,7 +56,7 @@ PORT SIZE ACTION MEANING ...@@ -56,7 +56,7 @@ PORT SIZE ACTION MEANING
All other communication is through memory! All other communication is through memory!
*/ */
#define SLOW_DOWN_IO udelay(5); #define SLOW_DOWN_IO udelay(5)
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -195,7 +195,7 @@ i596_out_status(int status) { ...@@ -195,7 +195,7 @@ i596_out_status(int status) {
typedef u32 phys_addr; typedef u32 phys_addr;
static inline phys_addr static inline phys_addr
va_to_pa(volatile void *x) { va_to_pa(void *x) {
return x ? virt_to_bus(x) : I596_NULL; return x ? virt_to_bus(x) : I596_NULL;
} }
...@@ -341,14 +341,15 @@ struct i596_private { /* aligned to a 16-byte boundary */ ...@@ -341,14 +341,15 @@ struct i596_private { /* aligned to a 16-byte boundary */
unsigned long tdr_stat; /* directly follows tdr */ unsigned long tdr_stat; /* directly follows tdr */
int last_restart; int last_restart;
volatile struct i596_rbd *rbd_list; struct i596_rbd *rbd_list;
volatile struct i596_rbd *rbd_tail; struct i596_rbd *rbd_tail;
volatile struct i596_rfd *rx_tail; struct i596_rfd *rx_tail;
volatile struct i596_cmd *cmd_tail; struct i596_cmd *cmd_tail;
volatile struct i596_cmd *cmd_head; struct i596_cmd *cmd_head;
int cmd_backlog; int cmd_backlog;
unsigned long last_cmd; unsigned long last_cmd;
struct net_device_stats stats; struct net_device_stats stats;
spinlock_t cmd_lock;
}; };
static char init_setup[14] = { static char init_setup[14] = {
...@@ -386,7 +387,7 @@ static void i596_tx_timeout(struct net_device *dev); ...@@ -386,7 +387,7 @@ static void i596_tx_timeout(struct net_device *dev);
static int static int
i596_timeout(struct net_device *dev, char *msg, int ct) { i596_timeout(struct net_device *dev, char *msg, int ct) {
volatile struct i596_private *lp; struct i596_private *lp;
int boguscnt = ct; int boguscnt = ct;
lp = (struct i596_private *) dev->priv; lp = (struct i596_private *) dev->priv;
...@@ -398,13 +399,14 @@ i596_timeout(struct net_device *dev, char *msg, int ct) { ...@@ -398,13 +399,14 @@ i596_timeout(struct net_device *dev, char *msg, int ct) {
return 1; return 1;
} }
udelay(5); udelay(5);
barrier();
} }
return 0; return 0;
} }
static inline int static inline int
init_rx_bufs(struct net_device *dev, int num) { init_rx_bufs(struct net_device *dev, int num) {
volatile struct i596_private *lp; struct i596_private *lp;
struct i596_rfd *rfd; struct i596_rfd *rfd;
int i; int i;
// struct i596_rbd *rbd; // struct i596_rbd *rbd;
...@@ -517,8 +519,8 @@ CLEAR_INT(void) { ...@@ -517,8 +519,8 @@ CLEAR_INT(void) {
/* selftest or dump */ /* selftest or dump */
static void static void
i596_port_do(struct net_device *dev, int portcmd, char *cmdname) { i596_port_do(struct net_device *dev, int portcmd, char *cmdname) {
volatile struct i596_private *lp = dev->priv; struct i596_private *lp = dev->priv;
volatile u16 *outp; u16 *outp;
int i, m; int i, m;
memset((void *)&(lp->dump), 0, sizeof(struct i596_dump)); memset((void *)&(lp->dump), 0, sizeof(struct i596_dump));
...@@ -541,7 +543,7 @@ i596_port_do(struct net_device *dev, int portcmd, char *cmdname) { ...@@ -541,7 +543,7 @@ i596_port_do(struct net_device *dev, int portcmd, char *cmdname) {
static int static int
i596_scp_setup(struct net_device *dev) { i596_scp_setup(struct net_device *dev) {
volatile struct i596_private *lp = dev->priv; struct i596_private *lp = dev->priv;
int boguscnt; int boguscnt;
/* Setup SCP, ISCP, SCB */ /* Setup SCP, ISCP, SCB */
...@@ -608,6 +610,7 @@ i596_scp_setup(struct net_device *dev) { ...@@ -608,6 +610,7 @@ i596_scp_setup(struct net_device *dev) {
return 1; return 1;
} }
udelay(5); udelay(5);
barrier();
} }
/* I find here boguscnt==100, so no delay was required. */ /* I find here boguscnt==100, so no delay was required. */
...@@ -616,7 +619,7 @@ i596_scp_setup(struct net_device *dev) { ...@@ -616,7 +619,7 @@ i596_scp_setup(struct net_device *dev) {
static int static int
init_i596(struct net_device *dev) { init_i596(struct net_device *dev) {
volatile struct i596_private *lp; struct i596_private *lp;
if (i596_scp_setup(dev)) if (i596_scp_setup(dev))
return 1; return 1;
...@@ -641,6 +644,8 @@ init_i596(struct net_device *dev) { ...@@ -641,6 +644,8 @@ init_i596(struct net_device *dev) {
lp->scb.command = RX_START; lp->scb.command = RX_START;
CA(); CA();
barrier();
if (lp->scb.command && i596_timeout(dev, "Receive Unit start", 100)) if (lp->scb.command && i596_timeout(dev, "Receive Unit start", 100))
return 1; return 1;
...@@ -649,7 +654,7 @@ init_i596(struct net_device *dev) { ...@@ -649,7 +654,7 @@ init_i596(struct net_device *dev) {
/* Receive a single frame */ /* Receive a single frame */
static inline int static inline int
i596_rx_one(struct net_device *dev, volatile struct i596_private *lp, i596_rx_one(struct net_device *dev, struct i596_private *lp,
struct i596_rfd *rfd, int *frames) { struct i596_rfd *rfd, int *frames) {
if (rfd->stat & RFD_STAT_OK) { if (rfd->stat & RFD_STAT_OK) {
...@@ -703,14 +708,14 @@ i596_rx_one(struct net_device *dev, volatile struct i596_private *lp, ...@@ -703,14 +708,14 @@ i596_rx_one(struct net_device *dev, volatile struct i596_private *lp,
static int static int
i596_rx(struct net_device *dev) { i596_rx(struct net_device *dev) {
volatile struct i596_private *lp = (struct i596_private *) dev->priv; struct i596_private *lp = (struct i596_private *) dev->priv;
struct i596_rfd *rfd; struct i596_rfd *rfd;
int frames = 0; int frames = 0;
while (1) { while (1) {
rfd = pa_to_va(lp->scb.pa_rfd); rfd = pa_to_va(lp->scb.pa_rfd);
if (!rfd) { if (!rfd) {
printk("i596_rx: NULL rfd?\n"); printk(KERN_ERR "i596_rx: NULL rfd?\n");
return 0; return 0;
} }
#if 1 #if 1
...@@ -725,6 +730,7 @@ i596_rx(struct net_device *dev) { ...@@ -725,6 +730,7 @@ i596_rx(struct net_device *dev) {
lp->rx_tail->cmd = 0; lp->rx_tail->cmd = 0;
lp->rx_tail = rfd; lp->rx_tail = rfd;
lp->scb.pa_rfd = rfd->pa_next; lp->scb.pa_rfd = rfd->pa_next;
barrier();
} }
return frames; return frames;
...@@ -732,7 +738,7 @@ i596_rx(struct net_device *dev) { ...@@ -732,7 +738,7 @@ i596_rx(struct net_device *dev) {
static void static void
i596_cleanup_cmd(struct net_device *dev) { i596_cleanup_cmd(struct net_device *dev) {
volatile struct i596_private *lp; struct i596_private *lp;
struct i596_cmd *cmd; struct i596_cmd *cmd;
lp = (struct i596_private *) dev->priv; lp = (struct i596_private *) dev->priv;
...@@ -770,6 +776,7 @@ i596_cleanup_cmd(struct net_device *dev) { ...@@ -770,6 +776,7 @@ i596_cleanup_cmd(struct net_device *dev) {
break; break;
} }
} }
barrier();
} }
if (lp->scb.command && i596_timeout(dev, "i596_cleanup_cmd", 100)) if (lp->scb.command && i596_timeout(dev, "i596_cleanup_cmd", 100))
...@@ -778,9 +785,7 @@ i596_cleanup_cmd(struct net_device *dev) { ...@@ -778,9 +785,7 @@ i596_cleanup_cmd(struct net_device *dev) {
lp->scb.pa_cmd = va_to_pa(lp->cmd_head); lp->scb.pa_cmd = va_to_pa(lp->cmd_head);
} }
static inline void static void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr) {
i596_reset(struct net_device *dev,
volatile struct i596_private *lp, int ioaddr) {
if (lp->scb.command && i596_timeout(dev, "i596_reset", 100)) if (lp->scb.command && i596_timeout(dev, "i596_reset", 100))
; ;
...@@ -789,6 +794,7 @@ i596_reset(struct net_device *dev, ...@@ -789,6 +794,7 @@ i596_reset(struct net_device *dev,
lp->scb.command = CUC_ABORT | RX_ABORT; lp->scb.command = CUC_ABORT | RX_ABORT;
CA(); CA();
barrier();
/* wait for shutdown */ /* wait for shutdown */
if (lp->scb.command && i596_timeout(dev, "i596_reset(2)", 400)) if (lp->scb.command && i596_timeout(dev, "i596_reset(2)", 400))
...@@ -803,7 +809,7 @@ i596_reset(struct net_device *dev, ...@@ -803,7 +809,7 @@ i596_reset(struct net_device *dev,
} }
static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) { static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) {
volatile struct i596_private *lp = dev->priv; struct i596_private *lp = dev->priv;
int ioaddr = dev->base_addr; int ioaddr = dev->base_addr;
unsigned long flags; unsigned long flags;
...@@ -811,8 +817,8 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) { ...@@ -811,8 +817,8 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) {
cmd->command |= (CMD_EOL | CMD_INTR); cmd->command |= (CMD_EOL | CMD_INTR);
cmd->pa_next = I596_NULL; cmd->pa_next = I596_NULL;
save_flags(flags); spin_lock_irqsave(&lp->cmd_lock, flags);
cli();
if (lp->cmd_head) { if (lp->cmd_head) {
lp->cmd_tail->pa_next = va_to_pa(cmd); lp->cmd_tail->pa_next = va_to_pa(cmd);
} else { } else {
...@@ -827,64 +833,45 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) { ...@@ -827,64 +833,45 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) {
lp->cmd_backlog++; lp->cmd_backlog++;
lp->cmd_head = pa_to_va(lp->scb.pa_cmd); lp->cmd_head = pa_to_va(lp->scb.pa_cmd);
restore_flags(flags); spin_unlock_irqrestore(&lp->cmd_lock, flags);
if (lp->cmd_backlog > 16) { if (lp->cmd_backlog > 16) {
int tickssofar = jiffies - lp->last_cmd; int tickssofar = jiffies - lp->last_cmd;
if (tickssofar < 25) return; if (tickssofar < HZ/4)
return;
printk("%s: command unit timed out, status resetting.\n", printk(KERN_WARNING "%s: command unit timed out, status resetting.\n", dev->name);
dev->name);
i596_reset(dev, lp, ioaddr); i596_reset(dev, lp, ioaddr);
} }
} }
static int static int i596_open(struct net_device *dev)
i596_open(struct net_device *dev) { {
int i; int i;
i = request_irq(dev->irq, &i596_interrupt, SA_SHIRQ, dev->name, dev); i = request_irq(dev->irq, &i596_interrupt, SA_SHIRQ, dev->name, dev);
if (i) { if (i) {
printk("%s: IRQ %d not free\n", dev->name, dev->irq); printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
return i; return i;
} }
if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE) if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE)
printk("%s: only able to allocate %d receive buffers\n", printk(KERN_ERR "%s: only able to allocate %d receive buffers\n", dev->name, i);
dev->name, i);
if (i < 4) { if (i < 4) {
// release buffers
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
return -EAGAIN; return -EAGAIN;
} }
netif_start_queue(dev); netif_start_queue(dev);
init_i596(dev); init_i596(dev);
return 0; /* Always succeed */ return 0; /* Always succeed */
} }
static int static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
i596_start_xmit (struct sk_buff *skb, struct net_device *dev) { struct i596_private *lp = dev->priv;
volatile struct i596_private *lp = dev->priv;
struct tx_cmd *tx_cmd; struct tx_cmd *tx_cmd;
short length; short length;
/* If some higher level thinks we've missed a tx-done interrupt
we are passed NULL. n.b. dev_tint handles the cli()/sti()
itself. */
if (skb == NULL) {
printk ("What about dev_tint\n");
/* dev_tint(dev); */
return 0;
}
/* shouldn't happen */
if (skb->len <= 0)
return 0;
length = skb->len; length = skb->len;
if (length < ETH_ZLEN) { if (length < ETH_ZLEN) {
...@@ -896,14 +883,10 @@ i596_start_xmit (struct sk_buff *skb, struct net_device *dev) { ...@@ -896,14 +883,10 @@ i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
dev->trans_start = jiffies; dev->trans_start = jiffies;
tx_cmd = (struct tx_cmd *) tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
kmalloc ((sizeof (struct tx_cmd)
+ sizeof (struct i596_tbd)), GFP_ATOMIC);
if (tx_cmd == NULL) { if (tx_cmd == NULL) {
printk ("%s: i596_xmit Memory squeeze, dropping packet.\n", printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
dev->name);
lp->stats.tx_dropped++; lp->stats.tx_dropped++;
dev_kfree_skb (skb); dev_kfree_skb (skb);
} else { } else {
struct i596_tbd *tx_cmd_tbd; struct i596_tbd *tx_cmd_tbd;
...@@ -934,11 +917,11 @@ i596_start_xmit (struct sk_buff *skb, struct net_device *dev) { ...@@ -934,11 +917,11 @@ i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
static void static void
i596_tx_timeout (struct net_device *dev) { i596_tx_timeout (struct net_device *dev) {
volatile struct i596_private *lp = dev->priv; struct i596_private *lp = dev->priv;
int ioaddr = dev->base_addr; int ioaddr = dev->base_addr;
/* Transmitter timeout, serious problems. */ /* Transmitter timeout, serious problems. */
printk ("%s: transmit timed out, status resetting.\n", dev->name); printk(KERN_WARNING "%s: transmit timed out, status resetting.\n", dev->name);
lp->stats.tx_errors++; lp->stats.tx_errors++;
/* Try to restart the adaptor */ /* Try to restart the adaptor */
...@@ -957,8 +940,8 @@ i596_tx_timeout (struct net_device *dev) { ...@@ -957,8 +940,8 @@ i596_tx_timeout (struct net_device *dev) {
netif_wake_queue(dev); netif_wake_queue(dev);
} }
static void static void print_eth(char *add)
print_eth(char *add) { {
int i; int i;
printk ("Dest "); printk ("Dest ");
...@@ -975,9 +958,8 @@ print_eth(char *add) { ...@@ -975,9 +958,8 @@ print_eth(char *add) {
(unsigned char) add[12], (unsigned char) add[13]); (unsigned char) add[12], (unsigned char) add[13]);
} }
int __init int __init lp486e_probe(struct net_device *dev) {
lp486e_probe(struct net_device *dev) { struct i596_private *lp;
volatile struct i596_private *lp;
unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 }; unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 };
unsigned char *bios; unsigned char *bios;
int i, j; int i, j;
...@@ -996,13 +978,13 @@ lp486e_probe(struct net_device *dev) { ...@@ -996,13 +978,13 @@ lp486e_probe(struct net_device *dev) {
/* /*
* Allocate working memory, 16-byte aligned * Allocate working memory, 16-byte aligned
*/ */
dev->mem_start = (unsigned long) dev->mem_start = (unsigned long) kmalloc(sizeof(struct i596_private) + 0x0f, GFP_KERNEL);
kmalloc(sizeof(struct i596_private) + 0x0f, GFP_KERNEL);
if (!dev->mem_start) if (!dev->mem_start)
goto err_out; goto err_out;
dev->priv = (void *)((dev->mem_start + 0xf) & 0xfffffff0); dev->priv = (void *)((dev->mem_start + 0xf) & 0xfffffff0);
lp = (struct i596_private *) dev->priv; lp = (struct i596_private *) dev->priv;
memset((void *)lp, 0, sizeof(struct i596_private)); memset((void *)lp, 0, sizeof(struct i596_private));
spin_lock_init(&lp->cmd_lock);
/* /*
* Do we really have this thing? * Do we really have this thing?
...@@ -1071,14 +1053,16 @@ lp486e_probe(struct net_device *dev) { ...@@ -1071,14 +1053,16 @@ lp486e_probe(struct net_device *dev) {
static inline void static inline void
i596_handle_CU_completion(struct net_device *dev, i596_handle_CU_completion(struct net_device *dev,
volatile struct i596_private *lp, struct i596_private *lp,
unsigned short status, unsigned short status,
unsigned short *ack_cmdp) { unsigned short *ack_cmdp) {
volatile struct i596_cmd *cmd; struct i596_cmd *cmd;
int frames_out = 0; int frames_out = 0;
int commands_done = 0; int commands_done = 0;
int cmd_val; int cmd_val;
unsigned long flags;
spin_lock_irqsave(&lp->cmd_lock, flags);
cmd = lp->cmd_head; cmd = lp->cmd_head;
while (lp->cmd_head && (lp->cmd_head->status & CMD_STAT_C)) { while (lp->cmd_head && (lp->cmd_head->status & CMD_STAT_C)) {
...@@ -1160,31 +1144,29 @@ i596_handle_CU_completion(struct net_device *dev, ...@@ -1160,31 +1144,29 @@ i596_handle_CU_completion(struct net_device *dev,
lp->last_cmd = jiffies; lp->last_cmd = jiffies;
} }
barrier();
} }
cmd = lp->cmd_head; cmd = lp->cmd_head;
while (cmd && (cmd != lp->cmd_tail)) { while (cmd && (cmd != lp->cmd_tail)) {
cmd->command &= 0x1fff; cmd->command &= 0x1fff;
cmd = pa_to_va(cmd->pa_next); cmd = pa_to_va(cmd->pa_next);
barrier();
} }
if (lp->cmd_head) if (lp->cmd_head)
*ack_cmdp |= CUC_START; *ack_cmdp |= CUC_START;
lp->scb.pa_cmd = va_to_pa(lp->cmd_head); lp->scb.pa_cmd = va_to_pa(lp->cmd_head);
spin_unlock_irqrestore(&lp->cmd_lock, flags);
} }
static void static void
i596_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { i596_interrupt (int irq, void *dev_instance, struct pt_regs *regs) {
struct net_device *dev = (struct net_device *) dev_instance; struct net_device *dev = (struct net_device *) dev_instance;
volatile struct i596_private *lp; struct i596_private *lp;
unsigned short status, ack_cmd = 0; unsigned short status, ack_cmd = 0;
int frames_in = 0; int frames_in = 0;
if (dev == NULL) {
printk ("i596_interrupt(): irq %d for unknown device.\n", irq);
return;
}
lp = (struct i596_private *) dev->priv; lp = (struct i596_private *) dev->priv;
/* /*
...@@ -1251,7 +1233,7 @@ i596_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { ...@@ -1251,7 +1233,7 @@ i596_interrupt (int irq, void *dev_instance, struct pt_regs *regs) {
} }
static int i596_close(struct net_device *dev) { static int i596_close(struct net_device *dev) {
volatile struct i596_private *lp = dev->priv; struct i596_private *lp = dev->priv;
netif_stop_queue(dev); netif_stop_queue(dev);
...@@ -1284,7 +1266,7 @@ static struct net_device_stats * i596_get_stats(struct net_device *dev) { ...@@ -1284,7 +1266,7 @@ static struct net_device_stats * i596_get_stats(struct net_device *dev) {
*/ */
static void set_multicast_list(struct net_device *dev) { static void set_multicast_list(struct net_device *dev) {
volatile struct i596_private *lp = dev->priv; struct i596_private *lp = dev->priv;
struct i596_cmd *cmd; struct i596_cmd *cmd;
if (i596_debug > 1) if (i596_debug > 1)
...@@ -1294,12 +1276,9 @@ static void set_multicast_list(struct net_device *dev) { ...@@ -1294,12 +1276,9 @@ static void set_multicast_list(struct net_device *dev) {
if (dev->mc_count > 0) { if (dev->mc_count > 0) {
struct dev_mc_list *dmi; struct dev_mc_list *dmi;
char *cp; char *cp;
cmd = (struct i596_cmd *) cmd = (struct i596_cmd *)kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6,
GFP_ATOMIC);
if (cmd == NULL) { if (cmd == NULL) {
printk ("%s: set_multicast Memory squeeze.\n", printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name);
dev->name);
return; return;
} }
cmd->command = CmdMulticastList; cmd->command = CmdMulticastList;
...@@ -1316,8 +1295,7 @@ static void set_multicast_list(struct net_device *dev) { ...@@ -1316,8 +1295,7 @@ static void set_multicast_list(struct net_device *dev) {
if (lp->set_conf.pa_next != I596_NULL) { if (lp->set_conf.pa_next != I596_NULL) {
return; return;
} }
if (dev->mc_count == 0 && if (dev->mc_count == 0 && !(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
if (dev->flags & IFF_ALLMULTI) if (dev->flags & IFF_ALLMULTI)
dev->flags |= IFF_PROMISC; dev->flags |= IFF_PROMISC;
lp->i596_config[8] &= ~0x01; lp->i596_config[8] &= ~0x01;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment