brintos

brintos / linux-shallow public Read only

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