linux-mips
[Top] [All Lists]

[PATCH] au1k_ir - fix for 2.6

To: Jean Tourrilhes <jt@bougret.hpl.hp.com>, Jeff Garzik <jgarzik@pobox.com>, Ralf Baechle <ralf@gnu.org>
Subject: [PATCH] au1k_ir - fix for 2.6
From: Stephen Hemminger <shemminger@osdl.org>
Date: Tue, 9 Dec 2003 15:54:40 -0800
Cc: linux-mips@linux-mips.org, irda-users@sourceforge.net
Organization: Open Source Development Lab
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
This fixes some of the issues with the Alchemy irda driver for MIPS on
2.6.0-test11.  Tested with cross compile.  This driver is probably obsolete
but it is one of the two remaining users of dev_alloc

Changes:
        * irqreturn_t for irq routine
        * alloc_irdadev instead of dev_alloc
        * should work as non module

Some mips build notes:
        * no way to enable the device at present since drivers/net/irda/Kconfig
          expects MIPS_A1000 and arch/mips/Kconfig defines SOC_AU1000!
        * include/asm-mips/timex.h does not define CLOCK_TICK_RATE for this
          that type.  Code should probably be:

#ifdef CONFIG_SGI_IP22
#define CLOCK_TICK_RATE         1000000
#else
#define CLOCK_TICK_RATE         1193182
#endif

diff -Nru a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
--- a/drivers/net/irda/au1k_ir.c        Mon Dec  8 13:44:44 2003
+++ b/drivers/net/irda/au1k_ir.c        Mon Dec  8 13:44:44 2003
@@ -54,18 +54,17 @@
 #include <net/irda/irda_device.h>
 #include "net/irda/au1000_ircc.h"
 
-static int au1k_irda_net_init(struct net_device *);
 static int au1k_irda_start(struct net_device *);
 static int au1k_irda_stop(struct net_device *dev);
 static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *);
 static int au1k_irda_rx(struct net_device *);
-static void au1k_irda_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t au1k_irda_interrupt(int, void *, struct pt_regs *);
 static void au1k_tx_timeout(struct net_device *);
 static struct net_device_stats *au1k_irda_stats(struct net_device *);
 static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int);
 static int au1k_irda_set_speed(struct net_device *dev, int speed);
 
-static void *dma_alloc(size_t, dma_addr_t *);
+static void *dma_alloc(size_t);
 static void dma_free(void *, size_t);
 
 static int qos_mtt_bits = 0x07;  /* 1 ms or more */
@@ -81,7 +80,7 @@
  * IrDA peripheral bug. You have to read the register
  * twice to get the right value.
  */
-u32 read_ir_reg(u32 addr) 
+static u32 read_ir_reg(u32 addr) 
 { 
        readl(addr);
        return readl(addr);
@@ -93,32 +92,23 @@
  * has the virtual and dma address of a buffer suitable for 
  * both, receive and transmit operations.
  */
-static db_dest_t *GetFreeDB(struct au1k_private *aup)
+static inline db_dest_t *GetFreeDB(struct au1k_private *aup)
 {
        db_dest_t *pDB;
        pDB = aup->pDBfree;
 
-       if (pDB) {
+       if (pDB) 
                aup->pDBfree = pDB->pnext;
-       }
-       return pDB;
-}
 
-static void ReleaseDB(struct au1k_private *aup, db_dest_t *pDB)
-{
-       db_dest_t *pDBfree = aup->pDBfree;
-       if (pDBfree)
-               pDBfree->pnext = pDB;
-       aup->pDBfree = pDB;
+       return pDB;
 }
 
-
 /*
   DMA memory allocation, derived from pci_alloc_consistent.
   However, the Au1000 data cache is coherent (when programmed
   so), therefore we return KSEG0 address, not KSEG1.
 */
-static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
+static void *dma_alloc(size_t size)
 {
        void *ret;
        int gfp = GFP_ATOMIC | GFP_DMA;
@@ -127,8 +117,7 @@
 
        if (ret != NULL) {
                memset(ret, 0, size);
-               *dma_handle = virt_to_bus(ret);
-               ret = KSEG0ADDR(ret);
+               ret = (void *) KSEG0ADDR(ret);
        }
        return ret;
 }
@@ -136,7 +125,7 @@
 
 static void dma_free(void *vaddr, size_t size)
 {
-       vaddr = KSEG0ADDR(vaddr);
+       vaddr = (void *) KSEG0ADDR(vaddr);
        free_pages((unsigned long) vaddr, get_order(size));
 }
 
@@ -155,48 +144,7 @@
        }
 }
 
-
-/* 
- * Device has already been stopped at this point.
- */
-static void au1k_irda_net_uninit(struct net_device *dev)
-{
-       dev->hard_start_xmit = NULL;
-       dev->open            = NULL;
-       dev->stop            = NULL;
-       dev->do_ioctl        = NULL;
-       dev->get_stats       = NULL;
-       dev->priv            = NULL;
-}
-
-
-static int au1k_irda_init(void)
-{
-       static unsigned version_printed = 0;
-       struct net_device *dev;
-       int err;
-
-       if (version_printed++ == 0) printk(version);
-
-       rtnl_lock();
-       dev = dev_alloc("irda%d", &err);
-       if (dev) {
-               dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
-               dev->init = au1k_irda_net_init;
-               dev->uninit = au1k_irda_net_uninit;
-               err = register_netdevice(dev);
-
-               if (err)
-                       kfree(dev);
-               else
-                       ir_devs[0] = dev;
-               printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
-       }
-       rtnl_unlock();
-       return err;
-}
-
-static int au1k_irda_init_iobuf(iobuff_t *io, int size)
+static __init int au1k_irda_init_iobuf(iobuff_t *io, int size)
 {
        io->head = kmalloc(size, GFP_KERNEL);
        if (io->head != NULL) {
@@ -208,25 +156,26 @@
        return io->head ? 0 : -ENOMEM;
 }
 
-static int au1k_irda_net_init(struct net_device *dev)
+static __init int au1k_irda_init(void)
 {
-       struct au1k_private *aup = NULL;
-       int i, retval = 0, err;
+       static unsigned version_printed = 0;
+       struct net_device *dev;
+       struct au1k_private *aup;
        db_dest_t *pDB, *pDBfree;
-       unsigned long temp;
+       int i, err;
 
-       dev->priv = kmalloc(sizeof(struct au1k_private), GFP_KERNEL);
-       if (dev->priv == NULL) {
-               retval = -ENOMEM;
-               goto out;
-       }
-       memset(dev->priv, 0, sizeof(struct au1k_private));
-       aup = dev->priv;
+       if (version_printed++ == 0) printk(version);
 
+       dev = alloc_irdadev(sizeof(struct au1k_private));
+       if (!dev) 
+               return -ENOMEM;
+
+       aup = dev->priv;
        err = au1k_irda_init_iobuf(&aup->rx_buff, 14384);
        if (err)
-               goto out;
+               goto out1;
 
+       dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
        dev->open = au1k_irda_start;
        dev->hard_start_xmit = au1k_irda_hard_xmit;
        dev->stop = au1k_irda_stop;
@@ -244,19 +193,19 @@
        aup->qos.min_turn_time.bits = qos_mtt_bits;
        irda_qos_bits_to_value(&aup->qos);
 
-
+       err = -ENOMEM;
        /* Tx ring follows rx ring + 512 bytes */
        /* we need a 1k aligned buffer */
        aup->rx_ring[0] = (ring_dest_t *)
-               dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp);
+               dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
+
+       if (!aup->rx_ring[0])
+               goto out2;
 
        /* allocate the data buffers */
-       aup->db[0].vaddr = 
-               (void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp);
-       if (!aup->db[0].vaddr || !aup->rx_ring[0]) {
-               retval = -ENOMEM;
-               goto out;
-       }
+       aup->db[0].vaddr = dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC);
+       if (!aup->db[0].vaddr) 
+               goto out3;
 
        setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512);
 
@@ -275,16 +224,17 @@
        /* attach a data buffer to each descriptor */
        for (i=0; i<NUM_IR_DESC; i++) {
                pDB = GetFreeDB(aup);
-               if (!pDB) goto out;
+               if (!pDB) goto out4;
                aup->rx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
                aup->rx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
                aup->rx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
                aup->rx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
                aup->rx_db_inuse[i] = pDB;
        }
+
        for (i=0; i<NUM_IR_DESC; i++) {
                pDB = GetFreeDB(aup);
-               if (!pDB) goto out;
+               if (!pDB) goto out4;
                aup->tx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
                aup->tx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
                aup->tx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
@@ -294,24 +244,28 @@
                aup->tx_ring[i]->flags = 0;
                aup->tx_db_inuse[i] = pDB;
        }
-       return 0;
 
-out:
-       if (aup->db[0].vaddr) 
-               dma_free((void *)aup->db[0].vaddr, 
-                               MAX_BUF_SIZE * 2*NUM_IR_DESC);
-       if (aup->rx_ring[0])
-               kfree((void *)aup->rx_ring[0]);
-       if (aup->rx_buff.head)
-               kfree(aup->rx_buff.head);
-       if (dev->priv != NULL)
-               kfree(dev->priv);
-       unregister_netdevice(dev);
-       printk(KERN_ERR "%s: au1k_init_module failed.  Returns %d\n",
-              dev->name, retval);
-       return retval;
-}
+       err = register_netdev(dev);
+       if (err)
+               goto out4;
+       else {
+               ir_devs[0] = dev;
+               printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
+       }
+       return err;
 
+ out4:
+       dma_free((void *)aup->db[0].vaddr, 
+                MAX_BUF_SIZE * 2*NUM_IR_DESC);
+ out3:
+       dma_free((void *)aup->rx_ring[0],
+                2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
+ out2:
+       kfree(aup->rx_buff.head);
+ out1:
+       free_netdev(dev);
+       return err;
+}
 
 static int au1k_init(struct net_device *dev)
 {
@@ -361,11 +315,8 @@
        char hwname[32];
        struct au1k_private *aup = (struct au1k_private *) dev->priv;
 
-       MOD_INC_USE_COUNT;
-
        if ((retval = au1k_init(dev))) {
                printk(KERN_ERR "%s: error in au1k_init\n", dev->name);
-               MOD_DEC_USE_COUNT;
                return retval;
        }
 
@@ -373,7 +324,6 @@
                                        0, dev->name, dev))) {
                printk(KERN_ERR "%s: unable to get IRQ %d\n", 
                                dev->name, dev->irq);
-               MOD_DEC_USE_COUNT;
                return retval;
        }
        if ((retval = request_irq(AU1000_IRDA_RX_INT, &au1k_irda_interrupt, 
@@ -381,7 +331,6 @@
                free_irq(AU1000_IRDA_TX_INT, dev);
                printk(KERN_ERR "%s: unable to get IRQ %d\n", 
                                dev->name, dev->irq);
-               MOD_DEC_USE_COUNT;
                return retval;
        }
 
@@ -418,19 +367,20 @@
        /* disable the interrupt */
        free_irq(AU1000_IRDA_TX_INT, dev);
        free_irq(AU1000_IRDA_RX_INT, dev);
-       MOD_DEC_USE_COUNT;
        return 0;
 }
 
 static void __exit au1k_irda_exit(void)
 {
        struct net_device *dev = ir_devs[0];
-       struct au1k_private *aup = (struct au1k_private *) dev->priv;
+       struct au1k_private *aup;
 
        if (!dev) {
                printk(KERN_ERR "au1k_ircc no dev found\n");
                return;
        }
+
+       aup = (struct au1k_private *) dev->priv;
        if (aup->db[0].vaddr)  {
                dma_free((void *)aup->db[0].vaddr, 
                                MAX_BUF_SIZE * 2*NUM_IR_DESC);
@@ -441,10 +391,16 @@
                                2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
                aup->rx_ring[0] = 0;
        }
-       rtnl_lock();
-       unregister_netdevice(dev);
-       rtnl_unlock();
+
+       unregister_netdev(dev);
+
+       dma_free((void *)aup->db[0].vaddr, MAX_BUF_SIZE * 2*NUM_IR_DESC);
+       dma_free((void *)aup->rx_ring[0], 
+                2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
+       kfree(aup->rx_buff.head);
+
        ir_devs[0] = 0;
+       free_netdev(dev);
 }
 
 
@@ -656,19 +612,21 @@
 }
 
 
-void au1k_irda_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t au1k_irda_interrupt(int irq, void *dev_id, 
+                                      struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) dev_id;
 
        if (dev == NULL) {
                printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
-               return;
+               return IRQ_NONE;
        }
 
        writel(0, IR_INT_CLEAR); /* ack irda interrupts */
 
        au1k_irda_rx(dev);
        au1k_tx_ack(dev);
+       return IRQ_HANDLED;
 }
 
 
@@ -859,10 +817,8 @@
        return &aup->stats;
 }
 
-#ifdef MODULE
 MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
 MODULE_DESCRIPTION("Au1000 IrDA Device Driver");
 
 module_init(au1k_irda_init);
 module_exit(au1k_irda_exit);
-#endif /* MODULE */

<Prev in Thread] Current Thread [Next in Thread>