^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* drivers/atm/eni.c - Efficient Networks ENI155P device driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/atm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/atmdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sonet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/atm_eni.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "tonga.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "midway.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "suni.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "eni.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Show stoppers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Minor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * - OAM support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * - fix bugs listed below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * KNOWN BUGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * - may run into JK-JK bug and deadlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * - should allocate UBR channel first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * - buffer space allocation algorithm is stupid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * (RX: should be maxSDU+maxdelay*rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * TX: should be maxSDU+min(maxSDU,maxdelay*rate) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * - doesn't support OAM cells
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * - eni_put_free may hang if not putting memory fragments that _complete_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * 2^n block (never happens in real life, though)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define DPRINTK(format,args...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #ifndef CONFIG_ATM_ENI_TUNE_BURST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define CONFIG_ATM_ENI_BURST_TX_8W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CONFIG_ATM_ENI_BURST_RX_4W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #ifndef CONFIG_ATM_ENI_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define NULLCHECK(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define EVENT(s,a,b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void event_dump(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * NULL pointer checking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define NULLCHECK(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if ((unsigned long) (x) < 0x30) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) printk(KERN_CRIT #x "==0x%lx\n",(unsigned long) (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Very extensive activity logging. Greatly improves bug detection speed but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * costs a few Mbps if enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define EV 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static const char *ev[EV];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static unsigned long ev_a[EV],ev_b[EV];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int ec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static void EVENT(const char *s,unsigned long a,unsigned long b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ev[ec] = s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ev_a[ec] = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ev_b[ec] = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ec = (ec+1) % EV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void event_dump(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int n,i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) for (n = 0; n < EV; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) i = (ec+n) % EV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) printk(KERN_NOTICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) printk(ev[i] ? ev[i] : "(null)",ev_a[i],ev_b[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #endif /* CONFIG_ATM_ENI_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * NExx must not be equal at end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * EExx may be equal at end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * xxPJOK verify validity of pointer jumps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * xxPMOK operating on a circular buffer of "c" words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define NEPJOK(a0,a1,b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ((a0) < (a1) ? (b) <= (a0) || (b) > (a1) : (b) <= (a0) && (b) > (a1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define EEPJOK(a0,a1,b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ((a0) < (a1) ? (b) < (a0) || (b) >= (a1) : (b) < (a0) && (b) >= (a1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define NEPMOK(a0,d,b,c) NEPJOK(a0,(a0+d) & (c-1),b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define EEPMOK(a0,d,b,c) EEPJOK(a0,(a0+d) & (c-1),b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) backlogged = 0,rx_enqueued = 0,rx_dequeued = 0,pushed = 0,submitted = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) putting = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static struct atm_dev *eni_boards = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Read/write registers on card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define eni_in(r) readl(eni_dev->reg+(r)*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define eni_out(v,r) writel((v),eni_dev->reg+(r)*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*-------------------------------- utilities --------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static void dump_mem(struct eni_dev *eni_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for (i = 0; i < eni_dev->free_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) printk(KERN_DEBUG " %d: %p %d\n",i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) eni_dev->free_list[i].start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 1 << eni_dev->free_list[i].order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void dump(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) printk(KERN_NOTICE "Free memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dump_mem(eni_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) printk(KERN_NOTICE "TX buffers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) for (i = 0; i < NR_CHAN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (eni_dev->tx[i].send)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) printk(KERN_NOTICE " TX %d @ %p: %ld\n",i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) eni_dev->tx[i].send,eni_dev->tx[i].words*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) printk(KERN_NOTICE "RX buffers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) for (i = 0; i < 1024; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) printk(KERN_NOTICE " RX %d @ %p: %ld\n",i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ENI_VCC(eni_dev->rx_map[i])->recv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ENI_VCC(eni_dev->rx_map[i])->words*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) printk(KERN_NOTICE "----\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void eni_put_free(struct eni_dev *eni_dev, void __iomem *start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct eni_free *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int len,order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) DPRINTK("init 0x%lx+%ld(0x%lx)\n",start,size,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) start += eni_dev->base_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) list = eni_dev->free_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) len = eni_dev->free_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) while (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (len >= eni_dev->free_list_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) printk(KERN_CRIT "eni_put_free overflow (%p,%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) start,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (order = 0; !(((unsigned long)start | size) & (1 << order)); order++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (MID_MIN_BUF_SIZE > (1 << order)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) printk(KERN_CRIT "eni_put_free: order %d too small\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) list[len].start = (void __iomem *) start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) list[len].order = order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) start += 1 << order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) size -= 1 << order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) eni_dev->free_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /*dump_mem(eni_dev);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static void __iomem *eni_alloc_mem(struct eni_dev *eni_dev, unsigned long *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct eni_free *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void __iomem *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int len,i,order,best_order,index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) list = eni_dev->free_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) len = eni_dev->free_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (*size < MID_MIN_BUF_SIZE) *size = MID_MIN_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (*size > MID_MAX_BUF_SIZE) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) for (order = 0; (1 << order) < *size; order++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) DPRINTK("trying: %ld->%d\n",*size,order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) best_order = 65; /* we don't have more than 2^64 of anything ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) index = 0; /* silence GCC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (list[i].order == order) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) best_order = order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) else if (best_order > list[i].order && list[i].order > order) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) best_order = list[i].order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (best_order == 65) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) start = list[index].start-eni_dev->base_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) list[index] = list[--len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) eni_dev->free_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *size = 1 << order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) eni_put_free(eni_dev,start+*size,(1 << best_order)-*size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) DPRINTK("%ld bytes (order %d) at 0x%lx\n",*size,order,start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) memset_io(start,0,*size); /* never leak data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*dump_mem(eni_dev);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void eni_free_mem(struct eni_dev *eni_dev, void __iomem *start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct eni_free *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int len,i,order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) start += eni_dev->base_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) list = eni_dev->free_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) len = eni_dev->free_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) for (order = -1; size; order++) size >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) DPRINTK("eni_free_mem: %p+0x%lx (order %d)\n",start,size,order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (((unsigned long) list[i].start) == ((unsigned long)start^(1 << order)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) list[i].order == order) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) DPRINTK("match[%d]: 0x%lx/0x%lx(0x%x), %d/%d\n",i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) list[i].start,start,1 << order,list[i].order,order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) list[i] = list[--len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) start = (void __iomem *) ((unsigned long) start & ~(unsigned long) (1 << order));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) order++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) i = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (len >= eni_dev->free_list_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) printk(KERN_ALERT "eni_free_mem overflow (%p,%d)\n",start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) list[len].start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) list[len].order = order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) eni_dev->free_len = len+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*dump_mem(eni_dev);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*----------------------------------- RX ------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #define ENI_VCC_NOS ((struct atm_vcc *) 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void rx_ident_err(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct atm_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev = vcc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* immediately halt adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) eni_out(eni_in(MID_MC_S) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ~(MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE),MID_MC_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* dump useful information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) printk(KERN_ALERT DEV_LABEL "(itf %d): driver error - RX ident "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) "mismatch\n",dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) printk(KERN_ALERT " VCI %d, rxing %d, words %ld\n",vcc->vci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) eni_vcc->rxing,eni_vcc->words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) printk(KERN_ALERT " host descr 0x%lx, rx pos 0x%lx, descr value "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) printk(KERN_ALERT " last %p, servicing %d\n",eni_vcc->last,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) eni_vcc->servicing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) EVENT("---dump ends here---\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) printk(KERN_NOTICE "---recent events---\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) event_dump();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ENI_DEV(dev)->fast = NULL; /* really stop it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ENI_DEV(dev)->slow = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) skb_queue_head_init(&ENI_DEV(dev)->rx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) unsigned long skip,unsigned long size,unsigned long eff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u32 dma_rd,dma_wr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) u32 dma[RX_DMA_BUF*2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dma_addr_t paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) unsigned long here;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) int i,j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) paddr = 0; /* GCC, shut up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) paddr = dma_map_single(&eni_dev->pci_dev->dev,skb->data,skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (dma_mapping_error(&eni_dev->pci_dev->dev, paddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) goto dma_map_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ENI_PRV_PADDR(skb) = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (paddr & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d has "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) "mis-aligned RX data (0x%lx)\n",vcc->dev->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) vcc->vci,(unsigned long) paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ENI_PRV_SIZE(skb) = size+skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* PDU plus descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) ATM_SKB(skb)->vcc = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if ((eff && skip) || 1) { /* @@@ actually, skip is always == 1 ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) here = (eni_vcc->descr+skip) & (eni_vcc->words-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) << MID_DMA_VCI_SHIFT) | MID_DT_JK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) dma[j++] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) here = (eni_vcc->descr+size+skip) & (eni_vcc->words-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!eff) size += skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) unsigned long words;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) DPRINTK("strange things happen ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) EVENT("strange things happen ... (skip=%ld,eff=%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) size,eff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) words = eff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (paddr & 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) unsigned long init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) init = 4-((paddr & 15) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (init > words) init = words;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) dma[j++] = MID_DT_WORD | (init << MID_DMA_COUNT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) (vcc->vci << MID_DMA_VCI_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dma[j++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) paddr += init << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) words -= init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) #ifdef CONFIG_ATM_ENI_BURST_RX_16W /* may work with some PCI chipsets ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (words & ~15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) dma[j++] = MID_DT_16W | ((words >> 4) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) MID_DMA_COUNT_SHIFT) | (vcc->vci <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) MID_DMA_VCI_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) dma[j++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) paddr += (words & ~15) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) words &= 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) #ifdef CONFIG_ATM_ENI_BURST_RX_8W /* works only with *some* PCI chipsets ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (words & ~7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) dma[j++] = MID_DT_8W | ((words >> 3) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) MID_DMA_COUNT_SHIFT) | (vcc->vci <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) MID_DMA_VCI_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) dma[j++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) paddr += (words & ~7) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) words &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) #ifdef CONFIG_ATM_ENI_BURST_RX_4W /* recommended */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (words & ~3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) dma[j++] = MID_DT_4W | ((words >> 2) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) MID_DMA_COUNT_SHIFT) | (vcc->vci <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) MID_DMA_VCI_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dma[j++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) paddr += (words & ~3) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) words &= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) #ifdef CONFIG_ATM_ENI_BURST_RX_2W /* probably useless if RX_4W, RX_8W, ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (words & ~1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) dma[j++] = MID_DT_2W | ((words >> 1) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) MID_DMA_COUNT_SHIFT) | (vcc->vci <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) MID_DMA_VCI_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) dma[j++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) paddr += (words & ~1) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) words &= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (words) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) dma[j++] = MID_DT_WORD | (words << MID_DMA_COUNT_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) | (vcc->vci << MID_DMA_VCI_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dma[j++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (size != eff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) dma[j++] = (here << MID_DMA_COUNT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) dma[j++] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (!j || j > 2*RX_DMA_BUF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) printk(KERN_CRIT DEV_LABEL "!j or j too big!!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) goto trouble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) dma[j-2] |= MID_DMA_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) j = j >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) dma_wr = eni_in(MID_DMA_WR_RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) dma_rd = eni_in(MID_DMA_RD_RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * Can I move the dma_wr pointer by 2j+1 positions without overwriting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * data that hasn't been read (position of dma_rd) yet ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!NEPMOK(dma_wr,j+j+1,dma_rd,NR_DMA_RX)) { /* @@@ +1 is ugly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) printk(KERN_WARNING DEV_LABEL "(itf %d): RX DMA full\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) vcc->dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) goto trouble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) for (i = 0; i < j; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) writel(dma[i*2],eni_dev->rx_dma+dma_wr*8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) writel(dma[i*2+1],eni_dev->rx_dma+dma_wr*8+4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) dma_wr = (dma_wr+1) & (NR_DMA_RX-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ENI_PRV_POS(skb) = eni_vcc->descr+size+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) skb_queue_tail(&eni_dev->rx_queue,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) eni_vcc->last = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) rx_enqueued++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) eni_vcc->descr = here;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) eni_out(dma_wr,MID_DMA_WR_RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) trouble:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) dma_unmap_single(&eni_dev->pci_dev->dev,paddr,skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dma_map_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (skb) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static void discard(struct atm_vcc *vcc,unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) EVENT("discard (size=%ld)\n",size,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) while (do_rx_dma(vcc,NULL,1,size,0)) EVENT("BUSY LOOP",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* could do a full fallback, but that might be more expensive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (eni_vcc->rxing) ENI_PRV_POS(eni_vcc->last) += size+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) else eni_vcc->rx_pos = (eni_vcc->rx_pos+size+1) & (eni_vcc->words-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * TODO: should check whether direct copies (without DMA setup, dequeuing on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * interrupt, etc.) aren't much faster for AAL0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int rx_aal0(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) unsigned long descr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) DPRINTK(">rx_aal0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) descr = readl(eni_vcc->recv+eni_vcc->descr*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) rx_ident_err(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (descr & MID_RED_T) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) vcc->dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) atomic_inc(&vcc->stats->rx_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) length = ATM_CELL_SIZE-1; /* no HEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) skb = length ? atm_alloc_charge(vcc,length,GFP_ATOMIC) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) discard(vcc,length >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) skb_put(skb,length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) skb->tstamp = eni_vcc->timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) DPRINTK("got len %ld\n",length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (do_rx_dma(vcc,skb,1,length >> 2,length >> 2)) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) eni_vcc->rxing++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static int rx_aal5(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) unsigned long descr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) unsigned long size,eff,length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) EVENT("rx_aal5\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) DPRINTK(">rx_aal5\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) descr = readl(eni_vcc->recv+eni_vcc->descr*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) rx_ident_err(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (descr & (MID_RED_T | MID_RED_CRC_ERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (descr & MID_RED_T) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) EVENT("empty cell (descr=0x%lx)\n",descr,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) vcc->dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static unsigned long silence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (time_after(jiffies, silence) || silence == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) printk(KERN_WARNING DEV_LABEL "(itf %d): "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) "discarding PDU(s) with CRC error\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) vcc->dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) silence = (jiffies+2*HZ)|1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) EVENT("CRC error (descr=0x%lx,size=%ld)\n",descr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) eff = length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) atomic_inc(&vcc->stats->rx_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) DPRINTK("size=%ld\n",size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) length = readl(eni_vcc->recv+(((eni_vcc->descr+size-1) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) (eni_vcc->words-1)))*4) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* -trailer(2)+header(1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (length && length <= (size << 2)-8 && length <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ATM_MAX_AAL5_PDU) eff = (length+3) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) else { /* ^ trailer length (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) EVENT("bad PDU (descr=0x08%lx,length=%ld)\n",descr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) printk(KERN_ERR DEV_LABEL "(itf %d): bad AAL5 PDU "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) "(VCI=%d,length=%ld,size=%ld (descr 0x%lx))\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) vcc->dev->number,vcc->vci,length,size << 2,descr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) length = eff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) atomic_inc(&vcc->stats->rx_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) skb = eff ? atm_alloc_charge(vcc,eff << 2,GFP_ATOMIC) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) discard(vcc,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) skb_put(skb,length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) DPRINTK("got len %ld\n",length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (do_rx_dma(vcc,skb,1,size,eff)) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) eni_vcc->rxing++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static inline int rx_vcc(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) void __iomem *vci_dsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) vci_dsc = ENI_DEV(vcc->dev)->vci+vcc->vci*16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) EVENT("rx_vcc(1)\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) while (eni_vcc->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) MID_VCI_DESCR_SHIFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) EVENT("rx_vcc(2: host dsc=0x%lx, nic dsc=0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) eni_vcc->descr,tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) MID_VCI_DESCR_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (ENI_VCC(vcc)->rx(vcc)) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* clear IN_SERVICE flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) writel(readl(vci_dsc) & ~MID_VCI_IN_SERVICE,vci_dsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * If new data has arrived between evaluating the while condition and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * clearing IN_SERVICE, we wouldn't be notified until additional data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * follows. So we have to loop again to be sure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) EVENT("rx_vcc(3)\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) while (ENI_VCC(vcc)->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) >> MID_VCI_DESCR_SHIFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) EVENT("rx_vcc(4: host dsc=0x%lx, nic dsc=0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) eni_vcc->descr,tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) MID_VCI_DESCR_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (ENI_VCC(vcc)->rx(vcc)) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static void poll_rx(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) struct atm_vcc *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) while ((curr = eni_dev->fast)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) EVENT("poll_rx.fast\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (rx_vcc(curr)) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) eni_dev->fast = ENI_VCC(curr)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) ENI_VCC(curr)->next = ENI_VCC_NOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) ENI_VCC(curr)->servicing--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) while ((curr = eni_dev->slow)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) EVENT("poll_rx.slow\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (rx_vcc(curr)) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) eni_dev->slow = ENI_VCC(curr)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ENI_VCC(curr)->next = ENI_VCC_NOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ENI_VCC(curr)->servicing--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static void get_service(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) unsigned long vci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) DPRINTK(">get_service\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) while (eni_in(MID_SERV_WRITE) != eni_dev->serv_read) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) vci = readl(eni_dev->service+eni_dev->serv_read*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) eni_dev->serv_read = (eni_dev->serv_read+1) & (NR_SERVICE-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) vcc = eni_dev->rx_map[vci & 1023];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (!vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %ld not "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) "found\n",dev->number,vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) continue; /* nasty but we try to go on anyway */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* @@@ nope, doesn't work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) EVENT("getting from service\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (ENI_VCC(vcc)->next != ENI_VCC_NOS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) EVENT("double service\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) DPRINTK("Grr, servicing VCC %ld twice\n",vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ENI_VCC(vcc)->timestamp = ktime_get_real();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ENI_VCC(vcc)->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (vcc->qos.rxtp.traffic_class == ATM_CBR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (eni_dev->fast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) ENI_VCC(eni_dev->last_fast)->next = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) else eni_dev->fast = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) eni_dev->last_fast = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (eni_dev->slow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ENI_VCC(eni_dev->last_slow)->next = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) else eni_dev->slow = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) eni_dev->last_slow = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) putting++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ENI_VCC(vcc)->servicing++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static void dequeue_rx(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) void __iomem *vci_dsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) first = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) skb = skb_dequeue(&eni_dev->rx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) DPRINTK(DEV_LABEL "(itf %d): RX but not "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) "rxing\n",dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) EVENT("nothing to dequeue\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) EVENT("dequeued (size=%ld,pos=0x%lx)\n",ENI_PRV_SIZE(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ENI_PRV_POS(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) rx_dequeued++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) vcc = ATM_SKB(skb)->vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) first = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) vci_dsc = eni_dev->vci+vcc->vci*16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (!EEPMOK(eni_vcc->rx_pos,ENI_PRV_SIZE(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) (readl(vci_dsc+4) & MID_VCI_READ) >> MID_VCI_READ_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) eni_vcc->words)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) EVENT("requeuing\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) skb_queue_head(&eni_dev->rx_queue,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) eni_vcc->rxing--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) eni_vcc->rx_pos = ENI_PRV_POS(skb) & (eni_vcc->words-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) dma_unmap_single(&eni_dev->pci_dev->dev,ENI_PRV_PADDR(skb),skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (!skb->len) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) EVENT("pushing (len=%ld)\n",skb->len,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (vcc->qos.aal == ATM_AAL0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) *(unsigned long *) skb->data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ntohl(*(unsigned long *) skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) memset(skb->cb,0,sizeof(struct eni_skb_prv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) vcc->push(vcc,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) pushed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) atomic_inc(&vcc->stats->rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) wake_up(&eni_dev->rx_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static int open_rx_first(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) DPRINTK("open_rx_first\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) eni_vcc->rx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) size = vcc->qos.rxtp.max_sdu*eni_dev->rx_mult/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (size > MID_MAX_BUF_SIZE && vcc->qos.rxtp.max_sdu <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) MID_MAX_BUF_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) size = MID_MAX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) eni_vcc->recv = eni_alloc_mem(eni_dev,&size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) DPRINTK("rx at 0x%lx\n",eni_vcc->recv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) eni_vcc->words = size >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (!eni_vcc->recv) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) eni_vcc->rx = vcc->qos.aal == ATM_AAL5 ? rx_aal5 : rx_aal0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) eni_vcc->descr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) eni_vcc->rx_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) eni_vcc->rxing = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) eni_vcc->servicing = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) eni_vcc->next = ENI_VCC_NOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static int open_rx_second(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) void __iomem *here;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) DPRINTK("open_rx_second\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (!eni_vcc->rx) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* set up VCI descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) here = eni_dev->vci+vcc->vci*16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) DPRINTK("loc 0x%x\n",(unsigned) (eni_vcc->recv-eni_dev->ram)/4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) size = eni_vcc->words >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) for (order = -1; size; order++) size >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) writel(0,here+4); /* descr, read = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) writel(0,here+8); /* write, state, count = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (eni_dev->rx_map[vcc->vci])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) printk(KERN_CRIT DEV_LABEL "(itf %d): BUG - VCI %d already "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) "in use\n",vcc->dev->number,vcc->vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) eni_dev->rx_map[vcc->vci] = vcc; /* now it counts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) writel(((vcc->qos.aal != ATM_AAL5 ? MID_MODE_RAW : MID_MODE_AAL5) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) MID_VCI_MODE_SHIFT) | MID_VCI_PTI_MODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) (((eni_vcc->recv-eni_dev->ram) >> (MID_LOC_SKIP+2)) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) MID_VCI_LOCATION_SHIFT) | (order << MID_VCI_SIZE_SHIFT),here);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static void close_rx(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) DECLARE_WAITQUEUE(wait,current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) void __iomem *here;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (!eni_vcc->rx) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (vcc->vpi != ATM_VPI_UNSPEC && vcc->vci != ATM_VCI_UNSPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) here = eni_dev->vci+vcc->vci*16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /* block receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) writel((readl(here) & ~MID_VCI_MODE) | (MID_MODE_TRASH <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) MID_VCI_MODE_SHIFT),here);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /* wait for receiver to become idle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) udelay(27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) /* discard pending cell */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) writel(readl(here) & ~MID_VCI_IN_SERVICE,here);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) /* don't accept any new ones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) eni_dev->rx_map[vcc->vci] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) /* wait for RX queue to drain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) DPRINTK("eni_close: waiting for RX ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) EVENT("RX closing\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) add_wait_queue(&eni_dev->rx_wait,&wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* transition service->rx: rxing++, servicing-- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (!eni_vcc->servicing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (!eni_vcc->rxing) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) EVENT("drain PDUs (rx %ld, serv %ld)\n",eni_vcc->rxing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) eni_vcc->servicing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) printk(KERN_INFO "%d+%d RX left\n",eni_vcc->servicing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) eni_vcc->rxing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) int at_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) tasklet_disable(&eni_dev->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) tmp = readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) at_end = eni_vcc->rx_pos == tmp >> MID_VCI_READ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) tasklet_enable(&eni_dev->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (at_end) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) EVENT("drain discard (host 0x%lx, nic 0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) eni_vcc->rx_pos,tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) printk(KERN_INFO "draining RX: host 0x%lx, nic 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) eni_vcc->rx_pos,tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) remove_wait_queue(&eni_dev->rx_wait,&wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) eni_free_mem(eni_dev,eni_vcc->recv,eni_vcc->words << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) eni_vcc->rx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static int start_rx(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) eni_dev->rx_map = (struct atm_vcc **) get_zeroed_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (!eni_dev->rx_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) free_page((unsigned long) eni_dev->free_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) eni_dev->rx_mult = DEFAULT_RX_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) eni_dev->fast = eni_dev->last_fast = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) eni_dev->slow = eni_dev->last_slow = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) init_waitqueue_head(&eni_dev->rx_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) skb_queue_head_init(&eni_dev->rx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) eni_dev->serv_read = eni_in(MID_SERV_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) eni_out(0,MID_DMA_WR_RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /*----------------------------------- TX ------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) enum enq_res { enq_ok,enq_next,enq_jam };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static inline void put_dma(int chan,u32 *dma,int *j,dma_addr_t paddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) u32 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) u32 init,words;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) DPRINTK("put_dma: 0x%lx+0x%x\n",(unsigned long) paddr,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) EVENT("put_dma: 0x%lx+0x%lx\n",(unsigned long) paddr,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) #if 0 /* don't complain anymore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (paddr & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) printk(KERN_ERR "put_dma: unaligned addr (0x%lx)\n",paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (size & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) printk(KERN_ERR "put_dma: unaligned size (0x%lx)\n",size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (paddr & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) init = 4-(paddr & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (init > size || size < 7) init = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) DPRINTK("put_dma: %lx DMA: %d/%d bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) (unsigned long) paddr,init,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) dma[(*j)++] = MID_DT_BYTE | (init << MID_DMA_COUNT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) paddr += init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) size -= init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) words = size >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) size &= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (words && (paddr & 31)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) init = 8-((paddr & 31) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (init > words) init = words;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) DPRINTK("put_dma: %lx DMA: %d/%d words\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) (unsigned long) paddr,init,words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) dma[(*j)++] = MID_DT_WORD | (init << MID_DMA_COUNT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) paddr += init << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) words -= init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) #ifdef CONFIG_ATM_ENI_BURST_TX_16W /* may work with some PCI chipsets ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (words & ~15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) DPRINTK("put_dma: %lx DMA: %d*16/%d words\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) (unsigned long) paddr,words >> 4,words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) dma[(*j)++] = MID_DT_16W | ((words >> 4) << MID_DMA_COUNT_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) | (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) paddr += (words & ~15) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) words &= 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) #ifdef CONFIG_ATM_ENI_BURST_TX_8W /* recommended */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (words & ~7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) DPRINTK("put_dma: %lx DMA: %d*8/%d words\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) (unsigned long) paddr,words >> 3,words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) dma[(*j)++] = MID_DT_8W | ((words >> 3) << MID_DMA_COUNT_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) | (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) paddr += (words & ~7) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) words &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) #ifdef CONFIG_ATM_ENI_BURST_TX_4W /* probably useless if TX_8W or TX_16W */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (words & ~3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) DPRINTK("put_dma: %lx DMA: %d*4/%d words\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) (unsigned long) paddr,words >> 2,words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) dma[(*j)++] = MID_DT_4W | ((words >> 2) << MID_DMA_COUNT_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) | (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) paddr += (words & ~3) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) words &= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) #ifdef CONFIG_ATM_ENI_BURST_TX_2W /* probably useless if TX_4W, TX_8W, ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (words & ~1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) DPRINTK("put_dma: %lx DMA: %d*2/%d words\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) (unsigned long) paddr,words >> 1,words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) dma[(*j)++] = MID_DT_2W | ((words >> 1) << MID_DMA_COUNT_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) | (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) paddr += (words & ~1) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) words &= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (words) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) DPRINTK("put_dma: %lx DMA: %d words\n",(unsigned long) paddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) dma[(*j)++] = MID_DT_WORD | (words << MID_DMA_COUNT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) paddr += words << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) DPRINTK("put_dma: %lx DMA: %d bytes\n",(unsigned long) paddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) dma[(*j)++] = MID_DT_BYTE | (size << MID_DMA_COUNT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) (chan << MID_DMA_CHAN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) dma[(*j)++] = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static enum enq_res do_tx(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) struct eni_tx *tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) dma_addr_t paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) u32 dma_rd,dma_wr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) u32 size; /* in words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) int aal5,dma_size,i,j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) unsigned char skb_data3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) DPRINTK(">do_tx\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) NULLCHECK(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) EVENT("do_tx: skb=0x%lx, %ld bytes\n",(unsigned long) skb,skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) vcc = ATM_SKB(skb)->vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) NULLCHECK(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) NULLCHECK(eni_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) tx = eni_vcc->tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) NULLCHECK(tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) #if 0 /* Enable this for testing with the "align" program */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) unsigned int hack = *((char *) skb->data)-'0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (hack < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) skb->data += hack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) skb->len -= hack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) #if 0 /* should work now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if ((unsigned long) skb->data & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) printk(KERN_ERR DEV_LABEL "(itf %d): VCI %d has mis-aligned "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) "TX data\n",vcc->dev->number,vcc->vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * Potential future IP speedup: make hard_header big enough to put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * segmentation descriptor directly into PDU. Saves: 4 slave writes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * 1 DMA xfer & 2 DMA'ed bytes (protocol layering is for wimps :-)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) aal5 = vcc->qos.aal == ATM_AAL5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /* check space in buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (!aal5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) size = (ATM_CELL_PAYLOAD >> 2)+TX_DESCR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* cell without HEC plus segmentation header (includes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) four-byte cell header) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) size = skb->len+4*AAL5_TRAILER+ATM_CELL_PAYLOAD-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* add AAL5 trailer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) size = ((size-(size % ATM_CELL_PAYLOAD)) >> 2)+TX_DESCR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) /* add segmentation header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) * Can I move tx_pos by size bytes without getting closer than TX_GAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * to the read pointer ? TX_GAP means to leave some space for what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * the manual calls "too close".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (!NEPMOK(tx->tx_pos,size+TX_GAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) eni_in(MID_TX_RDPTR(tx->index)),tx->words)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) DPRINTK(DEV_LABEL "(itf %d): TX full (size %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) vcc->dev->number,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return enq_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) /* check DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) dma_wr = eni_in(MID_DMA_WR_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) dma_rd = eni_in(MID_DMA_RD_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) dma_size = 3; /* JK for descriptor and final fill, plus final size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) mis-alignment fix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) DPRINTK("iovcnt = %d\n",skb_shinfo(skb)->nr_frags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (!skb_shinfo(skb)->nr_frags) dma_size += 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) else dma_size += 5*(skb_shinfo(skb)->nr_frags+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (dma_size > TX_DMA_BUF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) DPRINTK("dma_wr is %d, tx_pos is %ld\n",dma_wr,tx->tx_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (dma_wr != dma_rd && ((dma_rd+NR_DMA_TX-dma_wr) & (NR_DMA_TX-1)) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) dma_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) printk(KERN_WARNING DEV_LABEL "(itf %d): TX DMA full\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) vcc->dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) return enq_jam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) skb_data3 = skb->data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) paddr = dma_map_single(&eni_dev->pci_dev->dev,skb->data,skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (dma_mapping_error(&eni_dev->pci_dev->dev, paddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return enq_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) ENI_PRV_PADDR(skb) = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /* prepare DMA queue entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) eni_dev->dma[j++] = (((tx->tx_pos+TX_DESCR_SIZE) & (tx->words-1)) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) MID_DT_JK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!skb_shinfo(skb)->nr_frags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (aal5) put_dma(tx->index,eni_dev->dma,&j,paddr,skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) else put_dma(tx->index,eni_dev->dma,&j,paddr+4,skb->len-4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) for (i = -1; i < skb_shinfo(skb)->nr_frags; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (i == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) skb_headlen(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) skb_frag_page(&skb_shinfo(skb)->frags[i]) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) skb_frag_off(&skb_shinfo(skb)->frags[i]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) skb_frag_size(&skb_shinfo(skb)->frags[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (skb->len & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) put_dma(tx->index, eni_dev->dma, &j, eni_dev->zero.dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 4 - (skb->len & 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) MID_DMA_END | MID_DT_JK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) DPRINTK("DMA at end: %d\n",j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /* store frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) writel((MID_SEG_TX_ID << MID_SEG_ID_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) (aal5 ? MID_SEG_AAL5 : 0) | (tx->prescaler << MID_SEG_PR_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) (tx->resolution << MID_SEG_RATE_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) (size/(ATM_CELL_PAYLOAD/4)),tx->send+tx->tx_pos*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) /*printk("dsc = 0x%08lx\n",(unsigned long) readl(tx->send+tx->tx_pos*4));*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) writel((vcc->vci << MID_SEG_VCI_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) (aal5 ? 0 : (skb_data3 & 0xf)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? MID_SEG_CLP : 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) tx->send+((tx->tx_pos+1) & (tx->words-1))*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) DPRINTK("size: %d, len:%d\n",size,skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (aal5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) writel(skb->len,tx->send+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) ((tx->tx_pos+size-AAL5_TRAILER) & (tx->words-1))*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) j = j >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) for (i = 0; i < j; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) writel(eni_dev->dma[i*2],eni_dev->tx_dma+dma_wr*8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) writel(eni_dev->dma[i*2+1],eni_dev->tx_dma+dma_wr*8+4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) dma_wr = (dma_wr+1) & (NR_DMA_TX-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) ENI_PRV_POS(skb) = tx->tx_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) ENI_PRV_SIZE(skb) = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) ENI_VCC(vcc)->txing += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) tx->tx_pos = (tx->tx_pos+size) & (tx->words-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) DPRINTK("dma_wr set to %d, tx_pos is now %ld\n",dma_wr,tx->tx_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) eni_out(dma_wr,MID_DMA_WR_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) skb_queue_tail(&eni_dev->tx_queue,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) queued++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) return enq_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) static void poll_tx(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct eni_tx *tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) enum enq_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) DPRINTK(">poll_tx\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) for (i = NR_CHAN-1; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) tx = &ENI_DEV(dev)->tx[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (tx->send)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) while ((skb = skb_dequeue(&tx->backlog))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) res = do_tx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (res == enq_ok) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) DPRINTK("re-queuing TX PDU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) skb_queue_head(&tx->backlog,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) requeued++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (res == enq_jam) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static void dequeue_tx(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) struct eni_tx *tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) NULLCHECK(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) NULLCHECK(eni_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) while ((skb = skb_dequeue(&eni_dev->tx_queue))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) vcc = ATM_SKB(skb)->vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) NULLCHECK(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) tx = ENI_VCC(vcc)->tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) NULLCHECK(ENI_VCC(vcc)->tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) DPRINTK("dequeue_tx: next 0x%lx curr 0x%x\n",ENI_PRV_POS(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) (unsigned) eni_in(MID_TX_DESCRSTART(tx->index)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (ENI_VCC(vcc)->txing < tx->words && ENI_PRV_POS(skb) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) eni_in(MID_TX_DESCRSTART(tx->index))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) skb_queue_head(&eni_dev->tx_queue,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ENI_VCC(vcc)->txing -= ENI_PRV_SIZE(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) dma_unmap_single(&eni_dev->pci_dev->dev,ENI_PRV_PADDR(skb),skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (vcc->pop) vcc->pop(vcc,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) else dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) atomic_inc(&vcc->stats->tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) wake_up(&eni_dev->tx_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) dma_complete++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) static struct eni_tx *alloc_tx(struct eni_dev *eni_dev,int ubr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) for (i = !ubr; i < NR_CHAN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (!eni_dev->tx[i].send) return eni_dev->tx+i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) static int comp_tx(struct eni_dev *eni_dev,int *pcr,int reserved,int *pre,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) int *res,int unlimited)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) static const int pre_div[] = { 4,16,128,2048 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /* 2^(((x+2)^2-(x+2))/2+1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (unlimited) *pre = *res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (*pcr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) for (*pre = 0; *pre < 3; (*pre)++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (TS_CLOCK/pre_div[*pre]/64 <= *pcr) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) div = pre_div[*pre]**pcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) DPRINTK("min div %d\n",div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) *res = TS_CLOCK/div-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (!*pcr) *pcr = eni_dev->tx_bw+reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) for (*pre = 3; *pre >= 0; (*pre)--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (TS_CLOCK/pre_div[*pre]/64 > -*pcr) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (*pre < 3) (*pre)++; /* else fail later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) div = pre_div[*pre]*-*pcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) DPRINTK("max div %d\n",div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) *res = DIV_ROUND_UP(TS_CLOCK, div)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (*res < 0) *res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (*res > MID_SEG_MAX_RATE) *res = MID_SEG_MAX_RATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) *pcr = TS_CLOCK/pre_div[*pre]/(*res+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) DPRINTK("out pcr: %d (%d:%d)\n",*pcr,*pre,*res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) int set_rsv,int set_shp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) struct eni_vcc *eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) struct eni_tx *tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) void __iomem *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) int rate,ubr,unlimited,new_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) int pre,res,order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) rate = atm_pcr_goal(txtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ubr = txtp->traffic_class == ATM_UBR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) unlimited = ubr && (!rate || rate <= -ATM_OC3_PCR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) rate >= ATM_OC3_PCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (!unlimited) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) size = txtp->max_sdu*eni_dev->tx_mult/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (size > MID_MAX_BUF_SIZE && txtp->max_sdu <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) MID_MAX_BUF_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) size = MID_MAX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (eni_dev->ubr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) eni_vcc->tx = eni_dev->ubr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) txtp->pcr = ATM_OC3_PCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) size = UBR_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) new_tx = !eni_vcc->tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) mem = NULL; /* for gcc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (!new_tx) tx = eni_vcc->tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) mem = eni_alloc_mem(eni_dev,&size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (!mem) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) tx = alloc_tx(eni_dev,unlimited);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (!tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) eni_free_mem(eni_dev,mem,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) DPRINTK("got chan %d\n",tx->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) tx->reserved = tx->shaping = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) tx->send = mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) tx->words = size >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) skb_queue_head_init(&tx->backlog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) for (order = 0; size > (1 << (order+10)); order++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) eni_out((order << MID_SIZE_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) MID_TX_PLACE(tx->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) tx->tx_pos = eni_in(MID_TX_DESCRSTART(tx->index)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) MID_DESCR_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) error = comp_tx(eni_dev,&rate,tx->reserved,&pre,&res,unlimited);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (!error && txtp->min_pcr > rate) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (!error && txtp->max_pcr && txtp->max_pcr != ATM_MAX_PCR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) txtp->max_pcr < rate) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if (!error && !ubr && rate > eni_dev->tx_bw+tx->reserved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (!error && set_rsv && !set_shp && rate < tx->shaping)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (!error && !set_rsv && rate > tx->reserved && !ubr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (new_tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) tx->send = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) eni_free_mem(eni_dev,mem,size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) txtp->pcr = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (set_rsv && !ubr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) eni_dev->tx_bw += tx->reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) tx->reserved = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) eni_dev->tx_bw -= rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (set_shp || (unlimited && new_tx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (unlimited && new_tx) eni_dev->ubr = tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) tx->prescaler = pre;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) tx->resolution = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) tx->shaping = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (set_shp) eni_vcc->tx = tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) DPRINTK("rsv %d shp %d\n",tx->reserved,tx->shaping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) static int open_tx_first(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) ENI_VCC(vcc)->tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) ENI_VCC(vcc)->txing = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) return reserve_or_set_tx(vcc,&vcc->qos.txtp,1,1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) static int open_tx_second(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) return 0; /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) static void close_tx(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) DECLARE_WAITQUEUE(wait,current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (!eni_vcc->tx) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) /* wait for TX queue to drain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) DPRINTK("eni_close: waiting for TX ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) add_wait_queue(&eni_dev->tx_wait,&wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) int txing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) tasklet_disable(&eni_dev->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) txing = skb_peek(&eni_vcc->tx->backlog) || eni_vcc->txing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) tasklet_enable(&eni_dev->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (!txing) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) DPRINTK("%d TX left\n",eni_vcc->txing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) remove_wait_queue(&eni_dev->tx_wait,&wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (eni_vcc->tx != eni_dev->ubr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * Looping a few times in here is probably far cheaper than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) * keeping track of TX completions all the time, so let's poll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * a bit ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) eni_vcc->tx->send = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) eni_dev->tx_bw += eni_vcc->tx->reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) eni_vcc->tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) static int start_tx(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) eni_dev->lost = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) eni_dev->tx_bw = ATM_OC3_PCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) eni_dev->tx_mult = DEFAULT_TX_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) init_waitqueue_head(&eni_dev->tx_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) eni_dev->ubr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) skb_queue_head_init(&eni_dev->tx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) eni_out(0,MID_DMA_WR_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) for (i = 0; i < NR_CHAN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) eni_dev->tx[i].send = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) eni_dev->tx[i].index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) /*--------------------------------- common ----------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) #if 0 /* may become useful again when tuning things */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) static void foo(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) "tx_complete=%d,dma_complete=%d,queued=%d,requeued=%d,sub=%d,\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) "backlogged=%d,rx_enqueued=%d,rx_dequeued=%d,putting=%d,pushed=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) tx_complete,dma_complete,queued,requeued,submitted,backlogged,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) rx_enqueued,rx_dequeued,putting,pushed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) static void bug_int(struct atm_dev *dev,unsigned long reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) DPRINTK(">bug_int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) if (reason & MID_DMA_ERR_ACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) "error\n",dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if (reason & MID_TX_IDENT_MISM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - ident "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) "mismatch\n",dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (reason & MID_TX_DMA_OVFL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) "overflow\n",dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) EVENT("---dump ends here---\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) printk(KERN_NOTICE "---recent events---\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) event_dump();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) static irqreturn_t eni_int(int irq,void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) struct atm_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) u32 reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) DPRINTK(">eni_int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) reason = eni_in(MID_ISA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) DPRINTK(DEV_LABEL ": int 0x%lx\n",(unsigned long) reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) * Must handle these two right now, because reading ISA doesn't clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) * them, so they re-occur and we never make it to the tasklet. Since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) * they're rare, we don't mind the occasional invocation of eni_tasklet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) * with eni_dev->events == 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) if (reason & MID_STAT_OVFL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) EVENT("stat overflow\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (reason & MID_SUNI_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) EVENT("SUNI int\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) dev->phy->interrupt(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) foo();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) spin_lock(&eni_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) eni_dev->events |= reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) spin_unlock(&eni_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) tasklet_schedule(&eni_dev->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) static void eni_tasklet(unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) struct atm_dev *dev = (struct atm_dev *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct eni_dev *eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) u32 events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) DPRINTK("eni_tasklet (dev %p)\n",dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) spin_lock_irqsave(&eni_dev->lock,flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) events = xchg(&eni_dev->events,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) spin_unlock_irqrestore(&eni_dev->lock,flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) if (events & MID_RX_DMA_COMPLETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) EVENT("INT: RX DMA complete, starting dequeue_rx\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) dequeue_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) EVENT("dequeue_rx done, starting poll_rx\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) poll_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) EVENT("poll_rx done\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) /* poll_tx ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) if (events & MID_SERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) EVENT("INT: service, starting get_service\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) get_service(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) EVENT("get_service done, starting poll_rx\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) poll_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) EVENT("poll_rx done\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (events & MID_TX_DMA_COMPLETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) EVENT("INT: TX DMA COMPLETE\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) dequeue_tx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if (events & MID_TX_COMPLETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) EVENT("INT: TX COMPLETE\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) tx_complete++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) wake_up(&eni_dev->tx_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) /* poll_rx ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (events & (MID_DMA_ERR_ACK | MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) EVENT("bug interrupt\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) bug_int(dev,events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) poll_tx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) /*--------------------------------- entries ---------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) static char * const media_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) "MMF", "SMF", "MMF", "03?", /* 0- 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) "UTP", "05?", "06?", "07?", /* 4- 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) "TAXI","09?", "10?", "11?", /* 8-11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) "12?", "13?", "14?", "15?", /* 12-15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) "MMF", "SMF", "18?", "19?", /* 16-19 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) "UTP", "21?", "22?", "23?", /* 20-23 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) "24?", "25?", "26?", "27?", /* 24-27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) "28?", "29?", "30?", "31?" /* 28-31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) #define SET_SEPROM \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) ({ if (!error && !pci_error) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) pci_error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,tonga); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) udelay(10); /* 10 usecs */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) } })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) #define GET_SEPROM \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) ({ if (!error && !pci_error) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) pci_error = pci_read_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,&tonga); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) udelay(10); /* 10 usecs */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) } })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) static int get_esi_asic(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) unsigned char tonga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) int error,failed,pci_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) int address,i,j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) error = pci_error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) tonga = SEPROM_MAGIC | SEPROM_DATA | SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) for (i = 0; i < ESI_LEN && !error && !pci_error; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) /* start operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) tonga |= SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) tonga &= ~SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) tonga &= ~SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) /* send address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) address = ((i+SEPROM_ESI_BASE) << 1)+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) for (j = 7; j >= 0; j--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) tonga = (address >> j) & 1 ? tonga | SEPROM_DATA :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) tonga & ~SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) tonga |= SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) tonga &= ~SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) /* get ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) tonga |= SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) GET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) failed = tonga & SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) tonga &= ~SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) if (failed) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) dev->esi[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) for (j = 7; j >= 0; j--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) dev->esi[i] <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) tonga |= SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) GET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) if (tonga & SEPROM_DATA) dev->esi[i] |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) tonga &= ~SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) /* get ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) tonga |= SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) GET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (!(tonga & SEPROM_DATA)) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) tonga &= ~SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) /* stop operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) tonga &= ~SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) tonga |= SEPROM_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) tonga |= SEPROM_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) SET_SEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (pci_error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) printk(KERN_ERR DEV_LABEL "(itf %d): error reading ESI "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) "(0x%02x)\n",dev->number,pci_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) #undef SET_SEPROM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) #undef GET_SEPROM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) static int get_esi_fpga(struct atm_dev *dev, void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) void __iomem *mac_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) for (i = 0; i < ESI_LEN; i++) dev->esi[i] = readb(mac_base+(i^3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) static int eni_do_init(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) struct midway_eprom __iomem *eprom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) struct pci_dev *pci_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) unsigned long real_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) int error,i,last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) DPRINTK(">eni_init\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) dev->ci_range.vpi_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) dev->ci_range.vci_bits = NR_VCI_LD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) dev->link_rate = ATM_OC3_PCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) pci_dev = eni_dev->pci_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) real_base = pci_resource_start(pci_dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) eni_dev->irq = pci_dev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if ((error = pci_write_config_word(pci_dev,PCI_COMMAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) PCI_COMMAND_MEMORY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) "(0x%02x)\n",dev->number,error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) dev->number,pci_dev->revision,real_base,eni_dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (!(base = ioremap(real_base,MAP_MAX_SIZE))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) "mapping\n",dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) eni_dev->ioaddr = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) eni_dev->base_diff = real_base - (unsigned long) base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) /* id may not be present in ASIC Tonga boards - check this @@@ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (!eni_dev->asic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) eprom = (base+EPROM_SIZE-sizeof(struct midway_eprom));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) if (readl(&eprom->magic) != ENI155_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) printk(KERN_ERR DEV_LABEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) "(itf %d): bad magic - expected 0x%x, got 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) dev->number, ENI155_MAGIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) (unsigned)readl(&eprom->magic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) eni_dev->phy = base+PHY_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) eni_dev->reg = base+REG_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) eni_dev->ram = base+RAM_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) last = MAP_MAX_SIZE-RAM_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) writel(0x55555555,eni_dev->ram+i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (readl(eni_dev->ram+i) != 0x55555555) last = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) writel(0xAAAAAAAA,eni_dev->ram+i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (readl(eni_dev->ram+i) != 0xAAAAAAAA) last = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) else writel(i,eni_dev->ram+i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) for (i = 0; i < last; i += RAM_INCREMENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) if (readl(eni_dev->ram+i) != i) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) eni_dev->mem = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) memset_io(eni_dev->ram,0,eni_dev->mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) /* TODO: should shrink allocation now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) printk("mem=%dkB (",eni_dev->mem >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) /* TODO: check for non-SUNI, check for TAXI ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (!(eni_in(MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) printk(")\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) dev->number,(unsigned) eni_in(MID_RES_ID_MCON));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) error = eni_dev->asic ? get_esi_asic(dev) : get_esi_fpga(dev,base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) for (i = 0; i < ESI_LEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) printk("%s%02X",i ? "-" : "",dev->esi[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) printk(")\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) printk(KERN_NOTICE DEV_LABEL "(itf %d): %s,%s\n",dev->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) eni_in(MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) media_name[eni_in(MID_RES_ID_MCON) & DAUGHTER_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) error = suni_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) iounmap(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) static void eni_do_release(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) struct eni_dev *ed = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) dev->phy->stop(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) dev->phy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) iounmap(ed->ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) static int eni_start(struct atm_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) void __iomem *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) unsigned long buffer_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) DPRINTK(">eni_start\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) if (request_irq(eni_dev->irq,&eni_int,IRQF_SHARED,DEV_LABEL,dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) dev->number,eni_dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) error = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) pci_set_master(eni_dev->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) "master (0x%02x)\n",dev->number,error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) goto free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) END_SWAP_DMA))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) "(0x%02x)\n",dev->number,error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) goto free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) /* determine addresses of internal tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) eni_dev->vci = eni_dev->ram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) eni_dev->rx_dma = eni_dev->ram+NR_VCI*16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) buf = eni_dev->service+NR_SERVICE*4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) DPRINTK("vci 0x%lx,rx 0x%lx, tx 0x%lx,srv 0x%lx,buf 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) eni_dev->service,buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) spin_lock_init(&eni_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) eni_dev->events = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) /* initialize memory management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) eni_dev->free_list = kmalloc_array(eni_dev->free_list_size + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) sizeof(*eni_dev->free_list),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) if (!eni_dev->free_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) goto free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) eni_dev->free_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) eni_put_free(eni_dev,buf,buffer_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) memset_io(eni_dev->vci,0,16*NR_VCI); /* clear VCI table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) * byte_addr free (k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) * 0x00000000 512 VCI table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) * 0x00004000 496 RX DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) * 0x00005000 492 TX DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) * 0x00006000 488 service list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) * 0x00007000 484 buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) * 0x00080000 0 end (512kB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) eni_out(0xffffffff,MID_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) error = start_tx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) if (error) goto free_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) error = start_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if (error) goto free_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) error = dev->phy->start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) if (error) goto free_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) MID_MC_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) /* Tonga uses SBus INTReq1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) (void) eni_in(MID_ISA); /* clear Midway interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) free_list:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) kfree(eni_dev->free_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) free_irq(eni_dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) static void eni_close(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) DPRINTK(">eni_close\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) if (!ENI_VCC(vcc)) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) clear_bit(ATM_VF_READY,&vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) close_rx(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) close_tx(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) DPRINTK("eni_close: done waiting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) /* deallocate memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) kfree(ENI_VCC(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) vcc->dev_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) clear_bit(ATM_VF_ADDR,&vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) /*foo();*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) static int eni_open(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) short vpi = vcc->vpi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) int vci = vcc->vci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) DPRINTK(">eni_open\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) EVENT("eni_open\n",0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) vcc->dev_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) set_bit(ATM_VF_ADDR,&vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) vcc->vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) eni_vcc = kmalloc(sizeof(struct eni_vcc),GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) if (!eni_vcc) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) vcc->dev_data = eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) eni_vcc->tx = NULL; /* for eni_close after open_rx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) if ((error = open_rx_first(vcc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) eni_close(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) if ((error = open_tx_first(vcc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) eni_close(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) if (vci == ATM_VPI_UNSPEC || vpi == ATM_VCI_UNSPEC) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) if ((error = open_rx_second(vcc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) eni_close(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) if ((error = open_tx_second(vcc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) eni_close(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) set_bit(ATM_VF_READY,&vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) /* should power down SUNI while !ref_count @@@ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) struct eni_tx *tx = ENI_VCC(vcc)->tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) int error,rate,rsv,shp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) if (qos->txtp.traffic_class == ATM_NONE) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) if (tx == eni_dev->ubr) return -EBADFD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) rate = atm_pcr_goal(&qos->txtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) if (rate < 0) rate = -rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) rsv = shp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) if ((flgs & ATM_MF_DEC_RSV) && rate && rate < tx->reserved) rsv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) if ((flgs & ATM_MF_INC_RSV) && (!rate || rate > tx->reserved)) rsv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) if ((flgs & ATM_MF_DEC_SHP) && rate && rate < tx->shaping) shp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if ((flgs & ATM_MF_INC_SHP) && (!rate || rate > tx->shaping)) shp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) if (!rsv && !shp) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) error = reserve_or_set_tx(vcc,&qos->txtp,rsv,shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) if (error) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) if (shp && !(flgs & ATM_MF_IMMED)) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) * Walk through the send buffer and patch the rate information in all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) * segmentation buffer descriptors of this VCC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) tasklet_disable(&eni_dev->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) skb_queue_walk(&eni_dev->tx_queue, skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) void __iomem *dsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) if (ATM_SKB(skb)->vcc != vcc) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) dsc = tx->send+ENI_PRV_POS(skb)*4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) writel((readl(dsc) & ~(MID_SEG_RATE | MID_SEG_PR)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) (tx->prescaler << MID_SEG_PR_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) (tx->resolution << MID_SEG_RATE_SHIFT), dsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) tasklet_enable(&eni_dev->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) static int eni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) struct eni_dev *eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (cmd == ENI_MEMDUMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) if (!capable(CAP_NET_ADMIN)) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) printk(KERN_WARNING "Please use /proc/atm/" DEV_LABEL ":%d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) "instead of obsolete ioctl ENI_MEMDUMP\n",dev->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) dump(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) if (cmd == ENI_SETMULT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) struct eni_multipliers mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) if (!capable(CAP_NET_ADMIN)) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) if (copy_from_user(&mult, arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) sizeof(struct eni_multipliers)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) if ((mult.tx && mult.tx <= 100) || (mult.rx &&mult.rx <= 100) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) mult.tx > 65536 || mult.rx > 65536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) if (mult.tx) eni_dev->tx_mult = mult.tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) if (mult.rx) eni_dev->rx_mult = mult.rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) if (cmd == ATM_SETCIRANGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) struct atm_cirange ci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) if (copy_from_user(&ci, arg,sizeof(struct atm_cirange)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) if ((ci.vpi_bits == 0 || ci.vpi_bits == ATM_CI_MAX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) (ci.vci_bits == NR_VCI_LD || ci.vpi_bits == ATM_CI_MAX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) if (!dev->phy->ioctl) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) return dev->phy->ioctl(dev,cmd,arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) enum enq_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) DPRINTK(">eni_send\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) if (!ENI_VCC(vcc)->tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) if (vcc->pop) vcc->pop(vcc,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) else dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) printk(KERN_CRIT "!skb in eni_send ?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) if (vcc->pop) vcc->pop(vcc,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) if (vcc->qos.aal == ATM_AAL0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) if (skb->len != ATM_CELL_SIZE-1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) if (vcc->pop) vcc->pop(vcc,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) else dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) *(u32 *) skb->data = htonl(*(u32 *) skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) submitted++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) ATM_SKB(skb)->vcc = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) tasklet_disable(&ENI_DEV(vcc->dev)->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) res = do_tx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) tasklet_enable(&ENI_DEV(vcc->dev)->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) if (res == enq_ok) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) backlogged++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) tasklet_schedule(&ENI_DEV(vcc->dev)->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) static void eni_phy_put(struct atm_dev *dev,unsigned char value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) writel(value,ENI_DEV(dev)->phy+addr*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) return readl(ENI_DEV(dev)->phy+addr*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) struct sock *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) static const char *signal[] = { "LOST","unknown","okay" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) struct eni_dev *eni_dev = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) int left,i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) left = *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) if (!left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) return sprintf(page,DEV_LABEL "(itf %d) signal %s, %dkB, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) "%d cps remaining\n",dev->number,signal[(int) dev->signal],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) eni_dev->mem >> 10,eni_dev->tx_bw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) if (!--left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) return sprintf(page,"%4sBursts: TX"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) #if !defined(CONFIG_ATM_ENI_BURST_TX_16W) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) !defined(CONFIG_ATM_ENI_BURST_TX_8W) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) !defined(CONFIG_ATM_ENI_BURST_TX_4W) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) !defined(CONFIG_ATM_ENI_BURST_TX_2W)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) " none"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) #ifdef CONFIG_ATM_ENI_BURST_TX_16W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) " 16W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) #ifdef CONFIG_ATM_ENI_BURST_TX_8W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) " 8W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) #ifdef CONFIG_ATM_ENI_BURST_TX_4W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) " 4W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) #ifdef CONFIG_ATM_ENI_BURST_TX_2W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) " 2W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) ", RX"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) #if !defined(CONFIG_ATM_ENI_BURST_RX_16W) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) !defined(CONFIG_ATM_ENI_BURST_RX_8W) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) !defined(CONFIG_ATM_ENI_BURST_RX_4W) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) !defined(CONFIG_ATM_ENI_BURST_RX_2W)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) " none"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) #ifdef CONFIG_ATM_ENI_BURST_RX_16W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) " 16W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) #ifdef CONFIG_ATM_ENI_BURST_RX_8W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) " 8W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) #ifdef CONFIG_ATM_ENI_BURST_RX_4W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) " 4W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) #ifdef CONFIG_ATM_ENI_BURST_RX_2W
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) " 2W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) #ifndef CONFIG_ATM_ENI_TUNE_BURST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) " (default)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) "\n","");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) if (!--left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) return sprintf(page,"%4sBuffer multipliers: tx %d%%, rx %d%%\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) "",eni_dev->tx_mult,eni_dev->rx_mult);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) for (i = 0; i < NR_CHAN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) struct eni_tx *tx = eni_dev->tx+i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) if (!tx->send) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) if (!--left) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) return sprintf(page, "tx[%d]: 0x%lx-0x%lx "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) (unsigned long) (tx->send - eni_dev->ram),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) tx->reserved,tx->shaping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) tx == eni_dev->ubr ? " (UBR)" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) if (--left) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) return sprintf(page,"%10sbacklog %u packets\n","",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) skb_queue_len(&tx->backlog));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) read_lock(&vcc_sklist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) struct hlist_head *head = &vcc_hash[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) sk_for_each(s, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) struct eni_vcc *eni_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) vcc = atm_sk(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) if (vcc->dev != dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) eni_vcc = ENI_VCC(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) if (--left) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) length = sprintf(page,"vcc %4d: ",vcc->vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) if (eni_vcc->rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) length += sprintf(page+length, "0x%lx-0x%lx "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) "(%6ld bytes)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) (unsigned long) (eni_vcc->recv - eni_dev->ram),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) eni_vcc->words*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) if (eni_vcc->tx) length += sprintf(page+length,", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) if (eni_vcc->tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) length += sprintf(page+length,"tx[%d], txing %d bytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) eni_vcc->tx->index,eni_vcc->txing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) page[length] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) read_unlock(&vcc_sklist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) return length+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) read_unlock(&vcc_sklist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) for (i = 0; i < eni_dev->free_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) struct eni_free *fe = eni_dev->free_list+i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) if (--left) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) offset = (unsigned long) eni_dev->ram+eni_dev->base_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) return sprintf(page,"free %p-%p (%6d bytes)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) fe->start-offset,fe->start-offset+(1 << fe->order)-1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) 1 << fe->order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) static const struct atmdev_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) .open = eni_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) .close = eni_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) .ioctl = eni_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) .send = eni_send,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) .phy_put = eni_phy_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) .phy_get = eni_phy_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) .change_qos = eni_change_qos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) .proc_read = eni_proc_read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) static int eni_init_one(struct pci_dev *pci_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) struct atm_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) struct eni_dev *eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) struct eni_zero *zero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) rc = pci_enable_device(pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) goto err_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) if (!eni_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) goto err_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) zero = &eni_dev->zero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) zero->addr = dma_alloc_coherent(&pci_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) ENI_ZEROES_SIZE, &zero->dma, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) if (!zero->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) goto err_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) goto err_free_consistent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) dev->dev_data = eni_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) pci_set_drvdata(pci_dev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) eni_dev->pci_dev = pci_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) eni_dev->asic = ent->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) rc = eni_do_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) goto err_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) rc = eni_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) goto err_eni_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) eni_dev->more = eni_boards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) eni_boards = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) err_eni_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) dev->phy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) iounmap(ENI_DEV(dev)->ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) err_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) atm_dev_deregister(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) err_free_consistent:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) dma_free_coherent(&pci_dev->dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) err_kfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) kfree(eni_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) err_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) pci_disable_device(pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) static const struct pci_device_id eni_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_FPGA), 0 /* FPGA */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_ASIC), 1 /* ASIC */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) static void eni_remove_one(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) struct atm_dev *dev = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) struct eni_dev *ed = ENI_DEV(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) struct eni_zero *zero = &ed->zero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) eni_do_release(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) atm_dev_deregister(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) dma_free_coherent(&pdev->dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) kfree(ed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) static struct pci_driver eni_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) .name = DEV_LABEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) .id_table = eni_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) .probe = eni_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) .remove = eni_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) static int __init eni_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) struct sk_buff *skb; /* dummy for sizeof */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct eni_skb_prv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) return pci_register_driver(&eni_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) module_init(eni_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) /* @@@ since exit routine not defined, this module can not be unloaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) MODULE_LICENSE("GPL");