diff options
Diffstat (limited to 'drivers/atm')
| -rw-r--r-- | drivers/atm/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/atm/Makefile | 2 | ||||
| -rw-r--r-- | drivers/atm/adummy.c | 42 | ||||
| -rw-r--r-- | drivers/atm/ambassador.c | 102 | ||||
| -rw-r--r-- | drivers/atm/ambassador.h | 4 | ||||
| -rw-r--r-- | drivers/atm/atmtcp.c | 22 | ||||
| -rw-r--r-- | drivers/atm/eni.c | 148 | ||||
| -rw-r--r-- | drivers/atm/eni.h | 8 | ||||
| -rw-r--r-- | drivers/atm/firestream.c | 59 | ||||
| -rw-r--r-- | drivers/atm/firestream.h | 1 | ||||
| -rw-r--r-- | drivers/atm/fore200e.c | 162 | ||||
| -rw-r--r-- | drivers/atm/fore200e.h | 4 | ||||
| -rw-r--r-- | drivers/atm/he.c | 393 | ||||
| -rw-r--r-- | drivers/atm/he.h | 65 | ||||
| -rw-r--r-- | drivers/atm/horizon.c | 41 | ||||
| -rw-r--r-- | drivers/atm/idt77105.c | 21 | ||||
| -rw-r--r-- | drivers/atm/idt77252.c | 114 | ||||
| -rw-r--r-- | drivers/atm/idt77252.h | 4 | ||||
| -rw-r--r-- | drivers/atm/iphase.c | 315 | ||||
| -rw-r--r-- | drivers/atm/iphase.h | 543 | ||||
| -rw-r--r-- | drivers/atm/lanai.c | 77 | ||||
| -rw-r--r-- | drivers/atm/nicstar.c | 5187 | ||||
| -rw-r--r-- | drivers/atm/nicstar.h | 602 | ||||
| -rw-r--r-- | drivers/atm/nicstarmac.c | 364 | ||||
| -rw-r--r-- | drivers/atm/solos-attrlist.c | 1 | ||||
| -rw-r--r-- | drivers/atm/solos-pci.c | 370 | ||||
| -rw-r--r-- | drivers/atm/suni.c | 9 | ||||
| -rw-r--r-- | drivers/atm/uPD98402.c | 3 | ||||
| -rw-r--r-- | drivers/atm/zatm.c | 44 |
29 files changed, 4215 insertions, 4497 deletions
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig index 191b85e857e..31c60101a69 100644 --- a/drivers/atm/Kconfig +++ b/drivers/atm/Kconfig @@ -177,7 +177,7 @@ config ATM_ZATM_DEBUG config ATM_NICSTAR tristate "IDT 77201 (NICStAR) (ForeRunnerLE)" - depends on PCI && !64BIT && VIRT_TO_BUS + depends on PCI help The NICStAR chipset family is used in a large number of ATM NICs for 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE @@ -301,7 +301,7 @@ config ATM_IA control memory (128K-1KVC, 512K-4KVC), the size of the packet memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3, UTP155, UTP25, DS3 and E3). Go to: - <http://www.iphase.com/products/ClassSheet.cfm?ClassID=ATM> + <http://www.iphase.com/> for more info about the cards. Say Y (or M to compile as a module named iphase) here if you have one of these cards. @@ -394,6 +394,7 @@ config ATM_HE_USE_SUNI config ATM_SOLOS tristate "Solos ADSL2+ PCI Multiport card driver" depends on PCI + select FW_LOADER help Support for the Solos multiport ADSL2+ card. diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile index 62c3cc1075a..c6c9ee9f5da 100644 --- a/drivers/atm/Makefile +++ b/drivers/atm/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux network (ATM) device drivers. # -fore_200e-objs := fore200e.o +fore_200e-y := fore200e.o obj-$(CONFIG_ATM_ZATM) += zatm.o uPD98402.o obj-$(CONFIG_ATM_NICSTAR) += nicstar.o diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c index 5effec6f545..f9b983ae687 100644 --- a/drivers/atm/adummy.c +++ b/drivers/atm/adummy.c @@ -13,6 +13,7 @@ #include <linux/mm.h> #include <linux/timer.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/byteorder.h> #include <asm/uaccess.h> @@ -39,6 +40,42 @@ struct adummy_dev { static LIST_HEAD(adummy_devs); +static ssize_t __set_signal(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev); + int signal; + + if (sscanf(buf, "%d", &signal) == 1) { + + if (signal < ATM_PHY_SIG_LOST || signal > ATM_PHY_SIG_FOUND) + signal = ATM_PHY_SIG_UNKNOWN; + + atm_dev_signal_change(atm_dev, signal); + return 1; + } + return -EINVAL; +} + +static ssize_t __show_signal(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev); + return sprintf(buf, "%d\n", atm_dev->signal); +} +static DEVICE_ATTR(signal, 0644, __show_signal, __set_signal); + +static struct attribute *adummy_attrs[] = { + &dev_attr_signal.attr, + NULL +}; + +static struct attribute_group adummy_group_attrs = { + .name = NULL, /* We want them in dev's root folder */ + .attrs = adummy_attrs +}; + static int __init adummy_start(struct atm_dev *dev) { @@ -117,7 +154,7 @@ static int __init adummy_init(void) err = -ENOMEM; goto out; } - atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, NULL); + atm_dev = atm_dev_register(DEV_LABEL, NULL, &adummy_ops, -1, NULL); if (!atm_dev) { printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n"); err = -ENODEV; @@ -127,6 +164,9 @@ static int __init adummy_init(void) adummy_dev->atm_dev = atm_dev; atm_dev->dev_data = adummy_dev; + if (sysfs_create_group(&atm_dev->class_dev.kobj, &adummy_group_attrs)) + dev_err(&atm_dev->class_dev, "Could not register attrs for adummy\n"); + if (adummy_start(atm_dev)) { printk(KERN_ERR DEV_LABEL ": adummy_start() failed\n"); err = -ENODEV; diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 8af23411743..f1a9198dfe5 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -36,8 +36,9 @@ #include <linux/mutex.h> #include <linux/firmware.h> #include <linux/ihex.h> +#include <linux/slab.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/io.h> #include <asm/byteorder.h> @@ -496,7 +497,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { // VC layer stats atomic_inc(&atm_vcc->stats->rx); __net_timestamp(skb); - // end of our responsability + // end of our responsibility atm_vcc->push (atm_vcc, skb); return; @@ -801,7 +802,7 @@ static void fill_rx_pool (amb_dev * dev, unsigned char pool, } // cast needed as there is no %? for pointer differences PRINTD (DBG_SKB, "allocated skb at %p, head %p, area %li", - skb, skb->head, (long) (skb_end_pointer(skb) - skb->head)); + skb, skb->head, (long) skb_end_offset(skb)); rx.handle = virt_to_bus (skb); rx.host_address = cpu_to_be32 (virt_to_bus (skb->data)); if (rx_give (dev, &rx, pool)) @@ -812,7 +813,7 @@ static void fill_rx_pool (amb_dev * dev, unsigned char pool, return; } -// top up all RX pools (can also be called as a bottom half) +// top up all RX pools static void fill_rx_pools (amb_dev * dev) { unsigned char pool; @@ -871,11 +872,7 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) { ++irq_work; if (irq_work) { -#ifdef FILL_RX_POOLS_IN_BH - schedule_work (&dev->bh); -#else fill_rx_pools (dev); -#endif PRINTD (DBG_IRQ, "work done: %u", irq_work); } else { @@ -1406,7 +1403,7 @@ static void amb_free_rx_skb (struct atm_vcc * atm_vcc, struct sk_buff * skb) { rx.host_address = cpu_to_be32 (virt_to_bus (skb->data)); skb->data = skb->head; - skb->tail = skb->head; + skb_reset_tail_pointer(skb); skb->len = 0; if (!rx_give (dev, &rx, pool)) { @@ -1510,9 +1507,9 @@ static void do_housekeeping (unsigned long arg) { /********** creation of communication queues **********/ -static int __devinit create_queues (amb_dev * dev, unsigned int cmds, - unsigned int txs, unsigned int * rxs, - unsigned int * rx_buffer_sizes) { +static int create_queues(amb_dev *dev, unsigned int cmds, unsigned int txs, + unsigned int *rxs, unsigned int *rx_buffer_sizes) +{ unsigned char pool; size_t total = 0; void * memory; @@ -1740,8 +1737,9 @@ static int decode_loader_result (loader_command cmd, u32 result) return res; } -static int __devinit do_loader_command (volatile loader_block * lb, - const amb_dev * dev, loader_command cmd) { +static int do_loader_command(volatile loader_block *lb, const amb_dev *dev, + loader_command cmd) +{ unsigned long timeout; @@ -1796,8 +1794,9 @@ static int __devinit do_loader_command (volatile loader_block * lb, /* loader: determine loader version */ -static int __devinit get_loader_version (loader_block * lb, - const amb_dev * dev, u32 * version) { +static int get_loader_version(loader_block *lb, const amb_dev *dev, + u32 *version) +{ int res; PRINTD (DBG_FLOW|DBG_LOAD, "get_loader_version"); @@ -1812,9 +1811,9 @@ static int __devinit get_loader_version (loader_block * lb, /* loader: write memory data blocks */ -static int __devinit loader_write (loader_block* lb, - const amb_dev *dev, - const struct ihex_binrec *rec) { +static int loader_write(loader_block *lb, const amb_dev *dev, + const struct ihex_binrec *rec) +{ transfer_block * tb = &lb->payload.transfer; PRINTD (DBG_FLOW|DBG_LOAD, "loader_write"); @@ -1827,9 +1826,9 @@ static int __devinit loader_write (loader_block* lb, /* loader: verify memory data blocks */ -static int __devinit loader_verify (loader_block * lb, - const amb_dev *dev, - const struct ihex_binrec *rec) { +static int loader_verify(loader_block *lb, const amb_dev *dev, + const struct ihex_binrec *rec) +{ transfer_block * tb = &lb->payload.transfer; int res; @@ -1845,8 +1844,8 @@ static int __devinit loader_verify (loader_block * lb, /* loader: start microcode */ -static int __devinit loader_start (loader_block * lb, - const amb_dev * dev, u32 address) { +static int loader_start(loader_block *lb, const amb_dev *dev, u32 address) +{ PRINTD (DBG_FLOW|DBG_LOAD, "loader_start"); lb->payload.start = cpu_to_be32 (address); @@ -1921,12 +1920,14 @@ static int amb_reset (amb_dev * dev, int diags) { /********** transfer and start the microcode **********/ -static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { +static int ucode_init(loader_block *lb, amb_dev *dev) +{ const struct firmware *fw; unsigned long start_address; const struct ihex_binrec *rec; + const char *errmsg = NULL; int res; - + res = request_ihex_firmware(&fw, "atmsar11.fw", &dev->pci_dev->dev); if (res) { PRINTK (KERN_ERR, "Cannot load microcode data"); @@ -1936,8 +1937,8 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { /* First record contains just the start address */ rec = (const struct ihex_binrec *)fw->data; if (be16_to_cpu(rec->len) != sizeof(__be32) || be32_to_cpu(rec->addr)) { - PRINTK (KERN_ERR, "Bad microcode data (no start record)"); - return -EINVAL; + errmsg = "no start record"; + goto fail; } start_address = be32_to_cpup((__be32 *)rec->data); @@ -1949,12 +1950,12 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { PRINTD (DBG_LOAD, "starting region (%x, %u)", be32_to_cpu(rec->addr), be16_to_cpu(rec->len)); if (be16_to_cpu(rec->len) > 4 * MAX_TRANSFER_DATA) { - PRINTK (KERN_ERR, "Bad microcode data (record too long)"); - return -EINVAL; + errmsg = "record too long"; + goto fail; } if (be16_to_cpu(rec->len) & 3) { - PRINTK (KERN_ERR, "Bad microcode data (odd number of bytes)"); - return -EINVAL; + errmsg = "odd number of bytes"; + goto fail; } res = loader_write(lb, dev, rec); if (res) @@ -1963,12 +1964,17 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { res = loader_verify(lb, dev, rec); if (res) break; + rec = ihex_next_binrec(rec); } release_firmware(fw); if (!res) res = loader_start(lb, dev, start_address); return res; +fail: + release_firmware(fw); + PRINTK(KERN_ERR, "Bad microcode data (%s)", errmsg); + return -EINVAL; } /********** give adapter parameters **********/ @@ -1977,7 +1983,8 @@ static inline __be32 bus_addr(void * addr) { return cpu_to_be32 (virt_to_bus (addr)); } -static int __devinit amb_talk (amb_dev * dev) { +static int amb_talk(amb_dev *dev) +{ adap_talk_block a; unsigned char pool; unsigned long timeout; @@ -2024,7 +2031,8 @@ static int __devinit amb_talk (amb_dev * dev) { } // get microcode version -static void __devinit amb_ucode_version (amb_dev * dev) { +static void amb_ucode_version(amb_dev *dev) +{ u32 major; u32 minor; command cmd; @@ -2039,7 +2047,8 @@ static void __devinit amb_ucode_version (amb_dev * dev) { } // get end station address -static void __devinit amb_esi (amb_dev * dev, u8 * esi) { +static void amb_esi(amb_dev *dev, u8 *esi) +{ u32 lower4; u16 upper2; command cmd; @@ -2085,7 +2094,7 @@ static void fixup_plx_window (amb_dev *dev, loader_block *lb) return; } -static int __devinit amb_init (amb_dev * dev) +static int amb_init(amb_dev *dev) { loader_block lb; @@ -2148,11 +2157,6 @@ static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev) dev->tx_avail = ATM_OC3_PCR; dev->rx_avail = ATM_OC3_PCR; -#ifdef FILL_RX_POOLS_IN_BH - // initialise bottom half - INIT_WORK(&dev->bh, (void (*)(void *)) fill_rx_pools, dev); -#endif - // semaphore for txer/rxer modifications - we cannot use a // spinlock as the critical region needs to switch processes mutex_init(&dev->vcc_sf); @@ -2186,7 +2190,8 @@ static void setup_pci_dev(struct pci_dev *pci_dev) } } -static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +static int amb_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_ent) { amb_dev * dev; int err; @@ -2243,7 +2248,8 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_ goto out_reset; } - dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, NULL); + dev->atm_dev = atm_dev_register (DEV_LABEL, &pci_dev->dev, &amb_ops, -1, + NULL); if (!dev->atm_dev) { PRINTD (DBG_ERR, "failed to register Madge ATM adapter"); err = -EINVAL; @@ -2286,7 +2292,7 @@ out_disable: } -static void __devexit amb_remove_one(struct pci_dev *pci_dev) +static void amb_remove_one(struct pci_dev *pci_dev) { struct amb_dev *dev; @@ -2370,10 +2376,8 @@ MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); /********** module entry **********/ static struct pci_device_id amb_pci_tbl[] = { - { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 0 }, - { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 0 }, + { PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR), 0 }, + { PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD), 0 }, { 0, } }; @@ -2382,7 +2386,7 @@ MODULE_DEVICE_TABLE(pci, amb_pci_tbl); static struct pci_driver amb_driver = { .name = "amb", .probe = amb_probe, - .remove = __devexit_p(amb_remove_one), + .remove = amb_remove_one, .id_table = amb_pci_tbl, }; diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h index bd1c46a7ef4..aa9710556bd 100644 --- a/drivers/atm/ambassador.h +++ b/drivers/atm/ambassador.h @@ -630,10 +630,6 @@ struct amb_dev { u32 iobase; u32 * membase; -#ifdef FILL_RX_POOLS_IN_BH - struct work_struct bh; -#endif - amb_cq cq; amb_txq txq; amb_rxq rxq[NUM_RX_POOLS]; diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index 02ad83d6b56..0e3f8f9dcd2 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -9,8 +9,9 @@ #include <linux/atm_tcp.h> #include <linux/bitops.h> #include <linux/init.h> +#include <linux/slab.h> #include <asm/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h> extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */ @@ -67,7 +68,7 @@ static int atmtcp_send_control(struct atm_vcc *vcc,int type, *(struct atm_vcc **) &new_msg->vcc = vcc; old_test = test_bit(flag,&vcc->flags); out_vcc->push(out_vcc,skb); - add_wait_queue(sk_atm(vcc)->sk_sleep, &wait); + add_wait_queue(sk_sleep(sk_atm(vcc)), &wait); while (test_bit(flag,&vcc->flags) == old_test) { mb(); out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL; @@ -79,7 +80,7 @@ static int atmtcp_send_control(struct atm_vcc *vcc,int type, schedule(); } set_current_state(TASK_RUNNING); - remove_wait_queue(sk_atm(vcc)->sk_sleep, &wait); + remove_wait_queue(sk_sleep(sk_atm(vcc)), &wait); return error; } @@ -104,7 +105,7 @@ static int atmtcp_recv_control(const struct atmtcp_control *msg) msg->type); return -EINVAL; } - wake_up(sk_atm(vcc)->sk_sleep); + wake_up(sk_sleep(sk_atm(vcc))); return 0; } @@ -156,7 +157,6 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) { struct atm_cirange ci; struct atm_vcc *vcc; - struct hlist_node *node; struct sock *s; int i; @@ -170,7 +170,7 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) for(i = 0; i < VCC_HTABLE_SIZE; ++i) { struct hlist_head *head = &vcc_hash[i]; - sk_for_each(s, node, head) { + sk_for_each(s, head) { vcc = atm_sk(s); if (vcc->dev != dev) continue; @@ -263,12 +263,11 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) { struct hlist_head *head; struct atm_vcc *vcc; - struct hlist_node *node; struct sock *s; head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)]; - sk_for_each(s, node, head) { + sk_for_each(s, head) { vcc = atm_sk(s); if (vcc->dev == dev && vcc->vci == vci && vcc->vpi == vpi && @@ -365,7 +364,7 @@ static int atmtcp_create(int itf,int persist,struct atm_dev **result) if (!dev_data) return -ENOMEM; - dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL); + dev = atm_dev_register(DEV_LABEL,NULL,&atmtcp_v_dev_ops,itf,NULL); if (!dev) { kfree(dev_data); return itf == -1 ? -ENOMEM : -EBUSY; @@ -391,7 +390,10 @@ static int atmtcp_attach(struct atm_vcc *vcc,int itf) atm_dev_put(dev); return -EMEDIUMTYPE; } - if (PRIV(dev)->vcc) return -EBUSY; + if (PRIV(dev)->vcc) { + atm_dev_put(dev); + return -EBUSY; + } } else { int error; diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 0c302614544..b1955ba40d6 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -18,9 +18,9 @@ #include <linux/init.h> #include <linux/atm_eni.h> #include <linux/bitops.h> -#include <asm/system.h> +#include <linux/slab.h> #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/uaccess.h> #include <asm/string.h> #include <asm/byteorder.h> @@ -155,9 +155,6 @@ static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0, static struct atm_dev *eni_boards = NULL; -static u32 *cpu_zeroes = NULL; /* aligned "magic" zeroes */ -static dma_addr_t zeroes; - /* Read/write registers on card */ #define eni_in(r) readl(eni_dev->reg+(r)*4) #define eni_out(v,r) writel((v),eni_dev->reg+(r)*4) @@ -1130,14 +1127,17 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */ if (i == -1) put_dma(tx->index,eni_dev->dma,&j,(unsigned long) skb->data, - skb->len - skb->data_len); + skb_headlen(skb)); else put_dma(tx->index,eni_dev->dma,&j,(unsigned long) - skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset, - skb_shinfo(skb)->frags[i].size); + skb_frag_page(&skb_shinfo(skb)->frags[i]) + + skb_shinfo(skb)->frags[i].page_offset, + skb_frag_size(&skb_shinfo(skb)->frags[i])); + } + if (skb->len & 3) { + put_dma(tx->index, eni_dev->dma, &j, eni_dev->zero.dma, + 4 - (skb->len & 3)); } - if (skb->len & 3) - put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3)); /* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */ eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) << MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) | @@ -1468,10 +1468,7 @@ if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost); static void bug_int(struct atm_dev *dev,unsigned long reason) { - struct eni_dev *eni_dev; - DPRINTK(">bug_int\n"); - eni_dev = ENI_DEV(dev); if (reason & MID_DMA_ERR_ACK) printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA " "error\n",dev->number); @@ -1570,7 +1567,7 @@ tx_complete++; /*--------------------------------- entries ---------------------------------*/ -static const char *media_name[] __devinitdata = { +static char * const media_name[] = { "MMF", "SMF", "MMF", "03?", /* 0- 3 */ "UTP", "05?", "06?", "07?", /* 4- 7 */ "TAXI","09?", "10?", "11?", /* 8-11 */ @@ -1594,7 +1591,7 @@ static const char *media_name[] __devinitdata = { } }) -static int __devinit get_esi_asic(struct atm_dev *dev) +static int get_esi_asic(struct atm_dev *dev) { struct eni_dev *eni_dev; unsigned char tonga; @@ -1686,7 +1683,7 @@ static int __devinit get_esi_asic(struct atm_dev *dev) #undef GET_SEPROM -static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base) +static int get_esi_fpga(struct atm_dev *dev, void __iomem *base) { void __iomem *mac_base; int i; @@ -1697,7 +1694,7 @@ static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base) } -static int __devinit eni_do_init(struct atm_dev *dev) +static int eni_do_init(struct atm_dev *dev) { struct midway_eprom __iomem *eprom; struct eni_dev *eni_dev; @@ -1729,15 +1726,17 @@ static int __devinit eni_do_init(struct atm_dev *dev) "mapping\n",dev->number); return error; } + eni_dev->ioaddr = base; eni_dev->base_diff = real_base - (unsigned long) base; /* id may not be present in ASIC Tonga boards - check this @@@ */ if (!eni_dev->asic) { eprom = (base+EPROM_SIZE-sizeof(struct midway_eprom)); if (readl(&eprom->magic) != ENI155_MAGIC) { printk("\n"); - printk(KERN_ERR KERN_ERR DEV_LABEL "(itf %d): bad " - "magic - expected 0x%x, got 0x%x\n",dev->number, - ENI155_MAGIC,(unsigned) readl(&eprom->magic)); + printk(KERN_ERR DEV_LABEL + "(itf %d): bad magic - expected 0x%x, got 0x%x\n", + dev->number, ENI155_MAGIC, + (unsigned)readl(&eprom->magic)); error = -EINVAL; goto unmap; } @@ -1789,8 +1788,16 @@ unmap: goto out; } +static void eni_do_release(struct atm_dev *dev) +{ + struct eni_dev *ed = ENI_DEV(dev); + + dev->phy->stop(dev); + dev->phy = NULL; + iounmap(ed->ioaddr); +} -static int __devinit eni_start(struct atm_dev *dev) +static int eni_start(struct atm_dev *dev) { struct eni_dev *eni_dev; @@ -1873,7 +1880,7 @@ free_list: kfree(eni_dev->free_list); free_irq: - free_irq(eni_dev->irq, eni_dev); + free_irq(eni_dev->irq, dev); out: return error; @@ -1898,7 +1905,6 @@ static void eni_close(struct atm_vcc *vcc) static int eni_open(struct atm_vcc *vcc) { - struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; int error; short vpi = vcc->vpi; @@ -1908,7 +1914,6 @@ static int eni_open(struct atm_vcc *vcc) EVENT("eni_open\n",0,0); if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) vcc->dev_data = NULL; - eni_dev = ENI_DEV(vcc->dev); if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) set_bit(ATM_VF_ADDR,&vcc->flags); if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5) @@ -2088,7 +2093,6 @@ static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr) static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) { - struct hlist_node *node; struct sock *s; static const char *signal[] = { "LOST","unknown","okay" }; struct eni_dev *eni_dev = ENI_DEV(dev); @@ -2166,7 +2170,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) for(i = 0; i < VCC_HTABLE_SIZE; ++i) { struct hlist_head *head = &vcc_hash[i]; - sk_for_each(s, node, head) { + sk_for_each(s, head) { struct eni_vcc *eni_vcc; int length; @@ -2221,65 +2225,83 @@ static const struct atmdev_ops ops = { }; -static int __devinit eni_init_one(struct pci_dev *pci_dev, - const struct pci_device_id *ent) +static int eni_init_one(struct pci_dev *pci_dev, + const struct pci_device_id *ent) { struct atm_dev *dev; struct eni_dev *eni_dev; - int error = -ENOMEM; + struct eni_zero *zero; + int rc; - DPRINTK("eni_init_one\n"); + rc = pci_enable_device(pci_dev); + if (rc < 0) + goto out; - if (pci_enable_device(pci_dev)) { - error = -EIO; - goto out0; - } + rc = -ENOMEM; + eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL); + if (!eni_dev) + goto err_disable; - eni_dev = kmalloc(sizeof(struct eni_dev),GFP_KERNEL); - if (!eni_dev) goto out0; - if (!cpu_zeroes) { - cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE, - &zeroes); - if (!cpu_zeroes) goto out1; - } - dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL); - if (!dev) goto out2; + zero = &eni_dev->zero; + zero->addr = pci_alloc_consistent(pci_dev, ENI_ZEROES_SIZE, &zero->dma); + if (!zero->addr) + goto err_kfree; + + dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL); + if (!dev) + goto err_free_consistent; + + dev->dev_data = eni_dev; pci_set_drvdata(pci_dev, dev); eni_dev->pci_dev = pci_dev; - dev->dev_data = eni_dev; eni_dev->asic = ent->driver_data; - error = eni_do_init(dev); - if (error) goto out3; - error = eni_start(dev); - if (error) goto out3; + + rc = eni_do_init(dev); + if (rc < 0) + goto err_unregister; + + rc = eni_start(dev); + if (rc < 0) + goto err_eni_release; + eni_dev->more = eni_boards; eni_boards = dev; - return 0; -out3: +out: + return rc; + +err_eni_release: + eni_do_release(dev); +err_unregister: atm_dev_deregister(dev); -out2: - pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes); - cpu_zeroes = NULL; -out1: +err_free_consistent: + pci_free_consistent(pci_dev, ENI_ZEROES_SIZE, zero->addr, zero->dma); +err_kfree: kfree(eni_dev); -out0: - return error; +err_disable: + pci_disable_device(pci_dev); + goto out; } static struct pci_device_id eni_pci_tbl[] = { - { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_FPGA, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 0 /* FPGA */ }, - { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 1 /* ASIC */ }, + { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_FPGA), 0 /* FPGA */ }, + { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_ASIC), 1 /* ASIC */ }, { 0, } }; MODULE_DEVICE_TABLE(pci,eni_pci_tbl); -static void __devexit eni_remove_one(struct pci_dev *pci_dev) +static void eni_remove_one(struct pci_dev *pdev) { - /* grrr */ + struct atm_dev *dev = pci_get_drvdata(pdev); + struct eni_dev *ed = ENI_DEV(dev); + struct eni_zero *zero = &ed->zero; + + eni_do_release(dev); + atm_dev_deregister(dev); + pci_free_consistent(pdev, ENI_ZEROES_SIZE, zero->addr, zero->dma); + kfree(ed); + pci_disable_device(pdev); } @@ -2287,7 +2309,7 @@ static struct pci_driver eni_driver = { .name = DEV_LABEL, .id_table = eni_pci_tbl, .probe = eni_init_one, - .remove = __devexit_p(eni_remove_one), + .remove = eni_remove_one, }; diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index e4c9525e60b..565e53a5cb7 100644 --- a/drivers/atm/eni.h +++ b/drivers/atm/eni.h @@ -8,12 +8,13 @@ #include <linux/atm.h> #include <linux/atmdev.h> +#include <linux/interrupt.h> #include <linux/sonet.h> #include <linux/skbuff.h> #include <linux/time.h> #include <linux/pci.h> #include <linux/spinlock.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include "midway.h" @@ -71,6 +72,7 @@ struct eni_dev { u32 events; /* pending events */ /*-------------------------------- base pointers into Midway address space */ + void __iomem *ioaddr; void __iomem *phy; /* PHY interface chip registers */ void __iomem *reg; /* register base */ void __iomem *ram; /* RAM base */ @@ -85,6 +87,10 @@ struct eni_dev { wait_queue_head_t tx_wait; /* for close */ int tx_bw; /* remaining bandwidth */ u32 dma[TX_DMA_BUF*2]; /* DMA request scratch area */ + struct eni_zero { /* aligned "magic" zeroes */ + u32 *addr; + dma_addr_t dma; + } zero; int tx_mult; /* buffer size multiplier (percent) */ /*-------------------------------- RX part */ u32 serv_read; /* host service read index */ diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index cd5049af47a..82f2ae0d7cc 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -44,13 +44,14 @@ #include <linux/ioport.h> /* for request_region */ #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/capability.h> #include <linux/bitops.h> +#include <linux/slab.h> #include <asm/byteorder.h> -#include <asm/system.h> #include <asm/string.h> #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/uaccess.h> #include <linux/wait.h> @@ -251,7 +252,7 @@ struct reginit_item { }; -static struct reginit_item PHY_NTC_INIT[] __devinitdata = { +static struct reginit_item PHY_NTC_INIT[] = { { PHY_CLEARALL, 0x40 }, { 0x12, 0x0001 }, { 0x13, 0x7605 }, @@ -443,8 +444,8 @@ static inline void fs_kfree_skb (struct sk_buff * skb) #define ROUND_NEAREST 3 /********** make rate (not quite as much fun as Horizon) **********/ -static unsigned int make_rate (unsigned int rate, int r, - u16 * bits, unsigned int * actual) +static int make_rate(unsigned int rate, int r, + u16 *bits, unsigned int *actual) { unsigned char exp = -1; /* hush gcc */ unsigned int man = -1; /* hush gcc */ @@ -735,8 +736,8 @@ static void process_txdone_queue (struct fs_dev *dev, struct queue *q) skb = td->skb; if (skb == FS_VCC (ATM_SKB(skb)->vcc)->last_skb) { - wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait); FS_VCC (ATM_SKB(skb)->vcc)->last_skb = NULL; + wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait); } td->dev->ntxpckts--; @@ -1030,7 +1031,7 @@ static int fs_open(struct atm_vcc *atm_vcc) /* We now use the "submit_command" function to submit commands to the firestream. There is a define up near the definition of that routine that switches this routine between immediate write - to the immediate comamnd registers and queuing the commands in + to the immediate command registers and queuing the commands in the HPTXQ for execution. This last technique might be more efficient if we know we're going to submit a whole lot of commands in one go, but this driver is not setup to be able to @@ -1122,7 +1123,7 @@ static void fs_close(struct atm_vcc *atm_vcc) this sleep_on, we'll lose any reference to these packets. Memory leak! On the other hand, it's awfully convenient that we can abort a "close" that is taking too long. Maybe just use non-interruptible sleep on? -- REW */ - interruptible_sleep_on (& vcc->close_wait); + wait_event_interruptible(vcc->close_wait, !vcc->last_skb); } txtp = &atm_vcc->qos.txtp; @@ -1294,7 +1295,7 @@ static const struct atmdev_ops ops = { }; -static void __devinit undocumented_pci_fix (struct pci_dev *pdev) +static void undocumented_pci_fix(struct pci_dev *pdev) { u32 tint; @@ -1318,13 +1319,13 @@ static void __devinit undocumented_pci_fix (struct pci_dev *pdev) * PHY routines * **************************************************************************/ -static void __devinit write_phy (struct fs_dev *dev, int regnum, int val) +static void write_phy(struct fs_dev *dev, int regnum, int val) { submit_command (dev, &dev->hp_txq, QE_CMD_PRP_WR | QE_CMD_IMM_INQ, regnum, val, 0); } -static int __devinit init_phy (struct fs_dev *dev, struct reginit_item *reginit) +static int init_phy(struct fs_dev *dev, struct reginit_item *reginit) { int i; @@ -1380,7 +1381,7 @@ static void reset_chip (struct fs_dev *dev) } } -static void __devinit *aligned_kmalloc (int size, gfp_t flags, int alignment) +static void *aligned_kmalloc(int size, gfp_t flags, int alignment) { void *t; @@ -1397,8 +1398,8 @@ static void __devinit *aligned_kmalloc (int size, gfp_t flags, int alignment) return NULL; } -static int __devinit init_q (struct fs_dev *dev, - struct queue *txq, int queue, int nentries, int is_rq) +static int init_q(struct fs_dev *dev, struct queue *txq, int queue, + int nentries, int is_rq) { int sz = nentries * sizeof (struct FS_QENTRY); struct FS_QENTRY *p; @@ -1433,8 +1434,8 @@ static int __devinit init_q (struct fs_dev *dev, } -static int __devinit init_fp (struct fs_dev *dev, - struct freepool *fp, int queue, int bufsize, int nr_buffers) +static int init_fp(struct fs_dev *dev, struct freepool *fp, int queue, + int bufsize, int nr_buffers) { func_enter (); @@ -1527,7 +1528,7 @@ static void top_off_fp (struct fs_dev *dev, struct freepool *fp, fs_dprintk (FS_DEBUG_QUEUE, "Added %d entries. \n", n); } -static void __devexit free_queue (struct fs_dev *dev, struct queue *txq) +static void free_queue(struct fs_dev *dev, struct queue *txq) { func_enter (); @@ -1543,7 +1544,7 @@ static void __devexit free_queue (struct fs_dev *dev, struct queue *txq) func_exit (); } -static void __devexit free_freepool (struct fs_dev *dev, struct freepool *fp) +static void free_freepool(struct fs_dev *dev, struct freepool *fp) { func_enter (); @@ -1661,7 +1662,7 @@ static void fs_poll (unsigned long data) } #endif -static int __devinit fs_init (struct fs_dev *dev) +static int fs_init(struct fs_dev *dev) { struct pci_dev *pci_dev; int isr, to; @@ -1781,7 +1782,7 @@ static int __devinit fs_init (struct fs_dev *dev) write_fs (dev, RAS0, RAS0_DCD_XHLT | (((1 << FS155_VPI_BITS) - 1) * RAS0_VPSEL) | (((1 << FS155_VCI_BITS) - 1) * RAS0_VCSEL)); - /* We can chose the split arbitarily. We might be able to + /* We can chose the split arbitrarily. We might be able to support more. Whatever. This should do for now. */ dev->atm_dev->ci_range.vpi_bits = FS155_VPI_BITS; dev->atm_dev->ci_range.vci_bits = FS155_VCI_BITS; @@ -1896,8 +1897,8 @@ unmap: return 1; } -static int __devinit firestream_init_one (struct pci_dev *pci_dev, - const struct pci_device_id *ent) +static int firestream_init_one(struct pci_dev *pci_dev, + const struct pci_device_id *ent) { struct atm_dev *atm_dev; struct fs_dev *fs_dev; @@ -1910,7 +1911,7 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev, fs_dev, sizeof (struct fs_dev)); if (!fs_dev) goto err_out; - atm_dev = atm_dev_register("fs", &ops, -1, NULL); + atm_dev = atm_dev_register("fs", &pci_dev->dev, &ops, -1, NULL); if (!atm_dev) goto err_out_free_fs_dev; @@ -1933,7 +1934,7 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev, return -ENODEV; } -static void __devexit firestream_remove_one (struct pci_dev *pdev) +static void firestream_remove_one(struct pci_dev *pdev) { int i; struct fs_dev *dev, *nxtdev; @@ -1999,7 +2000,7 @@ static void __devexit firestream_remove_one (struct pci_dev *pdev) fs_dprintk (FS_DEBUG_CLEANUP, "Freeing irq%d.\n", dev->irq); free_irq (dev->irq, dev); - del_timer (&dev->timer); + del_timer_sync (&dev->timer); atm_dev_deregister(dev->atm_dev); free_queue (dev, &dev->hp_txq); @@ -2026,10 +2027,8 @@ static void __devexit firestream_remove_one (struct pci_dev *pdev) } static struct pci_device_id firestream_pci_tbl[] = { - { PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS50}, - { PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS155}, + { PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50), FS_IS50}, + { PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155), FS_IS155}, { 0, } }; @@ -2039,7 +2038,7 @@ static struct pci_driver firestream_driver = { .name = "firestream", .id_table = firestream_pci_tbl, .probe = firestream_init_one, - .remove = __devexit_p(firestream_remove_one), + .remove = firestream_remove_one, }; static int __init firestream_init_module (void) diff --git a/drivers/atm/firestream.h b/drivers/atm/firestream.h index 49e783e35ee..364eded3188 100644 --- a/drivers/atm/firestream.h +++ b/drivers/atm/firestream.h @@ -420,7 +420,6 @@ struct fs_transmit_config { #define RC_FLAGS_BFPS_BFP27 (0xd << 17) #define RC_FLAGS_BFPS_BFP47 (0xe << 17) -#define RC_FLAGS_BFPS (0x1 << 17) #define RC_FLAGS_BFPP (0x1 << 21) #define RC_FLAGS_TEVC (0x1 << 22) #define RC_FLAGS_TEP (0x1 << 23) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index bc53fed89b1..d4725fc0395 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -44,7 +44,7 @@ #include <asm/dma.h> #include <asm/byteorder.h> #include <asm/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #ifdef CONFIG_SBUS #include <linux/of.h> @@ -92,7 +92,7 @@ #define FORE200E_INDEX(virt_addr, type, index) (&((type *)(virt_addr))[ index ]) -#define FORE200E_NEXT_ENTRY(index, modulo) (index = ++(index) % (modulo)) +#define FORE200E_NEXT_ENTRY(index, modulo) (index = ((index) + 1) % (modulo)) #if 1 #define ASSERT(expr) if (!(expr)) { \ @@ -527,8 +527,7 @@ fore200e_pca_reset(struct fore200e* fore200e) } -static int __devinit -fore200e_pca_map(struct fore200e* fore200e) +static int fore200e_pca_map(struct fore200e* fore200e) { DPRINTK(2, "device %s being mapped in memory\n", fore200e->name); @@ -561,8 +560,7 @@ fore200e_pca_unmap(struct fore200e* fore200e) } -static int __devinit -fore200e_pca_configure(struct fore200e* fore200e) +static int fore200e_pca_configure(struct fore200e *fore200e) { struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev; u8 master_ctrl, latency; @@ -674,7 +672,7 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; u32 dma_addr; dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); @@ -687,7 +685,7 @@ static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction); @@ -697,7 +695,7 @@ static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); @@ -706,7 +704,7 @@ static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_add static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); @@ -719,7 +717,7 @@ static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, int size, int nbr, int alignment) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; chunk->alloc_size = chunk->align_size = size * nbr; @@ -738,7 +736,7 @@ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk /* free a DVMA consistent chunk of memory */ static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; dma_free_coherent(&op->dev, chunk->alloc_size, chunk->alloc_addr, chunk->dma_addr); @@ -770,7 +768,7 @@ static void fore200e_sba_reset(struct fore200e *fore200e) static int __init fore200e_sba_map(struct fore200e *fore200e) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; unsigned int bursts; /* gain access to the SBA specific registers */ @@ -789,7 +787,7 @@ static int __init fore200e_sba_map(struct fore200e *fore200e) fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */ /* get the supported DVMA burst sizes */ - bursts = of_getintprop_default(op->node->parent, "burst-sizes", 0x00); + bursts = of_getintprop_default(op->dev.of_node->parent, "burst-sizes", 0x00); if (sbus_can_dma_64bit()) sbus_set_sbus64(&op->dev, bursts); @@ -800,7 +798,7 @@ static int __init fore200e_sba_map(struct fore200e *fore200e) static void fore200e_sba_unmap(struct fore200e *fore200e) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); @@ -816,35 +814,37 @@ static int __init fore200e_sba_configure(struct fore200e *fore200e) static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; const u8 *prop; int len; - prop = of_get_property(op->node, "madaddrlo2", &len); + prop = of_get_property(op->dev.of_node, "madaddrlo2", &len); if (!prop) return -ENODEV; memcpy(&prom->mac_addr[4], prop, 4); - prop = of_get_property(op->node, "madaddrhi4", &len); + prop = of_get_property(op->dev.of_node, "madaddrhi4", &len); if (!prop) return -ENODEV; memcpy(&prom->mac_addr[2], prop, 4); - prom->serial_number = of_getintprop_default(op->node, "serialnumber", 0); - prom->hw_revision = of_getintprop_default(op->node, "promversion", 0); + prom->serial_number = of_getintprop_default(op->dev.of_node, + "serialnumber", 0); + prom->hw_revision = of_getintprop_default(op->dev.of_node, + "promversion", 0); return 0; } static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; const struct linux_prom_registers *regs; - regs = of_get_property(op->node, "reg", NULL); + regs = of_get_property(op->dev.of_node, "reg", NULL); return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", - (regs ? regs->which_io : 0), op->node->name); + (regs ? regs->which_io : 0), op->dev.of_node->name); } #endif /* CONFIG_SBUS */ @@ -2026,8 +2026,7 @@ fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags) } -static int __devinit -fore200e_irq_request(struct fore200e* fore200e) +static int fore200e_irq_request(struct fore200e *fore200e) { if (request_irq(fore200e->irq, fore200e_interrupt, IRQF_SHARED, fore200e->name, fore200e->atm_dev) < 0) { @@ -2049,8 +2048,7 @@ fore200e_irq_request(struct fore200e* fore200e) } -static int __devinit -fore200e_get_esi(struct fore200e* fore200e) +static int fore200e_get_esi(struct fore200e *fore200e) { struct prom_data* prom = kzalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA); int ok, i; @@ -2064,12 +2062,10 @@ fore200e_get_esi(struct fore200e* fore200e) return -EBUSY; } - printk(FORE200E "device %s, rev. %c, S/N: %d, ESI: %02x:%02x:%02x:%02x:%02x:%02x\n", + printk(FORE200E "device %s, rev. %c, S/N: %d, ESI: %pM\n", fore200e->name, (prom->hw_revision & 0xFF) + '@', /* probably meaningless with SBA boards */ - prom->serial_number & 0xFFFF, - prom->mac_addr[ 2 ], prom->mac_addr[ 3 ], prom->mac_addr[ 4 ], - prom->mac_addr[ 5 ], prom->mac_addr[ 6 ], prom->mac_addr[ 7 ]); + prom->serial_number & 0xFFFF, &prom->mac_addr[2]); for (i = 0; i < ESI_LEN; i++) { fore200e->esi[ i ] = fore200e->atm_dev->esi[ i ] = prom->mac_addr[ i + 2 ]; @@ -2081,8 +2077,7 @@ fore200e_get_esi(struct fore200e* fore200e) } -static int __devinit -fore200e_alloc_rx_buf(struct fore200e* fore200e) +static int fore200e_alloc_rx_buf(struct fore200e *fore200e) { int scheme, magn, nbr, size, i; @@ -2146,8 +2141,7 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e) } -static int __devinit -fore200e_init_bs_queue(struct fore200e* fore200e) +static int fore200e_init_bs_queue(struct fore200e *fore200e) { int scheme, magn, i; @@ -2209,8 +2203,7 @@ fore200e_init_bs_queue(struct fore200e* fore200e) } -static int __devinit -fore200e_init_rx_queue(struct fore200e* fore200e) +static int fore200e_init_rx_queue(struct fore200e *fore200e) { struct host_rxq* rxq = &fore200e->host_rxq; struct cp_rxq_entry __iomem * cp_entry; @@ -2269,8 +2262,7 @@ fore200e_init_rx_queue(struct fore200e* fore200e) } -static int __devinit -fore200e_init_tx_queue(struct fore200e* fore200e) +static int fore200e_init_tx_queue(struct fore200e *fore200e) { struct host_txq* txq = &fore200e->host_txq; struct cp_txq_entry __iomem * cp_entry; @@ -2332,8 +2324,7 @@ fore200e_init_tx_queue(struct fore200e* fore200e) } -static int __devinit -fore200e_init_cmd_queue(struct fore200e* fore200e) +static int fore200e_init_cmd_queue(struct fore200e *fore200e) { struct host_cmdq* cmdq = &fore200e->host_cmdq; struct cp_cmdq_entry __iomem * cp_entry; @@ -2374,10 +2365,10 @@ fore200e_init_cmd_queue(struct fore200e* fore200e) } -static void __devinit -fore200e_param_bs_queue(struct fore200e* fore200e, - enum buffer_scheme scheme, enum buffer_magn magn, - int queue_length, int pool_size, int supply_blksize) +static void fore200e_param_bs_queue(struct fore200e *fore200e, + enum buffer_scheme scheme, + enum buffer_magn magn, int queue_length, + int pool_size, int supply_blksize) { struct bs_spec __iomem * bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ]; @@ -2388,8 +2379,7 @@ fore200e_param_bs_queue(struct fore200e* fore200e, } -static int __devinit -fore200e_initialize(struct fore200e* fore200e) +static int fore200e_initialize(struct fore200e *fore200e) { struct cp_queues __iomem * cpq; int ok, scheme, magn; @@ -2440,8 +2430,7 @@ fore200e_initialize(struct fore200e* fore200e) } -static void __devinit -fore200e_monitor_putc(struct fore200e* fore200e, char c) +static void fore200e_monitor_putc(struct fore200e *fore200e, char c) { struct cp_monitor __iomem * monitor = fore200e->cp_monitor; @@ -2452,8 +2441,7 @@ fore200e_monitor_putc(struct fore200e* fore200e, char c) } -static int __devinit -fore200e_monitor_getc(struct fore200e* fore200e) +static int fore200e_monitor_getc(struct fore200e *fore200e) { struct cp_monitor __iomem * monitor = fore200e->cp_monitor; unsigned long timeout = jiffies + msecs_to_jiffies(50); @@ -2477,8 +2465,7 @@ fore200e_monitor_getc(struct fore200e* fore200e) } -static void __devinit -fore200e_monitor_puts(struct fore200e* fore200e, char* str) +static void fore200e_monitor_puts(struct fore200e *fore200e, char *str) { while (*str) { @@ -2497,8 +2484,7 @@ fore200e_monitor_puts(struct fore200e* fore200e, char* str) #define FW_EXT "_ecd.bin2" #endif -static int __devinit -fore200e_load_and_start_fw(struct fore200e* fore200e) +static int fore200e_load_and_start_fw(struct fore200e *fore200e) { const struct firmware *firmware; struct device *device; @@ -2513,7 +2499,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) device = &((struct pci_dev *) fore200e->bus_dev)->dev; #ifdef CONFIG_SBUS else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) - device = &((struct of_device *) fore200e->bus_dev)->dev; + device = &((struct platform_device *) fore200e->bus_dev)->dev; #endif else return err; @@ -2566,15 +2552,14 @@ release: } -static int __devinit -fore200e_register(struct fore200e* fore200e) +static int fore200e_register(struct fore200e *fore200e, struct device *parent) { struct atm_dev* atm_dev; DPRINTK(2, "device %s being registered\n", fore200e->name); - atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1, - NULL); + atm_dev = atm_dev_register(fore200e->bus->proc_name, parent, &fore200e_ops, + -1, NULL); if (atm_dev == NULL) { printk(FORE200E "unable to register device %s\n", fore200e->name); return -ENODEV; @@ -2593,10 +2578,9 @@ fore200e_register(struct fore200e* fore200e) } -static int __devinit -fore200e_init(struct fore200e* fore200e) +static int fore200e_init(struct fore200e *fore200e, struct device *parent) { - if (fore200e_register(fore200e) < 0) + if (fore200e_register(fore200e, parent) < 0) return -ENODEV; if (fore200e->bus->configure(fore200e) < 0) @@ -2643,26 +2627,32 @@ fore200e_init(struct fore200e* fore200e) } #ifdef CONFIG_SBUS -static int __devinit fore200e_sba_probe(struct of_device *op, - const struct of_device_id *match) +static const struct of_device_id fore200e_sba_match[]; +static int fore200e_sba_probe(struct platform_device *op) { - const struct fore200e_bus *bus = match->data; + const struct of_device_id *match; + const struct fore200e_bus *bus; struct fore200e *fore200e; static int index = 0; int err; + match = of_match_device(fore200e_sba_match, &op->dev); + if (!match) + return -EINVAL; + bus = match->data; + fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL); if (!fore200e) return -ENOMEM; fore200e->bus = bus; fore200e->bus_dev = op; - fore200e->irq = op->irqs[0]; + fore200e->irq = op->archdata.irqs[0]; fore200e->phys_base = op->resource[0].start; sprintf(fore200e->name, "%s-%d", bus->model_name, index); - err = fore200e_init(fore200e); + err = fore200e_init(fore200e, &op->dev); if (err < 0) { fore200e_shutdown(fore200e); kfree(fore200e); @@ -2675,7 +2665,7 @@ static int __devinit fore200e_sba_probe(struct of_device *op, return 0; } -static int __devexit fore200e_sba_remove(struct of_device *op) +static int fore200e_sba_remove(struct platform_device *op) { struct fore200e *fore200e = dev_get_drvdata(&op->dev); @@ -2694,17 +2684,20 @@ static const struct of_device_id fore200e_sba_match[] = { }; MODULE_DEVICE_TABLE(of, fore200e_sba_match); -static struct of_platform_driver fore200e_sba_driver = { - .name = "fore_200e", - .match_table = fore200e_sba_match, +static struct platform_driver fore200e_sba_driver = { + .driver = { + .name = "fore_200e", + .owner = THIS_MODULE, + .of_match_table = fore200e_sba_match, + }, .probe = fore200e_sba_probe, - .remove = __devexit_p(fore200e_sba_remove), + .remove = fore200e_sba_remove, }; #endif #ifdef CONFIG_PCI -static int __devinit -fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +static int fore200e_pca_detect(struct pci_dev *pci_dev, + const struct pci_device_id *pci_ent) { const struct fore200e_bus* bus = (struct fore200e_bus*) pci_ent->driver_data; struct fore200e* fore200e; @@ -2737,7 +2730,7 @@ fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent sprintf(fore200e->name, "%s-%d", bus->model_name, index); - err = fore200e_init(fore200e); + err = fore200e_init(fore200e, &pci_dev->dev); if (err < 0) { fore200e_shutdown(fore200e); goto out_free; @@ -2757,7 +2750,7 @@ out_disable: } -static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev) +static void fore200e_pca_remove_one(struct pci_dev *pci_dev) { struct fore200e *fore200e; @@ -2780,19 +2773,19 @@ MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl); static struct pci_driver fore200e_pca_driver = { .name = "fore_200e", .probe = fore200e_pca_detect, - .remove = __devexit_p(fore200e_pca_remove_one), + .remove = fore200e_pca_remove_one, .id_table = fore200e_pca_tbl, }; #endif static int __init fore200e_module_init(void) { - int err; + int err = 0; printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n"); #ifdef CONFIG_SBUS - err = of_register_driver(&fore200e_sba_driver, &of_bus_type); + err = platform_driver_register(&fore200e_sba_driver); if (err) return err; #endif @@ -2803,7 +2796,7 @@ static int __init fore200e_module_init(void) #ifdef CONFIG_SBUS if (err) - of_unregister_driver(&fore200e_sba_driver); + platform_driver_unregister(&fore200e_sba_driver); #endif return err; @@ -2815,7 +2808,7 @@ static void __exit fore200e_module_cleanup(void) pci_unregister_driver(&fore200e_pca_driver); #endif #ifdef CONFIG_SBUS - of_unregister_driver(&fore200e_sba_driver); + platform_driver_unregister(&fore200e_sba_driver); #endif } @@ -2845,13 +2838,12 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) " interrupt line:\t\t%s\n" " physical base address:\t0x%p\n" " virtual base address:\t0x%p\n" - " factory address (ESI):\t%02x:%02x:%02x:%02x:%02x:%02x\n" + " factory address (ESI):\t%pM\n" " board serial number:\t\t%d\n\n", fore200e_irq_itoa(fore200e->irq), (void*)fore200e->phys_base, fore200e->virt_base, - fore200e->esi[0], fore200e->esi[1], fore200e->esi[2], - fore200e->esi[3], fore200e->esi[4], fore200e->esi[5], + fore200e->esi, fore200e->esi[4] * 256 + fore200e->esi[5]); return len; diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index 7f97c09aaea..ba34a02b717 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -263,7 +263,7 @@ typedef enum opcode { } opcode_t; -/* virtual path / virtual channel identifers */ +/* virtual path / virtual channel identifiers */ typedef struct vpvc { BITFIELD3( @@ -926,7 +926,7 @@ typedef struct fore200e_vcc { #define PCA200E_PCI_LATENCY 0x40 /* maximum slave latenty */ #define PCA200E_PCI_MASTER_CTRL 0x41 /* master control */ -#define PCA200E_PCI_THRESHOLD 0x42 /* burst / continous req threshold */ +#define PCA200E_PCI_THRESHOLD 0x42 /* burst / continuous req threshold */ /* PBI master control register */ diff --git a/drivers/atm/he.c b/drivers/atm/he.c index e8c6529dc36..aa6be269866 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -67,6 +67,8 @@ #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> +#include <linux/bitmap.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/byteorder.h> #include <asm/uaccess.h> @@ -110,12 +112,12 @@ static u8 read_prom_byte(struct he_dev *he_dev, int addr); /* globals */ static struct he_dev *he_devs; -static int disable64; +static bool disable64; static short nvpibits = -1; static short nvcibits = -1; static short rx_skb_reserve = 16; -static int irq_coalesce = 1; -static int sdh = 0; +static bool irq_coalesce = 1; +static bool sdh = 0; /* Read from EEPROM = 0000 0011b */ static unsigned int readtab[] = { @@ -327,7 +329,6 @@ __find_vcc(struct he_dev *he_dev, unsigned cid) { struct hlist_head *head; struct atm_vcc *vcc; - struct hlist_node *node; struct sock *s; short vpi; int vci; @@ -336,7 +337,7 @@ __find_vcc(struct he_dev *he_dev, unsigned cid) vci = cid & ((1 << he_dev->vcibits) - 1); head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)]; - sk_for_each(s, node, head) { + sk_for_each(s, head) { vcc = atm_sk(s); if (vcc->dev == he_dev->atm_dev && vcc->vci == vci && vcc->vpi == vpi && @@ -347,8 +348,8 @@ __find_vcc(struct he_dev *he_dev, unsigned cid) return NULL; } -static int __devinit -he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +static int he_init_one(struct pci_dev *pci_dev, + const struct pci_device_id *pci_ent) { struct atm_dev *atm_dev = NULL; struct he_dev *he_dev = NULL; @@ -364,7 +365,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) goto init_one_failure; } - atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, NULL); + atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &he_ops, -1, NULL); if (!atm_dev) { err = -ENODEV; goto init_one_failure; @@ -404,8 +405,7 @@ init_one_failure: return err; } -static void __devexit -he_remove_one (struct pci_dev *pci_dev) +static void he_remove_one(struct pci_dev *pci_dev) { struct atm_dev *atm_dev; struct he_dev *he_dev; @@ -419,7 +419,6 @@ he_remove_one (struct pci_dev *pci_dev) atm_dev_deregister(atm_dev); kfree(he_dev); - pci_set_drvdata(pci_dev, NULL); pci_disable_device(pci_dev); } @@ -443,8 +442,7 @@ rate_to_atmf(unsigned rate) /* cps to atm forum format */ return (NONZERO | (exp << 9) | (rate & 0x1ff)); } -static void __devinit -he_init_rx_lbfp0(struct he_dev *he_dev) +static void he_init_rx_lbfp0(struct he_dev *he_dev) { unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; @@ -474,8 +472,7 @@ he_init_rx_lbfp0(struct he_dev *he_dev) he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C); } -static void __devinit -he_init_rx_lbfp1(struct he_dev *he_dev) +static void he_init_rx_lbfp1(struct he_dev *he_dev) { unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; @@ -505,8 +502,7 @@ he_init_rx_lbfp1(struct he_dev *he_dev) he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C); } -static void __devinit -he_init_tx_lbfp(struct he_dev *he_dev) +static void he_init_tx_lbfp(struct he_dev *he_dev) { unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; @@ -535,8 +531,7 @@ he_init_tx_lbfp(struct he_dev *he_dev) he_writel(he_dev, lbufd_index - 1, TLBF_T); } -static int __devinit -he_init_tpdrq(struct he_dev *he_dev) +static int he_init_tpdrq(struct he_dev *he_dev) { he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev, CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys); @@ -557,8 +552,7 @@ he_init_tpdrq(struct he_dev *he_dev) return 0; } -static void __devinit -he_init_cs_block(struct he_dev *he_dev) +static void he_init_cs_block(struct he_dev *he_dev) { unsigned clock, rate, delta; int reg; @@ -653,8 +647,7 @@ he_init_cs_block(struct he_dev *he_dev) } -static int __devinit -he_init_cs_block_rcm(struct he_dev *he_dev) +static int he_init_cs_block_rcm(struct he_dev *he_dev) { unsigned (*rategrid)[16][16]; unsigned rate, delta; @@ -774,64 +767,41 @@ he_init_cs_block_rcm(struct he_dev *he_dev) return 0; } -static int __devinit -he_init_group(struct he_dev *he_dev, int group) +static int he_init_group(struct he_dev *he_dev, int group) { + struct he_buff *heb, *next; + dma_addr_t mapping; int i; - /* small buffer pool */ - he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev, - CONFIG_RBPS_BUFSIZE, 8, 0); - if (he_dev->rbps_pool == NULL) { - hprintk("unable to create rbps pages\n"); + he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), + G0_RBPS_BS + (group * 32)); + + /* bitmap table */ + he_dev->rbpl_table = kmalloc(BITS_TO_LONGS(RBPL_TABLE_SIZE) + * sizeof(unsigned long), GFP_KERNEL); + if (!he_dev->rbpl_table) { + hprintk("unable to allocate rbpl bitmap table\n"); return -ENOMEM; } + bitmap_zero(he_dev->rbpl_table, RBPL_TABLE_SIZE); - he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, - CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); - if (he_dev->rbps_base == NULL) { - hprintk("failed to alloc rbps_base\n"); - goto out_destroy_rbps_pool; + /* rbpl_virt 64-bit pointers */ + he_dev->rbpl_virt = kmalloc(RBPL_TABLE_SIZE + * sizeof(struct he_buff *), GFP_KERNEL); + if (!he_dev->rbpl_virt) { + hprintk("unable to allocate rbpl virt table\n"); + goto out_free_rbpl_table; } - memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); - he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); - if (he_dev->rbps_virt == NULL) { - hprintk("failed to alloc rbps_virt\n"); - goto out_free_rbps_base; - } - - for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { - dma_addr_t dma_handle; - void *cpuaddr; - - cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle); - if (cpuaddr == NULL) - goto out_free_rbps_virt; - - he_dev->rbps_virt[i].virt = cpuaddr; - he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); - he_dev->rbps_base[i].phys = dma_handle; - - } - he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE - 1]; - - he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32)); - he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), - G0_RBPS_T + (group * 32)); - he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4, - G0_RBPS_BS + (group * 32)); - he_writel(he_dev, - RBP_THRESH(CONFIG_RBPS_THRESH) | - RBP_QSIZE(CONFIG_RBPS_SIZE - 1) | - RBP_INT_ENB, - G0_RBPS_QI + (group * 32)); /* large buffer pool */ he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev, - CONFIG_RBPL_BUFSIZE, 8, 0); + CONFIG_RBPL_BUFSIZE, 64, 0); if (he_dev->rbpl_pool == NULL) { hprintk("unable to create rbpl pool\n"); - goto out_free_rbps_virt; + goto out_free_rbpl_virt; } he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, @@ -841,30 +811,29 @@ he_init_group(struct he_dev *he_dev, int group) goto out_destroy_rbpl_pool; } memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); - he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); - if (he_dev->rbpl_virt == NULL) { - hprintk("failed to alloc rbpl_virt\n"); - goto out_free_rbpl_base; - } + + INIT_LIST_HEAD(&he_dev->rbpl_outstanding); for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { - dma_addr_t dma_handle; - void *cpuaddr; - cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle); - if (cpuaddr == NULL) - goto out_free_rbpl_virt; + heb = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &mapping); + if (!heb) + goto out_free_rbpl; + heb->mapping = mapping; + list_add(&heb->entry, &he_dev->rbpl_outstanding); - he_dev->rbpl_virt[i].virt = cpuaddr; - he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); - he_dev->rbpl_base[i].phys = dma_handle; + set_bit(i, he_dev->rbpl_table); + he_dev->rbpl_virt[i] = heb; + he_dev->rbpl_hint = i + 1; + he_dev->rbpl_base[i].idx = i << RBP_IDX_OFFSET; + he_dev->rbpl_base[i].phys = mapping + offsetof(struct he_buff, data); } he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE - 1]; he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32)); he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T + (group * 32)); - he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4, + he_writel(he_dev, (CONFIG_RBPL_BUFSIZE - sizeof(struct he_buff))/4, G0_RBPL_BS + (group * 32)); he_writel(he_dev, RBP_THRESH(CONFIG_RBPL_THRESH) | @@ -878,7 +847,7 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); if (he_dev->rbrq_base == NULL) { hprintk("failed to allocate rbrq\n"); - goto out_free_rbpl_virt; + goto out_free_rbpl; } memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); @@ -919,38 +888,24 @@ out_free_rbpq_base: pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), he_dev->rbrq_base, he_dev->rbrq_phys); - i = CONFIG_RBPL_SIZE; -out_free_rbpl_virt: - while (i--) - pci_pool_free(he_dev->rbpl_pool, he_dev->rbpl_virt[i].virt, - he_dev->rbpl_base[i].phys); - kfree(he_dev->rbpl_virt); +out_free_rbpl: + list_for_each_entry_safe(heb, next, &he_dev->rbpl_outstanding, entry) + pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping); -out_free_rbpl_base: pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys); out_destroy_rbpl_pool: pci_pool_destroy(he_dev->rbpl_pool); +out_free_rbpl_virt: + kfree(he_dev->rbpl_virt); +out_free_rbpl_table: + kfree(he_dev->rbpl_table); - i = CONFIG_RBPS_SIZE; -out_free_rbps_virt: - while (i--) - pci_pool_free(he_dev->rbps_pool, he_dev->rbps_virt[i].virt, - he_dev->rbps_base[i].phys); - kfree(he_dev->rbps_virt); - -out_free_rbps_base: - pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * - sizeof(struct he_rbp), he_dev->rbps_base, - he_dev->rbps_phys); -out_destroy_rbps_pool: - pci_pool_destroy(he_dev->rbps_pool); return -ENOMEM; } -static int __devinit -he_init_irq(struct he_dev *he_dev) +static int he_init_irq(struct he_dev *he_dev) { int i; @@ -1001,7 +956,8 @@ 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, IRQF_DISABLED|IRQF_SHARED, DEV_LABEL, he_dev)) { + if (request_irq(he_dev->pci_dev->irq, + he_irq_handler, IRQF_SHARED, DEV_LABEL, he_dev)) { hprintk("irq %d already in use\n", he_dev->pci_dev->irq); return -EINVAL; } @@ -1011,8 +967,7 @@ he_init_irq(struct he_dev *he_dev) return 0; } -static int __devinit -he_start(struct atm_dev *dev) +static int he_start(struct atm_dev *dev) { struct he_dev *he_dev; struct pci_dev *pci_dev; @@ -1099,7 +1054,7 @@ he_start(struct atm_dev *dev) he_writel(he_dev, 0x0, RESET_CNTL); he_writel(he_dev, 0xff, RESET_CNTL); - udelay(16*1000); /* 16 ms */ + msleep(16); /* 16 ms */ status = he_readl(he_dev, RESET_CNTL); if ((status & BOARD_RST_STATUS) == 0) { hprintk("reset failed\n"); @@ -1132,15 +1087,8 @@ he_start(struct atm_dev *dev) for (i = 0; i < 6; ++i) dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i); - hprintk("%s%s, %x:%x:%x:%x:%x:%x\n", - he_dev->prod_id, - he_dev->media & 0x40 ? "SM" : "MM", - dev->esi[0], - dev->esi[1], - dev->esi[2], - dev->esi[3], - dev->esi[4], - dev->esi[5]); + hprintk("%s%s, %pM\n", he_dev->prod_id, + he_dev->media & 0x40 ? "SM" : "MM", dev->esi); he_dev->atm_dev->link_rate = he_is622(he_dev) ? ATM_OC12_PCR : ATM_OC3_PCR; @@ -1575,9 +1523,10 @@ he_start(struct atm_dev *dev) static void he_stop(struct he_dev *he_dev) { - u16 command; - u32 gen_cntl_0, reg; + struct he_buff *heb, *next; struct pci_dev *pci_dev; + u32 gen_cntl_0, reg; + u16 command; pci_dev = he_dev->pci_dev; @@ -1618,37 +1567,19 @@ he_stop(struct he_dev *he_dev) he_dev->hsp, he_dev->hsp_phys); if (he_dev->rbpl_base) { - int i; - - for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { - void *cpuaddr = he_dev->rbpl_virt[i].virt; - dma_addr_t dma_handle = he_dev->rbpl_base[i].phys; + list_for_each_entry_safe(heb, next, &he_dev->rbpl_outstanding, entry) + pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping); - pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle); - } pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys); } + kfree(he_dev->rbpl_virt); + kfree(he_dev->rbpl_table); + if (he_dev->rbpl_pool) pci_pool_destroy(he_dev->rbpl_pool); - if (he_dev->rbps_base) { - int i; - - for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { - void *cpuaddr = he_dev->rbps_virt[i].virt; - dma_addr_t dma_handle = he_dev->rbps_base[i].phys; - - pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle); - } - pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE - * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys); - } - - if (he_dev->rbps_pool) - pci_pool_destroy(he_dev->rbps_pool); - if (he_dev->rbrq_base) pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), he_dev->rbrq_base, he_dev->rbrq_phys); @@ -1678,13 +1609,13 @@ static struct he_tpd * __alloc_tpd(struct he_dev *he_dev) { struct he_tpd *tpd; - dma_addr_t dma_handle; + dma_addr_t mapping; - tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &dma_handle); + tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &mapping); if (tpd == NULL) return NULL; - tpd->status = TPD_ADDR(dma_handle); + tpd->status = TPD_ADDR(mapping); tpd->reserved = 0; tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0; tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0; @@ -1713,13 +1644,12 @@ he_service_rbrq(struct he_dev *he_dev, int group) struct he_rbrq *rbrq_tail = (struct he_rbrq *) ((unsigned long)he_dev->rbrq_base | he_dev->hsp->group[group].rbrq_tail); - struct he_rbp *rbp = NULL; unsigned cid, lastcid = -1; - unsigned buf_len = 0; struct sk_buff *skb; struct atm_vcc *vcc = NULL; struct he_vcc *he_vcc; - struct he_iovec *iov; + struct he_buff *heb, *next; + int i; int pdus_assembled = 0; int updated = 0; @@ -1739,44 +1669,35 @@ he_service_rbrq(struct he_dev *he_dev, int group) RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "", RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : ""); - if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF) - rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; - else - rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; - - buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; - cid = RBRQ_CID(he_dev->rbrq_head); + i = RBRQ_ADDR(he_dev->rbrq_head) >> RBP_IDX_OFFSET; + heb = he_dev->rbpl_virt[i]; + cid = RBRQ_CID(he_dev->rbrq_head); if (cid != lastcid) vcc = __find_vcc(he_dev, cid); lastcid = cid; - if (vcc == NULL) { - hprintk("vcc == NULL (cid 0x%x)\n", cid); - if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) - rbp->status &= ~RBP_LOANED; + if (vcc == NULL || (he_vcc = HE_VCC(vcc)) == NULL) { + hprintk("vcc/he_vcc == NULL (cid 0x%x)\n", cid); + if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) { + clear_bit(i, he_dev->rbpl_table); + list_del(&heb->entry); + pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping); + } goto next_rbrq_entry; } - he_vcc = HE_VCC(vcc); - if (he_vcc == NULL) { - hprintk("he_vcc == NULL (cid 0x%x)\n", cid); - if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) - rbp->status &= ~RBP_LOANED; - goto next_rbrq_entry; - } - if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) { hprintk("HBUF_ERR! (cid 0x%x)\n", cid); atomic_inc(&vcc->stats->rx_drop); goto return_host_buffers; } - he_vcc->iov_tail->iov_base = RBRQ_ADDR(he_dev->rbrq_head); - he_vcc->iov_tail->iov_len = buf_len; - he_vcc->pdu_len += buf_len; - ++he_vcc->iov_tail; + heb->len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; + clear_bit(i, he_dev->rbpl_table); + list_move_tail(&heb->entry, &he_vcc->buffers); + he_vcc->pdu_len += heb->len; if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) { lastcid = -1; @@ -1785,12 +1706,6 @@ he_service_rbrq(struct he_dev *he_dev, int group) goto return_host_buffers; } -#ifdef notdef - if ((he_vcc->iov_tail - he_vcc->iov_head) > HE_MAXIOV) { - hprintk("iovec full! cid 0x%x\n", cid); - goto return_host_buffers; - } -#endif if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry; @@ -1818,15 +1733,8 @@ he_service_rbrq(struct he_dev *he_dev, int group) __net_timestamp(skb); - for (iov = he_vcc->iov_head; - iov < he_vcc->iov_tail; ++iov) { - if (iov->iov_base & RBP_SMALLBUF) - memcpy(skb_put(skb, iov->iov_len), - he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); - else - memcpy(skb_put(skb, iov->iov_len), - he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); - } + list_for_each_entry(heb, &he_vcc->buffers, entry) + memcpy(skb_put(skb, heb->len), &heb->data, heb->len); switch (vcc->qos.aal) { case ATM_AAL0: @@ -1866,23 +1774,15 @@ he_service_rbrq(struct he_dev *he_dev, int group) return_host_buffers: ++pdus_assembled; - for (iov = he_vcc->iov_head; - iov < he_vcc->iov_tail; ++iov) { - if (iov->iov_base & RBP_SMALLBUF) - rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)]; - else - rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)]; - - rbp->status &= ~RBP_LOANED; - } - - he_vcc->iov_tail = he_vcc->iov_head; + list_for_each_entry_safe(heb, next, &he_vcc->buffers, entry) + pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping); + INIT_LIST_HEAD(&he_vcc->buffers); he_vcc->pdu_len = 0; next_rbrq_entry: he_dev->rbrq_head = (struct he_rbrq *) ((unsigned long) he_dev->rbrq_base | - RBRQ_MASK(++he_dev->rbrq_head)); + RBRQ_MASK(he_dev->rbrq_head + 1)); } read_unlock(&vcc_sklist_lock); @@ -1965,7 +1865,7 @@ next_tbrq_entry: pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); he_dev->tbrq_head = (struct he_tbrq *) ((unsigned long) he_dev->tbrq_base | - TBRQ_MASK(++he_dev->tbrq_head)); + TBRQ_MASK(he_dev->tbrq_head + 1)); } if (updated) { @@ -1977,59 +1877,51 @@ next_tbrq_entry: } } - static void he_service_rbpl(struct he_dev *he_dev, int group) { - struct he_rbp *newtail; + struct he_rbp *new_tail; struct he_rbp *rbpl_head; + struct he_buff *heb; + dma_addr_t mapping; + int i; int moved = 0; rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | RBPL_MASK(he_readl(he_dev, G0_RBPL_S))); for (;;) { - newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | + new_tail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | RBPL_MASK(he_dev->rbpl_tail+1)); /* table 3.42 -- rbpl_tail should never be set to rbpl_head */ - if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED)) + if (new_tail == rbpl_head) break; - newtail->status |= RBP_LOANED; - he_dev->rbpl_tail = newtail; - ++moved; - } - - if (moved) - he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T); -} - -static void -he_service_rbps(struct he_dev *he_dev, int group) -{ - struct he_rbp *newtail; - struct he_rbp *rbps_head; - int moved = 0; - - rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | - RBPS_MASK(he_readl(he_dev, G0_RBPS_S))); - - for (;;) { - newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | - RBPS_MASK(he_dev->rbps_tail+1)); + i = find_next_zero_bit(he_dev->rbpl_table, RBPL_TABLE_SIZE, he_dev->rbpl_hint); + if (i > (RBPL_TABLE_SIZE - 1)) { + i = find_first_zero_bit(he_dev->rbpl_table, RBPL_TABLE_SIZE); + if (i > (RBPL_TABLE_SIZE - 1)) + break; + } + he_dev->rbpl_hint = i + 1; - /* table 3.42 -- rbps_tail should never be set to rbps_head */ - if ((newtail == rbps_head) || (newtail->status & RBP_LOANED)) + heb = pci_pool_alloc(he_dev->rbpl_pool, GFP_ATOMIC|GFP_DMA, &mapping); + if (!heb) break; - - newtail->status |= RBP_LOANED; - he_dev->rbps_tail = newtail; + heb->mapping = mapping; + list_add(&heb->entry, &he_dev->rbpl_outstanding); + he_dev->rbpl_virt[i] = heb; + set_bit(i, he_dev->rbpl_table); + new_tail->idx = i << RBP_IDX_OFFSET; + new_tail->phys = mapping + offsetof(struct he_buff, data); + + he_dev->rbpl_tail = new_tail; ++moved; } if (moved) - he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T); + he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T); } static void @@ -2054,10 +1946,8 @@ he_tasklet(unsigned long data) HPRINTK("rbrq%d threshold\n", group); /* fall through */ case ITYPE_RBRQ_TIMER: - if (he_service_rbrq(he_dev, group)) { + if (he_service_rbrq(he_dev, group)) he_service_rbpl(he_dev, group); - he_service_rbps(he_dev, group); - } break; case ITYPE_TBRQ_THRESH: HPRINTK("tbrq%d threshold\n", group); @@ -2069,7 +1959,7 @@ he_tasklet(unsigned long data) he_service_rbpl(he_dev, group); break; case ITYPE_RBPS_THRESH: - he_service_rbps(he_dev, group); + /* shouldn't happen unless small buffers enabled */ break; case ITYPE_PHY: HPRINTK("phy interrupt\n"); @@ -2097,7 +1987,6 @@ he_tasklet(unsigned long data) he_service_rbrq(he_dev, 0); he_service_rbpl(he_dev, 0); - he_service_rbps(he_dev, 0); he_service_tbrq(he_dev, 0); break; default: @@ -2251,7 +2140,7 @@ he_open(struct atm_vcc *vcc) return -ENOMEM; } - he_vcc->iov_tail = he_vcc->iov_head; + INIT_LIST_HEAD(&he_vcc->buffers); he_vcc->pdu_len = 0; he_vcc->rc_index = -1; @@ -2405,8 +2294,8 @@ he_open(struct atm_vcc *vcc) goto open_failed; } - rsr1 = RSR1_GROUP(0); - rsr4 = RSR4_GROUP(0); + rsr1 = RSR1_GROUP(0) | RSR1_RBPL_ONLY; + rsr4 = RSR4_GROUP(0) | RSR4_RBPL_ONLY; rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ? (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0; @@ -2663,8 +2552,8 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb) #ifdef USE_SCATTERGATHER tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data, - skb->len - skb->data_len, PCI_DMA_TODEVICE); - tpd->iovec[slot].len = skb->len - skb->data_len; + skb_headlen(skb), PCI_DMA_TODEVICE); + tpd->iovec[slot].len = skb_headlen(skb); ++slot; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { @@ -2962,8 +2851,7 @@ module_param(sdh, bool, 0); MODULE_PARM_DESC(sdh, "use SDH framing (default 0)"); static struct pci_device_id he_pci_tbl[] = { - { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 0 }, + { PCI_VDEVICE(FORE, PCI_DEVICE_ID_FORE_HE), 0 }, { 0, } }; @@ -2972,19 +2860,8 @@ MODULE_DEVICE_TABLE(pci, he_pci_tbl); static struct pci_driver he_driver = { .name = "he", .probe = he_init_one, - .remove = __devexit_p(he_remove_one), + .remove = he_remove_one, .id_table = he_pci_tbl, }; -static int __init he_init(void) -{ - return pci_register_driver(&he_driver); -} - -static void __exit he_cleanup(void) -{ - pci_unregister_driver(&he_driver); -} - -module_init(he_init); -module_exit(he_cleanup); +module_pci_driver(he_driver); diff --git a/drivers/atm/he.h b/drivers/atm/he.h index c2983e0d4ec..110a27d2ecf 100644 --- a/drivers/atm/he.h +++ b/drivers/atm/he.h @@ -67,11 +67,6 @@ #define CONFIG_RBPL_BUFSIZE 4096 #define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1)) -#define CONFIG_RBPS_SIZE 1024 -#define CONFIG_RBPS_THRESH 64 -#define CONFIG_RBPS_BUFSIZE 128 -#define RBPS_MASK(x) (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1)) - /* 5.1.3 initialize connection memory */ #define CONFIG_RSRA 0x00000 @@ -203,36 +198,37 @@ struct he_hsp { } group[HE_NUM_GROUPS]; }; -/* figure 2.9 receive buffer pools */ +/* + * figure 2.9 receive buffer pools + * + * since a virtual address might be more than 32 bits, we store an index + * in the virt member of he_rbp. NOTE: the lower six bits in the rbrq + * addr member are used for buffer status further limiting us to 26 bits. + */ struct he_rbp { volatile u32 phys; - volatile u32 status; + volatile u32 idx; /* virt */ }; -/* NOTE: it is suggested that virt be the virtual address of the host - buffer. on a 64-bit machine, this would not work. Instead, we - store the real virtual address in another list, and store an index - (and buffer status) in the virt member. -*/ +#define RBP_IDX_OFFSET 6 -#define RBP_INDEX_OFF 6 -#define RBP_INDEX(x) (((long)(x) >> RBP_INDEX_OFF) & 0xffff) -#define RBP_LOANED 0x80000000 -#define RBP_SMALLBUF 0x40000000 +/* + * the he dma engine will try to hold an extra 16 buffers in its local + * caches. and add a couple buffers for safety. + */ -struct he_virt { - void *virt; -}; +#define RBPL_TABLE_SIZE (CONFIG_RBPL_SIZE + 16 + 2) -#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE -#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE +struct he_buff { + struct list_head entry; + dma_addr_t mapping; + unsigned long len; + u8 data[]; +}; #ifdef notyet struct he_group { - u32 rpbs_size, rpbs_qsize; - struct he_rbp rbps_ba; - u32 rpbl_size, rpbl_qsize; struct he_rpb_entry *rbpl_ba; }; @@ -297,18 +293,15 @@ struct he_dev { struct he_rbrq *rbrq_base, *rbrq_head; int rbrq_peak; + struct he_buff **rbpl_virt; + unsigned long *rbpl_table; + unsigned long rbpl_hint; struct pci_pool *rbpl_pool; dma_addr_t rbpl_phys; struct he_rbp *rbpl_base, *rbpl_tail; - struct he_virt *rbpl_virt; + struct list_head rbpl_outstanding; int rbpl_peak; - struct pci_pool *rbps_pool; - dma_addr_t rbps_phys; - struct he_rbp *rbps_base, *rbps_tail; - struct he_virt *rbps_virt; - int rbps_peak; - dma_addr_t tbrq_phys; struct he_tbrq *tbrq_base, *tbrq_head; int tbrq_peak; @@ -321,20 +314,12 @@ struct he_dev { struct he_dev *next; }; -struct he_iovec -{ - u32 iov_base; - u32 iov_len; -}; - #define HE_MAXIOV 20 struct he_vcc { - struct he_iovec iov_head[HE_MAXIOV]; - struct he_iovec *iov_tail; + struct list_head buffers; int pdu_len; - int rc_index; wait_queue_head_t rx_waitq; diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 4e49021e67e..1dc0519333f 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -38,12 +38,13 @@ #include <linux/delay.h> #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/wait.h> +#include <linux/slab.h> -#include <asm/system.h> #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/uaccess.h> #include <asm/string.h> #include <asm/byteorder.h> @@ -168,13 +169,13 @@ static inline void __init show_version (void) { Real Time (cdv and max CDT given) CBR(pcr) pcr bandwidth always available - rtVBR(pcr,scr,mbs) scr bandwidth always available, upto pcr at mbs too + rtVBR(pcr,scr,mbs) scr bandwidth always available, up to pcr at mbs too Non Real Time - nrtVBR(pcr,scr,mbs) scr bandwidth always available, upto pcr at mbs too + nrtVBR(pcr,scr,mbs) scr bandwidth always available, up to pcr at mbs too UBR() - ABR(mcr,pcr) mcr bandwidth always available, upto pcr (depending) too + ABR(mcr,pcr) mcr bandwidth always available, up to pcr (depending) too mbs is max burst size (bucket) pcr and scr have associated cdvt values @@ -943,7 +944,7 @@ static void hrz_close_rx (hrz_dev * dev, u16 vc) { // to be fixed soon, so do not define TAILRECUSRIONWORKS unless you // are sure it does as you may otherwise overflow the kernel stack. -// giving this fn a return value would help GCC, alledgedly +// giving this fn a return value would help GCC, allegedly static void rx_schedule (hrz_dev * dev, int irq) { unsigned int rx_bytes; @@ -1035,7 +1036,7 @@ static void rx_schedule (hrz_dev * dev, int irq) { // VC layer stats atomic_inc(&vcc->stats->rx); __net_timestamp(skb); - // end of our responsability + // end of our responsibility vcc->push (vcc, skb); } } @@ -1644,10 +1645,8 @@ static int hrz_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { unsigned short d = 0; char * s = skb->data; if (*s++ == 'D') { - for (i = 0; i < 4; ++i) { - d = (d<<4) | ((*s <= '9') ? (*s - '0') : (*s - 'a' + 10)); - ++s; - } + for (i = 0; i < 4; ++i) + d = (d << 4) | hex_to_bin(*s++); PRINTK (KERN_INFO, "debug bitmap is now %hx", debug = d); } } @@ -1790,7 +1789,7 @@ static void CLOCK_IT (const hrz_dev *dev, u32 ctrl) WRITE_IT_WAIT(dev, ctrl | SEEPROM_SK); } -static u16 __devinit read_bia (const hrz_dev * dev, u16 addr) +static u16 read_bia(const hrz_dev *dev, u16 addr) { u32 ctrl = rd_regl (dev, CONTROL_0_REG); @@ -1846,7 +1845,8 @@ static u16 __devinit read_bia (const hrz_dev * dev, u16 addr) /********** initialise a card **********/ -static int __devinit hrz_init (hrz_dev * dev) { +static int hrz_init(hrz_dev *dev) +{ int onefivefive; u16 chan; @@ -2183,7 +2183,6 @@ static int hrz_open (struct atm_vcc *atm_vcc) default: PRINTD (DBG_QOS|DBG_VCC, "Bad AAL!"); return -EINVAL; - break; } // TX traffic parameters @@ -2358,7 +2357,6 @@ static int hrz_open (struct atm_vcc *atm_vcc) default: { PRINTD (DBG_QOS, "unsupported TX traffic class"); return -EINVAL; - break; } } } @@ -2434,7 +2432,6 @@ static int hrz_open (struct atm_vcc *atm_vcc) default: { PRINTD (DBG_QOS, "unsupported RX traffic class"); return -EINVAL; - break; } } } @@ -2582,7 +2579,6 @@ static int hrz_getsockopt (struct atm_vcc * atm_vcc, int level, int optname, // break; default: return -ENOPROTOOPT; - break; }; break; } @@ -2602,7 +2598,6 @@ static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname, // break; default: return -ENOPROTOOPT; - break; }; break; } @@ -2687,7 +2682,8 @@ static const struct atmdev_ops hrz_ops = { .owner = THIS_MODULE, }; -static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +static int hrz_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_ent) { hrz_dev * dev; int err = 0; @@ -2734,7 +2730,8 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_ PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p", iobase, irq, membase); - dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL); + dev->atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &hrz_ops, -1, + NULL); if (!(dev->atm_dev)) { PRINTD(DBG_ERR, "failed to register Madge ATM adapter"); err = -EINVAL; @@ -2841,7 +2838,7 @@ out_disable: goto out; } -static void __devexit hrz_remove_one(struct pci_dev *pci_dev) +static void hrz_remove_one(struct pci_dev *pci_dev) { hrz_dev *dev; @@ -2906,7 +2903,7 @@ MODULE_DEVICE_TABLE(pci, hrz_pci_tbl); static struct pci_driver hrz_driver = { .name = "horizon", .probe = hrz_probe, - .remove = __devexit_p(hrz_remove_one), + .remove = hrz_remove_one, .id_table = hrz_pci_tbl, }; diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index 84672dc57f7..909c95bd7be 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c @@ -15,7 +15,7 @@ #include <linux/capability.h> #include <linux/atm_idt77105.h> #include <linux/spinlock.h> -#include <asm/system.h> +#include <linux/slab.h> #include <asm/param.h> #include <asm/uaccess.h> @@ -125,7 +125,7 @@ static void idt77105_restart_timer_func(unsigned long dummy) istat = GET(ISTAT); /* side effect: clears all interrupt status bits */ if (istat & IDT77105_ISTAT_GOODSIG) { /* Found signal again */ - dev->signal = ATM_PHY_SIG_FOUND; + atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND); printk(KERN_NOTICE "%s(itf %d): signal detected again\n", dev->type,dev->number); /* flush the receive FIFO */ @@ -150,7 +150,7 @@ static int fetch_stats(struct atm_dev *dev,struct idt77105_stats __user *arg,int spin_unlock_irqrestore(&idt77105_priv_lock, flags); if (arg == NULL) return 0; - return copy_to_user(arg, &PRIV(dev)->stats, + return copy_to_user(arg, &stats, sizeof(struct idt77105_stats)) ? -EFAULT : 0; } @@ -221,7 +221,7 @@ static void idt77105_int(struct atm_dev *dev) /* Rx Signal Condition Change - line went up or down */ if (istat & IDT77105_ISTAT_GOODSIG) { /* signal detected again */ /* This should not happen (restart timer does it) but JIC */ - dev->signal = ATM_PHY_SIG_FOUND; + atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND); } else { /* signal lost */ /* * Disable interrupts and stop all transmission and @@ -234,7 +234,7 @@ static void idt77105_int(struct atm_dev *dev) IDT77105_MCR_DRIC| IDT77105_MCR_HALTTX ) & ~IDT77105_MCR_EIP, MCR); - dev->signal = ATM_PHY_SIG_LOST; + atm_dev_signal_change(dev, ATM_PHY_SIG_LOST); printk(KERN_NOTICE "%s(itf %d): signal lost\n", dev->type,dev->number); } @@ -271,8 +271,9 @@ static int idt77105_start(struct atm_dev *dev) memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats)); /* initialise dev->signal from Good Signal Bit */ - dev->signal = GET(ISTAT) & IDT77105_ISTAT_GOODSIG ? ATM_PHY_SIG_FOUND : - ATM_PHY_SIG_LOST; + atm_dev_signal_change(dev, + GET(ISTAT) & IDT77105_ISTAT_GOODSIG ? + ATM_PHY_SIG_FOUND : ATM_PHY_SIG_LOST); if (dev->signal == ATM_PHY_SIG_LOST) printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type, dev->number); @@ -367,9 +368,9 @@ EXPORT_SYMBOL(idt77105_init); static void __exit idt77105_exit(void) { - /* turn off timers */ - del_timer(&stats_timer); - del_timer(&restart_timer); + /* turn off timers */ + del_timer_sync(&stats_timer); + del_timer_sync(&restart_timer); } module_exit(idt77105_exit); diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index e33ae0025b1..b621f56a36b 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -37,14 +37,16 @@ #include <linux/atm.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/bitops.h> #include <linux/wait.h> #include <linux/jiffies.h> #include <linux/mutex.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/byteorder.h> #ifdef CONFIG_ATM_IDT77252_USE_SUNI @@ -1256,18 +1258,17 @@ idt77252_rx_raw(struct idt77252_dev *card) tail = readl(SAR_REG_RAWCT); pci_dma_sync_single_for_cpu(card->pcidev, IDT77252_PRV_PADDR(queue), - skb_end_pointer(queue) - queue->head - 16, + skb_end_offset(queue) - 16, PCI_DMA_FROMDEVICE); while (head != tail) { - unsigned int vpi, vci, pti; + unsigned int vpi, vci; u32 header; header = le32_to_cpu(*(u32 *) &queue->data[0]); vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT; vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT; - pti = (header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; #ifdef CONFIG_ATM_IDT77252_DEBUG if (debug & DBG_RAW_CELL) { @@ -2550,12 +2551,12 @@ done: timeout = 5 * 1000; while (atomic_read(&vc->scq->used) > 0) { timeout = msleep_interruptible(timeout); - if (!timeout) + if (!timeout) { + pr_warn("%s: SCQ drain timeout: %u used\n", + card->name, atomic_read(&vc->scq->used)); break; + } } - if (!timeout) - printk("%s: SCQ drain timeout: %u used\n", - card->name, atomic_read(&vc->scq->used)); writel(TCMDQ_HALT | vc->index, SAR_REG_TCMDQ); clear_scd(card, vc->scq, vc->class); @@ -2708,53 +2709,10 @@ idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page) static void idt77252_collect_stat(struct idt77252_dev *card) { - u32 cdc, vpec, icc; - - cdc = readl(SAR_REG_CDC); - vpec = readl(SAR_REG_VPEC); - icc = readl(SAR_REG_ICC); - -#ifdef NOTDEF - printk("%s:", card->name); - - if (cdc & 0x7f0000) { - char *s = ""; - - printk(" ["); - if (cdc & (1 << 22)) { - printk("%sRM ID", s); - s = " | "; - } - if (cdc & (1 << 21)) { - printk("%sCON TAB", s); - s = " | "; - } - if (cdc & (1 << 20)) { - printk("%sNO FB", s); - s = " | "; - } - if (cdc & (1 << 19)) { - printk("%sOAM CRC", s); - s = " | "; - } - if (cdc & (1 << 18)) { - printk("%sRM CRC", s); - s = " | "; - } - if (cdc & (1 << 17)) { - printk("%sRM FIFO", s); - s = " | "; - } - if (cdc & (1 << 16)) { - printk("%sRX FIFO", s); - s = " | "; - } - printk("]"); - } + (void) readl(SAR_REG_CDC); + (void) readl(SAR_REG_VPEC); + (void) readl(SAR_REG_ICC); - printk(" CDC %04x, VPEC %04x, ICC: %04x\n", - cdc & 0xffff, vpec & 0xffff, icc & 0xffff); -#endif } static irqreturn_t @@ -3151,8 +3109,7 @@ deinit_card(struct idt77252_dev *card) } -static int __devinit -init_sram(struct idt77252_dev *card) +static void init_sram(struct idt77252_dev *card) { int i; @@ -3297,11 +3254,9 @@ init_sram(struct idt77252_dev *card) SAR_REG_RXFD); IPRINTK("%s: SRAM initialization complete.\n", card->name); - return 0; } -static int __devinit -init_card(struct atm_dev *dev) +static int init_card(struct atm_dev *dev) { struct idt77252_dev *card = dev->dev_data; struct pci_dev *pcidev = card->pcidev; @@ -3363,7 +3318,7 @@ init_card(struct atm_dev *dev) writel(SAR_STAT_TMROF, SAR_REG_STAT); } IPRINTK("%s: Request IRQ ... ", card->name); - if (request_irq(pcidev->irq, idt77252_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pcidev->irq, idt77252_interrupt, IRQF_SHARED, card->name, card) != 0) { printk("%s: can't allocate IRQ.\n", card->name); deinit_card(card); @@ -3409,8 +3364,7 @@ init_card(struct atm_dev *dev) writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG); - if (init_sram(card) < 0) - return -1; + init_sram(card); /********************************************************************/ /* A L L O C R A M A N D S E T V A R I O U S T H I N G S */ @@ -3460,27 +3414,28 @@ init_card(struct atm_dev *dev) size = sizeof(struct vc_map *) * card->tct_size; IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size); - if (NULL == (card->vcs = vmalloc(size))) { + card->vcs = vzalloc(size); + if (!card->vcs) { printk("%s: memory allocation failure.\n", card->name); deinit_card(card); return -1; } - memset(card->vcs, 0, size); size = sizeof(struct vc_map *) * card->scd_size; IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n", card->name, size); - if (NULL == (card->scd2vc = vmalloc(size))) { + card->scd2vc = vzalloc(size); + if (!card->scd2vc) { printk("%s: memory allocation failure.\n", card->name); deinit_card(card); return -1; } - memset(card->scd2vc, 0, size); size = sizeof(struct tst_info) * (card->tst_size - 2); IPRINTK("%s: allocate %d byte for TST to VC mapping.\n", card->name, size); - if (NULL == (card->soft_tst = vmalloc(size))) { + card->soft_tst = vmalloc(size); + if (!card->soft_tst) { printk("%s: memory allocation failure.\n", card->name); deinit_card(card); return -1; @@ -3496,7 +3451,7 @@ init_card(struct atm_dev *dev) return -1; } if (dev->phy->ioctl == NULL) { - printk("%s: LT had no IOCTL funtion defined.\n", card->name); + printk("%s: LT had no IOCTL function defined.\n", card->name); deinit_card(card); return -1; } @@ -3556,11 +3511,8 @@ init_card(struct atm_dev *dev) tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */ if (tmp) { memcpy(card->atmdev->esi, tmp->dev_addr, 6); - - printk("%s: ESI %02x:%02x:%02x:%02x:%02x:%02x\n", - card->name, card->atmdev->esi[0], card->atmdev->esi[1], - card->atmdev->esi[2], card->atmdev->esi[3], - card->atmdev->esi[4], card->atmdev->esi[5]); + dev_put(tmp); + printk("%s: ESI %pM\n", card->name, card->atmdev->esi); } /* * XXX: </hack> @@ -3583,8 +3535,7 @@ init_card(struct atm_dev *dev) /*****************************************************************************/ -static int __devinit -idt77252_preset(struct idt77252_dev *card) +static int idt77252_preset(struct idt77252_dev *card) { u16 pci_command; @@ -3625,8 +3576,7 @@ idt77252_preset(struct idt77252_dev *card) } -static unsigned long __devinit -probe_sram(struct idt77252_dev *card) +static unsigned long probe_sram(struct idt77252_dev *card) { u32 data, addr; @@ -3647,8 +3597,8 @@ probe_sram(struct idt77252_dev *card) return addr * sizeof(u32); } -static int __devinit -idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) +static int idt77252_init_one(struct pci_dev *pcidev, + const struct pci_device_id *id) { static struct idt77252_dev **last = &idt77252_chain; static int index = 0; @@ -3702,7 +3652,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) goto err_out_iounmap; } - dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL); + dev = atm_dev_register("idt77252", &pcidev->dev, &idt77252_ops, -1, + NULL); if (!dev) { printk("%s: can't register atm device\n", card->name); err = -EIO; @@ -3781,8 +3732,7 @@ err_out_disable_pdev: static struct pci_device_id idt77252_pci_tbl[] = { - { PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_IDT_IDT77252, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77252), 0 }, { 0, } }; diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h index 5042bb2dab1..3a82cc23a05 100644 --- a/drivers/atm/idt77252.h +++ b/drivers/atm/idt77252.h @@ -572,7 +572,7 @@ struct idt77252_dev #define SAR_STAT_TSQF 0x00001000 /* Transmit Status Queue full */ #define SAR_STAT_TMROF 0x00000800 /* Timer overflow */ #define SAR_STAT_PHYI 0x00000400 /* PHY device Interrupt flag */ -#define SAR_STAT_CMDBZ 0x00000200 /* ABR SAR Comand Busy Flag */ +#define SAR_STAT_CMDBZ 0x00000200 /* ABR SAR Command Busy Flag */ #define SAR_STAT_FBQ3A 0x00000100 /* Free Buffer Queue 3 Attention */ #define SAR_STAT_FBQ2A 0x00000080 /* Free Buffer Queue 2 Attention */ #define SAR_STAT_RSQF 0x00000040 /* Receive Status Queue full */ @@ -766,7 +766,7 @@ struct idt77252_dev #define SAR_RCTE_BUFFSTAT_MASK 0x00003000 /* buffer status */ #define SAR_RCTE_EFCI 0x00000800 /* EFCI Congestion flag */ #define SAR_RCTE_CLP 0x00000400 /* Cell Loss Priority flag */ -#define SAR_RCTE_CRC 0x00000200 /* Recieved CRC Error */ +#define SAR_RCTE_CRC 0x00000200 /* Received CRC Error */ #define SAR_RCTE_CELLCNT_MASK 0x000001FF /* cell Count */ #define SAR_RCTE_AAL0 0x00000000 /* AAL types for ALL field */ diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 25a4c86f839..4217f29a85e 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -53,10 +53,11 @@ #include <linux/delay.h> #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/wait.h> -#include <asm/system.h> +#include <linux/slab.h> #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/uaccess.h> #include <asm/string.h> #include <asm/byteorder.h> @@ -219,7 +220,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) { while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) { dev->ffL.tcq_rd += 2; if (dev->ffL.tcq_rd > dev->ffL.tcq_ed) - dev->ffL.tcq_rd = dev->ffL.tcq_st; + dev->ffL.tcq_rd = dev->ffL.tcq_st; if (dev->ffL.tcq_rd == dev->host_tcq_wr) return 0xFFFF; desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd); @@ -612,7 +613,6 @@ static int ia_que_tx (IADEV *iadev) { struct sk_buff *skb; int num_desc; struct atm_vcc *vcc; - struct ia_vcc *iavcc; num_desc = ia_avail_descs(iadev); while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) { @@ -626,7 +626,6 @@ static int ia_que_tx (IADEV *iadev) { printk("Free the SKB on closed vci %d \n", vcc->vci); break; } - iavcc = INPH_IA_VCC(vcc); if (ia_pkt_tx (vcc, skb)) { skb_queue_head(&iadev->tx_backlog, skb); } @@ -818,129 +817,152 @@ static void ia_hw_type(IADEV *iadev) { } -static void IaFrontEndIntr(IADEV *iadev) { - volatile IA_SUNI *suni; - volatile ia_mb25_t *mb25; - volatile suni_pm7345_t *suni_pm7345; - u32 intr_status; - u_int frmr_intr; - - if(iadev->phy_type & FE_25MBIT_PHY) { - mb25 = (ia_mb25_t*)iadev->phy; - iadev->carrier_detect = Boolean(mb25->mb25_intr_status & MB25_IS_GSB); - } else if (iadev->phy_type & FE_DS3_PHY) { - suni_pm7345 = (suni_pm7345_t *)iadev->phy; - /* clear FRMR interrupts */ - frmr_intr = suni_pm7345->suni_ds3_frm_intr_stat; - iadev->carrier_detect = - Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); - } else if (iadev->phy_type & FE_E3_PHY ) { - suni_pm7345 = (suni_pm7345_t *)iadev->phy; - frmr_intr = suni_pm7345->suni_e3_frm_maint_intr_ind; - iadev->carrier_detect = - Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS)); - } - else { - suni = (IA_SUNI *)iadev->phy; - intr_status = suni->suni_rsop_status & 0xff; - iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV)); - } - if (iadev->carrier_detect) - printk("IA: SUNI carrier detected\n"); - else - printk("IA: SUNI carrier lost signal\n"); - return; +static u32 ia_phy_read32(struct iadev_priv *ia, unsigned int reg) +{ + return readl(ia->phy + (reg >> 2)); +} + +static void ia_phy_write32(struct iadev_priv *ia, unsigned int reg, u32 val) +{ + writel(val, ia->phy + (reg >> 2)); } -static void ia_mb25_init (IADEV *iadev) +static void ia_frontend_intr(struct iadev_priv *iadev) +{ + u32 status; + + if (iadev->phy_type & FE_25MBIT_PHY) { + status = ia_phy_read32(iadev, MB25_INTR_STATUS); + iadev->carrier_detect = (status & MB25_IS_GSB) ? 1 : 0; + } else if (iadev->phy_type & FE_DS3_PHY) { + ia_phy_read32(iadev, SUNI_DS3_FRM_INTR_STAT); + status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT); + iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1; + } else if (iadev->phy_type & FE_E3_PHY) { + ia_phy_read32(iadev, SUNI_E3_FRM_MAINT_INTR_IND); + status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT); + iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1; + } else { + status = ia_phy_read32(iadev, SUNI_RSOP_STATUS); + iadev->carrier_detect = (status & SUNI_LOSV) ? 0 : 1; + } + + printk(KERN_INFO "IA: SUNI carrier %s\n", + iadev->carrier_detect ? "detected" : "lost signal"); +} + +static void ia_mb25_init(struct iadev_priv *iadev) { - volatile ia_mb25_t *mb25 = (ia_mb25_t*)iadev->phy; #if 0 mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED; #endif - mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC; - mb25->mb25_diag_control = 0; - /* - * Initialize carrier detect state - */ - iadev->carrier_detect = Boolean(mb25->mb25_intr_status & MB25_IS_GSB); - return; -} + ia_phy_write32(iadev, MB25_MASTER_CTRL, MB25_MC_DRIC | MB25_MC_DREC); + ia_phy_write32(iadev, MB25_DIAG_CONTROL, 0); + + iadev->carrier_detect = + (ia_phy_read32(iadev, MB25_INTR_STATUS) & MB25_IS_GSB) ? 1 : 0; +} + +struct ia_reg { + u16 reg; + u16 val; +}; -static void ia_suni_pm7345_init (IADEV *iadev) +static void ia_phy_write(struct iadev_priv *iadev, + const struct ia_reg *regs, int len) { - volatile suni_pm7345_t *suni_pm7345 = (suni_pm7345_t *)iadev->phy; - if (iadev->phy_type & FE_DS3_PHY) - { - iadev->carrier_detect = - Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); - suni_pm7345->suni_ds3_frm_intr_enbl = 0x17; - suni_pm7345->suni_ds3_frm_cfg = 1; - suni_pm7345->suni_ds3_tran_cfg = 1; - suni_pm7345->suni_config = 0; - suni_pm7345->suni_splr_cfg = 0; - suni_pm7345->suni_splt_cfg = 0; - } - else - { - iadev->carrier_detect = - Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat & SUNI_E3_LOS)); - suni_pm7345->suni_e3_frm_fram_options = 0x4; - suni_pm7345->suni_e3_frm_maint_options = 0x20; - suni_pm7345->suni_e3_frm_fram_intr_enbl = 0x1d; - suni_pm7345->suni_e3_frm_maint_intr_enbl = 0x30; - suni_pm7345->suni_e3_tran_stat_diag_options = 0x0; - suni_pm7345->suni_e3_tran_fram_options = 0x1; - suni_pm7345->suni_config = SUNI_PM7345_E3ENBL; - suni_pm7345->suni_splr_cfg = 0x41; - suni_pm7345->suni_splt_cfg = 0x41; - } - /* - * Enable RSOP loss of signal interrupt. - */ - suni_pm7345->suni_intr_enbl = 0x28; - - /* - * Clear error counters - */ - suni_pm7345->suni_id_reset = 0; - - /* - * Clear "PMCTST" in master test register. - */ - suni_pm7345->suni_master_test = 0; - - suni_pm7345->suni_rxcp_ctrl = 0x2c; - suni_pm7345->suni_rxcp_fctrl = 0x81; - - suni_pm7345->suni_rxcp_idle_pat_h1 = - suni_pm7345->suni_rxcp_idle_pat_h2 = - suni_pm7345->suni_rxcp_idle_pat_h3 = 0; - suni_pm7345->suni_rxcp_idle_pat_h4 = 1; - - suni_pm7345->suni_rxcp_idle_mask_h1 = 0xff; - suni_pm7345->suni_rxcp_idle_mask_h2 = 0xff; - suni_pm7345->suni_rxcp_idle_mask_h3 = 0xff; - suni_pm7345->suni_rxcp_idle_mask_h4 = 0xfe; - - suni_pm7345->suni_rxcp_cell_pat_h1 = - suni_pm7345->suni_rxcp_cell_pat_h2 = - suni_pm7345->suni_rxcp_cell_pat_h3 = 0; - suni_pm7345->suni_rxcp_cell_pat_h4 = 1; - - suni_pm7345->suni_rxcp_cell_mask_h1 = - suni_pm7345->suni_rxcp_cell_mask_h2 = - suni_pm7345->suni_rxcp_cell_mask_h3 = - suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff; - - suni_pm7345->suni_txcp_ctrl = 0xa4; - suni_pm7345->suni_txcp_intr_en_sts = 0x10; - suni_pm7345->suni_txcp_idle_pat_h5 = 0x55; - - suni_pm7345->suni_config &= ~(SUNI_PM7345_LLB | - SUNI_PM7345_CLB | - SUNI_PM7345_DLB | - SUNI_PM7345_PLB); + while (len--) { + ia_phy_write32(iadev, regs->reg, regs->val); + regs++; + } +} + +static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev) +{ + static const struct ia_reg suni_ds3_init [] = { + { SUNI_DS3_FRM_INTR_ENBL, 0x17 }, + { SUNI_DS3_FRM_CFG, 0x01 }, + { SUNI_DS3_TRAN_CFG, 0x01 }, + { SUNI_CONFIG, 0 }, + { SUNI_SPLR_CFG, 0 }, + { SUNI_SPLT_CFG, 0 } + }; + u32 status; + + status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT); + iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1; + + ia_phy_write(iadev, suni_ds3_init, ARRAY_SIZE(suni_ds3_init)); +} + +static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev) +{ + static const struct ia_reg suni_e3_init [] = { + { SUNI_E3_FRM_FRAM_OPTIONS, 0x04 }, + { SUNI_E3_FRM_MAINT_OPTIONS, 0x20 }, + { SUNI_E3_FRM_FRAM_INTR_ENBL, 0x1d }, + { SUNI_E3_FRM_MAINT_INTR_ENBL, 0x30 }, + { SUNI_E3_TRAN_STAT_DIAG_OPTIONS, 0 }, + { SUNI_E3_TRAN_FRAM_OPTIONS, 0x01 }, + { SUNI_CONFIG, SUNI_PM7345_E3ENBL }, + { SUNI_SPLR_CFG, 0x41 }, + { SUNI_SPLT_CFG, 0x41 } + }; + u32 status; + + status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT); + iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1; + ia_phy_write(iadev, suni_e3_init, ARRAY_SIZE(suni_e3_init)); +} + +static void ia_suni_pm7345_init(struct iadev_priv *iadev) +{ + static const struct ia_reg suni_init [] = { + /* Enable RSOP loss of signal interrupt. */ + { SUNI_INTR_ENBL, 0x28 }, + /* Clear error counters. */ + { SUNI_ID_RESET, 0 }, + /* Clear "PMCTST" in master test register. */ + { SUNI_MASTER_TEST, 0 }, + + { SUNI_RXCP_CTRL, 0x2c }, + { SUNI_RXCP_FCTRL, 0x81 }, + + { SUNI_RXCP_IDLE_PAT_H1, 0 }, + { SUNI_RXCP_IDLE_PAT_H2, 0 }, + { SUNI_RXCP_IDLE_PAT_H3, 0 }, + { SUNI_RXCP_IDLE_PAT_H4, 0x01 }, + + { SUNI_RXCP_IDLE_MASK_H1, 0xff }, + { SUNI_RXCP_IDLE_MASK_H2, 0xff }, + { SUNI_RXCP_IDLE_MASK_H3, 0xff }, + { SUNI_RXCP_IDLE_MASK_H4, 0xfe }, + + { SUNI_RXCP_CELL_PAT_H1, 0 }, + { SUNI_RXCP_CELL_PAT_H2, 0 }, + { SUNI_RXCP_CELL_PAT_H3, 0 }, + { SUNI_RXCP_CELL_PAT_H4, 0x01 }, + + { SUNI_RXCP_CELL_MASK_H1, 0xff }, + { SUNI_RXCP_CELL_MASK_H2, 0xff }, + { SUNI_RXCP_CELL_MASK_H3, 0xff }, + { SUNI_RXCP_CELL_MASK_H4, 0xff }, + + { SUNI_TXCP_CTRL, 0xa4 }, + { SUNI_TXCP_INTR_EN_STS, 0x10 }, + { SUNI_TXCP_IDLE_PAT_H5, 0x55 } + }; + + if (iadev->phy_type & FE_DS3_PHY) + ia_suni_pm7345_init_ds3(iadev); + else + ia_suni_pm7345_init_e3(iadev); + + ia_phy_write(iadev, suni_init, ARRAY_SIZE(suni_init)); + + ia_phy_write32(iadev, SUNI_CONFIG, ia_phy_read32(iadev, SUNI_CONFIG) & + ~(SUNI_PM7345_LLB | SUNI_PM7345_CLB | + SUNI_PM7345_DLB | SUNI_PM7345_PLB)); #ifdef __SNMP__ suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE; #endif /* __SNMP__ */ @@ -1024,7 +1046,7 @@ static void desc_dbg(IADEV *iadev) { } -/*----------------------------- Recieving side stuff --------------------------*/ +/*----------------------------- Receiving side stuff --------------------------*/ static void rx_excp_rcvd(struct atm_dev *dev) { @@ -1194,7 +1216,7 @@ static void rx_intr(struct atm_dev *dev) if (status & RX_PKT_RCVD) { /* do something */ - /* Basically recvd an interrupt for receving a packet. + /* Basically recvd an interrupt for receiving a packet. A descriptor would have been written to the packet complete queue. Get all the descriptors and set up dma to move the packets till the packet complete queue is empty.. @@ -1297,8 +1319,8 @@ static void rx_dle_intr(struct atm_dev *dev) if (ia_vcc == NULL) { atomic_inc(&vcc->stats->rx_err); + atm_return(vcc, skb->truesize); dev_kfree_skb_any(skb); - atm_return(vcc, atm_guess_pdu2truesize(len)); goto INCR_DLE; } // get real pkt length pwang_test @@ -1311,8 +1333,8 @@ static void rx_dle_intr(struct atm_dev *dev) atomic_inc(&vcc->stats->rx_err); IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)", length, skb->len);) + atm_return(vcc, skb->truesize); dev_kfree_skb_any(skb); - atm_return(vcc, atm_guess_pdu2truesize(len)); goto INCR_DLE; } skb_trim(skb, length); @@ -1427,10 +1449,10 @@ static int rx_init(struct atm_dev *dev) iadev->dma + IPHASE5575_RX_LIST_ADDR); IF_INIT(printk("Tx Dle list addr: 0x%p value: 0x%0x\n", iadev->dma+IPHASE5575_TX_LIST_ADDR, - *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR)); + readl(iadev->dma + IPHASE5575_TX_LIST_ADDR)); printk("Rx Dle list addr: 0x%p value: 0x%0x\n", iadev->dma+IPHASE5575_RX_LIST_ADDR, - *(u32*)(iadev->dma+IPHASE5575_RX_LIST_ADDR));) + readl(iadev->dma + IPHASE5575_RX_LIST_ADDR));) writew(0xffff, iadev->reass_reg+REASS_MASK_REG); writew(0, iadev->reass_reg+MODE_REG); @@ -1854,7 +1876,7 @@ static int open_tx(struct atm_vcc *vcc) return -EINVAL; } if (vcc->qos.txtp.max_pcr > iadev->LineRate) { - IF_CBR(printk("PCR is not availble\n");) + IF_CBR(printk("PCR is not available\n");) return -1; } vc->type = CBR; @@ -2062,7 +2084,7 @@ static int tx_init(struct atm_dev *dev) - UBR Table size is 4K - UBR wait queue is 4K since the table and wait queues are contiguous, all the bytes - can be initialized by one memeset. + can be initialized by one memeset. */ vcsize_sel = 0; @@ -2088,7 +2110,7 @@ static int tx_init(struct atm_dev *dev) - ABR Table size is 2K - ABR wait queue is 2K since the table and wait queues are contiguous, all the bytes - can be intialized by one memeset. + can be initialized by one memeset. */ i = ABR_SCHED_TABLE * iadev->memSize; writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE); @@ -2210,7 +2232,7 @@ static irqreturn_t ia_int(int irq, void *dev_id) if (status & STAT_DLERINT) { /* Clear this bit by writing a 1 to it. */ - *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLERINT; + writel(STAT_DLERINT, iadev->reg + IPHASE5575_BUS_STATUS_REG); rx_dle_intr(dev); } if (status & STAT_SEGINT) @@ -2221,13 +2243,13 @@ static irqreturn_t ia_int(int irq, void *dev_id) } if (status & STAT_DLETINT) { - *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLETINT; + writel(STAT_DLETINT, iadev->reg + IPHASE5575_BUS_STATUS_REG); tx_dle_intr(dev); } if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT)) { if (status & STAT_FEINT) - IaFrontEndIntr(iadev); + ia_frontend_intr(iadev); } } return IRQ_RETVAL(handled); @@ -2277,7 +2299,7 @@ static int reset_sar(struct atm_dev *dev) } -static int __devinit ia_init(struct atm_dev *dev) +static int ia_init(struct atm_dev *dev) { IADEV *iadev; unsigned long real_base; @@ -2340,7 +2362,7 @@ static int __devinit ia_init(struct atm_dev *dev) { printk(DEV_LABEL " (itf %d): can't set up page mapping\n", dev->number); - return error; + return -ENOMEM; } IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n", dev->number, iadev->pci->revision, base, iadev->irq);) @@ -2470,7 +2492,7 @@ static void ia_free_rx(IADEV *iadev) iadev->rx_dle_dma); } -static int __devinit ia_start(struct atm_dev *dev) +static int ia_start(struct atm_dev *dev) { IADEV *iadev; int error; @@ -2558,7 +2580,7 @@ static int __devinit ia_start(struct atm_dev *dev) goto err_free_rx; } /* Get iadev->carrier_detect status */ - IaFrontEndIntr(iadev); + ia_frontend_intr(iadev); } return 0; @@ -2659,7 +2681,6 @@ static void ia_close(struct atm_vcc *vcc) static int ia_open(struct atm_vcc *vcc) { - IADEV *iadev; struct ia_vcc *ia_vcc; int error; if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) @@ -2667,7 +2688,6 @@ static int ia_open(struct atm_vcc *vcc) IF_EVENT(printk("ia: not partially allocated resources\n");) vcc->dev_data = NULL; } - iadev = INPH_IA_DEV(vcc->dev); if (vcc->vci != ATM_VPI_UNSPEC && vcc->vpi != ATM_VCI_UNSPEC) { IF_EVENT(printk("iphase open: unspec part\n");) @@ -2831,7 +2851,7 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) case 0xb: if (!capable(CAP_NET_ADMIN)) return -EPERM; - IaFrontEndIntr(iadev); + ia_frontend_intr(iadev); break; case 0xa: if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -3051,11 +3071,9 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb) { IADEV *iadev; - struct ia_vcc *iavcc; unsigned long flags; iadev = INPH_IA_DEV(vcc->dev); - iavcc = INPH_IA_VCC(vcc); if ((!skb)||(skb->len>(iadev->tx_buf_sz-sizeof(struct cpcs_trailer)))) { if (!skb) @@ -3150,12 +3168,10 @@ static const struct atmdev_ops ops = { .owner = THIS_MODULE, }; -static int __devinit ia_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int ia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct atm_dev *dev; IADEV *iadev; - unsigned long flags; int ret; iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); @@ -3172,7 +3188,7 @@ static int __devinit ia_init_one(struct pci_dev *pdev, ret = -ENODEV; goto err_out_free_iadev; } - dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); + dev = atm_dev_register(DEV_LABEL, &pdev->dev, &ops, -1, NULL); if (!dev) { ret = -ENOMEM; goto err_out_disable_dev; @@ -3187,19 +3203,14 @@ static int __devinit ia_init_one(struct pci_dev *pdev, ia_dev[iadev_count] = iadev; _ia_dev[iadev_count] = dev; iadev_count++; - spin_lock_init(&iadev->misc_lock); - /* First fixes first. I don't want to think about this now. */ - spin_lock_irqsave(&iadev->misc_lock, flags); if (ia_init(dev) || ia_start(dev)) { IF_INIT(printk("IA register failed!\n");) iadev_count--; ia_dev[iadev_count] = NULL; _ia_dev[iadev_count] = NULL; - spin_unlock_irqrestore(&iadev->misc_lock, flags); ret = -EINVAL; goto err_out_deregister_dev; } - spin_unlock_irqrestore(&iadev->misc_lock, flags); IF_EVENT(printk("iadev_count = %d\n", iadev_count);) iadev->next_board = ia_boards; @@ -3217,7 +3228,7 @@ err_out: return ret; } -static void __devexit ia_remove_one(struct pci_dev *pdev) +static void ia_remove_one(struct pci_dev *pdev) { struct atm_dev *dev = pci_get_drvdata(pdev); IADEV *iadev = INPH_IA_DEV(dev); @@ -3258,7 +3269,7 @@ static struct pci_driver ia_driver = { .name = DEV_LABEL, .id_table = ia_pci_tbl, .probe = ia_init_one, - .remove = __devexit_p(ia_remove_one), + .remove = ia_remove_one, }; static int __init ia_module_init(void) diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index b2cd20f549c..53ecac5a216 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h @@ -636,82 +636,82 @@ struct rx_buf_desc { #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE -typedef volatile u_int freg_t; +typedef volatile u_int ffreg_t; typedef u_int rreg_t; typedef struct _ffredn_t { - freg_t idlehead_high; /* Idle cell header (high) */ - freg_t idlehead_low; /* Idle cell header (low) */ - freg_t maxrate; /* Maximum rate */ - freg_t stparms; /* Traffic Management Parameters */ - freg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ - freg_t rm_type; /* */ - u_int filler5[0x17 - 0x06]; - freg_t cmd_reg; /* Command register */ - u_int filler18[0x20 - 0x18]; - freg_t cbr_base; /* CBR Pointer Base */ - freg_t vbr_base; /* VBR Pointer Base */ - freg_t abr_base; /* ABR Pointer Base */ - freg_t ubr_base; /* UBR Pointer Base */ - u_int filler24; - freg_t vbrwq_base; /* VBR Wait Queue Base */ - freg_t abrwq_base; /* ABR Wait Queue Base */ - freg_t ubrwq_base; /* UBR Wait Queue Base */ - freg_t vct_base; /* Main VC Table Base */ - freg_t vcte_base; /* Extended Main VC Table Base */ - u_int filler2a[0x2C - 0x2A]; - freg_t cbr_tab_beg; /* CBR Table Begin */ - freg_t cbr_tab_end; /* CBR Table End */ - freg_t cbr_pointer; /* CBR Pointer */ - u_int filler2f[0x30 - 0x2F]; - freg_t prq_st_adr; /* Packet Ready Queue Start Address */ - freg_t prq_ed_adr; /* Packet Ready Queue End Address */ - freg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ - freg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ - freg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ - freg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ - freg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ - freg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ - u_int filler38[0x40 - 0x38]; - freg_t queue_base; /* Base address for PRQ and TCQ */ - freg_t desc_base; /* Base address of descriptor table */ - u_int filler42[0x45 - 0x42]; - freg_t mode_reg_0; /* Mode register 0 */ - freg_t mode_reg_1; /* Mode register 1 */ - freg_t intr_status_reg;/* Interrupt Status register */ - freg_t mask_reg; /* Mask Register */ - freg_t cell_ctr_high1; /* Total cell transfer count (high) */ - freg_t cell_ctr_lo1; /* Total cell transfer count (low) */ - freg_t state_reg; /* Status register */ - u_int filler4c[0x58 - 0x4c]; - freg_t curr_desc_num; /* Contains the current descriptor num */ - freg_t next_desc; /* Next descriptor */ - freg_t next_vc; /* Next VC */ - u_int filler5b[0x5d - 0x5b]; - freg_t present_slot_cnt;/* Present slot count */ - u_int filler5e[0x6a - 0x5e]; - freg_t new_desc_num; /* New descriptor number */ - freg_t new_vc; /* New VC */ - freg_t sched_tbl_ptr; /* Schedule table pointer */ - freg_t vbrwq_wptr; /* VBR wait queue write pointer */ - freg_t vbrwq_rptr; /* VBR wait queue read pointer */ - freg_t abrwq_wptr; /* ABR wait queue write pointer */ - freg_t abrwq_rptr; /* ABR wait queue read pointer */ - freg_t ubrwq_wptr; /* UBR wait queue write pointer */ - freg_t ubrwq_rptr; /* UBR wait queue read pointer */ - freg_t cbr_vc; /* CBR VC */ - freg_t vbr_sb_vc; /* VBR SB VC */ - freg_t abr_sb_vc; /* ABR SB VC */ - freg_t ubr_sb_vc; /* UBR SB VC */ - freg_t vbr_next_link; /* VBR next link */ - freg_t abr_next_link; /* ABR next link */ - freg_t ubr_next_link; /* UBR next link */ - u_int filler7a[0x7c-0x7a]; - freg_t out_rate_head; /* Out of rate head */ - u_int filler7d[0xca-0x7d]; /* pad out to full address space */ - freg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ - freg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ - u_int fillercc[0x100-0xcc]; /* pad out to full address space */ + ffreg_t idlehead_high; /* Idle cell header (high) */ + ffreg_t idlehead_low; /* Idle cell header (low) */ + ffreg_t maxrate; /* Maximum rate */ + ffreg_t stparms; /* Traffic Management Parameters */ + ffreg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ + ffreg_t rm_type; /* */ + u_int filler5[0x17 - 0x06]; + ffreg_t cmd_reg; /* Command register */ + u_int filler18[0x20 - 0x18]; + ffreg_t cbr_base; /* CBR Pointer Base */ + ffreg_t vbr_base; /* VBR Pointer Base */ + ffreg_t abr_base; /* ABR Pointer Base */ + ffreg_t ubr_base; /* UBR Pointer Base */ + u_int filler24; + ffreg_t vbrwq_base; /* VBR Wait Queue Base */ + ffreg_t abrwq_base; /* ABR Wait Queue Base */ + ffreg_t ubrwq_base; /* UBR Wait Queue Base */ + ffreg_t vct_base; /* Main VC Table Base */ + ffreg_t vcte_base; /* Extended Main VC Table Base */ + u_int filler2a[0x2C - 0x2A]; + ffreg_t cbr_tab_beg; /* CBR Table Begin */ + ffreg_t cbr_tab_end; /* CBR Table End */ + ffreg_t cbr_pointer; /* CBR Pointer */ + u_int filler2f[0x30 - 0x2F]; + ffreg_t prq_st_adr; /* Packet Ready Queue Start Address */ + ffreg_t prq_ed_adr; /* Packet Ready Queue End Address */ + ffreg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ + ffreg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ + ffreg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ + ffreg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ + ffreg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ + ffreg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ + u_int filler38[0x40 - 0x38]; + ffreg_t queue_base; /* Base address for PRQ and TCQ */ + ffreg_t desc_base; /* Base address of descriptor table */ + u_int filler42[0x45 - 0x42]; + ffreg_t mode_reg_0; /* Mode register 0 */ + ffreg_t mode_reg_1; /* Mode register 1 */ + ffreg_t intr_status_reg;/* Interrupt Status register */ + ffreg_t mask_reg; /* Mask Register */ + ffreg_t cell_ctr_high1; /* Total cell transfer count (high) */ + ffreg_t cell_ctr_lo1; /* Total cell transfer count (low) */ + ffreg_t state_reg; /* Status register */ + u_int filler4c[0x58 - 0x4c]; + ffreg_t curr_desc_num; /* Contains the current descriptor num */ + ffreg_t next_desc; /* Next descriptor */ + ffreg_t next_vc; /* Next VC */ + u_int filler5b[0x5d - 0x5b]; + ffreg_t present_slot_cnt;/* Present slot count */ + u_int filler5e[0x6a - 0x5e]; + ffreg_t new_desc_num; /* New descriptor number */ + ffreg_t new_vc; /* New VC */ + ffreg_t sched_tbl_ptr; /* Schedule table pointer */ + ffreg_t vbrwq_wptr; /* VBR wait queue write pointer */ + ffreg_t vbrwq_rptr; /* VBR wait queue read pointer */ + ffreg_t abrwq_wptr; /* ABR wait queue write pointer */ + ffreg_t abrwq_rptr; /* ABR wait queue read pointer */ + ffreg_t ubrwq_wptr; /* UBR wait queue write pointer */ + ffreg_t ubrwq_rptr; /* UBR wait queue read pointer */ + ffreg_t cbr_vc; /* CBR VC */ + ffreg_t vbr_sb_vc; /* VBR SB VC */ + ffreg_t abr_sb_vc; /* ABR SB VC */ + ffreg_t ubr_sb_vc; /* UBR SB VC */ + ffreg_t vbr_next_link; /* VBR next link */ + ffreg_t abr_next_link; /* ABR next link */ + ffreg_t ubr_next_link; /* UBR next link */ + u_int filler7a[0x7c-0x7a]; + ffreg_t out_rate_head; /* Out of rate head */ + u_int filler7d[0xca-0x7d]; /* pad out to full address space */ + ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ + ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ + u_int fillercc[0x100-0xcc]; /* pad out to full address space */ } ffredn_t; typedef struct _rfredn_t { @@ -889,79 +889,71 @@ typedef struct ia_rtn_q { } IARTN_Q; #define SUNI_LOSV 0x04 -typedef struct { - u32 suni_master_reset; /* SUNI Master Reset and Identity */ - u32 suni_master_config; /* SUNI Master Configuration */ - u32 suni_master_intr_stat; /* SUNI Master Interrupt Status */ - u32 suni_reserved1; /* Reserved */ - u32 suni_master_clk_monitor;/* SUNI Master Clock Monitor */ - u32 suni_master_control; /* SUNI Master Clock Monitor */ - u32 suni_reserved2[10]; /* Reserved */ - - u32 suni_rsop_control; /* RSOP Control/Interrupt Enable */ - u32 suni_rsop_status; /* RSOP Status/Interrupt States */ - u32 suni_rsop_section_bip8l;/* RSOP Section BIP-8 LSB */ - u32 suni_rsop_section_bip8m;/* RSOP Section BIP-8 MSB */ - - u32 suni_tsop_control; /* TSOP Control */ - u32 suni_tsop_diag; /* TSOP Disgnostics */ - u32 suni_tsop_reserved[2]; /* TSOP Reserved */ - - u32 suni_rlop_cs; /* RLOP Control/Status */ - u32 suni_rlop_intr; /* RLOP Interrupt Enable/Status */ - u32 suni_rlop_line_bip24l; /* RLOP Line BIP-24 LSB */ - u32 suni_rlop_line_bip24; /* RLOP Line BIP-24 */ - u32 suni_rlop_line_bip24m; /* RLOP Line BIP-24 MSB */ - u32 suni_rlop_line_febel; /* RLOP Line FEBE LSB */ - u32 suni_rlop_line_febe; /* RLOP Line FEBE */ - u32 suni_rlop_line_febem; /* RLOP Line FEBE MSB */ - - u32 suni_tlop_control; /* TLOP Control */ - u32 suni_tlop_disg; /* TLOP Disgnostics */ - u32 suni_tlop_reserved[14]; /* TLOP Reserved */ - - u32 suni_rpop_cs; /* RPOP Status/Control */ - u32 suni_rpop_intr; /* RPOP Interrupt/Status */ - u32 suni_rpop_reserved; /* RPOP Reserved */ - u32 suni_rpop_intr_ena; /* RPOP Interrupt Enable */ - u32 suni_rpop_reserved1[3]; /* RPOP Reserved */ - u32 suni_rpop_path_sig; /* RPOP Path Signal Label */ - u32 suni_rpop_bip8l; /* RPOP Path BIP-8 LSB */ - u32 suni_rpop_bip8m; /* RPOP Path BIP-8 MSB */ - u32 suni_rpop_febel; /* RPOP Path FEBE LSB */ - u32 suni_rpop_febem; /* RPOP Path FEBE MSB */ - u32 suni_rpop_reserved2[4]; /* RPOP Reserved */ - - u32 suni_tpop_cntrl_daig; /* TPOP Control/Disgnostics */ - u32 suni_tpop_pointer_ctrl; /* TPOP Pointer Control */ - u32 suni_tpop_sourcer_ctrl; /* TPOP Source Control */ - u32 suni_tpop_reserved1[2]; /* TPOP Reserved */ - u32 suni_tpop_arb_prtl; /* TPOP Arbitrary Pointer LSB */ - u32 suni_tpop_arb_prtm; /* TPOP Arbitrary Pointer MSB */ - u32 suni_tpop_reserved2; /* TPOP Reserved */ - u32 suni_tpop_path_sig; /* TPOP Path Signal Lable */ - u32 suni_tpop_path_status; /* TPOP Path Status */ - u32 suni_tpop_reserved3[6]; /* TPOP Reserved */ - - u32 suni_racp_cs; /* RACP Control/Status */ - u32 suni_racp_intr; /* RACP Interrupt Enable/Status */ - u32 suni_racp_hdr_pattern; /* RACP Match Header Pattern */ - u32 suni_racp_hdr_mask; /* RACP Match Header Mask */ - u32 suni_racp_corr_hcs; /* RACP Correctable HCS Error Count */ - u32 suni_racp_uncorr_hcs; /* RACP Uncorrectable HCS Error Count */ - u32 suni_racp_reserved[10]; /* RACP Reserved */ - - u32 suni_tacp_control; /* TACP Control */ - u32 suni_tacp_idle_hdr_pat; /* TACP Idle Cell Header Pattern */ - u32 suni_tacp_idle_pay_pay; /* TACP Idle Cell Payld Octet Pattern */ - u32 suni_tacp_reserved[5]; /* TACP Reserved */ - - u32 suni_reserved3[24]; /* Reserved */ - - u32 suni_master_test; /* SUNI Master Test */ - u32 suni_reserved_test; /* SUNI Reserved for Test */ -} IA_SUNI; - +enum ia_suni { + SUNI_MASTER_RESET = 0x000, /* SUNI Master Reset and Identity */ + SUNI_MASTER_CONFIG = 0x004, /* SUNI Master Configuration */ + SUNI_MASTER_INTR_STAT = 0x008, /* SUNI Master Interrupt Status */ + SUNI_RESERVED1 = 0x00c, /* Reserved */ + SUNI_MASTER_CLK_MONITOR = 0x010, /* SUNI Master Clock Monitor */ + SUNI_MASTER_CONTROL = 0x014, /* SUNI Master Clock Monitor */ + /* Reserved (10) */ + SUNI_RSOP_CONTROL = 0x040, /* RSOP Control/Interrupt Enable */ + SUNI_RSOP_STATUS = 0x044, /* RSOP Status/Interrupt States */ + SUNI_RSOP_SECTION_BIP8L = 0x048, /* RSOP Section BIP-8 LSB */ + SUNI_RSOP_SECTION_BIP8M = 0x04c, /* RSOP Section BIP-8 MSB */ + + SUNI_TSOP_CONTROL = 0x050, /* TSOP Control */ + SUNI_TSOP_DIAG = 0x054, /* TSOP Disgnostics */ + /* Reserved (2) */ + SUNI_RLOP_CS = 0x060, /* RLOP Control/Status */ + SUNI_RLOP_INTR = 0x064, /* RLOP Interrupt Enable/Status */ + SUNI_RLOP_LINE_BIP24L = 0x068, /* RLOP Line BIP-24 LSB */ + SUNI_RLOP_LINE_BIP24 = 0x06c, /* RLOP Line BIP-24 */ + SUNI_RLOP_LINE_BIP24M = 0x070, /* RLOP Line BIP-24 MSB */ + SUNI_RLOP_LINE_FEBEL = 0x074, /* RLOP Line FEBE LSB */ + SUNI_RLOP_LINE_FEBE = 0x078, /* RLOP Line FEBE */ + SUNI_RLOP_LINE_FEBEM = 0x07c, /* RLOP Line FEBE MSB */ + + SUNI_TLOP_CONTROL = 0x080, /* TLOP Control */ + SUNI_TLOP_DISG = 0x084, /* TLOP Disgnostics */ + /* Reserved (14) */ + SUNI_RPOP_CS = 0x0c0, /* RPOP Status/Control */ + SUNI_RPOP_INTR = 0x0c4, /* RPOP Interrupt/Status */ + SUNI_RPOP_RESERVED = 0x0c8, /* RPOP Reserved */ + SUNI_RPOP_INTR_ENA = 0x0cc, /* RPOP Interrupt Enable */ + /* Reserved (3) */ + SUNI_RPOP_PATH_SIG = 0x0dc, /* RPOP Path Signal Label */ + SUNI_RPOP_BIP8L = 0x0e0, /* RPOP Path BIP-8 LSB */ + SUNI_RPOP_BIP8M = 0x0e4, /* RPOP Path BIP-8 MSB */ + SUNI_RPOP_FEBEL = 0x0e8, /* RPOP Path FEBE LSB */ + SUNI_RPOP_FEBEM = 0x0ec, /* RPOP Path FEBE MSB */ + /* Reserved (4) */ + SUNI_TPOP_CNTRL_DAIG = 0x100, /* TPOP Control/Disgnostics */ + SUNI_TPOP_POINTER_CTRL = 0x104, /* TPOP Pointer Control */ + SUNI_TPOP_SOURCER_CTRL = 0x108, /* TPOP Source Control */ + /* Reserved (2) */ + SUNI_TPOP_ARB_PRTL = 0x114, /* TPOP Arbitrary Pointer LSB */ + SUNI_TPOP_ARB_PRTM = 0x118, /* TPOP Arbitrary Pointer MSB */ + SUNI_TPOP_RESERVED2 = 0x11c, /* TPOP Reserved */ + SUNI_TPOP_PATH_SIG = 0x120, /* TPOP Path Signal Lable */ + SUNI_TPOP_PATH_STATUS = 0x124, /* TPOP Path Status */ + /* Reserved (6) */ + SUNI_RACP_CS = 0x140, /* RACP Control/Status */ + SUNI_RACP_INTR = 0x144, /* RACP Interrupt Enable/Status */ + SUNI_RACP_HDR_PATTERN = 0x148, /* RACP Match Header Pattern */ + SUNI_RACP_HDR_MASK = 0x14c, /* RACP Match Header Mask */ + SUNI_RACP_CORR_HCS = 0x150, /* RACP Correctable HCS Error Count */ + SUNI_RACP_UNCORR_HCS = 0x154, /* RACP Uncorrectable HCS Err Count */ + /* Reserved (10) */ + SUNI_TACP_CONTROL = 0x180, /* TACP Control */ + SUNI_TACP_IDLE_HDR_PAT = 0x184, /* TACP Idle Cell Header Pattern */ + SUNI_TACP_IDLE_PAY_PAY = 0x188, /* TACP Idle Cell Payld Octet Patrn */ + /* Reserved (5) */ + /* Reserved (24) */ + /* FIXME: unused but name conflicts. + * SUNI_MASTER_TEST = 0x200, SUNI Master Test */ + SUNI_RESERVED_TEST = 0x204 /* SUNI Reserved for Test */ +}; typedef struct _SUNI_STATS_ { @@ -993,13 +985,11 @@ typedef struct _SUNI_STATS_ u32 racp_uchcs_count; // uncorrectable HCS error count } IA_SUNI_STATS; -typedef struct iadev_t { +typedef struct iadev_priv { /*-----base pointers into (i)chipSAR+ address space */ - u32 __iomem *phy; /* base pointer into phy(SUNI) */ - u32 __iomem *dma; /* base pointer into DMA control - registers */ - u32 __iomem *reg; /* base pointer to SAR registers - - Bus Interface Control Regs */ + u32 __iomem *phy; /* Base pointer into phy (SUNI). */ + u32 __iomem *dma; /* Base pointer into DMA control registers. */ + u32 __iomem *reg; /* Base pointer to SAR registers. */ u32 __iomem *seg_reg; /* base pointer to segmentation engine internal registers */ u32 __iomem *reass_reg; /* base pointer to reassemble engine @@ -1022,7 +1012,7 @@ typedef struct iadev_t { struct dle_q rx_dle_q; struct free_desc_q *rx_free_desc_qhead; struct sk_buff_head rx_dma_q; - spinlock_t rx_lock, misc_lock; + spinlock_t rx_lock; struct atm_vcc **rx_open; /* list of all open VCs */ u16 num_rx_desc, rx_buf_sz, rxing; u32 rx_pkt_ram, rx_tmp_cnt; @@ -1071,14 +1061,14 @@ typedef struct iadev_t { #define INPH_IA_VCC(v) ((struct ia_vcc *) (v)->dev_data) /******************* IDT77105 25MB/s PHY DEFINE *****************************/ -typedef struct { - u_int mb25_master_ctrl; /* Master control */ - u_int mb25_intr_status; /* Interrupt status */ - u_int mb25_diag_control; /* Diagnostic control */ - u_int mb25_led_hec; /* LED driver and HEC status/control */ - u_int mb25_low_byte_counter; /* Low byte counter */ - u_int mb25_high_byte_counter; /* High byte counter */ -} ia_mb25_t; +enum ia_mb25 { + MB25_MASTER_CTRL = 0x00, /* Master control */ + MB25_INTR_STATUS = 0x04, /* Interrupt status */ + MB25_DIAG_CONTROL = 0x08, /* Diagnostic control */ + MB25_LED_HEC = 0x0c, /* LED driver and HEC status/control */ + MB25_LOW_BYTE_COUNTER = 0x10, + MB25_HIGH_BYTE_COUNTER = 0x14 +}; /* * Master Control @@ -1127,122 +1117,121 @@ typedef struct { #define FE_E3_PHY 0x0090 /* E3 */ /*********************** SUNI_PM7345 PHY DEFINE HERE *********************/ -typedef struct _suni_pm7345_t -{ - u_int suni_config; /* SUNI Configuration */ - u_int suni_intr_enbl; /* SUNI Interrupt Enable */ - u_int suni_intr_stat; /* SUNI Interrupt Status */ - u_int suni_control; /* SUNI Control */ - u_int suni_id_reset; /* SUNI Reset and Identity */ - u_int suni_data_link_ctrl; - u_int suni_rboc_conf_intr_enbl; - u_int suni_rboc_stat; - u_int suni_ds3_frm_cfg; - u_int suni_ds3_frm_intr_enbl; - u_int suni_ds3_frm_intr_stat; - u_int suni_ds3_frm_stat; - u_int suni_rfdl_cfg; - u_int suni_rfdl_enbl_stat; - u_int suni_rfdl_stat; - u_int suni_rfdl_data; - u_int suni_pmon_chng; - u_int suni_pmon_intr_enbl_stat; - u_int suni_reserved1[0x13-0x11]; - u_int suni_pmon_lcv_evt_cnt_lsb; - u_int suni_pmon_lcv_evt_cnt_msb; - u_int suni_pmon_fbe_evt_cnt_lsb; - u_int suni_pmon_fbe_evt_cnt_msb; - u_int suni_pmon_sez_det_cnt_lsb; - u_int suni_pmon_sez_det_cnt_msb; - u_int suni_pmon_pe_evt_cnt_lsb; - u_int suni_pmon_pe_evt_cnt_msb; - u_int suni_pmon_ppe_evt_cnt_lsb; - u_int suni_pmon_ppe_evt_cnt_msb; - u_int suni_pmon_febe_evt_cnt_lsb; - u_int suni_pmon_febe_evt_cnt_msb; - u_int suni_ds3_tran_cfg; - u_int suni_ds3_tran_diag; - u_int suni_reserved2[0x23-0x21]; - u_int suni_xfdl_cfg; - u_int suni_xfdl_intr_st; - u_int suni_xfdl_xmit_data; - u_int suni_xboc_code; - u_int suni_splr_cfg; - u_int suni_splr_intr_en; - u_int suni_splr_intr_st; - u_int suni_splr_status; - u_int suni_splt_cfg; - u_int suni_splt_cntl; - u_int suni_splt_diag_g1; - u_int suni_splt_f1; - u_int suni_cppm_loc_meters; - u_int suni_cppm_chng_of_cppm_perf_meter; - u_int suni_cppm_b1_err_cnt_lsb; - u_int suni_cppm_b1_err_cnt_msb; - u_int suni_cppm_framing_err_cnt_lsb; - u_int suni_cppm_framing_err_cnt_msb; - u_int suni_cppm_febe_cnt_lsb; - u_int suni_cppm_febe_cnt_msb; - u_int suni_cppm_hcs_err_cnt_lsb; - u_int suni_cppm_hcs_err_cnt_msb; - u_int suni_cppm_idle_un_cell_cnt_lsb; - u_int suni_cppm_idle_un_cell_cnt_msb; - u_int suni_cppm_rcv_cell_cnt_lsb; - u_int suni_cppm_rcv_cell_cnt_msb; - u_int suni_cppm_xmit_cell_cnt_lsb; - u_int suni_cppm_xmit_cell_cnt_msb; - u_int suni_rxcp_ctrl; - u_int suni_rxcp_fctrl; - u_int suni_rxcp_intr_en_sts; - u_int suni_rxcp_idle_pat_h1; - u_int suni_rxcp_idle_pat_h2; - u_int suni_rxcp_idle_pat_h3; - u_int suni_rxcp_idle_pat_h4; - u_int suni_rxcp_idle_mask_h1; - u_int suni_rxcp_idle_mask_h2; - u_int suni_rxcp_idle_mask_h3; - u_int suni_rxcp_idle_mask_h4; - u_int suni_rxcp_cell_pat_h1; - u_int suni_rxcp_cell_pat_h2; - u_int suni_rxcp_cell_pat_h3; - u_int suni_rxcp_cell_pat_h4; - u_int suni_rxcp_cell_mask_h1; - u_int suni_rxcp_cell_mask_h2; - u_int suni_rxcp_cell_mask_h3; - u_int suni_rxcp_cell_mask_h4; - u_int suni_rxcp_hcs_cs; - u_int suni_rxcp_lcd_cnt_threshold; - u_int suni_reserved3[0x57-0x54]; - u_int suni_txcp_ctrl; - u_int suni_txcp_intr_en_sts; - u_int suni_txcp_idle_pat_h1; - u_int suni_txcp_idle_pat_h2; - u_int suni_txcp_idle_pat_h3; - u_int suni_txcp_idle_pat_h4; - u_int suni_txcp_idle_pat_h5; - u_int suni_txcp_idle_payload; - u_int suni_e3_frm_fram_options; - u_int suni_e3_frm_maint_options; - u_int suni_e3_frm_fram_intr_enbl; - u_int suni_e3_frm_fram_intr_ind_stat; - u_int suni_e3_frm_maint_intr_enbl; - u_int suni_e3_frm_maint_intr_ind; - u_int suni_e3_frm_maint_stat; - u_int suni_reserved4; - u_int suni_e3_tran_fram_options; - u_int suni_e3_tran_stat_diag_options; - u_int suni_e3_tran_bip_8_err_mask; - u_int suni_e3_tran_maint_adapt_options; - u_int suni_ttb_ctrl; - u_int suni_ttb_trail_trace_id_stat; - u_int suni_ttb_ind_addr; - u_int suni_ttb_ind_data; - u_int suni_ttb_exp_payload_type; - u_int suni_ttb_payload_type_ctrl_stat; - u_int suni_pad5[0x7f-0x71]; - u_int suni_master_test; - u_int suni_pad6[0xff-0x80]; -}suni_pm7345_t; +enum suni_pm7345 { + SUNI_CONFIG = 0x000, /* SUNI Configuration */ + SUNI_INTR_ENBL = 0x004, /* SUNI Interrupt Enable */ + SUNI_INTR_STAT = 0x008, /* SUNI Interrupt Status */ + SUNI_CONTROL = 0x00c, /* SUNI Control */ + SUNI_ID_RESET = 0x010, /* SUNI Reset and Identity */ + SUNI_DATA_LINK_CTRL = 0x014, + SUNI_RBOC_CONF_INTR_ENBL = 0x018, + SUNI_RBOC_STAT = 0x01c, + SUNI_DS3_FRM_CFG = 0x020, + SUNI_DS3_FRM_INTR_ENBL = 0x024, + SUNI_DS3_FRM_INTR_STAT = 0x028, + SUNI_DS3_FRM_STAT = 0x02c, + SUNI_RFDL_CFG = 0x030, + SUNI_RFDL_ENBL_STAT = 0x034, + SUNI_RFDL_STAT = 0x038, + SUNI_RFDL_DATA = 0x03c, + SUNI_PMON_CHNG = 0x040, + SUNI_PMON_INTR_ENBL_STAT = 0x044, + /* SUNI_RESERVED1 (0x13 - 0x11) */ + SUNI_PMON_LCV_EVT_CNT_LSB = 0x050, + SUNI_PMON_LCV_EVT_CNT_MSB = 0x054, + SUNI_PMON_FBE_EVT_CNT_LSB = 0x058, + SUNI_PMON_FBE_EVT_CNT_MSB = 0x05c, + SUNI_PMON_SEZ_DET_CNT_LSB = 0x060, + SUNI_PMON_SEZ_DET_CNT_MSB = 0x064, + SUNI_PMON_PE_EVT_CNT_LSB = 0x068, + SUNI_PMON_PE_EVT_CNT_MSB = 0x06c, + SUNI_PMON_PPE_EVT_CNT_LSB = 0x070, + SUNI_PMON_PPE_EVT_CNT_MSB = 0x074, + SUNI_PMON_FEBE_EVT_CNT_LSB = 0x078, + SUNI_PMON_FEBE_EVT_CNT_MSB = 0x07c, + SUNI_DS3_TRAN_CFG = 0x080, + SUNI_DS3_TRAN_DIAG = 0x084, + /* SUNI_RESERVED2 (0x23 - 0x21) */ + SUNI_XFDL_CFG = 0x090, + SUNI_XFDL_INTR_ST = 0x094, + SUNI_XFDL_XMIT_DATA = 0x098, + SUNI_XBOC_CODE = 0x09c, + SUNI_SPLR_CFG = 0x0a0, + SUNI_SPLR_INTR_EN = 0x0a4, + SUNI_SPLR_INTR_ST = 0x0a8, + SUNI_SPLR_STATUS = 0x0ac, + SUNI_SPLT_CFG = 0x0b0, + SUNI_SPLT_CNTL = 0x0b4, + SUNI_SPLT_DIAG_G1 = 0x0b8, + SUNI_SPLT_F1 = 0x0bc, + SUNI_CPPM_LOC_METERS = 0x0c0, + SUNI_CPPM_CHG_OF_CPPM_PERF_METR = 0x0c4, + SUNI_CPPM_B1_ERR_CNT_LSB = 0x0c8, + SUNI_CPPM_B1_ERR_CNT_MSB = 0x0cc, + SUNI_CPPM_FRAMING_ERR_CNT_LSB = 0x0d0, + SUNI_CPPM_FRAMING_ERR_CNT_MSB = 0x0d4, + SUNI_CPPM_FEBE_CNT_LSB = 0x0d8, + SUNI_CPPM_FEBE_CNT_MSB = 0x0dc, + SUNI_CPPM_HCS_ERR_CNT_LSB = 0x0e0, + SUNI_CPPM_HCS_ERR_CNT_MSB = 0x0e4, + SUNI_CPPM_IDLE_UN_CELL_CNT_LSB = 0x0e8, + SUNI_CPPM_IDLE_UN_CELL_CNT_MSB = 0x0ec, + SUNI_CPPM_RCV_CELL_CNT_LSB = 0x0f0, + SUNI_CPPM_RCV_CELL_CNT_MSB = 0x0f4, + SUNI_CPPM_XMIT_CELL_CNT_LSB = 0x0f8, + SUNI_CPPM_XMIT_CELL_CNT_MSB = 0x0fc, + SUNI_RXCP_CTRL = 0x100, + SUNI_RXCP_FCTRL = 0x104, + SUNI_RXCP_INTR_EN_STS = 0x108, + SUNI_RXCP_IDLE_PAT_H1 = 0x10c, + SUNI_RXCP_IDLE_PAT_H2 = 0x110, + SUNI_RXCP_IDLE_PAT_H3 = 0x114, + SUNI_RXCP_IDLE_PAT_H4 = 0x118, + SUNI_RXCP_IDLE_MASK_H1 = 0x11c, + SUNI_RXCP_IDLE_MASK_H2 = 0x120, + SUNI_RXCP_IDLE_MASK_H3 = 0x124, + SUNI_RXCP_IDLE_MASK_H4 = 0x128, + SUNI_RXCP_CELL_PAT_H1 = 0x12c, + SUNI_RXCP_CELL_PAT_H2 = 0x130, + SUNI_RXCP_CELL_PAT_H3 = 0x134, + SUNI_RXCP_CELL_PAT_H4 = 0x138, + SUNI_RXCP_CELL_MASK_H1 = 0x13c, + SUNI_RXCP_CELL_MASK_H2 = 0x140, + SUNI_RXCP_CELL_MASK_H3 = 0x144, + SUNI_RXCP_CELL_MASK_H4 = 0x148, + SUNI_RXCP_HCS_CS = 0x14c, + SUNI_RXCP_LCD_CNT_THRESHOLD = 0x150, + /* SUNI_RESERVED3 (0x57 - 0x54) */ + SUNI_TXCP_CTRL = 0x160, + SUNI_TXCP_INTR_EN_STS = 0x164, + SUNI_TXCP_IDLE_PAT_H1 = 0x168, + SUNI_TXCP_IDLE_PAT_H2 = 0x16c, + SUNI_TXCP_IDLE_PAT_H3 = 0x170, + SUNI_TXCP_IDLE_PAT_H4 = 0x174, + SUNI_TXCP_IDLE_PAT_H5 = 0x178, + SUNI_TXCP_IDLE_PAYLOAD = 0x17c, + SUNI_E3_FRM_FRAM_OPTIONS = 0x180, + SUNI_E3_FRM_MAINT_OPTIONS = 0x184, + SUNI_E3_FRM_FRAM_INTR_ENBL = 0x188, + SUNI_E3_FRM_FRAM_INTR_IND_STAT = 0x18c, + SUNI_E3_FRM_MAINT_INTR_ENBL = 0x190, + SUNI_E3_FRM_MAINT_INTR_IND = 0x194, + SUNI_E3_FRM_MAINT_STAT = 0x198, + SUNI_RESERVED4 = 0x19c, + SUNI_E3_TRAN_FRAM_OPTIONS = 0x1a0, + SUNI_E3_TRAN_STAT_DIAG_OPTIONS = 0x1a4, + SUNI_E3_TRAN_BIP_8_ERR_MASK = 0x1a8, + SUNI_E3_TRAN_MAINT_ADAPT_OPTS = 0x1ac, + SUNI_TTB_CTRL = 0x1b0, + SUNI_TTB_TRAIL_TRACE_ID_STAT = 0x1b4, + SUNI_TTB_IND_ADDR = 0x1b8, + SUNI_TTB_IND_DATA = 0x1bc, + SUNI_TTB_EXP_PAYLOAD_TYPE = 0x1c0, + SUNI_TTB_PAYLOAD_TYPE_CTRL_STAT = 0x1c4, + /* SUNI_PAD5 (0x7f - 0x71) */ + SUNI_MASTER_TEST = 0x200, + /* SUNI_PAD6 (0xff - 0x80) */ +}; #define SUNI_PM7345_T suni_pm7345_t #define SUNI_PM7345 0x20 /* Suni chip type */ diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index cf97c34cbaf..fa7d701933b 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -55,6 +55,7 @@ */ #include <linux/module.h> +#include <linux/slab.h> #include <linux/mm.h> #include <linux/atmdev.h> #include <asm/io.h> @@ -306,11 +307,10 @@ static void vci_bitfield_iterate(struct lanai_dev *lanai, const unsigned long *lp, void (*func)(struct lanai_dev *,vci_t vci)) { - vci_t vci = find_first_bit(lp, NUM_VCI); - while (vci < NUM_VCI) { + vci_t vci; + + for_each_set_bit(vci, lp, NUM_VCI) func(lanai, vci); - vci = find_next_bit(lp, NUM_VCI, vci + 1); - } } /* -------------------- BUFFER UTILITIES: */ @@ -551,8 +551,8 @@ static inline void sram_write(const struct lanai_dev *lanai, writel(val, sram_addr(lanai, offset)); } -static int __devinit sram_test_word(const struct lanai_dev *lanai, - int offset, u32 pattern) +static int sram_test_word(const struct lanai_dev *lanai, int offset, + u32 pattern) { u32 readback; sram_write(lanai, pattern, offset); @@ -566,7 +566,7 @@ static int __devinit sram_test_word(const struct lanai_dev *lanai, return -EIO; } -static int __devinit sram_test_pass(const struct lanai_dev *lanai, u32 pattern) +static int sram_test_pass(const struct lanai_dev *lanai, u32 pattern) { int offset, result = 0; for (offset = 0; offset < SRAM_BYTES && result == 0; offset += 4) @@ -574,7 +574,7 @@ static int __devinit sram_test_pass(const struct lanai_dev *lanai, u32 pattern) return result; } -static int __devinit sram_test_and_clear(const struct lanai_dev *lanai) +static int sram_test_and_clear(const struct lanai_dev *lanai) { #ifdef FULL_MEMORY_TEST int result; @@ -860,7 +860,7 @@ static inline void aal0_buffer_free(struct lanai_dev *lanai) #ifndef READ_EEPROM /* Stub functions to use if EEPROM reading is disabled */ -static int __devinit eeprom_read(struct lanai_dev *lanai) +static int eeprom_read(struct lanai_dev *lanai) { printk(KERN_INFO DEV_LABEL "(itf %d): *NOT* reading EEPROM\n", lanai->number); @@ -868,7 +868,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai) return 0; } -static int __devinit eeprom_validate(struct lanai_dev *lanai) +static int eeprom_validate(struct lanai_dev *lanai) { lanai->serialno = 0; lanai->magicno = EEPROM_MAGIC_VALUE; @@ -877,7 +877,7 @@ static int __devinit eeprom_validate(struct lanai_dev *lanai) #else /* READ_EEPROM */ -static int __devinit eeprom_read(struct lanai_dev *lanai) +static int eeprom_read(struct lanai_dev *lanai) { int i, address; u8 data; @@ -953,7 +953,7 @@ static inline u32 eeprom_be4(const struct lanai_dev *lanai, int address) } /* Checksum/validate EEPROM contents */ -static int __devinit eeprom_validate(struct lanai_dev *lanai) +static int eeprom_validate(struct lanai_dev *lanai) { int i, s; u32 v; @@ -998,9 +998,7 @@ static int __devinit eeprom_validate(struct lanai_dev *lanai) (unsigned int) e[EEPROM_MAC_REV + i]); return -EIO; } - DPRINTK("eeprom: MAC address = %02X:%02X:%02X:%02X:%02X:%02X\n", - e[EEPROM_MAC + 0], e[EEPROM_MAC + 1], e[EEPROM_MAC + 2], - e[EEPROM_MAC + 3], e[EEPROM_MAC + 4], e[EEPROM_MAC + 5]); + DPRINTK("eeprom: MAC address = %pM\n", &e[EEPROM_MAC]); /* Verify serial number */ lanai->serialno = eeprom_be4(lanai, EEPROM_SERIAL); v = eeprom_be4(lanai, EEPROM_SERIAL_REV); @@ -1257,7 +1255,7 @@ static inline void lanai_endtx(struct lanai_dev *lanai, /* * Since the "butt register" is a shared resounce on the card we * serialize all accesses to it through this spinlock. This is - * mostly just paranoia sicne the register is rarely "busy" anyway + * mostly just paranoia since the register is rarely "busy" anyway * but is needed for correctness. */ spin_lock(&lanai->endtxlock); @@ -1450,7 +1448,7 @@ static void vcc_rx_aal0(struct lanai_dev *lanai) #include <linux/vmalloc.h> #endif -static int __devinit vcc_table_allocate(struct lanai_dev *lanai) +static int vcc_table_allocate(struct lanai_dev *lanai) { #ifdef VCCTABLE_GETFREEPAGE APRINTK((lanai->num_vci) * sizeof(struct lanai_vcc *) <= PAGE_SIZE, @@ -1459,10 +1457,9 @@ static int __devinit vcc_table_allocate(struct lanai_dev *lanai) return (lanai->vccs == NULL) ? -ENOMEM : 0; #else int bytes = (lanai->num_vci) * sizeof(struct lanai_vcc *); - lanai->vccs = (struct lanai_vcc **) vmalloc(bytes); + lanai->vccs = vzalloc(bytes); if (unlikely(lanai->vccs == NULL)) return -ENOMEM; - memset(lanai->vccs, 0, bytes); return 0; #endif } @@ -1575,7 +1572,7 @@ static inline void host_vcc_unbind(struct lanai_dev *lanai, static void lanai_reset(struct lanai_dev *lanai) { - printk(KERN_CRIT DEV_LABEL "(itf %d): *NOT* reseting - not " + printk(KERN_CRIT DEV_LABEL "(itf %d): *NOT* resetting - not " "implemented\n", lanai->number); /* TODO */ /* The following is just a hack until we write the real @@ -1591,7 +1588,7 @@ static void lanai_reset(struct lanai_dev *lanai) /* * Allocate service buffer and tell card about it */ -static int __devinit service_buffer_allocate(struct lanai_dev *lanai) +static int service_buffer_allocate(struct lanai_dev *lanai) { lanai_buf_allocate(&lanai->service, SERVICE_ENTRIES * 4, 8, lanai->pci); @@ -1945,11 +1942,10 @@ static int check_board_id_and_rev(const char *name, u32 val, int *revp) /* -------------------- PCI INITIALIZATION/SHUTDOWN: */ -static int __devinit lanai_pci_start(struct lanai_dev *lanai) +static int lanai_pci_start(struct lanai_dev *lanai) { struct pci_dev *pci = lanai->pci; int result; - u16 w; if (pci_enable_device(pci) != 0) { printk(KERN_ERR DEV_LABEL "(itf %d): can't enable " @@ -1967,13 +1963,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai) "(itf %d): No suitable DMA available.\n", lanai->number); return -EBUSY; } - result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w); - if (result != PCIBIOS_SUCCESSFUL) { - printk(KERN_ERR DEV_LABEL "(itf %d): can't read " - "PCI_SUBSYSTEM_ID: %d\n", lanai->number, result); - return -EINVAL; - } - result = check_board_id_and_rev("PCI", w, NULL); + result = check_board_id_and_rev("PCI", pci->subsystem_device, NULL); if (result != 0) return result; /* Set latency timer to zero as per lanai docs */ @@ -1992,7 +1982,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai) /* * We _can_ use VCI==0 for normal traffic, but only for UBR (or we'll - * get a CBRZERO interrupt), and we can use it only if noone is receiving + * get a CBRZERO interrupt), and we can use it only if no one is receiving * AAL0 traffic (since they will use the same queue) - according to the * docs we shouldn't even use it for AAL0 traffic */ @@ -2133,7 +2123,7 @@ static inline void lanai_cbr_shutdown(struct lanai_dev *lanai) /* -------------------- OPERATIONS: */ /* setup a newly detected device */ -static int __devinit lanai_dev_open(struct atm_dev *atmdev) +static int lanai_dev_open(struct atm_dev *atmdev) { struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; unsigned long raw_base; @@ -2243,11 +2233,8 @@ static int __devinit lanai_dev_open(struct atm_dev *atmdev) memcpy(atmdev->esi, eeprom_mac(lanai), ESI_LEN); lanai_timed_poll_start(lanai); printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=0x%lx, irq=%u " - "(%02X-%02X-%02X-%02X-%02X-%02X)\n", lanai->number, - (int) lanai->pci->revision, (unsigned long) lanai->base, - lanai->pci->irq, - atmdev->esi[0], atmdev->esi[1], atmdev->esi[2], - atmdev->esi[3], atmdev->esi[4], atmdev->esi[5]); + "(%pMF)\n", lanai->number, (int) lanai->pci->revision, + (unsigned long) lanai->base, lanai->pci->irq, atmdev->esi); printk(KERN_NOTICE DEV_LABEL "(itf %d): LANAI%s, serialno=%u(0x%X), " "board_rev=%d\n", lanai->number, lanai->type==lanai2 ? "2" : "HB", (unsigned int) lanai->serialno, @@ -2483,14 +2470,8 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page) return sprintf(page, "revision: board=%d, pci_if=%d\n", lanai->board_rev, (int) lanai->pci->revision); if (left-- == 0) - return sprintf(page, "EEPROM ESI: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - lanai->eeprom[EEPROM_MAC + 0], - lanai->eeprom[EEPROM_MAC + 1], - lanai->eeprom[EEPROM_MAC + 2], - lanai->eeprom[EEPROM_MAC + 3], - lanai->eeprom[EEPROM_MAC + 4], - lanai->eeprom[EEPROM_MAC + 5]); + return sprintf(page, "EEPROM ESI: %pM\n", + &lanai->eeprom[EEPROM_MAC]); if (left-- == 0) return sprintf(page, "status: SOOL=%d, LOCD=%d, LED=%d, " "GPIN=%d\n", (lanai->status & STATUS_SOOL) ? 1 : 0, @@ -2585,8 +2566,8 @@ static const struct atmdev_ops ops = { }; /* initialize one probed card */ -static int __devinit lanai_init_one(struct pci_dev *pci, - const struct pci_device_id *ident) +static int lanai_init_one(struct pci_dev *pci, + const struct pci_device_id *ident) { struct lanai_dev *lanai; struct atm_dev *atmdev; @@ -2599,7 +2580,7 @@ static int __devinit lanai_init_one(struct pci_dev *pci, return -ENOMEM; } - atmdev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); + atmdev = atm_dev_register(DEV_LABEL, &pci->dev, &ops, -1, NULL); if (atmdev == NULL) { printk(KERN_ERR DEV_LABEL ": couldn't register atm device!\n"); diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 3da804b1627..9988ac98b6d 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -1,5 +1,4 @@ -/****************************************************************************** - * +/* * nicstar.c * * Device driver supporting CBR for IDT 77201/77211 "NICStAR" based cards. @@ -16,12 +15,10 @@ * * * (C) INESC 1999 - * - * - ******************************************************************************/ - + */ -/**** IMPORTANT INFORMATION *************************************************** +/* + * IMPORTANT INFORMATION * * There are currently three types of spinlocks: * @@ -31,9 +28,9 @@ * * These must NEVER be grabbed in reverse order. * - ******************************************************************************/ + */ -/* Header files ***************************************************************/ +/* Header files */ #include <linux/module.h> #include <linux/kernel.h> @@ -41,6 +38,7 @@ #include <linux/atmdev.h> #include <linux/atm.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/types.h> #include <linux/string.h> #include <linux/delay.h> @@ -49,9 +47,12 @@ #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/bitops.h> +#include <linux/slab.h> +#include <linux/idr.h> #include <asm/io.h> #include <asm/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h> +#include <linux/etherdevice.h> #include "nicstar.h" #ifdef CONFIG_ATM_NICSTAR_USE_SUNI #include "suni.h" @@ -60,16 +61,11 @@ #include "idt77105.h" #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ -#if BITS_PER_LONG != 32 -# error FIXME: this driver requires a 32-bit platform -#endif - -/* Additional code ************************************************************/ +/* Additional code */ #include "nicstarmac.c" - -/* Configurable parameters ****************************************************/ +/* Configurable parameters */ #undef PHY_LOOPBACK #undef TX_DEBUG @@ -77,11 +73,10 @@ #undef GENERAL_DEBUG #undef EXTRA_DEBUG -#undef NS_USE_DESTRUCTORS /* For now keep this undefined unless you know - you're going to use only raw ATM */ - +#undef NS_USE_DESTRUCTORS /* For now keep this undefined unless you know + you're going to use only raw ATM */ -/* Do not touch these *********************************************************/ +/* Do not touch these */ #ifdef TX_DEBUG #define TXPRINTK(args...) printk(args) @@ -107,2910 +102,2736 @@ #define XPRINTK(args...) #endif /* EXTRA_DEBUG */ - -/* Macros *********************************************************************/ +/* Macros */ #define CMD_BUSY(card) (readl((card)->membase + STAT) & NS_STAT_CMDBZ) #define NS_DELAY mdelay(1) -#define ALIGN_BUS_ADDR(addr, alignment) \ - ((((u32) (addr)) + (((u32) (alignment)) - 1)) & ~(((u32) (alignment)) - 1)) -#define ALIGN_ADDRESS(addr, alignment) \ - bus_to_virt(ALIGN_BUS_ADDR(virt_to_bus(addr), alignment)) - -#undef CEIL +#define PTR_DIFF(a, b) ((u32)((unsigned long)(a) - (unsigned long)(b))) #ifndef ATM_SKB #define ATM_SKB(s) (&(s)->atm) #endif +#define scq_virt_to_bus(scq, p) \ + (scq->dma + ((unsigned long)(p) - (unsigned long)(scq)->org)) -/* Function declarations ******************************************************/ +/* Function declarations */ -static u32 ns_read_sram(ns_dev *card, u32 sram_address); -static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count); -static int __devinit ns_init_card(int i, struct pci_dev *pcidev); -static void __devinit ns_init_card_error(ns_dev *card, int error); -static scq_info *get_scq(int size, u32 scd); -static void free_scq(scq_info *scq, struct atm_vcc *vcc); +static u32 ns_read_sram(ns_dev * card, u32 sram_address); +static void ns_write_sram(ns_dev * card, u32 sram_address, u32 * value, + int count); +static int ns_init_card(int i, struct pci_dev *pcidev); +static void ns_init_card_error(ns_dev * card, int error); +static scq_info *get_scq(ns_dev *card, int size, u32 scd); +static void free_scq(ns_dev *card, scq_info * scq, struct atm_vcc *vcc); static void push_rxbufs(ns_dev *, struct sk_buff *); static irqreturn_t ns_irq_handler(int irq, void *dev_id); static int ns_open(struct atm_vcc *vcc); static void ns_close(struct atm_vcc *vcc); -static void fill_tst(ns_dev *card, int n, vc_map *vc); +static void fill_tst(ns_dev * card, int n, vc_map * vc); static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb); -static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, - struct sk_buff *skb); -static void process_tsq(ns_dev *card); -static void drain_scq(ns_dev *card, scq_info *scq, int pos); -static void process_rsq(ns_dev *card); -static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe); +static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd, + struct sk_buff *skb); +static void process_tsq(ns_dev * card); +static void drain_scq(ns_dev * card, scq_info * scq, int pos); +static void process_rsq(ns_dev * card); +static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe); #ifdef NS_USE_DESTRUCTORS static void ns_sb_destructor(struct sk_buff *sb); static void ns_lb_destructor(struct sk_buff *lb); static void ns_hb_destructor(struct sk_buff *hb); #endif /* NS_USE_DESTRUCTORS */ -static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb); -static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count); -static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb); -static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb); -static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb); -static int ns_proc_read(struct atm_dev *dev, loff_t *pos, char *page); -static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg); -static void which_list(ns_dev *card, struct sk_buff *skb); +static void recycle_rx_buf(ns_dev * card, struct sk_buff *skb); +static void recycle_iovec_rx_bufs(ns_dev * card, struct iovec *iov, int count); +static void recycle_iov_buf(ns_dev * card, struct sk_buff *iovb); +static void dequeue_sm_buf(ns_dev * card, struct sk_buff *sb); +static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb); +static int ns_proc_read(struct atm_dev *dev, loff_t * pos, char *page); +static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg); +#ifdef EXTRA_DEBUG +static void which_list(ns_dev * card, struct sk_buff *skb); +#endif static void ns_poll(unsigned long arg); -static int ns_parse_mac(char *mac, unsigned char *esi); -static short ns_h2i(char c); static void ns_phy_put(struct atm_dev *dev, unsigned char value, - unsigned long addr); + unsigned long addr); static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr); - - -/* Global variables ***********************************************************/ +/* Global variables */ static struct ns_dev *cards[NS_MAX_CARDS]; static unsigned num_cards; -static struct atmdev_ops atm_ops = -{ - .open = ns_open, - .close = ns_close, - .ioctl = ns_ioctl, - .send = ns_send, - .phy_put = ns_phy_put, - .phy_get = ns_phy_get, - .proc_read = ns_proc_read, - .owner = THIS_MODULE, +static struct atmdev_ops atm_ops = { + .open = ns_open, + .close = ns_close, + .ioctl = ns_ioctl, + .send = ns_send, + .phy_put = ns_phy_put, + .phy_get = ns_phy_get, + .proc_read = ns_proc_read, + .owner = THIS_MODULE, }; + static struct timer_list ns_timer; static char *mac[NS_MAX_CARDS]; module_param_array(mac, charp, NULL, 0); MODULE_LICENSE("GPL"); +/* Functions */ -/* Functions*******************************************************************/ - -static int __devinit nicstar_init_one(struct pci_dev *pcidev, - const struct pci_device_id *ent) +static int nicstar_init_one(struct pci_dev *pcidev, + const struct pci_device_id *ent) { - static int index = -1; - unsigned int error; + static int index = -1; + unsigned int error; - index++; - cards[index] = NULL; + index++; + cards[index] = NULL; - error = ns_init_card(index, pcidev); - if (error) { - cards[index--] = NULL; /* don't increment index */ - goto err_out; - } + error = ns_init_card(index, pcidev); + if (error) { + cards[index--] = NULL; /* don't increment index */ + goto err_out; + } - return 0; + return 0; err_out: - return -ENODEV; + return -ENODEV; } - - -static void __devexit nicstar_remove_one(struct pci_dev *pcidev) +static void nicstar_remove_one(struct pci_dev *pcidev) { - int i, j; - ns_dev *card = pci_get_drvdata(pcidev); - struct sk_buff *hb; - struct sk_buff *iovb; - struct sk_buff *lb; - struct sk_buff *sb; - - i = card->index; - - if (cards[i] == NULL) - return; - - if (card->atmdev->phy && card->atmdev->phy->stop) - card->atmdev->phy->stop(card->atmdev); - - /* Stop everything */ - writel(0x00000000, card->membase + CFG); - - /* De-register device */ - atm_dev_deregister(card->atmdev); - - /* Disable PCI device */ - pci_disable_device(pcidev); - - /* Free up resources */ - j = 0; - PRINTK("nicstar%d: freeing %d huge buffers.\n", i, card->hbpool.count); - while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) - { - dev_kfree_skb_any(hb); - j++; - } - PRINTK("nicstar%d: %d huge buffers freed.\n", i, j); - j = 0; - PRINTK("nicstar%d: freeing %d iovec buffers.\n", i, card->iovpool.count); - while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) - { - dev_kfree_skb_any(iovb); - j++; - } - PRINTK("nicstar%d: %d iovec buffers freed.\n", i, j); - while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) - dev_kfree_skb_any(lb); - while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) - dev_kfree_skb_any(sb); - free_scq(card->scq0, NULL); - for (j = 0; j < NS_FRSCD_NUM; j++) - { - if (card->scd2vc[j] != NULL) - free_scq(card->scd2vc[j]->scq, card->scd2vc[j]->tx_vcc); - } - kfree(card->rsq.org); - kfree(card->tsq.org); - free_irq(card->pcidev->irq, card); - iounmap(card->membase); - kfree(card); + int i, j; + ns_dev *card = pci_get_drvdata(pcidev); + struct sk_buff *hb; + struct sk_buff *iovb; + struct sk_buff *lb; + struct sk_buff *sb; + + i = card->index; + + if (cards[i] == NULL) + return; + + if (card->atmdev->phy && card->atmdev->phy->stop) + card->atmdev->phy->stop(card->atmdev); + + /* Stop everything */ + writel(0x00000000, card->membase + CFG); + + /* De-register device */ + atm_dev_deregister(card->atmdev); + + /* Disable PCI device */ + pci_disable_device(pcidev); + + /* Free up resources */ + j = 0; + PRINTK("nicstar%d: freeing %d huge buffers.\n", i, card->hbpool.count); + while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) { + dev_kfree_skb_any(hb); + j++; + } + PRINTK("nicstar%d: %d huge buffers freed.\n", i, j); + j = 0; + PRINTK("nicstar%d: freeing %d iovec buffers.\n", i, + card->iovpool.count); + while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) { + dev_kfree_skb_any(iovb); + j++; + } + PRINTK("nicstar%d: %d iovec buffers freed.\n", i, j); + while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) + dev_kfree_skb_any(lb); + while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) + dev_kfree_skb_any(sb); + free_scq(card, card->scq0, NULL); + for (j = 0; j < NS_FRSCD_NUM; j++) { + if (card->scd2vc[j] != NULL) + free_scq(card, card->scd2vc[j]->scq, card->scd2vc[j]->tx_vcc); + } + idr_destroy(&card->idr); + pci_free_consistent(card->pcidev, NS_RSQSIZE + NS_RSQ_ALIGNMENT, + card->rsq.org, card->rsq.dma); + pci_free_consistent(card->pcidev, NS_TSQSIZE + NS_TSQ_ALIGNMENT, + card->tsq.org, card->tsq.dma); + free_irq(card->pcidev->irq, card); + iounmap(card->membase); + kfree(card); } - - -static struct pci_device_id nicstar_pci_tbl[] __devinitdata = -{ - {PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_IDT_IDT77201, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +static struct pci_device_id nicstar_pci_tbl[] = { + { PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77201), 0 }, {0,} /* terminate list */ }; -MODULE_DEVICE_TABLE(pci, nicstar_pci_tbl); - +MODULE_DEVICE_TABLE(pci, nicstar_pci_tbl); static struct pci_driver nicstar_driver = { - .name = "nicstar", - .id_table = nicstar_pci_tbl, - .probe = nicstar_init_one, - .remove = __devexit_p(nicstar_remove_one), + .name = "nicstar", + .id_table = nicstar_pci_tbl, + .probe = nicstar_init_one, + .remove = nicstar_remove_one, }; - - static int __init nicstar_init(void) { - unsigned error = 0; /* Initialized to remove compile warning */ + unsigned error = 0; /* Initialized to remove compile warning */ + + XPRINTK("nicstar: nicstar_init() called.\n"); - XPRINTK("nicstar: nicstar_init() called.\n"); + error = pci_register_driver(&nicstar_driver); - error = pci_register_driver(&nicstar_driver); - - TXPRINTK("nicstar: TX debug enabled.\n"); - RXPRINTK("nicstar: RX debug enabled.\n"); - PRINTK("nicstar: General debug enabled.\n"); + TXPRINTK("nicstar: TX debug enabled.\n"); + RXPRINTK("nicstar: RX debug enabled.\n"); + PRINTK("nicstar: General debug enabled.\n"); #ifdef PHY_LOOPBACK - printk("nicstar: using PHY loopback.\n"); + printk("nicstar: using PHY loopback.\n"); #endif /* PHY_LOOPBACK */ - XPRINTK("nicstar: nicstar_init() returned.\n"); - - if (!error) { - init_timer(&ns_timer); - ns_timer.expires = jiffies + NS_POLL_PERIOD; - ns_timer.data = 0UL; - ns_timer.function = ns_poll; - add_timer(&ns_timer); - } - - return error; -} + XPRINTK("nicstar: nicstar_init() returned.\n"); + if (!error) { + init_timer(&ns_timer); + ns_timer.expires = jiffies + NS_POLL_PERIOD; + ns_timer.data = 0UL; + ns_timer.function = ns_poll; + add_timer(&ns_timer); + } + return error; +} static void __exit nicstar_cleanup(void) { - XPRINTK("nicstar: nicstar_cleanup() called.\n"); + XPRINTK("nicstar: nicstar_cleanup() called.\n"); - del_timer(&ns_timer); + del_timer(&ns_timer); - pci_unregister_driver(&nicstar_driver); + pci_unregister_driver(&nicstar_driver); - XPRINTK("nicstar: nicstar_cleanup() returned.\n"); + XPRINTK("nicstar: nicstar_cleanup() returned.\n"); } - - -static u32 ns_read_sram(ns_dev *card, u32 sram_address) +static u32 ns_read_sram(ns_dev * card, u32 sram_address) { - unsigned long flags; - u32 data; - sram_address <<= 2; - sram_address &= 0x0007FFFC; /* address must be dword aligned */ - sram_address |= 0x50000000; /* SRAM read command */ - spin_lock_irqsave(&card->res_lock, flags); - while (CMD_BUSY(card)); - writel(sram_address, card->membase + CMD); - while (CMD_BUSY(card)); - data = readl(card->membase + DR0); - spin_unlock_irqrestore(&card->res_lock, flags); - return data; + unsigned long flags; + u32 data; + sram_address <<= 2; + sram_address &= 0x0007FFFC; /* address must be dword aligned */ + sram_address |= 0x50000000; /* SRAM read command */ + spin_lock_irqsave(&card->res_lock, flags); + while (CMD_BUSY(card)) ; + writel(sram_address, card->membase + CMD); + while (CMD_BUSY(card)) ; + data = readl(card->membase + DR0); + spin_unlock_irqrestore(&card->res_lock, flags); + return data; } - - -static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count) +static void ns_write_sram(ns_dev * card, u32 sram_address, u32 * value, + int count) { - unsigned long flags; - int i, c; - count--; /* count range now is 0..3 instead of 1..4 */ - c = count; - c <<= 2; /* to use increments of 4 */ - spin_lock_irqsave(&card->res_lock, flags); - while (CMD_BUSY(card)); - for (i = 0; i <= c; i += 4) - writel(*(value++), card->membase + i); - /* Note: DR# registers are the first 4 dwords in nicstar's memspace, - so card->membase + DR0 == card->membase */ - sram_address <<= 2; - sram_address &= 0x0007FFFC; - sram_address |= (0x40000000 | count); - writel(sram_address, card->membase + CMD); - spin_unlock_irqrestore(&card->res_lock, flags); + unsigned long flags; + int i, c; + count--; /* count range now is 0..3 instead of 1..4 */ + c = count; + c <<= 2; /* to use increments of 4 */ + spin_lock_irqsave(&card->res_lock, flags); + while (CMD_BUSY(card)) ; + for (i = 0; i <= c; i += 4) + writel(*(value++), card->membase + i); + /* Note: DR# registers are the first 4 dwords in nicstar's memspace, + so card->membase + DR0 == card->membase */ + sram_address <<= 2; + sram_address &= 0x0007FFFC; + sram_address |= (0x40000000 | count); + writel(sram_address, card->membase + CMD); + spin_unlock_irqrestore(&card->res_lock, flags); } - -static int __devinit ns_init_card(int i, struct pci_dev *pcidev) +static int ns_init_card(int i, struct pci_dev *pcidev) { - int j; - struct ns_dev *card = NULL; - unsigned char pci_latency; - unsigned error; - u32 data; - u32 u32d[4]; - u32 ns_cfg_rctsize; - int bcount; - unsigned long membase; - - error = 0; - - if (pci_enable_device(pcidev)) - { - printk("nicstar%d: can't enable PCI device\n", i); - error = 2; - ns_init_card_error(card, error); - return error; - } - - if ((card = kmalloc(sizeof(ns_dev), GFP_KERNEL)) == NULL) - { - printk("nicstar%d: can't allocate memory for device structure.\n", i); - error = 2; - ns_init_card_error(card, error); - return error; - } - cards[i] = card; - spin_lock_init(&card->int_lock); - spin_lock_init(&card->res_lock); - - pci_set_drvdata(pcidev, card); - - card->index = i; - card->atmdev = NULL; - card->pcidev = pcidev; - membase = pci_resource_start(pcidev, 1); - card->membase = ioremap(membase, NS_IOREMAP_SIZE); - if (!card->membase) - { - printk("nicstar%d: can't ioremap() membase.\n",i); - error = 3; - ns_init_card_error(card, error); - return error; - } - PRINTK("nicstar%d: membase at 0x%x.\n", i, card->membase); - - pci_set_master(pcidev); - - if (pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency) != 0) - { - printk("nicstar%d: can't read PCI latency timer.\n", i); - error = 6; - ns_init_card_error(card, error); - return error; - } + int j; + struct ns_dev *card = NULL; + unsigned char pci_latency; + unsigned error; + u32 data; + u32 u32d[4]; + u32 ns_cfg_rctsize; + int bcount; + unsigned long membase; + + error = 0; + + if (pci_enable_device(pcidev)) { + printk("nicstar%d: can't enable PCI device\n", i); + error = 2; + ns_init_card_error(card, error); + return error; + } + if ((pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)) != 0) || + (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32)) != 0)) { + printk(KERN_WARNING + "nicstar%d: No suitable DMA available.\n", i); + error = 2; + ns_init_card_error(card, error); + return error; + } + + if ((card = kmalloc(sizeof(ns_dev), GFP_KERNEL)) == NULL) { + printk + ("nicstar%d: can't allocate memory for device structure.\n", + i); + error = 2; + ns_init_card_error(card, error); + return error; + } + cards[i] = card; + spin_lock_init(&card->int_lock); + spin_lock_init(&card->res_lock); + + pci_set_drvdata(pcidev, card); + + card->index = i; + card->atmdev = NULL; + card->pcidev = pcidev; + membase = pci_resource_start(pcidev, 1); + card->membase = ioremap(membase, NS_IOREMAP_SIZE); + if (!card->membase) { + printk("nicstar%d: can't ioremap() membase.\n", i); + error = 3; + ns_init_card_error(card, error); + return error; + } + PRINTK("nicstar%d: membase at 0x%p.\n", i, card->membase); + + pci_set_master(pcidev); + + if (pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency) != 0) { + printk("nicstar%d: can't read PCI latency timer.\n", i); + error = 6; + ns_init_card_error(card, error); + return error; + } #ifdef NS_PCI_LATENCY - if (pci_latency < NS_PCI_LATENCY) - { - PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i, NS_PCI_LATENCY); - for (j = 1; j < 4; j++) - { - if (pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0) - break; - } - if (j == 4) - { - printk("nicstar%d: can't set PCI latency timer to %d.\n", i, NS_PCI_LATENCY); - error = 7; - ns_init_card_error(card, error); - return error; - } - } + if (pci_latency < NS_PCI_LATENCY) { + PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i, + NS_PCI_LATENCY); + for (j = 1; j < 4; j++) { + if (pci_write_config_byte + (pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0) + break; + } + if (j == 4) { + printk + ("nicstar%d: can't set PCI latency timer to %d.\n", + i, NS_PCI_LATENCY); + error = 7; + ns_init_card_error(card, error); + return error; + } + } #endif /* NS_PCI_LATENCY */ - - /* Clear timer overflow */ - data = readl(card->membase + STAT); - if (data & NS_STAT_TMROF) - writel(NS_STAT_TMROF, card->membase + STAT); - - /* Software reset */ - writel(NS_CFG_SWRST, card->membase + CFG); - NS_DELAY; - writel(0x00000000, card->membase + CFG); - - /* PHY reset */ - writel(0x00000008, card->membase + GP); - NS_DELAY; - writel(0x00000001, card->membase + GP); - NS_DELAY; - while (CMD_BUSY(card)); - writel(NS_CMD_WRITE_UTILITY | 0x00000100, card->membase + CMD); /* Sync UTOPIA with SAR clock */ - NS_DELAY; - - /* Detect PHY type */ - while (CMD_BUSY(card)); - writel(NS_CMD_READ_UTILITY | 0x00000200, card->membase + CMD); - while (CMD_BUSY(card)); - data = readl(card->membase + DR0); - switch(data) { - case 0x00000009: - printk("nicstar%d: PHY seems to be 25 Mbps.\n", i); - card->max_pcr = ATM_25_PCR; - while(CMD_BUSY(card)); - writel(0x00000008, card->membase + DR0); - writel(NS_CMD_WRITE_UTILITY | 0x00000200, card->membase + CMD); - /* Clear an eventual pending interrupt */ - writel(NS_STAT_SFBQF, card->membase + STAT); + + /* Clear timer overflow */ + data = readl(card->membase + STAT); + if (data & NS_STAT_TMROF) + writel(NS_STAT_TMROF, card->membase + STAT); + + /* Software reset */ + writel(NS_CFG_SWRST, card->membase + CFG); + NS_DELAY; + writel(0x00000000, card->membase + CFG); + + /* PHY reset */ + writel(0x00000008, card->membase + GP); + NS_DELAY; + writel(0x00000001, card->membase + GP); + NS_DELAY; + while (CMD_BUSY(card)) ; + writel(NS_CMD_WRITE_UTILITY | 0x00000100, card->membase + CMD); /* Sync UTOPIA with SAR clock */ + NS_DELAY; + + /* Detect PHY type */ + while (CMD_BUSY(card)) ; + writel(NS_CMD_READ_UTILITY | 0x00000200, card->membase + CMD); + while (CMD_BUSY(card)) ; + data = readl(card->membase + DR0); + switch (data) { + case 0x00000009: + printk("nicstar%d: PHY seems to be 25 Mbps.\n", i); + card->max_pcr = ATM_25_PCR; + while (CMD_BUSY(card)) ; + writel(0x00000008, card->membase + DR0); + writel(NS_CMD_WRITE_UTILITY | 0x00000200, card->membase + CMD); + /* Clear an eventual pending interrupt */ + writel(NS_STAT_SFBQF, card->membase + STAT); #ifdef PHY_LOOPBACK - while(CMD_BUSY(card)); - writel(0x00000022, card->membase + DR0); - writel(NS_CMD_WRITE_UTILITY | 0x00000202, card->membase + CMD); + while (CMD_BUSY(card)) ; + writel(0x00000022, card->membase + DR0); + writel(NS_CMD_WRITE_UTILITY | 0x00000202, card->membase + CMD); #endif /* PHY_LOOPBACK */ - break; - case 0x00000030: - case 0x00000031: - printk("nicstar%d: PHY seems to be 155 Mbps.\n", i); - card->max_pcr = ATM_OC3_PCR; + break; + case 0x00000030: + case 0x00000031: + printk("nicstar%d: PHY seems to be 155 Mbps.\n", i); + card->max_pcr = ATM_OC3_PCR; #ifdef PHY_LOOPBACK - while(CMD_BUSY(card)); - writel(0x00000002, card->membase + DR0); - writel(NS_CMD_WRITE_UTILITY | 0x00000205, card->membase + CMD); + while (CMD_BUSY(card)) ; + writel(0x00000002, card->membase + DR0); + writel(NS_CMD_WRITE_UTILITY | 0x00000205, card->membase + CMD); #endif /* PHY_LOOPBACK */ - break; - default: - printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data); - error = 8; - ns_init_card_error(card, error); - return error; - } - writel(0x00000000, card->membase + GP); - - /* Determine SRAM size */ - data = 0x76543210; - ns_write_sram(card, 0x1C003, &data, 1); - data = 0x89ABCDEF; - ns_write_sram(card, 0x14003, &data, 1); - if (ns_read_sram(card, 0x14003) == 0x89ABCDEF && - ns_read_sram(card, 0x1C003) == 0x76543210) - card->sram_size = 128; - else - card->sram_size = 32; - PRINTK("nicstar%d: %dK x 32bit SRAM size.\n", i, card->sram_size); - - card->rct_size = NS_MAX_RCTSIZE; + break; + default: + printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data); + error = 8; + ns_init_card_error(card, error); + return error; + } + writel(0x00000000, card->membase + GP); + + /* Determine SRAM size */ + data = 0x76543210; + ns_write_sram(card, 0x1C003, &data, 1); + data = 0x89ABCDEF; + ns_write_sram(card, 0x14003, &data, 1); + if (ns_read_sram(card, 0x14003) == 0x89ABCDEF && + ns_read_sram(card, 0x1C003) == 0x76543210) + card->sram_size = 128; + else + card->sram_size = 32; + PRINTK("nicstar%d: %dK x 32bit SRAM size.\n", i, card->sram_size); + + card->rct_size = NS_MAX_RCTSIZE; #if (NS_MAX_RCTSIZE == 4096) - if (card->sram_size == 128) - printk("nicstar%d: limiting maximum VCI. See NS_MAX_RCTSIZE in nicstar.h\n", i); + if (card->sram_size == 128) + printk + ("nicstar%d: limiting maximum VCI. See NS_MAX_RCTSIZE in nicstar.h\n", + i); #elif (NS_MAX_RCTSIZE == 16384) - if (card->sram_size == 32) - { - printk("nicstar%d: wasting memory. See NS_MAX_RCTSIZE in nicstar.h\n", i); - card->rct_size = 4096; - } + if (card->sram_size == 32) { + printk + ("nicstar%d: wasting memory. See NS_MAX_RCTSIZE in nicstar.h\n", + i); + card->rct_size = 4096; + } #else #error NS_MAX_RCTSIZE must be either 4096 or 16384 in nicstar.c #endif - card->vpibits = NS_VPIBITS; - if (card->rct_size == 4096) - card->vcibits = 12 - NS_VPIBITS; - else /* card->rct_size == 16384 */ - card->vcibits = 14 - NS_VPIBITS; - - /* Initialize the nicstar eeprom/eprom stuff, for the MAC addr */ - if (mac[i] == NULL) - nicstar_init_eprom(card->membase); - - /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ - writel(0x00000000, card->membase + VPM); - - /* Initialize TSQ */ - card->tsq.org = kmalloc(NS_TSQSIZE + NS_TSQ_ALIGNMENT, GFP_KERNEL); - if (card->tsq.org == NULL) - { - printk("nicstar%d: can't allocate TSQ.\n", i); - error = 10; - ns_init_card_error(card, error); - return error; - } - card->tsq.base = (ns_tsi *) ALIGN_ADDRESS(card->tsq.org, NS_TSQ_ALIGNMENT); - card->tsq.next = card->tsq.base; - card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1); - for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++) - ns_tsi_init(card->tsq.base + j); - writel(0x00000000, card->membase + TSQH); - writel((u32) virt_to_bus(card->tsq.base), card->membase + TSQB); - PRINTK("nicstar%d: TSQ base at 0x%x 0x%x 0x%x.\n", i, (u32) card->tsq.base, - (u32) virt_to_bus(card->tsq.base), readl(card->membase + TSQB)); - - /* Initialize RSQ */ - card->rsq.org = kmalloc(NS_RSQSIZE + NS_RSQ_ALIGNMENT, GFP_KERNEL); - if (card->rsq.org == NULL) - { - printk("nicstar%d: can't allocate RSQ.\n", i); - error = 11; - ns_init_card_error(card, error); - return error; - } - card->rsq.base = (ns_rsqe *) ALIGN_ADDRESS(card->rsq.org, NS_RSQ_ALIGNMENT); - card->rsq.next = card->rsq.base; - card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1); - for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++) - ns_rsqe_init(card->rsq.base + j); - writel(0x00000000, card->membase + RSQH); - writel((u32) virt_to_bus(card->rsq.base), card->membase + RSQB); - PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base); - - /* Initialize SCQ0, the only VBR SCQ used */ - card->scq1 = NULL; - card->scq2 = NULL; - card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0); - if (card->scq0 == NULL) - { - printk("nicstar%d: can't get SCQ0.\n", i); - error = 12; - ns_init_card_error(card, error); - return error; - } - u32d[0] = (u32) virt_to_bus(card->scq0->base); - u32d[1] = (u32) 0x00000000; - u32d[2] = (u32) 0xffffffff; - u32d[3] = (u32) 0x00000000; - ns_write_sram(card, NS_VRSCD0, u32d, 4); - ns_write_sram(card, NS_VRSCD1, u32d, 4); /* These last two won't be used */ - ns_write_sram(card, NS_VRSCD2, u32d, 4); /* but are initialized, just in case... */ - card->scq0->scd = NS_VRSCD0; - PRINTK("nicstar%d: VBR-SCQ0 base at 0x%x.\n", i, (u32) card->scq0->base); - - /* Initialize TSTs */ - card->tst_addr = NS_TST0; - card->tst_free_entries = NS_TST_NUM_ENTRIES; - data = NS_TST_OPCODE_VARIABLE; - for (j = 0; j < NS_TST_NUM_ENTRIES; j++) - ns_write_sram(card, NS_TST0 + j, &data, 1); - data = ns_tste_make(NS_TST_OPCODE_END, NS_TST0); - ns_write_sram(card, NS_TST0 + NS_TST_NUM_ENTRIES, &data, 1); - for (j = 0; j < NS_TST_NUM_ENTRIES; j++) - ns_write_sram(card, NS_TST1 + j, &data, 1); - data = ns_tste_make(NS_TST_OPCODE_END, NS_TST1); - ns_write_sram(card, NS_TST1 + NS_TST_NUM_ENTRIES, &data, 1); - for (j = 0; j < NS_TST_NUM_ENTRIES; j++) - card->tste2vc[j] = NULL; - writel(NS_TST0 << 2, card->membase + TSTB); - - - /* Initialize RCT. AAL type is set on opening the VC. */ + card->vpibits = NS_VPIBITS; + if (card->rct_size == 4096) + card->vcibits = 12 - NS_VPIBITS; + else /* card->rct_size == 16384 */ + card->vcibits = 14 - NS_VPIBITS; + + /* Initialize the nicstar eeprom/eprom stuff, for the MAC addr */ + if (mac[i] == NULL) + nicstar_init_eprom(card->membase); + + /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ + writel(0x00000000, card->membase + VPM); + + /* Initialize TSQ */ + card->tsq.org = pci_alloc_consistent(card->pcidev, + NS_TSQSIZE + NS_TSQ_ALIGNMENT, + &card->tsq.dma); + if (card->tsq.org == NULL) { + printk("nicstar%d: can't allocate TSQ.\n", i); + error = 10; + ns_init_card_error(card, error); + return error; + } + card->tsq.base = PTR_ALIGN(card->tsq.org, NS_TSQ_ALIGNMENT); + card->tsq.next = card->tsq.base; + card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1); + for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++) + ns_tsi_init(card->tsq.base + j); + writel(0x00000000, card->membase + TSQH); + writel(ALIGN(card->tsq.dma, NS_TSQ_ALIGNMENT), card->membase + TSQB); + PRINTK("nicstar%d: TSQ base at 0x%p.\n", i, card->tsq.base); + + /* Initialize RSQ */ + card->rsq.org = pci_alloc_consistent(card->pcidev, + NS_RSQSIZE + NS_RSQ_ALIGNMENT, + &card->rsq.dma); + if (card->rsq.org == NULL) { + printk("nicstar%d: can't allocate RSQ.\n", i); + error = 11; + ns_init_card_error(card, error); + return error; + } + card->rsq.base = PTR_ALIGN(card->rsq.org, NS_RSQ_ALIGNMENT); + card->rsq.next = card->rsq.base; + card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1); + for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++) + ns_rsqe_init(card->rsq.base + j); + writel(0x00000000, card->membase + RSQH); + writel(ALIGN(card->rsq.dma, NS_RSQ_ALIGNMENT), card->membase + RSQB); + PRINTK("nicstar%d: RSQ base at 0x%p.\n", i, card->rsq.base); + + /* Initialize SCQ0, the only VBR SCQ used */ + card->scq1 = NULL; + card->scq2 = NULL; + card->scq0 = get_scq(card, VBR_SCQSIZE, NS_VRSCD0); + if (card->scq0 == NULL) { + printk("nicstar%d: can't get SCQ0.\n", i); + error = 12; + ns_init_card_error(card, error); + return error; + } + u32d[0] = scq_virt_to_bus(card->scq0, card->scq0->base); + u32d[1] = (u32) 0x00000000; + u32d[2] = (u32) 0xffffffff; + u32d[3] = (u32) 0x00000000; + ns_write_sram(card, NS_VRSCD0, u32d, 4); + ns_write_sram(card, NS_VRSCD1, u32d, 4); /* These last two won't be used */ + ns_write_sram(card, NS_VRSCD2, u32d, 4); /* but are initialized, just in case... */ + card->scq0->scd = NS_VRSCD0; + PRINTK("nicstar%d: VBR-SCQ0 base at 0x%p.\n", i, card->scq0->base); + + /* Initialize TSTs */ + card->tst_addr = NS_TST0; + card->tst_free_entries = NS_TST_NUM_ENTRIES; + data = NS_TST_OPCODE_VARIABLE; + for (j = 0; j < NS_TST_NUM_ENTRIES; j++) + ns_write_sram(card, NS_TST0 + j, &data, 1); + data = ns_tste_make(NS_TST_OPCODE_END, NS_TST0); + ns_write_sram(card, NS_TST0 + NS_TST_NUM_ENTRIES, &data, 1); + for (j = 0; j < NS_TST_NUM_ENTRIES; j++) + ns_write_sram(card, NS_TST1 + j, &data, 1); + data = ns_tste_make(NS_TST_OPCODE_END, NS_TST1); + ns_write_sram(card, NS_TST1 + NS_TST_NUM_ENTRIES, &data, 1); + for (j = 0; j < NS_TST_NUM_ENTRIES; j++) + card->tste2vc[j] = NULL; + writel(NS_TST0 << 2, card->membase + TSTB); + + /* Initialize RCT. AAL type is set on opening the VC. */ #ifdef RCQ_SUPPORT - u32d[0] = NS_RCTE_RAWCELLINTEN; + u32d[0] = NS_RCTE_RAWCELLINTEN; #else - u32d[0] = 0x00000000; + u32d[0] = 0x00000000; #endif /* RCQ_SUPPORT */ - u32d[1] = 0x00000000; - u32d[2] = 0x00000000; - u32d[3] = 0xFFFFFFFF; - for (j = 0; j < card->rct_size; j++) - ns_write_sram(card, j * 4, u32d, 4); - - memset(card->vcmap, 0, NS_MAX_RCTSIZE * sizeof(vc_map)); - - for (j = 0; j < NS_FRSCD_NUM; j++) - card->scd2vc[j] = NULL; - - /* Initialize buffer levels */ - card->sbnr.min = MIN_SB; - card->sbnr.init = NUM_SB; - card->sbnr.max = MAX_SB; - card->lbnr.min = MIN_LB; - card->lbnr.init = NUM_LB; - card->lbnr.max = MAX_LB; - card->iovnr.min = MIN_IOVB; - card->iovnr.init = NUM_IOVB; - card->iovnr.max = MAX_IOVB; - card->hbnr.min = MIN_HB; - card->hbnr.init = NUM_HB; - card->hbnr.max = MAX_HB; - - card->sm_handle = 0x00000000; - card->sm_addr = 0x00000000; - card->lg_handle = 0x00000000; - card->lg_addr = 0x00000000; - - card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */ - - /* Pre-allocate some huge buffers */ - skb_queue_head_init(&card->hbpool.queue); - card->hbpool.count = 0; - for (j = 0; j < NUM_HB; j++) - { - struct sk_buff *hb; - hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); - if (hb == NULL) - { - printk("nicstar%d: can't allocate %dth of %d huge buffers.\n", - i, j, NUM_HB); - error = 13; - ns_init_card_error(card, error); - return error; - } - NS_SKB_CB(hb)->buf_type = BUF_NONE; - skb_queue_tail(&card->hbpool.queue, hb); - card->hbpool.count++; - } - - - /* Allocate large buffers */ - skb_queue_head_init(&card->lbpool.queue); - card->lbpool.count = 0; /* Not used */ - for (j = 0; j < NUM_LB; j++) - { - struct sk_buff *lb; - lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); - if (lb == NULL) - { - printk("nicstar%d: can't allocate %dth of %d large buffers.\n", - i, j, NUM_LB); - error = 14; - ns_init_card_error(card, error); - return error; - } - NS_SKB_CB(lb)->buf_type = BUF_LG; - skb_queue_tail(&card->lbpool.queue, lb); - skb_reserve(lb, NS_SMBUFSIZE); - push_rxbufs(card, lb); - /* Due to the implementation of push_rxbufs() this is 1, not 0 */ - if (j == 1) - { - card->rcbuf = lb; - card->rawch = (u32) virt_to_bus(lb->data); - } - } - /* Test for strange behaviour which leads to crashes */ - if ((bcount = ns_stat_lfbqc_get(readl(card->membase + STAT))) < card->lbnr.min) - { - printk("nicstar%d: Strange... Just allocated %d large buffers and lfbqc = %d.\n", - i, j, bcount); - error = 14; - ns_init_card_error(card, error); - return error; - } - - - /* Allocate small buffers */ - skb_queue_head_init(&card->sbpool.queue); - card->sbpool.count = 0; /* Not used */ - for (j = 0; j < NUM_SB; j++) - { - struct sk_buff *sb; - sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); - if (sb == NULL) - { - printk("nicstar%d: can't allocate %dth of %d small buffers.\n", - i, j, NUM_SB); - error = 15; - ns_init_card_error(card, error); - return error; - } - NS_SKB_CB(sb)->buf_type = BUF_SM; - skb_queue_tail(&card->sbpool.queue, sb); - skb_reserve(sb, NS_AAL0_HEADER); - push_rxbufs(card, sb); - } - /* Test for strange behaviour which leads to crashes */ - if ((bcount = ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min) - { - printk("nicstar%d: Strange... Just allocated %d small buffers and sfbqc = %d.\n", - i, j, bcount); - error = 15; - ns_init_card_error(card, error); - return error; - } - - - /* Allocate iovec buffers */ - skb_queue_head_init(&card->iovpool.queue); - card->iovpool.count = 0; - for (j = 0; j < NUM_IOVB; j++) - { - struct sk_buff *iovb; - iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); - if (iovb == NULL) - { - printk("nicstar%d: can't allocate %dth of %d iovec buffers.\n", - i, j, NUM_IOVB); - error = 16; - ns_init_card_error(card, error); - return error; - } - NS_SKB_CB(iovb)->buf_type = BUF_NONE; - skb_queue_tail(&card->iovpool.queue, iovb); - card->iovpool.count++; - } - - /* Configure NICStAR */ - if (card->rct_size == 4096) - ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES; - else /* (card->rct_size == 16384) */ - ns_cfg_rctsize = NS_CFG_RCTSIZE_16384_ENTRIES; - - card->efbie = 1; - - card->intcnt = 0; - if (request_irq(pcidev->irq, &ns_irq_handler, IRQF_DISABLED | IRQF_SHARED, "nicstar", card) != 0) - { - printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); - error = 9; - ns_init_card_error(card, error); - return error; - } - - /* Register device */ - card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL); - if (card->atmdev == NULL) - { - printk("nicstar%d: can't register device.\n", i); - error = 17; - ns_init_card_error(card, error); - return error; - } - - if (ns_parse_mac(mac[i], card->atmdev->esi)) { - nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET, - card->atmdev->esi, 6); - if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) == 0) { - nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT, - card->atmdev->esi, 6); - } - } - - printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i, - card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2], - card->atmdev->esi[3], card->atmdev->esi[4], card->atmdev->esi[5]); - - card->atmdev->dev_data = card; - card->atmdev->ci_range.vpi_bits = card->vpibits; - card->atmdev->ci_range.vci_bits = card->vcibits; - card->atmdev->link_rate = card->max_pcr; - card->atmdev->phy = NULL; + u32d[1] = 0x00000000; + u32d[2] = 0x00000000; + u32d[3] = 0xFFFFFFFF; + for (j = 0; j < card->rct_size; j++) + ns_write_sram(card, j * 4, u32d, 4); + + memset(card->vcmap, 0, NS_MAX_RCTSIZE * sizeof(vc_map)); + + for (j = 0; j < NS_FRSCD_NUM; j++) + card->scd2vc[j] = NULL; + + /* Initialize buffer levels */ + card->sbnr.min = MIN_SB; + card->sbnr.init = NUM_SB; + card->sbnr.max = MAX_SB; + card->lbnr.min = MIN_LB; + card->lbnr.init = NUM_LB; + card->lbnr.max = MAX_LB; + card->iovnr.min = MIN_IOVB; + card->iovnr.init = NUM_IOVB; + card->iovnr.max = MAX_IOVB; + card->hbnr.min = MIN_HB; + card->hbnr.init = NUM_HB; + card->hbnr.max = MAX_HB; + + card->sm_handle = NULL; + card->sm_addr = 0x00000000; + card->lg_handle = NULL; + card->lg_addr = 0x00000000; + + card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */ + + idr_init(&card->idr); + + /* Pre-allocate some huge buffers */ + skb_queue_head_init(&card->hbpool.queue); + card->hbpool.count = 0; + for (j = 0; j < NUM_HB; j++) { + struct sk_buff *hb; + hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); + if (hb == NULL) { + printk + ("nicstar%d: can't allocate %dth of %d huge buffers.\n", + i, j, NUM_HB); + error = 13; + ns_init_card_error(card, error); + return error; + } + NS_PRV_BUFTYPE(hb) = BUF_NONE; + skb_queue_tail(&card->hbpool.queue, hb); + card->hbpool.count++; + } + + /* Allocate large buffers */ + skb_queue_head_init(&card->lbpool.queue); + card->lbpool.count = 0; /* Not used */ + for (j = 0; j < NUM_LB; j++) { + struct sk_buff *lb; + lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); + if (lb == NULL) { + printk + ("nicstar%d: can't allocate %dth of %d large buffers.\n", + i, j, NUM_LB); + error = 14; + ns_init_card_error(card, error); + return error; + } + NS_PRV_BUFTYPE(lb) = BUF_LG; + skb_queue_tail(&card->lbpool.queue, lb); + skb_reserve(lb, NS_SMBUFSIZE); + push_rxbufs(card, lb); + /* Due to the implementation of push_rxbufs() this is 1, not 0 */ + if (j == 1) { + card->rcbuf = lb; + card->rawcell = (struct ns_rcqe *) lb->data; + card->rawch = NS_PRV_DMA(lb); + } + } + /* Test for strange behaviour which leads to crashes */ + if ((bcount = + ns_stat_lfbqc_get(readl(card->membase + STAT))) < card->lbnr.min) { + printk + ("nicstar%d: Strange... Just allocated %d large buffers and lfbqc = %d.\n", + i, j, bcount); + error = 14; + ns_init_card_error(card, error); + return error; + } + + /* Allocate small buffers */ + skb_queue_head_init(&card->sbpool.queue); + card->sbpool.count = 0; /* Not used */ + for (j = 0; j < NUM_SB; j++) { + struct sk_buff *sb; + sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); + if (sb == NULL) { + printk + ("nicstar%d: can't allocate %dth of %d small buffers.\n", + i, j, NUM_SB); + error = 15; + ns_init_card_error(card, error); + return error; + } + NS_PRV_BUFTYPE(sb) = BUF_SM; + skb_queue_tail(&card->sbpool.queue, sb); + skb_reserve(sb, NS_AAL0_HEADER); + push_rxbufs(card, sb); + } + /* Test for strange behaviour which leads to crashes */ + if ((bcount = + ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min) { + printk + ("nicstar%d: Strange... Just allocated %d small buffers and sfbqc = %d.\n", + i, j, bcount); + error = 15; + ns_init_card_error(card, error); + return error; + } + + /* Allocate iovec buffers */ + skb_queue_head_init(&card->iovpool.queue); + card->iovpool.count = 0; + for (j = 0; j < NUM_IOVB; j++) { + struct sk_buff *iovb; + iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); + if (iovb == NULL) { + printk + ("nicstar%d: can't allocate %dth of %d iovec buffers.\n", + i, j, NUM_IOVB); + error = 16; + ns_init_card_error(card, error); + return error; + } + NS_PRV_BUFTYPE(iovb) = BUF_NONE; + skb_queue_tail(&card->iovpool.queue, iovb); + card->iovpool.count++; + } + + /* Configure NICStAR */ + if (card->rct_size == 4096) + ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES; + else /* (card->rct_size == 16384) */ + ns_cfg_rctsize = NS_CFG_RCTSIZE_16384_ENTRIES; + + card->efbie = 1; + + card->intcnt = 0; + if (request_irq + (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) { + printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); + error = 9; + ns_init_card_error(card, error); + return error; + } + + /* Register device */ + card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops, + -1, NULL); + if (card->atmdev == NULL) { + printk("nicstar%d: can't register device.\n", i); + error = 17; + ns_init_card_error(card, error); + return error; + } + + if (mac[i] == NULL || !mac_pton(mac[i], card->atmdev->esi)) { + nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET, + card->atmdev->esi, 6); + if (ether_addr_equal(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00")) { + nicstar_read_eprom(card->membase, + NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT, + card->atmdev->esi, 6); + } + } + + printk("nicstar%d: MAC address %pM\n", i, card->atmdev->esi); + + card->atmdev->dev_data = card; + card->atmdev->ci_range.vpi_bits = card->vpibits; + card->atmdev->ci_range.vci_bits = card->vcibits; + card->atmdev->link_rate = card->max_pcr; + card->atmdev->phy = NULL; #ifdef CONFIG_ATM_NICSTAR_USE_SUNI - if (card->max_pcr == ATM_OC3_PCR) - suni_init(card->atmdev); + if (card->max_pcr == ATM_OC3_PCR) + suni_init(card->atmdev); #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105 - if (card->max_pcr == ATM_25_PCR) - idt77105_init(card->atmdev); + if (card->max_pcr == ATM_25_PCR) + idt77105_init(card->atmdev); #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ - if (card->atmdev->phy && card->atmdev->phy->start) - card->atmdev->phy->start(card->atmdev); - - writel(NS_CFG_RXPATH | - NS_CFG_SMBUFSIZE | - NS_CFG_LGBUFSIZE | - NS_CFG_EFBIE | - NS_CFG_RSQSIZE | - NS_CFG_VPIBITS | - ns_cfg_rctsize | - NS_CFG_RXINT_NODELAY | - NS_CFG_RAWIE | /* Only enabled if RCQ_SUPPORT */ - NS_CFG_RSQAFIE | - NS_CFG_TXEN | - NS_CFG_TXIE | - NS_CFG_TSQFIE_OPT | /* Only enabled if ENABLE_TSQFIE */ - NS_CFG_PHYIE, - card->membase + CFG); - - num_cards++; - - return error; -} + if (card->atmdev->phy && card->atmdev->phy->start) + card->atmdev->phy->start(card->atmdev); + writel(NS_CFG_RXPATH | NS_CFG_SMBUFSIZE | NS_CFG_LGBUFSIZE | NS_CFG_EFBIE | NS_CFG_RSQSIZE | NS_CFG_VPIBITS | ns_cfg_rctsize | NS_CFG_RXINT_NODELAY | NS_CFG_RAWIE | /* Only enabled if RCQ_SUPPORT */ + NS_CFG_RSQAFIE | NS_CFG_TXEN | NS_CFG_TXIE | NS_CFG_TSQFIE_OPT | /* Only enabled if ENABLE_TSQFIE */ + NS_CFG_PHYIE, card->membase + CFG); + num_cards++; -static void __devinit ns_init_card_error(ns_dev *card, int error) -{ - if (error >= 17) - { - writel(0x00000000, card->membase + CFG); - } - if (error >= 16) - { - struct sk_buff *iovb; - while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) - dev_kfree_skb_any(iovb); - } - if (error >= 15) - { - struct sk_buff *sb; - while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) - dev_kfree_skb_any(sb); - free_scq(card->scq0, NULL); - } - if (error >= 14) - { - struct sk_buff *lb; - while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) - dev_kfree_skb_any(lb); - } - if (error >= 13) - { - struct sk_buff *hb; - while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) - dev_kfree_skb_any(hb); - } - if (error >= 12) - { - kfree(card->rsq.org); - } - if (error >= 11) - { - kfree(card->tsq.org); - } - if (error >= 10) - { - free_irq(card->pcidev->irq, card); - } - if (error >= 4) - { - iounmap(card->membase); - } - if (error >= 3) - { - pci_disable_device(card->pcidev); - kfree(card); - } + return error; } - - -static scq_info *get_scq(int size, u32 scd) +static void ns_init_card_error(ns_dev *card, int error) { - scq_info *scq; - int i; - - if (size != VBR_SCQSIZE && size != CBR_SCQSIZE) - return NULL; - - scq = kmalloc(sizeof(scq_info), GFP_KERNEL); - if (scq == NULL) - return NULL; - scq->org = kmalloc(2 * size, GFP_KERNEL); - if (scq->org == NULL) - { - kfree(scq); - return NULL; - } - scq->skb = kmalloc(sizeof(struct sk_buff *) * - (size / NS_SCQE_SIZE), GFP_KERNEL); - if (scq->skb == NULL) - { - kfree(scq->org); - kfree(scq); - return NULL; - } - scq->num_entries = size / NS_SCQE_SIZE; - scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size); - scq->next = scq->base; - scq->last = scq->base + (scq->num_entries - 1); - scq->tail = scq->last; - scq->scd = scd; - scq->num_entries = size / NS_SCQE_SIZE; - scq->tbd_count = 0; - init_waitqueue_head(&scq->scqfull_waitq); - scq->full = 0; - spin_lock_init(&scq->lock); - - for (i = 0; i < scq->num_entries; i++) - scq->skb[i] = NULL; - - return scq; + if (error >= 17) { + writel(0x00000000, card->membase + CFG); + } + if (error >= 16) { + struct sk_buff *iovb; + while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) + dev_kfree_skb_any(iovb); + } + if (error >= 15) { + struct sk_buff *sb; + while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) + dev_kfree_skb_any(sb); + free_scq(card, card->scq0, NULL); + } + if (error >= 14) { + struct sk_buff *lb; + while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) + dev_kfree_skb_any(lb); + } + if (error >= 13) { + struct sk_buff *hb; + while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) + dev_kfree_skb_any(hb); + } + if (error >= 12) { + kfree(card->rsq.org); + } + if (error >= 11) { + kfree(card->tsq.org); + } + if (error >= 10) { + free_irq(card->pcidev->irq, card); + } + if (error >= 4) { + iounmap(card->membase); + } + if (error >= 3) { + pci_disable_device(card->pcidev); + kfree(card); + } } - +static scq_info *get_scq(ns_dev *card, int size, u32 scd) +{ + scq_info *scq; + int i; + + if (size != VBR_SCQSIZE && size != CBR_SCQSIZE) + return NULL; + + scq = kmalloc(sizeof(scq_info), GFP_KERNEL); + if (!scq) + return NULL; + scq->org = pci_alloc_consistent(card->pcidev, 2 * size, &scq->dma); + if (!scq->org) { + kfree(scq); + return NULL; + } + scq->skb = kmalloc(sizeof(struct sk_buff *) * + (size / NS_SCQE_SIZE), GFP_KERNEL); + if (!scq->skb) { + kfree(scq->org); + kfree(scq); + return NULL; + } + scq->num_entries = size / NS_SCQE_SIZE; + scq->base = PTR_ALIGN(scq->org, size); + scq->next = scq->base; + scq->last = scq->base + (scq->num_entries - 1); + scq->tail = scq->last; + scq->scd = scd; + scq->num_entries = size / NS_SCQE_SIZE; + scq->tbd_count = 0; + init_waitqueue_head(&scq->scqfull_waitq); + scq->full = 0; + spin_lock_init(&scq->lock); + + for (i = 0; i < scq->num_entries; i++) + scq->skb[i] = NULL; + + return scq; +} /* For variable rate SCQ vcc must be NULL */ -static void free_scq(scq_info *scq, struct atm_vcc *vcc) +static void free_scq(ns_dev *card, scq_info *scq, struct atm_vcc *vcc) { - int i; - - if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) - for (i = 0; i < scq->num_entries; i++) - { - if (scq->skb[i] != NULL) - { - vcc = ATM_SKB(scq->skb[i])->vcc; - if (vcc->pop != NULL) - vcc->pop(vcc, scq->skb[i]); - else - dev_kfree_skb_any(scq->skb[i]); - } - } - else /* vcc must be != NULL */ - { - if (vcc == NULL) - { - printk("nicstar: free_scq() called with vcc == NULL for fixed rate scq."); - for (i = 0; i < scq->num_entries; i++) - dev_kfree_skb_any(scq->skb[i]); - } - else - for (i = 0; i < scq->num_entries; i++) - { - if (scq->skb[i] != NULL) - { - if (vcc->pop != NULL) - vcc->pop(vcc, scq->skb[i]); - else - dev_kfree_skb_any(scq->skb[i]); - } - } - } - kfree(scq->skb); - kfree(scq->org); - kfree(scq); + int i; + + if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) + for (i = 0; i < scq->num_entries; i++) { + if (scq->skb[i] != NULL) { + vcc = ATM_SKB(scq->skb[i])->vcc; + if (vcc->pop != NULL) + vcc->pop(vcc, scq->skb[i]); + else + dev_kfree_skb_any(scq->skb[i]); + } + } else { /* vcc must be != NULL */ + + if (vcc == NULL) { + printk + ("nicstar: free_scq() called with vcc == NULL for fixed rate scq."); + for (i = 0; i < scq->num_entries; i++) + dev_kfree_skb_any(scq->skb[i]); + } else + for (i = 0; i < scq->num_entries; i++) { + if (scq->skb[i] != NULL) { + if (vcc->pop != NULL) + vcc->pop(vcc, scq->skb[i]); + else + dev_kfree_skb_any(scq->skb[i]); + } + } + } + kfree(scq->skb); + pci_free_consistent(card->pcidev, + 2 * (scq->num_entries == VBR_SCQ_NUM_ENTRIES ? + VBR_SCQSIZE : CBR_SCQSIZE), + scq->org, scq->dma); + kfree(scq); } - - /* The handles passed must be pointers to the sk_buff containing the small or large buffer(s) cast to u32. */ -static void push_rxbufs(ns_dev *card, struct sk_buff *skb) +static void push_rxbufs(ns_dev * card, struct sk_buff *skb) { - struct ns_skb_cb *cb = NS_SKB_CB(skb); - u32 handle1, addr1; - u32 handle2, addr2; - u32 stat; - unsigned long flags; - - /* *BARF* */ - handle2 = addr2 = 0; - handle1 = (u32)skb; - addr1 = (u32)virt_to_bus(skb->data); + struct sk_buff *handle1, *handle2; + int id1, id2; + u32 addr1, addr2; + u32 stat; + unsigned long flags; + + /* *BARF* */ + handle2 = NULL; + addr2 = 0; + handle1 = skb; + addr1 = pci_map_single(card->pcidev, + skb->data, + (NS_PRV_BUFTYPE(skb) == BUF_SM + ? NS_SMSKBSIZE : NS_LGSKBSIZE), + PCI_DMA_TODEVICE); + NS_PRV_DMA(skb) = addr1; /* save so we can unmap later */ #ifdef GENERAL_DEBUG - if (!addr1) - printk("nicstar%d: push_rxbufs called with addr1 = 0.\n", card->index); + if (!addr1) + printk("nicstar%d: push_rxbufs called with addr1 = 0.\n", + card->index); #endif /* GENERAL_DEBUG */ - stat = readl(card->membase + STAT); - card->sbfqc = ns_stat_sfbqc_get(stat); - card->lbfqc = ns_stat_lfbqc_get(stat); - if (cb->buf_type == BUF_SM) - { - if (!addr2) - { - if (card->sm_addr) - { - addr2 = card->sm_addr; - handle2 = card->sm_handle; - card->sm_addr = 0x00000000; - card->sm_handle = 0x00000000; - } - else /* (!sm_addr) */ - { - card->sm_addr = addr1; - card->sm_handle = handle1; - } - } - } - else /* buf_type == BUF_LG */ - { - if (!addr2) - { - if (card->lg_addr) - { - addr2 = card->lg_addr; - handle2 = card->lg_handle; - card->lg_addr = 0x00000000; - card->lg_handle = 0x00000000; - } - else /* (!lg_addr) */ - { - card->lg_addr = addr1; - card->lg_handle = handle1; - } - } - } - - if (addr2) - { - if (cb->buf_type == BUF_SM) - { - if (card->sbfqc >= card->sbnr.max) - { - skb_unlink((struct sk_buff *) handle1, &card->sbpool.queue); - dev_kfree_skb_any((struct sk_buff *) handle1); - skb_unlink((struct sk_buff *) handle2, &card->sbpool.queue); - dev_kfree_skb_any((struct sk_buff *) handle2); - return; - } - else - card->sbfqc += 2; - } - else /* (buf_type == BUF_LG) */ - { - if (card->lbfqc >= card->lbnr.max) - { - skb_unlink((struct sk_buff *) handle1, &card->lbpool.queue); - dev_kfree_skb_any((struct sk_buff *) handle1); - skb_unlink((struct sk_buff *) handle2, &card->lbpool.queue); - dev_kfree_skb_any((struct sk_buff *) handle2); - return; - } - else - card->lbfqc += 2; - } - - spin_lock_irqsave(&card->res_lock, flags); - - while (CMD_BUSY(card)); - writel(addr2, card->membase + DR3); - writel(handle2, card->membase + DR2); - writel(addr1, card->membase + DR1); - writel(handle1, card->membase + DR0); - writel(NS_CMD_WRITE_FREEBUFQ | cb->buf_type, card->membase + CMD); - - spin_unlock_irqrestore(&card->res_lock, flags); - - XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index, - (cb->buf_type == BUF_SM ? "small" : "large"), addr1, addr2); - } - - if (!card->efbie && card->sbfqc >= card->sbnr.min && - card->lbfqc >= card->lbnr.min) - { - card->efbie = 1; - writel((readl(card->membase + CFG) | NS_CFG_EFBIE), card->membase + CFG); - } - - return; + stat = readl(card->membase + STAT); + card->sbfqc = ns_stat_sfbqc_get(stat); + card->lbfqc = ns_stat_lfbqc_get(stat); + if (NS_PRV_BUFTYPE(skb) == BUF_SM) { + if (!addr2) { + if (card->sm_addr) { + addr2 = card->sm_addr; + handle2 = card->sm_handle; + card->sm_addr = 0x00000000; + card->sm_handle = NULL; + } else { /* (!sm_addr) */ + + card->sm_addr = addr1; + card->sm_handle = handle1; + } + } + } else { /* buf_type == BUF_LG */ + + if (!addr2) { + if (card->lg_addr) { + addr2 = card->lg_addr; + handle2 = card->lg_handle; + card->lg_addr = 0x00000000; + card->lg_handle = NULL; + } else { /* (!lg_addr) */ + + card->lg_addr = addr1; + card->lg_handle = handle1; + } + } + } + + if (addr2) { + if (NS_PRV_BUFTYPE(skb) == BUF_SM) { + if (card->sbfqc >= card->sbnr.max) { + skb_unlink(handle1, &card->sbpool.queue); + dev_kfree_skb_any(handle1); + skb_unlink(handle2, &card->sbpool.queue); + dev_kfree_skb_any(handle2); + return; + } else + card->sbfqc += 2; + } else { /* (buf_type == BUF_LG) */ + + if (card->lbfqc >= card->lbnr.max) { + skb_unlink(handle1, &card->lbpool.queue); + dev_kfree_skb_any(handle1); + skb_unlink(handle2, &card->lbpool.queue); + dev_kfree_skb_any(handle2); + return; + } else + card->lbfqc += 2; + } + + id1 = idr_alloc(&card->idr, handle1, 0, 0, GFP_ATOMIC); + if (id1 < 0) + goto out; + + id2 = idr_alloc(&card->idr, handle2, 0, 0, GFP_ATOMIC); + if (id2 < 0) + goto out; + + spin_lock_irqsave(&card->res_lock, flags); + while (CMD_BUSY(card)) ; + writel(addr2, card->membase + DR3); + writel(id2, card->membase + DR2); + writel(addr1, card->membase + DR1); + writel(id1, card->membase + DR0); + writel(NS_CMD_WRITE_FREEBUFQ | NS_PRV_BUFTYPE(skb), + card->membase + CMD); + spin_unlock_irqrestore(&card->res_lock, flags); + + XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", + card->index, + (NS_PRV_BUFTYPE(skb) == BUF_SM ? "small" : "large"), + addr1, addr2); + } + + if (!card->efbie && card->sbfqc >= card->sbnr.min && + card->lbfqc >= card->lbnr.min) { + card->efbie = 1; + writel((readl(card->membase + CFG) | NS_CFG_EFBIE), + card->membase + CFG); + } + +out: + return; } - - static irqreturn_t ns_irq_handler(int irq, void *dev_id) { - u32 stat_r; - ns_dev *card; - struct atm_dev *dev; - unsigned long flags; - - card = (ns_dev *) dev_id; - dev = card->atmdev; - card->intcnt++; - - PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index); - - spin_lock_irqsave(&card->int_lock, flags); - - stat_r = readl(card->membase + STAT); - - /* Transmit Status Indicator has been written to T. S. Queue */ - if (stat_r & NS_STAT_TSIF) - { - TXPRINTK("nicstar%d: TSI interrupt\n", card->index); - process_tsq(card); - writel(NS_STAT_TSIF, card->membase + STAT); - } - - /* Incomplete CS-PDU has been transmitted */ - if (stat_r & NS_STAT_TXICP) - { - writel(NS_STAT_TXICP, card->membase + STAT); - TXPRINTK("nicstar%d: Incomplete CS-PDU transmitted.\n", - card->index); - } - - /* Transmit Status Queue 7/8 full */ - if (stat_r & NS_STAT_TSQF) - { - writel(NS_STAT_TSQF, card->membase + STAT); - PRINTK("nicstar%d: TSQ full.\n", card->index); - process_tsq(card); - } - - /* Timer overflow */ - if (stat_r & NS_STAT_TMROF) - { - writel(NS_STAT_TMROF, card->membase + STAT); - PRINTK("nicstar%d: Timer overflow.\n", card->index); - } - - /* PHY device interrupt signal active */ - if (stat_r & NS_STAT_PHYI) - { - writel(NS_STAT_PHYI, card->membase + STAT); - PRINTK("nicstar%d: PHY interrupt.\n", card->index); - if (dev->phy && dev->phy->interrupt) { - dev->phy->interrupt(dev); - } - } - - /* Small Buffer Queue is full */ - if (stat_r & NS_STAT_SFBQF) - { - writel(NS_STAT_SFBQF, card->membase + STAT); - printk("nicstar%d: Small free buffer queue is full.\n", card->index); - } - - /* Large Buffer Queue is full */ - if (stat_r & NS_STAT_LFBQF) - { - writel(NS_STAT_LFBQF, card->membase + STAT); - printk("nicstar%d: Large free buffer queue is full.\n", card->index); - } - - /* Receive Status Queue is full */ - if (stat_r & NS_STAT_RSQF) - { - writel(NS_STAT_RSQF, card->membase + STAT); - printk("nicstar%d: RSQ full.\n", card->index); - process_rsq(card); - } - - /* Complete CS-PDU received */ - if (stat_r & NS_STAT_EOPDU) - { - RXPRINTK("nicstar%d: End of CS-PDU received.\n", card->index); - process_rsq(card); - writel(NS_STAT_EOPDU, card->membase + STAT); - } - - /* Raw cell received */ - if (stat_r & NS_STAT_RAWCF) - { - writel(NS_STAT_RAWCF, card->membase + STAT); + u32 stat_r; + ns_dev *card; + struct atm_dev *dev; + unsigned long flags; + + card = (ns_dev *) dev_id; + dev = card->atmdev; + card->intcnt++; + + PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index); + + spin_lock_irqsave(&card->int_lock, flags); + + stat_r = readl(card->membase + STAT); + + /* Transmit Status Indicator has been written to T. S. Queue */ + if (stat_r & NS_STAT_TSIF) { + TXPRINTK("nicstar%d: TSI interrupt\n", card->index); + process_tsq(card); + writel(NS_STAT_TSIF, card->membase + STAT); + } + + /* Incomplete CS-PDU has been transmitted */ + if (stat_r & NS_STAT_TXICP) { + writel(NS_STAT_TXICP, card->membase + STAT); + TXPRINTK("nicstar%d: Incomplete CS-PDU transmitted.\n", + card->index); + } + + /* Transmit Status Queue 7/8 full */ + if (stat_r & NS_STAT_TSQF) { + writel(NS_STAT_TSQF, card->membase + STAT); + PRINTK("nicstar%d: TSQ full.\n", card->index); + process_tsq(card); + } + + /* Timer overflow */ + if (stat_r & NS_STAT_TMROF) { + writel(NS_STAT_TMROF, card->membase + STAT); + PRINTK("nicstar%d: Timer overflow.\n", card->index); + } + + /* PHY device interrupt signal active */ + if (stat_r & NS_STAT_PHYI) { + writel(NS_STAT_PHYI, card->membase + STAT); + PRINTK("nicstar%d: PHY interrupt.\n", card->index); + if (dev->phy && dev->phy->interrupt) { + dev->phy->interrupt(dev); + } + } + + /* Small Buffer Queue is full */ + if (stat_r & NS_STAT_SFBQF) { + writel(NS_STAT_SFBQF, card->membase + STAT); + printk("nicstar%d: Small free buffer queue is full.\n", + card->index); + } + + /* Large Buffer Queue is full */ + if (stat_r & NS_STAT_LFBQF) { + writel(NS_STAT_LFBQF, card->membase + STAT); + printk("nicstar%d: Large free buffer queue is full.\n", + card->index); + } + + /* Receive Status Queue is full */ + if (stat_r & NS_STAT_RSQF) { + writel(NS_STAT_RSQF, card->membase + STAT); + printk("nicstar%d: RSQ full.\n", card->index); + process_rsq(card); + } + + /* Complete CS-PDU received */ + if (stat_r & NS_STAT_EOPDU) { + RXPRINTK("nicstar%d: End of CS-PDU received.\n", card->index); + process_rsq(card); + writel(NS_STAT_EOPDU, card->membase + STAT); + } + + /* Raw cell received */ + if (stat_r & NS_STAT_RAWCF) { + writel(NS_STAT_RAWCF, card->membase + STAT); #ifndef RCQ_SUPPORT - printk("nicstar%d: Raw cell received and no support yet...\n", - card->index); + printk("nicstar%d: Raw cell received and no support yet...\n", + card->index); #endif /* RCQ_SUPPORT */ - /* NOTE: the following procedure may keep a raw cell pending until the - next interrupt. As this preliminary support is only meant to - avoid buffer leakage, this is not an issue. */ - while (readl(card->membase + RAWCT) != card->rawch) - { - ns_rcqe *rawcell; - - rawcell = (ns_rcqe *) bus_to_virt(card->rawch); - if (ns_rcqe_islast(rawcell)) - { - struct sk_buff *oldbuf; - - oldbuf = card->rcbuf; - card->rcbuf = (struct sk_buff *) ns_rcqe_nextbufhandle(rawcell); - card->rawch = (u32) virt_to_bus(card->rcbuf->data); - recycle_rx_buf(card, oldbuf); - } - else - card->rawch += NS_RCQE_SIZE; - } - } - - /* Small buffer queue is empty */ - if (stat_r & NS_STAT_SFBQE) - { - int i; - struct sk_buff *sb; - - writel(NS_STAT_SFBQE, card->membase + STAT); - printk("nicstar%d: Small free buffer queue empty.\n", - card->index); - for (i = 0; i < card->sbnr.min; i++) - { - sb = dev_alloc_skb(NS_SMSKBSIZE); - if (sb == NULL) - { - writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG); - card->efbie = 0; - break; - } - NS_SKB_CB(sb)->buf_type = BUF_SM; - skb_queue_tail(&card->sbpool.queue, sb); - skb_reserve(sb, NS_AAL0_HEADER); - push_rxbufs(card, sb); - } - card->sbfqc = i; - process_rsq(card); - } - - /* Large buffer queue empty */ - if (stat_r & NS_STAT_LFBQE) - { - int i; - struct sk_buff *lb; - - writel(NS_STAT_LFBQE, card->membase + STAT); - printk("nicstar%d: Large free buffer queue empty.\n", - card->index); - for (i = 0; i < card->lbnr.min; i++) - { - lb = dev_alloc_skb(NS_LGSKBSIZE); - if (lb == NULL) - { - writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG); - card->efbie = 0; - break; - } - NS_SKB_CB(lb)->buf_type = BUF_LG; - skb_queue_tail(&card->lbpool.queue, lb); - skb_reserve(lb, NS_SMBUFSIZE); - push_rxbufs(card, lb); - } - card->lbfqc = i; - process_rsq(card); - } - - /* Receive Status Queue is 7/8 full */ - if (stat_r & NS_STAT_RSQAF) - { - writel(NS_STAT_RSQAF, card->membase + STAT); - RXPRINTK("nicstar%d: RSQ almost full.\n", card->index); - process_rsq(card); - } - - spin_unlock_irqrestore(&card->int_lock, flags); - PRINTK("nicstar%d: end of interrupt service\n", card->index); - return IRQ_HANDLED; + /* NOTE: the following procedure may keep a raw cell pending until the + next interrupt. As this preliminary support is only meant to + avoid buffer leakage, this is not an issue. */ + while (readl(card->membase + RAWCT) != card->rawch) { + + if (ns_rcqe_islast(card->rawcell)) { + struct sk_buff *oldbuf; + + oldbuf = card->rcbuf; + card->rcbuf = idr_find(&card->idr, + ns_rcqe_nextbufhandle(card->rawcell)); + card->rawch = NS_PRV_DMA(card->rcbuf); + card->rawcell = (struct ns_rcqe *) + card->rcbuf->data; + recycle_rx_buf(card, oldbuf); + } else { + card->rawch += NS_RCQE_SIZE; + card->rawcell++; + } + } + } + + /* Small buffer queue is empty */ + if (stat_r & NS_STAT_SFBQE) { + int i; + struct sk_buff *sb; + + writel(NS_STAT_SFBQE, card->membase + STAT); + printk("nicstar%d: Small free buffer queue empty.\n", + card->index); + for (i = 0; i < card->sbnr.min; i++) { + sb = dev_alloc_skb(NS_SMSKBSIZE); + if (sb == NULL) { + writel(readl(card->membase + CFG) & + ~NS_CFG_EFBIE, card->membase + CFG); + card->efbie = 0; + break; + } + NS_PRV_BUFTYPE(sb) = BUF_SM; + skb_queue_tail(&card->sbpool.queue, sb); + skb_reserve(sb, NS_AAL0_HEADER); + push_rxbufs(card, sb); + } + card->sbfqc = i; + process_rsq(card); + } + + /* Large buffer queue empty */ + if (stat_r & NS_STAT_LFBQE) { + int i; + struct sk_buff *lb; + + writel(NS_STAT_LFBQE, card->membase + STAT); + printk("nicstar%d: Large free buffer queue empty.\n", + card->index); + for (i = 0; i < card->lbnr.min; i++) { + lb = dev_alloc_skb(NS_LGSKBSIZE); + if (lb == NULL) { + writel(readl(card->membase + CFG) & + ~NS_CFG_EFBIE, card->membase + CFG); + card->efbie = 0; + break; + } + NS_PRV_BUFTYPE(lb) = BUF_LG; + skb_queue_tail(&card->lbpool.queue, lb); + skb_reserve(lb, NS_SMBUFSIZE); + push_rxbufs(card, lb); + } + card->lbfqc = i; + process_rsq(card); + } + + /* Receive Status Queue is 7/8 full */ + if (stat_r & NS_STAT_RSQAF) { + writel(NS_STAT_RSQAF, card->membase + STAT); + RXPRINTK("nicstar%d: RSQ almost full.\n", card->index); + process_rsq(card); + } + + spin_unlock_irqrestore(&card->int_lock, flags); + PRINTK("nicstar%d: end of interrupt service\n", card->index); + return IRQ_HANDLED; } - - static int ns_open(struct atm_vcc *vcc) { - ns_dev *card; - vc_map *vc; - unsigned long tmpl, modl; - int tcr, tcra; /* target cell rate, and absolute value */ - int n = 0; /* Number of entries in the TST. Initialized to remove - the compiler warning. */ - u32 u32d[4]; - int frscdi = 0; /* Index of the SCD. Initialized to remove the compiler - warning. How I wish compilers were clever enough to - tell which variables can truly be used - uninitialized... */ - int inuse; /* tx or rx vc already in use by another vcc */ - short vpi = vcc->vpi; - int vci = vcc->vci; - - card = (ns_dev *) vcc->dev->dev_data; - PRINTK("nicstar%d: opening vpi.vci %d.%d \n", card->index, (int) vpi, vci); - if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) - { - PRINTK("nicstar%d: unsupported AAL.\n", card->index); - return -EINVAL; - } - - vc = &(card->vcmap[vpi << card->vcibits | vci]); - vcc->dev_data = vc; - - inuse = 0; - if (vcc->qos.txtp.traffic_class != ATM_NONE && vc->tx) - inuse = 1; - if (vcc->qos.rxtp.traffic_class != ATM_NONE && vc->rx) - inuse += 2; - if (inuse) - { - printk("nicstar%d: %s vci already in use.\n", card->index, - inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx"); - return -EINVAL; - } - - set_bit(ATM_VF_ADDR,&vcc->flags); - - /* NOTE: You are not allowed to modify an open connection's QOS. To change - that, remove the ATM_VF_PARTIAL flag checking. There may be other changes - needed to do that. */ - if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) - { - scq_info *scq; - - set_bit(ATM_VF_PARTIAL,&vcc->flags); - if (vcc->qos.txtp.traffic_class == ATM_CBR) - { - /* Check requested cell rate and availability of SCD */ - if (vcc->qos.txtp.max_pcr == 0 && vcc->qos.txtp.pcr == 0 && - vcc->qos.txtp.min_pcr == 0) - { - PRINTK("nicstar%d: trying to open a CBR vc with cell rate = 0 \n", - card->index); - clear_bit(ATM_VF_PARTIAL,&vcc->flags); - clear_bit(ATM_VF_ADDR,&vcc->flags); - return -EINVAL; - } - - tcr = atm_pcr_goal(&(vcc->qos.txtp)); - tcra = tcr >= 0 ? tcr : -tcr; - - PRINTK("nicstar%d: target cell rate = %d.\n", card->index, - vcc->qos.txtp.max_pcr); - - tmpl = (unsigned long)tcra * (unsigned long)NS_TST_NUM_ENTRIES; - modl = tmpl % card->max_pcr; - - n = (int)(tmpl / card->max_pcr); - if (tcr > 0) - { - if (modl > 0) n++; - } - else if (tcr == 0) - { - if ((n = (card->tst_free_entries - NS_TST_RESERVED)) <= 0) - { - PRINTK("nicstar%d: no CBR bandwidth free.\n", card->index); - clear_bit(ATM_VF_PARTIAL,&vcc->flags); - clear_bit(ATM_VF_ADDR,&vcc->flags); - return -EINVAL; - } - } - - if (n == 0) - { - printk("nicstar%d: selected bandwidth < granularity.\n", card->index); - clear_bit(ATM_VF_PARTIAL,&vcc->flags); - clear_bit(ATM_VF_ADDR,&vcc->flags); - return -EINVAL; - } - - if (n > (card->tst_free_entries - NS_TST_RESERVED)) - { - PRINTK("nicstar%d: not enough free CBR bandwidth.\n", card->index); - clear_bit(ATM_VF_PARTIAL,&vcc->flags); - clear_bit(ATM_VF_ADDR,&vcc->flags); - return -EINVAL; - } - else - card->tst_free_entries -= n; - - XPRINTK("nicstar%d: writing %d tst entries.\n", card->index, n); - for (frscdi = 0; frscdi < NS_FRSCD_NUM; frscdi++) - { - if (card->scd2vc[frscdi] == NULL) - { - card->scd2vc[frscdi] = vc; - break; - } - } - if (frscdi == NS_FRSCD_NUM) - { - PRINTK("nicstar%d: no SCD available for CBR channel.\n", card->index); - card->tst_free_entries += n; - clear_bit(ATM_VF_PARTIAL,&vcc->flags); - clear_bit(ATM_VF_ADDR,&vcc->flags); - return -EBUSY; - } - - vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE; - - scq = get_scq(CBR_SCQSIZE, vc->cbr_scd); - if (scq == NULL) - { - PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index); - card->scd2vc[frscdi] = NULL; - card->tst_free_entries += n; - clear_bit(ATM_VF_PARTIAL,&vcc->flags); - clear_bit(ATM_VF_ADDR,&vcc->flags); - return -ENOMEM; - } - vc->scq = scq; - u32d[0] = (u32) virt_to_bus(scq->base); - u32d[1] = (u32) 0x00000000; - u32d[2] = (u32) 0xffffffff; - u32d[3] = (u32) 0x00000000; - ns_write_sram(card, vc->cbr_scd, u32d, 4); - - fill_tst(card, n, vc); - } - else if (vcc->qos.txtp.traffic_class == ATM_UBR) - { - vc->cbr_scd = 0x00000000; - vc->scq = card->scq0; - } - - if (vcc->qos.txtp.traffic_class != ATM_NONE) - { - vc->tx = 1; - vc->tx_vcc = vcc; - vc->tbd_count = 0; - } - if (vcc->qos.rxtp.traffic_class != ATM_NONE) - { - u32 status; - - vc->rx = 1; - vc->rx_vcc = vcc; - vc->rx_iov = NULL; - - /* Open the connection in hardware */ - if (vcc->qos.aal == ATM_AAL5) - status = NS_RCTE_AAL5 | NS_RCTE_CONNECTOPEN; - else /* vcc->qos.aal == ATM_AAL0 */ - status = NS_RCTE_AAL0 | NS_RCTE_CONNECTOPEN; + ns_dev *card; + vc_map *vc; + unsigned long tmpl, modl; + int tcr, tcra; /* target cell rate, and absolute value */ + int n = 0; /* Number of entries in the TST. Initialized to remove + the compiler warning. */ + u32 u32d[4]; + int frscdi = 0; /* Index of the SCD. Initialized to remove the compiler + warning. How I wish compilers were clever enough to + tell which variables can truly be used + uninitialized... */ + int inuse; /* tx or rx vc already in use by another vcc */ + short vpi = vcc->vpi; + int vci = vcc->vci; + + card = (ns_dev *) vcc->dev->dev_data; + PRINTK("nicstar%d: opening vpi.vci %d.%d \n", card->index, (int)vpi, + vci); + if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) { + PRINTK("nicstar%d: unsupported AAL.\n", card->index); + return -EINVAL; + } + + vc = &(card->vcmap[vpi << card->vcibits | vci]); + vcc->dev_data = vc; + + inuse = 0; + if (vcc->qos.txtp.traffic_class != ATM_NONE && vc->tx) + inuse = 1; + if (vcc->qos.rxtp.traffic_class != ATM_NONE && vc->rx) + inuse += 2; + if (inuse) { + printk("nicstar%d: %s vci already in use.\n", card->index, + inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx"); + return -EINVAL; + } + + set_bit(ATM_VF_ADDR, &vcc->flags); + + /* NOTE: You are not allowed to modify an open connection's QOS. To change + that, remove the ATM_VF_PARTIAL flag checking. There may be other changes + needed to do that. */ + if (!test_bit(ATM_VF_PARTIAL, &vcc->flags)) { + scq_info *scq; + + set_bit(ATM_VF_PARTIAL, &vcc->flags); + if (vcc->qos.txtp.traffic_class == ATM_CBR) { + /* Check requested cell rate and availability of SCD */ + if (vcc->qos.txtp.max_pcr == 0 && vcc->qos.txtp.pcr == 0 + && vcc->qos.txtp.min_pcr == 0) { + PRINTK + ("nicstar%d: trying to open a CBR vc with cell rate = 0 \n", + card->index); + clear_bit(ATM_VF_PARTIAL, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); + return -EINVAL; + } + + tcr = atm_pcr_goal(&(vcc->qos.txtp)); + tcra = tcr >= 0 ? tcr : -tcr; + + PRINTK("nicstar%d: target cell rate = %d.\n", + card->index, vcc->qos.txtp.max_pcr); + + tmpl = + (unsigned long)tcra *(unsigned long) + NS_TST_NUM_ENTRIES; + modl = tmpl % card->max_pcr; + + n = (int)(tmpl / card->max_pcr); + if (tcr > 0) { + if (modl > 0) + n++; + } else if (tcr == 0) { + if ((n = + (card->tst_free_entries - + NS_TST_RESERVED)) <= 0) { + PRINTK + ("nicstar%d: no CBR bandwidth free.\n", + card->index); + clear_bit(ATM_VF_PARTIAL, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); + return -EINVAL; + } + } + + if (n == 0) { + printk + ("nicstar%d: selected bandwidth < granularity.\n", + card->index); + clear_bit(ATM_VF_PARTIAL, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); + return -EINVAL; + } + + if (n > (card->tst_free_entries - NS_TST_RESERVED)) { + PRINTK + ("nicstar%d: not enough free CBR bandwidth.\n", + card->index); + clear_bit(ATM_VF_PARTIAL, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); + return -EINVAL; + } else + card->tst_free_entries -= n; + + XPRINTK("nicstar%d: writing %d tst entries.\n", + card->index, n); + for (frscdi = 0; frscdi < NS_FRSCD_NUM; frscdi++) { + if (card->scd2vc[frscdi] == NULL) { + card->scd2vc[frscdi] = vc; + break; + } + } + if (frscdi == NS_FRSCD_NUM) { + PRINTK + ("nicstar%d: no SCD available for CBR channel.\n", + card->index); + card->tst_free_entries += n; + clear_bit(ATM_VF_PARTIAL, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); + return -EBUSY; + } + + vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE; + + scq = get_scq(card, CBR_SCQSIZE, vc->cbr_scd); + if (scq == NULL) { + PRINTK("nicstar%d: can't get fixed rate SCQ.\n", + card->index); + card->scd2vc[frscdi] = NULL; + card->tst_free_entries += n; + clear_bit(ATM_VF_PARTIAL, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); + return -ENOMEM; + } + vc->scq = scq; + u32d[0] = scq_virt_to_bus(scq, scq->base); + u32d[1] = (u32) 0x00000000; + u32d[2] = (u32) 0xffffffff; + u32d[3] = (u32) 0x00000000; + ns_write_sram(card, vc->cbr_scd, u32d, 4); + + fill_tst(card, n, vc); + } else if (vcc->qos.txtp.traffic_class == ATM_UBR) { + vc->cbr_scd = 0x00000000; + vc->scq = card->scq0; + } + + if (vcc->qos.txtp.traffic_class != ATM_NONE) { + vc->tx = 1; + vc->tx_vcc = vcc; + vc->tbd_count = 0; + } + if (vcc->qos.rxtp.traffic_class != ATM_NONE) { + u32 status; + + vc->rx = 1; + vc->rx_vcc = vcc; + vc->rx_iov = NULL; + + /* Open the connection in hardware */ + if (vcc->qos.aal == ATM_AAL5) + status = NS_RCTE_AAL5 | NS_RCTE_CONNECTOPEN; + else /* vcc->qos.aal == ATM_AAL0 */ + status = NS_RCTE_AAL0 | NS_RCTE_CONNECTOPEN; #ifdef RCQ_SUPPORT - status |= NS_RCTE_RAWCELLINTEN; + status |= NS_RCTE_RAWCELLINTEN; #endif /* RCQ_SUPPORT */ - ns_write_sram(card, NS_RCT + (vpi << card->vcibits | vci) * - NS_RCT_ENTRY_SIZE, &status, 1); - } - - } - - set_bit(ATM_VF_READY,&vcc->flags); - return 0; -} + ns_write_sram(card, + NS_RCT + + (vpi << card->vcibits | vci) * + NS_RCT_ENTRY_SIZE, &status, 1); + } + } + set_bit(ATM_VF_READY, &vcc->flags); + return 0; +} static void ns_close(struct atm_vcc *vcc) { - vc_map *vc; - ns_dev *card; - u32 data; - int i; - - vc = vcc->dev_data; - card = vcc->dev->dev_data; - PRINTK("nicstar%d: closing vpi.vci %d.%d \n", card->index, - (int) vcc->vpi, vcc->vci); - - clear_bit(ATM_VF_READY,&vcc->flags); - - if (vcc->qos.rxtp.traffic_class != ATM_NONE) - { - u32 addr; - unsigned long flags; - - addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE; - spin_lock_irqsave(&card->res_lock, flags); - while(CMD_BUSY(card)); - writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD); - spin_unlock_irqrestore(&card->res_lock, flags); - - vc->rx = 0; - if (vc->rx_iov != NULL) - { - struct sk_buff *iovb; - u32 stat; - - stat = readl(card->membase + STAT); - card->sbfqc = ns_stat_sfbqc_get(stat); - card->lbfqc = ns_stat_lfbqc_get(stat); - - PRINTK("nicstar%d: closing a VC with pending rx buffers.\n", - card->index); - iovb = vc->rx_iov; - recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - NS_SKB(iovb)->iovcnt); - NS_SKB(iovb)->iovcnt = 0; - NS_SKB(iovb)->vcc = NULL; - spin_lock_irqsave(&card->int_lock, flags); - recycle_iov_buf(card, iovb); - spin_unlock_irqrestore(&card->int_lock, flags); - vc->rx_iov = NULL; - } - } - - if (vcc->qos.txtp.traffic_class != ATM_NONE) - { - vc->tx = 0; - } - - if (vcc->qos.txtp.traffic_class == ATM_CBR) - { - unsigned long flags; - ns_scqe *scqep; - scq_info *scq; - - scq = vc->scq; - - for (;;) - { - spin_lock_irqsave(&scq->lock, flags); - scqep = scq->next; - if (scqep == scq->base) - scqep = scq->last; - else - scqep--; - if (scqep == scq->tail) - { - spin_unlock_irqrestore(&scq->lock, flags); - break; - } - /* If the last entry is not a TSR, place one in the SCQ in order to - be able to completely drain it and then close. */ - if (!ns_scqe_is_tsr(scqep) && scq->tail != scq->next) - { - ns_scqe tsr; - u32 scdi, scqi; - u32 data; - int index; - - tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); - scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; - scqi = scq->next - scq->base; - tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); - tsr.word_3 = 0x00000000; - tsr.word_4 = 0x00000000; - *scq->next = tsr; - index = (int) scqi; - scq->skb[index] = NULL; - if (scq->next == scq->last) - scq->next = scq->base; - else - scq->next++; - data = (u32) virt_to_bus(scq->next); - ns_write_sram(card, scq->scd, &data, 1); - } - spin_unlock_irqrestore(&scq->lock, flags); - schedule(); - } - - /* Free all TST entries */ - data = NS_TST_OPCODE_VARIABLE; - for (i = 0; i < NS_TST_NUM_ENTRIES; i++) - { - if (card->tste2vc[i] == vc) - { - ns_write_sram(card, card->tst_addr + i, &data, 1); - card->tste2vc[i] = NULL; - card->tst_free_entries++; - } - } - - card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL; - free_scq(vc->scq, vcc); - } - - /* remove all references to vcc before deleting it */ - if (vcc->qos.txtp.traffic_class != ATM_NONE) - { - unsigned long flags; - scq_info *scq = card->scq0; - - spin_lock_irqsave(&scq->lock, flags); - - for(i = 0; i < scq->num_entries; i++) { - if(scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) { - ATM_SKB(scq->skb[i])->vcc = NULL; - atm_return(vcc, scq->skb[i]->truesize); - PRINTK("nicstar: deleted pending vcc mapping\n"); - } - } - - spin_unlock_irqrestore(&scq->lock, flags); - } - - vcc->dev_data = NULL; - clear_bit(ATM_VF_PARTIAL,&vcc->flags); - clear_bit(ATM_VF_ADDR,&vcc->flags); + vc_map *vc; + ns_dev *card; + u32 data; + int i; + + vc = vcc->dev_data; + card = vcc->dev->dev_data; + PRINTK("nicstar%d: closing vpi.vci %d.%d \n", card->index, + (int)vcc->vpi, vcc->vci); + + clear_bit(ATM_VF_READY, &vcc->flags); + + if (vcc->qos.rxtp.traffic_class != ATM_NONE) { + u32 addr; + unsigned long flags; + + addr = + NS_RCT + + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE; + spin_lock_irqsave(&card->res_lock, flags); + while (CMD_BUSY(card)) ; + writel(NS_CMD_CLOSE_CONNECTION | addr << 2, + card->membase + CMD); + spin_unlock_irqrestore(&card->res_lock, flags); + + vc->rx = 0; + if (vc->rx_iov != NULL) { + struct sk_buff *iovb; + u32 stat; + + stat = readl(card->membase + STAT); + card->sbfqc = ns_stat_sfbqc_get(stat); + card->lbfqc = ns_stat_lfbqc_get(stat); + + PRINTK + ("nicstar%d: closing a VC with pending rx buffers.\n", + card->index); + iovb = vc->rx_iov; + recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, + NS_PRV_IOVCNT(iovb)); + NS_PRV_IOVCNT(iovb) = 0; + spin_lock_irqsave(&card->int_lock, flags); + recycle_iov_buf(card, iovb); + spin_unlock_irqrestore(&card->int_lock, flags); + vc->rx_iov = NULL; + } + } + + if (vcc->qos.txtp.traffic_class != ATM_NONE) { + vc->tx = 0; + } + + if (vcc->qos.txtp.traffic_class == ATM_CBR) { + unsigned long flags; + ns_scqe *scqep; + scq_info *scq; + + scq = vc->scq; + + for (;;) { + spin_lock_irqsave(&scq->lock, flags); + scqep = scq->next; + if (scqep == scq->base) + scqep = scq->last; + else + scqep--; + if (scqep == scq->tail) { + spin_unlock_irqrestore(&scq->lock, flags); + break; + } + /* If the last entry is not a TSR, place one in the SCQ in order to + be able to completely drain it and then close. */ + if (!ns_scqe_is_tsr(scqep) && scq->tail != scq->next) { + ns_scqe tsr; + u32 scdi, scqi; + u32 data; + int index; + + tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); + scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; + scqi = scq->next - scq->base; + tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); + tsr.word_3 = 0x00000000; + tsr.word_4 = 0x00000000; + *scq->next = tsr; + index = (int)scqi; + scq->skb[index] = NULL; + if (scq->next == scq->last) + scq->next = scq->base; + else + scq->next++; + data = scq_virt_to_bus(scq, scq->next); + ns_write_sram(card, scq->scd, &data, 1); + } + spin_unlock_irqrestore(&scq->lock, flags); + schedule(); + } + + /* Free all TST entries */ + data = NS_TST_OPCODE_VARIABLE; + for (i = 0; i < NS_TST_NUM_ENTRIES; i++) { + if (card->tste2vc[i] == vc) { + ns_write_sram(card, card->tst_addr + i, &data, + 1); + card->tste2vc[i] = NULL; + card->tst_free_entries++; + } + } + + card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL; + free_scq(card, vc->scq, vcc); + } + + /* remove all references to vcc before deleting it */ + if (vcc->qos.txtp.traffic_class != ATM_NONE) { + unsigned long flags; + scq_info *scq = card->scq0; + + spin_lock_irqsave(&scq->lock, flags); + + for (i = 0; i < scq->num_entries; i++) { + if (scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) { + ATM_SKB(scq->skb[i])->vcc = NULL; + atm_return(vcc, scq->skb[i]->truesize); + PRINTK + ("nicstar: deleted pending vcc mapping\n"); + } + } + + spin_unlock_irqrestore(&scq->lock, flags); + } + + vcc->dev_data = NULL; + clear_bit(ATM_VF_PARTIAL, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); #ifdef RX_DEBUG - { - u32 stat, cfg; - stat = readl(card->membase + STAT); - cfg = readl(card->membase + CFG); - printk("STAT = 0x%08X CFG = 0x%08X \n", stat, cfg); - printk("TSQ: base = 0x%08X next = 0x%08X last = 0x%08X TSQT = 0x%08X \n", - (u32) card->tsq.base, (u32) card->tsq.next,(u32) card->tsq.last, - readl(card->membase + TSQT)); - printk("RSQ: base = 0x%08X next = 0x%08X last = 0x%08X RSQT = 0x%08X \n", - (u32) card->rsq.base, (u32) card->rsq.next,(u32) card->rsq.last, - readl(card->membase + RSQT)); - printk("Empty free buffer queue interrupt %s \n", - card->efbie ? "enabled" : "disabled"); - printk("SBCNT = %d count = %d LBCNT = %d count = %d \n", - ns_stat_sfbqc_get(stat), card->sbpool.count, - ns_stat_lfbqc_get(stat), card->lbpool.count); - printk("hbpool.count = %d iovpool.count = %d \n", - card->hbpool.count, card->iovpool.count); - } + { + u32 stat, cfg; + stat = readl(card->membase + STAT); + cfg = readl(card->membase + CFG); + printk("STAT = 0x%08X CFG = 0x%08X \n", stat, cfg); + printk + ("TSQ: base = 0x%p next = 0x%p last = 0x%p TSQT = 0x%08X \n", + card->tsq.base, card->tsq.next, + card->tsq.last, readl(card->membase + TSQT)); + printk + ("RSQ: base = 0x%p next = 0x%p last = 0x%p RSQT = 0x%08X \n", + card->rsq.base, card->rsq.next, + card->rsq.last, readl(card->membase + RSQT)); + printk("Empty free buffer queue interrupt %s \n", + card->efbie ? "enabled" : "disabled"); + printk("SBCNT = %d count = %d LBCNT = %d count = %d \n", + ns_stat_sfbqc_get(stat), card->sbpool.count, + ns_stat_lfbqc_get(stat), card->lbpool.count); + printk("hbpool.count = %d iovpool.count = %d \n", + card->hbpool.count, card->iovpool.count); + } #endif /* RX_DEBUG */ } - - -static void fill_tst(ns_dev *card, int n, vc_map *vc) +static void fill_tst(ns_dev * card, int n, vc_map * vc) { - u32 new_tst; - unsigned long cl; - int e, r; - u32 data; - - /* It would be very complicated to keep the two TSTs synchronized while - assuring that writes are only made to the inactive TST. So, for now I - will use only one TST. If problems occur, I will change this again */ - - new_tst = card->tst_addr; - - /* Fill procedure */ - - for (e = 0; e < NS_TST_NUM_ENTRIES; e++) - { - if (card->tste2vc[e] == NULL) - break; - } - if (e == NS_TST_NUM_ENTRIES) { - printk("nicstar%d: No free TST entries found. \n", card->index); - return; - } - - r = n; - cl = NS_TST_NUM_ENTRIES; - data = ns_tste_make(NS_TST_OPCODE_FIXED, vc->cbr_scd); - - while (r > 0) - { - if (cl >= NS_TST_NUM_ENTRIES && card->tste2vc[e] == NULL) - { - card->tste2vc[e] = vc; - ns_write_sram(card, new_tst + e, &data, 1); - cl -= NS_TST_NUM_ENTRIES; - r--; - } - - if (++e == NS_TST_NUM_ENTRIES) { - e = 0; - } - cl += n; - } - - /* End of fill procedure */ - - data = ns_tste_make(NS_TST_OPCODE_END, new_tst); - ns_write_sram(card, new_tst + NS_TST_NUM_ENTRIES, &data, 1); - ns_write_sram(card, card->tst_addr + NS_TST_NUM_ENTRIES, &data, 1); - card->tst_addr = new_tst; + u32 new_tst; + unsigned long cl; + int e, r; + u32 data; + + /* It would be very complicated to keep the two TSTs synchronized while + assuring that writes are only made to the inactive TST. So, for now I + will use only one TST. If problems occur, I will change this again */ + + new_tst = card->tst_addr; + + /* Fill procedure */ + + for (e = 0; e < NS_TST_NUM_ENTRIES; e++) { + if (card->tste2vc[e] == NULL) + break; + } + if (e == NS_TST_NUM_ENTRIES) { + printk("nicstar%d: No free TST entries found. \n", card->index); + return; + } + + r = n; + cl = NS_TST_NUM_ENTRIES; + data = ns_tste_make(NS_TST_OPCODE_FIXED, vc->cbr_scd); + + while (r > 0) { + if (cl >= NS_TST_NUM_ENTRIES && card->tste2vc[e] == NULL) { + card->tste2vc[e] = vc; + ns_write_sram(card, new_tst + e, &data, 1); + cl -= NS_TST_NUM_ENTRIES; + r--; + } + + if (++e == NS_TST_NUM_ENTRIES) { + e = 0; + } + cl += n; + } + + /* End of fill procedure */ + + data = ns_tste_make(NS_TST_OPCODE_END, new_tst); + ns_write_sram(card, new_tst + NS_TST_NUM_ENTRIES, &data, 1); + ns_write_sram(card, card->tst_addr + NS_TST_NUM_ENTRIES, &data, 1); + card->tst_addr = new_tst; } - - static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) { - ns_dev *card; - vc_map *vc; - scq_info *scq; - unsigned long buflen; - ns_scqe scqe; - u32 flags; /* TBD flags, not CPU flags */ - - card = vcc->dev->dev_data; - TXPRINTK("nicstar%d: ns_send() called.\n", card->index); - if ((vc = (vc_map *) vcc->dev_data) == NULL) - { - printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n", card->index); - atomic_inc(&vcc->stats->tx_err); - dev_kfree_skb_any(skb); - return -EINVAL; - } - - if (!vc->tx) - { - printk("nicstar%d: Trying to transmit on a non-tx VC.\n", card->index); - atomic_inc(&vcc->stats->tx_err); - dev_kfree_skb_any(skb); - return -EINVAL; - } - - if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) - { - printk("nicstar%d: Only AAL0 and AAL5 are supported.\n", card->index); - atomic_inc(&vcc->stats->tx_err); - dev_kfree_skb_any(skb); - return -EINVAL; - } - - if (skb_shinfo(skb)->nr_frags != 0) - { - printk("nicstar%d: No scatter-gather yet.\n", card->index); - atomic_inc(&vcc->stats->tx_err); - dev_kfree_skb_any(skb); - return -EINVAL; - } - - ATM_SKB(skb)->vcc = vcc; - - if (vcc->qos.aal == ATM_AAL5) - { - buflen = (skb->len + 47 + 8) / 48 * 48; /* Multiple of 48 */ - flags = NS_TBD_AAL5; - scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data)); - scqe.word_3 = cpu_to_le32((u32) skb->len); - scqe.word_4 = ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0, - ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? 1 : 0); - flags |= NS_TBD_EOPDU; - } - else /* (vcc->qos.aal == ATM_AAL0) */ - { - buflen = ATM_CELL_PAYLOAD; /* i.e., 48 bytes */ - flags = NS_TBD_AAL0; - scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data) + NS_AAL0_HEADER); - scqe.word_3 = cpu_to_le32(0x00000000); - if (*skb->data & 0x02) /* Payload type 1 - end of pdu */ - flags |= NS_TBD_EOPDU; - scqe.word_4 = cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK); - /* Force the VPI/VCI to be the same as in VCC struct */ - scqe.word_4 |= cpu_to_le32((((u32) vcc->vpi) << NS_TBD_VPI_SHIFT | - ((u32) vcc->vci) << NS_TBD_VCI_SHIFT) & - NS_TBD_VC_MASK); - } - - if (vcc->qos.txtp.traffic_class == ATM_CBR) - { - scqe.word_1 = ns_tbd_mkword_1_novbr(flags, (u32) buflen); - scq = ((vc_map *) vcc->dev_data)->scq; - } - else - { - scqe.word_1 = ns_tbd_mkword_1(flags, (u32) 1, (u32) 1, (u32) buflen); - scq = card->scq0; - } - - if (push_scqe(card, vc, scq, &scqe, skb) != 0) - { - atomic_inc(&vcc->stats->tx_err); - dev_kfree_skb_any(skb); - return -EIO; - } - atomic_inc(&vcc->stats->tx); - - return 0; -} - + ns_dev *card; + vc_map *vc; + scq_info *scq; + unsigned long buflen; + ns_scqe scqe; + u32 flags; /* TBD flags, not CPU flags */ + + card = vcc->dev->dev_data; + TXPRINTK("nicstar%d: ns_send() called.\n", card->index); + if ((vc = (vc_map *) vcc->dev_data) == NULL) { + printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n", + card->index); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); + return -EINVAL; + } + if (!vc->tx) { + printk("nicstar%d: Trying to transmit on a non-tx VC.\n", + card->index); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); + return -EINVAL; + } -static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, - struct sk_buff *skb) -{ - unsigned long flags; - ns_scqe tsr; - u32 scdi, scqi; - int scq_is_vbr; - u32 data; - int index; - - spin_lock_irqsave(&scq->lock, flags); - while (scq->tail == scq->next) - { - if (in_interrupt()) { - spin_unlock_irqrestore(&scq->lock, flags); - printk("nicstar%d: Error pushing TBD.\n", card->index); - return 1; - } - - scq->full = 1; - spin_unlock_irqrestore(&scq->lock, flags); - interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); - spin_lock_irqsave(&scq->lock, flags); - - if (scq->full) { - spin_unlock_irqrestore(&scq->lock, flags); - printk("nicstar%d: Timeout pushing TBD.\n", card->index); - return 1; - } - } - *scq->next = *tbd; - index = (int) (scq->next - scq->base); - scq->skb[index] = skb; - XPRINTK("nicstar%d: sending skb at 0x%x (pos %d).\n", - card->index, (u32) skb, index); - XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", - card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2), - le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4), - (u32) scq->next); - if (scq->next == scq->last) - scq->next = scq->base; - else - scq->next++; - - vc->tbd_count++; - if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) - { - scq->tbd_count++; - scq_is_vbr = 1; - } - else - scq_is_vbr = 0; - - if (vc->tbd_count >= MAX_TBD_PER_VC || scq->tbd_count >= MAX_TBD_PER_SCQ) - { - int has_run = 0; - - while (scq->tail == scq->next) - { - if (in_interrupt()) { - data = (u32) virt_to_bus(scq->next); - ns_write_sram(card, scq->scd, &data, 1); - spin_unlock_irqrestore(&scq->lock, flags); - printk("nicstar%d: Error pushing TSR.\n", card->index); - return 0; - } - - scq->full = 1; - if (has_run++) break; - spin_unlock_irqrestore(&scq->lock, flags); - interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); - spin_lock_irqsave(&scq->lock, flags); - } - - if (!scq->full) - { - tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); - if (scq_is_vbr) - scdi = NS_TSR_SCDISVBR; - else - scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; - scqi = scq->next - scq->base; - tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); - tsr.word_3 = 0x00000000; - tsr.word_4 = 0x00000000; - - *scq->next = tsr; - index = (int) scqi; - scq->skb[index] = NULL; - XPRINTK("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", - card->index, le32_to_cpu(tsr.word_1), le32_to_cpu(tsr.word_2), - le32_to_cpu(tsr.word_3), le32_to_cpu(tsr.word_4), - (u32) scq->next); - if (scq->next == scq->last) - scq->next = scq->base; - else - scq->next++; - vc->tbd_count = 0; - scq->tbd_count = 0; - } - else - PRINTK("nicstar%d: Timeout pushing TSR.\n", card->index); - } - data = (u32) virt_to_bus(scq->next); - ns_write_sram(card, scq->scd, &data, 1); - - spin_unlock_irqrestore(&scq->lock, flags); - - return 0; -} + if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) { + printk("nicstar%d: Only AAL0 and AAL5 are supported.\n", + card->index); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); + return -EINVAL; + } + if (skb_shinfo(skb)->nr_frags != 0) { + printk("nicstar%d: No scatter-gather yet.\n", card->index); + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); + return -EINVAL; + } + + ATM_SKB(skb)->vcc = vcc; + + NS_PRV_DMA(skb) = pci_map_single(card->pcidev, skb->data, + skb->len, PCI_DMA_TODEVICE); + + if (vcc->qos.aal == ATM_AAL5) { + buflen = (skb->len + 47 + 8) / 48 * 48; /* Multiple of 48 */ + flags = NS_TBD_AAL5; + scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb)); + scqe.word_3 = cpu_to_le32(skb->len); + scqe.word_4 = + ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0, + ATM_SKB(skb)-> + atm_options & ATM_ATMOPT_CLP ? 1 : 0); + flags |= NS_TBD_EOPDU; + } else { /* (vcc->qos.aal == ATM_AAL0) */ + + buflen = ATM_CELL_PAYLOAD; /* i.e., 48 bytes */ + flags = NS_TBD_AAL0; + scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb) + NS_AAL0_HEADER); + scqe.word_3 = cpu_to_le32(0x00000000); + if (*skb->data & 0x02) /* Payload type 1 - end of pdu */ + flags |= NS_TBD_EOPDU; + scqe.word_4 = + cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK); + /* Force the VPI/VCI to be the same as in VCC struct */ + scqe.word_4 |= + cpu_to_le32((((u32) vcc-> + vpi) << NS_TBD_VPI_SHIFT | ((u32) vcc-> + vci) << + NS_TBD_VCI_SHIFT) & NS_TBD_VC_MASK); + } + + if (vcc->qos.txtp.traffic_class == ATM_CBR) { + scqe.word_1 = ns_tbd_mkword_1_novbr(flags, (u32) buflen); + scq = ((vc_map *) vcc->dev_data)->scq; + } else { + scqe.word_1 = + ns_tbd_mkword_1(flags, (u32) 1, (u32) 1, (u32) buflen); + scq = card->scq0; + } + + if (push_scqe(card, vc, scq, &scqe, skb) != 0) { + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); + return -EIO; + } + atomic_inc(&vcc->stats->tx); + return 0; +} -static void process_tsq(ns_dev *card) +static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd, + struct sk_buff *skb) { - u32 scdi; - scq_info *scq; - ns_tsi *previous = NULL, *one_ahead, *two_ahead; - int serviced_entries; /* flag indicating at least on entry was serviced */ - - serviced_entries = 0; - - if (card->tsq.next == card->tsq.last) - one_ahead = card->tsq.base; - else - one_ahead = card->tsq.next + 1; - - if (one_ahead == card->tsq.last) - two_ahead = card->tsq.base; - else - two_ahead = one_ahead + 1; - - while (!ns_tsi_isempty(card->tsq.next) || !ns_tsi_isempty(one_ahead) || - !ns_tsi_isempty(two_ahead)) - /* At most two empty, as stated in the 77201 errata */ - { - serviced_entries = 1; - - /* Skip the one or two possible empty entries */ - while (ns_tsi_isempty(card->tsq.next)) { - if (card->tsq.next == card->tsq.last) - card->tsq.next = card->tsq.base; - else - card->tsq.next++; - } - - if (!ns_tsi_tmrof(card->tsq.next)) - { - scdi = ns_tsi_getscdindex(card->tsq.next); - if (scdi == NS_TSI_SCDISVBR) - scq = card->scq0; - else - { - if (card->scd2vc[scdi] == NULL) - { - printk("nicstar%d: could not find VC from SCD index.\n", - card->index); - ns_tsi_init(card->tsq.next); - return; - } - scq = card->scd2vc[scdi]->scq; - } - drain_scq(card, scq, ns_tsi_getscqpos(card->tsq.next)); - scq->full = 0; - wake_up_interruptible(&(scq->scqfull_waitq)); - } - - ns_tsi_init(card->tsq.next); - previous = card->tsq.next; - if (card->tsq.next == card->tsq.last) - card->tsq.next = card->tsq.base; - else - card->tsq.next++; - - if (card->tsq.next == card->tsq.last) - one_ahead = card->tsq.base; - else - one_ahead = card->tsq.next + 1; - - if (one_ahead == card->tsq.last) - two_ahead = card->tsq.base; - else - two_ahead = one_ahead + 1; - } - - if (serviced_entries) { - writel((((u32) previous) - ((u32) card->tsq.base)), - card->membase + TSQH); - } + unsigned long flags; + ns_scqe tsr; + u32 scdi, scqi; + int scq_is_vbr; + u32 data; + int index; + + spin_lock_irqsave(&scq->lock, flags); + while (scq->tail == scq->next) { + if (in_interrupt()) { + spin_unlock_irqrestore(&scq->lock, flags); + printk("nicstar%d: Error pushing TBD.\n", card->index); + return 1; + } + + scq->full = 1; + wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq, + scq->tail != scq->next, + scq->lock, + SCQFULL_TIMEOUT); + + if (scq->full) { + spin_unlock_irqrestore(&scq->lock, flags); + printk("nicstar%d: Timeout pushing TBD.\n", + card->index); + return 1; + } + } + *scq->next = *tbd; + index = (int)(scq->next - scq->base); + scq->skb[index] = skb; + XPRINTK("nicstar%d: sending skb at 0x%p (pos %d).\n", + card->index, skb, index); + XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n", + card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2), + le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4), + scq->next); + if (scq->next == scq->last) + scq->next = scq->base; + else + scq->next++; + + vc->tbd_count++; + if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) { + scq->tbd_count++; + scq_is_vbr = 1; + } else + scq_is_vbr = 0; + + if (vc->tbd_count >= MAX_TBD_PER_VC + || scq->tbd_count >= MAX_TBD_PER_SCQ) { + int has_run = 0; + + while (scq->tail == scq->next) { + if (in_interrupt()) { + data = scq_virt_to_bus(scq, scq->next); + ns_write_sram(card, scq->scd, &data, 1); + spin_unlock_irqrestore(&scq->lock, flags); + printk("nicstar%d: Error pushing TSR.\n", + card->index); + return 0; + } + + scq->full = 1; + if (has_run++) + break; + wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq, + scq->tail != scq->next, + scq->lock, + SCQFULL_TIMEOUT); + } + + if (!scq->full) { + tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); + if (scq_is_vbr) + scdi = NS_TSR_SCDISVBR; + else + scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; + scqi = scq->next - scq->base; + tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); + tsr.word_3 = 0x00000000; + tsr.word_4 = 0x00000000; + + *scq->next = tsr; + index = (int)scqi; + scq->skb[index] = NULL; + XPRINTK + ("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n", + card->index, le32_to_cpu(tsr.word_1), + le32_to_cpu(tsr.word_2), le32_to_cpu(tsr.word_3), + le32_to_cpu(tsr.word_4), scq->next); + if (scq->next == scq->last) + scq->next = scq->base; + else + scq->next++; + vc->tbd_count = 0; + scq->tbd_count = 0; + } else + PRINTK("nicstar%d: Timeout pushing TSR.\n", + card->index); + } + data = scq_virt_to_bus(scq, scq->next); + ns_write_sram(card, scq->scd, &data, 1); + + spin_unlock_irqrestore(&scq->lock, flags); + + return 0; } - - -static void drain_scq(ns_dev *card, scq_info *scq, int pos) +static void process_tsq(ns_dev * card) { - struct atm_vcc *vcc; - struct sk_buff *skb; - int i; - unsigned long flags; - - XPRINTK("nicstar%d: drain_scq() called, scq at 0x%x, pos %d.\n", - card->index, (u32) scq, pos); - if (pos >= scq->num_entries) - { - printk("nicstar%d: Bad index on drain_scq().\n", card->index); - return; - } - - spin_lock_irqsave(&scq->lock, flags); - i = (int) (scq->tail - scq->base); - if (++i == scq->num_entries) - i = 0; - while (i != pos) - { - skb = scq->skb[i]; - XPRINTK("nicstar%d: freeing skb at 0x%x (index %d).\n", - card->index, (u32) skb, i); - if (skb != NULL) - { - vcc = ATM_SKB(skb)->vcc; - if (vcc && vcc->pop != NULL) { - vcc->pop(vcc, skb); - } else { - dev_kfree_skb_irq(skb); - } - scq->skb[i] = NULL; - } - if (++i == scq->num_entries) - i = 0; - } - scq->tail = scq->base + pos; - spin_unlock_irqrestore(&scq->lock, flags); + u32 scdi; + scq_info *scq; + ns_tsi *previous = NULL, *one_ahead, *two_ahead; + int serviced_entries; /* flag indicating at least on entry was serviced */ + + serviced_entries = 0; + + if (card->tsq.next == card->tsq.last) + one_ahead = card->tsq.base; + else + one_ahead = card->tsq.next + 1; + + if (one_ahead == card->tsq.last) + two_ahead = card->tsq.base; + else + two_ahead = one_ahead + 1; + + while (!ns_tsi_isempty(card->tsq.next) || !ns_tsi_isempty(one_ahead) || + !ns_tsi_isempty(two_ahead)) + /* At most two empty, as stated in the 77201 errata */ + { + serviced_entries = 1; + + /* Skip the one or two possible empty entries */ + while (ns_tsi_isempty(card->tsq.next)) { + if (card->tsq.next == card->tsq.last) + card->tsq.next = card->tsq.base; + else + card->tsq.next++; + } + + if (!ns_tsi_tmrof(card->tsq.next)) { + scdi = ns_tsi_getscdindex(card->tsq.next); + if (scdi == NS_TSI_SCDISVBR) + scq = card->scq0; + else { + if (card->scd2vc[scdi] == NULL) { + printk + ("nicstar%d: could not find VC from SCD index.\n", + card->index); + ns_tsi_init(card->tsq.next); + return; + } + scq = card->scd2vc[scdi]->scq; + } + drain_scq(card, scq, ns_tsi_getscqpos(card->tsq.next)); + scq->full = 0; + wake_up_interruptible(&(scq->scqfull_waitq)); + } + + ns_tsi_init(card->tsq.next); + previous = card->tsq.next; + if (card->tsq.next == card->tsq.last) + card->tsq.next = card->tsq.base; + else + card->tsq.next++; + + if (card->tsq.next == card->tsq.last) + one_ahead = card->tsq.base; + else + one_ahead = card->tsq.next + 1; + + if (one_ahead == card->tsq.last) + two_ahead = card->tsq.base; + else + two_ahead = one_ahead + 1; + } + + if (serviced_entries) + writel(PTR_DIFF(previous, card->tsq.base), + card->membase + TSQH); } +static void drain_scq(ns_dev * card, scq_info * scq, int pos) +{ + struct atm_vcc *vcc; + struct sk_buff *skb; + int i; + unsigned long flags; + + XPRINTK("nicstar%d: drain_scq() called, scq at 0x%p, pos %d.\n", + card->index, scq, pos); + if (pos >= scq->num_entries) { + printk("nicstar%d: Bad index on drain_scq().\n", card->index); + return; + } + + spin_lock_irqsave(&scq->lock, flags); + i = (int)(scq->tail - scq->base); + if (++i == scq->num_entries) + i = 0; + while (i != pos) { + skb = scq->skb[i]; + XPRINTK("nicstar%d: freeing skb at 0x%p (index %d).\n", + card->index, skb, i); + if (skb != NULL) { + pci_unmap_single(card->pcidev, + NS_PRV_DMA(skb), + skb->len, + PCI_DMA_TODEVICE); + vcc = ATM_SKB(skb)->vcc; + if (vcc && vcc->pop != NULL) { + vcc->pop(vcc, skb); + } else { + dev_kfree_skb_irq(skb); + } + scq->skb[i] = NULL; + } + if (++i == scq->num_entries) + i = 0; + } + scq->tail = scq->base + pos; + spin_unlock_irqrestore(&scq->lock, flags); +} - -static void process_rsq(ns_dev *card) +static void process_rsq(ns_dev * card) { - ns_rsqe *previous; - - if (!ns_rsqe_valid(card->rsq.next)) - return; - do { - dequeue_rx(card, card->rsq.next); - ns_rsqe_init(card->rsq.next); - previous = card->rsq.next; - if (card->rsq.next == card->rsq.last) - card->rsq.next = card->rsq.base; - else - card->rsq.next++; - } while (ns_rsqe_valid(card->rsq.next)); - writel((((u32) previous) - ((u32) card->rsq.base)), - card->membase + RSQH); + ns_rsqe *previous; + + if (!ns_rsqe_valid(card->rsq.next)) + return; + do { + dequeue_rx(card, card->rsq.next); + ns_rsqe_init(card->rsq.next); + previous = card->rsq.next; + if (card->rsq.next == card->rsq.last) + card->rsq.next = card->rsq.base; + else + card->rsq.next++; + } while (ns_rsqe_valid(card->rsq.next)); + writel(PTR_DIFF(previous, card->rsq.base), card->membase + RSQH); } +static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) +{ + u32 vpi, vci; + vc_map *vc; + struct sk_buff *iovb; + struct iovec *iov; + struct atm_vcc *vcc; + struct sk_buff *skb; + unsigned short aal5_len; + int len; + u32 stat; + u32 id; + + stat = readl(card->membase + STAT); + card->sbfqc = ns_stat_sfbqc_get(stat); + card->lbfqc = ns_stat_lfbqc_get(stat); + + id = le32_to_cpu(rsqe->buffer_handle); + skb = idr_find(&card->idr, id); + if (!skb) { + RXPRINTK(KERN_ERR + "nicstar%d: idr_find() failed!\n", card->index); + return; + } + idr_remove(&card->idr, id); + pci_dma_sync_single_for_cpu(card->pcidev, + NS_PRV_DMA(skb), + (NS_PRV_BUFTYPE(skb) == BUF_SM + ? NS_SMSKBSIZE : NS_LGSKBSIZE), + PCI_DMA_FROMDEVICE); + pci_unmap_single(card->pcidev, + NS_PRV_DMA(skb), + (NS_PRV_BUFTYPE(skb) == BUF_SM + ? NS_SMSKBSIZE : NS_LGSKBSIZE), + PCI_DMA_FROMDEVICE); + vpi = ns_rsqe_vpi(rsqe); + vci = ns_rsqe_vci(rsqe); + if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) { + printk("nicstar%d: SDU received for out-of-range vc %d.%d.\n", + card->index, vpi, vci); + recycle_rx_buf(card, skb); + return; + } + + vc = &(card->vcmap[vpi << card->vcibits | vci]); + if (!vc->rx) { + RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n", + card->index, vpi, vci); + recycle_rx_buf(card, skb); + return; + } + + vcc = vc->rx_vcc; + + if (vcc->qos.aal == ATM_AAL0) { + struct sk_buff *sb; + unsigned char *cell; + int i; + + cell = skb->data; + for (i = ns_rsqe_cellcount(rsqe); i; i--) { + if ((sb = dev_alloc_skb(NS_SMSKBSIZE)) == NULL) { + printk + ("nicstar%d: Can't allocate buffers for aal0.\n", + card->index); + atomic_add(i, &vcc->stats->rx_drop); + break; + } + if (!atm_charge(vcc, sb->truesize)) { + RXPRINTK + ("nicstar%d: atm_charge() dropped aal0 packets.\n", + card->index); + atomic_add(i - 1, &vcc->stats->rx_drop); /* already increased by 1 */ + dev_kfree_skb_any(sb); + break; + } + /* Rebuild the header */ + *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 | + (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000); + if (i == 1 && ns_rsqe_eopdu(rsqe)) + *((u32 *) sb->data) |= 0x00000002; + skb_put(sb, NS_AAL0_HEADER); + memcpy(skb_tail_pointer(sb), cell, ATM_CELL_PAYLOAD); + skb_put(sb, ATM_CELL_PAYLOAD); + ATM_SKB(sb)->vcc = vcc; + __net_timestamp(sb); + vcc->push(vcc, sb); + atomic_inc(&vcc->stats->rx); + cell += ATM_CELL_PAYLOAD; + } + + recycle_rx_buf(card, skb); + return; + } + + /* To reach this point, the AAL layer can only be AAL5 */ + + if ((iovb = vc->rx_iov) == NULL) { + iovb = skb_dequeue(&(card->iovpool.queue)); + if (iovb == NULL) { /* No buffers in the queue */ + iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC); + if (iovb == NULL) { + printk("nicstar%d: Out of iovec buffers.\n", + card->index); + atomic_inc(&vcc->stats->rx_drop); + recycle_rx_buf(card, skb); + return; + } + NS_PRV_BUFTYPE(iovb) = BUF_NONE; + } else if (--card->iovpool.count < card->iovnr.min) { + struct sk_buff *new_iovb; + if ((new_iovb = + alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL) { + NS_PRV_BUFTYPE(iovb) = BUF_NONE; + skb_queue_tail(&card->iovpool.queue, new_iovb); + card->iovpool.count++; + } + } + vc->rx_iov = iovb; + NS_PRV_IOVCNT(iovb) = 0; + iovb->len = 0; + iovb->data = iovb->head; + skb_reset_tail_pointer(iovb); + /* IMPORTANT: a pointer to the sk_buff containing the small or large + buffer is stored as iovec base, NOT a pointer to the + small or large buffer itself. */ + } else if (NS_PRV_IOVCNT(iovb) >= NS_MAX_IOVECS) { + printk("nicstar%d: received too big AAL5 SDU.\n", card->index); + atomic_inc(&vcc->stats->rx_err); + recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, + NS_MAX_IOVECS); + NS_PRV_IOVCNT(iovb) = 0; + iovb->len = 0; + iovb->data = iovb->head; + skb_reset_tail_pointer(iovb); + } + iov = &((struct iovec *)iovb->data)[NS_PRV_IOVCNT(iovb)++]; + iov->iov_base = (void *)skb; + iov->iov_len = ns_rsqe_cellcount(rsqe) * 48; + iovb->len += iov->iov_len; +#ifdef EXTRA_DEBUG + if (NS_PRV_IOVCNT(iovb) == 1) { + if (NS_PRV_BUFTYPE(skb) != BUF_SM) { + printk + ("nicstar%d: Expected a small buffer, and this is not one.\n", + card->index); + which_list(card, skb); + atomic_inc(&vcc->stats->rx_err); + recycle_rx_buf(card, skb); + vc->rx_iov = NULL; + recycle_iov_buf(card, iovb); + return; + } + } else { /* NS_PRV_IOVCNT(iovb) >= 2 */ + + if (NS_PRV_BUFTYPE(skb) != BUF_LG) { + printk + ("nicstar%d: Expected a large buffer, and this is not one.\n", + card->index); + which_list(card, skb); + atomic_inc(&vcc->stats->rx_err); + recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, + NS_PRV_IOVCNT(iovb)); + vc->rx_iov = NULL; + recycle_iov_buf(card, iovb); + return; + } + } +#endif /* EXTRA_DEBUG */ -static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) -{ - u32 vpi, vci; - vc_map *vc; - struct sk_buff *iovb; - struct iovec *iov; - struct atm_vcc *vcc; - struct sk_buff *skb; - unsigned short aal5_len; - int len; - u32 stat; - - stat = readl(card->membase + STAT); - card->sbfqc = ns_stat_sfbqc_get(stat); - card->lbfqc = ns_stat_lfbqc_get(stat); - - skb = (struct sk_buff *) le32_to_cpu(rsqe->buffer_handle); - vpi = ns_rsqe_vpi(rsqe); - vci = ns_rsqe_vci(rsqe); - if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) - { - printk("nicstar%d: SDU received for out-of-range vc %d.%d.\n", - card->index, vpi, vci); - recycle_rx_buf(card, skb); - return; - } - - vc = &(card->vcmap[vpi << card->vcibits | vci]); - if (!vc->rx) - { - RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n", - card->index, vpi, vci); - recycle_rx_buf(card, skb); - return; - } - - vcc = vc->rx_vcc; - - if (vcc->qos.aal == ATM_AAL0) - { - struct sk_buff *sb; - unsigned char *cell; - int i; - - cell = skb->data; - for (i = ns_rsqe_cellcount(rsqe); i; i--) - { - if ((sb = dev_alloc_skb(NS_SMSKBSIZE)) == NULL) - { - printk("nicstar%d: Can't allocate buffers for aal0.\n", - card->index); - atomic_add(i,&vcc->stats->rx_drop); - break; - } - if (!atm_charge(vcc, sb->truesize)) - { - RXPRINTK("nicstar%d: atm_charge() dropped aal0 packets.\n", - card->index); - atomic_add(i-1,&vcc->stats->rx_drop); /* already increased by 1 */ - dev_kfree_skb_any(sb); - break; - } - /* Rebuild the header */ - *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 | - (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000); - if (i == 1 && ns_rsqe_eopdu(rsqe)) - *((u32 *) sb->data) |= 0x00000002; - skb_put(sb, NS_AAL0_HEADER); - memcpy(skb_tail_pointer(sb), cell, ATM_CELL_PAYLOAD); - skb_put(sb, ATM_CELL_PAYLOAD); - ATM_SKB(sb)->vcc = vcc; - __net_timestamp(sb); - vcc->push(vcc, sb); - atomic_inc(&vcc->stats->rx); - cell += ATM_CELL_PAYLOAD; - } - - recycle_rx_buf(card, skb); - return; - } - - /* To reach this point, the AAL layer can only be AAL5 */ - - if ((iovb = vc->rx_iov) == NULL) - { - iovb = skb_dequeue(&(card->iovpool.queue)); - if (iovb == NULL) /* No buffers in the queue */ - { - iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC); - if (iovb == NULL) - { - printk("nicstar%d: Out of iovec buffers.\n", card->index); - atomic_inc(&vcc->stats->rx_drop); - recycle_rx_buf(card, skb); - return; - } - NS_SKB_CB(iovb)->buf_type = BUF_NONE; - } - else - if (--card->iovpool.count < card->iovnr.min) - { - struct sk_buff *new_iovb; - if ((new_iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL) - { - NS_SKB_CB(iovb)->buf_type = BUF_NONE; - skb_queue_tail(&card->iovpool.queue, new_iovb); - card->iovpool.count++; - } - } - vc->rx_iov = iovb; - NS_SKB(iovb)->iovcnt = 0; - iovb->len = 0; - iovb->data = iovb->head; - skb_reset_tail_pointer(iovb); - NS_SKB(iovb)->vcc = vcc; - /* IMPORTANT: a pointer to the sk_buff containing the small or large - buffer is stored as iovec base, NOT a pointer to the - small or large buffer itself. */ - } - else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS) - { - printk("nicstar%d: received too big AAL5 SDU.\n", card->index); - atomic_inc(&vcc->stats->rx_err); - recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS); - NS_SKB(iovb)->iovcnt = 0; - iovb->len = 0; - iovb->data = iovb->head; - skb_reset_tail_pointer(iovb); - NS_SKB(iovb)->vcc = vcc; - } - iov = &((struct iovec *) iovb->data)[NS_SKB(iovb)->iovcnt++]; - iov->iov_base = (void *) skb; - iov->iov_len = ns_rsqe_cellcount(rsqe) * 48; - iovb->len += iov->iov_len; - - if (NS_SKB(iovb)->iovcnt == 1) - { - if (NS_SKB_CB(skb)->buf_type != BUF_SM) - { - printk("nicstar%d: Expected a small buffer, and this is not one.\n", - card->index); - which_list(card, skb); - atomic_inc(&vcc->stats->rx_err); - recycle_rx_buf(card, skb); - vc->rx_iov = NULL; - recycle_iov_buf(card, iovb); - return; - } - } - else /* NS_SKB(iovb)->iovcnt >= 2 */ - { - if (NS_SKB_CB(skb)->buf_type != BUF_LG) - { - printk("nicstar%d: Expected a large buffer, and this is not one.\n", - card->index); - which_list(card, skb); - atomic_inc(&vcc->stats->rx_err); - recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - NS_SKB(iovb)->iovcnt); - vc->rx_iov = NULL; - recycle_iov_buf(card, iovb); - return; - } - } - - if (ns_rsqe_eopdu(rsqe)) - { - /* This works correctly regardless of the endianness of the host */ - unsigned char *L1L2 = (unsigned char *)((u32)skb->data + - iov->iov_len - 6); - aal5_len = L1L2[0] << 8 | L1L2[1]; - len = (aal5_len == 0x0000) ? 0x10000 : aal5_len; - if (ns_rsqe_crcerr(rsqe) || - len + 8 > iovb->len || len + (47 + 8) < iovb->len) - { - printk("nicstar%d: AAL5 CRC error", card->index); - if (len + 8 > iovb->len || len + (47 + 8) < iovb->len) - printk(" - PDU size mismatch.\n"); - else - printk(".\n"); - atomic_inc(&vcc->stats->rx_err); - recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - NS_SKB(iovb)->iovcnt); - vc->rx_iov = NULL; - recycle_iov_buf(card, iovb); - return; - } - - /* By this point we (hopefully) have a complete SDU without errors. */ - - if (NS_SKB(iovb)->iovcnt == 1) /* Just a small buffer */ - { - /* skb points to a small buffer */ - if (!atm_charge(vcc, skb->truesize)) - { - push_rxbufs(card, skb); - atomic_inc(&vcc->stats->rx_drop); - } - else - { - skb_put(skb, len); - dequeue_sm_buf(card, skb); + if (ns_rsqe_eopdu(rsqe)) { + /* This works correctly regardless of the endianness of the host */ + unsigned char *L1L2 = (unsigned char *) + (skb->data + iov->iov_len - 6); + aal5_len = L1L2[0] << 8 | L1L2[1]; + len = (aal5_len == 0x0000) ? 0x10000 : aal5_len; + if (ns_rsqe_crcerr(rsqe) || + len + 8 > iovb->len || len + (47 + 8) < iovb->len) { + printk("nicstar%d: AAL5 CRC error", card->index); + if (len + 8 > iovb->len || len + (47 + 8) < iovb->len) + printk(" - PDU size mismatch.\n"); + else + printk(".\n"); + atomic_inc(&vcc->stats->rx_err); + recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, + NS_PRV_IOVCNT(iovb)); + vc->rx_iov = NULL; + recycle_iov_buf(card, iovb); + return; + } + + /* By this point we (hopefully) have a complete SDU without errors. */ + + if (NS_PRV_IOVCNT(iovb) == 1) { /* Just a small buffer */ + /* skb points to a small buffer */ + if (!atm_charge(vcc, skb->truesize)) { + push_rxbufs(card, skb); + atomic_inc(&vcc->stats->rx_drop); + } else { + skb_put(skb, len); + dequeue_sm_buf(card, skb); #ifdef NS_USE_DESTRUCTORS - skb->destructor = ns_sb_destructor; + skb->destructor = ns_sb_destructor; #endif /* NS_USE_DESTRUCTORS */ - ATM_SKB(skb)->vcc = vcc; - __net_timestamp(skb); - vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); - } - } - else if (NS_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */ - { - struct sk_buff *sb; - - sb = (struct sk_buff *) (iov - 1)->iov_base; - /* skb points to a large buffer */ - - if (len <= NS_SMBUFSIZE) - { - if (!atm_charge(vcc, sb->truesize)) - { - push_rxbufs(card, sb); - atomic_inc(&vcc->stats->rx_drop); - } - else - { - skb_put(sb, len); - dequeue_sm_buf(card, sb); + ATM_SKB(skb)->vcc = vcc; + __net_timestamp(skb); + vcc->push(vcc, skb); + atomic_inc(&vcc->stats->rx); + } + } else if (NS_PRV_IOVCNT(iovb) == 2) { /* One small plus one large buffer */ + struct sk_buff *sb; + + sb = (struct sk_buff *)(iov - 1)->iov_base; + /* skb points to a large buffer */ + + if (len <= NS_SMBUFSIZE) { + if (!atm_charge(vcc, sb->truesize)) { + push_rxbufs(card, sb); + atomic_inc(&vcc->stats->rx_drop); + } else { + skb_put(sb, len); + dequeue_sm_buf(card, sb); #ifdef NS_USE_DESTRUCTORS - sb->destructor = ns_sb_destructor; + sb->destructor = ns_sb_destructor; #endif /* NS_USE_DESTRUCTORS */ - ATM_SKB(sb)->vcc = vcc; - __net_timestamp(sb); - vcc->push(vcc, sb); - atomic_inc(&vcc->stats->rx); - } - - push_rxbufs(card, skb); - - } - else /* len > NS_SMBUFSIZE, the usual case */ - { - if (!atm_charge(vcc, skb->truesize)) - { - push_rxbufs(card, skb); - atomic_inc(&vcc->stats->rx_drop); - } - else - { - dequeue_lg_buf(card, skb); + ATM_SKB(sb)->vcc = vcc; + __net_timestamp(sb); + vcc->push(vcc, sb); + atomic_inc(&vcc->stats->rx); + } + + push_rxbufs(card, skb); + + } else { /* len > NS_SMBUFSIZE, the usual case */ + + if (!atm_charge(vcc, skb->truesize)) { + push_rxbufs(card, skb); + atomic_inc(&vcc->stats->rx_drop); + } else { + dequeue_lg_buf(card, skb); #ifdef NS_USE_DESTRUCTORS - skb->destructor = ns_lb_destructor; + skb->destructor = ns_lb_destructor; #endif /* NS_USE_DESTRUCTORS */ - skb_push(skb, NS_SMBUFSIZE); - skb_copy_from_linear_data(sb, skb->data, NS_SMBUFSIZE); - skb_put(skb, len - NS_SMBUFSIZE); - ATM_SKB(skb)->vcc = vcc; - __net_timestamp(skb); - vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); - } - - push_rxbufs(card, sb); - - } - - } - else /* Must push a huge buffer */ - { - struct sk_buff *hb, *sb, *lb; - int remaining, tocopy; - int j; - - hb = skb_dequeue(&(card->hbpool.queue)); - if (hb == NULL) /* No buffers in the queue */ - { - - hb = dev_alloc_skb(NS_HBUFSIZE); - if (hb == NULL) - { - printk("nicstar%d: Out of huge buffers.\n", card->index); - atomic_inc(&vcc->stats->rx_drop); - recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - NS_SKB(iovb)->iovcnt); - vc->rx_iov = NULL; - recycle_iov_buf(card, iovb); - return; - } - else if (card->hbpool.count < card->hbnr.min) - { - struct sk_buff *new_hb; - if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) - { - skb_queue_tail(&card->hbpool.queue, new_hb); - card->hbpool.count++; - } - } - NS_SKB_CB(hb)->buf_type = BUF_NONE; - } - else - if (--card->hbpool.count < card->hbnr.min) - { - struct sk_buff *new_hb; - if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) - { - NS_SKB_CB(new_hb)->buf_type = BUF_NONE; - skb_queue_tail(&card->hbpool.queue, new_hb); - card->hbpool.count++; - } - if (card->hbpool.count < card->hbnr.min) - { - if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) - { - NS_SKB_CB(new_hb)->buf_type = BUF_NONE; - skb_queue_tail(&card->hbpool.queue, new_hb); - card->hbpool.count++; - } - } - } - - iov = (struct iovec *) iovb->data; - - if (!atm_charge(vcc, hb->truesize)) - { - recycle_iovec_rx_bufs(card, iov, NS_SKB(iovb)->iovcnt); - if (card->hbpool.count < card->hbnr.max) - { - skb_queue_tail(&card->hbpool.queue, hb); - card->hbpool.count++; - } - else - dev_kfree_skb_any(hb); - atomic_inc(&vcc->stats->rx_drop); - } - else - { - /* Copy the small buffer to the huge buffer */ - sb = (struct sk_buff *) iov->iov_base; - skb_copy_from_linear_data(sb, hb->data, iov->iov_len); - skb_put(hb, iov->iov_len); - remaining = len - iov->iov_len; - iov++; - /* Free the small buffer */ - push_rxbufs(card, sb); - - /* Copy all large buffers to the huge buffer and free them */ - for (j = 1; j < NS_SKB(iovb)->iovcnt; j++) - { - lb = (struct sk_buff *) iov->iov_base; - tocopy = min_t(int, remaining, iov->iov_len); - skb_copy_from_linear_data(lb, skb_tail_pointer(hb), tocopy); - skb_put(hb, tocopy); - iov++; - remaining -= tocopy; - push_rxbufs(card, lb); - } + skb_push(skb, NS_SMBUFSIZE); + skb_copy_from_linear_data(sb, skb->data, + NS_SMBUFSIZE); + skb_put(skb, len - NS_SMBUFSIZE); + ATM_SKB(skb)->vcc = vcc; + __net_timestamp(skb); + vcc->push(vcc, skb); + atomic_inc(&vcc->stats->rx); + } + + push_rxbufs(card, sb); + + } + + } else { /* Must push a huge buffer */ + + struct sk_buff *hb, *sb, *lb; + int remaining, tocopy; + int j; + + hb = skb_dequeue(&(card->hbpool.queue)); + if (hb == NULL) { /* No buffers in the queue */ + + hb = dev_alloc_skb(NS_HBUFSIZE); + if (hb == NULL) { + printk + ("nicstar%d: Out of huge buffers.\n", + card->index); + atomic_inc(&vcc->stats->rx_drop); + recycle_iovec_rx_bufs(card, + (struct iovec *) + iovb->data, + NS_PRV_IOVCNT(iovb)); + vc->rx_iov = NULL; + recycle_iov_buf(card, iovb); + return; + } else if (card->hbpool.count < card->hbnr.min) { + struct sk_buff *new_hb; + if ((new_hb = + dev_alloc_skb(NS_HBUFSIZE)) != + NULL) { + skb_queue_tail(&card->hbpool. + queue, new_hb); + card->hbpool.count++; + } + } + NS_PRV_BUFTYPE(hb) = BUF_NONE; + } else if (--card->hbpool.count < card->hbnr.min) { + struct sk_buff *new_hb; + if ((new_hb = + dev_alloc_skb(NS_HBUFSIZE)) != NULL) { + NS_PRV_BUFTYPE(new_hb) = BUF_NONE; + skb_queue_tail(&card->hbpool.queue, + new_hb); + card->hbpool.count++; + } + if (card->hbpool.count < card->hbnr.min) { + if ((new_hb = + dev_alloc_skb(NS_HBUFSIZE)) != + NULL) { + NS_PRV_BUFTYPE(new_hb) = + BUF_NONE; + skb_queue_tail(&card->hbpool. + queue, new_hb); + card->hbpool.count++; + } + } + } + + iov = (struct iovec *)iovb->data; + + if (!atm_charge(vcc, hb->truesize)) { + recycle_iovec_rx_bufs(card, iov, + NS_PRV_IOVCNT(iovb)); + if (card->hbpool.count < card->hbnr.max) { + skb_queue_tail(&card->hbpool.queue, hb); + card->hbpool.count++; + } else + dev_kfree_skb_any(hb); + atomic_inc(&vcc->stats->rx_drop); + } else { + /* Copy the small buffer to the huge buffer */ + sb = (struct sk_buff *)iov->iov_base; + skb_copy_from_linear_data(sb, hb->data, + iov->iov_len); + skb_put(hb, iov->iov_len); + remaining = len - iov->iov_len; + iov++; + /* Free the small buffer */ + push_rxbufs(card, sb); + + /* Copy all large buffers to the huge buffer and free them */ + for (j = 1; j < NS_PRV_IOVCNT(iovb); j++) { + lb = (struct sk_buff *)iov->iov_base; + tocopy = + min_t(int, remaining, iov->iov_len); + skb_copy_from_linear_data(lb, + skb_tail_pointer + (hb), tocopy); + skb_put(hb, tocopy); + iov++; + remaining -= tocopy; + push_rxbufs(card, lb); + } #ifdef EXTRA_DEBUG - if (remaining != 0 || hb->len != len) - printk("nicstar%d: Huge buffer len mismatch.\n", card->index); + if (remaining != 0 || hb->len != len) + printk + ("nicstar%d: Huge buffer len mismatch.\n", + card->index); #endif /* EXTRA_DEBUG */ - ATM_SKB(hb)->vcc = vcc; + ATM_SKB(hb)->vcc = vcc; #ifdef NS_USE_DESTRUCTORS - hb->destructor = ns_hb_destructor; + hb->destructor = ns_hb_destructor; #endif /* NS_USE_DESTRUCTORS */ - __net_timestamp(hb); - vcc->push(vcc, hb); - atomic_inc(&vcc->stats->rx); - } - } + __net_timestamp(hb); + vcc->push(vcc, hb); + atomic_inc(&vcc->stats->rx); + } + } - vc->rx_iov = NULL; - recycle_iov_buf(card, iovb); - } + vc->rx_iov = NULL; + recycle_iov_buf(card, iovb); + } } - - #ifdef NS_USE_DESTRUCTORS static void ns_sb_destructor(struct sk_buff *sb) { - ns_dev *card; - u32 stat; - - card = (ns_dev *) ATM_SKB(sb)->vcc->dev->dev_data; - stat = readl(card->membase + STAT); - card->sbfqc = ns_stat_sfbqc_get(stat); - card->lbfqc = ns_stat_lfbqc_get(stat); - - do - { - sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); - if (sb == NULL) - break; - NS_SKB_CB(sb)->buf_type = BUF_SM; - skb_queue_tail(&card->sbpool.queue, sb); - skb_reserve(sb, NS_AAL0_HEADER); - push_rxbufs(card, sb); - } while (card->sbfqc < card->sbnr.min); + ns_dev *card; + u32 stat; + + card = (ns_dev *) ATM_SKB(sb)->vcc->dev->dev_data; + stat = readl(card->membase + STAT); + card->sbfqc = ns_stat_sfbqc_get(stat); + card->lbfqc = ns_stat_lfbqc_get(stat); + + do { + sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); + if (sb == NULL) + break; + NS_PRV_BUFTYPE(sb) = BUF_SM; + skb_queue_tail(&card->sbpool.queue, sb); + skb_reserve(sb, NS_AAL0_HEADER); + push_rxbufs(card, sb); + } while (card->sbfqc < card->sbnr.min); } - - static void ns_lb_destructor(struct sk_buff *lb) { - ns_dev *card; - u32 stat; - - card = (ns_dev *) ATM_SKB(lb)->vcc->dev->dev_data; - stat = readl(card->membase + STAT); - card->sbfqc = ns_stat_sfbqc_get(stat); - card->lbfqc = ns_stat_lfbqc_get(stat); - - do - { - lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); - if (lb == NULL) - break; - NS_SKB_CB(lb)->buf_type = BUF_LG; - skb_queue_tail(&card->lbpool.queue, lb); - skb_reserve(lb, NS_SMBUFSIZE); - push_rxbufs(card, lb); - } while (card->lbfqc < card->lbnr.min); + ns_dev *card; + u32 stat; + + card = (ns_dev *) ATM_SKB(lb)->vcc->dev->dev_data; + stat = readl(card->membase + STAT); + card->sbfqc = ns_stat_sfbqc_get(stat); + card->lbfqc = ns_stat_lfbqc_get(stat); + + do { + lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); + if (lb == NULL) + break; + NS_PRV_BUFTYPE(lb) = BUF_LG; + skb_queue_tail(&card->lbpool.queue, lb); + skb_reserve(lb, NS_SMBUFSIZE); + push_rxbufs(card, lb); + } while (card->lbfqc < card->lbnr.min); } - - static void ns_hb_destructor(struct sk_buff *hb) { - ns_dev *card; - - card = (ns_dev *) ATM_SKB(hb)->vcc->dev->dev_data; - - while (card->hbpool.count < card->hbnr.init) - { - hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); - if (hb == NULL) - break; - NS_SKB_CB(hb)->buf_type = BUF_NONE; - skb_queue_tail(&card->hbpool.queue, hb); - card->hbpool.count++; - } + ns_dev *card; + + card = (ns_dev *) ATM_SKB(hb)->vcc->dev->dev_data; + + while (card->hbpool.count < card->hbnr.init) { + hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); + if (hb == NULL) + break; + NS_PRV_BUFTYPE(hb) = BUF_NONE; + skb_queue_tail(&card->hbpool.queue, hb); + card->hbpool.count++; + } } #endif /* NS_USE_DESTRUCTORS */ - -static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb) +static void recycle_rx_buf(ns_dev * card, struct sk_buff *skb) { - struct ns_skb_cb *cb = NS_SKB_CB(skb); - - if (unlikely(cb->buf_type == BUF_NONE)) { - printk("nicstar%d: What kind of rx buffer is this?\n", card->index); + if (unlikely(NS_PRV_BUFTYPE(skb) == BUF_NONE)) { + printk("nicstar%d: What kind of rx buffer is this?\n", + card->index); dev_kfree_skb_any(skb); } else push_rxbufs(card, skb); } - -static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count) +static void recycle_iovec_rx_bufs(ns_dev * card, struct iovec *iov, int count) { while (count-- > 0) - recycle_rx_buf(card, (struct sk_buff *) (iov++)->iov_base); + recycle_rx_buf(card, (struct sk_buff *)(iov++)->iov_base); } - -static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb) +static void recycle_iov_buf(ns_dev * card, struct sk_buff *iovb) { - if (card->iovpool.count < card->iovnr.max) - { - skb_queue_tail(&card->iovpool.queue, iovb); - card->iovpool.count++; - } - else - dev_kfree_skb_any(iovb); + if (card->iovpool.count < card->iovnr.max) { + skb_queue_tail(&card->iovpool.queue, iovb); + card->iovpool.count++; + } else + dev_kfree_skb_any(iovb); } - - -static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb) +static void dequeue_sm_buf(ns_dev * card, struct sk_buff *sb) { - skb_unlink(sb, &card->sbpool.queue); + skb_unlink(sb, &card->sbpool.queue); #ifdef NS_USE_DESTRUCTORS - if (card->sbfqc < card->sbnr.min) + if (card->sbfqc < card->sbnr.min) #else - if (card->sbfqc < card->sbnr.init) - { - struct sk_buff *new_sb; - if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) - { - NS_SKB_CB(new_sb)->buf_type = BUF_SM; - skb_queue_tail(&card->sbpool.queue, new_sb); - skb_reserve(new_sb, NS_AAL0_HEADER); - push_rxbufs(card, new_sb); - } - } - if (card->sbfqc < card->sbnr.init) + if (card->sbfqc < card->sbnr.init) { + struct sk_buff *new_sb; + if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) { + NS_PRV_BUFTYPE(new_sb) = BUF_SM; + skb_queue_tail(&card->sbpool.queue, new_sb); + skb_reserve(new_sb, NS_AAL0_HEADER); + push_rxbufs(card, new_sb); + } + } + if (card->sbfqc < card->sbnr.init) #endif /* NS_USE_DESTRUCTORS */ - { - struct sk_buff *new_sb; - if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) - { - NS_SKB_CB(new_sb)->buf_type = BUF_SM; - skb_queue_tail(&card->sbpool.queue, new_sb); - skb_reserve(new_sb, NS_AAL0_HEADER); - push_rxbufs(card, new_sb); - } - } + { + struct sk_buff *new_sb; + if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) { + NS_PRV_BUFTYPE(new_sb) = BUF_SM; + skb_queue_tail(&card->sbpool.queue, new_sb); + skb_reserve(new_sb, NS_AAL0_HEADER); + push_rxbufs(card, new_sb); + } + } } - - -static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb) +static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb) { - skb_unlink(lb, &card->lbpool.queue); + skb_unlink(lb, &card->lbpool.queue); #ifdef NS_USE_DESTRUCTORS - if (card->lbfqc < card->lbnr.min) + if (card->lbfqc < card->lbnr.min) #else - if (card->lbfqc < card->lbnr.init) - { - struct sk_buff *new_lb; - if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) - { - NS_SKB_CB(new_lb)->buf_type = BUF_LG; - skb_queue_tail(&card->lbpool.queue, new_lb); - skb_reserve(new_lb, NS_SMBUFSIZE); - push_rxbufs(card, new_lb); - } - } - if (card->lbfqc < card->lbnr.init) + if (card->lbfqc < card->lbnr.init) { + struct sk_buff *new_lb; + if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) { + NS_PRV_BUFTYPE(new_lb) = BUF_LG; + skb_queue_tail(&card->lbpool.queue, new_lb); + skb_reserve(new_lb, NS_SMBUFSIZE); + push_rxbufs(card, new_lb); + } + } + if (card->lbfqc < card->lbnr.init) #endif /* NS_USE_DESTRUCTORS */ - { - struct sk_buff *new_lb; - if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) - { - NS_SKB_CB(new_lb)->buf_type = BUF_LG; - skb_queue_tail(&card->lbpool.queue, new_lb); - skb_reserve(new_lb, NS_SMBUFSIZE); - push_rxbufs(card, new_lb); - } - } + { + struct sk_buff *new_lb; + if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) { + NS_PRV_BUFTYPE(new_lb) = BUF_LG; + skb_queue_tail(&card->lbpool.queue, new_lb); + skb_reserve(new_lb, NS_SMBUFSIZE); + push_rxbufs(card, new_lb); + } + } } - - -static int ns_proc_read(struct atm_dev *dev, loff_t *pos, char *page) +static int ns_proc_read(struct atm_dev *dev, loff_t * pos, char *page) { - u32 stat; - ns_dev *card; - int left; - - left = (int) *pos; - card = (ns_dev *) dev->dev_data; - stat = readl(card->membase + STAT); - if (!left--) - return sprintf(page, "Pool count min init max \n"); - if (!left--) - return sprintf(page, "Small %5d %5d %5d %5d \n", - ns_stat_sfbqc_get(stat), card->sbnr.min, card->sbnr.init, - card->sbnr.max); - if (!left--) - return sprintf(page, "Large %5d %5d %5d %5d \n", - ns_stat_lfbqc_get(stat), card->lbnr.min, card->lbnr.init, - card->lbnr.max); - if (!left--) - return sprintf(page, "Huge %5d %5d %5d %5d \n", card->hbpool.count, - card->hbnr.min, card->hbnr.init, card->hbnr.max); - if (!left--) - return sprintf(page, "Iovec %5d %5d %5d %5d \n", card->iovpool.count, - card->iovnr.min, card->iovnr.init, card->iovnr.max); - if (!left--) - { - int retval; - retval = sprintf(page, "Interrupt counter: %u \n", card->intcnt); - card->intcnt = 0; - return retval; - } + u32 stat; + ns_dev *card; + int left; + + left = (int)*pos; + card = (ns_dev *) dev->dev_data; + stat = readl(card->membase + STAT); + if (!left--) + return sprintf(page, "Pool count min init max \n"); + if (!left--) + return sprintf(page, "Small %5d %5d %5d %5d \n", + ns_stat_sfbqc_get(stat), card->sbnr.min, + card->sbnr.init, card->sbnr.max); + if (!left--) + return sprintf(page, "Large %5d %5d %5d %5d \n", + ns_stat_lfbqc_get(stat), card->lbnr.min, + card->lbnr.init, card->lbnr.max); + if (!left--) + return sprintf(page, "Huge %5d %5d %5d %5d \n", + card->hbpool.count, card->hbnr.min, + card->hbnr.init, card->hbnr.max); + if (!left--) + return sprintf(page, "Iovec %5d %5d %5d %5d \n", + card->iovpool.count, card->iovnr.min, + card->iovnr.init, card->iovnr.max); + if (!left--) { + int retval; + retval = + sprintf(page, "Interrupt counter: %u \n", card->intcnt); + card->intcnt = 0; + return retval; + } #if 0 - /* Dump 25.6 Mbps PHY registers */ - /* Now there's a 25.6 Mbps PHY driver this code isn't needed. I left it - here just in case it's needed for debugging. */ - if (card->max_pcr == ATM_25_PCR && !left--) - { - u32 phy_regs[4]; - u32 i; - - for (i = 0; i < 4; i++) - { - while (CMD_BUSY(card)); - writel(NS_CMD_READ_UTILITY | 0x00000200 | i, card->membase + CMD); - while (CMD_BUSY(card)); - phy_regs[i] = readl(card->membase + DR0) & 0x000000FF; - } - - return sprintf(page, "PHY regs: 0x%02X 0x%02X 0x%02X 0x%02X \n", - phy_regs[0], phy_regs[1], phy_regs[2], phy_regs[3]); - } + /* Dump 25.6 Mbps PHY registers */ + /* Now there's a 25.6 Mbps PHY driver this code isn't needed. I left it + here just in case it's needed for debugging. */ + if (card->max_pcr == ATM_25_PCR && !left--) { + u32 phy_regs[4]; + u32 i; + + for (i = 0; i < 4; i++) { + while (CMD_BUSY(card)) ; + writel(NS_CMD_READ_UTILITY | 0x00000200 | i, + card->membase + CMD); + while (CMD_BUSY(card)) ; + phy_regs[i] = readl(card->membase + DR0) & 0x000000FF; + } + + return sprintf(page, "PHY regs: 0x%02X 0x%02X 0x%02X 0x%02X \n", + phy_regs[0], phy_regs[1], phy_regs[2], + phy_regs[3]); + } #endif /* 0 - Dump 25.6 Mbps PHY registers */ #if 0 - /* Dump TST */ - if (left-- < NS_TST_NUM_ENTRIES) - { - if (card->tste2vc[left + 1] == NULL) - return sprintf(page, "%5d - VBR/UBR \n", left + 1); - else - return sprintf(page, "%5d - %d %d \n", left + 1, - card->tste2vc[left + 1]->tx_vcc->vpi, - card->tste2vc[left + 1]->tx_vcc->vci); - } + /* Dump TST */ + if (left-- < NS_TST_NUM_ENTRIES) { + if (card->tste2vc[left + 1] == NULL) + return sprintf(page, "%5d - VBR/UBR \n", left + 1); + else + return sprintf(page, "%5d - %d %d \n", left + 1, + card->tste2vc[left + 1]->tx_vcc->vpi, + card->tste2vc[left + 1]->tx_vcc->vci); + } #endif /* 0 */ - return 0; + return 0; } - - -static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) +static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg) { - ns_dev *card; - pool_levels pl; - long btype; - unsigned long flags; - - card = dev->dev_data; - switch (cmd) - { - case NS_GETPSTAT: - if (get_user(pl.buftype, &((pool_levels __user *) arg)->buftype)) - return -EFAULT; - switch (pl.buftype) - { - case NS_BUFTYPE_SMALL: - pl.count = ns_stat_sfbqc_get(readl(card->membase + STAT)); - pl.level.min = card->sbnr.min; - pl.level.init = card->sbnr.init; - pl.level.max = card->sbnr.max; - break; - - case NS_BUFTYPE_LARGE: - pl.count = ns_stat_lfbqc_get(readl(card->membase + STAT)); - pl.level.min = card->lbnr.min; - pl.level.init = card->lbnr.init; - pl.level.max = card->lbnr.max; - break; - - case NS_BUFTYPE_HUGE: - pl.count = card->hbpool.count; - pl.level.min = card->hbnr.min; - pl.level.init = card->hbnr.init; - pl.level.max = card->hbnr.max; - break; - - case NS_BUFTYPE_IOVEC: - pl.count = card->iovpool.count; - pl.level.min = card->iovnr.min; - pl.level.init = card->iovnr.init; - pl.level.max = card->iovnr.max; - break; - - default: - return -ENOIOCTLCMD; - - } - if (!copy_to_user((pool_levels __user *) arg, &pl, sizeof(pl))) - return (sizeof(pl)); - else - return -EFAULT; - - case NS_SETBUFLEV: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&pl, (pool_levels __user *) arg, sizeof(pl))) - return -EFAULT; - if (pl.level.min >= pl.level.init || pl.level.init >= pl.level.max) - return -EINVAL; - if (pl.level.min == 0) - return -EINVAL; - switch (pl.buftype) - { - case NS_BUFTYPE_SMALL: - if (pl.level.max > TOP_SB) - return -EINVAL; - card->sbnr.min = pl.level.min; - card->sbnr.init = pl.level.init; - card->sbnr.max = pl.level.max; - break; - - case NS_BUFTYPE_LARGE: - if (pl.level.max > TOP_LB) - return -EINVAL; - card->lbnr.min = pl.level.min; - card->lbnr.init = pl.level.init; - card->lbnr.max = pl.level.max; - break; - - case NS_BUFTYPE_HUGE: - if (pl.level.max > TOP_HB) - return -EINVAL; - card->hbnr.min = pl.level.min; - card->hbnr.init = pl.level.init; - card->hbnr.max = pl.level.max; - break; - - case NS_BUFTYPE_IOVEC: - if (pl.level.max > TOP_IOVB) - return -EINVAL; - card->iovnr.min = pl.level.min; - card->iovnr.init = pl.level.init; - card->iovnr.max = pl.level.max; - break; - - default: - return -EINVAL; - - } - return 0; - - case NS_ADJBUFLEV: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - btype = (long) arg; /* a long is the same size as a pointer or bigger */ - switch (btype) - { - case NS_BUFTYPE_SMALL: - while (card->sbfqc < card->sbnr.init) - { - struct sk_buff *sb; - - sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); - if (sb == NULL) - return -ENOMEM; - NS_SKB_CB(sb)->buf_type = BUF_SM; - skb_queue_tail(&card->sbpool.queue, sb); - skb_reserve(sb, NS_AAL0_HEADER); - push_rxbufs(card, sb); - } - break; - - case NS_BUFTYPE_LARGE: - while (card->lbfqc < card->lbnr.init) - { - struct sk_buff *lb; - - lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); - if (lb == NULL) - return -ENOMEM; - NS_SKB_CB(lb)->buf_type = BUF_LG; - skb_queue_tail(&card->lbpool.queue, lb); - skb_reserve(lb, NS_SMBUFSIZE); - push_rxbufs(card, lb); - } - break; - - case NS_BUFTYPE_HUGE: - while (card->hbpool.count > card->hbnr.init) - { - struct sk_buff *hb; - - spin_lock_irqsave(&card->int_lock, flags); - hb = skb_dequeue(&card->hbpool.queue); - card->hbpool.count--; - spin_unlock_irqrestore(&card->int_lock, flags); - if (hb == NULL) - printk("nicstar%d: huge buffer count inconsistent.\n", - card->index); - else - dev_kfree_skb_any(hb); - - } - while (card->hbpool.count < card->hbnr.init) - { - struct sk_buff *hb; - - hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); - if (hb == NULL) - return -ENOMEM; - NS_SKB_CB(hb)->buf_type = BUF_NONE; - spin_lock_irqsave(&card->int_lock, flags); - skb_queue_tail(&card->hbpool.queue, hb); - card->hbpool.count++; - spin_unlock_irqrestore(&card->int_lock, flags); - } - break; - - case NS_BUFTYPE_IOVEC: - while (card->iovpool.count > card->iovnr.init) - { - struct sk_buff *iovb; - - spin_lock_irqsave(&card->int_lock, flags); - iovb = skb_dequeue(&card->iovpool.queue); - card->iovpool.count--; - spin_unlock_irqrestore(&card->int_lock, flags); - if (iovb == NULL) - printk("nicstar%d: iovec buffer count inconsistent.\n", - card->index); - else - dev_kfree_skb_any(iovb); - - } - while (card->iovpool.count < card->iovnr.init) - { - struct sk_buff *iovb; - - iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); - if (iovb == NULL) - return -ENOMEM; - NS_SKB_CB(iovb)->buf_type = BUF_NONE; - spin_lock_irqsave(&card->int_lock, flags); - skb_queue_tail(&card->iovpool.queue, iovb); - card->iovpool.count++; - spin_unlock_irqrestore(&card->int_lock, flags); - } - break; - - default: - return -EINVAL; - - } - return 0; - - default: - if (dev->phy && dev->phy->ioctl) { - return dev->phy->ioctl(dev, cmd, arg); - } - else { - printk("nicstar%d: %s == NULL \n", card->index, - dev->phy ? "dev->phy->ioctl" : "dev->phy"); - return -ENOIOCTLCMD; - } - } + ns_dev *card; + pool_levels pl; + long btype; + unsigned long flags; + + card = dev->dev_data; + switch (cmd) { + case NS_GETPSTAT: + if (get_user + (pl.buftype, &((pool_levels __user *) arg)->buftype)) + return -EFAULT; + switch (pl.buftype) { + case NS_BUFTYPE_SMALL: + pl.count = + ns_stat_sfbqc_get(readl(card->membase + STAT)); + pl.level.min = card->sbnr.min; + pl.level.init = card->sbnr.init; + pl.level.max = card->sbnr.max; + break; + + case NS_BUFTYPE_LARGE: + pl.count = + ns_stat_lfbqc_get(readl(card->membase + STAT)); + pl.level.min = card->lbnr.min; + pl.level.init = card->lbnr.init; + pl.level.max = card->lbnr.max; + break; + + case NS_BUFTYPE_HUGE: + pl.count = card->hbpool.count; + pl.level.min = card->hbnr.min; + pl.level.init = card->hbnr.init; + pl.level.max = card->hbnr.max; + break; + + case NS_BUFTYPE_IOVEC: + pl.count = card->iovpool.count; + pl.level.min = card->iovnr.min; + pl.level.init = card->iovnr.init; + pl.level.max = card->iovnr.max; + break; + + default: + return -ENOIOCTLCMD; + + } + if (!copy_to_user((pool_levels __user *) arg, &pl, sizeof(pl))) + return (sizeof(pl)); + else + return -EFAULT; + + case NS_SETBUFLEV: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&pl, (pool_levels __user *) arg, sizeof(pl))) + return -EFAULT; + if (pl.level.min >= pl.level.init + || pl.level.init >= pl.level.max) + return -EINVAL; + if (pl.level.min == 0) + return -EINVAL; + switch (pl.buftype) { + case NS_BUFTYPE_SMALL: + if (pl.level.max > TOP_SB) + return -EINVAL; + card->sbnr.min = pl.level.min; + card->sbnr.init = pl.level.init; + card->sbnr.max = pl.level.max; + break; + + case NS_BUFTYPE_LARGE: + if (pl.level.max > TOP_LB) + return -EINVAL; + card->lbnr.min = pl.level.min; + card->lbnr.init = pl.level.init; + card->lbnr.max = pl.level.max; + break; + + case NS_BUFTYPE_HUGE: + if (pl.level.max > TOP_HB) + return -EINVAL; + card->hbnr.min = pl.level.min; + card->hbnr.init = pl.level.init; + card->hbnr.max = pl.level.max; + break; + + case NS_BUFTYPE_IOVEC: + if (pl.level.max > TOP_IOVB) + return -EINVAL; + card->iovnr.min = pl.level.min; + card->iovnr.init = pl.level.init; + card->iovnr.max = pl.level.max; + break; + + default: + return -EINVAL; + + } + return 0; + + case NS_ADJBUFLEV: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + btype = (long)arg; /* a long is the same size as a pointer or bigger */ + switch (btype) { + case NS_BUFTYPE_SMALL: + while (card->sbfqc < card->sbnr.init) { + struct sk_buff *sb; + + sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); + if (sb == NULL) + return -ENOMEM; + NS_PRV_BUFTYPE(sb) = BUF_SM; + skb_queue_tail(&card->sbpool.queue, sb); + skb_reserve(sb, NS_AAL0_HEADER); + push_rxbufs(card, sb); + } + break; + + case NS_BUFTYPE_LARGE: + while (card->lbfqc < card->lbnr.init) { + struct sk_buff *lb; + + lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); + if (lb == NULL) + return -ENOMEM; + NS_PRV_BUFTYPE(lb) = BUF_LG; + skb_queue_tail(&card->lbpool.queue, lb); + skb_reserve(lb, NS_SMBUFSIZE); + push_rxbufs(card, lb); + } + break; + + case NS_BUFTYPE_HUGE: + while (card->hbpool.count > card->hbnr.init) { + struct sk_buff *hb; + + spin_lock_irqsave(&card->int_lock, flags); + hb = skb_dequeue(&card->hbpool.queue); + card->hbpool.count--; + spin_unlock_irqrestore(&card->int_lock, flags); + if (hb == NULL) + printk + ("nicstar%d: huge buffer count inconsistent.\n", + card->index); + else + dev_kfree_skb_any(hb); + + } + while (card->hbpool.count < card->hbnr.init) { + struct sk_buff *hb; + + hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); + if (hb == NULL) + return -ENOMEM; + NS_PRV_BUFTYPE(hb) = BUF_NONE; + spin_lock_irqsave(&card->int_lock, flags); + skb_queue_tail(&card->hbpool.queue, hb); + card->hbpool.count++; + spin_unlock_irqrestore(&card->int_lock, flags); + } + break; + + case NS_BUFTYPE_IOVEC: + while (card->iovpool.count > card->iovnr.init) { + struct sk_buff *iovb; + + spin_lock_irqsave(&card->int_lock, flags); + iovb = skb_dequeue(&card->iovpool.queue); + card->iovpool.count--; + spin_unlock_irqrestore(&card->int_lock, flags); + if (iovb == NULL) + printk + ("nicstar%d: iovec buffer count inconsistent.\n", + card->index); + else + dev_kfree_skb_any(iovb); + + } + while (card->iovpool.count < card->iovnr.init) { + struct sk_buff *iovb; + + iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); + if (iovb == NULL) + return -ENOMEM; + NS_PRV_BUFTYPE(iovb) = BUF_NONE; + spin_lock_irqsave(&card->int_lock, flags); + skb_queue_tail(&card->iovpool.queue, iovb); + card->iovpool.count++; + spin_unlock_irqrestore(&card->int_lock, flags); + } + break; + + default: + return -EINVAL; + + } + return 0; + + default: + if (dev->phy && dev->phy->ioctl) { + return dev->phy->ioctl(dev, cmd, arg); + } else { + printk("nicstar%d: %s == NULL \n", card->index, + dev->phy ? "dev->phy->ioctl" : "dev->phy"); + return -ENOIOCTLCMD; + } + } } - -static void which_list(ns_dev *card, struct sk_buff *skb) +#ifdef EXTRA_DEBUG +static void which_list(ns_dev * card, struct sk_buff *skb) { - printk("skb buf_type: 0x%08x\n", NS_SKB_CB(skb)->buf_type); + printk("skb buf_type: 0x%08x\n", NS_PRV_BUFTYPE(skb)); } - +#endif /* EXTRA_DEBUG */ static void ns_poll(unsigned long arg) { - int i; - ns_dev *card; - unsigned long flags; - u32 stat_r, stat_w; - - PRINTK("nicstar: Entering ns_poll().\n"); - for (i = 0; i < num_cards; i++) - { - card = cards[i]; - if (spin_is_locked(&card->int_lock)) { - /* Probably it isn't worth spinning */ - continue; - } - spin_lock_irqsave(&card->int_lock, flags); - - stat_w = 0; - stat_r = readl(card->membase + STAT); - if (stat_r & NS_STAT_TSIF) - stat_w |= NS_STAT_TSIF; - if (stat_r & NS_STAT_EOPDU) - stat_w |= NS_STAT_EOPDU; - - process_tsq(card); - process_rsq(card); - - writel(stat_w, card->membase + STAT); - spin_unlock_irqrestore(&card->int_lock, flags); - } - mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD); - PRINTK("nicstar: Leaving ns_poll().\n"); + int i; + ns_dev *card; + unsigned long flags; + u32 stat_r, stat_w; + + PRINTK("nicstar: Entering ns_poll().\n"); + for (i = 0; i < num_cards; i++) { + card = cards[i]; + if (spin_is_locked(&card->int_lock)) { + /* Probably it isn't worth spinning */ + continue; + } + spin_lock_irqsave(&card->int_lock, flags); + + stat_w = 0; + stat_r = readl(card->membase + STAT); + if (stat_r & NS_STAT_TSIF) + stat_w |= NS_STAT_TSIF; + if (stat_r & NS_STAT_EOPDU) + stat_w |= NS_STAT_EOPDU; + + process_tsq(card); + process_rsq(card); + + writel(stat_w, card->membase + STAT); + spin_unlock_irqrestore(&card->int_lock, flags); + } + mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD); + PRINTK("nicstar: Leaving ns_poll().\n"); } - - -static int ns_parse_mac(char *mac, unsigned char *esi) -{ - int i, j; - short byte1, byte0; - - if (mac == NULL || esi == NULL) - return -1; - j = 0; - for (i = 0; i < 6; i++) - { - if ((byte1 = ns_h2i(mac[j++])) < 0) - return -1; - if ((byte0 = ns_h2i(mac[j++])) < 0) - return -1; - esi[i] = (unsigned char) (byte1 * 16 + byte0); - if (i < 5) - { - if (mac[j++] != ':') - return -1; - } - } - return 0; -} - - - -static short ns_h2i(char c) -{ - if (c >= '0' && c <= '9') - return (short) (c - '0'); - if (c >= 'A' && c <= 'F') - return (short) (c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return (short) (c - 'a' + 10); - return -1; -} - - - static void ns_phy_put(struct atm_dev *dev, unsigned char value, - unsigned long addr) + unsigned long addr) { - ns_dev *card; - unsigned long flags; - - card = dev->dev_data; - spin_lock_irqsave(&card->res_lock, flags); - while(CMD_BUSY(card)); - writel((unsigned long) value, card->membase + DR0); - writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), - card->membase + CMD); - spin_unlock_irqrestore(&card->res_lock, flags); + ns_dev *card; + unsigned long flags; + + card = dev->dev_data; + spin_lock_irqsave(&card->res_lock, flags); + while (CMD_BUSY(card)) ; + writel((u32) value, card->membase + DR0); + writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), + card->membase + CMD); + spin_unlock_irqrestore(&card->res_lock, flags); } - - static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr) { - ns_dev *card; - unsigned long flags; - unsigned long data; - - card = dev->dev_data; - spin_lock_irqsave(&card->res_lock, flags); - while(CMD_BUSY(card)); - writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF), - card->membase + CMD); - while(CMD_BUSY(card)); - data = readl(card->membase + DR0) & 0x000000FF; - spin_unlock_irqrestore(&card->res_lock, flags); - return (unsigned char) data; + ns_dev *card; + unsigned long flags; + u32 data; + + card = dev->dev_data; + spin_lock_irqsave(&card->res_lock, flags); + while (CMD_BUSY(card)) ; + writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF), + card->membase + CMD); + while (CMD_BUSY(card)) ; + data = readl(card->membase + DR0) & 0x000000FF; + spin_unlock_irqrestore(&card->res_lock, flags); + return (unsigned char)data; } - - module_init(nicstar_init); module_exit(nicstar_cleanup); diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h index 6010e3daa6a..9bc27ea5088 100644 --- a/drivers/atm/nicstar.h +++ b/drivers/atm/nicstar.h @@ -1,5 +1,4 @@ -/****************************************************************************** - * +/* * nicstar.h * * Header file for the nicstar device driver. @@ -8,29 +7,26 @@ * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999 * * (C) INESC 1998 - * - ******************************************************************************/ - + */ #ifndef _LINUX_NICSTAR_H_ #define _LINUX_NICSTAR_H_ - -/* Includes *******************************************************************/ +/* Includes */ #include <linux/types.h> #include <linux/pci.h> +#include <linux/idr.h> #include <linux/uio.h> #include <linux/skbuff.h> #include <linux/atmdev.h> #include <linux/atm_nicstar.h> - -/* Options ********************************************************************/ +/* Options */ #define NS_MAX_CARDS 4 /* Maximum number of NICStAR based cards controlled by the device driver. Must - be <= 5 */ + be <= 5 */ #undef RCQ_SUPPORT /* Do not define this for now */ @@ -43,7 +39,7 @@ #define NS_VPIBITS 2 /* 0, 1, 2, or 8 */ #define NS_MAX_RCTSIZE 4096 /* Number of entries. 4096 or 16384. - Define 4096 only if (all) your card(s) + Define 4096 only if (all) your card(s) have 32K x 32bit SRAM, in which case setting this to 16384 will just waste a lot of memory. @@ -51,33 +47,32 @@ 128K x 32bit SRAM will limit the maximum VCI. */ -/*#define NS_PCI_LATENCY 64*/ /* Must be a multiple of 32 */ + /*#define NS_PCI_LATENCY 64*//* Must be a multiple of 32 */ /* Number of buffers initially allocated */ -#define NUM_SB 32 /* Must be even */ -#define NUM_LB 24 /* Must be even */ -#define NUM_HB 8 /* Pre-allocated huge buffers */ -#define NUM_IOVB 48 /* Iovec buffers */ +#define NUM_SB 32 /* Must be even */ +#define NUM_LB 24 /* Must be even */ +#define NUM_HB 8 /* Pre-allocated huge buffers */ +#define NUM_IOVB 48 /* Iovec buffers */ /* Lower level for count of buffers */ -#define MIN_SB 8 /* Must be even */ -#define MIN_LB 8 /* Must be even */ +#define MIN_SB 8 /* Must be even */ +#define MIN_LB 8 /* Must be even */ #define MIN_HB 6 #define MIN_IOVB 8 /* Upper level for count of buffers */ -#define MAX_SB 64 /* Must be even, <= 508 */ -#define MAX_LB 48 /* Must be even, <= 508 */ +#define MAX_SB 64 /* Must be even, <= 508 */ +#define MAX_LB 48 /* Must be even, <= 508 */ #define MAX_HB 10 #define MAX_IOVB 80 /* These are the absolute maximum allowed for the ioctl() */ -#define TOP_SB 256 /* Must be even, <= 508 */ -#define TOP_LB 128 /* Must be even, <= 508 */ +#define TOP_SB 256 /* Must be even, <= 508 */ +#define TOP_LB 128 /* Must be even, <= 508 */ #define TOP_HB 64 #define TOP_IOVB 256 - #define MAX_TBD_PER_VC 1 /* Number of TBDs before a TSR */ #define MAX_TBD_PER_SCQ 10 /* Only meaningful for variable rate SCQs */ @@ -89,15 +84,12 @@ #define PCR_TOLERANCE (1.0001) - - -/* ESI stuff ******************************************************************/ +/* ESI stuff */ #define NICSTAR_EPROM_MAC_ADDR_OFFSET 0x6C #define NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT 0xF6 - -/* #defines *******************************************************************/ +/* #defines */ #define NS_IOREMAP_SIZE 4096 @@ -123,22 +115,19 @@ #define NS_SMSKBSIZE (NS_SMBUFSIZE + NS_AAL0_HEADER) #define NS_LGSKBSIZE (NS_SMBUFSIZE + NS_LGBUFSIZE) +/* NICStAR structures located in host memory */ -/* NICStAR structures located in host memory **********************************/ - - - -/* RSQ - Receive Status Queue +/* + * RSQ - Receive Status Queue * * Written by the NICStAR, read by the device driver. */ -typedef struct ns_rsqe -{ - u32 word_1; - u32 buffer_handle; - u32 final_aal5_crc32; - u32 word_4; +typedef struct ns_rsqe { + u32 word_1; + u32 buffer_handle; + u32 final_aal5_crc32; + u32 word_4; } ns_rsqe; #define ns_rsqe_vpi(ns_rsqep) \ @@ -175,30 +164,27 @@ typedef struct ns_rsqe #define ns_rsqe_cellcount(ns_rsqep) \ (le32_to_cpu((ns_rsqep)->word_4) & 0x000001FF) #define ns_rsqe_init(ns_rsqep) \ - ((ns_rsqep)->word_4 = cpu_to_le32(0x00000000)) + ((ns_rsqep)->word_4 = cpu_to_le32(0x00000000)) #define NS_RSQ_NUM_ENTRIES (NS_RSQSIZE / 16) #define NS_RSQ_ALIGNMENT NS_RSQSIZE - - -/* RCQ - Raw Cell Queue +/* + * RCQ - Raw Cell Queue * * Written by the NICStAR, read by the device driver. */ -typedef struct cell_payload -{ - u32 word[12]; +typedef struct cell_payload { + u32 word[12]; } cell_payload; -typedef struct ns_rcqe -{ - u32 word_1; - u32 word_2; - u32 word_3; - u32 word_4; - cell_payload payload; +typedef struct ns_rcqe { + u32 word_1; + u32 word_2; + u32 word_3; + u32 word_4; + cell_payload payload; } ns_rcqe; #define NS_RCQE_SIZE 64 /* bytes */ @@ -210,28 +196,25 @@ typedef struct ns_rcqe #define ns_rcqe_nextbufhandle(ns_rcqep) \ (le32_to_cpu((ns_rcqep)->word_2)) - - -/* SCQ - Segmentation Channel Queue +/* + * SCQ - Segmentation Channel Queue * * Written by the device driver, read by the NICStAR. */ -typedef struct ns_scqe -{ - u32 word_1; - u32 word_2; - u32 word_3; - u32 word_4; +typedef struct ns_scqe { + u32 word_1; + u32 word_2; + u32 word_3; + u32 word_4; } ns_scqe; /* NOTE: SCQ entries can be either a TBD (Transmit Buffer Descriptors) - or TSR (Transmit Status Requests) */ + or TSR (Transmit Status Requests) */ #define NS_SCQE_TYPE_TBD 0x00000000 #define NS_SCQE_TYPE_TSR 0x80000000 - #define NS_TBD_EOPDU 0x40000000 #define NS_TBD_AAL0 0x00000000 #define NS_TBD_AAL34 0x04000000 @@ -253,10 +236,9 @@ typedef struct ns_scqe #define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) \ (cpu_to_le32((gfc) << 28 | (vpi) << 20 | (vci) << 4 | (pt) << 1 | (clp))) - #define NS_TSR_INTENABLE 0x20000000 -#define NS_TSR_SCDISVBR 0xFFFF /* Use as scdi for VBR SCD */ +#define NS_TSR_SCDISVBR 0xFFFF /* Use as scdi for VBR SCD */ #define ns_tsr_mkword_1(flags) \ (cpu_to_le32(NS_SCQE_TYPE_TSR | (flags))) @@ -273,22 +255,20 @@ typedef struct ns_scqe #define NS_SCQE_SIZE 16 - - -/* TSQ - Transmit Status Queue +/* + * TSQ - Transmit Status Queue * * Written by the NICStAR, read by the device driver. */ -typedef struct ns_tsi -{ - u32 word_1; - u32 word_2; +typedef struct ns_tsi { + u32 word_1; + u32 word_2; } ns_tsi; /* NOTE: The first word can be a status word copied from the TSR which - originated the TSI, or a timer overflow indicator. In this last - case, the value of the first word is all zeroes. */ + originated the TSI, or a timer overflow indicator. In this last + case, the value of the first word is all zeroes. */ #define NS_TSI_EMPTY 0x80000000 #define NS_TSI_TIMESTAMP_MASK 0x00FFFFFF @@ -301,12 +281,10 @@ typedef struct ns_tsi #define ns_tsi_init(ns_tsip) \ ((ns_tsip)->word_2 = cpu_to_le32(NS_TSI_EMPTY)) - #define NS_TSQSIZE 8192 #define NS_TSQ_NUM_ENTRIES 1024 #define NS_TSQ_ALIGNMENT 8192 - #define NS_TSI_SCDISVBR NS_TSR_SCDISVBR #define ns_tsi_tmrof(ns_tsip) \ @@ -316,26 +294,22 @@ typedef struct ns_tsi #define ns_tsi_getscqpos(ns_tsip) \ (le32_to_cpu((ns_tsip)->word_1) & 0x00007FFF) +/* NICStAR structures located in local SRAM */ - -/* NICStAR structures located in local SRAM ***********************************/ - - - -/* RCT - Receive Connection Table +/* + * RCT - Receive Connection Table * * Written by both the NICStAR and the device driver. */ -typedef struct ns_rcte -{ - u32 word_1; - u32 buffer_handle; - u32 dma_address; - u32 aal5_crc32; +typedef struct ns_rcte { + u32 word_1; + u32 buffer_handle; + u32 dma_address; + u32 aal5_crc32; } ns_rcte; -#define NS_RCTE_BSFB 0x00200000 /* Rev. D only */ +#define NS_RCTE_BSFB 0x00200000 /* Rev. D only */ #define NS_RCTE_NZGFC 0x00100000 #define NS_RCTE_CONNECTOPEN 0x00080000 #define NS_RCTE_AALMASK 0x00070000 @@ -358,25 +332,21 @@ typedef struct ns_rcte #define NS_RCT_ENTRY_SIZE 4 /* Number of dwords */ /* NOTE: We could make macros to contruct the first word of the RCTE, - but that doesn't seem to make much sense... */ + but that doesn't seem to make much sense... */ - - -/* FBD - Free Buffer Descriptor +/* + * FBD - Free Buffer Descriptor * * Written by the device driver using via the command register. */ -typedef struct ns_fbd -{ - u32 buffer_handle; - u32 dma_address; +typedef struct ns_fbd { + u32 buffer_handle; + u32 dma_address; } ns_fbd; - - - -/* TST - Transmit Schedule Table +/* + * TST - Transmit Schedule Table * * Written by the device driver. */ @@ -385,40 +355,38 @@ typedef u32 ns_tste; #define NS_TST_OPCODE_MASK 0x60000000 -#define NS_TST_OPCODE_NULL 0x00000000 /* Insert null cell */ -#define NS_TST_OPCODE_FIXED 0x20000000 /* Cell from a fixed rate channel */ +#define NS_TST_OPCODE_NULL 0x00000000 /* Insert null cell */ +#define NS_TST_OPCODE_FIXED 0x20000000 /* Cell from a fixed rate channel */ #define NS_TST_OPCODE_VARIABLE 0x40000000 -#define NS_TST_OPCODE_END 0x60000000 /* Jump */ +#define NS_TST_OPCODE_END 0x60000000 /* Jump */ #define ns_tste_make(opcode, sramad) (opcode | sramad) /* NOTE: - When the opcode is FIXED, sramad specifies the SRAM address of the - SCD for that fixed rate channel. + SCD for that fixed rate channel. - When the opcode is END, sramad specifies the SRAM address of the - location of the next TST entry to read. + location of the next TST entry to read. */ - - -/* SCD - Segmentation Channel Descriptor +/* + * SCD - Segmentation Channel Descriptor * * Written by both the device driver and the NICStAR */ -typedef struct ns_scd -{ - u32 word_1; - u32 word_2; - u32 partial_aal5_crc; - u32 reserved; - ns_scqe cache_a; - ns_scqe cache_b; +typedef struct ns_scd { + u32 word_1; + u32 word_2; + u32 partial_aal5_crc; + u32 reserved; + ns_scqe cache_a; + ns_scqe cache_b; } ns_scd; -#define NS_SCD_BASE_MASK_VAR 0xFFFFE000 /* Variable rate */ -#define NS_SCD_BASE_MASK_FIX 0xFFFFFC00 /* Fixed rate */ +#define NS_SCD_BASE_MASK_VAR 0xFFFFE000 /* Variable rate */ +#define NS_SCD_BASE_MASK_FIX 0xFFFFFC00 /* Fixed rate */ #define NS_SCD_TAIL_MASK_VAR 0x00001FF0 #define NS_SCD_TAIL_MASK_FIX 0x000003F0 #define NS_SCD_HEAD_MASK_VAR 0x00001FF0 @@ -426,13 +394,9 @@ typedef struct ns_scd #define NS_SCD_XMITFOREVER 0x02000000 /* NOTE: There are other fields in word 2 of the SCD, but as they should - not be needed in the device driver they are not defined here. */ - - - - -/* NICStAR local SRAM memory map **********************************************/ + not be needed in the device driver they are not defined here. */ +/* NICStAR local SRAM memory map */ #define NS_RCT 0x00000 #define NS_RCT_32_END 0x03FFF @@ -455,100 +419,93 @@ typedef struct ns_scd #define NS_LGFBQ 0x1FC00 #define NS_LGFBQ_END 0x1FFFF - - -/* NISCtAR operation registers ************************************************/ - +/* NISCtAR operation registers */ /* See Section 3.4 of `IDT77211 NICStAR User Manual' from www.idt.com */ -enum ns_regs -{ - DR0 = 0x00, /* Data Register 0 R/W*/ - DR1 = 0x04, /* Data Register 1 W */ - DR2 = 0x08, /* Data Register 2 W */ - DR3 = 0x0C, /* Data Register 3 W */ - CMD = 0x10, /* Command W */ - CFG = 0x14, /* Configuration R/W */ - STAT = 0x18, /* Status R/W */ - RSQB = 0x1C, /* Receive Status Queue Base W */ - RSQT = 0x20, /* Receive Status Queue Tail R */ - RSQH = 0x24, /* Receive Status Queue Head W */ - CDC = 0x28, /* Cell Drop Counter R/clear */ - VPEC = 0x2C, /* VPI/VCI Lookup Error Count R/clear */ - ICC = 0x30, /* Invalid Cell Count R/clear */ - RAWCT = 0x34, /* Raw Cell Tail R */ - TMR = 0x38, /* Timer R */ - TSTB = 0x3C, /* Transmit Schedule Table Base R/W */ - TSQB = 0x40, /* Transmit Status Queue Base W */ - TSQT = 0x44, /* Transmit Status Queue Tail R */ - TSQH = 0x48, /* Transmit Status Queue Head W */ - GP = 0x4C, /* General Purpose R/W */ - VPM = 0x50 /* VPI/VCI Mask W */ +enum ns_regs { + DR0 = 0x00, /* Data Register 0 R/W */ + DR1 = 0x04, /* Data Register 1 W */ + DR2 = 0x08, /* Data Register 2 W */ + DR3 = 0x0C, /* Data Register 3 W */ + CMD = 0x10, /* Command W */ + CFG = 0x14, /* Configuration R/W */ + STAT = 0x18, /* Status R/W */ + RSQB = 0x1C, /* Receive Status Queue Base W */ + RSQT = 0x20, /* Receive Status Queue Tail R */ + RSQH = 0x24, /* Receive Status Queue Head W */ + CDC = 0x28, /* Cell Drop Counter R/clear */ + VPEC = 0x2C, /* VPI/VCI Lookup Error Count R/clear */ + ICC = 0x30, /* Invalid Cell Count R/clear */ + RAWCT = 0x34, /* Raw Cell Tail R */ + TMR = 0x38, /* Timer R */ + TSTB = 0x3C, /* Transmit Schedule Table Base R/W */ + TSQB = 0x40, /* Transmit Status Queue Base W */ + TSQT = 0x44, /* Transmit Status Queue Tail R */ + TSQH = 0x48, /* Transmit Status Queue Head W */ + GP = 0x4C, /* General Purpose R/W */ + VPM = 0x50 /* VPI/VCI Mask W */ }; - -/* NICStAR commands issued to the CMD register ********************************/ - +/* NICStAR commands issued to the CMD register */ /* Top 4 bits are command opcode, lower 28 are parameters. */ #define NS_CMD_NO_OPERATION 0x00000000 - /* params always 0 */ + /* params always 0 */ #define NS_CMD_OPENCLOSE_CONNECTION 0x20000000 - /* b19{1=open,0=close} b18-2{SRAM addr} */ + /* b19{1=open,0=close} b18-2{SRAM addr} */ #define NS_CMD_WRITE_SRAM 0x40000000 - /* b18-2{SRAM addr} b1-0{burst size} */ + /* b18-2{SRAM addr} b1-0{burst size} */ #define NS_CMD_READ_SRAM 0x50000000 - /* b18-2{SRAM addr} */ + /* b18-2{SRAM addr} */ #define NS_CMD_WRITE_FREEBUFQ 0x60000000 - /* b0{large buf indicator} */ + /* b0{large buf indicator} */ #define NS_CMD_READ_UTILITY 0x80000000 - /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */ + /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */ #define NS_CMD_WRITE_UTILITY 0x90000000 - /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */ + /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */ #define NS_CMD_OPEN_CONNECTION (NS_CMD_OPENCLOSE_CONNECTION | 0x00080000) #define NS_CMD_CLOSE_CONNECTION NS_CMD_OPENCLOSE_CONNECTION - -/* NICStAR configuration bits *************************************************/ - -#define NS_CFG_SWRST 0x80000000 /* Software Reset */ -#define NS_CFG_RXPATH 0x20000000 /* Receive Path Enable */ -#define NS_CFG_SMBUFSIZE_MASK 0x18000000 /* Small Receive Buffer Size */ -#define NS_CFG_LGBUFSIZE_MASK 0x06000000 /* Large Receive Buffer Size */ -#define NS_CFG_EFBIE 0x01000000 /* Empty Free Buffer Queue - Interrupt Enable */ -#define NS_CFG_RSQSIZE_MASK 0x00C00000 /* Receive Status Queue Size */ -#define NS_CFG_ICACCEPT 0x00200000 /* Invalid Cell Accept */ -#define NS_CFG_IGNOREGFC 0x00100000 /* Ignore General Flow Control */ -#define NS_CFG_VPIBITS_MASK 0x000C0000 /* VPI/VCI Bits Size Select */ -#define NS_CFG_RCTSIZE_MASK 0x00030000 /* Receive Connection Table Size */ -#define NS_CFG_VCERRACCEPT 0x00008000 /* VPI/VCI Error Cell Accept */ -#define NS_CFG_RXINT_MASK 0x00007000 /* End of Receive PDU Interrupt - Handling */ -#define NS_CFG_RAWIE 0x00000800 /* Raw Cell Qu' Interrupt Enable */ -#define NS_CFG_RSQAFIE 0x00000400 /* Receive Queue Almost Full - Interrupt Enable */ -#define NS_CFG_RXRM 0x00000200 /* Receive RM Cells */ -#define NS_CFG_TMRROIE 0x00000080 /* Timer Roll Over Interrupt - Enable */ -#define NS_CFG_TXEN 0x00000020 /* Transmit Operation Enable */ -#define NS_CFG_TXIE 0x00000010 /* Transmit Status Interrupt - Enable */ -#define NS_CFG_TXURIE 0x00000008 /* Transmit Under-run Interrupt - Enable */ -#define NS_CFG_UMODE 0x00000004 /* Utopia Mode (cell/byte) Select */ -#define NS_CFG_TSQFIE 0x00000002 /* Transmit Status Queue Full - Interrupt Enable */ -#define NS_CFG_PHYIE 0x00000001 /* PHY Interrupt Enable */ +/* NICStAR configuration bits */ + +#define NS_CFG_SWRST 0x80000000 /* Software Reset */ +#define NS_CFG_RXPATH 0x20000000 /* Receive Path Enable */ +#define NS_CFG_SMBUFSIZE_MASK 0x18000000 /* Small Receive Buffer Size */ +#define NS_CFG_LGBUFSIZE_MASK 0x06000000 /* Large Receive Buffer Size */ +#define NS_CFG_EFBIE 0x01000000 /* Empty Free Buffer Queue + Interrupt Enable */ +#define NS_CFG_RSQSIZE_MASK 0x00C00000 /* Receive Status Queue Size */ +#define NS_CFG_ICACCEPT 0x00200000 /* Invalid Cell Accept */ +#define NS_CFG_IGNOREGFC 0x00100000 /* Ignore General Flow Control */ +#define NS_CFG_VPIBITS_MASK 0x000C0000 /* VPI/VCI Bits Size Select */ +#define NS_CFG_RCTSIZE_MASK 0x00030000 /* Receive Connection Table Size */ +#define NS_CFG_VCERRACCEPT 0x00008000 /* VPI/VCI Error Cell Accept */ +#define NS_CFG_RXINT_MASK 0x00007000 /* End of Receive PDU Interrupt + Handling */ +#define NS_CFG_RAWIE 0x00000800 /* Raw Cell Qu' Interrupt Enable */ +#define NS_CFG_RSQAFIE 0x00000400 /* Receive Queue Almost Full + Interrupt Enable */ +#define NS_CFG_RXRM 0x00000200 /* Receive RM Cells */ +#define NS_CFG_TMRROIE 0x00000080 /* Timer Roll Over Interrupt + Enable */ +#define NS_CFG_TXEN 0x00000020 /* Transmit Operation Enable */ +#define NS_CFG_TXIE 0x00000010 /* Transmit Status Interrupt + Enable */ +#define NS_CFG_TXURIE 0x00000008 /* Transmit Under-run Interrupt + Enable */ +#define NS_CFG_UMODE 0x00000004 /* Utopia Mode (cell/byte) Select */ +#define NS_CFG_TSQFIE 0x00000002 /* Transmit Status Queue Full + Interrupt Enable */ +#define NS_CFG_PHYIE 0x00000001 /* PHY Interrupt Enable */ #define NS_CFG_SMBUFSIZE_48 0x00000000 #define NS_CFG_SMBUFSIZE_96 0x08000000 @@ -579,33 +536,29 @@ enum ns_regs #define NS_CFG_RXINT_624US 0x00003000 #define NS_CFG_RXINT_899US 0x00004000 - -/* NICStAR STATus bits ********************************************************/ - -#define NS_STAT_SFBQC_MASK 0xFF000000 /* hi 8 bits Small Buffer Queue Count */ -#define NS_STAT_LFBQC_MASK 0x00FF0000 /* hi 8 bits Large Buffer Queue Count */ -#define NS_STAT_TSIF 0x00008000 /* Transmit Status Queue Indicator */ -#define NS_STAT_TXICP 0x00004000 /* Transmit Incomplete PDU */ -#define NS_STAT_TSQF 0x00001000 /* Transmit Status Queue Full */ -#define NS_STAT_TMROF 0x00000800 /* Timer Overflow */ -#define NS_STAT_PHYI 0x00000400 /* PHY Device Interrupt */ -#define NS_STAT_CMDBZ 0x00000200 /* Command Busy */ -#define NS_STAT_SFBQF 0x00000100 /* Small Buffer Queue Full */ -#define NS_STAT_LFBQF 0x00000080 /* Large Buffer Queue Full */ -#define NS_STAT_RSQF 0x00000040 /* Receive Status Queue Full */ -#define NS_STAT_EOPDU 0x00000020 /* End of PDU */ -#define NS_STAT_RAWCF 0x00000010 /* Raw Cell Flag */ -#define NS_STAT_SFBQE 0x00000008 /* Small Buffer Queue Empty */ -#define NS_STAT_LFBQE 0x00000004 /* Large Buffer Queue Empty */ -#define NS_STAT_RSQAF 0x00000002 /* Receive Status Queue Almost Full */ +/* NICStAR STATus bits */ + +#define NS_STAT_SFBQC_MASK 0xFF000000 /* hi 8 bits Small Buffer Queue Count */ +#define NS_STAT_LFBQC_MASK 0x00FF0000 /* hi 8 bits Large Buffer Queue Count */ +#define NS_STAT_TSIF 0x00008000 /* Transmit Status Queue Indicator */ +#define NS_STAT_TXICP 0x00004000 /* Transmit Incomplete PDU */ +#define NS_STAT_TSQF 0x00001000 /* Transmit Status Queue Full */ +#define NS_STAT_TMROF 0x00000800 /* Timer Overflow */ +#define NS_STAT_PHYI 0x00000400 /* PHY Device Interrupt */ +#define NS_STAT_CMDBZ 0x00000200 /* Command Busy */ +#define NS_STAT_SFBQF 0x00000100 /* Small Buffer Queue Full */ +#define NS_STAT_LFBQF 0x00000080 /* Large Buffer Queue Full */ +#define NS_STAT_RSQF 0x00000040 /* Receive Status Queue Full */ +#define NS_STAT_EOPDU 0x00000020 /* End of PDU */ +#define NS_STAT_RAWCF 0x00000010 /* Raw Cell Flag */ +#define NS_STAT_SFBQE 0x00000008 /* Small Buffer Queue Empty */ +#define NS_STAT_LFBQE 0x00000004 /* Large Buffer Queue Empty */ +#define NS_STAT_RSQAF 0x00000002 /* Receive Status Queue Almost Full */ #define ns_stat_sfbqc_get(stat) (((stat) & NS_STAT_SFBQC_MASK) >> 23) #define ns_stat_lfbqc_get(stat) (((stat) & NS_STAT_LFBQC_MASK) >> 15) - - -/* #defines which depend on other #defines ************************************/ - +/* #defines which depend on other #defines */ #define NS_TST0 NS_TST_FRSCD #define NS_TST1 (NS_TST_FRSCD + NS_TST_NUM_ENTRIES + 1) @@ -672,8 +625,7 @@ enum ns_regs #define NS_CFG_TSQFIE_OPT 0x00000000 #endif /* ENABLE_TSQFIE */ - -/* PCI stuff ******************************************************************/ +/* PCI stuff */ #ifndef PCI_VENDOR_ID_IDT #define PCI_VENDOR_ID_IDT 0x111D @@ -683,138 +635,124 @@ enum ns_regs #define PCI_DEVICE_ID_IDT_IDT77201 0x0001 #endif /* PCI_DEVICE_ID_IDT_IDT77201 */ +/* Device driver structures */ - -/* Device driver structures ***************************************************/ - - -struct ns_skb_cb { - u32 buf_type; /* BUF_SM/BUF_LG/BUF_NONE */ +struct ns_skb_prv { + u32 buf_type; /* BUF_SM/BUF_LG/BUF_NONE */ + u32 dma; + int iovcnt; }; -#define NS_SKB_CB(skb) ((struct ns_skb_cb *)((skb)->cb)) - -typedef struct tsq_info -{ - void *org; - ns_tsi *base; - ns_tsi *next; - ns_tsi *last; +#define NS_PRV_BUFTYPE(skb) \ + (((struct ns_skb_prv *)(ATM_SKB(skb)+1))->buf_type) +#define NS_PRV_DMA(skb) \ + (((struct ns_skb_prv *)(ATM_SKB(skb)+1))->dma) +#define NS_PRV_IOVCNT(skb) \ + (((struct ns_skb_prv *)(ATM_SKB(skb)+1))->iovcnt) + +typedef struct tsq_info { + void *org; + dma_addr_t dma; + ns_tsi *base; + ns_tsi *next; + ns_tsi *last; } tsq_info; - -typedef struct scq_info -{ - void *org; - ns_scqe *base; - ns_scqe *last; - ns_scqe *next; - volatile ns_scqe *tail; /* Not related to the nicstar register */ - unsigned num_entries; - struct sk_buff **skb; /* Pointer to an array of pointers - to the sk_buffs used for tx */ - u32 scd; /* SRAM address of the corresponding - SCD */ - int tbd_count; /* Only meaningful on variable rate */ - wait_queue_head_t scqfull_waitq; - volatile char full; /* SCQ full indicator */ - spinlock_t lock; /* SCQ spinlock */ +typedef struct scq_info { + void *org; + dma_addr_t dma; + ns_scqe *base; + ns_scqe *last; + ns_scqe *next; + volatile ns_scqe *tail; /* Not related to the nicstar register */ + unsigned num_entries; + struct sk_buff **skb; /* Pointer to an array of pointers + to the sk_buffs used for tx */ + u32 scd; /* SRAM address of the corresponding + SCD */ + int tbd_count; /* Only meaningful on variable rate */ + wait_queue_head_t scqfull_waitq; + volatile char full; /* SCQ full indicator */ + spinlock_t lock; /* SCQ spinlock */ } scq_info; - - -typedef struct rsq_info -{ - void *org; - ns_rsqe *base; - ns_rsqe *next; - ns_rsqe *last; +typedef struct rsq_info { + void *org; + dma_addr_t dma; + ns_rsqe *base; + ns_rsqe *next; + ns_rsqe *last; } rsq_info; - -typedef struct skb_pool -{ - volatile int count; /* number of buffers in the queue */ - struct sk_buff_head queue; +typedef struct skb_pool { + volatile int count; /* number of buffers in the queue */ + struct sk_buff_head queue; } skb_pool; /* NOTE: for small and large buffer pools, the count is not used, as the actual value used for buffer management is the one read from the card. */ - -typedef struct vc_map -{ - volatile unsigned int tx:1; /* TX vc? */ - volatile unsigned int rx:1; /* RX vc? */ - struct atm_vcc *tx_vcc, *rx_vcc; - struct sk_buff *rx_iov; /* RX iovector skb */ - scq_info *scq; /* To keep track of the SCQ */ - u32 cbr_scd; /* SRAM address of the corresponding - SCD. 0x00000000 for UBR/VBR/ABR */ - int tbd_count; +typedef struct vc_map { + volatile unsigned int tx:1; /* TX vc? */ + volatile unsigned int rx:1; /* RX vc? */ + struct atm_vcc *tx_vcc, *rx_vcc; + struct sk_buff *rx_iov; /* RX iovector skb */ + scq_info *scq; /* To keep track of the SCQ */ + u32 cbr_scd; /* SRAM address of the corresponding + SCD. 0x00000000 for UBR/VBR/ABR */ + int tbd_count; } vc_map; - -struct ns_skb_data -{ - struct atm_vcc *vcc; - int iovcnt; -}; - -#define NS_SKB(skb) (((struct ns_skb_data *) (skb)->cb)) - - -typedef struct ns_dev -{ - int index; /* Card ID to the device driver */ - int sram_size; /* In k x 32bit words. 32 or 128 */ - void __iomem *membase; /* Card's memory base address */ - unsigned long max_pcr; - int rct_size; /* Number of entries */ - int vpibits; - int vcibits; - struct pci_dev *pcidev; - struct atm_dev *atmdev; - tsq_info tsq; - rsq_info rsq; - scq_info *scq0, *scq1, *scq2; /* VBR SCQs */ - skb_pool sbpool; /* Small buffers */ - skb_pool lbpool; /* Large buffers */ - skb_pool hbpool; /* Pre-allocated huge buffers */ - skb_pool iovpool; /* iovector buffers */ - volatile int efbie; /* Empty free buf. queue int. enabled */ - volatile u32 tst_addr; /* SRAM address of the TST in use */ - volatile int tst_free_entries; - vc_map vcmap[NS_MAX_RCTSIZE]; - vc_map *tste2vc[NS_TST_NUM_ENTRIES]; - vc_map *scd2vc[NS_FRSCD_NUM]; - buf_nr sbnr; - buf_nr lbnr; - buf_nr hbnr; - buf_nr iovnr; - int sbfqc; - int lbfqc; - u32 sm_handle; - u32 sm_addr; - u32 lg_handle; - u32 lg_addr; - struct sk_buff *rcbuf; /* Current raw cell buffer */ - u32 rawch; /* Raw cell queue head */ - unsigned intcnt; /* Interrupt counter */ - spinlock_t int_lock; /* Interrupt lock */ - spinlock_t res_lock; /* Card resource lock */ +typedef struct ns_dev { + int index; /* Card ID to the device driver */ + int sram_size; /* In k x 32bit words. 32 or 128 */ + void __iomem *membase; /* Card's memory base address */ + unsigned long max_pcr; + int rct_size; /* Number of entries */ + int vpibits; + int vcibits; + struct pci_dev *pcidev; + struct idr idr; + struct atm_dev *atmdev; + tsq_info tsq; + rsq_info rsq; + scq_info *scq0, *scq1, *scq2; /* VBR SCQs */ + skb_pool sbpool; /* Small buffers */ + skb_pool lbpool; /* Large buffers */ + skb_pool hbpool; /* Pre-allocated huge buffers */ + skb_pool iovpool; /* iovector buffers */ + volatile int efbie; /* Empty free buf. queue int. enabled */ + volatile u32 tst_addr; /* SRAM address of the TST in use */ + volatile int tst_free_entries; + vc_map vcmap[NS_MAX_RCTSIZE]; + vc_map *tste2vc[NS_TST_NUM_ENTRIES]; + vc_map *scd2vc[NS_FRSCD_NUM]; + buf_nr sbnr; + buf_nr lbnr; + buf_nr hbnr; + buf_nr iovnr; + int sbfqc; + int lbfqc; + struct sk_buff *sm_handle; + u32 sm_addr; + struct sk_buff *lg_handle; + u32 lg_addr; + struct sk_buff *rcbuf; /* Current raw cell buffer */ + struct ns_rcqe *rawcell; + u32 rawch; /* Raw cell queue head */ + unsigned intcnt; /* Interrupt counter */ + spinlock_t int_lock; /* Interrupt lock */ + spinlock_t res_lock; /* Card resource lock */ } ns_dev; - /* NOTE: Each tste2vc entry relates a given TST entry to the corresponding - CBR vc. If the entry is not allocated, it must be NULL. - - There are two TSTs so the driver can modify them on the fly - without stopping the transmission. - - scd2vc allows us to find out unused fixed rate SCDs, because - they must have a NULL pointer here. */ + CBR vc. If the entry is not allocated, it must be NULL. + + There are two TSTs so the driver can modify them on the fly + without stopping the transmission. + scd2vc allows us to find out unused fixed rate SCDs, because + they must have a NULL pointer here. */ #endif /* _LINUX_NICSTAR_H_ */ diff --git a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c index 842e26c4555..f594526f8c6 100644 --- a/drivers/atm/nicstarmac.c +++ b/drivers/atm/nicstarmac.c @@ -13,15 +13,15 @@ typedef void __iomem *virt_addr_t; #define CYCLE_DELAY 5 -/* This was the original definition +/* + This was the original definition #define osp_MicroDelay(microsec) \ do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) */ #define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \ udelay((useconds));} - - -/* The following tables represent the timing diagrams found in +/* + * The following tables represent the timing diagrams found in * the Data Sheet for the Xicor X25020 EEProm. The #defines below * represent the bits in the NICStAR's General Purpose register * that must be toggled for the corresponding actions on the EEProm @@ -31,86 +31,80 @@ typedef void __iomem *virt_addr_t; /* Write Data To EEProm from SI line on rising edge of CLK */ /* Read Data From EEProm on falling edge of CLK */ -#define CS_HIGH 0x0002 /* Chip select high */ -#define CS_LOW 0x0000 /* Chip select low (active low)*/ -#define CLK_HIGH 0x0004 /* Clock high */ -#define CLK_LOW 0x0000 /* Clock low */ -#define SI_HIGH 0x0001 /* Serial input data high */ -#define SI_LOW 0x0000 /* Serial input data low */ +#define CS_HIGH 0x0002 /* Chip select high */ +#define CS_LOW 0x0000 /* Chip select low (active low) */ +#define CLK_HIGH 0x0004 /* Clock high */ +#define CLK_LOW 0x0000 /* Clock low */ +#define SI_HIGH 0x0001 /* Serial input data high */ +#define SI_LOW 0x0000 /* Serial input data low */ /* Read Status Register = 0000 0101b */ #if 0 -static u_int32_t rdsrtab[] = -{ - 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 | SI_HIGH, - CLK_HIGH | SI_HIGH, /* 1 */ - CLK_LOW | SI_LOW, - CLK_HIGH, /* 0 */ - CLK_LOW | SI_HIGH, - CLK_HIGH | SI_HIGH /* 1 */ +static u_int32_t rdsrtab[] = { + 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 | SI_HIGH, + CLK_HIGH | SI_HIGH, /* 1 */ + CLK_LOW | SI_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW | SI_HIGH, + CLK_HIGH | SI_HIGH /* 1 */ }; -#endif /* 0 */ - +#endif /* 0 */ /* Read from EEPROM = 0000 0011b */ -static u_int32_t 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 */ +static u_int32_t 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 u_int32_t 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 u_int32_t 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 }; - #define NICSTAR_REG_WRITE(bs, reg, val) \ while ( readl(bs + STAT) & 0x0200 ) ; \ writel((val),(base)+(reg)) @@ -124,153 +118,131 @@ static u_int32_t clocktab[] = * register. */ #if 0 -u_int32_t -nicstar_read_eprom_status( virt_addr_t base ) +u_int32_t nicstar_read_eprom_status(virt_addr_t base) { - u_int32_t val; - u_int32_t rbyte; - int32_t i, j; - - /* Send read instruction */ - val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0; - - for (i=0; i<ARRAY_SIZE(rdsrtab); i++) - { - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | rdsrtab[i]) ); - osp_MicroDelay( CYCLE_DELAY ); - } - - /* Done sending instruction - now pull data off of bit 16, MSB first */ - /* Data clocked out of eeprom on falling edge of clock */ - - rbyte = 0; - for (i=7, j=0; i>=0; i--) - { - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | clocktab[j++]) ); - rbyte |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE) - & 0x00010000) >> 16) << i); - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | clocktab[j++]) ); - osp_MicroDelay( CYCLE_DELAY ); - } - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 ); - osp_MicroDelay( CYCLE_DELAY ); - return rbyte; + u_int32_t val; + u_int32_t rbyte; + int32_t i, j; + + /* Send read instruction */ + val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0; + + for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) { + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | rdsrtab[i])); + osp_MicroDelay(CYCLE_DELAY); + } + + /* Done sending instruction - now pull data off of bit 16, MSB first */ + /* Data clocked out of eeprom on falling edge of clock */ + + rbyte = 0; + for (i = 7, j = 0; i >= 0; i--) { + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | clocktab[j++])); + rbyte |= (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) + & 0x00010000) >> 16) << i); + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | clocktab[j++])); + osp_MicroDelay(CYCLE_DELAY); + } + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2); + osp_MicroDelay(CYCLE_DELAY); + return rbyte; } -#endif /* 0 */ - +#endif /* 0 */ /* * This routine will clock the Read_data function into the X2520 * eeprom, followed by the address to read from, through the NicSTaR's General * Purpose register. */ - -static u_int8_t -read_eprom_byte(virt_addr_t base, u_int8_t offset) + +static u_int8_t read_eprom_byte(virt_addr_t base, u_int8_t offset) { - u_int32_t val = 0; - int i,j=0; - u_int8_t tempread = 0; - - val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0; - - /* Send READ instruction */ - for (i=0; i<ARRAY_SIZE(readtab); i++) - { - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | readtab[i]) ); - osp_MicroDelay( CYCLE_DELAY ); - } - - /* Next, we need to send the byte address to read from */ - for (i=7; i>=0; i--) - { - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | clocktab[j++] | ((offset >> i) & 1) ) ); - osp_MicroDelay(CYCLE_DELAY); - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | clocktab[j++] | ((offset >> i) & 1) ) ); - osp_MicroDelay( CYCLE_DELAY ); - } - - j = 0; - - /* Now, we can read data from the eeprom by clocking it in */ - for (i=7; i>=0; i--) - { - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | clocktab[j++]) ); - osp_MicroDelay( CYCLE_DELAY ); - tempread |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) - & 0x00010000) >> 16) << i); - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, - (val | clocktab[j++]) ); - osp_MicroDelay( CYCLE_DELAY ); - } - - NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 ); - osp_MicroDelay( CYCLE_DELAY ); - return tempread; + u_int32_t val = 0; + int i, j = 0; + u_int8_t tempread = 0; + + val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0; + + /* Send READ instruction */ + for (i = 0; i < ARRAY_SIZE(readtab); i++) { + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | readtab[i])); + osp_MicroDelay(CYCLE_DELAY); + } + + /* Next, we need to send the byte address to read from */ + for (i = 7; i >= 0; i--) { + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | clocktab[j++] | ((offset >> i) & 1))); + osp_MicroDelay(CYCLE_DELAY); + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | clocktab[j++] | ((offset >> i) & 1))); + osp_MicroDelay(CYCLE_DELAY); + } + + j = 0; + + /* Now, we can read data from the eeprom by clocking it in */ + for (i = 7; i >= 0; i--) { + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | clocktab[j++])); + osp_MicroDelay(CYCLE_DELAY); + tempread |= + (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) + & 0x00010000) >> 16) << i); + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | clocktab[j++])); + osp_MicroDelay(CYCLE_DELAY); + } + + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2); + osp_MicroDelay(CYCLE_DELAY); + return tempread; } - -static void -nicstar_init_eprom( virt_addr_t base ) +static void nicstar_init_eprom(virt_addr_t base) { - u_int32_t val; + u_int32_t val; - /* - * turn chip select off - */ - val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0; + /* + * turn chip select off + */ + val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0; - NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, - (val | CS_HIGH | CLK_HIGH)); - osp_MicroDelay( CYCLE_DELAY ); + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | CS_HIGH | CLK_HIGH)); + osp_MicroDelay(CYCLE_DELAY); - NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, - (val | CS_HIGH | CLK_LOW)); - osp_MicroDelay( CYCLE_DELAY ); + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | CS_HIGH | CLK_LOW)); + osp_MicroDelay(CYCLE_DELAY); - NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, - (val | CS_HIGH | CLK_HIGH)); - osp_MicroDelay( CYCLE_DELAY ); + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | CS_HIGH | CLK_HIGH)); + osp_MicroDelay(CYCLE_DELAY); - NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, - (val | CS_HIGH | CLK_LOW)); - osp_MicroDelay( CYCLE_DELAY ); + NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, + (val | CS_HIGH | CLK_LOW)); + osp_MicroDelay(CYCLE_DELAY); } - /* * This routine will be the interface to the ReadPromByte function * above. - */ + */ static void -nicstar_read_eprom( - virt_addr_t base, - u_int8_t prom_offset, - u_int8_t *buffer, - u_int32_t nbytes ) +nicstar_read_eprom(virt_addr_t base, + u_int8_t prom_offset, u_int8_t * buffer, u_int32_t nbytes) { - u_int i; - - for (i=0; i<nbytes; i++) - { - buffer[i] = read_eprom_byte( base, prom_offset ); - ++prom_offset; - osp_MicroDelay( CYCLE_DELAY ); - } -} - + u_int i; -/* -void osp_MicroDelay(int x) { - + for (i = 0; i < nbytes; i++) { + buffer[i] = read_eprom_byte(base, prom_offset); + ++prom_offset; + osp_MicroDelay(CYCLE_DELAY); + } } -*/ - diff --git a/drivers/atm/solos-attrlist.c b/drivers/atm/solos-attrlist.c index 1a9332e4efe..9a676ee3082 100644 --- a/drivers/atm/solos-attrlist.c +++ b/drivers/atm/solos-attrlist.c @@ -1,6 +1,7 @@ SOLOS_ATTR_RO(DriverVersion) SOLOS_ATTR_RO(APIVersion) SOLOS_ATTR_RO(FirmwareVersion) +SOLOS_ATTR_RO(Version) // SOLOS_ATTR_RO(DspVersion) // SOLOS_ATTR_RO(CommonHandshake) SOLOS_ATTR_RO(Connected) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 51eed679a05..943cf0d6aba 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -40,8 +40,10 @@ #include <linux/firmware.h> #include <linux/ctype.h> #include <linux/swab.h> +#include <linux/slab.h> -#define VERSION "0.07" +#define VERSION "1.04" +#define DRIVER_VERSION 0x01 #define PTAG "solos-pci" #define CONFIG_RAM_SIZE 128 @@ -55,16 +57,21 @@ #define FLASH_BUSY 0x60 #define FPGA_MODE 0x5C #define FLASH_MODE 0x58 +#define GPIO_STATUS 0x54 +#define DRIVER_VER 0x50 #define TX_DMA_ADDR(port) (0x40 + (4 * (port))) #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) #define DATA_RAM_SIZE 32768 #define BUF_SIZE 2048 #define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/ -#define FPGA_PAGE 528 /* FPGA flash page size*/ -#define SOLOS_PAGE 512 /* Solos flash page size*/ -#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ -#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ +/* Old boards use ATMEL AD45DB161D flash */ +#define ATMEL_FPGA_PAGE 528 /* FPGA flash page size*/ +#define ATMEL_SOLOS_PAGE 512 /* Solos flash page size*/ +#define ATMEL_FPGA_BLOCK (ATMEL_FPGA_PAGE * 8) /* FPGA block size*/ +#define ATMEL_SOLOS_BLOCK (ATMEL_SOLOS_PAGE * 8) /* Solos block size*/ +/* Current boards use M25P/M25PE SPI flash */ +#define SPI_FLASH_BLOCK (256 * 64) #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2) #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size)) @@ -121,11 +128,14 @@ struct solos_card { struct sk_buff_head cli_queue[4]; struct sk_buff *tx_skb[4]; struct sk_buff *rx_skb[4]; + unsigned char *dma_bounce; wait_queue_head_t param_wq; wait_queue_head_t fw_wq; int using_dma; + int dma_alignment; int fpga_version; int buffer_size; + int atmel_flash; }; @@ -163,9 +173,7 @@ static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, static uint32_t fpga_tx(struct solos_card *); static irqreturn_t solos_irq(int irq, void *dev_id); static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci); -static int list_vccs(int vci); -static void release_vccs(struct atm_dev *dev); -static int atm_init(struct solos_card *); +static int atm_init(struct solos_card *, struct device *); static void atm_remove(struct solos_card *); static int send_command(struct solos_card *card, int dev, const char *buf, size_t size); static void solos_bh(unsigned long); @@ -382,8 +390,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb /* Anything but 'Showtime' is down */ if (strcmp(state_str, "Showtime")) { - card->atmdev[port]->signal = ATM_PHY_SIG_LOST; - release_vccs(card->atmdev[port]); + atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST); dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str); return 0; } @@ -400,7 +407,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn); card->atmdev[port]->link_rate = rate_down / 424; - card->atmdev[port]->signal = ATM_PHY_SIG_FOUND; + atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_FOUND); return 0; } @@ -443,6 +450,7 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev); struct solos_card *card = atmdev->dev_data; struct sk_buff *skb; + unsigned int len; spin_lock(&card->cli_queue_lock); skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]); @@ -450,11 +458,11 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, if(skb == NULL) return sprintf(buf, "No data.\n"); - memcpy(buf, skb->data, skb->len); - dev_dbg(&card->dev->dev, "len: %d\n", skb->len); + len = skb->len; + memcpy(buf, skb->data, len); kfree_skb(skb); - return skb->len; + return len; } static int send_command(struct solos_card *card, int dev, const char *buf, size_t size) @@ -498,6 +506,78 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr, return err?:count; } +struct geos_gpio_attr { + struct device_attribute attr; + int offset; +}; + +#define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset) \ + struct geos_gpio_attr gpio_attr_##_name = { \ + .attr = __ATTR(_name, _mode, _show, _store), \ + .offset = _offset } + +static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); + struct solos_card *card = pci_get_drvdata(pdev); + uint32_t data32; + + if (count != 1 && (count != 2 || buf[1] != '\n')) + return -EINVAL; + + spin_lock_irq(&card->param_queue_lock); + data32 = ioread32(card->config_regs + GPIO_STATUS); + if (buf[0] == '1') { + data32 |= 1 << gattr->offset; + iowrite32(data32, card->config_regs + GPIO_STATUS); + } else if (buf[0] == '0') { + data32 &= ~(1 << gattr->offset); + iowrite32(data32, card->config_regs + GPIO_STATUS); + } else { + count = -EINVAL; + } + spin_unlock_irq(&card->param_queue_lock); + return count; +} + +static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); + struct solos_card *card = pci_get_drvdata(pdev); + uint32_t data32; + + data32 = ioread32(card->config_regs + GPIO_STATUS); + data32 = (data32 >> gattr->offset) & 1; + + return sprintf(buf, "%d\n", data32); +} + +static ssize_t hardware_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); + struct solos_card *card = pci_get_drvdata(pdev); + uint32_t data32; + + data32 = ioread32(card->config_regs + GPIO_STATUS); + switch (gattr->offset) { + case 0: + /* HardwareVersion */ + data32 = data32 & 0x1F; + break; + case 1: + /* HardwareVariant */ + data32 = (data32 >> 5) & 0x0F; + break; + } + return sprintf(buf, "%d\n", data32); +} + static DEVICE_ATTR(console, 0644, console_show, console_store); @@ -506,6 +586,14 @@ static DEVICE_ATTR(console, 0644, console_show, console_store); #include "solos-attrlist.c" +static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9); +static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10); +static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11); +static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12); +static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13); +static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14); +static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0); +static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1); #undef SOLOS_ATTR_RO #undef SOLOS_ATTR_RW @@ -522,11 +610,27 @@ static struct attribute_group solos_attr_group = { .name = "parameters", }; +static struct attribute *gpio_attrs[] = { + &gpio_attr_GPIO1.attr.attr, + &gpio_attr_GPIO2.attr.attr, + &gpio_attr_GPIO3.attr.attr, + &gpio_attr_GPIO4.attr.attr, + &gpio_attr_GPIO5.attr.attr, + &gpio_attr_PushButton.attr.attr, + &gpio_attr_HardwareVersion.attr.attr, + &gpio_attr_HardwareVariant.attr.attr, + NULL +}; + +static struct attribute_group gpio_attr_group = { + .attrs = gpio_attrs, + .name = "gpio", +}; + static int flash_upgrade(struct solos_card *card, int chip) { const struct firmware *fw; const char *fw_name; - uint32_t data32 = 0; int blocksize = 0; int numblocks = 0; int offset; @@ -534,16 +638,25 @@ static int flash_upgrade(struct solos_card *card, int chip) switch (chip) { case 0: fw_name = "solos-FPGA.bin"; - blocksize = FPGA_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_FPGA_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; break; case 1: fw_name = "solos-Firmware.bin"; - blocksize = SOLOS_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_SOLOS_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; break; case 2: if (card->fpga_version > LEGACY_BUFFERS){ fw_name = "solos-db-FPGA.bin"; - blocksize = FPGA_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_FPGA_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; } else { dev_info(&card->dev->dev, "FPGA version doesn't support" " daughter board upgrades\n"); @@ -553,7 +666,10 @@ static int flash_upgrade(struct solos_card *card, int chip) case 3: if (card->fpga_version > LEGACY_BUFFERS){ fw_name = "solos-Firmware.bin"; - blocksize = SOLOS_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_SOLOS_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; } else { dev_info(&card->dev->dev, "FPGA version doesn't support" " daughter board upgrades\n"); @@ -569,13 +685,16 @@ static int flash_upgrade(struct solos_card *card, int chip) dev_info(&card->dev->dev, "Flash upgrade starting\n"); + /* New FPGAs require driver version before permitting flash upgrades */ + iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER); + numblocks = fw->size / blocksize; dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size); dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks); dev_info(&card->dev->dev, "Changing FPGA to Update mode\n"); iowrite32(1, card->config_regs + FPGA_MODE); - data32 = ioread32(card->config_regs + FPGA_MODE); + (void) ioread32(card->config_regs + FPGA_MODE); /* Set mode to Chip Erase */ if(chip == 0 || chip == 2) @@ -598,9 +717,13 @@ static int flash_upgrade(struct solos_card *card, int chip) /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */ iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE); - /* Copy block to buffer, swapping each 16 bits */ + /* Copy block to buffer, swapping each 16 bits for Atmel flash */ for(i = 0; i < blocksize; i += 4) { - uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); + uint32_t word; + if (card->atmel_flash) + word = swahb32p((uint32_t *)(fw->data + offset + i)); + else + word = *(uint32_t *)(fw->data + offset + i); if(card->fpga_version > LEGACY_BUFFERS) iowrite32(word, FLASH_BUF + i); else @@ -637,7 +760,7 @@ static irqreturn_t solos_irq(int irq, void *dev_id) return IRQ_RETVAL(handled); } -void solos_bh(unsigned long card_arg) +static void solos_bh(unsigned long card_arg) { struct solos_card *card = (void *)card_arg; uint32_t card_flags; @@ -694,7 +817,7 @@ void solos_bh(unsigned long card_arg) size); } if (atmdebug) { - dev_info(&card->dev->dev, "Received: device %d\n", port); + dev_info(&card->dev->dev, "Received: port %d\n", port); dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", size, le16_to_cpu(header->vpi), le16_to_cpu(header->vci)); @@ -707,10 +830,11 @@ void solos_bh(unsigned long card_arg) le16_to_cpu(header->vci)); if (!vcc) { if (net_ratelimit()) - dev_warn(&card->dev->dev, "Received packet for unknown VCI.VPI %d.%d on port %d\n", - le16_to_cpu(header->vci), le16_to_cpu(header->vpi), + dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n", + le16_to_cpu(header->vpi), le16_to_cpu(header->vci), port); - continue; + dev_kfree_skb_any(skb); + break; } atm_charge(vcc, skb->truesize); vcc->push(vcc, skb); @@ -772,15 +896,15 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) { struct hlist_head *head; struct atm_vcc *vcc = NULL; - struct hlist_node *node; struct sock *s; read_lock(&vcc_sklist_lock); head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)]; - sk_for_each(s, node, head) { + sk_for_each(s, head) { vcc = atm_sk(s); if (vcc->dev == dev && vcc->vci == vci && - vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE) + vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE && + test_bit(ATM_VF_READY, &vcc->flags)) goto out; } vcc = NULL; @@ -789,66 +913,6 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) return vcc; } -static int list_vccs(int vci) -{ - struct hlist_head *head; - struct atm_vcc *vcc; - struct hlist_node *node; - struct sock *s; - int num_found = 0; - int i; - - read_lock(&vcc_sklist_lock); - if (vci != 0){ - head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)]; - sk_for_each(s, node, head) { - num_found ++; - vcc = atm_sk(s); - printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n", - vcc->dev->number, - vcc->vpi, - vcc->vci); - } - } else { - for(i = 0; i < VCC_HTABLE_SIZE; i++){ - head = &vcc_hash[i]; - sk_for_each(s, node, head) { - num_found ++; - vcc = atm_sk(s); - printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n", - vcc->dev->number, - vcc->vpi, - vcc->vci); - } - } - } - read_unlock(&vcc_sklist_lock); - return num_found; -} - -static void release_vccs(struct atm_dev *dev) -{ - int i; - - write_lock_irq(&vcc_sklist_lock); - for (i = 0; i < VCC_HTABLE_SIZE; i++) { - struct hlist_head *head = &vcc_hash[i]; - struct hlist_node *node, *tmp; - struct sock *s; - struct atm_vcc *vcc; - - sk_for_each_safe(s, node, tmp, head) { - vcc = atm_sk(s); - if (vcc->dev == dev) { - vcc_release_async(vcc, -EPIPE); - sk_del_node_init(s); - } - } - } - write_unlock_irq(&vcc_sklist_lock); -} - - static int popen(struct atm_vcc *vcc) { struct solos_card *card = vcc->dev->dev_data; @@ -861,9 +925,10 @@ static int popen(struct atm_vcc *vcc) return -EINVAL; } - skb = alloc_skb(sizeof(*header), GFP_ATOMIC); - if (!skb && net_ratelimit()) { - dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n"); + skb = alloc_skb(sizeof(*header), GFP_KERNEL); + if (!skb) { + if (net_ratelimit()) + dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n"); return -ENOMEM; } header = (void *)skb_put(skb, sizeof(*header)); @@ -877,8 +942,6 @@ static int popen(struct atm_vcc *vcc) set_bit(ATM_VF_ADDR, &vcc->flags); set_bit(ATM_VF_READY, &vcc->flags); - list_vccs(0); - return 0; } @@ -886,10 +949,21 @@ static int popen(struct atm_vcc *vcc) static void pclose(struct atm_vcc *vcc) { struct solos_card *card = vcc->dev->dev_data; - struct sk_buff *skb; + unsigned char port = SOLOS_CHAN(vcc->dev); + struct sk_buff *skb, *tmpskb; struct pkt_hdr *header; - skb = alloc_skb(sizeof(*header), GFP_ATOMIC); + /* Remove any yet-to-be-transmitted packets from the pending queue */ + spin_lock(&card->tx_queue_lock); + skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) { + if (SKB_CB(skb)->vcc == vcc) { + skb_unlink(skb, &card->tx_queue[port]); + solos_pop(vcc, skb); + } + } + spin_unlock(&card->tx_queue_lock); + + skb = alloc_skb(sizeof(*header), GFP_KERNEL); if (!skb) { dev_warn(&card->dev->dev, "Failed to allocate sk_buff in pclose()\n"); return; @@ -901,10 +975,21 @@ static void pclose(struct atm_vcc *vcc) header->vci = cpu_to_le16(vcc->vci); header->type = cpu_to_le16(PKT_PCLOSE); - fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL); + skb_get(skb); + fpga_queue(card, port, skb, NULL); + + if (!wait_event_timeout(card->param_wq, !skb_shared(skb), 5 * HZ)) + dev_warn(&card->dev->dev, + "Timeout waiting for VCC close on port %d\n", port); + + dev_kfree_skb(skb); + + /* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the + tasklet has finished processing any incoming packets (and, more to + the point, using the vcc pointer). */ + tasklet_unlock_wait(&card->tlet); clear_bit(ATM_VF_ADDR, &vcc->flags); - clear_bit(ATM_VF_READY, &vcc->flags); return; } @@ -983,10 +1068,11 @@ static uint32_t fpga_tx(struct solos_card *card) for (port = 0; tx_pending; tx_pending >>= 1, port++) { if (tx_pending & 1) { struct sk_buff *oldskb = card->tx_skb[port]; - if (oldskb) + if (oldskb) { pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr, oldskb->len, PCI_DMA_TODEVICE); - + card->tx_skb[port] = NULL; + } spin_lock(&card->tx_queue_lock); skb = skb_dequeue(&card->tx_queue[port]); if (!skb) @@ -998,8 +1084,14 @@ static uint32_t fpga_tx(struct solos_card *card) tx_started |= 1 << port; oldskb = skb; /* We're done with this skb already */ } else if (skb && card->using_dma) { - SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, + unsigned char *data = skb->data; + if ((unsigned long)data & card->dma_alignment) { + data = card->dma_bounce + (BUF_SIZE * port); + memcpy(data, skb->data, skb->len); + } + SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data, skb->len, PCI_DMA_TODEVICE); + card->tx_skb[port] = skb; iowrite32(SKB_CB(skb)->dma_addr, card->config_regs + TX_DMA_ADDR(port)); } @@ -1009,8 +1101,15 @@ static uint32_t fpga_tx(struct solos_card *card) /* Clean up and free oldskb now it's gone */ if (atmdebug) { + struct pkt_hdr *header = (void *)oldskb->data; + int size = le16_to_cpu(header->size); + + skb_pull(oldskb, sizeof(*header)); dev_info(&card->dev->dev, "Transmitted: port %d\n", port); + dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", + size, le16_to_cpu(header->vpi), + le16_to_cpu(header->vci)); print_buffer(oldskb); } @@ -1019,9 +1118,10 @@ static uint32_t fpga_tx(struct solos_card *card) if (vcc) { atomic_inc(&vcc->stats->tx); solos_pop(vcc, oldskb); - } else + } else { dev_kfree_skb_irq(oldskb); - + wake_up(&card->param_wq); + } } } /* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */ @@ -1153,17 +1253,41 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n", major_ver, minor_ver, fpga_ver); - if (card->fpga_version >= DMA_SUPPORTED){ + if (fpga_ver < 37 && (fpga_upgrade || firmware_upgrade || + db_fpga_upgrade || db_firmware_upgrade)) { + dev_warn(&dev->dev, + "FPGA too old; cannot upgrade flash. Use JTAG.\n"); + fpga_upgrade = firmware_upgrade = 0; + db_fpga_upgrade = db_firmware_upgrade = 0; + } + + /* Stopped using Atmel flash after 0.03-38 */ + if (fpga_ver < 39) + card->atmel_flash = 1; + else + card->atmel_flash = 0; + + data32 = ioread32(card->config_regs + PORTS); + card->nr_ports = (data32 & 0x000000FF); + + if (card->fpga_version >= DMA_SUPPORTED) { + pci_set_master(dev); card->using_dma = 1; + if (1) { /* All known FPGA versions so far */ + card->dma_alignment = 3; + card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL); + if (!card->dma_bounce) { + dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n"); + /* Fallback to MMIO doesn't work */ + goto out_unmap_both; + } + } } else { card->using_dma = 0; /* Set RX empty flag for all ports */ iowrite32(0xF0, card->config_regs + FLAGS_ADDR); } - data32 = ioread32(card->config_regs + PORTS); - card->nr_ports = (data32 & 0x000000FF); - pci_set_drvdata(dev, card); tasklet_init(&card->tlet, solos_bh, (unsigned long)card); @@ -1194,10 +1318,14 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) if (db_firmware_upgrade) flash_upgrade(card, 3); - err = atm_init(card); + err = atm_init(card, &dev->dev); if (err) goto out_free_irq; + if (card->fpga_version >= DMA_SUPPORTED && + sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group)) + dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n"); + return 0; out_free_irq: @@ -1206,10 +1334,10 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) tasklet_kill(&card->tlet); out_unmap_both: - pci_set_drvdata(dev, NULL); - pci_iounmap(dev, card->config_regs); - out_unmap_config: + kfree(card->dma_bounce); pci_iounmap(dev, card->buffers); + out_unmap_config: + pci_iounmap(dev, card->config_regs); out_release_regions: pci_release_regions(dev); out: @@ -1217,7 +1345,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) return err; } -static int atm_init(struct solos_card *card) +static int atm_init(struct solos_card *card, struct device *parent) { int i; @@ -1228,7 +1356,7 @@ static int atm_init(struct solos_card *card) skb_queue_head_init(&card->tx_queue[i]); skb_queue_head_init(&card->cli_queue[i]); - card->atmdev[i] = atm_dev_register("solos-pci", &fpga_ops, -1, NULL); + card->atmdev[i] = atm_dev_register("solos-pci", parent, &fpga_ops, -1, NULL); if (!card->atmdev[i]) { dev_err(&card->dev->dev, "Could not register ATM device %d\n", i); atm_remove(card); @@ -1245,9 +1373,9 @@ static int atm_init(struct solos_card *card) card->atmdev[i]->ci_range.vci_bits = 16; card->atmdev[i]->dev_data = card; card->atmdev[i]->phy_data = (void *)(unsigned long)i; - card->atmdev[i]->signal = ATM_PHY_SIG_UNKNOWN; + atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND); - skb = alloc_skb(sizeof(*header), GFP_ATOMIC); + skb = alloc_skb(sizeof(*header), GFP_KERNEL); if (!skb) { dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n"); continue; @@ -1308,11 +1436,16 @@ static void fpga_remove(struct pci_dev *dev) iowrite32(1, card->config_regs + FPGA_MODE); (void)ioread32(card->config_regs + FPGA_MODE); + if (card->fpga_version >= DMA_SUPPORTED) + sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group); + atm_remove(card); free_irq(dev->irq, card); tasklet_kill(&card->tlet); + kfree(card->dma_bounce); + /* Release device from reset */ iowrite32(0, card->config_regs + FPGA_MODE); (void)ioread32(card->config_regs + FPGA_MODE); @@ -1323,11 +1456,10 @@ static void fpga_remove(struct pci_dev *dev) pci_release_regions(dev); pci_disable_device(dev); - pci_set_drvdata(dev, NULL); kfree(card); } -static struct pci_device_id fpga_pci_tbl[] __devinitdata = { +static struct pci_device_id fpga_pci_tbl[] = { { 0x10ee, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, } }; @@ -1344,6 +1476,8 @@ static struct pci_driver fpga_driver = { static int __init solos_pci_init(void) { + BUILD_BUG_ON(sizeof(struct solos_skb_cb) > sizeof(((struct sk_buff *)0)->cb)); + printk(KERN_INFO "Solos PCI Driver Version %s\n", VERSION); return pci_register_driver(&fpga_driver); } diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c index 6dd3f591996..02159345566 100644 --- a/drivers/atm/suni.c +++ b/drivers/atm/suni.c @@ -21,10 +21,10 @@ #include <linux/init.h> #include <linux/capability.h> #include <linux/atm_suni.h> -#include <asm/system.h> +#include <linux/slab.h> #include <asm/param.h> #include <asm/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include "suni.h" @@ -290,8 +290,9 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) static void poll_los(struct atm_dev *dev) { - dev->signal = GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ? ATM_PHY_SIG_LOST : - ATM_PHY_SIG_FOUND; + atm_dev_signal_change(dev, + GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ? + ATM_PHY_SIG_LOST : ATM_PHY_SIG_FOUND); } diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c index fc8cb07c247..5120a96b3a8 100644 --- a/drivers/atm/uPD98402.c +++ b/drivers/atm/uPD98402.c @@ -9,8 +9,9 @@ #include <linux/atmdev.h> #include <linux/sonet.h> #include <linux/init.h> +#include <linux/slab.h> #include <asm/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include "uPD98402.h" diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 2e9635be048..969c3c29000 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -16,16 +16,17 @@ #include <linux/delay.h> #include <linux/uio.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/atm_zatm.h> #include <linux/capability.h> #include <linux/bitops.h> #include <linux/wait.h> +#include <linux/slab.h> #include <asm/byteorder.h> -#include <asm/system.h> #include <asm/string.h> #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/uaccess.h> #include "uPD98401.h" @@ -1093,8 +1094,8 @@ static irqreturn_t zatm_int(int irq,void *dev_id) /*----------------------------- (E)EPROM access -----------------------------*/ -static void __devinit eprom_set(struct zatm_dev *zatm_dev,unsigned long value, - unsigned short cmd) +static void eprom_set(struct zatm_dev *zatm_dev, unsigned long value, + unsigned short cmd) { int error; @@ -1104,8 +1105,7 @@ static void __devinit eprom_set(struct zatm_dev *zatm_dev,unsigned long value, } -static unsigned long __devinit eprom_get(struct zatm_dev *zatm_dev, - unsigned short cmd) +static unsigned long eprom_get(struct zatm_dev *zatm_dev, unsigned short cmd) { unsigned int value; int error; @@ -1117,8 +1117,8 @@ static unsigned long __devinit eprom_get(struct zatm_dev *zatm_dev, } -static void __devinit eprom_put_bits(struct zatm_dev *zatm_dev, - unsigned long data,int bits,unsigned short cmd) +static void eprom_put_bits(struct zatm_dev *zatm_dev, unsigned long data, + int bits, unsigned short cmd) { unsigned long value; int i; @@ -1132,8 +1132,8 @@ static void __devinit eprom_put_bits(struct zatm_dev *zatm_dev, } -static void __devinit eprom_get_byte(struct zatm_dev *zatm_dev, - unsigned char *byte,unsigned short cmd) +static void eprom_get_byte(struct zatm_dev *zatm_dev, unsigned char *byte, + unsigned short cmd) { int i; @@ -1148,8 +1148,8 @@ static void __devinit eprom_get_byte(struct zatm_dev *zatm_dev, } -static unsigned char __devinit eprom_try_esi(struct atm_dev *dev, - unsigned short cmd,int offset,int swap) +static unsigned char eprom_try_esi(struct atm_dev *dev, unsigned short cmd, + int offset, int swap) { unsigned char buf[ZEPROM_SIZE]; struct zatm_dev *zatm_dev; @@ -1169,7 +1169,7 @@ static unsigned char __devinit eprom_try_esi(struct atm_dev *dev, } -static void __devinit eprom_get_esi(struct atm_dev *dev) +static void eprom_get_esi(struct atm_dev *dev) { if (eprom_try_esi(dev,ZEPROM_V1_REG,ZEPROM_V1_ESI_OFF,1)) return; (void) eprom_try_esi(dev,ZEPROM_V2_REG,ZEPROM_V2_ESI_OFF,0); @@ -1179,7 +1179,7 @@ static void __devinit eprom_get_esi(struct atm_dev *dev) /*--------------------------------- entries ---------------------------------*/ -static int __devinit zatm_init(struct atm_dev *dev) +static int zatm_init(struct atm_dev *dev) { struct zatm_dev *zatm_dev; struct pci_dev *pci_dev; @@ -1256,7 +1256,7 @@ static int __devinit zatm_init(struct atm_dev *dev) } -static int __devinit zatm_start(struct atm_dev *dev) +static int zatm_start(struct atm_dev *dev) { struct zatm_dev *zatm_dev = ZATM_DEV(dev); struct pci_dev *pdev = zatm_dev->pci_dev; @@ -1583,8 +1583,8 @@ static const struct atmdev_ops ops = { .change_qos = zatm_change_qos, }; -static int __devinit zatm_init_one(struct pci_dev *pci_dev, - const struct pci_device_id *ent) +static int zatm_init_one(struct pci_dev *pci_dev, + const struct pci_device_id *ent) { struct atm_dev *dev; struct zatm_dev *zatm_dev; @@ -1596,7 +1596,7 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev, goto out; } - dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); + dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL); if (!dev) goto out_free; @@ -1635,11 +1635,9 @@ out_free: MODULE_LICENSE("GPL"); -static struct pci_device_id zatm_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1221, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, ZATM_COPPER }, - { PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1225, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +static struct pci_device_id zatm_pci_tbl[] = { + { PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1221), ZATM_COPPER }, + { PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1225), 0 }, { 0, } }; MODULE_DEVICE_TABLE(pci, zatm_pci_tbl); |
