fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / atm / he.c
index ad746d9..db33f6f 100644 (file)
@@ -55,9 +55,7 @@
 
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/pci.h>
@@ -70,6 +68,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #undef USE_RBPL_POOL                   /* if memory is tight try this */
 #define USE_TPD_POOL
 /* #undef CONFIG_ATM_HE_USE_SUNI */
-
-/* compatibility */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)
-typedef void irqreturn_t;
-#define IRQ_NONE
-#define IRQ_HANDLED
-#define IRQ_RETVAL(x)
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9)
-#define __devexit_p(func)              func
-#endif
-
-#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(x)
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
-#define pci_set_drvdata(pci_dev, data) (pci_dev)->driver_data = (data)
-#define pci_get_drvdata(pci_dev)       (pci_dev)->driver_data
-#endif
+/* #undef HE_DEBUG */
 
 #include "he.h"
-
 #include "suni.h"
-
 #include <linux/atm_he.h>
 
 #define hprintk(fmt,args...)   printk(KERN_ERR DEV_LABEL "%d: " fmt, he_dev->number , ##args)
 
-#undef DEBUG
-#ifdef DEBUG
+#ifdef HE_DEBUG
 #define HPRINTK(fmt,args...)   printk(KERN_DEBUG DEV_LABEL "%d: " fmt, he_dev->number , ##args)
-#else
+#else /* !HE_DEBUG */
 #define HPRINTK(fmt,args...)   do { } while (0)
-#endif /* DEBUG */
-
+#endif /* HE_DEBUG */
 
 /* version definition */
 
@@ -135,7 +109,7 @@ static int he_open(struct atm_vcc *vcc);
 static void he_close(struct atm_vcc *vcc);
 static int he_send(struct atm_vcc *vcc, struct sk_buff *skb);
 static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg);
-static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t he_irq_handler(int irq, void *dev_id);
 static void he_tasklet(unsigned long data);
 static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
 static int he_start(struct atm_dev *dev);
@@ -147,13 +121,55 @@ static u8 read_prom_byte(struct he_dev *he_dev, int addr);
 
 /* globals */
 
-struct he_dev *he_devs = NULL;
-static short disable64 = -1;
+static struct he_dev *he_devs;
+static int disable64;
 static short nvpibits = -1;
 static short nvcibits = -1;
 static short rx_skb_reserve = 16;
-static short irq_coalesce = 1;
-static short sdh = 0;
+static int irq_coalesce = 1;
+static int sdh = 0;
+
+/* Read from EEPROM = 0000 0011b */
+static unsigned int readtab[] = {
+       CS_HIGH | CLK_HIGH,
+       CS_LOW | CLK_LOW,
+       CLK_HIGH,               /* 0 */
+       CLK_LOW,
+       CLK_HIGH,               /* 0 */
+       CLK_LOW,
+       CLK_HIGH,               /* 0 */
+       CLK_LOW,
+       CLK_HIGH,               /* 0 */
+       CLK_LOW,
+       CLK_HIGH,               /* 0 */
+       CLK_LOW,
+       CLK_HIGH,               /* 0 */
+       CLK_LOW | SI_HIGH,
+       CLK_HIGH | SI_HIGH,     /* 1 */
+       CLK_LOW | SI_HIGH,
+       CLK_HIGH | SI_HIGH      /* 1 */
+};     
+/* Clock to read from/write to the EEPROM */
+static unsigned int clocktab[] = {
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW,
+       CLK_HIGH,
+       CLK_LOW
+};     
 
 static struct atmdev_ops he_ops =
 {
@@ -354,27 +370,25 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
 
        if (pci_enable_device(pci_dev))
                return -EIO;
-       if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) {
+       if (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK) != 0) {
                printk(KERN_WARNING "he: no suitable dma available\n");
                err = -EIO;
                goto init_one_failure;
        }
 
-       atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0);
+       atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, NULL);
        if (!atm_dev) {
                err = -ENODEV;
                goto init_one_failure;
        }
        pci_set_drvdata(pci_dev, atm_dev);
 
-       he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev),
+       he_dev = kzalloc(sizeof(struct he_dev),
                                                        GFP_KERNEL);
        if (!he_dev) {
                err = -ENOMEM;
                goto init_one_failure;
        }
-       memset(he_dev, 0, sizeof(struct he_dev));
-
        he_dev->pci_dev = pci_dev;
        he_dev->atm_dev = atm_dev;
        he_dev->atm_dev->dev_data = he_dev;
@@ -394,8 +408,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
 init_one_failure:
        if (atm_dev)
                atm_dev_deregister(atm_dev);
-       if (he_dev)
-               kfree(he_dev);
+       kfree(he_dev);
        pci_disable_device(pci_dev);
        return err;
 }
@@ -439,7 +452,7 @@ rate_to_atmf(unsigned rate)         /* cps to atm forum format */
        return (NONZERO | (exp << 9) | (rate & 0x1ff));
 }
 
-static void __init
+static void __devinit
 he_init_rx_lbfp0(struct he_dev *he_dev)
 {
        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
@@ -470,7 +483,7 @@ he_init_rx_lbfp0(struct he_dev *he_dev)
        he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
 }
 
-static void __init
+static void __devinit
 he_init_rx_lbfp1(struct he_dev *he_dev)
 {
        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
@@ -501,7 +514,7 @@ he_init_rx_lbfp1(struct he_dev *he_dev)
        he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
 }
 
-static void __init
+static void __devinit
 he_init_tx_lbfp(struct he_dev *he_dev)
 {
        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
@@ -531,7 +544,7 @@ he_init_tx_lbfp(struct he_dev *he_dev)
        he_writel(he_dev, lbufd_index - 1, TLBF_T);
 }
 
-static int __init
+static int __devinit
 he_init_tpdrq(struct he_dev *he_dev)
 {
        he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
@@ -553,7 +566,7 @@ he_init_tpdrq(struct he_dev *he_dev)
        return 0;
 }
 
-static void __init
+static void __devinit
 he_init_cs_block(struct he_dev *he_dev)
 {
        unsigned clock, rate, delta;
@@ -649,7 +662,7 @@ he_init_cs_block(struct he_dev *he_dev)
 
 }
 
-static int __init
+static int __devinit
 he_init_cs_block_rcm(struct he_dev *he_dev)
 {
        unsigned (*rategrid)[16][16];
@@ -770,7 +783,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev)
        return 0;
 }
 
-static int __init
+static int __devinit
 he_init_group(struct he_dev *he_dev, int group)
 {
        int i;
@@ -807,7 +820,7 @@ he_init_group(struct he_dev *he_dev, int group)
                void *cpuaddr;
 
 #ifdef USE_RBPS_POOL 
-               cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+               cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
                if (cpuaddr == NULL)
                        return -ENOMEM;
 #else
@@ -871,7 +884,7 @@ he_init_group(struct he_dev *he_dev, int group)
                void *cpuaddr;
 
 #ifdef USE_RBPL_POOL
-               cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+               cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
                if (cpuaddr == NULL)
                        return -ENOMEM;
 #else
@@ -940,7 +953,7 @@ he_init_group(struct he_dev *he_dev, int group)
        return 0;
 }
 
-static int __init
+static int __devinit
 he_init_irq(struct he_dev *he_dev)
 {
        int i;
@@ -992,7 +1005,7 @@ he_init_irq(struct he_dev *he_dev)
        he_writel(he_dev, 0x0, GRP_54_MAP);
        he_writel(he_dev, 0x0, GRP_76_MAP);
 
-       if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev)) {
+       if (request_irq(he_dev->pci_dev->irq, he_irq_handler, IRQF_DISABLED|IRQF_SHARED, DEV_LABEL, he_dev)) {
                hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
                return -EINVAL;
        }   
@@ -1002,11 +1015,12 @@ he_init_irq(struct he_dev *he_dev)
        return 0;
 }
 
-static int __init
+static int __devinit
 he_start(struct atm_dev *dev)
 {
        struct he_dev *he_dev;
        struct pci_dev *pci_dev;
+       unsigned long membase;
 
        u16 command;
        u32 gen_cntl_0, host_cntl, lb_swap;
@@ -1019,8 +1033,8 @@ he_start(struct atm_dev *dev)
        he_dev = HE_DEV(dev);
        pci_dev = he_dev->pci_dev;
 
-       he_dev->membase = pci_dev->resource[0].start;
-       HPRINTK("membase = 0x%lx  irq = %d.\n", he_dev->membase, pci_dev->irq);
+       membase = pci_resource_start(pci_dev, 0);
+       HPRINTK("membase = 0x%lx  irq = %d.\n", membase, pci_dev->irq);
 
        /*
         * pci bus controller initialization 
@@ -1080,7 +1094,7 @@ he_start(struct atm_dev *dev)
                        hprintk("can't set latency timer to %d\n", timer);
        }
 
-       if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
+       if (!(he_dev->membase = ioremap(membase, HE_REGMAP_SIZE))) {
                hprintk("can't set up page mapping\n");
                return -EINVAL;
        }
@@ -1700,7 +1714,7 @@ he_stop(struct he_dev *he_dev)
        }
        
        if (he_dev->membase)
-               iounmap((void *) he_dev->membase);
+               iounmap(he_dev->membase);
 }
 
 static struct he_tpd *
@@ -1710,7 +1724,7 @@ __alloc_tpd(struct he_dev *he_dev)
        struct he_tpd *tpd;
        dma_addr_t dma_handle; 
 
-       tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle);              
+       tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &dma_handle);
        if (tpd == NULL)
                return NULL;
                        
@@ -1869,7 +1883,7 @@ he_service_rbrq(struct he_dev *he_dev, int group)
                if (rx_skb_reserve > 0)
                        skb_reserve(skb, rx_skb_reserve);
 
-               do_gettimeofday(&skb->stamp);
+               __net_timestamp(skb);
 
                for (iov = he_vcc->iov_head;
                                iov < he_vcc->iov_tail; ++iov) {
@@ -1896,7 +1910,7 @@ he_service_rbrq(struct he_dev *he_dev, int group)
                                skb->tail = skb->data + skb->len;
 #ifdef USE_CHECKSUM_HW
                                if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) {
-                                       skb->ip_summed = CHECKSUM_HW;
+                                       skb->ip_summed = CHECKSUM_COMPLETE;
                                        skb->csum = TCP_CKSUM(skb->data,
                                                        he_vcc->pdu_len);
                                }
@@ -1912,7 +1926,9 @@ he_service_rbrq(struct he_dev *he_dev, int group)
 #ifdef notdef
                ATM_SKB(skb)->vcc = vcc;
 #endif
+               spin_unlock(&he_dev->global_lock);
                vcc->push(vcc, skb);
+               spin_lock(&he_dev->global_lock);
 
                atomic_inc(&vcc->stats->rx);
 
@@ -1962,7 +1978,7 @@ he_service_tbrq(struct he_dev *he_dev, int group)
        struct he_tpd *tpd;
        int slot, updated = 0;
 #ifdef USE_TPD_POOL
-       struct list_head *p;
+       struct he_tpd *__tpd;
 #endif
 
        /* 2.1.6 transmit buffer return queue */
@@ -1977,8 +1993,7 @@ he_service_tbrq(struct he_dev *he_dev, int group)
                        TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
 #ifdef USE_TPD_POOL
                tpd = NULL;
-               list_for_each(p, &he_dev->outstanding_tpds) {
-                       struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry);
+               list_for_each_entry(__tpd, &he_dev->outstanding_tpds, entry) {
                        if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) {
                                tpd = __tpd;
                                list_del(&__tpd->entry);
@@ -2201,7 +2216,7 @@ he_tasklet(unsigned long data)
 }
 
 static irqreturn_t
-he_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+he_irq_handler(int irq, void *dev_id)
 {
        unsigned long flags;
        struct he_dev *he_dev = (struct he_dev * )dev_id;
@@ -2267,6 +2282,8 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
                                TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H)));
 
                if (new_tail == he_dev->tpdrq_head) {
+                       int slot;
+
                        hprintk("tpdrq full (cid 0x%x)\n", cid);
                        /*
                         * FIXME
@@ -2274,6 +2291,13 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
                         * after service_tbrq, service the backlog
                         * for now, we just drop the pdu
                         */
+                       for (slot = 0; slot < TPD_MAXIOV; ++slot) {
+                               if (tpd->iovec[slot].addr)
+                                       pci_unmap_single(he_dev->pci_dev,
+                                               tpd->iovec[slot].addr,
+                                               tpd->iovec[slot].len & TPD_LEN_MASK,
+                                                               PCI_DMA_TODEVICE);
+                       }
                        if (tpd->skb) {
                                if (tpd->vcc->pop)
                                        tpd->vcc->pop(tpd->vcc, tpd->skb);
@@ -2327,7 +2351,7 @@ he_open(struct atm_vcc *vcc)
 
        cid = he_mkcid(he_dev, vpi, vci);
 
-       he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
+       he_vcc = kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
        if (he_vcc == NULL) {
                hprintk("unable to allocate he_vcc during open\n");
                return -ENOMEM;
@@ -2516,8 +2540,7 @@ he_open(struct atm_vcc *vcc)
 open_failed:
 
        if (err) {
-               if (he_vcc)
-                       kfree(he_vcc);
+               kfree(he_vcc);
                clear_bit(ATM_VF_ADDR, &vcc->flags);
        }
        else
@@ -2558,8 +2581,8 @@ he_close(struct atm_vcc *vcc)
                        udelay(250);
                }
 
-               add_wait_queue(&he_vcc->rx_waitq, &wait);
                set_current_state(TASK_UNINTERRUPTIBLE);
+               add_wait_queue(&he_vcc->rx_waitq, &wait);
 
                he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid);
                (void) he_readl_rsr0(he_dev, cid);              /* flush posted writes */
@@ -2593,11 +2616,10 @@ he_close(struct atm_vcc *vcc)
                 * TBRQ, the host issues the close command to the adapter.
                 */
 
-               while (((tx_inuse = atomic_read(&vcc->sk->sk_wmem_alloc)) > 0) &&
+               while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 0) &&
                       (retry < MAX_RETRY)) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       (void) schedule_timeout(sleep);
-                       if (sleep < HZ)
+                       msleep(sleep);
+                       if (sleep < 250)
                                sleep = sleep * 2;
 
                        ++retry;
@@ -2634,8 +2656,8 @@ he_close(struct atm_vcc *vcc)
                tpd->vcc = vcc;
                wmb();
 
-               add_wait_queue(&he_vcc->tx_waitq, &wait);
                set_current_state(TASK_UNINTERRUPTIBLE);
+               add_wait_queue(&he_vcc->tx_waitq, &wait);
                __enqueue_tpd(he_dev, tpd, cid);
                spin_unlock_irqrestore(&he_dev->global_lock, flags);
 
@@ -3033,17 +3055,17 @@ read_prom_byte(struct he_dev *he_dev, int addr)
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>");
 MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver");
-MODULE_PARM(disable64, "h");
+module_param(disable64, bool, 0);
 MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers");
-MODULE_PARM(nvpibits, "i");
+module_param(nvpibits, short, 0);
 MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)");
-MODULE_PARM(nvcibits, "i");
+module_param(nvcibits, short, 0);
 MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)");
-MODULE_PARM(rx_skb_reserve, "i");
+module_param(rx_skb_reserve, short, 0);
 MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)");
-MODULE_PARM(irq_coalesce, "i");
+module_param(irq_coalesce, bool, 0);
 MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)");
-MODULE_PARM(sdh, "i");
+module_param(sdh, bool, 0);
 MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
 
 static struct pci_device_id he_pci_tbl[] = {
@@ -3052,6 +3074,8 @@ static struct pci_device_id he_pci_tbl[] = {
        { 0, }
 };
 
+MODULE_DEVICE_TABLE(pci, he_pci_tbl);
+
 static struct pci_driver he_driver = {
        .name =         "he",
        .probe =        he_init_one,
@@ -3061,7 +3085,7 @@ static struct pci_driver he_driver = {
 
 static int __init he_init(void)
 {
-       return pci_module_init(&he_driver);
+       return pci_register_driver(&he_driver);
 }
 
 static void __exit he_cleanup(void)