]> git.neil.brown.name Git - history.git/commitdiff
Bug fixes for Acorn network drivers.
authorRussell King <rmk@flint.arm.linux.org.uk>
Mon, 11 Mar 2002 15:57:00 +0000 (15:57 +0000)
committerRussell King <rmk@flint.arm.linux.org.uk>
Mon, 11 Mar 2002 15:57:00 +0000 (15:57 +0000)
drivers/acorn/net/ether3.c
drivers/acorn/net/etherh.c

index 196be921aec321a3a606fce031c01461092917d6..4f5dac26ad4dd083831de54f61f9d79d8d87b24d 100644 (file)
@@ -718,7 +718,7 @@ dropping:{
        /*
         * Don't print this message too many times...
         */
-       if (jiffies - last_warned > 30 * HZ) {
+       if (time_after(jiffies, last_warned + 10 * HZ)) {
                last_warned = jiffies;
                printk("%s: memory squeeze, dropping packet.\n", dev->name);
        }
index e91296836305b8b4eaac08f58d3a77a35be1284f..54b847ec7df41244d07a8d821cff2a4d9ed8618f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/acorn/net/etherh.c
  *
- *  Copyright (C) 2000 Russell King
+ *  Copyright (C) 2000-2002 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -23,6 +23,7 @@
  *  12-10-1999  CK/TEW         EtherM driver first release
  *  21-12-2000 TTC             EtherH/EtherM integration
  *  25-12-2000 RMK     1.08    Clean integration of EtherM into this driver.
+ *  03-01-2002 RMK     1.09    Always enable IRQs if we're in the nic slot.
  */
 
 #include <linux/module.h>
@@ -64,13 +65,18 @@ static const card_ids __init etherh_cids[] = {
        { 0xffff,   0xffff }
 };
 
+struct etherh_priv {
+       unsigned int    id;
+       unsigned int    ctrl_port;
+       unsigned int    ctrl;
+};
 
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("EtherH/EtherM driver");
 MODULE_LICENSE("GPL");
 
 static char version[] __initdata =
-       "EtherH/EtherM Driver (c) 2000 Russell King v1.08\n";
+       "EtherH/EtherM Driver (c) 2002 Russell King v1.09\n";
 
 #define ETHERH500_DATAPORT     0x200   /* MEMC */
 #define ETHERH500_NS8390       0x000   /* MEMC */
@@ -97,18 +103,61 @@ static char version[] __initdata =
 #define ETHERM_TX_START_PAGE   64
 #define ETHERM_STOP_PAGE       127
 
-/* --------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------ */
+
+static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask)
+{
+       eh->ctrl |= mask;
+       outb(eh->ctrl, eh->ctrl_port);
+}
+
+static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask)
+{
+       eh->ctrl &= ~mask;
+       outb(eh->ctrl, eh->ctrl_port);
+}
+
+static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
+{
+       return inb(eh->ctrl_port);
+}
+
+
+
+
+static void etherh_irq_enable(ecard_t *ec, int irqnr)
+{
+       struct etherh_priv *eh = ec->irq_data;
+
+       etherh_set_ctrl(eh, ETHERH_CP_IE);
+}
+
+static void etherh_irq_disable(ecard_t *ec, int irqnr)
+{
+       struct etherh_priv *eh = ec->irq_data;
+
+       etherh_clr_ctrl(eh, ETHERH_CP_IE);
+}
+
+static expansioncard_ops_t etherh_ops = {
+       irqenable:      etherh_irq_enable,
+       irqdisable:     etherh_irq_disable,
+};
+
+
+
 
 static void
 etherh_setif(struct net_device *dev)
 {
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
+       struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
        unsigned long addr, flags;
 
-       save_flags_cli(flags);
+       local_irq_save(flags);
 
        /* set the interface type */
-       switch (dev->mem_end) {
+       switch (eh->id) {
        case PROD_I3_ETHERLAN600:
        case PROD_I3_ETHERLAN600A:
                addr = dev->base_addr + EN0_RCNTHI;
@@ -124,14 +173,13 @@ etherh_setif(struct net_device *dev)
                break;
 
        case PROD_I3_ETHERLAN500:
-               addr = dev->rmem_start;
-
                switch (dev->if_port) {
                case IF_PORT_10BASE2:
-                       outb(inb(addr) & ~ETHERH_CP_IF, addr);
+                       etherh_clr_ctrl(eh, ETHERH_CP_IF);
                        break;
+
                case IF_PORT_10BASET:
-                       outb(inb(addr) | ETHERH_CP_IF, addr);
+                       etherh_set_ctrl(eh, ETHERH_CP_IF);
                        break;
                }
                break;
@@ -140,16 +188,17 @@ etherh_setif(struct net_device *dev)
                break;
        }
 
-       restore_flags(flags);
+       local_irq_restore(flags);
 }
 
 static int
 etherh_getifstat(struct net_device *dev)
 {
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
+       struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
        int stat = 0;
 
-       switch (dev->mem_end) {
+       switch (eh->id) {
        case PROD_I3_ETHERLAN600:
        case PROD_I3_ETHERLAN600A:
                switch (dev->if_port) {
@@ -168,7 +217,7 @@ etherh_getifstat(struct net_device *dev)
                        stat = 1;
                        break;
                case IF_PORT_10BASET:
-                       stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT;
+                       stat = etherh_get_stat(eh) & ETHERH_CP_HEARTBEAT;
                        break;
                }
                break;
@@ -251,7 +300,13 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
                return;
        }
 
-       ei_local->dmaing |= 1;
+       /*
+        * Make sure we have a round number of bytes if we're in word mode.
+        */
+       if (count & 1 && ei_local->word16)
+               count++;
+
+       ei_local->dmaing = 1;
 
        addr = dev->base_addr;
        dma_addr = dev->mem_start;
@@ -291,7 +346,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
                }
 
        outb (ENISR_RDC, addr + EN0_ISR);
-       ei_local->dmaing &= ~1;
+       ei_local->dmaing = 0;
 }
 
 /*
@@ -311,7 +366,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
                return;
        }
 
-       ei_local->dmaing |= 1;
+       ei_local->dmaing = 1;
 
        addr = dev->base_addr;
        dma_addr = dev->mem_start;
@@ -332,7 +387,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
                insb (dma_addr, buf, count);
 
        outb (ENISR_RDC, addr + EN0_ISR);
-       ei_local->dmaing &= ~1;
+       ei_local->dmaing = 0;
 }
 
 /*
@@ -351,7 +406,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
                return;
        }
 
-       ei_local->dmaing |= 1;
+       ei_local->dmaing = 1;
 
        addr = dev->base_addr;
        dma_addr = dev->mem_start;
@@ -369,7 +424,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
                insb (dma_addr, hdr, sizeof (*hdr));
 
        outb (ENISR_RDC, addr + EN0_ISR);
-       ei_local->dmaing &= ~1;
+       ei_local->dmaing = 0;
 }
 
 /*
@@ -427,23 +482,6 @@ etherh_close(struct net_device *dev)
        return 0;
 }
 
-static void etherh_irq_enable(ecard_t *ec, int irqnr)
-{
-       unsigned int ctrl_addr = (unsigned int)ec->irq_data;
-       outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr);
-}
-
-static void etherh_irq_disable(ecard_t *ec, int irqnr)
-{
-       unsigned int ctrl_addr = (unsigned int)ec->irq_data;
-       outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr);
-}
-
-static expansioncard_ops_t etherh_ops = {
-       irqenable:      etherh_irq_enable,
-       irqdisable:     etherh_irq_disable,
-};
-
 /*
  * Initialisation
  */
@@ -506,6 +544,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
 {
        struct ei_device *ei_local;
        struct net_device *dev;
+       struct etherh_priv *eh;
        const char *dev_type;
        int i, size;
 
@@ -517,6 +556,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
        if (!dev)
                goto out;
 
+       eh = kmalloc(sizeof(struct etherh_priv), GFP_KERNEL);
+       if (!eh)
+               goto out_nopriv;
+
        SET_MODULE_OWNER(dev);
 
        dev->open       = etherh_open;
@@ -524,8 +567,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
        dev->set_config = etherh_set_config;
        dev->irq        = ec->irq;
        dev->base_addr  = ecard_address(ec, ECARD_MEMC, 0);
-       dev->mem_end    = ec->cid.product;
+       dev->rmem_start = (unsigned long)eh;
+
+       /*
+        * IRQ and control port handling
+        */
        ec->ops         = &etherh_ops;
+       ec->irq_data    = eh;
+       eh->ctrl        = 0;
+       eh->id          = ec->cid.product;
 
        switch (ec->cid.product) {
        case PROD_ANT_ETHERM:
@@ -533,7 +583,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
                        goto free;
                dev->base_addr += ETHERM_NS8390;
                dev->mem_start  = dev->base_addr + ETHERM_DATAPORT;
-               ec->irq_data    = (void *)(dev->base_addr + ETHERM_CTRLPORT);
+               eh->ctrl_port   = dev->base_addr + ETHERM_CTRLPORT;
                break;
 
        case PROD_I3_ETHERLAN500:
@@ -541,8 +591,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
                        goto free;
                dev->base_addr += ETHERH500_NS8390;
                dev->mem_start  = dev->base_addr + ETHERH500_DATAPORT;
-               dev->rmem_start = (unsigned long)
-               ec->irq_data    = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST)
+               eh->ctrl_port   = ecard_address (ec, ECARD_IOC, ECARD_FAST)
                                  + ETHERH500_CTRLPORT;
                break;
 
@@ -551,8 +600,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
                if (etherh_addr(dev->dev_addr, ec))
                        goto free;
                dev->base_addr += ETHERH600_NS8390;
-               dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
-               ec->irq_data   = (void *)(dev->base_addr + ETHERH600_CTRLPORT);
+               dev->mem_start  = dev->base_addr + ETHERH600_DATAPORT;
+               eh->ctrl_port   = dev->base_addr + ETHERH600_CTRLPORT;
                break;
 
        default:
@@ -571,6 +620,12 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
        if (ethdev_init(dev))
                goto release;
 
+       /*
+        * If we're in the NIC slot, make sure the IRQ is enabled
+        */
+       if (dev->irq == 11)
+               etherh_set_ctrl(eh, ETHERH_CP_IE);
+
        /*
         * Unfortunately, ethdev_init eventually calls
         * ether_setup, which re-writes dev->flags.
@@ -636,6 +691,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
 release:
        release_region(dev->base_addr, 16);
 free:
+       kfree(eh);
+out_nopriv:
        unregister_netdev(dev);
        kfree(dev);
 out:
@@ -696,6 +753,7 @@ static void __exit etherh_exit(void)
                }
                if (e_card[i]) {
                        e_card[i]->ops = NULL;
+                       kfree(e_card[i]->irq_data);
                        ecard_release(e_card[i]);
                        e_card[i] = NULL;
                }