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 */
|