1 diff -urN linux-2.4.20/arch/alpha/config.in linux-2.4.20-atm/arch/alpha/config.in
2 --- linux-2.4.20/arch/alpha/config.in Wed May 28 01:53:41 2003
3 +++ linux-2.4.20-atm/arch/alpha/config.in Wed May 28 01:58:41 2003
5 bool 'Network device support' CONFIG_NETDEVICES
6 if [ "$CONFIG_NETDEVICES" = "y" ]; then
7 source drivers/net/Config.in
8 - if [ "$CONFIG_ATM" = "y" ]; then
9 + if [ "$CONFIG_ATM" != "n" ]; then
10 source drivers/atm/Config.in
13 diff -urN linux-2.4.20/arch/cris/config.in linux-2.4.20-atm/arch/cris/config.in
14 --- linux-2.4.20/arch/cris/config.in Wed May 28 01:53:41 2003
15 +++ linux-2.4.20-atm/arch/cris/config.in Wed May 28 01:58:41 2003
17 bool 'Network device support' CONFIG_NETDEVICES
18 if [ "$CONFIG_NETDEVICES" = "y" ]; then
19 source drivers/net/Config.in
20 - if [ "$CONFIG_ATM" = "y" ]; then
21 + if [ "$CONFIG_ATM" != "n" ]; then
22 source drivers/atm/Config.in
25 diff -urN linux-2.4.20/arch/i386/config.in linux-2.4.20-atm/arch/i386/config.in
26 --- linux-2.4.20/arch/i386/config.in Wed May 28 01:53:41 2003
27 +++ linux-2.4.20-atm/arch/i386/config.in Wed May 28 01:58:41 2003
29 bool 'Network device support' CONFIG_NETDEVICES
30 if [ "$CONFIG_NETDEVICES" = "y" ]; then
31 source drivers/net/Config.in
32 - if [ "$CONFIG_ATM" = "y" ]; then
33 + if [ "$CONFIG_ATM" != "n" ]; then
34 source drivers/atm/Config.in
37 diff -urN linux-2.4.20/arch/parisc/config.in linux-2.4.20-atm/arch/parisc/config.in
38 --- linux-2.4.20/arch/parisc/config.in Fri Nov 29 00:53:10 2002
39 +++ linux-2.4.20-atm/arch/parisc/config.in Wed May 28 01:58:41 2003
42 if [ "$CONFIG_NETDEVICES" = "y" ]; then
43 source drivers/net/Config.in
44 - if [ "$CONFIG_ATM" = "y" ]; then
45 + if [ "$CONFIG_ATM" != "n" ]; then
46 source drivers/atm/Config.in
49 diff -urN linux-2.4.20/arch/ppc/config.in linux-2.4.20-atm/arch/ppc/config.in
50 --- linux-2.4.20/arch/ppc/config.in Wed May 28 01:53:43 2003
51 +++ linux-2.4.20-atm/arch/ppc/config.in Wed May 28 01:58:41 2003
53 bool 'Network device support' CONFIG_NETDEVICES
54 if [ "$CONFIG_NETDEVICES" = "y" ]; then
55 source drivers/net/Config.in
56 - if [ "$CONFIG_ATM" = "y" ]; then
57 + if [ "$CONFIG_ATM" != "n" ]; then
58 source drivers/atm/Config.in
61 diff -urN linux-2.4.20/arch/ppc64/config.in linux-2.4.20-atm/arch/ppc64/config.in
62 --- linux-2.4.20/arch/ppc64/config.in Wed May 28 01:53:44 2003
63 +++ linux-2.4.20-atm/arch/ppc64/config.in Wed May 28 01:58:41 2003
65 bool 'Network device support' CONFIG_NETDEVICES
66 if [ "$CONFIG_NETDEVICES" = "y" ]; then
67 source drivers/net/Config.in
68 - if [ "$CONFIG_ATM" = "y" ]; then
69 + if [ "$CONFIG_ATM" != "n" ]; then
70 source drivers/atm/Config.in
73 diff -urN linux-2.4.20/arch/sh/config.in linux-2.4.20-atm/arch/sh/config.in
74 --- linux-2.4.20/arch/sh/config.in Wed May 28 01:53:44 2003
75 +++ linux-2.4.20-atm/arch/sh/config.in Wed May 28 01:58:41 2003
77 bool 'Network device support' CONFIG_NETDEVICES
78 if [ "$CONFIG_NETDEVICES" = "y" ]; then
79 source drivers/net/Config.in
80 - if [ "$CONFIG_ATM" = "y" ]; then
81 + if [ "$CONFIG_ATM" != "n" ]; then
82 source drivers/atm/Config.in
85 diff -urN linux-2.4.20/arch/sparc/config.in linux-2.4.20-atm/arch/sparc/config.in
86 --- linux-2.4.20/arch/sparc/config.in Wed May 28 01:53:44 2003
87 +++ linux-2.4.20-atm/arch/sparc/config.in Wed May 28 01:58:41 2003
89 dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
90 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
91 dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
92 - if [ "$CONFIG_ATM" = "y" ]; then
93 + if [ "$CONFIG_ATM" != "n" ]; then
94 dep_tristate ' PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP
98 # if [ "$CONFIG_FDDI" = "y" ]; then
101 - if [ "$CONFIG_ATM" = "y" ]; then
102 + if [ "$CONFIG_ATM" != "n" ]; then
103 source drivers/atm/Config.in
106 diff -urN linux-2.4.20/arch/sparc64/config.in linux-2.4.20-atm/arch/sparc64/config.in
107 --- linux-2.4.20/arch/sparc64/config.in Fri Nov 29 00:53:12 2002
108 +++ linux-2.4.20-atm/arch/sparc64/config.in Wed May 28 01:58:41 2003
110 bool 'Network device support' CONFIG_NETDEVICES
111 if [ "$CONFIG_NETDEVICES" = "y" ]; then
112 source drivers/net/Config.in
113 - if [ "$CONFIG_ATM" = "y" ]; then
114 + if [ "$CONFIG_ATM" != "n" ]; then
115 source drivers/atm/Config.in
118 diff -urN linux-2.4.20/arch/x86_64/config.in linux-2.4.20-atm/arch/x86_64/config.in
119 --- linux-2.4.20/arch/x86_64/config.in Wed May 28 01:53:44 2003
120 +++ linux-2.4.20-atm/arch/x86_64/config.in Wed May 28 01:58:41 2003
122 bool 'Network device support' CONFIG_NETDEVICES
123 if [ "$CONFIG_NETDEVICES" = "y" ]; then
124 source drivers/net/Config.in
125 -# seems to be largely not 64bit safe
126 -# if [ "$CONFIG_ATM" = "y" ]; then
127 -# source drivers/atm/Config.in
129 + if [ "$CONFIG_ATM" != "n" ]; then
130 + source drivers/atm/Config.in
135 diff -urN linux-2.4.20/drivers/atm/Config.in linux-2.4.20-atm/drivers/atm/Config.in
136 --- linux-2.4.20/drivers/atm/Config.in Tue Nov 13 18:19:41 2001
137 +++ linux-2.4.20-atm/drivers/atm/Config.in Wed May 28 01:58:41 2003
139 mainmenu_option next_comment
140 comment 'ATM drivers'
141 if [ "$CONFIG_INET" = "y" ]; then
142 - tristate 'ATM over TCP' CONFIG_ATM_TCP
143 + dep_tristate 'ATM over TCP' CONFIG_ATM_TCP $CONFIG_ATM
145 if [ "$CONFIG_PCI" = "y" ]; then
146 - tristate 'Efficient Networks Speedstream 3010' CONFIG_ATM_LANAI
147 - tristate 'Efficient Networks ENI155P' CONFIG_ATM_ENI
148 + dep_tristate 'Efficient Networks Speedstream 3010' CONFIG_ATM_LANAI $CONFIG_ATM
149 + dep_tristate 'Efficient Networks ENI155P' CONFIG_ATM_ENI $CONFIG_ATM
150 if [ "$CONFIG_ATM_ENI" != "n" ]; then
151 bool ' Enable extended debugging' CONFIG_ATM_ENI_DEBUG
152 bool ' Fine-tune burst settings' CONFIG_ATM_ENI_TUNE_BURST
154 bool ' Enable 2W RX bursts (optional)' CONFIG_ATM_ENI_BURST_RX_2W
157 - tristate 'Fujitsu FireStream (FS50/FS155) ' CONFIG_ATM_FIRESTREAM
158 - tristate 'ZeitNet ZN1221/ZN1225' CONFIG_ATM_ZATM
159 + dep_tristate 'Fujitsu FireStream (FS50/FS155) ' CONFIG_ATM_FIRESTREAM $CONFIG_ATM
160 + dep_tristate 'ZeitNet ZN1221/ZN1225' CONFIG_ATM_ZATM $CONFIG_ATM
161 if [ "$CONFIG_ATM_ZATM" != "n" ]; then
162 bool ' Enable extended debugging' CONFIG_ATM_ZATM_DEBUG
163 if [ "$CONFIG_X86" = "y" ]; then
165 # if [ "$CONFIG_ATM_TNETA1570" = "y" ]; then
166 # bool ' Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n
168 - tristate 'IDT 77201 (NICStAR) (ForeRunnerLE)' CONFIG_ATM_NICSTAR
169 + dep_tristate 'IDT 77201 (NICStAR) (ForeRunnerLE)' CONFIG_ATM_NICSTAR $CONFIG_ATM
170 if [ "$CONFIG_ATM_NICSTAR" != "n" ]; then
171 bool ' Use suni PHY driver (155Mbps)' CONFIG_ATM_NICSTAR_USE_SUNI
172 bool ' Use IDT77015 PHY driver (25Mbps)' CONFIG_ATM_NICSTAR_USE_IDT77105
174 - tristate 'IDT 77252 (NICStAR II)' CONFIG_ATM_IDT77252
175 + dep_tristate 'IDT 77252 (NICStAR II)' CONFIG_ATM_IDT77252 $CONFIG_ATM
176 if [ "$CONFIG_ATM_IDT77252" != "n" ]; then
177 bool ' Enable debugging messages' CONFIG_ATM_IDT77252_DEBUG
178 bool ' Receive ALL cells in raw queue' CONFIG_ATM_IDT77252_RCV_ALL
179 define_bool CONFIG_ATM_IDT77252_USE_SUNI y
181 - tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR
182 + dep_tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR $CONFIG_ATM
183 if [ "$CONFIG_ATM_AMBASSADOR" != "n" ]; then
184 bool ' Enable debugging messages' CONFIG_ATM_AMBASSADOR_DEBUG
186 - tristate 'Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)' CONFIG_ATM_HORIZON
187 + dep_tristate 'Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)' CONFIG_ATM_HORIZON $CONFIG_ATM
188 if [ "$CONFIG_ATM_HORIZON" != "n" ]; then
189 bool ' Enable debugging messages' CONFIG_ATM_HORIZON_DEBUG
191 - tristate 'Interphase ATM PCI x575/x525/x531' CONFIG_ATM_IA
192 - if [ "$CONFIG_ATM_IA" != "n" ]; then
193 - bool ' Enable debugging messages' CONFIG_ATM_IA_DEBUG
195 + dep_tristate 'Interphase ATM PCI x575/x525/x531' CONFIG_ATM_IA $CONFIG_ATM
196 + if [ "$CONFIG_ATM_IA" != "n" ]; then
197 + bool ' Enable debugging messages' CONFIG_ATM_IA_DEBUG
200 if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBUS" = "y" ]; then
201 - tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E_MAYBE
202 + dep_tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E_MAYBE $CONFIG_ATM
203 if [ "$CONFIG_ATM_FORE200E_MAYBE" != "n" ]; then
204 if [ "$CONFIG_PCI" = "y" ]; then
205 bool ' PCA-200E support' CONFIG_ATM_FORE200E_PCA
208 define_tristate CONFIG_ATM_FORE200E m
211 + dep_tristate 'ForeRunnerHE (155/622)' CONFIG_ATM_HE $CONFIG_ATM
212 + if [ "$CONFIG_ATM_HE" != "n" ] ; then
213 + bool ' Use S/UNI PHY driver' CONFIG_ATM_HE_USE_SUNI $CONFIG_ATM_HE
217 diff -urN linux-2.4.20/drivers/atm/Makefile linux-2.4.20-atm/drivers/atm/Makefile
218 --- linux-2.4.20/drivers/atm/Makefile Wed Nov 7 23:39:36 2001
219 +++ linux-2.4.20-atm/drivers/atm/Makefile Wed May 28 01:58:41 2003
221 obj-$(CONFIG_ATM_IA) += iphase.o suni.o
222 obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o
223 obj-$(CONFIG_ATM_LANAI) += lanai.o
224 +obj-$(CONFIG_ATM_HE) += he.o
225 +ifeq ($(CONFIG_ATM_HE_USE_SUNI),y)
226 + obj-$(CONFIG_ATM_HE) += suni.o
229 ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
230 FORE200E_FW_OBJS += fore200e_pca_fw.o
231 diff -urN linux-2.4.20/drivers/atm/ambassador.c linux-2.4.20-atm/drivers/atm/ambassador.c
232 --- linux-2.4.20/drivers/atm/ambassador.c Fri Sep 14 00:21:32 2001
233 +++ linux-2.4.20-atm/drivers/atm/ambassador.c Wed May 28 01:58:41 2003
234 @@ -1149,14 +1149,6 @@
238 - // deal with possibly wildcarded VCs
239 - error = atm_find_ci (atm_vcc, &vpi, &vci);
241 - PRINTD (DBG_WARN|DBG_VCC, "atm_find_ci failed!");
244 - PRINTD (DBG_VCC, "atm_find_ci gives %x %x", vpi, vci);
246 if (!(0 <= vpi && vpi < (1<<NUM_VPI_BITS) &&
247 0 <= vci && vci < (1<<NUM_VCI_BITS))) {
248 PRINTD (DBG_WARN|DBG_VCC, "VPI/VCI out of range: %hd/%d", vpi, vci);
249 diff -urN linux-2.4.20/drivers/atm/atmtcp.c linux-2.4.20-atm/drivers/atm/atmtcp.c
250 --- linux-2.4.20/drivers/atm/atmtcp.c Fri Nov 29 00:53:12 2002
251 +++ linux-2.4.20-atm/drivers/atm/atmtcp.c Wed May 28 01:58:41 2003
255 #include <linux/module.h>
256 +#include <linux/init.h>
257 #include <linux/wait.h>
258 #include <linux/atmdev.h>
259 #include <linux/atm_tcp.h>
261 msg.addr.sap_addr.vpi = vpi;
262 msg.hdr.vci = htons(vci);
263 msg.addr.sap_addr.vci = vci;
264 - error = atm_find_ci(vcc,&msg.addr.sap_addr.vpi,&msg.addr.sap_addr.vci);
265 - if (error) return error;
266 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0;
267 msg.type = ATMTCP_CTRL_OPEN;
271 struct atm_cirange ci;
275 if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
276 if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
278 if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS;
279 if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 ||
280 ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL;
281 - for (vcc = dev->vccs; vcc; vcc = vcc->next)
282 + read_lock(&vcc_sklist_lock);
283 + for (s = vcc_sklist; s; s = s->next) {
285 + if (vcc->dev != dev) continue;
286 if ((vcc->vpi >> ci.vpi_bits) ||
287 - (vcc->vci >> ci.vci_bits)) return -EBUSY;
288 + (vcc->vci >> ci.vci_bits)) {
289 + read_unlock(&vcc_sklist_lock);
293 + read_unlock(&vcc_sklist_lock);
298 struct atm_dev *atmtcp_dev;
299 struct atmtcp_dev_data *dev_data;
300 struct atm_vcc *walk;
303 atmtcp_dev = (struct atm_dev *) vcc->dev_data;
304 dev_data = PRIV(atmtcp_dev);
307 shutdown_atm_dev(atmtcp_dev);
308 vcc->dev_data = NULL;
309 - for (walk = atmtcp_dev->vccs; walk; walk = walk->next)
310 - wake_up(&walk->sleep);
311 + read_lock(&vcc_sklist_lock);
312 + for (s = vcc_sklist; s; s = s->next) {
314 + if (walk->dev == atmtcp_dev) wake_up(&walk->sleep);
316 + read_unlock(&vcc_sklist_lock);
323 struct atmtcp_hdr *hdr;
324 - struct atm_vcc *out_vcc;
325 + struct atm_vcc *out_vcc = NULL;
327 struct sk_buff *new_skb;
330 @@ -260,11 +273,17 @@
331 (struct atmtcp_control *) skb->data);
334 - for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next)
335 + read_lock(&vcc_sklist_lock);
336 + for (s = vcc_sklist; s; s = s->next) {
337 + out_vcc = atm_sk(s);
338 + if (out_vcc->dev != dev) continue;
339 if (out_vcc->vpi == ntohs(hdr->vpi) &&
340 out_vcc->vci == ntohs(hdr->vci) &&
341 out_vcc->qos.rxtp.traffic_class != ATM_NONE)
345 + read_unlock(&vcc_sklist_lock);
347 atomic_inc(&vcc->stats->tx_err);
349 @@ -315,15 +334,10 @@
352 static struct atm_dev atmtcp_control_dev = {
355 - "atmtcp", /* type */
356 - 999, /* dummy device number */
357 - NULL,NULL, /* pretend not to have any VCCs */
358 - NULL,NULL, /* no data */
359 - { 0 }, /* no flags */
360 - NULL, /* no local address */
361 - { 0 } /* no ESI, no statistics */
362 + .ops = &atmtcp_c_dev_ops,
365 + .lock = SPIN_LOCK_UNLOCKED
373 - if (itf != -1) dev = atm_find_dev(itf);
374 + if (itf != -1) dev = atm_dev_lookup(itf);
376 - if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
377 + if (dev->ops != &atmtcp_v_dev_ops) {
378 + atm_dev_release(dev);
379 + return -EMEDIUMTYPE;
381 if (PRIV(dev)->vcc) return -EBUSY;
385 if (error) return error;
387 PRIV(dev)->vcc = vcc;
388 - bind_vcc(vcc,&atmtcp_control_dev);
389 + vcc_insert_socket(&atmtcp_control_dev, vcc->sk);
390 set_bit(ATM_VF_META,&vcc->flags);
391 set_bit(ATM_VF_READY,&vcc->flags);
393 @@ -389,44 +406,42 @@
395 struct atmtcp_dev_data *dev_data;
397 - dev = atm_find_dev(itf);
398 + dev = atm_dev_lookup(itf);
399 if (!dev) return -ENODEV;
400 - if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
401 + if (dev->ops != &atmtcp_v_dev_ops) {
402 + atm_dev_release(dev);
403 + return -EMEDIUMTYPE;
405 dev_data = PRIV(dev);
406 if (!dev_data->persist) return 0;
407 dev_data->persist = 0;
408 if (PRIV(dev)->vcc) return 0;
410 + atm_dev_release(dev);
411 shutdown_atm_dev(dev);
417 +static struct atm_tcp_ops __atm_tcp_ops = {
418 + atmtcp_attach, /* attach */
419 + atmtcp_create_persistent, /* create_persistent */
420 + atmtcp_remove_persistent /* remove_persistent */
424 -int init_module(void)
425 +static int __init atmtcp_init(void)
427 - atm_tcp_ops.attach = atmtcp_attach;
428 - atm_tcp_ops.create_persistent = atmtcp_create_persistent;
429 - atm_tcp_ops.remove_persistent = atmtcp_remove_persistent;
430 + atm_tcp_ops = &__atm_tcp_ops;
435 -void cleanup_module(void)
436 +static void __exit atmtcp_cleanup(void)
438 - atm_tcp_ops.attach = NULL;
439 - atm_tcp_ops.create_persistent = NULL;
440 - atm_tcp_ops.remove_persistent = NULL;
441 + atm_tcp_ops = NULL;
444 -MODULE_LICENSE("GPL");
446 +module_init(atmtcp_init);
447 +module_exit(atmtcp_cleanup);
449 -struct atm_tcp_ops atm_tcp_ops = {
450 - atmtcp_attach, /* attach */
451 - atmtcp_create_persistent, /* create_persistent */
452 - atmtcp_remove_persistent /* remove_persistent */
456 +MODULE_LICENSE("GPL");
457 diff -urN linux-2.4.20/drivers/atm/eni.c linux-2.4.20-atm/drivers/atm/eni.c
458 --- linux-2.4.20/drivers/atm/eni.c Fri Dec 21 18:41:53 2001
459 +++ linux-2.4.20-atm/drivers/atm/eni.c Wed May 28 01:58:41 2003
461 if (eni_dev->rx_map[vcc->vci])
462 printk(KERN_CRIT DEV_LABEL "(itf %d): BUG - VCI %d already "
463 "in use\n",vcc->dev->number,vcc->vci);
465 eni_dev->rx_map[vcc->vci] = vcc; /* now it counts */
466 writel(((vcc->qos.aal != ATM_AAL5 ? MID_MODE_RAW : MID_MODE_AAL5) <<
467 MID_VCI_MODE_SHIFT) | MID_VCI_PTI_MODE |
469 /* discard pending cell */
470 writel(readl(here) & ~MID_VCI_IN_SERVICE,here);
471 /* don't accept any new ones */
472 + tasklet_disable(&eni_dev->task);
473 eni_dev->rx_map[vcc->vci] = NULL;
475 + tasklet_enable(&eni_dev->task);
477 /* wait for RX queue to drain */
478 DPRINTK("eni_close: waiting for RX ...\n");
479 EVENT("RX closing\n",0,0);
480 @@ -1101,9 +1106,9 @@
481 dma_rd = eni_in(MID_DMA_RD_TX);
482 dma_size = 3; /* JK for descriptor and final fill, plus final size
484 -DPRINTK("iovcnt = %d\n",ATM_SKB(skb)->iovcnt);
485 - if (!ATM_SKB(skb)->iovcnt) dma_size += 5;
486 - else dma_size += 5*ATM_SKB(skb)->iovcnt;
487 +DPRINTK("nr_frags = %d\n", skb_shinfo(skb)->nr_frags);
488 + if (!skb_shinfo(skb)->nr_frags) dma_size += 5;
489 + else dma_size += 5*skb_shinfo(skb)->nr_frags;
490 if (dma_size > TX_DMA_BUF) {
491 printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries "
492 "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF);
493 @@ -1124,15 +1129,15 @@
494 MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
497 - if (!ATM_SKB(skb)->iovcnt)
498 + if (!skb_shinfo(skb)->nr_frags)
499 if (aal5) put_dma(tx->index,eni_dev->dma,&j,paddr,skb->len);
500 else put_dma(tx->index,eni_dev->dma,&j,paddr+4,skb->len-4);
502 DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
503 - for (i = 0; i < ATM_SKB(skb)->iovcnt; i++)
504 + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
505 put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
506 - ((struct iovec *) skb->data)[i].iov_base,
507 - ((struct iovec *) skb->data)[i].iov_len);
508 + skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset,
509 + skb_shinfo(skb)->frags[i].size);
512 put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
513 @@ -1880,43 +1885,6 @@
517 -static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci)
519 - struct atm_vcc *walk;
521 - if (*vpi == ATM_VPI_ANY) *vpi = 0;
522 - if (*vci == ATM_VCI_ANY) {
523 - for (*vci = ATM_NOT_RSV_VCI; *vci < NR_VCI; (*vci)++) {
524 - if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
525 - ENI_DEV(vcc->dev)->rx_map[*vci])
527 - if (vcc->qos.txtp.traffic_class != ATM_NONE) {
528 - for (walk = vcc->dev->vccs; walk;
530 - if (test_bit(ATM_VF_ADDR,&walk->flags)
531 - && walk->vci == *vci &&
532 - walk->qos.txtp.traffic_class !=
535 - if (walk) continue;
539 - return *vci == NR_VCI ? -EADDRINUSE : 0;
541 - if (*vci == ATM_VCI_UNSPEC) return 0;
542 - if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
543 - ENI_DEV(vcc->dev)->rx_map[*vci])
544 - return -EADDRINUSE;
545 - if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;
546 - for (walk = vcc->dev->vccs; walk; walk = walk->next)
547 - if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vci == *vci &&
548 - walk->qos.txtp.traffic_class != ATM_NONE)
549 - return -EADDRINUSE;
554 static int eni_open(struct atm_vcc *vcc,short vpi,int vci)
556 struct eni_dev *eni_dev;
557 @@ -1927,8 +1895,6 @@
558 EVENT("eni_open\n",0,0);
559 if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ENI_VCC(vcc) = NULL;
560 eni_dev = ENI_DEV(vcc->dev);
561 - error = get_ci(vcc,&vpi,&vci);
562 - if (error) return error;
565 if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
566 @@ -2122,8 +2088,8 @@
568 static const char *signal[] = { "LOST","unknown","okay" };
569 struct eni_dev *eni_dev = ENI_DEV(dev);
570 - struct atm_vcc *vcc;
576 @@ -2192,10 +2158,13 @@
577 return sprintf(page,"%10sbacklog %u packets\n","",
578 skb_queue_len(&tx->backlog));
580 - for (vcc = dev->vccs; vcc; vcc = vcc->next) {
581 + read_lock(&vcc_sklist_lock);
582 + for(s = vcc_sklist; s; s = s->next) {
583 + struct atm_vcc *vcc = atm_sk(s);
584 struct eni_vcc *eni_vcc = ENI_VCC(vcc);
587 + if (vcc->dev != dev) continue;
588 if (--left) continue;
589 length = sprintf(page,"vcc %4d: ",vcc->vci);
591 @@ -2210,8 +2179,10 @@
592 length += sprintf(page+length,"tx[%d], txing %d bytes",
593 eni_vcc->tx->index,eni_vcc->txing);
595 + spin_unlock(&dev->lock);
598 + read_unlock(&vcc_sklist_lock);
599 for (i = 0; i < eni_dev->free_len; i++) {
600 struct eni_free *fe = eni_dev->free_list+i;
601 unsigned long offset;
602 diff -urN linux-2.4.20/drivers/atm/firestream.c linux-2.4.20-atm/drivers/atm/firestream.c
603 --- linux-2.4.20/drivers/atm/firestream.c Fri Nov 29 00:53:12 2002
604 +++ linux-2.4.20-atm/drivers/atm/firestream.c Wed May 28 01:58:41 2003
606 fs_dprintk (FS_DEBUG_OPEN, "fs: open on dev: %p, vcc at %p\n",
609 - error = atm_find_ci(atm_vcc, &vpi, &vci);
611 - fs_dprintk (FS_DEBUG_OPEN, "fs: find_ci failed.\n");
617 if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
618 diff -urN linux-2.4.20/drivers/atm/fore200e.c linux-2.4.20-atm/drivers/atm/fore200e.c
619 --- linux-2.4.20/drivers/atm/fore200e.c Wed May 28 01:53:45 2003
620 +++ linux-2.4.20-atm/drivers/atm/fore200e.c Wed May 28 01:58:41 2003
622 #define FORE200E_52BYTE_AAL0_SDU
625 -#define FORE200E_VERSION "0.2d"
626 +#define FORE200E_VERSION "0.2f"
629 #define FORE200E "fore200e: "
630 @@ -1077,15 +1077,7 @@
631 static struct atm_vcc*
632 fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
634 - struct atm_vcc* vcc;
636 - for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {
638 - if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci)
643 + return vcc_lookup(fore200e->atm_dev, rpd->atm_header.vpi, rpd->atm_header.vci);
647 @@ -1132,6 +1124,7 @@
649 printk(FORE200E "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
650 atomic_inc(&vcc->stats->rx_drop);
655 @@ -1166,14 +1159,16 @@
656 if (atm_charge(vcc, skb->truesize) == 0) {
658 DPRINTK(2, "receive buffers saturated for %d.%d.%d - PDU dropped\n",
659 - vcc->itf, vcc->vpi, vcc->vci);
660 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci);
662 dev_kfree_skb_irq(skb);
668 atomic_inc(&vcc->stats->rx);
673 @@ -1215,8 +1210,8 @@
674 fore200e_push_rpd(fore200e, entry->rpd);
677 - printk(FORE200E "damaged PDU on %d.%d.%d\n",
678 - fore200e->atm_dev->number, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
679 + DPRINTK(1, "damaged PDU on %d.%d.%d\n",
680 + fore200e->atm_dev->number, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
683 fore200e_collect_rpd(fore200e, entry->rpd);
684 @@ -1281,7 +1276,7 @@
687 DPRINTK(1, "vpvc %d.%d.%d uses the %s buffer scheme\n",
688 - vcc->itf, vcc->vpi, vcc->vci, scheme == BUFFER_SCHEME_ONE ? "first" : "second");
689 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, scheme == BUFFER_SCHEME_ONE ? "first" : "second");
693 @@ -1351,39 +1346,6 @@
698 -fore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci)
700 - struct atm_vcc* walk;
702 - /* find a free VPI */
703 - if (*vpi == ATM_VPI_ANY) {
705 - for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) {
707 - if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
709 - walk = vcc->dev->vccs;
714 - /* find a free VCI */
715 - if (*vci == ATM_VCI_ANY) {
717 - for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk; walk = walk->next) {
719 - if ((walk->vpi = *vpi) && (walk->vci == *vci)) {
720 - *vci = walk->vci + 1;
721 - walk = vcc->dev->vccs;
730 #define FORE200E_MAX_BACK2BACK_CELLS 255 /* XXX depends on CDVT */
733 @@ -1408,9 +1370,6 @@
734 struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
735 struct fore200e_vcc* fore200e_vcc;
737 - /* find a free VPI/VCI */
738 - fore200e_walk_vccs(vcc, &vpi, &vci);
743 @@ -1419,11 +1378,11 @@
746 set_bit(ATM_VF_ADDR, &vcc->flags);
747 - vcc->itf = vcc->dev->number;
748 + vcc->sk->bound_dev_if = vcc->dev->number;
750 DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
751 "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d)\n",
752 - vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
753 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
754 fore200e_traffic_class[ vcc->qos.txtp.traffic_class ],
755 vcc->qos.txtp.min_pcr, vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_cdv, vcc->qos.txtp.max_sdu,
756 fore200e_traffic_class[ vcc->qos.rxtp.traffic_class ],
757 @@ -1469,7 +1428,7 @@
758 fore200e_rate_ctrl(&vcc->qos, &fore200e_vcc->rate);
760 DPRINTK(3, "tx on %d.%d.%d:%d, tx PCR = %d, rx PCR = %d, data_cells = %u, idle_cells = %u\n",
761 - vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
762 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
763 vcc->qos.txtp.max_pcr, vcc->qos.rxtp.max_pcr,
764 fore200e_vcc->rate.data_cells, fore200e_vcc->rate.idle_cells);
766 @@ -1488,7 +1447,7 @@
768 struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
770 - DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal));
771 + DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal));
773 fore200e_activate_vcin(fore200e, 0, vcc, 0);
775 @@ -1543,7 +1502,7 @@
779 - tasklet_disable(&fore200e->tasklet);
780 + spin_lock_bh(&fore200e->tx_lock);
782 entry = &txq->host_entry[ txq->head ];
784 @@ -1553,8 +1512,8 @@
785 fore200e_irq_tx(fore200e);
787 if (*entry->status != STATUS_FREE) {
789 - tasklet_enable(&fore200e->tasklet);
791 + spin_unlock_bh(&fore200e->tx_lock);
793 /* retry once again? */
795 @@ -1593,8 +1552,9 @@
797 entry->data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);
798 if (entry->data == NULL) {
800 - tasklet_enable(&fore200e->tasklet);
802 + spin_unlock_bh(&fore200e->tx_lock);
807 @@ -1618,13 +1578,13 @@
808 FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
811 - tasklet_enable(&fore200e->tasklet);
812 + spin_unlock_bh(&fore200e->tx_lock);
814 /* ensure DMA synchronisation */
815 fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
817 DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n",
818 - vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
819 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
820 tpd->tsd[0].length, skb_len);
822 if (skb_len < fore200e_vcc->tx_min_pdu)
823 @@ -1690,14 +1650,14 @@
827 - printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci);
828 + printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->sk->bound_dev_if, vcc->vpi, vcc->vci);
830 atomic_inc(&entry->vcc->stats->tx_err);
833 atomic_inc(&entry->vcc->stats->tx);
835 - DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->itf, vcc->vpi, vcc->vci);
836 + DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->sk->bound_dev_if, vcc->vpi, vcc->vci);
840 @@ -1755,7 +1715,7 @@
841 // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
843 DPRINTK(2, "getsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",
844 - vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);
845 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, level, optname, optval, optlen);
849 @@ -1767,7 +1727,7 @@
850 // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
852 DPRINTK(2, "setsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",
853 - vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);
854 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci, level, optname, optval, optlen);
858 @@ -1963,7 +1923,7 @@
859 "(tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
860 "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d), flags = 0x%x\n"
861 "available_cell_rate = %u",
862 - vcc->itf, vcc->vpi, vcc->vci,
863 + vcc->sk->bound_dev_if, vcc->vpi, vcc->vci,
864 fore200e_traffic_class[ qos->txtp.traffic_class ],
865 qos->txtp.min_pcr, qos->txtp.max_pcr, qos->txtp.max_cdv, qos->txtp.max_sdu,
866 fore200e_traffic_class[ qos->rxtp.traffic_class ],
867 @@ -2355,6 +2315,7 @@
869 DPRINTK(2, "device %s being initialized\n", fore200e->name);
871 + spin_lock_init(&fore200e->tx_lock);
872 init_MUTEX(&fore200e->rate_sf);
874 cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
875 @@ -2642,6 +2603,7 @@
877 struct fore200e* fore200e = FORE200E_DEV(dev);
878 int len, left = *pos;
883 @@ -2886,7 +2848,11 @@
884 len = sprintf(page,"\n"
885 " VCCs:\n address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n");
887 - for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {
888 + read_lock(&vcc_sklist_lock);
889 + for(s = vcc_sklist; s; s = s->next) {
892 + if (vcc->dev != fore200e->atm_dev) continue;
894 fore200e_vcc = FORE200E_VCC(vcc);
896 @@ -2900,6 +2866,7 @@
897 fore200e_vcc->rx_max_pdu
900 + read_unlock(&vcc_sklist_lock);
904 diff -urN linux-2.4.20/drivers/atm/fore200e.h linux-2.4.20-atm/drivers/atm/fore200e.h
905 --- linux-2.4.20/drivers/atm/fore200e.h Mon Dec 11 22:22:12 2000
906 +++ linux-2.4.20-atm/drivers/atm/fore200e.h Wed May 28 01:58:41 2003
908 struct stats* stats; /* last snapshot of the stats */
910 struct semaphore rate_sf; /* protects rate reservation ops */
911 + spinlock_t tx_lock; /* protects tx ops */
912 struct tasklet_struct tasklet; /* performs interrupt work */
915 diff -urN linux-2.4.20/drivers/atm/he.c linux-2.4.20-atm/drivers/atm/he.c
916 --- linux-2.4.20/drivers/atm/he.c Thu Jan 1 01:00:00 1970
917 +++ linux-2.4.20-atm/drivers/atm/he.c Wed May 28 01:58:41 2003
925 + ForeRunnerHE ATM Adapter driver for ATM on Linux
926 + Copyright (C) 1999-2001 Naval Research Laboratory
928 + This library is free software; you can redistribute it and/or
929 + modify it under the terms of the GNU Lesser General Public
930 + License as published by the Free Software Foundation; either
931 + version 2.1 of the License, or (at your option) any later version.
933 + This library is distributed in the hope that it will be useful,
934 + but WITHOUT ANY WARRANTY; without even the implied warranty of
935 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
936 + Lesser General Public License for more details.
938 + You should have received a copy of the GNU Lesser General Public
939 + License along with this library; if not, write to the Free Software
940 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
948 + ForeRunnerHE ATM Adapter driver for ATM on Linux
949 + Copyright (C) 1999-2001 Naval Research Laboratory
951 + Permission to use, copy, modify and distribute this software and its
952 + documentation is hereby granted, provided that both the copyright
953 + notice and this permission notice appear in all copies of the software,
954 + derivative works or modified versions, and any portions thereof, and
955 + that both notices appear in supporting documentation.
957 + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
958 + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
959 + RESULTING FROM THE USE OF THIS SOFTWARE.
961 + This driver was written using the "Programmer's Reference Manual for
962 + ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98.
965 + chas williams <chas@cmf.nrl.navy.mil>
966 + eric kinzie <ekinzie@cmf.nrl.navy.mil>
969 + 4096 supported 'connections'
970 + group 0 is used for all traffic
971 + interrupt queue 0 is used for all interrupts
972 + aal0 support for receive only
976 +#include <linux/config.h>
977 +#include <linux/module.h>
978 +#include <linux/version.h>
979 +#include <linux/kernel.h>
980 +#include <linux/skbuff.h>
981 +#include <linux/pci.h>
982 +#include <linux/errno.h>
983 +#include <linux/types.h>
984 +#include <linux/string.h>
985 +#include <linux/delay.h>
986 +#include <linux/init.h>
987 +#include <linux/mm.h>
988 +#include <linux/sched.h>
989 +#include <linux/timer.h>
990 +#include <linux/interrupt.h>
992 +#include <asm/byteorder.h>
993 +#include <asm/uaccess.h>
995 +#include <linux/atmdev.h>
996 +#include <linux/atm.h>
997 +#include <linux/sonet.h>
998 +#ifndef ATM_OC12_PCR
999 +#define ATM_OC12_PCR (622080000/1080*1040/8/53)
1003 +void sn_add_polled_interrupt(int irq, int interval);
1004 +void sn_delete_polled_interrupt(int irq);
1007 +#define USE_TASKLET
1008 +#define USE_HE_FIND_VCC
1009 +#define USE_SCATTERGATHER
1010 +#undef USE_CHECKSUM_HW /* still confused about this */
1011 +#define USE_RBPS /* probably broken */
1012 +#define USE_RBPL_POOL
1014 +#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
1015 +#define CONFIG_ATM_HE_USE_SUNI
1018 +/* 2.2 kernel support */
1020 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
1021 +#define dev_kfree_skb_irq(skb) dev_kfree_skb(skb)
1022 +#define dev_kfree_skb_any(skb) dev_kfree_skb(skb)
1025 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
1026 +#define set_current_state(x) current->state = (x);
1029 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
1037 +#include <linux/atm_he.h>
1039 +#define hprintk(fmt,args...) printk(DEV_LABEL "%d: " fmt, he_dev->number, args)
1040 +#define hprintk1(fmt) printk(DEV_LABEL "%d: " fmt, he_dev->number)
1044 +#define HPRINTK(fmt,args...) hprintk(fmt,args)
1045 +#define HPRINTK1(fmt) hprintk1(fmt)
1047 +#define HPRINTK(fmt,args...)
1048 +#define HPRINTK1(fmt,args...)
1052 +/* version definition */
1054 +static char *version = "$Id$";
1057 +#define ALIGN_ADDRESS(addr, alignment) \
1058 + ((((unsigned long) (addr)) + (((unsigned long) (alignment)) - 1)) & ~(((unsigned long) (alignment)) - 1))
1062 +static int he_open(struct atm_vcc *vcc, short vpi, int vci);
1063 +static void he_close(struct atm_vcc *vcc);
1064 +static int he_send(struct atm_vcc *vcc, struct sk_buff *skb);
1065 +static int he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size);
1066 +static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg);
1067 +static void he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
1068 +static void he_tasklet(unsigned long data);
1069 +static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
1070 +static int he_start(struct atm_dev *dev);
1071 +static void he_stop(struct he_dev *dev);
1072 +static void he_phy_put(struct atm_dev *, unsigned char, unsigned long);
1073 +static unsigned char he_phy_get(struct atm_dev *, unsigned long);
1075 +static u8 read_prom_byte(struct he_dev *he_dev, int addr);
1079 +struct he_dev *he_devs = NULL;
1080 +static short disable64 = -1;
1081 +static short nvpibits = -1;
1082 +static short nvcibits = -1;
1083 +static short rx_skb_reserve = 16;
1084 +static short irq_coalesce = 1;
1085 +static short sdh = 1;
1087 +static struct atmdev_ops he_ops =
1093 + sg_send: he_sg_send,
1094 + phy_put: he_phy_put,
1095 + phy_get: he_phy_get,
1096 + proc_read: he_proc_read,
1097 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1)
1098 + owner: THIS_MODULE
1102 +/* see the comments in he.h about global_lock */
1105 +#define HE_SPIN_LOCK(dev, flags) spin_lock_irqsave(&(dev)->global_lock, flags)
1106 +#define HE_SPIN_UNLOCK(dev, flags) spin_unlock_irqrestore(&(dev)->global_lock, flags)
1108 +#define HE_SPIN_LOCK(dev, flags) do { flags = 0; } while(0)
1109 +#define HE_SPIN_UNLOCK(dev, flags) do { flags = 0; } while(0)
1113 +#define he_writel(dev, val, reg) writel(val, (dev)->membase + (reg))
1114 +#define he_readl(dev, reg) readl((dev)->membase + (reg))
1116 +/* section 2.12 connection memory access */
1118 +static __inline__ void
1119 +he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr,
1122 + while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
1123 + he_writel(he_dev, val, CON_DAT);
1124 + he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL);
1127 +#define he_writel_rcm(dev, val, reg) \
1128 + he_writel_internal(dev, val, reg, CON_CTL_RCM)
1130 +#define he_writel_tcm(dev, val, reg) \
1131 + he_writel_internal(dev, val, reg, CON_CTL_TCM)
1133 +#define he_writel_mbox(dev, val, reg) \
1134 + he_writel_internal(dev, val, reg, CON_CTL_MBOX)
1137 +he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
1139 + while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
1140 + he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL);
1141 + return he_readl(he_dev, CON_DAT);
1144 +#define he_readl_rcm(dev, reg) \
1145 + he_readl_internal(dev, reg, CON_CTL_RCM)
1147 +#define he_readl_tcm(dev, reg) \
1148 + he_readl_internal(dev, reg, CON_CTL_TCM)
1150 +#define he_readl_mbox(dev, reg) \
1151 + he_readl_internal(dev, reg, CON_CTL_MBOX)
1154 +/* figure 2.2 connection id */
1156 +#define he_mkcid(dev, vpi, vci) (((vpi<<(dev)->vcibits) | vci) & 0x1fff)
1158 +/* 2.5.1 per connection transmit state registers */
1160 +#define he_writel_tsr0(dev, val, cid) \
1161 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 0)
1162 +#define he_readl_tsr0(dev, cid) \
1163 + he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 0)
1165 +#define he_writel_tsr1(dev, val, cid) \
1166 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 1)
1168 +#define he_writel_tsr2(dev, val, cid) \
1169 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 2)
1171 +#define he_writel_tsr3(dev, val, cid) \
1172 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 3)
1174 +#define he_writel_tsr4(dev, val, cid) \
1175 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 4)
1179 + * NOTE While the transmit connection is active, bits 23 through 0
1180 + * of this register must not be written by the host. Byte
1181 + * enables should be used during normal operation when writing
1182 + * the most significant byte.
1185 +#define he_writel_tsr4_upper(dev, val, cid) \
1186 + he_writel_internal(dev, val, CONFIG_TSRA | (cid<<3) | 4, \
1188 + | CON_BYTE_DISABLE_2 \
1189 + | CON_BYTE_DISABLE_1 \
1190 + | CON_BYTE_DISABLE_0)
1192 +#define he_readl_tsr4(dev, cid) \
1193 + he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 4)
1195 +#define he_writel_tsr5(dev, val, cid) \
1196 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 5)
1198 +#define he_writel_tsr6(dev, val, cid) \
1199 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 6)
1201 +#define he_writel_tsr7(dev, val, cid) \
1202 + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 7)
1205 +#define he_writel_tsr8(dev, val, cid) \
1206 + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<1) | 0)
1208 +#define he_writel_tsr9(dev, val, cid) \
1209 + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<1) | 1)
1212 +#define he_writel_tsr10(dev, val, cid) \
1213 + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 0)
1215 +#define he_writel_tsr11(dev, val, cid) \
1216 + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 1)
1218 +#define he_writel_tsr12(dev, val, cid) \
1219 + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 2)
1221 +#define he_writel_tsr13(dev, val, cid) \
1222 + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 3)
1225 +#define he_writel_tsr14(dev, val, cid) \
1226 + he_writel_tcm(dev, val, CONFIG_TSRD | cid)
1228 +#define he_writel_tsr14_upper(dev, val, cid) \
1229 + he_writel_internal(dev, val, CONFIG_TSRD | cid, \
1231 + | CON_BYTE_DISABLE_2 \
1232 + | CON_BYTE_DISABLE_1 \
1233 + | CON_BYTE_DISABLE_0)
1235 +/* 2.7.1 per connection receive state registers */
1237 +#define he_writel_rsr0(dev, val, cid) \
1238 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 0)
1239 +#define he_readl_rsr0(dev, cid) \
1240 + he_readl_rcm(dev, 0x00000 | (cid<<3) | 0)
1242 +#define he_writel_rsr1(dev, val, cid) \
1243 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 1)
1245 +#define he_writel_rsr2(dev, val, cid) \
1246 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 2)
1248 +#define he_writel_rsr3(dev, val, cid) \
1249 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 3)
1251 +#define he_writel_rsr4(dev, val, cid) \
1252 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 4)
1254 +#define he_writel_rsr5(dev, val, cid) \
1255 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 5)
1257 +#define he_writel_rsr6(dev, val, cid) \
1258 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 6)
1260 +#define he_writel_rsr7(dev, val, cid) \
1261 + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 7)
1263 +static __inline__ struct atm_vcc*
1264 +he_find_vcc(struct he_dev *he_dev, unsigned cid)
1269 + vpi = cid >> he_dev->vcibits;
1270 + vci = cid & ((1<<he_dev->vcibits)-1);
1272 + return __vcc_lookup(he_dev->atm_dev, vpi, vci);
1275 +static int __devinit
1276 +he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
1278 + struct atm_dev *atm_dev;
1279 + struct he_dev *he_dev;
1281 + printk(KERN_INFO "he: %s\n", version);
1283 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,43)
1284 + if (pci_enable_device(pci_dev)) return -EIO;
1286 + if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0)
1288 + printk(KERN_WARNING "he: no suitable dma available\n");
1292 + atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0);
1293 + if (!atm_dev) return -ENODEV;
1294 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
1295 + pci_set_drvdata(pci_dev, atm_dev);
1297 + pci_dev->driver_data = atm_dev;
1300 + he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev),
1302 + if (!he_dev) return -ENOMEM;
1303 + memset(he_dev, 0, sizeof(struct he_dev));
1305 + he_dev->pci_dev = pci_dev;
1306 + he_dev->atm_dev = atm_dev;
1307 + he_dev->atm_dev->dev_data = he_dev;
1308 + HE_DEV(atm_dev) = he_dev;
1309 + he_dev->number = atm_dev->number; /* was devs */
1310 + if (he_start(atm_dev)) {
1311 + atm_dev_deregister(atm_dev);
1316 + he_dev->next = NULL;
1317 + if (he_devs) he_dev->next = he_devs;
1323 +static void __devexit
1324 +he_remove_one (struct pci_dev *pci_dev)
1326 + struct atm_dev *atm_dev;
1327 + struct he_dev *he_dev;
1329 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
1330 + atm_dev = pci_get_drvdata(pci_dev);
1332 + atm_dev = pci_dev->driver_data;
1334 + he_dev = HE_DEV(atm_dev);
1336 + /* need to remove from he_devs */
1339 + atm_dev_deregister(atm_dev);
1342 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
1343 + pci_set_drvdata(pci_dev, NULL);
1345 + pci_dev->driver_data = NULL;
1351 +rate_to_atmf(unsigned rate) /* cps to atm forum format */
1353 +#define NONZERO (1<<14)
1357 + if (rate == 0) return(0);
1360 + while (rate > 0x3ff)
1366 + return (NONZERO | (exp << 9) | (rate & 0x1ff));
1370 +he_init_rx_lbfp0(struct he_dev *he_dev)
1372 + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
1373 + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
1374 + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
1375 + unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row;
1378 + lbm_offset = he_readl(he_dev, RCMLBM_BA);
1380 + he_writel(he_dev, lbufd_index, RLBF0_H);
1382 + for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i)
1385 + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
1387 + he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
1388 + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
1390 + if (++lbuf_count == lbufs_per_row)
1393 + row_offset += he_dev->bytes_per_row;
1398 + he_writel(he_dev, lbufd_index - 2, RLBF0_T);
1399 + he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
1403 +he_init_rx_lbfp1(struct he_dev *he_dev)
1405 + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
1406 + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
1407 + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
1408 + unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row;
1411 + lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
1413 + he_writel(he_dev, lbufd_index, RLBF1_H);
1415 + for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i)
1418 + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
1420 + he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
1421 + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
1423 + if (++lbuf_count == lbufs_per_row)
1426 + row_offset += he_dev->bytes_per_row;
1431 + he_writel(he_dev, lbufd_index - 2, RLBF1_T);
1432 + he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
1436 +he_init_tx_lbfp(struct he_dev *he_dev)
1438 + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
1439 + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
1440 + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
1441 + unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row;
1443 + lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs;
1444 + lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
1446 + he_writel(he_dev, lbufd_index, TLBF_H);
1448 + for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i)
1451 + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
1453 + he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
1454 + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
1456 + if (++lbuf_count == lbufs_per_row)
1459 + row_offset += he_dev->bytes_per_row;
1464 + he_writel(he_dev, lbufd_index - 1, TLBF_T);
1468 +he_init_tpdrq(struct he_dev *he_dev)
1470 + he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
1471 + CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys);
1472 + if (he_dev->tpdrq_base == NULL)
1474 + hprintk1("failed to alloc tpdrq\n");
1477 + memset(he_dev->tpdrq_base, 0,
1478 + CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq));
1480 + he_dev->tpdrq_tail = he_dev->tpdrq_base;
1481 + he_dev->tpdrq_head = he_dev->tpdrq_base;
1483 + he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H);
1484 + he_writel(he_dev, 0, TPDRQ_T);
1485 + he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S);
1491 +he_init_cs_block(struct he_dev *he_dev)
1493 + unsigned clock, rate, delta;
1496 + /* 5.1.7 cs block initialization */
1498 + for(reg = 0; reg < 0x20; ++reg)
1499 + he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg);
1501 + /* rate grid timer reload values */
1503 + clock = he_is622(he_dev) ? 66667000 : 50000000;
1504 + rate = he_dev->atm_dev->link_rate;
1505 + delta = rate / 16 / 2;
1507 + for(reg = 0; reg < 0x10; ++reg)
1509 + /* 2.4 internal transmit function
1511 + * we initialize the first row in the rate grid.
1512 + * values are period (in clock cycles) of timer
1514 + unsigned period = clock / rate;
1516 + he_writel_mbox(he_dev, period, CS_TGRLD0 + reg);
1520 + if (he_is622(he_dev))
1522 + /* table 5.2 (4 cells per lbuf) */
1523 + he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0);
1524 + he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1);
1525 + he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2);
1526 + he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3);
1527 + he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4);
1529 + /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
1530 + he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0);
1531 + he_writel_mbox(he_dev, 0x1801, CS_ERCTL1);
1532 + he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2);
1533 + he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
1534 + he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1);
1535 + he_writel_mbox(he_dev, 0x14585, CS_RTFWR);
1537 + he_writel_mbox(he_dev, 0x4680, CS_RTATR);
1540 + he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET);
1541 + he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX);
1542 + he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN);
1543 + he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC);
1544 + he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC);
1545 + he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL);
1548 + he_writel_mbox(he_dev, 0x5, CS_OTPPER);
1549 + he_writel_mbox(he_dev, 0x14, CS_OTWPER);
1553 + /* table 5.1 (4 cells per lbuf) */
1554 + he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0);
1555 + he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1);
1556 + he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2);
1557 + he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3);
1558 + he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4);
1560 + /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
1561 + he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0);
1562 + he_writel_mbox(he_dev, 0x4701, CS_ERCTL1);
1563 + he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2);
1564 + he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
1565 + he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1);
1566 + he_writel_mbox(he_dev, 0xf424, CS_RTFWR);
1568 + he_writel_mbox(he_dev, 0x4680, CS_RTATR);
1571 + he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET);
1572 + he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX);
1573 + he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN);
1574 + he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC);
1575 + he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC);
1576 + he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL);
1579 + he_writel_mbox(he_dev, 0x6, CS_OTPPER);
1580 + he_writel_mbox(he_dev, 0x1e, CS_OTWPER);
1584 + he_writel_mbox(he_dev, 0x8, CS_OTTLIM);
1586 + for(reg = 0; reg < 0x8; ++reg)
1587 + he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg);
1592 +he_init_cs_block_rcm(struct he_dev *he_dev)
1594 + unsigned rategrid[16][16];
1595 + unsigned rate, delta;
1598 + unsigned rate_atmf, exp, man;
1599 + unsigned long long rate_cps;
1600 + int mult, buf, buf_limit = 4;
1602 + /* initialize rate grid group table */
1604 + for (reg = 0x0; reg < 0xff; ++reg)
1605 + he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
1607 + /* initialize rate controller groups */
1609 + for (reg = 0x100; reg < 0x1ff; ++reg)
1610 + he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
1612 + /* initialize tNrm lookup table */
1614 + /* the manual makes reference to a routine in a sample driver
1615 + for proper configuration; fortunately, we only need this
1616 + in order to support abr connection */
1618 + /* initialize rate to group table */
1620 + rate = he_dev->atm_dev->link_rate;
1621 + delta = rate / 32;
1624 + * 2.4 transmit internal functions
1626 + * we construct a copy of the rate grid used by the scheduler
1627 + * in order to construct the rate to group table below
1630 + for (j = 0; j < 16; j++)
1632 + rategrid[0][j] = rate;
1636 + for (i = 1; i < 16; i++)
1637 + for (j = 0; j < 16; j++)
1639 + rategrid[i][j] = rategrid[i - 1][j] / 4;
1641 + rategrid[i][j] = rategrid[i - 1][j] / 2;
1644 + * 2.4 transmit internal function
1646 + * this table maps the upper 5 bits of exponent and mantissa
1647 + * of the atm forum representation of the rate into an index
1652 + while (rate_atmf < 0x400)
1654 + man = (rate_atmf & 0x1f) << 4;
1655 + exp = rate_atmf >> 5;
1658 + instead of '/ 512', use '>> 9' to prevent a call
1659 + to divdu3 on x86 platforms
1661 + rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
1663 + if (rate_cps < 10) rate_cps = 10;
1664 + /* 2.2.1 minimum payload rate is 10 cps */
1666 + for (i = 255; i > 0; i--)
1667 + if (rategrid[i/16][i%16] >= rate_cps) break;
1668 + /* pick nearest rate instead? */
1671 + * each table entry is 16 bits: (rate grid index (8 bits)
1672 + * and a buffer limit (8 bits)
1673 + * there are two table entries in each 32-bit register
1677 + buf = rate_cps * he_dev->tx_numbuffs /
1678 + (he_dev->atm_dev->link_rate * 2);
1680 + /* this is pretty, but avoids _divdu3 and is mostly correct */
1682 + mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR;
1683 + if (rate_cps > (68 * mult)) buf = 1;
1684 + if (rate_cps > (136 * mult)) buf = 2;
1685 + if (rate_cps > (204 * mult)) buf = 3;
1686 + if (rate_cps > (272 * mult)) buf = 4;
1688 + if (buf > buf_limit) buf = buf_limit;
1689 + reg = (reg<<16) | ((i<<8) | buf);
1691 +#define RTGTBL_OFFSET 0x400
1693 + if (rate_atmf & 0x1)
1694 + he_writel_rcm(he_dev, reg,
1695 + CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf>>1));
1703 +he_init_group(struct he_dev *he_dev, int group)
1708 + /* small buffer pool */
1709 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
1710 + he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
1711 + CONFIG_RBPS_BUFSIZE, 8, 0, SLAB_KERNEL);
1713 + he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
1714 + CONFIG_RBPS_BUFSIZE, 8, 0);
1716 + if (he_dev->rbps_pool == NULL)
1718 + hprintk1("unable to create rbpl pool\n");
1722 + he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
1723 + CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
1724 + if (he_dev->rbps_base == NULL)
1726 + hprintk1("failed to alloc rbps\n");
1729 + memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
1730 + he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
1732 + for (i = 0; i < CONFIG_RBPS_SIZE; ++i)
1734 + dma_addr_t dma_handle;
1737 + cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
1738 + if (cpuaddr == NULL)
1741 + he_dev->rbps_virt[i].virt = cpuaddr;
1742 + he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
1743 + he_dev->rbps_base[i].phys = dma_handle;
1746 + he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE-1];
1748 + he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32));
1749 + he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail),
1750 + G0_RBPS_T + (group * 32));
1751 + he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4,
1752 + G0_RBPS_BS + (group * 32));
1754 + RBP_THRESH(CONFIG_RBPS_THRESH) |
1755 + RBP_QSIZE(CONFIG_RBPS_SIZE-1) |
1757 + G0_RBPS_QI + (group * 32));
1758 +#else /* !USE_RBPS */
1759 + he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
1760 + he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
1761 + he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
1762 + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
1763 + G0_RBPS_BS + (group * 32));
1764 +#endif /* USE_RBPS */
1766 + /* large buffer pool */
1767 +#ifdef USE_RBPL_POOL
1768 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
1769 + he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
1770 + CONFIG_RBPL_BUFSIZE, 8, 0, SLAB_KERNEL);
1772 + he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
1773 + CONFIG_RBPL_BUFSIZE, 8, 0);
1775 + if (he_dev->rbpl_pool == NULL)
1777 + hprintk1("unable to create rbpl pool\n");
1782 + he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
1783 + CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
1784 + if (he_dev->rbpl_base == NULL)
1786 + hprintk1("failed to alloc rbpl\n");
1789 + memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
1790 + he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
1792 + for (i = 0; i < CONFIG_RBPL_SIZE; ++i)
1794 + dma_addr_t dma_handle;
1797 +#ifdef USE_RBPL_POOL
1798 + cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
1800 + cpuaddr = pci_alloc_consistent(he_dev->pci_dev, CONFIG_RBPL_BUFSIZE, &dma_handle);
1802 + if (cpuaddr == NULL)
1805 + he_dev->rbpl_virt[i].virt = cpuaddr;
1806 + he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
1807 + he_dev->rbpl_base[i].phys = dma_handle;
1810 + he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE-1];
1812 + he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32));
1813 + he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail),
1814 + G0_RBPL_T + (group * 32));
1815 + he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4,
1816 + G0_RBPL_BS + (group * 32));
1818 + RBP_THRESH(CONFIG_RBPL_THRESH) |
1819 + RBP_QSIZE(CONFIG_RBPL_SIZE-1) |
1821 + G0_RBPL_QI + (group * 32));
1823 + /* rx buffer ready queue */
1825 + he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev,
1826 + CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
1827 + if (he_dev->rbrq_base == NULL)
1829 + hprintk1("failed to allocate rbrq\n");
1832 + memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
1834 + he_dev->rbrq_head = he_dev->rbrq_base;
1835 + he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16));
1836 + he_writel(he_dev, 0, G0_RBRQ_H + (group * 16));
1838 + RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE-1),
1839 + G0_RBRQ_Q + (group * 16));
1842 + hprintk1("coalescing interrupts\n");
1843 + he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7),
1844 + G0_RBRQ_I + (group * 16));
1847 + he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1),
1848 + G0_RBRQ_I + (group * 16));
1850 + /* tx buffer ready queue */
1852 + he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev,
1853 + CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
1854 + if (he_dev->tbrq_base == NULL)
1856 + hprintk1("failed to allocate tbrq\n");
1859 + memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
1861 + he_dev->tbrq_head = he_dev->tbrq_base;
1863 + he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16));
1864 + he_writel(he_dev, 0, G0_TBRQ_H + (group * 16));
1865 + he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16));
1866 + he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
1872 +he_init_irq(struct he_dev *he_dev)
1876 + /* 2.9.3.5 tail offset for each interrupt queue is located after the
1877 + end of the interrupt queue */
1879 + he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev,
1880 + (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys);
1881 + if (he_dev->irq_base == NULL)
1883 + hprintk1("failed to allocate irq\n");
1886 + he_dev->irq_tailoffset = (unsigned *)
1887 + &he_dev->irq_base[CONFIG_IRQ_SIZE];
1888 + *he_dev->irq_tailoffset = 0;
1889 + he_dev->irq_head = he_dev->irq_base;
1890 + he_dev->irq_tail = he_dev->irq_base;
1892 + for(i=0; i < CONFIG_IRQ_SIZE; ++i)
1893 + he_dev->irq_base[i].isw = ITYPE_INVALID;
1895 + he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE);
1897 + IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH),
1899 + he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL);
1900 + he_writel(he_dev, 0x0, IRQ0_DATA);
1902 + he_writel(he_dev, 0x0, IRQ1_BASE);
1903 + he_writel(he_dev, 0x0, IRQ1_HEAD);
1904 + he_writel(he_dev, 0x0, IRQ1_CNTL);
1905 + he_writel(he_dev, 0x0, IRQ1_DATA);
1907 + he_writel(he_dev, 0x0, IRQ2_BASE);
1908 + he_writel(he_dev, 0x0, IRQ2_HEAD);
1909 + he_writel(he_dev, 0x0, IRQ2_CNTL);
1910 + he_writel(he_dev, 0x0, IRQ2_DATA);
1912 + he_writel(he_dev, 0x0, IRQ3_BASE);
1913 + he_writel(he_dev, 0x0, IRQ3_HEAD);
1914 + he_writel(he_dev, 0x0, IRQ3_CNTL);
1915 + he_writel(he_dev, 0x0, IRQ3_DATA);
1917 + /* 2.9.3.2 interrupt queue mapping registers */
1919 + he_writel(he_dev, 0x0, GRP_10_MAP);
1920 + he_writel(he_dev, 0x0, GRP_32_MAP);
1921 + he_writel(he_dev, 0x0, GRP_54_MAP);
1922 + he_writel(he_dev, 0x0, GRP_76_MAP);
1924 + if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev))
1926 + hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
1930 + he_dev->irq = he_dev->pci_dev->irq;
1933 + HPRINTK("sn_add_polled_interrupt(irq %d, 1)\n", he_dev->irq);
1934 + sn_add_polled_interrupt(he_dev->irq, 1);
1941 +he_start(struct atm_dev *dev)
1943 + struct he_dev *he_dev;
1944 + struct pci_dev *pci_dev;
1947 + u32 gen_cntl_0, host_cntl, lb_swap;
1948 + u8 cache_size, timer;
1951 + unsigned int status, reg;
1954 + he_dev = HE_DEV(dev);
1955 + pci_dev = he_dev->pci_dev;
1957 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,3)
1958 + he_dev->membase = pci_dev->resource[0].start;
1960 + he_dev->membase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
1962 + HPRINTK("membase = 0x%x irq = %d.\n", he_dev->membase, pci_dev->irq);
1965 + * pci bus controller initialization
1968 + /* 4.3 pci bus controller-specific initialization */
1969 + if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0)
1971 + hprintk1("can't read GEN_CNTL_0\n");
1974 + gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT);
1975 + if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0)
1977 + hprintk1("can't write GEN_CNTL_0.\n");
1981 + if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0)
1983 + hprintk1("can't read PCI_COMMAND.\n");
1987 + command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
1988 + if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0)
1990 + hprintk1("can't enable memory.\n");
1994 + if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size))
1996 + hprintk1("can't read cache line size?\n");
2000 + if (cache_size < 16)
2003 + if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size))
2004 + hprintk("can't set cache line size to %d\n", cache_size);
2007 + if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer))
2009 + hprintk1("can't read latency timer?\n");
2015 + * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE
2017 + * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles]
2018 + * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles]
2021 +#define LAT_TIMER 209
2022 + if (timer < LAT_TIMER)
2024 + HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER);
2025 + timer = LAT_TIMER;
2026 + if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer))
2027 + hprintk("can't set latency timer to %d\n", timer);
2030 + if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
2031 + hprintk1("can't set up page mapping\n");
2035 + /* 4.4 card reset */
2036 + he_writel(he_dev, 0x0, RESET_CNTL);
2037 + he_writel(he_dev, 0xff, RESET_CNTL);
2039 + udelay(16*1000); /* 16 ms */
2040 + status = he_readl(he_dev, RESET_CNTL);
2041 + if ((status & BOARD_RST_STATUS) == 0)
2043 + hprintk1("reset failed\n");
2047 + /* 4.5 set bus width */
2048 + host_cntl = he_readl(he_dev, HOST_CNTL);
2049 + if (host_cntl & PCI_BUS_SIZE64)
2050 + gen_cntl_0 |= ENBL_64;
2052 + gen_cntl_0 &= ~ENBL_64;
2054 + if (disable64 == 1)
2056 + hprintk1("disabling 64-bit pci bus transfers\n");
2057 + gen_cntl_0 &= ~ENBL_64;
2060 + if (gen_cntl_0 & ENBL_64) hprintk1("64-bit transfers enabled\n");
2062 + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
2064 + /* 4.7 read prom contents */
2065 + for(i=0; i<PROD_ID_LEN; ++i)
2066 + he_dev->prod_id[i] = read_prom_byte(he_dev, PROD_ID + i);
2068 + he_dev->media = read_prom_byte(he_dev, MEDIA);
2070 + for(i=0; i<6; ++i)
2071 + dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i);
2073 + hprintk("%s%s, %x:%x:%x:%x:%x:%x\n",
2075 + he_dev->media & 0x40 ? "SM" : "MM",
2082 + he_dev->atm_dev->link_rate = he_is622(he_dev) ?
2083 + ATM_OC12_PCR : ATM_OC3_PCR;
2085 + /* 4.6 set host endianess */
2086 + lb_swap = he_readl(he_dev, LB_SWAP);
2087 + if (he_is622(he_dev))
2088 + lb_swap &= ~XFER_SIZE; /* 4 cells */
2090 + lb_swap |= XFER_SIZE; /* 8 cells */
2091 +#ifdef __BIG_ENDIAN
2092 + lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST;
2094 + lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST |
2095 + DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP);
2096 +#endif /* __BIG_ENDIAN */
2097 + he_writel(he_dev, lb_swap, LB_SWAP);
2099 + /* 4.8 sdram controller initialization */
2100 + he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL);
2102 + /* 4.9 initialize rnum value */
2103 + lb_swap |= SWAP_RNUM_MAX(0xf);
2104 + he_writel(he_dev, lb_swap, LB_SWAP);
2106 + /* 4.10 initialize the interrupt queues */
2107 + if ((err = he_init_irq(he_dev)) != 0) return err;
2110 + tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
2112 + spin_lock_init(&he_dev->global_lock);
2113 + spin_lock_init(&he_dev->tpdrq_lock);
2115 + /* 4.11 enable pci bus controller state machines */
2116 + host_cntl |= (OUTFF_ENB | CMDFF_ENB |
2117 + QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB);
2118 + he_writel(he_dev, host_cntl, HOST_CNTL);
2120 + gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB;
2121 + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
2124 + * atm network controller initialization
2127 + /* 5.1.1 generic configuration state */
2130 + * local (cell) buffer memory map
2134 + * 0 ____________1023 bytes 0 _______________________2047 bytes
2136 + * | utility | | rx0 | |
2137 + * 5|____________| 255|___________________| u |
2140 + * | rx0 | row | tx | l |
2142 + * | | 767|___________________| t |
2143 + * 517|____________| 768| | y |
2144 + * row 518| | | rx1 | |
2145 + * | | 1023|___________________|___|
2150 + * 1535|____________|
2153 + * 2047|____________|
2157 + /* total 4096 connections */
2158 + he_dev->vcibits = CONFIG_DEFAULT_VCIBITS;
2159 + he_dev->vpibits = CONFIG_DEFAULT_VPIBITS;
2161 + if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS)
2163 + hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS);
2167 + if (nvpibits != -1)
2169 + he_dev->vpibits = nvpibits;
2170 + he_dev->vcibits = HE_MAXCIDBITS - nvpibits;
2173 + if (nvcibits != -1)
2175 + he_dev->vcibits = nvcibits;
2176 + he_dev->vpibits = HE_MAXCIDBITS - nvcibits;
2180 + if (he_is622(he_dev))
2182 + he_dev->cells_per_row = 40;
2183 + he_dev->bytes_per_row = 2048;
2184 + he_dev->r0_numrows = 256;
2185 + he_dev->tx_numrows = 512;
2186 + he_dev->r1_numrows = 256;
2187 + he_dev->r0_startrow = 0;
2188 + he_dev->tx_startrow = 256;
2189 + he_dev->r1_startrow = 768;
2193 + he_dev->cells_per_row = 20;
2194 + he_dev->bytes_per_row = 1024;
2195 + he_dev->r0_numrows = 512;
2196 + he_dev->tx_numrows = 1018;
2197 + he_dev->r1_numrows = 512;
2198 + he_dev->r0_startrow = 6;
2199 + he_dev->tx_startrow = 518;
2200 + he_dev->r1_startrow = 1536;
2203 + he_dev->cells_per_lbuf = 4;
2204 + he_dev->buffer_limit = 4;
2205 + he_dev->r0_numbuffs = he_dev->r0_numrows *
2206 + he_dev->cells_per_row / he_dev->cells_per_lbuf;
2207 + if (he_dev->r0_numbuffs > 2560) he_dev->r0_numbuffs = 2560;
2209 + he_dev->r1_numbuffs = he_dev->r1_numrows *
2210 + he_dev->cells_per_row / he_dev->cells_per_lbuf;
2211 + if (he_dev->r1_numbuffs > 2560) he_dev->r1_numbuffs = 2560;
2213 + he_dev->tx_numbuffs = he_dev->tx_numrows *
2214 + he_dev->cells_per_row / he_dev->cells_per_lbuf;
2215 + if (he_dev->tx_numbuffs > 5120) he_dev->tx_numbuffs = 5120;
2217 + /* 5.1.2 configure hardware dependent registers */
2220 + SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) |
2221 + RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) |
2222 + (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) |
2223 + (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)),
2226 + he_writel(he_dev, BANK_ON |
2227 + (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)),
2231 + (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) |
2232 + RM_RW_WAIT(1), RCMCONFIG);
2234 + (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) |
2235 + TM_RW_WAIT(1), TCMCONFIG);
2237 + he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG);
2240 + (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) |
2241 + (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) |
2242 + RX_VALVP(he_dev->vpibits) |
2243 + RX_VALVC(he_dev->vcibits), RC_CONFIG);
2245 + he_writel(he_dev, DRF_THRESH(0x20) |
2246 + (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) |
2247 + TX_VCI_MASK(he_dev->vcibits) |
2248 + LBFREE_CNT(he_dev->tx_numbuffs), TX_CONFIG);
2250 + he_writel(he_dev, 0x0, TXAAL5_PROTO);
2252 + he_writel(he_dev, PHY_INT_ENB |
2253 + (he_is622(he_dev) ? PTMR_PRE(67-1) : PTMR_PRE(50-1)),
2256 + /* 5.1.3 initialize connection memory */
2258 + for(i=0; i < TCM_MEM_SIZE; ++i)
2259 + he_writel_tcm(he_dev, 0, i);
2261 + for(i=0; i < RCM_MEM_SIZE; ++i)
2262 + he_writel_rcm(he_dev, 0, i);
2265 + * transmit connection memory map
2268 + * 0x0 ___________________
2274 + * 0x8000|___________________|
2277 + * 0xc000|___________________|
2280 + * 0xe000|___________________|
2282 + * 0xf000|___________________|
2284 + * 0x10000|___________________|
2287 + * |___________________|
2290 + * 0x1ffff|___________________|
2295 + he_writel(he_dev, CONFIG_TSRB, TSRB_BA);
2296 + he_writel(he_dev, CONFIG_TSRC, TSRC_BA);
2297 + he_writel(he_dev, CONFIG_TSRD, TSRD_BA);
2298 + he_writel(he_dev, CONFIG_TMABR, TMABR_BA);
2299 + he_writel(he_dev, CONFIG_TPDBA, TPD_BA);
2303 + * receive connection memory map
2305 + * 0x0 ___________________
2311 + * 0x8000|___________________|
2314 + * | LBM | link lists of local
2315 + * | tx | buffer memory
2317 + * 0xd000|___________________|
2320 + * 0xe000|___________________|
2323 + * |___________________|
2326 + * 0xffff|___________________|
2329 + he_writel(he_dev, 0x08000, RCMLBM_BA);
2330 + he_writel(he_dev, 0x0e000, RCMRSRB_BA);
2331 + he_writel(he_dev, 0x0d800, RCMABR_BA);
2333 + /* 5.1.4 initialize local buffer free pools linked lists */
2335 + he_init_rx_lbfp0(he_dev);
2336 + he_init_rx_lbfp1(he_dev);
2338 + he_writel(he_dev, 0x0, RLBC_H);
2339 + he_writel(he_dev, 0x0, RLBC_T);
2340 + he_writel(he_dev, 0x0, RLBC_H2);
2342 + he_writel(he_dev, 512, RXTHRSH); /* 10% of r0+r1 buffers */
2343 + he_writel(he_dev, 256, LITHRSH); /* 5% of r0+r1 buffers */
2345 + he_init_tx_lbfp(he_dev);
2347 + he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA);
2349 + /* 5.1.5 initialize intermediate receive queues */
2351 + if (he_is622(he_dev))
2353 + he_writel(he_dev, 0x000f, G0_INMQ_S);
2354 + he_writel(he_dev, 0x200f, G0_INMQ_L);
2356 + he_writel(he_dev, 0x001f, G1_INMQ_S);
2357 + he_writel(he_dev, 0x201f, G1_INMQ_L);
2359 + he_writel(he_dev, 0x002f, G2_INMQ_S);
2360 + he_writel(he_dev, 0x202f, G2_INMQ_L);
2362 + he_writel(he_dev, 0x003f, G3_INMQ_S);
2363 + he_writel(he_dev, 0x203f, G3_INMQ_L);
2365 + he_writel(he_dev, 0x004f, G4_INMQ_S);
2366 + he_writel(he_dev, 0x204f, G4_INMQ_L);
2368 + he_writel(he_dev, 0x005f, G5_INMQ_S);
2369 + he_writel(he_dev, 0x205f, G5_INMQ_L);
2371 + he_writel(he_dev, 0x006f, G6_INMQ_S);
2372 + he_writel(he_dev, 0x206f, G6_INMQ_L);
2374 + he_writel(he_dev, 0x007f, G7_INMQ_S);
2375 + he_writel(he_dev, 0x207f, G7_INMQ_L);
2379 + he_writel(he_dev, 0x0000, G0_INMQ_S);
2380 + he_writel(he_dev, 0x0008, G0_INMQ_L);
2382 + he_writel(he_dev, 0x0001, G1_INMQ_S);
2383 + he_writel(he_dev, 0x0009, G1_INMQ_L);
2385 + he_writel(he_dev, 0x0002, G2_INMQ_S);
2386 + he_writel(he_dev, 0x000a, G2_INMQ_L);
2388 + he_writel(he_dev, 0x0003, G3_INMQ_S);
2389 + he_writel(he_dev, 0x000b, G3_INMQ_L);
2391 + he_writel(he_dev, 0x0004, G4_INMQ_S);
2392 + he_writel(he_dev, 0x000c, G4_INMQ_L);
2394 + he_writel(he_dev, 0x0005, G5_INMQ_S);
2395 + he_writel(he_dev, 0x000d, G5_INMQ_L);
2397 + he_writel(he_dev, 0x0006, G6_INMQ_S);
2398 + he_writel(he_dev, 0x000e, G6_INMQ_L);
2400 + he_writel(he_dev, 0x0007, G7_INMQ_S);
2401 + he_writel(he_dev, 0x000f, G7_INMQ_L);
2404 + /* 5.1.6 application tunable parameters */
2406 + he_writel(he_dev, 0x0, MCC);
2407 + he_writel(he_dev, 0x0, OEC);
2408 + he_writel(he_dev, 0x0, DCC);
2409 + he_writel(he_dev, 0x0, CEC);
2411 + /* 5.1.7 cs block initialization */
2413 + he_init_cs_block(he_dev);
2415 + /* 5.1.8 cs block connection memory initialization */
2417 + he_init_cs_block_rcm(he_dev);
2419 + /* 5.1.10 initialize host structures */
2421 + he_init_tpdrq(he_dev);
2423 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
2424 + he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
2425 + sizeof(struct he_tpd), TPD_ALIGNMENT, 0, SLAB_KERNEL);
2427 + he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
2428 + sizeof(struct he_tpd), TPD_ALIGNMENT, 0);
2430 + if (he_dev->tpd_pool == NULL)
2432 + hprintk1("unable to create tpd pci_pool\n");
2435 + INIT_LIST_HEAD(&he_dev->outstanding_tpds);
2437 + if (he_init_group(he_dev, 0) != 0)
2440 + for (group = 1; group < HE_NUM_GROUPS; ++group)
2442 + he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
2443 + he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
2444 + he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
2445 + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
2446 + G0_RBPS_BS + (group * 32));
2448 + he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32));
2449 + he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32));
2450 + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
2451 + G0_RBPL_QI + (group * 32));
2452 + he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32));
2454 + he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16));
2455 + he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16));
2456 + he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0),
2457 + G0_RBRQ_Q + (group * 16));
2458 + he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16));
2460 + he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16));
2461 + he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16));
2462 + he_writel(he_dev, TBRQ_THRESH(0x1),
2463 + G0_TBRQ_THRESH + (group * 16));
2464 + he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16));
2467 + /* host status page */
2469 + he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev,
2470 + sizeof(struct he_hsp), &he_dev->hsp_phys);
2471 + if (he_dev->hsp == NULL)
2473 + hprintk1("failed to allocate host status page\n");
2476 + memset(he_dev->hsp, 0, sizeof(struct he_hsp));
2477 + he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
2479 + /* initialize framer */
2481 +#ifdef CONFIG_ATM_HE_USE_SUNI
2482 + suni_init(he_dev->atm_dev);
2483 + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start)
2484 + he_dev->atm_dev->phy->start(he_dev->atm_dev);
2485 +#endif /* CONFIG_ATM_HE_USE_SUNI */
2489 + /* this really should be in suni.c but for now... */
2493 + val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM);
2494 + val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT);
2495 + he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);
2498 + /* 5.1.12 enable transmit and receive */
2500 + reg = he_readl_mbox(he_dev, CS_ERCTL0);
2501 + reg |= TX_ENABLE|ER_ENABLE;
2502 + he_writel_mbox(he_dev, reg, CS_ERCTL0);
2504 + reg = he_readl(he_dev, RC_CONFIG);
2506 + he_writel(he_dev, reg, RC_CONFIG);
2508 +#ifndef USE_HE_FIND_VCC
2509 + he_dev->he_vcc_table = kmalloc(sizeof(struct he_vcc_table) *
2510 + (1 << (he_dev->vcibits + he_dev->vpibits)), GFP_KERNEL);
2511 + if (he_dev->he_vcc_table == NULL)
2513 + hprintk1("failed to alloc he_vcc_table\n");
2516 + memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) *
2517 + (1 << (he_dev->vcibits + he_dev->vpibits)));
2520 + for (i = 0; i < HE_NUM_CS_STPER; ++i)
2522 + he_dev->cs_stper[i].inuse = 0;
2523 + he_dev->cs_stper[i].pcr = -1;
2525 + he_dev->total_bw = 0;
2528 + /* atm linux initialization */
2530 + he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits;
2531 + he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits;
2533 + he_dev->irq_peak = 0;
2534 + he_dev->rbrq_peak = 0;
2535 + he_dev->rbpl_peak = 0;
2536 + he_dev->tbrq_peak = 0;
2538 + hprintk1("hell bent for leather!\n");
2544 +he_stop(struct he_dev *he_dev)
2547 + u32 gen_cntl_0, reg;
2548 + struct pci_dev *pci_dev;
2551 + pci_dev = he_dev->pci_dev;
2553 + /* disable interrupts */
2555 + if (he_dev->membase)
2557 + pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0);
2558 + gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB);
2559 + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
2562 + tasklet_disable(&he_dev->tasklet);
2565 + /* disable recv and transmit */
2567 + reg = he_readl_mbox(he_dev, CS_ERCTL0);
2568 + reg &= ~(TX_ENABLE|ER_ENABLE);
2569 + he_writel_mbox(he_dev, reg, CS_ERCTL0);
2571 + reg = he_readl(he_dev, RC_CONFIG);
2572 + reg &= ~(RX_ENABLE);
2573 + he_writel(he_dev, reg, RC_CONFIG);
2576 +#ifdef CONFIG_ATM_HE_USE_SUNI
2577 + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop)
2578 + he_dev->atm_dev->phy->stop(he_dev->atm_dev);
2579 +#endif /* CONFIG_ATM_HE_USE_SUNI */
2584 + sn_delete_polled_interrupt(he_dev->irq);
2586 + free_irq(he_dev->irq, he_dev);
2589 + if (he_dev->irq_base)
2590 + pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1)
2591 + * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys);
2594 + pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp),
2595 + he_dev->hsp, he_dev->hsp_phys);
2597 + if (he_dev->rbpl_base)
2599 + for (i=0; i<CONFIG_RBPL_SIZE; ++i)
2601 + void *cpuaddr = he_dev->rbpl_virt[i].virt;
2602 + dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
2604 +#ifdef USE_RBPL_POOL
2605 + pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle);
2607 + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_BUFSIZE, cpuaddr, dma_handle);
2610 + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
2611 + * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);
2614 +#ifdef USE_RBPL_POOL
2615 + if (he_dev->rbpl_pool)
2616 + pci_pool_destroy(he_dev->rbpl_pool);
2620 + if (he_dev->rbps_base)
2622 + for (i=0; i<CONFIG_RBPS_SIZE; ++i)
2624 + void *cpuaddr = he_dev->rbps_virt[i].virt;
2625 + dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
2627 + pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle);
2629 + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
2630 + * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys);
2632 +#endif /* USE_RBPS */
2634 + if (he_dev->rbrq_base)
2635 + pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
2636 + he_dev->rbrq_base, he_dev->rbrq_phys);
2638 + if (he_dev->tbrq_base)
2639 + pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
2640 + he_dev->tbrq_base, he_dev->tbrq_phys);
2642 + if (he_dev->tpdrq_base)
2643 + pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
2644 + he_dev->tpdrq_base, he_dev->tpdrq_phys);
2646 + if (he_dev->tpd_pool)
2647 + pci_pool_destroy(he_dev->tpd_pool);
2649 +#ifndef USE_HE_FIND_VCC
2650 + if (he_dev->he_vcc_table)
2651 + kfree(he_dev->he_vcc_table);
2654 + if (he_dev->pci_dev)
2656 + pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command);
2657 + command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
2658 + pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command);
2661 + if (he_dev->membase) iounmap((void *) he_dev->membase);
2664 +static __inline__ struct he_tpd *
2665 +he_alloc_tpd(struct he_dev *he_dev)
2667 + struct he_tpd *tpd;
2668 + dma_addr_t dma_handle;
2670 + tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle);
2674 + tpd->status = TPD_ADDR(dma_handle);
2675 + tpd->reserved = 0;
2676 + tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0;
2677 + tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0;
2678 + tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0;
2684 +#define AAL5_LEN(buf,len) \
2685 + ((((unsigned char *)(buf))[(len)-6]<<8) | \
2686 + (((unsigned char *)(buf))[(len)-5]))
2688 +/* 2.10.1.2 receive
2690 + * aal5 packets can optionally return the tcp checksum in the lower
2691 + * 16 bits of the crc (RSR0_TCP_CKSUM)
2694 +#define TCP_CKSUM(buf,len) \
2695 + ((((unsigned char *)(buf))[(len)-2]<<8) | \
2696 + (((unsigned char *)(buf))[(len-1)]))
2699 +he_service_rbrq(struct he_dev *he_dev, int group)
2701 + struct he_rbrq *rbrq_tail = (struct he_rbrq *)
2702 + ((unsigned long)he_dev->rbrq_base |
2703 + he_dev->hsp->group[group].rbrq_tail);
2704 + struct he_rbp *rbp = NULL;
2705 + unsigned cid, lastcid = -1;
2706 + unsigned buf_len = 0;
2707 + struct sk_buff *skb;
2708 + struct atm_vcc *vcc = NULL;
2709 + struct he_vcc *he_vcc;
2710 + struct iovec *iov;
2711 + int pdus_assembled = 0;
2714 + read_lock(&vcc_sklist_lock);
2715 + while (he_dev->rbrq_head != rbrq_tail)
2719 + HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n",
2720 + he_dev->rbrq_head, group,
2721 + RBRQ_ADDR(he_dev->rbrq_head),
2722 + RBRQ_BUFLEN(he_dev->rbrq_head),
2723 + RBRQ_CID(he_dev->rbrq_head),
2724 + RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "",
2725 + RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "",
2726 + RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "",
2727 + RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "",
2728 + RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "",
2729 + RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");
2732 + if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF)
2733 + rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
2736 + rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
2738 + buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
2739 + cid = RBRQ_CID(he_dev->rbrq_head);
2741 +#ifdef USE_HE_FIND_VCC
2742 + if (cid != lastcid)
2743 + vcc = he_find_vcc(he_dev, cid);
2746 + vcc = HE_LOOKUP_VCC(he_dev, cid);
2750 + hprintk("vcc == NULL (cid 0x%x)\n", cid);
2751 + if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
2752 + rbp->status &= ~RBP_LOANED;
2754 + goto next_rbrq_entry;
2757 + he_vcc = HE_VCC(vcc);
2758 + if (he_vcc == NULL)
2760 + hprintk("he_vcc == NULL (cid 0x%x)\n", cid);
2761 + if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
2762 + rbp->status &= ~RBP_LOANED;
2763 + goto next_rbrq_entry;
2766 + if (RBRQ_HBUF_ERR(he_dev->rbrq_head))
2768 + hprintk("HBUF_ERR! (cid 0x%x)\n", cid);
2769 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
2770 + ++vcc->stats->rx_drop;
2772 + atomic_inc(&vcc->stats->rx_drop);
2774 + goto return_host_buffers;
2777 + he_vcc->iov_tail->iov_base = (void *) RBRQ_ADDR(he_dev->rbrq_head);
2778 + he_vcc->iov_tail->iov_len = buf_len;
2779 + he_vcc->pdu_len += buf_len;
2780 + ++he_vcc->iov_tail;
2782 + if (RBRQ_CON_CLOSED(he_dev->rbrq_head))
2785 + HPRINTK("wake_up rx_waitq (cid 0x%x)\n", cid);
2786 + wake_up(&he_vcc->rx_waitq);
2787 + goto return_host_buffers;
2791 + if (he_vcc->iov_tail - he_vcc->iov_head > 32)
2793 + hprintk("iovec full! cid 0x%x\n", cid);
2794 + goto return_host_buffers;
2797 + if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry;
2799 + if (RBRQ_LEN_ERR(he_dev->rbrq_head)
2800 + || RBRQ_CRC_ERR(he_dev->rbrq_head))
2802 + HPRINTK("%s%s (%d.%d)\n",
2803 + RBRQ_CRC_ERR(he_dev->rbrq_head)
2804 + ? "CRC_ERR " : "",
2805 + RBRQ_LEN_ERR(he_dev->rbrq_head)
2807 + vcc->vpi, vcc->vci);
2808 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
2809 + ++vcc->stats->rx_err;
2811 + atomic_inc(&vcc->stats->rx_err);
2813 + goto return_host_buffers;
2816 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,15)
2817 + skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve,
2820 + if (!atm_charge(vcc, atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve)))
2824 + skb = alloc_skb(he_vcc->pdu_len + rx_skb_reserve, GFP_ATOMIC);
2825 + if (!skb) atm_return(vcc,
2826 + atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve));
2831 + HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci);
2832 + goto return_host_buffers;
2835 + if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve);
2837 + do_gettimeofday(&skb->stamp);
2839 + for(iov = he_vcc->iov_head;
2840 + iov < he_vcc->iov_tail; ++iov)
2843 + if ((u32)iov->iov_base & RBP_SMALLBUF)
2844 + memcpy(skb_put(skb, iov->iov_len),
2845 + he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
2848 + memcpy(skb_put(skb, iov->iov_len),
2849 + he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
2852 + switch(vcc->qos.aal)
2855 + /* 2.10.1.5 raw cell receive */
2856 + skb->len = ATM_AAL0_SDU;
2857 + skb->tail = skb->data + skb->len;
2860 + /* 2.10.1.2 aal5 receive */
2862 + skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len);
2863 + skb->tail = skb->data + skb->len;
2864 +#ifdef USE_CHECKSUM_HW
2865 + if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI)
2867 + skb->ip_summed = CHECKSUM_HW;
2868 + skb->csum = TCP_CKSUM(skb->data,
2875 +#ifdef should_never_happen
2876 + if (skb->len > vcc->qos.rxtp.max_sdu)
2877 + hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)! cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid);
2881 + ATM_SKB(skb)->vcc = vcc;
2883 + vcc->push(vcc, skb);
2885 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
2888 + atomic_inc(&vcc->stats->rx);
2891 +return_host_buffers:
2894 + for(iov = he_vcc->iov_head;
2895 + iov < he_vcc->iov_tail; ++iov)
2898 + if ((u32)iov->iov_base & RBP_SMALLBUF)
2899 + rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)];
2902 + rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)];
2904 + rbp->status &= ~RBP_LOANED;
2907 + he_vcc->iov_tail = he_vcc->iov_head;
2908 + he_vcc->pdu_len = 0;
2911 + he_dev->rbrq_head = (struct he_rbrq *)
2912 + ((unsigned long) he_dev->rbrq_base |
2913 + RBRQ_MASK(++he_dev->rbrq_head));
2916 + read_unlock(&vcc_sklist_lock);
2920 + if (updated > he_dev->rbrq_peak) he_dev->rbrq_peak = updated;
2922 + he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head),
2923 + G0_RBRQ_H + (group * 16));
2926 + return pdus_assembled;
2930 +he_service_tbrq(struct he_dev *he_dev, int group)
2932 + struct he_tbrq *tbrq_tail = (struct he_tbrq *)
2933 + ((unsigned long)he_dev->tbrq_base |
2934 + he_dev->hsp->group[group].tbrq_tail);
2935 + struct he_tpd *tpd;
2936 + int slot, updated = 0;
2937 + struct list_head *list;
2939 + /* 2.1.6 transmit buffer return queue */
2941 + while (he_dev->tbrq_head != tbrq_tail)
2945 + HPRINTK("tbrq%d 0x%x%s%s\n",
2947 + TBRQ_TPD(he_dev->tbrq_head),
2948 + TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "",
2949 + TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
2952 + list = &he_dev->outstanding_tpds;
2953 + while ((list = list->next) != &he_dev->outstanding_tpds)
2955 + struct he_tpd *_tpd = list_entry(list, struct he_tpd, entry);
2956 + if (TPD_ADDR(_tpd->status) == TBRQ_TPD(he_dev->tbrq_head))
2959 + list_del(&_tpd->entry);
2966 + hprintk("unable to locate tpd for dma buffer %x\n",
2967 + TBRQ_TPD(he_dev->tbrq_head));
2968 + goto next_tbrq_entry;
2971 + if (TBRQ_EOS(he_dev->tbrq_head))
2973 + HPRINTK("wake_up(tx_waitq) cid 0x%x\n",
2974 + he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci));
2976 + wake_up(&HE_VCC(tpd->vcc)->tx_waitq);
2978 + goto next_tbrq_entry;
2981 + for(slot = 0; slot < TPD_MAXIOV; ++slot)
2983 + if (tpd->iovec[slot].addr)
2984 + pci_unmap_single(he_dev->pci_dev,
2985 + tpd->iovec[slot].addr,
2986 + tpd->iovec[slot].len & TPD_LEN_MASK,
2987 + PCI_DMA_TODEVICE);
2988 + if (tpd->iovec[slot].len & TPD_LST) break;
2992 + if (tpd->skb) /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */
2994 + if (tpd->vcc && tpd->vcc->pop)
2995 + tpd->vcc->pop(tpd->vcc, tpd->skb);
2997 + dev_kfree_skb_any(tpd->skb);
3002 + pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
3004 + he_dev->tbrq_head = (struct he_tbrq *)
3005 + ((unsigned long) he_dev->tbrq_base |
3006 + TBRQ_MASK(++he_dev->tbrq_head));
3011 + if (updated > he_dev->tbrq_peak) he_dev->tbrq_peak = updated;
3013 + he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head),
3014 + G0_TBRQ_H + (group * 16));
3020 +he_service_rbpl(struct he_dev *he_dev, int group)
3022 + struct he_rbp *newtail;
3023 + struct he_rbp *rbpl_head;
3026 + rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
3027 + RBPL_MASK(he_readl(he_dev, G0_RBPL_S)));
3031 + newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
3032 + RBPL_MASK(he_dev->rbpl_tail+1));
3034 + /* table 3.42 -- rbpl_tail should never be set to rbpl_head */
3035 + if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED))
3038 + newtail->status |= RBP_LOANED;
3039 + he_dev->rbpl_tail = newtail;
3045 + he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
3050 +he_service_rbps(struct he_dev *he_dev, int group)
3052 + struct he_rbp *newtail;
3053 + struct he_rbp *rbps_head;
3056 + rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
3057 + RBPS_MASK(he_readl(he_dev, G0_RBPS_S)));
3061 + newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
3062 + RBPS_MASK(he_dev->rbps_tail+1));
3064 + /* table 3.42 -- rbps_tail should never be set to rbps_head */
3065 + if ((newtail == rbps_head) || (newtail->status & RBP_LOANED))
3068 + newtail->status |= RBP_LOANED;
3069 + he_dev->rbps_tail = newtail;
3075 + he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T);
3077 +#endif /* USE_RBPS */
3080 +he_tasklet(unsigned long data)
3082 + unsigned long flags;
3083 + struct he_dev *he_dev = (struct he_dev *) data;
3087 + HPRINTK("tasklet (0x%lx)\n", data);
3089 + HE_SPIN_LOCK(he_dev, flags);
3092 + while(he_dev->irq_head != he_dev->irq_tail)
3096 + type = ITYPE_TYPE(he_dev->irq_head->isw);
3097 + group = ITYPE_GROUP(he_dev->irq_head->isw);
3101 + case ITYPE_RBRQ_THRESH:
3102 + hprintk("rbrq%d threshold\n", group);
3103 + case ITYPE_RBRQ_TIMER:
3104 + if (he_service_rbrq(he_dev, group))
3106 + he_service_rbpl(he_dev, group);
3108 + he_service_rbps(he_dev, group);
3109 +#endif /* USE_RBPS */
3112 + case ITYPE_TBRQ_THRESH:
3113 + hprintk("tbrq%d threshold\n", group);
3114 + case ITYPE_TPD_COMPLETE:
3115 + he_service_tbrq(he_dev, group);
3117 + case ITYPE_RBPL_THRESH:
3118 + he_service_rbpl(he_dev, group);
3120 + case ITYPE_RBPS_THRESH:
3122 + he_service_rbps(he_dev, group);
3123 +#endif /* USE_RBPS */
3126 +#ifdef CONFIG_ATM_HE_USE_SUNI
3127 + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt)
3128 + he_dev->atm_dev->phy->interrupt(he_dev->atm_dev);
3130 + HPRINTK1("phy interrupt\n");
3133 + switch (type|group)
3135 + case ITYPE_PARITY:
3136 + hprintk1("parity error\n");
3139 + hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR));
3144 + if (he_dev->irq_head->isw == ITYPE_INVALID)
3146 + /* see 8.1.1 -- check all queues */
3148 + HPRINTK("isw not updated 0x%x\n",
3149 + he_dev->irq_head->isw);
3151 + he_service_rbrq(he_dev, 0);
3152 + he_service_rbpl(he_dev, 0);
3154 + he_service_rbps(he_dev, 0);
3155 +#endif /* USE_RBPS */
3156 + he_service_tbrq(he_dev, 0);
3159 + hprintk("bad isw = 0x%x?\n",
3160 + he_dev->irq_head->isw);
3163 + he_dev->irq_head->isw = ITYPE_INVALID;
3165 + he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK);
3170 + if (updated > he_dev->irq_peak) he_dev->irq_peak = updated;
3173 + IRQ_SIZE(CONFIG_IRQ_SIZE) |
3174 + IRQ_THRESH(CONFIG_IRQ_THRESH) |
3175 + IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD);
3176 + (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */
3179 + HE_SPIN_UNLOCK(he_dev, flags);
3184 +he_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
3186 + unsigned long flags;
3187 + struct he_dev *he_dev = (struct he_dev * )dev_id;
3189 + if (he_dev == NULL) return;
3191 + HE_SPIN_LOCK(he_dev, flags);
3193 + he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) |
3194 + (*he_dev->irq_tailoffset << 2));
3196 + if (he_dev->irq_tail == he_dev->irq_head)
3198 + HPRINTK1("tailoffset not updated?\n");
3199 + he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base |
3200 + ((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2));
3201 + (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */
3205 + if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */)
3206 + hprintk1("spurious interrupt?\n");
3209 + if (he_dev->irq_head != he_dev->irq_tail)
3212 + tasklet_schedule(&he_dev->tasklet);
3214 + he_tasklet((unsigned long) he_dev);
3216 + he_writel(he_dev, INT_CLEAR_A, INT_FIFO);
3217 + /* clear interrupt */
3220 + HE_SPIN_UNLOCK(he_dev, flags);
3223 +static __inline__ void
3224 +he_enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
3226 + struct he_tpdrq *new_tail;
3229 + spin_lock_irqsave(&he_dev->tpdrq_lock, flags);
3231 + HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n",
3232 + tpd, cid, he_dev->tpdrq_tail);
3234 + new_tail = he_dev->tpdrq_tail;
3235 + new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base |
3236 + TPDRQ_MASK(++new_tail));
3239 + * check to see if we are about to set the tail == head
3240 + * if true, update the head pointer from the adapter
3241 + * to see if this is really the case (reading the queue
3242 + * head for every enqueue would be unnecessarily slow)
3245 + if (new_tail == he_dev->tpdrq_head)
3247 + he_dev->tpdrq_head = (struct he_tpdrq *)
3248 + (((unsigned long)he_dev->tpdrq_base) |
3249 + TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H)));
3251 + if (new_tail == he_dev->tpdrq_head)
3253 + hprintk("tpdrq full (cid 0x%x)\n", cid);
3256 + * push tpd onto a transmit backlog queue
3257 + * after service_tbrq, service the backlog
3258 + * for now, we just drop the pdu
3262 + if (tpd->vcc->pop)
3263 + tpd->vcc->pop(tpd->vcc, tpd->skb);
3265 + dev_kfree_skb_any(tpd->skb);
3266 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3267 + ++tpd->vcc->stats->tx_err;
3269 + atomic_inc(&tpd->vcc->stats->tx_err);
3272 + pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
3273 + spin_unlock_irqrestore(&he_dev->tpdrq_lock, flags);
3278 + /* 2.1.5 transmit packet descriptor ready queue */
3279 + he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status);
3280 + he_dev->tpdrq_tail->cid = cid;
3282 + list_add_tail(&tpd->entry, &he_dev->outstanding_tpds);
3284 + he_dev->tpdrq_tail = new_tail;
3286 + he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T);
3287 + spin_unlock_irqrestore(&he_dev->tpdrq_lock, flags);
3291 +he_open(struct atm_vcc *vcc, short vpi, int vci)
3293 + unsigned long flags;
3294 + struct he_dev *he_dev = HE_DEV(vcc->dev);
3295 + struct he_vcc *he_vcc;
3297 + unsigned cid, rsr0, rsr1, rsr4, tsr0, period, reg, clock;
3298 + int first_open = 0;
3300 + if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0;
3304 + HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci);
3306 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3307 + vcc->flags |= ATM_VF_ADDR;
3309 + set_bit(ATM_VF_ADDR, &vcc->flags);
3312 + cid = he_mkcid(he_dev, vpi, vci);
3314 + he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_KERNEL);
3315 + if (he_vcc == NULL)
3317 + hprintk1("unable to allocate he_vcc during open\n");
3321 + he_vcc->iov_tail = he_vcc->iov_head;
3322 + he_vcc->pdu_len = 0;
3323 + he_vcc->rc_index = -1;
3325 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3326 + init_waitqueue(&he_vcc->rx_waitq);
3327 + init_waitqueue(&he_vcc->tx_waitq);
3329 + init_waitqueue_head(&he_vcc->rx_waitq);
3330 + init_waitqueue_head(&he_vcc->tx_waitq);
3333 + HE_VCC(vcc) = he_vcc;
3335 + if (vcc->qos.txtp.traffic_class != ATM_NONE)
3339 + pcr_goal = atm_pcr_goal(&vcc->qos.txtp);
3340 + if (pcr_goal == 0)
3341 + pcr_goal = he_dev->atm_dev->link_rate;
3342 + if (pcr_goal < 0) /* means round down, technically */
3343 + pcr_goal = -pcr_goal;
3345 + HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal);
3347 + /* no transmit support for AAL0 -- FIXME */
3349 + if (vcc->qos.aal != ATM_AAL5)
3355 + HE_SPIN_LOCK(he_dev, flags);
3356 + tsr0 = he_readl_tsr0(he_dev, cid);
3357 + HE_SPIN_UNLOCK(he_dev, flags);
3359 + if (tsr0 == 0 && vcc->qos.aal == ATM_AAL5) first_open = 1;
3361 + if (TSR0_CONN_STATE(tsr0) != 0)
3363 + hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0);
3370 + switch(vcc->qos.txtp.traffic_class)
3373 + /* 2.3.3.1 open connection ubr */
3375 + tsr0 = TSR0_UBR | TSR0_GROUP(0) | TSR0_AAL5 |
3376 + TSR0_USE_WMIN | TSR0_UPDATE_GER;
3380 + /* 2.3.3.2 open connection cbr */
3382 + clock = he_is622(he_dev) ? 66667000 : 50000000;
3383 + period = clock / pcr_goal;
3385 + /* find an unused cs_stper register */
3387 + for(reg = 0; reg < HE_NUM_CS_STPER; ++reg)
3388 + if (he_dev->cs_stper[reg].inuse == 0 ||
3389 + he_dev->cs_stper[reg].pcr == pcr_goal)
3392 + if (reg == HE_NUM_CS_STPER)
3398 + /* 8.2.3 cbr scheduler wrap problem */
3399 + if ((he_dev->total_bw + pcr_goal)
3400 + > (he_dev->atm_dev->link_rate * 10 / 9))
3405 + he_dev->total_bw += pcr_goal;
3407 + he_vcc->rc_index = reg;
3408 + ++he_dev->cs_stper[reg].inuse;
3409 + he_dev->cs_stper[reg].pcr = pcr_goal;
3411 + HPRINTK("rc_index = %d period = %d\n",
3414 + HE_SPIN_LOCK(he_dev, flags);
3415 + he_writel_mbox(he_dev, rate_to_atmf(period/2),
3417 + HE_SPIN_UNLOCK(he_dev, flags);
3419 + tsr0 = TSR0_CBR | TSR0_GROUP(0) | TSR0_AAL5 |
3420 + TSR0_RC_INDEX(reg);
3428 + HE_SPIN_LOCK(he_dev, flags);
3430 + he_writel_tsr0(he_dev, tsr0, cid);
3431 + he_writel_tsr4(he_dev, TSR4_AAL5 | 1, cid);
3432 + he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) |
3433 + TSR1_PCR(rate_to_atmf(pcr_goal)), cid);
3434 + he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid);
3435 + he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid);
3437 + he_writel_tsr3(he_dev, 0x0, cid);
3438 + he_writel_tsr5(he_dev, 0x0, cid);
3439 + he_writel_tsr6(he_dev, 0x0, cid);
3440 + he_writel_tsr7(he_dev, 0x0, cid);
3441 + he_writel_tsr8(he_dev, 0x0, cid);
3442 + he_writel_tsr10(he_dev, 0x0, cid);
3443 + he_writel_tsr11(he_dev, 0x0, cid);
3444 + he_writel_tsr12(he_dev, 0x0, cid);
3445 + he_writel_tsr13(he_dev, 0x0, cid);
3446 + he_writel_tsr14(he_dev, 0x0, cid);
3450 + * the first aal5 pdu sent always seems to have a bad
3451 + * crc. no idea why. probably initializing the card
3452 + * wrong? if tsr0 == 0 this is the first open after
3458 +#define BADCRCMESG "BAD CRC WORKAROUND"
3459 + static char *badcrc = NULL;
3460 + struct he_tpd *tpd;
3462 + tpd = he_alloc_tpd(he_dev);
3466 + badcrc = kmalloc(strlen(BADCRCMESG), GFP_DMA);
3467 + memcpy(badcrc, BADCRCMESG, strlen(BADCRCMESG));
3470 + HPRINTK("bad crc workaround cid = 0x%x\n", cid);
3472 + tpd->address0 = pci_map_single(he_dev->pci_dev,
3473 + badcrc, strlen(BADCRCMESG), PCI_DMA_TODEVICE);
3474 + tpd->length0 = strlen(BADCRCMESG) | TPD_LST;
3475 + tpd->status |= TPD_USERCELL | TPD_INT;
3480 + he_enqueue_tpd(he_dev, tpd, cid);
3483 + HE_SPIN_UNLOCK(he_dev, flags);
3486 + if (vcc->qos.rxtp.traffic_class != ATM_NONE)
3490 + HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid,
3491 + &HE_VCC(vcc)->rx_waitq);
3493 + switch (vcc->qos.aal)
3499 + aal = RSR0_RAWCELL;
3506 + HE_SPIN_LOCK(he_dev, flags);
3508 + rsr0 = he_readl_rsr0(he_dev, cid);
3509 + if (rsr0 & RSR0_OPEN_CONN)
3511 + HE_SPIN_UNLOCK(he_dev, flags);
3513 + hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0);
3519 + rsr1 = RSR1_GROUP(0);
3520 + rsr4 = RSR4_GROUP(0);
3521 +#else /* !USE_RBPS */
3522 + rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY;
3523 + rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY;
3524 +#endif /* USE_RBPS */
3525 + rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ?
3526 + (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0;
3528 +#ifdef USE_CHECKSUM_HW
3529 + if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) rsr0 |= RSR0_TCP_CKSUM;
3532 + he_writel_rsr4(he_dev, rsr4, cid);
3533 + he_writel_rsr1(he_dev, rsr1, cid);
3534 + /* 5.1.11 last parameter initialized should be
3535 + the open/closed indication in rsr0 */
3536 + he_writel_rsr0(he_dev,
3537 + rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid);
3539 + HE_SPIN_UNLOCK(he_dev, flags);
3541 +#ifndef USE_HE_FIND_VCC
3542 + HE_LOOKUP_VCC(he_dev, cid) = vcc;
3550 + if (he_vcc) kfree(he_vcc);
3551 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3552 + vcc->flags &= ~ATM_VF_ADDR;
3554 + clear_bit(ATM_VF_ADDR, &vcc->flags);
3559 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3560 + vcc->flags |= ATM_VF_READY;
3562 + set_bit(ATM_VF_READY, &vcc->flags);
3570 +he_close(struct atm_vcc *vcc)
3572 + unsigned long flags;
3573 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
3574 + DECLARE_WAITQUEUE(wait, current);
3576 + struct wait_queue wait = { current, NULL };
3578 + struct he_dev *he_dev = HE_DEV(vcc->dev);
3579 + struct he_tpd *tpd;
3581 + struct he_vcc *he_vcc = HE_VCC(vcc);
3582 +#define MAX_RETRY 30
3583 + int retry = 0, sleep = 1, tx_inuse;
3585 + HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci);
3587 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3588 + vcc->flags &= ~ATM_VF_READY;
3590 + clear_bit(ATM_VF_READY, &vcc->flags);
3592 + cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
3594 + HE_SPIN_LOCK(he_dev, flags);
3596 + if (vcc->qos.rxtp.traffic_class != ATM_NONE)
3600 + HPRINTK("close rx cid 0x%x\n", cid);
3602 + /* 2.7.2.2 close receive operation */
3604 + /* wait for previous close (if any) to finish */
3606 + while(he_readl(he_dev, RCC_STAT) & RCC_BUSY)
3608 + HPRINTK("close cid 0x%x RCC_BUSY\n", cid);
3612 + add_wait_queue(&he_vcc->rx_waitq, &wait);
3613 + set_current_state(TASK_UNINTERRUPTIBLE);
3615 + he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid);
3616 + he_writel_mbox(he_dev, cid, RXCON_CLOSE);
3618 + HE_SPIN_UNLOCK(he_dev, flags);
3619 + timeout = schedule_timeout(30*HZ);
3620 + HE_SPIN_LOCK(he_dev, flags);
3621 + remove_wait_queue(&he_vcc->rx_waitq, &wait);
3622 + set_current_state(TASK_RUNNING);
3625 + hprintk("close rx timeout cid 0x%x\n", cid);
3627 +#ifndef USE_HE_FIND_VCC
3628 + HE_LOOKUP_VCC(he_dev, cid) = NULL;
3630 + HPRINTK("close rx cid 0x%x complete\n", cid);
3634 + if (vcc->qos.txtp.traffic_class != ATM_NONE)
3636 + volatile unsigned tsr4, tsr0;
3639 + HPRINTK("close tx cid 0x%x\n", cid);
3643 + * ... the host must first stop queueing packets to the TPDRQ
3644 + * on the connection to be closed, then wait for all outstanding
3645 + * packets to be transmitted and their buffers returned to the
3646 + * TBRQ. When the last packet on the connection arrives in the
3647 + * TBRQ, the host issues the close command to the adapter.
3650 + HE_SPIN_UNLOCK(he_dev, flags);
3651 + while (((tx_inuse = atomic_read(&vcc->sk->wmem_alloc)) > 0)
3652 + && (retry < MAX_RETRY))
3654 + set_current_state(TASK_UNINTERRUPTIBLE);
3655 + (void) schedule_timeout(sleep);
3656 + set_current_state(TASK_RUNNING);
3657 + if (sleep < HZ) sleep = sleep * 2;
3662 + if (tx_inuse) hprintk("close tx cid 0x%x tx_inuse = %d\n",
3664 + HE_SPIN_LOCK(he_dev, flags);
3666 + /* 2.3.1.1 generic close operations with flush */
3668 + he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid);
3669 + /* also clears TSR4_SESSION_ENDED */
3671 + switch(vcc->qos.txtp.traffic_class)
3674 + he_writel_tsr1(he_dev,
3675 + TSR1_MCR(rate_to_atmf(200000))
3676 + | TSR1_PCR(0), cid);
3679 + he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid);
3684 + tpd = he_alloc_tpd(he_dev);
3687 + hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid);
3688 + goto close_tx_incomplete;
3690 + tpd->status |= TPD_EOS | TPD_INT;
3695 + add_wait_queue(&he_vcc->tx_waitq, &wait);
3696 + set_current_state(TASK_UNINTERRUPTIBLE);
3697 + he_enqueue_tpd(he_dev, tpd, cid);
3698 + HE_SPIN_UNLOCK(he_dev, flags);
3699 + timeout = schedule_timeout(30*HZ);
3700 + HE_SPIN_LOCK(he_dev, flags);
3701 + remove_wait_queue(&he_vcc->tx_waitq, &wait);
3702 + set_current_state(TASK_RUNNING);
3706 + hprintk("close tx timeout cid 0x%x\n", cid);
3707 + goto close_tx_incomplete;
3710 + while (!((tsr4 = he_readl_tsr4(he_dev, cid))
3711 + & TSR4_SESSION_ENDED))
3713 + HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4);
3717 + while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0)
3719 + HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0);
3723 +close_tx_incomplete:
3725 + if (vcc->qos.txtp.traffic_class == ATM_CBR)
3727 + int reg = he_vcc->rc_index;
3729 + HPRINTK("cs_stper reg = %d\n", reg);
3731 + if (he_dev->cs_stper[reg].inuse == 0)
3732 + hprintk("cs_stper[%d].inuse = 0!\n", reg);
3734 + --he_dev->cs_stper[reg].inuse;
3736 + he_dev->total_bw -= he_dev->cs_stper[reg].pcr;
3739 + HPRINTK("close tx cid 0x%x complete\n", cid);
3743 + HE_SPIN_UNLOCK(he_dev, flags);
3745 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3746 + vcc->flags &= ~ATM_VF_ADDR;
3748 + clear_bit(ATM_VF_ADDR, &vcc->flags);
3753 +he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size)
3755 +#ifdef USE_SCATTERGATHER
3763 +he_send(struct atm_vcc *vcc, struct sk_buff *skb)
3765 + unsigned long flags;
3766 + struct he_dev *he_dev = HE_DEV(vcc->dev);
3767 + unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
3768 + struct he_tpd *tpd;
3769 +#ifdef USE_SCATTERGATHER
3773 +#define HE_TPD_BUFSIZE 0xffff
3775 + HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci);
3777 + if (skb->len > HE_TPD_BUFSIZE )
3779 + hprintk("buffer too large (%d bytes)\n", skb->len );
3781 + vcc->pop(vcc, skb);
3783 + dev_kfree_skb_any(skb);
3784 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3785 + ++vcc->stats->tx_err;
3787 + atomic_inc(&vcc->stats->tx_err);
3792 +#ifndef USE_SCATTERGATHER
3793 + if (skb_shinfo(skb)->nr_frags)
3795 + hprintk1("no scatter/gather support\n");
3797 + vcc->pop(vcc, skb);
3799 + dev_kfree_skb_any(skb);
3800 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3801 + ++vcc->stats->tx_err;
3803 + atomic_inc(&vcc->stats->tx_err);
3809 + tpd = he_alloc_tpd(he_dev);
3813 + vcc->pop(vcc, skb);
3815 + dev_kfree_skb_any(skb);
3816 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3817 + ++vcc->stats->tx_err;
3819 + atomic_inc(&vcc->stats->tx_err);
3823 + tpd->status |= TPD_USERCELL;
3825 +#ifdef USE_SCATTERGATHER
3826 + tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data,
3827 + skb->len - skb->data_len, PCI_DMA_TODEVICE);
3828 + tpd->iovec[slot].len = skb->len - skb->data_len;
3831 + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
3833 + skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
3835 + if (slot == TPD_MAXIOV) /* send tpd; start new tpd */
3838 + tpd->skb = NULL; /* not the last fragment
3839 + so dont ->push() yet */
3842 + HE_SPIN_LOCK(he_dev, flags);
3843 + he_enqueue_tpd(he_dev, tpd, cid);
3844 + HE_SPIN_UNLOCK(he_dev, flags);
3845 + tpd = he_alloc_tpd(he_dev);
3849 + vcc->pop(vcc, skb);
3851 + dev_kfree_skb_any(skb);
3852 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3853 + ++vcc->stats->tx_err;
3855 + atomic_inc(&vcc->stats->tx_err);
3859 + tpd->status |= TPD_USERCELL;
3863 + tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev,
3864 + (void *) page_address(frag->page) + frag->page_offset,
3865 + frag->size, PCI_DMA_TODEVICE);
3866 + tpd->iovec[slot].len = frag->size;
3871 + tpd->iovec[slot-1].len |= TPD_LST;
3873 + tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
3874 + tpd->length0 = skb->len | TPD_LST;
3876 + tpd->status |= TPD_INT;
3881 + ATM_SKB(skb)->vcc = vcc;
3883 + HE_SPIN_LOCK(he_dev, flags);
3884 + he_enqueue_tpd(he_dev, tpd, cid);
3885 + HE_SPIN_UNLOCK(he_dev, flags);
3887 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3890 + atomic_inc(&vcc->stats->tx);
3897 +he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void *arg)
3899 + unsigned long flags;
3900 + struct he_dev *he_dev = HE_DEV(atm_dev);
3901 + struct he_ioctl_reg reg;
3907 + if (!capable(CAP_NET_ADMIN)) return -EPERM;
3909 + copy_from_user(®, (struct he_ioctl_reg *) arg,
3910 + sizeof(struct he_ioctl_reg));
3911 + HE_SPIN_LOCK(he_dev, flags);
3914 + case HE_REGTYPE_PCI:
3915 + reg.val = he_readl(he_dev, reg.addr);
3917 + case HE_REGTYPE_RCM:
3919 + he_readl_rcm(he_dev, reg.addr);
3921 + case HE_REGTYPE_TCM:
3923 + he_readl_tcm(he_dev, reg.addr);
3925 + case HE_REGTYPE_MBOX:
3927 + he_readl_mbox(he_dev, reg.addr);
3930 + HE_SPIN_UNLOCK(he_dev, flags);
3933 + HE_SPIN_UNLOCK(he_dev, flags);
3934 + copy_to_user((struct he_ioctl_reg *) arg, ®,
3935 + sizeof(struct he_ioctl_reg));
3938 +#ifdef CONFIG_ATM_HE_USE_SUNI
3939 + HE_SPIN_LOCK(he_dev, flags);
3940 + if (atm_dev->phy && atm_dev->phy->ioctl)
3941 + err = atm_dev->phy->ioctl(atm_dev, cmd, arg);
3942 + HE_SPIN_UNLOCK(he_dev, flags);
3943 +#else /* CONFIG_ATM_HE_USE_SUNI */
3945 +#endif /* CONFIG_ATM_HE_USE_SUNI */
3953 +he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr)
3955 + struct he_dev *he_dev = HE_DEV(atm_dev);
3957 + HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr);
3959 + he_writel(he_dev, val, FRAMER + (addr*4));
3963 +static unsigned char
3964 +he_phy_get(struct atm_dev *atm_dev, unsigned long addr)
3966 + struct he_dev *he_dev = HE_DEV(atm_dev);
3969 + reg = he_readl(he_dev, FRAMER + (addr*4));
3971 + HPRINTK("phy_get(addr 0x%lx) =0x%lx\n", addr, reg);
3976 +he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
3978 + unsigned long flags;
3979 + struct he_dev *he_dev = HE_DEV(dev);
3982 + struct he_rbrq *rbrq_tail;
3983 + struct he_tpdrq *tpdrq_head;
3984 + int rbpl_head, rbpl_tail;
3986 + static long mcc = 0, oec = 0, dcc = 0, cec = 0;
3991 + return sprintf(page, "%s\n", version);
3994 + return sprintf(page, "%s%s\n\n",
3995 + he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM");
3998 + return sprintf(page, "Mismatched Cells VPI/VCI Not Open Dropped Cells RCM Dropped Cells\n");
4000 + HE_SPIN_LOCK(he_dev, flags);
4001 + mcc += he_readl(he_dev, MCC);
4002 + oec += he_readl(he_dev, OEC);
4003 + dcc += he_readl(he_dev, DCC);
4004 + cec += he_readl(he_dev, CEC);
4005 + HE_SPIN_UNLOCK(he_dev, flags);
4008 + return sprintf(page, "%16ld %16ld %13ld %17ld\n\n",
4009 + mcc, oec, dcc, cec);
4012 + return sprintf(page, "irq_size = %d inuse = ? peak = %d\n",
4013 + CONFIG_IRQ_SIZE, he_dev->irq_peak);
4016 + return sprintf(page, "tpdrq_size = %d inuse = ?\n",
4017 + CONFIG_TPDRQ_SIZE);
4020 + return sprintf(page, "rbrq_size = %d inuse = ? peak = %d\n",
4021 + CONFIG_RBRQ_SIZE, he_dev->rbrq_peak);
4024 + return sprintf(page, "tbrq_size = %d peak = %d\n",
4025 + CONFIG_TBRQ_SIZE, he_dev->tbrq_peak);
4029 + rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S));
4030 + rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T));
4032 + inuse = rbpl_head - rbpl_tail;
4033 + if (inuse < 0) inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp);
4034 + inuse /= sizeof(struct he_rbp);
4037 + return sprintf(page, "rbpl_size = %d inuse = %d\n\n",
4038 + CONFIG_RBPL_SIZE, inuse);
4042 + return sprintf(page, "rate controller periods (cbr)\n pcr #vc\n");
4044 + for (i = 0; i < HE_NUM_CS_STPER; ++i)
4046 + return sprintf(page, "cs_stper%-2d %8ld %3d\n", i,
4047 + he_dev->cs_stper[i].pcr,
4048 + he_dev->cs_stper[i].inuse);
4051 + return sprintf(page, "total bw (cbr): %d (limit %d)\n",
4052 + he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9);
4057 +/* eeprom routines -- see 4.7 */
4060 +read_prom_byte(struct he_dev *he_dev, int addr)
4062 + u32 val = 0, tmp_read = 0;
4066 + val = readl(he_dev->membase + HOST_CNTL);
4067 + val &= 0xFFFFE0FF;
4069 + /* Turn on write enable */
4071 + writel(val, he_dev->membase + HOST_CNTL);
4073 + /* Send READ instruction */
4074 + for (i=0; i<sizeof(readtab)/sizeof(readtab[0]); i++) {
4075 + writel(val | readtab[i], he_dev->membase + HOST_CNTL);
4076 + udelay(EEPROM_DELAY);
4079 + /* Next, we need to send the byte address to read from */
4080 + for (i=7; i>=0; i--) {
4081 + writel(val | clocktab[j++] | (((addr >> i) & 1) << 9),
4082 + he_dev->membase + HOST_CNTL);
4083 + udelay(EEPROM_DELAY);
4084 + writel(val | clocktab[j++] | (((addr >> i) & 1) << 9),
4085 + he_dev->membase + HOST_CNTL);
4086 + udelay(EEPROM_DELAY);
4091 + val &= 0xFFFFF7FF; /* Turn off write enable */
4092 + writel(val, he_dev->membase + HOST_CNTL);
4094 + /* Now, we can read data from the EEPROM by clocking it in */
4095 + for (i=7; i>=0; i--) {
4096 + writel(val | clocktab[j++], he_dev->membase + HOST_CNTL);
4097 + udelay(EEPROM_DELAY);
4098 + tmp_read = readl(he_dev->membase + HOST_CNTL);
4099 + byte_read |= (unsigned char)
4100 + ((tmp_read & ID_DOUT)
4101 + >> ID_DOFFSET << i);
4102 + writel(val | clocktab[j++],
4103 + he_dev->membase + HOST_CNTL);
4104 + udelay(EEPROM_DELAY);
4107 + writel(val | clocktab[j++], he_dev->membase + HOST_CNTL);
4108 + udelay(EEPROM_DELAY);
4110 + return (byte_read);
4113 +MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>");
4114 +MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver");
4115 +MODULE_PARM(disable64, "h");
4116 +MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers");
4117 +MODULE_PARM(nvpibits, "i");
4118 +MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)");
4119 +MODULE_PARM(nvcibits, "i");
4120 +MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)");
4121 +MODULE_PARM(rx_skb_reserve, "i");
4122 +MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)");
4123 +MODULE_PARM(irq_coalesce, "i");
4124 +MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)");
4125 +MODULE_PARM(sdh, "i");
4126 +MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
4128 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
4129 +static struct pci_device_id he_pci_tbl[] __devinitdata = {
4130 + { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID,
4135 +static struct pci_driver he_driver = {
4137 + .probe = he_init_one,
4138 + .remove = __devexit_p(he_remove_one),
4139 + .id_table = he_pci_tbl,
4142 +static int __init he_init(void)
4144 + return pci_module_init(&he_driver);
4147 +static void __exit he_cleanup(void)
4149 + pci_unregister_driver(&he_driver);
4152 +module_init(he_init);
4153 +module_exit(he_cleanup);
4158 + if (!pci_present())
4161 +#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
4162 + /* request_module("suni"); */
4166 + while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FORE,
4167 + PCI_DEVICE_ID_FORE_HE, pci_dev)) != NULL)
4168 + if (he_init_one(pci_dev, NULL) == 0)
4171 + return (ndevs ? 0 : -ENODEV);
4174 +static void __devexit
4179 + struct he_dev *next = he_devs->next;
4181 + atm_dev_deregister(he_devs->atm_dev);
4189 +int init_module(void)
4194 +void cleanup_module(void)
4200 +MODULE_LICENSE("GPL");
4201 diff -urN linux-2.4.20/drivers/atm/he.h linux-2.4.20-atm/drivers/atm/he.h
4202 --- linux-2.4.20/drivers/atm/he.h Thu Jan 1 01:00:00 1970
4203 +++ linux-2.4.20-atm/drivers/atm/he.h Wed May 28 01:58:41 2003
4211 + ForeRunnerHE ATM Adapter driver for ATM on Linux
4212 + Copyright (C) 1999-2001 Naval Research Laboratory
4214 + This library is free software; you can redistribute it and/or
4215 + modify it under the terms of the GNU Lesser General Public
4216 + License as published by the Free Software Foundation; either
4217 + version 2.1 of the License, or (at your option) any later version.
4219 + This library is distributed in the hope that it will be useful,
4220 + but WITHOUT ANY WARRANTY; without even the implied warranty of
4221 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4222 + Lesser General Public License for more details.
4224 + You should have received a copy of the GNU Lesser General Public
4225 + License along with this library; if not, write to the Free Software
4226 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4234 + ForeRunnerHE ATM Adapter driver for ATM on Linux
4235 + Copyright (C) 1999-2000 Naval Research Laboratory
4237 + Permission to use, copy, modify and distribute this software and its
4238 + documentation is hereby granted, provided that both the copyright
4239 + notice and this permission notice appear in all copies of the software,
4240 + derivative works or modified versions, and any portions thereof, and
4241 + that both notices appear in supporting documentation.
4243 + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
4244 + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
4245 + RESULTING FROM THE USE OF THIS SOFTWARE.
4252 +#define DEV_LABEL "he"
4254 +#define CONFIG_DEFAULT_VCIBITS 12
4255 +#define CONFIG_DEFAULT_VPIBITS 0
4257 +#define CONFIG_IRQ_SIZE 128
4258 +#define CONFIG_IRQ_THRESH (CONFIG_IRQ_SIZE/2)
4260 +#define CONFIG_TPDRQ_SIZE 512
4261 +#define TPDRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1))
4263 +#define CONFIG_RBRQ_SIZE 512
4264 +#define CONFIG_RBRQ_THRESH 400
4265 +#define RBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1))
4267 +#define CONFIG_TBRQ_SIZE 512
4268 +#define CONFIG_TBRQ_THRESH 400
4269 +#define TBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1))
4271 +#define CONFIG_RBPL_SIZE 512
4272 +#define CONFIG_RBPL_THRESH 64
4273 +#define CONFIG_RBPL_BUFSIZE 4096
4274 +#define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1))
4276 +#define CONFIG_RBPS_SIZE 1024
4277 +#define CONFIG_RBPS_THRESH 64
4278 +#define CONFIG_RBPS_BUFSIZE 128
4279 +#define RBPS_MASK(x) (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1))
4281 +/* 5.1.3 initialize connection memory */
4283 +#define CONFIG_RSRA 0x00000
4284 +#define CONFIG_RCMLBM 0x08000
4285 +#define CONFIG_RCMABR 0x0d800
4286 +#define CONFIG_RSRB 0x0e000
4288 +#define CONFIG_TSRA 0x00000
4289 +#define CONFIG_TSRB 0x08000
4290 +#define CONFIG_TSRC 0x0c000
4291 +#define CONFIG_TSRD 0x0e000
4292 +#define CONFIG_TMABR 0x0f000
4293 +#define CONFIG_TPDBA 0x10000
4295 +#define HE_MAXCIDBITS 12
4297 +/* 2.9.3.3 interrupt encodings */
4303 +#define IRQ_ALIGNMENT 0x1000
4305 +#define NEXT_ENTRY(base, tail, mask) \
4306 + (((unsigned long)base)|(((unsigned long)(tail+1))&mask))
4308 +#define ITYPE_INVALID 0xffffffff
4309 +#define ITYPE_TBRQ_THRESH (0<<3)
4310 +#define ITYPE_TPD_COMPLETE (1<<3)
4311 +#define ITYPE_RBPS_THRESH (2<<3)
4312 +#define ITYPE_RBPL_THRESH (3<<3)
4313 +#define ITYPE_RBRQ_THRESH (4<<3)
4314 +#define ITYPE_RBRQ_TIMER (5<<3)
4315 +#define ITYPE_PHY (6<<3)
4316 +#define ITYPE_OTHER 0x80
4317 +#define ITYPE_PARITY 0x81
4318 +#define ITYPE_ABORT 0x82
4320 +#define ITYPE_GROUP(x) (x & 0x7)
4321 +#define ITYPE_TYPE(x) (x & 0xf8)
4323 +#define HE_NUM_GROUPS 8
4325 +/* 2.1.4 transmit packet descriptor */
4329 + /* read by the adapter */
4331 + volatile u32 status;
4332 + volatile u32 reserved;
4334 +#define TPD_MAXIOV 3
4337 + } iovec[TPD_MAXIOV];
4340 +#define address0 iovec[0].addr
4341 +#define length0 iovec[0].len
4343 + /* linux-atm extensions */
4345 + struct sk_buff *skb;
4346 + struct atm_vcc *vcc;
4348 + struct list_head entry;
4351 +#define TPD_ALIGNMENT 64
4352 +#define TPD_LEN_MASK 0xffff
4354 +#define TPD_ADDR(x) ((x) & 0xffffffc0)
4357 +/* table 2.3 transmit buffer return elements */
4360 + volatile u32 tbre;
4363 +#define TBRQ_ALIGNMENT CONFIG_TBRQ_SIZE
4365 +#define TBRQ_TPD(tbrq) ((tbrq)->tbre & 0xffffffc0)
4366 +#define TBRQ_EOS(tbrq) ((tbrq)->tbre & (1<<3))
4367 +#define TBRQ_MULTIPLE(tbrq) ((tbrq)->tbre & (1))
4369 +/* table 2.21 receive buffer return queue element field organization */
4372 + volatile u32 addr;
4373 + volatile u32 cidlen;
4376 +#define RBRQ_ALIGNMENT CONFIG_RBRQ_SIZE
4378 +#define RBRQ_ADDR(rbrq) ((rbrq)->addr & 0xffffffc0)
4379 +#define RBRQ_CRC_ERR(rbrq) ((rbrq)->addr & (1<<5))
4380 +#define RBRQ_LEN_ERR(rbrq) ((rbrq)->addr & (1<<4))
4381 +#define RBRQ_END_PDU(rbrq) ((rbrq)->addr & (1<<3))
4382 +#define RBRQ_AAL5_PROT(rbrq) ((rbrq)->addr & (1<<2))
4383 +#define RBRQ_CON_CLOSED(rbrq) ((rbrq)->addr & (1<<1))
4384 +#define RBRQ_HBUF_ERR(rbrq) ((rbrq)->addr & 1)
4385 +#define RBRQ_CID(rbrq) (((rbrq)->cidlen >> 16) & 0x1fff)
4386 +#define RBRQ_BUFLEN(rbrq) ((rbrq)->cidlen & 0xffff)
4388 +/* figure 2.3 transmit packet descriptor ready queue */
4395 +#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE
4397 +/* table 2.30 host status page detail */
4399 +#define HSP_ALIGNMENT 0x400 /* must align on 1k boundary */
4402 + struct he_hsp_entry {
4403 + volatile u32 tbrq_tail;
4404 + volatile u32 reserved1[15];
4405 + volatile u32 rbrq_tail;
4406 + volatile u32 reserved2[15];
4407 + } group[HE_NUM_GROUPS];
4410 +/* figure 2.9 receive buffer pools */
4413 + volatile u32 phys;
4414 + volatile u32 status;
4417 +/* NOTE: it is suggested that virt be the virtual address of the host
4418 + buffer. on a 64-bit machine, this would not work. Instead, we
4419 + store the real virtual address in another list, and store an index
4420 + (and buffer status) in the virt member.
4423 +#define RBP_INDEX_OFF 6
4424 +#define RBP_INDEX(x) (((long)(x) >> RBP_INDEX_OFF) & 0xffff)
4425 +#define RBP_LOANED 0x80000000
4426 +#define RBP_SMALLBUF 0x40000000
4432 +#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE
4433 +#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE
4437 + u32 rpbs_size, rpbs_qsize;
4438 + struct he_rbp rbps_ba;
4440 + u32 rpbl_size, rpbl_qsize;
4441 + struct he_rpb_entry *rbpl_ba;
4445 +#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc)
4447 +struct he_vcc_table
4449 + struct atm_vcc *vcc;
4458 +#define HE_NUM_CS_STPER 16
4461 + unsigned int number;
4463 + unsigned long membase;
4475 + unsigned int vcibits, vpibits;
4476 + unsigned int cells_per_row;
4477 + unsigned int bytes_per_row;
4478 + unsigned int cells_per_lbuf;
4479 + unsigned int r0_numrows, r0_startrow, r0_numbuffs;
4480 + unsigned int r1_numrows, r1_startrow, r1_numbuffs;
4481 + unsigned int tx_numrows, tx_startrow, tx_numbuffs;
4482 + unsigned int buffer_limit;
4484 + struct he_vcc_table *he_vcc_table;
4487 + struct he_group group[HE_NUM_GROUPS];
4489 + struct he_cs_stper cs_stper[HE_NUM_CS_STPER];
4490 + unsigned total_bw;
4492 + dma_addr_t irq_phys;
4493 + struct he_irq *irq_base, *irq_head, *irq_tail;
4494 + volatile unsigned *irq_tailoffset;
4498 + struct tasklet_struct tasklet;
4501 + struct pci_pool *tpd_pool;
4502 + struct list_head outstanding_tpds;
4503 + dma_addr_t tpdrq_phys;
4504 + struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head;
4505 + spinlock_t tpdrq_lock; /* serialize access to tpdrq */
4507 + spinlock_t global_lock; /* 8.1.5 pci transaction ordering
4509 + dma_addr_t rbrq_phys;
4510 + struct he_rbrq *rbrq_base, *rbrq_head;
4513 + struct pci_pool *rbpl_pool;
4514 + dma_addr_t rbpl_phys;
4515 + struct he_rbp *rbpl_base, *rbpl_tail;
4516 + struct he_virt *rbpl_virt;
4519 + struct pci_pool *rbps_pool;
4520 + dma_addr_t rbps_phys;
4521 + struct he_rbp *rbps_base, *rbps_tail;
4522 + struct he_virt *rbps_virt;
4525 + dma_addr_t tbrq_phys;
4526 + struct he_tbrq *tbrq_base, *tbrq_head;
4529 + dma_addr_t hsp_phys;
4530 + struct he_hsp *hsp;
4532 + struct pci_dev *pci_dev;
4533 + struct atm_dev *atm_dev;
4534 + struct he_dev *next;
4539 + struct iovec iov_head[32];
4540 + struct iovec *iov_tail;
4545 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
4546 + struct wait_queue *rx_waitq;
4547 + atruct wait_queue *tx_waitq;
4549 + wait_queue_head_t rx_waitq;
4550 + wait_queue_head_t tx_waitq;
4554 +#define HE_VCC(vcc) ((struct he_vcc *)(vcc->dev_data))
4556 +#define PCI_VENDOR_ID_FORE 0x1127
4557 +#define PCI_DEVICE_ID_FORE_HE 0x400
4559 +#define HE_DMA_MASK 0xffffffff
4561 +#define GEN_CNTL_0 0x40
4562 +#define INT_PROC_ENBL (1<<25)
4563 +#define SLAVE_ENDIAN_MODE (1<<16)
4564 +#define MRL_ENB (1<<5)
4565 +#define MRM_ENB (1<<4)
4566 +#define INIT_ENB (1<<2)
4567 +#define IGNORE_TIMEOUT (1<<1)
4568 +#define ENBL_64 (1<<0)
4570 +#define MIN_PCI_LATENCY 32 /* errata 8.1.3 */
4572 +#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data)
4574 +#define he_is622(dev) ((dev)->media & 0x1)
4576 +#define HE_REGMAP_SIZE 0x100000
4578 +#define RESET_CNTL 0x80000
4579 +#define BOARD_RST_STATUS (1<<6)
4581 +#define HOST_CNTL 0x80004
4582 +#define PCI_BUS_SIZE64 (1<<27)
4583 +#define DESC_RD_STATIC_64 (1<<26)
4584 +#define DATA_RD_STATIC_64 (1<<25)
4585 +#define DATA_WR_STATIC_64 (1<<24)
4586 +#define ID_CS (1<<12)
4587 +#define ID_WREN (1<<11)
4588 +#define ID_DOUT (1<<10)
4589 +#define ID_DOFFSET 10
4590 +#define ID_DIN (1<<9)
4591 +#define ID_CLOCK (1<<8)
4592 +#define QUICK_RD_RETRY (1<<7)
4593 +#define QUICK_WR_RETRY (1<<6)
4594 +#define OUTFF_ENB (1<<5)
4595 +#define CMDFF_ENB (1<<4)
4596 +#define PERR_INT_ENB (1<<2)
4597 +#define IGNORE_INTR (1<<0)
4599 +#define LB_SWAP 0x80008
4600 +#define SWAP_RNUM_MAX(x) (x<<27)
4601 +#define DATA_WR_SWAP (1<<20)
4602 +#define DESC_RD_SWAP (1<<19)
4603 +#define DATA_RD_SWAP (1<<18)
4604 +#define INTR_SWAP (1<<17)
4605 +#define DESC_WR_SWAP (1<<16)
4606 +#define SDRAM_INIT (1<<15)
4607 +#define BIG_ENDIAN_HOST (1<<14)
4608 +#define XFER_SIZE (1<<7)
4610 +#define LB_MEM_ADDR 0x8000c
4611 +#define LB_MEM_DATA 0x80010
4613 +#define LB_MEM_ACCESS 0x80014
4614 +#define LB_MEM_HNDSHK (1<<30)
4615 +#define LM_MEM_WRITE (0x7)
4616 +#define LM_MEM_READ (0x3)
4618 +#define SDRAM_CTL 0x80018
4619 +#define LB_64_ENB (1<<3)
4620 +#define LB_TWR (1<<2)
4621 +#define LB_TRP (1<<1)
4622 +#define LB_TRAS (1<<0)
4624 +#define INT_FIFO 0x8001c
4625 +#define INT_MASK_D (1<<15)
4626 +#define INT_MASK_C (1<<14)
4627 +#define INT_MASK_B (1<<13)
4628 +#define INT_MASK_A (1<<12)
4629 +#define INT_CLEAR_D (1<<11)
4630 +#define INT_CLEAR_C (1<<10)
4631 +#define INT_CLEAR_B (1<<9)
4632 +#define INT_CLEAR_A (1<<8)
4634 +#define ABORT_ADDR 0x80020
4636 +#define IRQ0_BASE 0x80080
4637 +#define IRQ_BASE(x) (x<<12)
4638 +#define IRQ_MASK ((CONFIG_IRQ_SIZE<<2)-1) /* was 0x3ff */
4639 +#define IRQ_TAIL(x) (((unsigned long)(x)) & IRQ_MASK)
4640 +#define IRQ0_HEAD 0x80084
4641 +#define IRQ_SIZE(x) (x<<22)
4642 +#define IRQ_THRESH(x) (x<<12)
4643 +#define IRQ_HEAD(x) (x<<2)
4644 +/* #define IRQ_PENDING (1) conflict with linux/irq.h */
4645 +#define IRQ0_CNTL 0x80088
4646 +#define IRQ_ADDRSEL(x) (x<<2)
4647 +#define IRQ_INT_A (0<<2)
4648 +#define IRQ_INT_B (1<<2)
4649 +#define IRQ_INT_C (2<<2)
4650 +#define IRQ_INT_D (3<<2)
4651 +#define IRQ_TYPE_ADDR 0x1
4652 +#define IRQ_TYPE_LINE 0x0
4653 +#define IRQ0_DATA 0x8008c
4655 +#define IRQ1_BASE 0x80090
4656 +#define IRQ1_HEAD 0x80094
4657 +#define IRQ1_CNTL 0x80098
4658 +#define IRQ1_DATA 0x8009c
4660 +#define IRQ2_BASE 0x800a0
4661 +#define IRQ2_HEAD 0x800a4
4662 +#define IRQ2_CNTL 0x800a8
4663 +#define IRQ2_DATA 0x800ac
4665 +#define IRQ3_BASE 0x800b0
4666 +#define IRQ3_HEAD 0x800b4
4667 +#define IRQ3_CNTL 0x800b8
4668 +#define IRQ3_DATA 0x800bc
4670 +#define GRP_10_MAP 0x800c0
4671 +#define GRP_32_MAP 0x800c4
4672 +#define GRP_54_MAP 0x800c8
4673 +#define GRP_76_MAP 0x800cc
4675 +#define G0_RBPS_S 0x80400
4676 +#define G0_RBPS_T 0x80404
4677 +#define RBP_TAIL(x) ((x)<<3)
4678 +#define RBP_MASK(x) ((x)|0x1fff)
4679 +#define G0_RBPS_QI 0x80408
4680 +#define RBP_QSIZE(x) ((x)<<14)
4681 +#define RBP_INT_ENB (1<<13)
4682 +#define RBP_THRESH(x) (x)
4683 +#define G0_RBPS_BS 0x8040c
4684 +#define G0_RBPL_S 0x80410
4685 +#define G0_RBPL_T 0x80414
4686 +#define G0_RBPL_QI 0x80418
4687 +#define G0_RBPL_BS 0x8041c
4689 +#define G1_RBPS_S 0x80420
4690 +#define G1_RBPS_T 0x80424
4691 +#define G1_RBPS_QI 0x80428
4692 +#define G1_RBPS_BS 0x8042c
4693 +#define G1_RBPL_S 0x80430
4694 +#define G1_RBPL_T 0x80434
4695 +#define G1_RBPL_QI 0x80438
4696 +#define G1_RBPL_BS 0x8043c
4698 +#define G2_RBPS_S 0x80440
4699 +#define G2_RBPS_T 0x80444
4700 +#define G2_RBPS_QI 0x80448
4701 +#define G2_RBPS_BS 0x8044c
4702 +#define G2_RBPL_S 0x80450
4703 +#define G2_RBPL_T 0x80454
4704 +#define G2_RBPL_QI 0x80458
4705 +#define G2_RBPL_BS 0x8045c
4707 +#define G3_RBPS_S 0x80460
4708 +#define G3_RBPS_T 0x80464
4709 +#define G3_RBPS_QI 0x80468
4710 +#define G3_RBPS_BS 0x8046c
4711 +#define G3_RBPL_S 0x80470
4712 +#define G3_RBPL_T 0x80474
4713 +#define G3_RBPL_QI 0x80478
4714 +#define G3_RBPL_BS 0x8047c
4716 +#define G4_RBPS_S 0x80480
4717 +#define G4_RBPS_T 0x80484
4718 +#define G4_RBPS_QI 0x80488
4719 +#define G4_RBPS_BS 0x8048c
4720 +#define G4_RBPL_S 0x80490
4721 +#define G4_RBPL_T 0x80494
4722 +#define G4_RBPL_QI 0x80498
4723 +#define G4_RBPL_BS 0x8049c
4725 +#define G5_RBPS_S 0x804a0
4726 +#define G5_RBPS_T 0x804a4
4727 +#define G5_RBPS_QI 0x804a8
4728 +#define G5_RBPS_BS 0x804ac
4729 +#define G5_RBPL_S 0x804b0
4730 +#define G5_RBPL_T 0x804b4
4731 +#define G5_RBPL_QI 0x804b8
4732 +#define G5_RBPL_BS 0x804bc
4734 +#define G6_RBPS_S 0x804c0
4735 +#define G6_RBPS_T 0x804c4
4736 +#define G6_RBPS_QI 0x804c8
4737 +#define G6_RBPS_BS 0x804cc
4738 +#define G6_RBPL_S 0x804d0
4739 +#define G6_RBPL_T 0x804d4
4740 +#define G6_RBPL_QI 0x804d8
4741 +#define G6_RBPL_BS 0x804dc
4743 +#define G7_RBPS_S 0x804e0
4744 +#define G7_RBPS_T 0x804e4
4745 +#define G7_RBPS_QI 0x804e8
4746 +#define G7_RBPS_BS 0x804ec
4748 +#define G7_RBPL_S 0x804f0
4749 +#define G7_RBPL_T 0x804f4
4750 +#define G7_RBPL_QI 0x804f8
4751 +#define G7_RBPL_BS 0x804fc
4753 +#define G0_RBRQ_ST 0x80500
4754 +#define G0_RBRQ_H 0x80504
4755 +#define G0_RBRQ_Q 0x80508
4756 +#define RBRQ_THRESH(x) ((x)<<13)
4757 +#define RBRQ_SIZE(x) (x)
4758 +#define G0_RBRQ_I 0x8050c
4759 +#define RBRQ_TIME(x) ((x)<<8)
4760 +#define RBRQ_COUNT(x) (x)
4762 +/* fill in 1 ... 7 later */
4764 +#define G0_TBRQ_B_T 0x80600
4765 +#define G0_TBRQ_H 0x80604
4766 +#define G0_TBRQ_S 0x80608
4767 +#define G0_TBRQ_THRESH 0x8060c
4768 +#define TBRQ_THRESH(x) (x)
4770 +/* fill in 1 ... 7 later */
4772 +#define RH_CONFIG 0x805c0
4773 +#define PHY_INT_ENB (1<<10)
4774 +#define OAM_GID(x) (x<<7)
4775 +#define PTMR_PRE(x) (x)
4777 +#define G0_INMQ_S 0x80580
4778 +#define G0_INMQ_L 0x80584
4779 +#define G1_INMQ_S 0x80588
4780 +#define G1_INMQ_L 0x8058c
4781 +#define G2_INMQ_S 0x80590
4782 +#define G2_INMQ_L 0x80594
4783 +#define G3_INMQ_S 0x80598
4784 +#define G3_INMQ_L 0x8059c
4785 +#define G4_INMQ_S 0x805a0
4786 +#define G4_INMQ_L 0x805a4
4787 +#define G5_INMQ_S 0x805a8
4788 +#define G5_INMQ_L 0x805ac
4789 +#define G6_INMQ_S 0x805b0
4790 +#define G6_INMQ_L 0x805b4
4791 +#define G7_INMQ_S 0x805b8
4792 +#define G7_INMQ_L 0x805bc
4794 +#define TPDRQ_B_H 0x80680
4795 +#define TPDRQ_T 0x80684
4796 +#define TPDRQ_S 0x80688
4798 +#define UBUFF_BA 0x8068c
4800 +#define RLBF0_H 0x806c0
4801 +#define RLBF0_T 0x806c4
4802 +#define RLBF1_H 0x806c8
4803 +#define RLBF1_T 0x806cc
4804 +#define RLBC_H 0x806d0
4805 +#define RLBC_T 0x806d4
4806 +#define RLBC_H2 0x806d8
4807 +#define TLBF_H 0x806e0
4808 +#define TLBF_T 0x806e4
4809 +#define RLBF0_C 0x806e8
4810 +#define RLBF1_C 0x806ec
4811 +#define RXTHRSH 0x806f0
4812 +#define LITHRSH 0x806f4
4814 +#define LBARB 0x80700
4815 +#define SLICE_X(x) (x<<28)
4816 +#define ARB_RNUM_MAX(x) (x<<23)
4817 +#define TH_PRTY(x) (x<<21)
4818 +#define RH_PRTY(x) (x<<19)
4819 +#define TL_PRTY(x) (x<<17)
4820 +#define RL_PRTY(x) (x<<15)
4821 +#define BUS_MULTI(x) (x<<8)
4822 +#define NET_PREF(x) (x)
4824 +#define SDRAMCON 0x80704
4825 +#define BANK_ON (1<<14)
4826 +#define WIDE_DATA (1<<13)
4827 +#define TWR_WAIT (1<<12)
4828 +#define TRP_WAIT (1<<11)
4829 +#define TRAS_WAIT (1<<10)
4830 +#define REF_RATE(x) (x)
4832 +#define LBSTAT 0x80708
4834 +#define RCC_STAT 0x8070c
4835 +#define RCC_BUSY (1)
4837 +#define TCMCONFIG 0x80740
4838 +#define TM_DESL2 (1<<10)
4839 +#define TM_BANK_WAIT(x) (x<<6)
4840 +#define TM_ADD_BANK4(x) (x<<4)
4841 +#define TM_PAR_CHECK(x) (x<<3)
4842 +#define TM_RW_WAIT(x) (x<<2)
4843 +#define TM_SRAM_TYPE(x) (x)
4845 +#define TSRB_BA 0x80744
4846 +#define TSRC_BA 0x80748
4847 +#define TMABR_BA 0x8074c
4848 +#define TPD_BA 0x80750
4849 +#define TSRD_BA 0x80758
4851 +#define TX_CONFIG 0x80760
4852 +#define DRF_THRESH(x) (x<<22)
4853 +#define TX_UT_MODE(x) (x<<21)
4854 +#define TX_VCI_MASK(x) (x<<17)
4855 +#define LBFREE_CNT(x) (x)
4857 +#define TXAAL5_PROTO 0x80764
4858 +#define CPCS_UU(x) (x<<8)
4861 +#define RCMCONFIG 0x80780
4862 +#define RM_DESL2(x) (x<<10)
4863 +#define RM_BANK_WAIT(x) (x<<6)
4864 +#define RM_ADD_BANK(x) (x<<4)
4865 +#define RM_PAR_CHECK(x) (x<<3)
4866 +#define RM_RW_WAIT(x) (x<<2)
4867 +#define RM_SRAM_TYPE(x) (x)
4869 +#define RCMRSRB_BA 0x80784
4870 +#define RCMLBM_BA 0x80788
4871 +#define RCMABR_BA 0x8078c
4873 +#define RC_CONFIG 0x807c0
4874 +#define UT_RD_DELAY(x) (x<<11)
4875 +#define WRAP_MODE(x) (x<<10)
4876 +#define RC_UT_MODE(x) (x<<9)
4877 +#define RX_ENABLE (1<<8)
4878 +#define RX_VALVP(x) (x<<4)
4879 +#define RX_VALVC(x) (x)
4881 +#define MCC 0x807c4
4882 +#define OEC 0x807c8
4883 +#define DCC 0x807cc
4884 +#define CEC 0x807d0
4886 +#define HSP_BA 0x807f0
4888 +#define LB_CONFIG 0x807f4
4889 +#define LB_SIZE(x) (x)
4891 +#define CON_DAT 0x807f8
4892 +#define CON_CTL 0x807fc
4893 +#define CON_CTL_MBOX (2<<30)
4894 +#define CON_CTL_TCM (1<<30)
4895 +#define CON_CTL_RCM (0<<30)
4896 +#define CON_CTL_WRITE (1<<29)
4897 +#define CON_CTL_READ (0<<29)
4898 +#define CON_CTL_BUSY (1<<28)
4899 +#define CON_BYTE_DISABLE_3 (1<<22) /* 24..31 */
4900 +#define CON_BYTE_DISABLE_2 (1<<21) /* 16..23 */
4901 +#define CON_BYTE_DISABLE_1 (1<<20) /* 8..15 */
4902 +#define CON_BYTE_DISABLE_0 (1<<19) /* 0..7 */
4903 +#define CON_CTL_ADDR(x) (x)
4905 +#define FRAMER 0x80800 /* to 0x80bfc */
4907 +/* 3.3 network controller (internal) mailbox registers */
4909 +#define CS_STPER0 0x0
4911 +#define CS_STPER31 0x01f
4913 +#define CS_STTIM0 0x020
4915 +#define CS_STTIM31 0x03f
4917 +#define CS_TGRLD0 0x040
4919 +#define CS_TGRLD15 0x04f
4921 +#define CS_ERTHR0 0x050
4922 +#define CS_ERTHR1 0x051
4923 +#define CS_ERTHR2 0x052
4924 +#define CS_ERTHR3 0x053
4925 +#define CS_ERTHR4 0x054
4926 +#define CS_ERCTL0 0x055
4927 +#define TX_ENABLE (1<<28)
4928 +#define ER_ENABLE (1<<27)
4929 +#define CS_ERCTL1 0x056
4930 +#define CS_ERCTL2 0x057
4931 +#define CS_ERSTAT0 0x058
4932 +#define CS_ERSTAT1 0x059
4934 +#define CS_RTCCT 0x060
4935 +#define CS_RTFWC 0x061
4936 +#define CS_RTFWR 0x062
4937 +#define CS_RTFTC 0x063
4938 +#define CS_RTATR 0x064
4940 +#define CS_TFBSET 0x070
4941 +#define CS_TFBADD 0x071
4942 +#define CS_TFBSUB 0x072
4943 +#define CS_WCRMAX 0x073
4944 +#define CS_WCRMIN 0x074
4945 +#define CS_WCRINC 0x075
4946 +#define CS_WCRDEC 0x076
4947 +#define CS_WCRCEIL 0x077
4948 +#define CS_BWDCNT 0x078
4950 +#define CS_OTPPER 0x080
4951 +#define CS_OTWPER 0x081
4952 +#define CS_OTTLIM 0x082
4953 +#define CS_OTTCNT 0x083
4955 +#define CS_HGRRT0 0x090
4957 +#define CS_HGRRT7 0x097
4959 +#define CS_ORPTRS 0x0a0
4961 +#define RXCON_CLOSE 0x100
4964 +#define RCM_MEM_SIZE 0x10000 /* 1M of 32-bit registers */
4965 +#define TCM_MEM_SIZE 0x20000 /* 2M of 32-bit registers */
4967 +/* 2.5 transmit connection memory registers */
4969 +#define TSR0_CONN_STATE(x) ((x>>28) & 0x7)
4970 +#define TSR0_USE_WMIN (1<<23)
4971 +#define TSR0_GROUP(x) ((x & 0x7)<<18)
4972 +#define TSR0_ABR (2<<16)
4973 +#define TSR0_UBR (1<<16)
4974 +#define TSR0_CBR (0<<16)
4975 +#define TSR0_PROT (1<<15)
4976 +#define TSR0_AAL0_SDU (2<<12)
4977 +#define TSR0_AAL0 (1<<12)
4978 +#define TSR0_AAL5 (0<<12)
4979 +#define TSR0_HALT_ER (1<<11)
4980 +#define TSR0_MARK_CI (1<<10)
4981 +#define TSR0_MARK_ER (1<<9)
4982 +#define TSR0_UPDATE_GER (1<<8)
4983 +#define TSR0_RC_INDEX(x) (x & 0x1F)
4985 +#define TSR1_PCR(x) ((x & 0x7FFF)<<16)
4986 +#define TSR1_MCR(x) (x & 0x7FFF)
4988 +#define TSR2_ACR(x) ((x & 0x7FFF)<<16)
4990 +#define TSR3_NRM_CNT(x) ((x & 0xFF)<<24)
4991 +#define TSR3_CRM_CNT(x) (x & 0xFFFF)
4993 +#define TSR4_FLUSH_CONN (1<<31)
4994 +#define TSR4_SESSION_ENDED (1<<30)
4995 +#define TSR4_CRC10 (1<<28)
4996 +#define TSR4_NULL_CRC10 (1<<27)
4997 +#define TSR4_PROT (1<<26)
4998 +#define TSR4_AAL0_SDU (2<<23)
4999 +#define TSR4_AAL0 (1<<23)
5000 +#define TSR4_AAL5 (0<<23)
5002 +#define TSR9_OPEN_CONN (1<<20)
5004 +#define TSR11_ICR(x) ((x & 0x7FFF)<<16)
5005 +#define TSR11_TRM(x) ((x & 0x7)<<13)
5006 +#define TSR11_NRM(x) ((x & 0x7)<<10)
5007 +#define TSR11_ADTF(x) (x & 0x3FF)
5009 +#define TSR13_RDF(x) ((x & 0xF)<<23)
5010 +#define TSR13_RIF(x) ((x & 0xF)<<19)
5011 +#define TSR13_CDF(x) ((x & 0x7)<<16)
5012 +#define TSR13_CRM(x) (x & 0xFFFF)
5014 +#define TSR14_DELETE (1<<31)
5015 +#define TSR14_ABR_CLOSE (1<<16)
5017 +/* 2.7.1 per connection receieve state registers */
5019 +#define RSR0_START_PDU (1<<10)
5020 +#define RSR0_OPEN_CONN (1<<6)
5021 +#define RSR0_CLOSE_CONN (0<<6)
5022 +#define RSR0_PPD_ENABLE (1<<5)
5023 +#define RSR0_EPD_ENABLE (1<<4)
5024 +#define RSR0_TCP_CKSUM (1<<3)
5025 +#define RSR0_AAL5 (0)
5026 +#define RSR0_AAL0 (1)
5027 +#define RSR0_AAL0_SDU (2)
5028 +#define RSR0_RAWCELL (3)
5029 +#define RSR0_RAWCELL_CRC10 (4)
5031 +#define RSR1_AQI_ENABLE (1<<20)
5032 +#define RSR1_RBPL_ONLY (1<<19)
5033 +#define RSR1_GROUP(x) ((x)<<16)
5035 +#define RSR4_AQI_ENABLE (1<<30)
5036 +#define RSR4_GROUP(x) ((x)<<27)
5037 +#define RSR4_RBPL_ONLY (1<<26)
5039 +/* 2.1.4 transmit packet descriptor */
5041 +#define TPD_USERCELL 0x0
5042 +#define TPD_SEGMENT_OAMF5 0x4
5043 +#define TPD_END2END_OAMF5 0x5
5044 +#define TPD_RMCELL 0x6
5045 +#define TPD_CELLTYPE(x) (x<<3)
5046 +#define TPD_EOS (1<<2)
5047 +#define TPD_CLP (1<<1)
5048 +#define TPD_INT (1)
5049 +#define TPD_LST (1<<31)
5051 +/* table 4.3 serial eeprom information */
5053 +#define PROD_ID 0x08 /* char[] */
5054 +#define PROD_ID_LEN 30
5055 +#define HW_REV 0x26 /* char[] */
5056 +#define M_SN 0x3a /* integer */
5057 +#define MEDIA 0x3e /* integer */
5058 +#define HE155MM 0x26
5059 +#define HE155SM 0x27
5060 +#define HE622MM 0x46
5061 +#define HE622SM 0x47
5062 +#define MAC_ADDR 0x42 /* char[] */
5065 +#define CS_HIGH ID_CS /* HOST_CNTL_ID_PROM_SEL */
5066 +#define CLK_LOW 0x0
5067 +#define CLK_HIGH ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */
5068 +#define SI_HIGH ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */
5069 +#define EEPROM_DELAY 400 /* microseconds */
5071 +/* Read from EEPROM = 0000 0011b */
5072 +unsigned int readtab[] = {
5073 + CS_HIGH | CLK_HIGH,
5086 + CLK_LOW | SI_HIGH,
5087 + CLK_HIGH | SI_HIGH, /* 1 */
5088 + CLK_LOW | SI_HIGH,
5089 + CLK_HIGH | SI_HIGH /* 1 */
5092 +/* Clock to read from/write to the EEPROM */
5093 +unsigned int clocktab[] = {
5114 +#endif /* _HE_H_ */
5115 diff -urN linux-2.4.20/drivers/atm/horizon.c linux-2.4.20-atm/drivers/atm/horizon.c
5116 --- linux-2.4.20/drivers/atm/horizon.c Sat Aug 3 02:39:43 2002
5117 +++ linux-2.4.20-atm/drivers/atm/horizon.c Wed May 28 01:58:41 2003
5118 @@ -1765,13 +1765,13 @@
5121 unsigned int tx_len = skb->len;
5122 - unsigned int tx_iovcnt = ATM_SKB(skb)->iovcnt;
5123 + unsigned int tx_nr_frags = skb_shinfo(skb)->nr_frags;
5124 // remember this so we can free it later
5128 + if (tx_nr_frags) {
5129 // scatter gather transfer
5130 - dev->tx_regions = tx_iovcnt;
5131 + dev->tx_regions = tx_nr_frags;
5132 dev->tx_iovec = (struct iovec *) skb->data;
5134 PRINTD (DBG_TX|DBG_BUS, "TX start scatter-gather transfer (iovec %p, len %d)",
5135 @@ -2189,14 +2189,6 @@
5139 - // deal with possibly wildcarded VCs
5140 - error = atm_find_ci (atm_vcc, &vpi, &vci);
5142 - PRINTD (DBG_WARN|DBG_VCC, "atm_find_ci failed!");
5145 - PRINTD (DBG_VCC, "atm_find_ci gives %x %x", vpi, vci);
5147 error = vpivci_to_channel (&channel, vpi, vci);
5149 PRINTD (DBG_WARN|DBG_VCC, "VPI/VCI out of range: %hd/%d", vpi, vci);
5150 diff -urN linux-2.4.20/drivers/atm/idt77252.c linux-2.4.20-atm/drivers/atm/idt77252.c
5151 --- linux-2.4.20/drivers/atm/idt77252.c Wed May 28 01:53:45 2003
5152 +++ linux-2.4.20-atm/drivers/atm/idt77252.c Wed May 28 01:58:41 2003
5153 @@ -1054,15 +1054,17 @@
5157 + read_lock(&vcc_sklist_lock);
5158 vc = card->vcs[VPCI2VC(card, vpi, vci)];
5159 - if (!vc || !test_bit(VCF_RX, &vc->flags)) {
5160 + if (!vc || !test_bit(VCF_RX, &vc->flags) || !(vcc = vc->rx_vcc)) {
5161 + read_unlock(&vcc_sklist_lock);
5162 printk("%s: SDU received on non RX vc %u.%u\n",
5163 card->name, vpi, vci);
5164 recycle_rx_skb(card, skb);
5170 + read_unlock(&vcc_sklist_lock);
5172 pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(skb),
5173 skb->end - skb->data, PCI_DMA_FROMDEVICE);
5174 @@ -1106,6 +1108,7 @@
5175 cell += ATM_CELL_PAYLOAD;
5179 recycle_rx_skb(card, skb);
5182 @@ -1113,6 +1116,7 @@
5183 printk("%s: Unexpected AAL type in dequeue_rx(): %d.\n",
5184 card->name, vcc->qos.aal);
5185 recycle_rx_skb(card, skb);
5189 skb->len = (stat & SAR_RSQE_CELLCNT) * ATM_CELL_PAYLOAD;
5190 @@ -1142,12 +1146,14 @@
5191 card->name, len, rpp->len, readl(SAR_REG_CDC));
5192 recycle_rx_pool_skb(card, rpp);
5193 atomic_inc(&vcc->stats->rx_err);
5197 if (stat & SAR_RSQE_CRC) {
5198 RXPRINTK("%s: AAL5 CRC error.\n", card->name);
5199 recycle_rx_pool_skb(card, rpp);
5200 atomic_inc(&vcc->stats->rx_err);
5204 if (rpp->count > 1) {
5205 @@ -1159,9 +1165,11 @@
5207 recycle_rx_pool_skb(card, rpp);
5208 atomic_inc(&vcc->stats->rx_err);
5212 if (!atm_charge(vcc, skb->truesize)) {
5214 recycle_rx_pool_skb(card, rpp);
5217 @@ -1181,6 +1189,7 @@
5219 vcc->push(vcc, skb);
5220 atomic_inc(&vcc->stats->rx);
5225 @@ -1189,6 +1198,7 @@
5226 flush_rx_pool(card, rpp);
5228 if (!atm_charge(vcc, skb->truesize)) {
5230 recycle_rx_skb(card, skb);
5233 @@ -1212,8 +1222,10 @@
5234 add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
5236 add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
5244 @@ -1988,7 +2000,7 @@
5248 - if (ATM_SKB(skb)->iovcnt != 0) {
5249 + if (skb_shinfo(skb)->nr_frags != 0) {
5250 printk("%s: No scatter-gather yet.\n", card->name);
5251 atomic_inc(&vcc->stats->tx_err);
5253 @@ -2025,8 +2037,7 @@
5254 atomic_inc(&vcc->stats->tx_err);
5257 - atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
5258 - ATM_SKB(skb)->iovcnt = 0;
5259 + atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
5261 memcpy(skb_put(skb, 52), cell, 52);
5263 @@ -2349,6 +2360,7 @@
5264 if (test_bit(VCF_RX, &vc->flags))
5269 set_bit(VCF_RX, &vc->flags);
5271 @@ -2403,40 +2415,6 @@
5275 -idt77252_find_vcc(struct atm_vcc *vcc, short *vpi, int *vci)
5277 - struct atm_vcc *walk;
5279 - if (*vpi == ATM_VPI_ANY) {
5281 - walk = vcc->dev->vccs;
5283 - if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
5285 - walk = vcc->dev->vccs;
5288 - walk = walk->next;
5292 - if (*vci == ATM_VCI_ANY) {
5293 - *vci = ATM_NOT_RSV_VCI;
5294 - walk = vcc->dev->vccs;
5296 - if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
5298 - walk = vcc->dev->vccs;
5301 - walk = walk->next;
5309 idt77252_open(struct atm_vcc *vcc, short vpi, int vci)
5311 struct atm_dev *dev = vcc->dev;
5312 @@ -2446,8 +2424,6 @@
5316 - idt77252_find_vcc(vcc, &vpi, &vci);
5318 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
5321 @@ -2565,6 +2541,8 @@
5322 spin_lock_irqsave(&vc->lock, flags);
5323 clear_bit(VCF_RX, &vc->flags);
5327 spin_unlock_irqrestore(&vc->lock, flags);
5329 if ((vcc->vci == 3) || (vcc->vci == 4))
5330 diff -urN linux-2.4.20/drivers/atm/iphase.c linux-2.4.20-atm/drivers/atm/iphase.c
5331 --- linux-2.4.20/drivers/atm/iphase.c Wed May 28 01:53:45 2003
5332 +++ linux-2.4.20-atm/drivers/atm/iphase.c Wed May 28 01:58:41 2003
5333 @@ -1122,13 +1122,17 @@
5334 IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
5337 + read_lock(&vcc_sklist_lock);
5338 vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];
5341 + read_unlock(&vcc_sklist_lock);
5342 free_desc(dev, desc);
5343 printk("IA: null vcc, drop PDU\n");
5347 + read_unlock(&vcc_sklist_lock);
5350 /* might want to check the status bits for errors */
5351 @@ -1185,8 +1189,6 @@
5355 - ATM_SKB(skb)->vcc = vcc;
5356 - ATM_SKB(skb)->iovcnt = 0;
5357 ATM_DESC(skb) = desc;
5358 skb_queue_tail(&iadev->rx_dma_q, skb);
5360 @@ -1205,7 +1207,8 @@
5362 /* Increment transaction counter */
5363 writel(1, iadev->dma+IPHASE5575_RX_COUNTER);
5368 free_desc(dev, desc);
5370 @@ -1283,6 +1286,7 @@
5371 struct dle *dle, *cur_dle;
5374 + struct rx_buf_desc *buf_desc_ptr;
5375 iadev = INPH_IA_DEV(dev);
5377 /* free all the dles done, that is just update our own dle read pointer
5378 @@ -1293,6 +1297,7 @@
5379 dle = iadev->rx_dle_q.read;
5380 dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1);
5381 cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4));
5382 + read_lock(&vcc_sklist_lock);
5383 while(dle != cur_dle)
5385 /* free the DMAed skb */
5386 @@ -1300,6 +1305,9 @@
5389 desc = ATM_DESC(skb);
5390 + buf_desc_ptr = (struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR;
5391 + buf_desc_ptr += desc;
5392 + vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];
5393 free_desc(dev, desc);
5395 if (!(len = skb->len))
5396 @@ -1316,7 +1324,6 @@
5397 pci_unmap_single(iadev->pci, iadev->rx_dle_q.write->sys_pkt_addr,
5398 len, PCI_DMA_FROMDEVICE);
5399 /* no VCC related housekeeping done as yet. lets see */
5400 - vcc = ATM_SKB(skb)->vcc;
5402 printk("IA: null vcc\n");
5403 dev_kfree_skb_any(skb);
5404 @@ -1360,6 +1367,7 @@
5407 IF_RX(printk("rx_dle_intr: skb push");)
5408 + ATM_SKB(skb)->vcc = vcc;
5410 atomic_inc(&vcc->stats->rx);
5411 iadev->rx_pkt_cnt++;
5412 @@ -1368,6 +1376,7 @@
5413 if (++dle == iadev->rx_dle_q.end)
5414 dle = iadev->rx_dle_q.start;
5416 + read_unlock(&vcc_sklist_lock);
5417 iadev->rx_dle_q.read = dle;
5419 /* if the interrupts are masked because there were no free desc available,
5420 @@ -1425,6 +1434,7 @@
5421 if (iadev->rx_open[vcc->vci])
5422 printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d already open\n",
5423 vcc->dev->number, vcc->vci);
5425 iadev->rx_open[vcc->vci] = vcc;
5428 @@ -1725,15 +1735,14 @@
5429 printk("tx_dle_intr: vcc is null\n");
5430 spin_unlock_irqrestore(&iadev->tx_lock, flags);
5431 dev_kfree_skb_any(skb);
5436 iavcc = INPH_IA_VCC(vcc);
5438 printk("tx_dle_intr: iavcc is null\n");
5439 spin_unlock_irqrestore(&iadev->tx_lock, flags);
5440 dev_kfree_skb_any(skb);
5444 if (vcc->qos.txtp.pcr >= iadev->rate_limit) {
5445 if ((vcc->pop) && (skb->len != 0))
5446 @@ -1749,6 +1758,7 @@
5447 skb_queue_tail(&iavcc->txing_skb, skb);
5449 IF_EVENT(printk("tx_dle_intr: enque skb = 0x%x \n", (u32)skb);)
5451 if (++dle == iadev->tx_dle_q.end)
5452 dle = iadev->tx_dle_q.start;
5454 @@ -2705,6 +2715,8 @@
5455 // Drain the packets
5456 rx_dle_intr(vcc->dev);
5457 iadev->rx_open[vcc->vci] = 0;
5461 kfree(INPH_IA_VCC(vcc));
5463 @@ -2724,12 +2736,6 @@
5464 INPH_IA_VCC(vcc) = NULL;
5466 iadev = INPH_IA_DEV(vcc->dev);
5467 - error = atm_find_ci(vcc, &vpi, &vci);
5470 - printk("iadev: atm_find_ci returned error %d\n", error);
5475 if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
5476 diff -urN linux-2.4.20/drivers/atm/lanai.c linux-2.4.20-atm/drivers/atm/lanai.c
5477 --- linux-2.4.20/drivers/atm/lanai.c Fri Nov 29 00:53:12 2002
5478 +++ linux-2.4.20-atm/drivers/atm/lanai.c Wed May 28 01:58:41 2003
5479 @@ -1820,10 +1820,10 @@
5481 vci_t vci = SERVICE_GET_VCI(s);
5482 struct lanai_vcc *lvcc;
5483 - vcclist_read_lock();
5484 + read_lock(&vcc_sklist_lock);
5485 lvcc = lanai->vccs[vci];
5487 - vcclist_read_unlock();
5488 + read_unlock(&vcc_sklist_lock);
5489 DPRINTK("(itf %d) got service entry 0x%X for nonexistent "
5490 "vcc %d\n", lanai->number, s, vci);
5492 @@ -1834,7 +1834,7 @@
5494 if (s & SERVICE_TX) { /* segmentation interrupt */
5495 if (lvcc->tx.atmvcc == NULL) {
5496 - vcclist_read_unlock();
5497 + read_unlock(&vcc_sklist_lock);
5498 DPRINTK("(itf %d) got service entry 0x%X for non-TX "
5499 "vcc %d\n", lanai->number, s, vci);
5500 lanai->stats.service_notx++;
5501 @@ -1842,18 +1842,18 @@
5503 vci_bitfield_set(&lanai->transmit_ready, vci);
5504 lvcc->tx.endptr = SERVICE_GET_END(s);
5505 - vcclist_read_unlock();
5506 + read_unlock(&vcc_sklist_lock);
5509 if (lvcc->rx.atmvcc == NULL) {
5510 - vcclist_read_unlock();
5511 + read_unlock(&vcc_sklist_lock);
5512 DPRINTK("(itf %d) got service entry 0x%X for non-RX "
5513 "vcc %d\n", lanai->number, s, vci);
5514 lanai->stats.service_norx++;
5517 if (lvcc->rx.atmvcc->qos.aal != ATM_AAL5) {
5518 - vcclist_read_unlock();
5519 + read_unlock(&vcc_sklist_lock);
5520 DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "
5521 "vcc %d\n", lanai->number, s, vci);
5522 lanai->stats.service_rxnotaal5++;
5523 @@ -1862,12 +1862,12 @@
5525 if ((s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)) == 0) {
5526 vcc_rx_aal5(lvcc, SERVICE_GET_END(s));
5527 - vcclist_read_unlock();
5528 + read_unlock(&vcc_sklist_lock);
5531 if (s & SERVICE_TRASH) {
5533 - vcclist_read_unlock();
5534 + read_unlock(&vcc_sklist_lock);
5535 DPRINTK("got trashed rx pdu on vci %d\n", vci);
5536 atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
5537 lvcc->stats.x.aal5.service_trash++;
5538 @@ -1880,7 +1880,7 @@
5541 if (s & SERVICE_STREAM) {
5542 - vcclist_read_unlock();
5543 + read_unlock(&vcc_sklist_lock);
5544 atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
5545 lvcc->stats.x.aal5.service_stream++;
5546 printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "
5547 @@ -1893,7 +1893,7 @@
5548 lvcc->stats.x.aal5.service_rxcrc++;
5549 lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];
5550 cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);
5551 - vcclist_read_unlock();
5552 + read_unlock(&vcc_sklist_lock);
5556 @@ -1924,11 +1924,11 @@
5557 reg_write(lanai, wreg, ServRead_Reg);
5559 spin_lock(&lanai->txlock);
5560 - vcclist_read_lock();
5561 + read_lock(&vcc_sklist_lock);
5562 vci_bitfield_iterate(lanai, &lanai->transmit_ready,
5564 vci_bitfield_init(&lanai->transmit_ready);
5565 - vcclist_read_unlock();
5566 + read_unlock(&vcc_sklist_lock);
5567 spin_unlock(&lanai->txlock);
5570 @@ -2785,7 +2785,7 @@
5571 return sprintf(page, "resets: dma=%d, card=%d\n",
5572 lanai->stats.dma_reenable, lanai->stats.card_reset);
5573 /* At this point, "left" should be the VCI we're looking for */
5574 - vcclist_read_lock();
5575 + read_lock(&vcc_sklist_lock);
5577 if (left >= NUM_VCI) {
5579 @@ -2821,7 +2821,7 @@
5580 page[left++] = '\n';
5583 - vcclist_read_unlock();
5584 + read_unlock(&vcc_sklist_lock);
5587 #endif /* CONFIG_PROC_FS */
5588 @@ -2842,7 +2842,6 @@
5591 change_qos: lanai_change_qos,
5592 - free_rx_skb: NULL,
5593 proc_read: lanai_proc_read
5596 diff -urN linux-2.4.20/drivers/atm/nicstar.c linux-2.4.20-atm/drivers/atm/nicstar.c
5597 --- linux-2.4.20/drivers/atm/nicstar.c Wed May 28 01:53:45 2003
5598 +++ linux-2.4.20-atm/drivers/atm/nicstar.c Wed May 28 01:58:41 2003
5599 @@ -941,9 +941,15 @@
5603 - if (ns_parse_mac(mac[i], card->atmdev->esi))
5604 + if (ns_parse_mac(mac[i], card->atmdev->esi)) {
5605 nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,
5606 card->atmdev->esi, 6);
5607 + if (!memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6)) {
5608 + nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT,
5609 + card->atmdev->esi, 6);
5614 printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i,
5615 card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2],
5616 @@ -1433,7 +1439,6 @@
5621 unsigned long tmpl, modl;
5622 int tcr, tcra; /* target cell rate, and absolute value */
5623 int n = 0; /* Number of entries in the TST. Initialized to remove
5624 @@ -1453,11 +1458,6 @@
5628 - if ((error = atm_find_ci(vcc, &vpi, &vci)))
5630 - PRINTK("nicstar%d: error in atm_find_ci().\n", card->index);
5633 vc = &(card->vcmap[vpi << card->vcibits | vci]);
5636 @@ -1597,6 +1597,7 @@
5644 @@ -1646,6 +1647,9 @@
5645 spin_unlock_irqrestore(&card->res_lock, flags);
5648 + vc->rx_vcc = NULL;
5651 if (vc->rx_iov != NULL)
5653 struct sk_buff *iovb;
5654 @@ -1659,9 +1663,9 @@
5657 recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
5658 - ATM_SKB(iovb)->iovcnt);
5659 - ATM_SKB(iovb)->iovcnt = 0;
5660 - ATM_SKB(iovb)->vcc = NULL;
5661 + NS_SKB(iovb)->iovcnt);
5662 + NS_SKB(iovb)->iovcnt = 0;
5663 + NS_SKB(iovb)->vcc = NULL;
5664 ns_grab_int_lock(card, flags);
5665 recycle_iov_buf(card, iovb);
5666 spin_unlock_irqrestore(&card->int_lock, flags);
5667 @@ -1859,7 +1863,7 @@
5671 - if (ATM_SKB(skb)->iovcnt != 0)
5672 + if (skb_shinfo(skb)->nr_frags != 0)
5674 printk("nicstar%d: No scatter-gather yet.\n", card->index);
5675 atomic_inc(&vcc->stats->tx_err);
5676 @@ -2203,16 +2207,18 @@
5680 + read_lock(&vcc_sklist_lock);
5681 vc = &(card->vcmap[vpi << card->vcibits | vci]);
5683 + if (!vc->rx || !(vcc = vc->rx_vcc))
5685 + read_unlock(&vcc_sklist_lock);
5686 RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n",
5687 card->index, vpi, vci);
5688 recycle_rx_buf(card, skb);
5694 + read_unlock(&vcc_sklist_lock);
5696 if (vcc->qos.aal == ATM_AAL0)
5698 @@ -2252,7 +2258,7 @@
5699 atomic_inc(&vcc->stats->rx);
5700 cell += ATM_CELL_PAYLOAD;
5704 recycle_rx_buf(card, skb);
5707 @@ -2269,6 +2275,7 @@
5709 printk("nicstar%d: Out of iovec buffers.\n", card->index);
5710 atomic_inc(&vcc->stats->rx_drop);
5712 recycle_rx_buf(card, skb);
5715 @@ -2284,30 +2291,30 @@
5719 - ATM_SKB(iovb)->iovcnt = 0;
5720 + NS_SKB(iovb)->iovcnt = 0;
5722 iovb->tail = iovb->data = iovb->head;
5723 - ATM_SKB(iovb)->vcc = vcc;
5724 + NS_SKB(iovb)->vcc = vcc;
5725 /* IMPORTANT: a pointer to the sk_buff containing the small or large
5726 buffer is stored as iovec base, NOT a pointer to the
5727 small or large buffer itself. */
5729 - else if (ATM_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)
5730 + else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)
5732 printk("nicstar%d: received too big AAL5 SDU.\n", card->index);
5733 atomic_inc(&vcc->stats->rx_err);
5734 recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS);
5735 - ATM_SKB(iovb)->iovcnt = 0;
5736 + NS_SKB(iovb)->iovcnt = 0;
5738 iovb->tail = iovb->data = iovb->head;
5739 - ATM_SKB(iovb)->vcc = vcc;
5740 + NS_SKB(iovb)->vcc = vcc;
5742 - iov = &((struct iovec *) iovb->data)[ATM_SKB(iovb)->iovcnt++];
5743 + iov = &((struct iovec *) iovb->data)[NS_SKB(iovb)->iovcnt++];
5744 iov->iov_base = (void *) skb;
5745 iov->iov_len = ns_rsqe_cellcount(rsqe) * 48;
5746 iovb->len += iov->iov_len;
5748 - if (ATM_SKB(iovb)->iovcnt == 1)
5749 + if (NS_SKB(iovb)->iovcnt == 1)
5751 if (skb->list != &card->sbpool.queue)
5753 @@ -2317,11 +2324,12 @@
5754 atomic_inc(&vcc->stats->rx_err);
5755 recycle_rx_buf(card, skb);
5758 recycle_iov_buf(card, iovb);
5762 - else /* ATM_SKB(iovb)->iovcnt >= 2 */
5763 + else /* NS_SKB(iovb)->iovcnt >= 2 */
5765 if (skb->list != &card->lbpool.queue)
5767 @@ -2330,8 +2338,9 @@
5768 which_list(card, skb);
5769 atomic_inc(&vcc->stats->rx_err);
5770 recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
5771 - ATM_SKB(iovb)->iovcnt);
5772 + NS_SKB(iovb)->iovcnt);
5775 recycle_iov_buf(card, iovb);
5778 @@ -2354,15 +2363,16 @@
5780 atomic_inc(&vcc->stats->rx_err);
5781 recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
5782 - ATM_SKB(iovb)->iovcnt);
5783 + NS_SKB(iovb)->iovcnt);
5786 recycle_iov_buf(card, iovb);
5790 /* By this point we (hopefully) have a complete SDU without errors. */
5792 - if (ATM_SKB(iovb)->iovcnt == 1) /* Just a small buffer */
5793 + if (NS_SKB(iovb)->iovcnt == 1) /* Just a small buffer */
5795 /* skb points to a small buffer */
5796 if (!atm_charge(vcc, skb->truesize))
5797 @@ -2384,7 +2394,7 @@
5798 atomic_inc(&vcc->stats->rx);
5801 - else if (ATM_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */
5802 + else if (NS_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */
5806 @@ -2461,8 +2471,9 @@
5807 printk("nicstar%d: Out of huge buffers.\n", card->index);
5808 atomic_inc(&vcc->stats->rx_drop);
5809 recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
5810 - ATM_SKB(iovb)->iovcnt);
5811 + NS_SKB(iovb)->iovcnt);
5814 recycle_iov_buf(card, iovb);
5817 @@ -2499,7 +2510,7 @@
5819 if (!atm_charge(vcc, hb->truesize))
5821 - recycle_iovec_rx_bufs(card, iov, ATM_SKB(iovb)->iovcnt);
5822 + recycle_iovec_rx_bufs(card, iov, NS_SKB(iovb)->iovcnt);
5823 if (card->hbpool.count < card->hbnr.max)
5825 skb_queue_tail(&card->hbpool.queue, hb);
5826 @@ -2522,7 +2533,7 @@
5829 /* Copy all large buffers to the huge buffer and free them */
5830 - for (j = 1; j < ATM_SKB(iovb)->iovcnt; j++)
5831 + for (j = 1; j < NS_SKB(iovb)->iovcnt; j++)
5833 lb = (struct sk_buff *) iov->iov_base;
5834 tocopy = MIN(remaining, iov->iov_len);
5835 @@ -2550,7 +2561,7 @@
5837 recycle_iov_buf(card, iovb);
5844 diff -urN linux-2.4.20/drivers/atm/nicstar.h linux-2.4.20-atm/drivers/atm/nicstar.h
5845 --- linux-2.4.20/drivers/atm/nicstar.h Thu Oct 25 22:53:46 2001
5846 +++ linux-2.4.20-atm/drivers/atm/nicstar.h Wed May 28 01:58:41 2003
5848 /* ESI stuff ******************************************************************/
5850 #define NICSTAR_EPROM_MAC_ADDR_OFFSET 0x6C
5851 +#define NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT 0xF6
5854 /* #defines *******************************************************************/
5855 @@ -748,6 +749,14 @@
5862 + struct atm_vcc *vcc;
5866 +#define NS_SKB(skb) (((struct ns_skb_data *) (skb)->cb))
5868 typedef struct ns_dev
5870 diff -urN linux-2.4.20/drivers/atm/zatm.c linux-2.4.20-atm/drivers/atm/zatm.c
5871 --- linux-2.4.20/drivers/atm/zatm.c Fri Sep 14 23:40:00 2001
5872 +++ linux-2.4.20-atm/drivers/atm/zatm.c Wed May 28 01:58:41 2003
5873 @@ -827,10 +827,10 @@
5874 vcc = ATM_SKB(skb)->vcc;
5875 zatm_dev = ZATM_DEV(vcc->dev);
5876 zatm_vcc = ZATM_VCC(vcc);
5877 - EVENT("iovcnt=%d\n",ATM_SKB(skb)->iovcnt,0);
5878 + EVENT("nr_frags=%d\n",skb_shinfo(skb)->nr_frags,0);
5881 - if (!ATM_SKB(skb)->iovcnt) {
5882 + if (!skb_shinfo(skb)->nr_frags) {
5883 if (zatm_vcc->txing == RING_ENTRIES-1) {
5884 restore_flags(flags);
5886 @@ -1579,8 +1579,6 @@
5887 DPRINTK(">zatm_open\n");
5888 zatm_dev = ZATM_DEV(vcc->dev);
5889 if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ZATM_VCC(vcc) = NULL;
5890 - error = atm_find_ci(vcc,&vpi,&vci);
5891 - if (error) return error;
5894 if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
5895 diff -urN linux-2.4.20/include/linux/atm_he.h linux-2.4.20-atm/include/linux/atm_he.h
5896 --- linux-2.4.20/include/linux/atm_he.h Thu Jan 1 01:00:00 1970
5897 +++ linux-2.4.20-atm/include/linux/atm_he.h Wed May 28 01:58:41 2003
5901 +#ifndef LINUX_ATM_HE_H
5902 +#define LINUX_ATM_HE_H
5904 +#include <linux/atmioc.h>
5906 +#define HE_GET_REG _IOW('a', ATMIOC_SARPRV, struct atmif_sioc)
5908 +#define HE_REGTYPE_PCI 1
5909 +#define HE_REGTYPE_RCM 2
5910 +#define HE_REGTYPE_TCM 3
5911 +#define HE_REGTYPE_MBOX 4
5913 +struct he_ioctl_reg {
5914 + unsigned addr, val;
5918 +#endif /* LINUX_ATM_HE_H */
5919 diff -urN linux-2.4.20/include/linux/atm_tcp.h linux-2.4.20-atm/include/linux/atm_tcp.h
5920 --- linux-2.4.20/include/linux/atm_tcp.h Fri Dec 29 23:35:47 2000
5921 +++ linux-2.4.20-atm/include/linux/atm_tcp.h Wed May 28 01:58:41 2003
5923 struct module *owner;
5926 -extern struct atm_tcp_ops atm_tcp_ops;
5927 +extern struct atm_tcp_ops *atm_tcp_ops;
5931 diff -urN linux-2.4.20/include/linux/atmdev.h linux-2.4.20-atm/include/linux/atmdev.h
5932 --- linux-2.4.20/include/linux/atmdev.h Wed May 28 01:54:12 2003
5933 +++ linux-2.4.20-atm/include/linux/atmdev.h Wed May 28 01:58:41 2003
5935 #define ATM_DS3_PCR (8000*12)
5936 /* DS3: 12 cells in a 125 usec time slot */
5938 -#define ATM_PDU_OVHD 0 /* number of bytes to charge against buffer
5941 -#define ATM_SD(s) ((s)->sk->protinfo.af_atm)
5942 +#define atm_sk(__sk) ((struct atm_vcc *)(__sk)->protinfo.af_atm)
5943 +#define ATM_SD(s) (atm_sk((s)->sk))
5946 #define __AAL_STAT_ITEMS \
5947 @@ -292,10 +291,6 @@
5948 struct atm_sap sap; /* SAP */
5949 void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
5950 void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
5951 - struct sk_buff *(*alloc_tx)(struct atm_vcc *vcc,unsigned int size);
5952 - /* TX allocation routine - can be */
5953 - /* modified by protocol or by driver.*/
5954 - /* NOTE: this interface will change */
5955 int (*push_oam)(struct atm_vcc *vcc,void *cell);
5956 int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
5957 void *dev_data; /* per-device data */
5958 @@ -303,15 +298,10 @@
5959 struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
5960 wait_queue_head_t sleep; /* if socket is busy */
5961 struct sock *sk; /* socket backpointer */
5962 - struct atm_vcc *prev,*next;
5963 /* SVC part --- may move later ------------------------------------- */
5964 - short itf; /* interface number */
5965 struct sockaddr_atmsvc local;
5966 struct sockaddr_atmsvc remote;
5967 void (*callback)(struct atm_vcc *vcc);
5968 - struct sk_buff_head listenq;
5969 - int backlog_quota; /* number of connection requests we */
5970 - /* can still accept */
5971 int reply; /* also used by ATMTCP */
5972 /* Multipoint part ------------------------------------------------- */
5973 struct atm_vcc *session; /* session VCC descriptor */
5976 const char *type; /* device type name */
5977 int number; /* device index */
5978 - struct atm_vcc *vccs; /* VCC table (or NULL) */
5979 - struct atm_vcc *last; /* last VCC (or undefined) */
5980 void *dev_data; /* per-device data */
5981 void *phy_data; /* private PHY date */
5982 atm_dev_flags_t flags; /* device flags (ATM_DF_*) */
5984 struct k_atm_dev_stats stats; /* statistics */
5985 char signal; /* signal status (ATM_PHY_SIG_*) */
5986 int link_rate; /* link rate (default: OC3) */
5987 + atomic_t refcnt; /* reference count */
5988 + spinlock_t lock; /* protect internal members */
5989 #ifdef CONFIG_PROC_FS
5990 struct proc_dir_entry *proc_entry; /* proc entry */
5991 char *proc_name; /* proc entry name */
5993 void (*feedback)(struct atm_vcc *vcc,struct sk_buff *skb,
5994 unsigned long start,unsigned long dest,int len);
5995 int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags);
5996 - void (*free_rx_skb)(struct atm_vcc *vcc, struct sk_buff *skb);
5997 - /* @@@ temporary hack */
5998 int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
5999 struct module *owner;
6001 @@ -404,53 +392,94 @@
6003 struct atm_skb_data {
6004 struct atm_vcc *vcc; /* ATM VCC */
6005 - int iovcnt; /* 0 for "normal" operation */
6006 unsigned long atm_options; /* ATM layer options */
6009 +extern struct sock *vcc_sklist;
6010 +extern rwlock_t vcc_sklist_lock;
6012 #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
6014 struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
6015 int number,atm_dev_flags_t *flags); /* number == -1: pick first available */
6016 -struct atm_dev *atm_find_dev(int number);
6017 void atm_dev_deregister(struct atm_dev *dev);
6018 +struct atm_dev *atm_dev_lookup(int number);
6019 +void atm_dev_hold(struct atm_dev *dev);
6020 +void atm_dev_release(struct atm_dev *dev);
6021 void shutdown_atm_dev(struct atm_dev *dev);
6022 -void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev);
6023 +void vcc_insert_socket(struct atm_dev *dev, struct sock *sk);
6024 +void vcc_remove_socket(struct atm_dev *dev, struct sock *sk);
6028 - * This is approximately the algorithm used by alloc_skb.
6031 +static inline int atm_guess_pdu2truesize(int pdu_size)
6033 + /* must match allocation in alloc_skb */
6034 + return SKB_DATA_ALIGN(pdu_size) + sizeof(struct sk_buff);
6038 -static __inline__ int atm_guess_pdu2truesize(int pdu_size)
6039 +static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
6041 - return ((pdu_size+15) & ~15) + sizeof(struct sk_buff);
6042 + atomic_add(truesize, &vcc->sk->rmem_alloc);
6046 -static __inline__ void atm_force_charge(struct atm_vcc *vcc,int truesize)
6047 +static inline void atm_return(struct atm_vcc *vcc,int truesize)
6049 - atomic_add(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
6050 + atomic_sub(truesize, &vcc->sk->rmem_alloc);
6054 +static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
6056 + return (size+atomic_read(&vcc->sk->wmem_alloc)) < vcc->sk->sndbuf;
6060 +static inline struct atm_vcc *__vcc_lookup(struct atm_dev *dev, short vpi, int vci)
6062 + struct atm_vcc *vcc;
6065 + for(s = vcc_sklist; s; s = s->next) {
6067 + if (vcc->vci == vci && vcc->vpi == vpi && vcc->dev == dev) return vcc;
6074 +static inline struct atm_vcc *vcc_lookup(struct atm_dev *dev, short vpi, int vci)
6076 + struct atm_vcc *vcc;
6078 + read_lock(&vcc_sklist_lock);
6079 + if ((vcc = __vcc_lookup(dev, vpi, vci))) {
6080 + sock_hold(vcc->sk);
6081 + read_unlock(&vcc_sklist_lock);
6084 + read_unlock(&vcc_sklist_lock);
6089 -static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
6090 +static inline void vcc_hold(struct atm_vcc *vcc)
6092 - atomic_sub(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
6093 + sock_hold(vcc->sk);
6097 -static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size)
6098 +static inline void vcc_put(struct atm_vcc *vcc)
6100 - return size+atomic_read(&vcc->sk->wmem_alloc)+ATM_PDU_OVHD < vcc->sk->sndbuf;
6101 + sock_put(vcc->sk);
6105 int atm_charge(struct atm_vcc *vcc,int truesize);
6106 struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
6108 -int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci);
6109 int atm_pcr_goal(struct atm_trafprm *tp);
6111 void atm_async_release_vcc(struct atm_vcc *vcc,int reply);
6112 diff -urN linux-2.4.20/include/linux/net.h linux-2.4.20-atm/include/linux/net.h
6113 --- linux-2.4.20/include/linux/net.h Thu Nov 22 20:46:19 2001
6114 +++ linux-2.4.20-atm/include/linux/net.h Wed May 28 01:58:41 2003
6116 extern int sock_recvmsg(struct socket *, struct msghdr *m, int len, int flags);
6117 extern int sock_readv_writev(int type, struct inode * inode, struct file * file,
6118 const struct iovec * iov, long count, long size);
6119 +extern struct socket *sockfd_lookup(int fd, int *err);
6121 extern int net_ratelimit(void);
6122 extern unsigned long net_random(void);
6123 diff -urN linux-2.4.20/include/net/atmclip.h linux-2.4.20-atm/include/net/atmclip.h
6124 --- linux-2.4.20/include/net/atmclip.h Thu Nov 22 20:49:31 2001
6125 +++ linux-2.4.20-atm/include/net/atmclip.h Wed May 28 01:58:41 2003
6130 -extern struct atm_vcc *atmarpd; /* ugly */
6131 extern struct neigh_table clip_tbl;
6132 +extern struct atm_vcc *atmarpd; /* ugly */
6134 int clip_create(int number);
6135 int clip_mkip(struct atm_vcc *vcc,int timeout);
6136 int clip_setentry(struct atm_vcc *vcc,u32 ip);
6137 int clip_encap(struct atm_vcc *vcc,int mode);
6138 -void atm_clip_init(void);
6140 +struct atm_clip_ops {
6141 + int (*clip_create)(int number);
6142 + int (*clip_mkip)(struct atm_vcc *vcc,int timeout);
6143 + int (*clip_setentry)(struct atm_vcc *vcc,u32 ip);
6144 + int (*clip_encap)(struct atm_vcc *vcc,int mode);
6145 + void (*clip_push)(struct atm_vcc *vcc,struct sk_buff *skb);
6146 + int (*atm_init_atmarp)(struct atm_vcc *vcc);
6147 + struct module *owner;
6151 +extern struct neigh_table *clip_tbl_hook;
6152 +extern struct atm_clip_ops *atm_clip_ops;
6156 diff -urN linux-2.4.20/net/Config.in linux-2.4.20-atm/net/Config.in
6157 --- linux-2.4.20/net/Config.in Sat Aug 3 02:39:46 2002
6158 +++ linux-2.4.20-atm/net/Config.in Wed May 28 01:58:41 2003
6162 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
6163 - bool 'Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)' CONFIG_ATM
6164 - if [ "$CONFIG_ATM" = "y" ]; then
6165 + tristate 'Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)' CONFIG_ATM
6166 + if [ "$CONFIG_ATM" != "n" ]; then
6167 if [ "$CONFIG_INET" = "y" ]; then
6168 - bool ' Classical IP over ATM' CONFIG_ATM_CLIP
6169 + dep_tristate ' Classical IP over ATM' CONFIG_ATM_CLIP $CONFIG_ATM
6170 if [ "$CONFIG_ATM_CLIP" = "y" ]; then
6171 bool ' Do NOT send ICMP if no neighbour' CONFIG_ATM_CLIP_NO_ICMP
6174 - tristate ' LAN Emulation (LANE) support' CONFIG_ATM_LANE
6175 + dep_tristate ' LAN Emulation (LANE) support' CONFIG_ATM_LANE $CONFIG_ATM
6176 if [ "$CONFIG_INET" = "y" -a "$CONFIG_ATM_LANE" != "n" ]; then
6177 - tristate ' Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA
6178 + dep_tristate ' Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA $CONFIG_ATM
6180 - tristate ' RFC1483/2684 Bridged protocols' CONFIG_ATM_BR2684
6181 + dep_tristate ' RFC1483/2684 Bridged protocols' CONFIG_ATM_BR2684 $CONFIG_ATM
6182 if [ "$CONFIG_ATM_BR2684" != "n" ]; then
6183 bool ' Per-VC IP filter kludge' CONFIG_ATM_BR2684_IPFILTER
6185 diff -urN linux-2.4.20/net/atm/Makefile linux-2.4.20-atm/net/atm/Makefile
6186 --- linux-2.4.20/net/atm/Makefile Sat Aug 3 02:39:46 2002
6187 +++ linux-2.4.20-atm/net/atm/Makefile Wed May 28 01:58:41 2003
6189 list-multi := mpoa.o
6190 mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o
6192 -obj-$(CONFIG_ATM) := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
6193 +obj-y := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
6194 +obj-m := $(O_TARGET)
6196 -ifeq ($(CONFIG_ATM_CLIP),y)
6198 -NEED_IPCOM = ipcommon.o
6201 -ifeq ($(CONFIG_ATM_BR2684),y)
6202 - NEED_IPCOM = ipcommon.o
6204 - ifeq ($(CONFIG_ATM_BR2684),m)
6205 - NEED_IPCOM = ipcommon.o
6208 +obj-$(CONFIG_ATM_CLIP) += clip.o
6209 obj-$(CONFIG_ATM_BR2684) += br2684.o
6211 -ifeq ($(CONFIG_NET_SCH_ATM),y)
6212 -NEED_IPCOM = ipcommon.o
6213 +ifneq ($(CONFIG_ATM_CLIP),n)
6214 + ip-common-obj-y = ipcommon.o
6217 -obj-y += $(NEED_IPCOM)
6219 -ifeq ($(CONFIG_PROC_FS),y)
6221 +ifneq ($(CONFIG_ATM_BR2684),n)
6222 + ip-common-obj-y = ipcommon.o
6224 +ifneq ($(CONFIG_NET_SCH_ATM),n)
6225 + ip-common-obj-y = ipcommon.o
6227 +obj-y += $(ip-common-obj-y)
6229 +obj-$(CONFIG_PROC_FS) += proc.o
6230 obj-$(CONFIG_ATM_LANE) += lec.o
6231 obj-$(CONFIG_ATM_MPOA) += mpoa.o
6232 obj-$(CONFIG_PPPOATM) += pppoatm.o
6233 diff -urN linux-2.4.20/net/atm/addr.c linux-2.4.20-atm/net/atm/addr.c
6234 --- linux-2.4.20/net/atm/addr.c Fri Apr 6 19:51:19 2001
6235 +++ linux-2.4.20-atm/net/atm/addr.c Wed May 28 01:58:41 2003
6241 - * Avoid modification of any list of local interfaces while reading it
6242 - * (which may involve page faults and therefore rescheduling)
6245 -static DECLARE_MUTEX(local_lock);
6246 -extern spinlock_t atm_dev_lock;
6248 static void notify_sigd(struct atm_dev *dev)
6250 struct sockaddr_atmpvc pvc;
6253 struct atm_dev_addr *this;
6255 - down(&local_lock);
6256 + spin_lock(&dev->lock);
6257 while (dev->local) {
6259 dev->local = this->next;
6263 + spin_unlock(&dev->lock);
6269 error = check_addr(addr);
6270 if (error) return error;
6271 - down(&local_lock);
6272 + spin_lock(&dev->lock);
6273 for (walk = &dev->local; *walk; walk = &(*walk)->next)
6274 if (identical(&(*walk)->addr,addr)) {
6276 + spin_unlock(&dev->lock);
6279 - *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_KERNEL);
6280 + *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_ATOMIC);
6283 + spin_unlock(&dev->lock);
6286 (*walk)->addr = *addr;
6287 (*walk)->next = NULL;
6289 + spin_unlock(&dev->lock);
6293 @@ -104,17 +96,17 @@
6295 error = check_addr(addr);
6296 if (error) return error;
6297 - down(&local_lock);
6298 + spin_lock(&dev->lock);
6299 for (walk = &dev->local; *walk; walk = &(*walk)->next)
6300 if (identical(&(*walk)->addr,addr)) break;
6303 + spin_unlock(&dev->lock);
6308 + spin_unlock(&dev->lock);
6314 @@ -125,21 +117,21 @@
6315 struct atm_dev_addr *walk;
6318 - down(&local_lock);
6319 + spin_lock(&dev->lock);
6321 for (walk = dev->local; walk; walk = walk->next) {
6322 total += sizeof(struct sockaddr_atmsvc);
6325 + spin_unlock(&dev->lock);
6328 if (copy_to_user(u_buf,&walk->addr,
6329 sizeof(struct sockaddr_atmsvc))) {
6331 + spin_unlock(&dev->lock);
6337 + spin_unlock(&dev->lock);
6340 diff -urN linux-2.4.20/net/atm/atm_misc.c linux-2.4.20-atm/net/atm/atm_misc.c
6341 --- linux-2.4.20/net/atm/atm_misc.c Wed May 28 01:54:25 2003
6342 +++ linux-2.4.20-atm/net/atm/atm_misc.c Wed May 28 01:58:41 2003
6347 -static int check_ci(struct atm_vcc *vcc,short vpi,int vci)
6349 - struct atm_vcc *walk;
6351 - for (walk = vcc->dev->vccs; walk; walk = walk->next)
6352 - if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vpi == vpi &&
6353 - walk->vci == vci && ((walk->qos.txtp.traffic_class !=
6354 - ATM_NONE && vcc->qos.txtp.traffic_class != ATM_NONE) ||
6355 - (walk->qos.rxtp.traffic_class != ATM_NONE &&
6356 - vcc->qos.rxtp.traffic_class != ATM_NONE)))
6357 - return -EADDRINUSE;
6358 - /* allow VCCs with same VPI/VCI iff they don't collide on
6359 - TX/RX (but we may refuse such sharing for other reasons,
6360 - e.g. if protocol requires to have both channels) */
6365 -int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
6367 - static short p = 0; /* poor man's per-device cache */
6372 - if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY)
6373 - return check_ci(vcc,*vpi,*vci);
6374 - /* last scan may have left values out of bounds for current device */
6375 - if (*vpi != ATM_VPI_ANY) p = *vpi;
6376 - else if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
6377 - if (*vci != ATM_VCI_ANY) c = *vci;
6378 - else if (c < ATM_NOT_RSV_VCI || c >= 1 << vcc->dev->ci_range.vci_bits)
6379 - c = ATM_NOT_RSV_VCI;
6383 - if (!check_ci(vcc,p,c)) {
6388 - if (*vci == ATM_VCI_ANY) {
6390 - if (c >= 1 << vcc->dev->ci_range.vci_bits)
6391 - c = ATM_NOT_RSV_VCI;
6393 - if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
6394 - *vpi == ATM_VPI_ANY) {
6396 - if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
6399 - while (old_p != p || old_c != c);
6400 - return -EADDRINUSE;
6405 * atm_pcr_goal returns the positive PCR if it should be rounded up, the
6406 * negative PCR if it should be rounded down, and zero if the maximum available
6409 EXPORT_SYMBOL(atm_charge);
6410 EXPORT_SYMBOL(atm_alloc_charge);
6411 -EXPORT_SYMBOL(atm_find_ci);
6412 EXPORT_SYMBOL(atm_pcr_goal);
6413 EXPORT_SYMBOL(sonet_copy_stats);
6414 EXPORT_SYMBOL(sonet_subtract_stats);
6415 diff -urN linux-2.4.20/net/atm/br2684.c linux-2.4.20-atm/net/atm/br2684.c
6416 --- linux-2.4.20/net/atm/br2684.c Wed May 28 01:54:25 2003
6417 +++ linux-2.4.20-atm/net/atm/br2684.c Wed May 28 01:58:41 2003
6421 atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc);
6422 - ATM_SKB(skb)->iovcnt = 0;
6423 ATM_SKB(skb)->atm_options = atmvcc->atm_options;
6424 brdev->stats.tx_packets++;
6425 brdev->stats.tx_bytes += skb->len;
6426 diff -urN linux-2.4.20/net/atm/clip.c linux-2.4.20-atm/net/atm/clip.c
6427 --- linux-2.4.20/net/atm/clip.c Wed May 28 01:54:25 2003
6428 +++ linux-2.4.20-atm/net/atm/clip.c Wed May 28 01:58:41 2003
6430 #include <linux/string.h>
6431 #include <linux/errno.h>
6432 #include <linux/kernel.h> /* for UINT_MAX */
6433 +#include <linux/module.h>
6434 #include <linux/netdevice.h>
6435 #include <linux/skbuff.h>
6436 #include <linux/wait.h>
6438 static struct timer_list idle_timer;
6439 static int start_timer = 1;
6442 static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
6444 struct atmarp_ctrl *ctrl;
6446 struct atmarp_entry *entry = NEIGH2ENTRY(n);
6447 struct clip_vcc *clip_vcc;
6449 + write_lock(&n->lock);
6451 for (clip_vcc = entry->vccs; clip_vcc;
6452 clip_vcc = clip_vcc->next)
6453 if (clip_vcc->idle_timeout &&
6457 time_before(jiffies, entry->expires)) {
6458 + write_unlock(&n->lock);
6462 @@ -151,12 +154,14 @@
6463 while ((skb = skb_dequeue(&n->arp_queue)) !=
6466 + write_unlock(&n->lock);
6471 DPRINTK("expired neigh %p\n",n);
6473 + write_unlock(&n->lock);
6478 clip_vcc->last_use = jiffies;
6479 PRIV(skb->dev)->stats.rx_packets++;
6480 PRIV(skb->dev)->stats.rx_bytes += skb->len;
6481 + memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
6486 ((u16 *) here)[3] = skb->protocol;
6488 atomic_add(skb->truesize,&vcc->sk->wmem_alloc);
6489 - ATM_SKB(skb)->iovcnt = 0;
6490 ATM_SKB(skb)->atm_options = vcc->atm_options;
6491 entry->vccs->last_use = jiffies;
6492 DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
6493 @@ -694,25 +699,21 @@
6494 printk(KERN_ERR "atmarpd_close: closing with requests "
6496 skb_queue_purge(&vcc->sk->receive_queue);
6497 + MOD_DEC_USE_COUNT;
6498 DPRINTK("(done)\n");
6502 static struct atmdev_ops atmarpd_dev_ops = {
6503 - close: atmarpd_close,
6504 + .close = atmarpd_close,
6508 static struct atm_dev atmarpd_dev = {
6510 - NULL, /* no PHY */
6511 - "arpd", /* type */
6512 - 999, /* dummy device number */
6513 - NULL,NULL, /* pretend not to have any VCCs */
6514 - NULL,NULL, /* no data */
6515 - { 0 }, /* no flags */
6516 - NULL, /* no local address */
6517 - { 0 } /* no ESI, no statistics */
6518 + .ops = &atmarpd_dev_ops,
6521 + .lock = SPIN_LOCK_UNLOCKED
6526 set_bit(ATM_VF_META,&vcc->flags);
6527 set_bit(ATM_VF_READY,&vcc->flags);
6528 /* allow replies and avoid getting closed if signaling dies */
6529 - bind_vcc(vcc,&atmarpd_dev);
6530 + vcc_insert_socket(&atmarpd_dev, vcc->sk);
6532 vcc->pop = NULL; /* crash */
6533 vcc->push_oam = NULL; /* crash */
6534 @@ -746,10 +747,59 @@
6538 +static struct atm_clip_ops __atm_clip_ops = {
6539 + .clip_create = clip_create,
6540 + .clip_mkip = clip_mkip,
6541 + .clip_setentry = clip_setentry,
6542 + .clip_encap = clip_encap,
6543 + .clip_push = clip_push,
6544 + .atm_init_atmarp = atm_init_atmarp,
6545 + .owner = THIS_MODULE
6548 -void atm_clip_init(void)
6549 +static int __init atm_clip_init(void)
6551 + /* we should use neigh_table_init() */
6552 clip_tbl.lock = RW_LOCK_UNLOCKED;
6553 clip_tbl.kmem_cachep = kmem_cache_create(clip_tbl.id,
6554 clip_tbl.entry_size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
6557 + /* so neigh_ifdown() doesn't complain */
6558 + clip_tbl.proxy_timer.data = 0;
6559 + clip_tbl.proxy_timer.function = 0;
6560 + init_timer(&clip_tbl.proxy_timer);
6561 + skb_queue_head_init(&clip_tbl.proxy_queue);
6564 + atm_clip_ops = &__atm_clip_ops;
6566 + clip_tbl_hook = &clip_tbl;
6571 +static void __exit atm_clip_exit(void)
6573 + struct net_device *dev, *next;
6575 + atm_clip_ops = NULL;
6576 + clip_tbl_hook = NULL;
6578 + neigh_ifdown(&clip_tbl, NULL);
6581 + next = PRIV(dev)->next;
6582 + unregister_netdev(dev);
6586 + if (start_timer == 0) del_timer(&idle_timer);
6588 + kmem_cache_destroy(clip_tbl.kmem_cachep);
6591 +module_init(atm_clip_init);
6592 +module_exit(atm_clip_exit);
6594 +MODULE_LICENSE("GPL");
6595 diff -urN linux-2.4.20/net/atm/common.c linux-2.4.20-atm/net/atm/common.c
6596 --- linux-2.4.20/net/atm/common.c Wed May 28 01:54:25 2003
6597 +++ linux-2.4.20-atm/net/atm/common.c Wed May 28 02:03:31 2003
6600 #include <linux/config.h>
6601 #include <linux/module.h>
6602 +#include <linux/init.h>
6603 #include <linux/kmod.h>
6604 #include <linux/net.h> /* struct socket, struct net_proto, struct
6607 #include <asm/atomic.h>
6608 #include <asm/poll.h>
6609 #include <asm/ioctls.h>
6610 +#include <asm/semaphore.h>
6612 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
6613 #include <linux/atmlec.h>
6615 #include "lec_arpc.h"
6616 -struct atm_lane_ops atm_lane_ops;
6618 +struct atm_lane_ops *atm_lane_ops;
6619 #ifdef CONFIG_ATM_LANE_MODULE
6620 EXPORT_SYMBOL(atm_lane_ops);
6624 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
6625 #include <linux/atmmpc.h>
6627 -struct atm_mpoa_ops atm_mpoa_ops;
6628 +struct atm_mpoa_ops *atm_mpoa_ops;
6630 #ifdef CONFIG_ATM_MPOA_MODULE
6631 EXPORT_SYMBOL(atm_mpoa_ops);
6634 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
6635 #include <linux/atm_tcp.h>
6636 +struct atm_tcp_ops *atm_tcp_ops;
6637 #ifdef CONFIG_ATM_TCP_MODULE
6638 -struct atm_tcp_ops atm_tcp_ops;
6639 EXPORT_SYMBOL(atm_tcp_ops);
6643 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
6644 +#include <net/atmclip.h>
6645 +struct atm_clip_ops *atm_clip_ops;
6646 +#ifdef CONFIG_ATM_CLIP_MODULE
6647 +EXPORT_SYMBOL(atm_clip_ops);
6651 #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
6652 int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
6653 EXPORT_SYMBOL(pppoatm_ioctl_hook);
6655 #include "common.h" /* prototypes */
6656 #include "protocols.h" /* atm_init_<transport> */
6657 #include "addr.h" /* address registry */
6658 -#ifdef CONFIG_ATM_CLIP
6659 -#include <net/atmclip.h> /* for clip_create */
6661 #include "signaling.h" /* for WAITING and sigd_attach */
6665 #define DPRINTK(format,args...)
6668 -spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
6670 static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
6672 struct sk_buff *skb;
6673 @@ -99,78 +103,94 @@
6675 while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
6676 DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->sk->wmem_alloc),skb->truesize);
6677 - atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
6678 + atomic_add(skb->truesize,&vcc->sk->wmem_alloc);
6683 -int atm_create(struct socket *sock,int protocol,int family)
6684 +static void vcc_destruct(struct sock *sk)
6686 + if (atomic_read(&sk->rmem_alloc))
6687 + printk(KERN_WARNING "rmem leakage (%d bytes) detected.\n", atomic_read(&sk->rmem_alloc));
6689 + if (atomic_read(&sk->wmem_alloc))
6690 + printk(KERN_WARNING "wmem leakage (%d bytes) detected.\n", atomic_read(&sk->wmem_alloc));
6692 + kfree(sk->protinfo.af_atm);
6696 +int vcc_create(struct socket *sock,int protocol,int family)
6699 struct atm_vcc *vcc;
6702 if (sock->type == SOCK_STREAM) return -EINVAL;
6703 - if (!(sk = alloc_atm_vcc_sk(family))) return -ENOMEM;
6704 - vcc = sk->protinfo.af_atm;
6705 + sk = sk_alloc(family, GFP_KERNEL, 1);
6708 + sock_init_data(NULL, sk);
6710 + vcc = atm_sk(sk) = kmalloc(sizeof(*vcc), GFP_KERNEL);
6715 + memset(vcc, 0, sizeof(*vcc));
6718 memset(&vcc->flags,0,sizeof(vcc->flags));
6720 - vcc->alloc_tx = alloc_tx;
6721 vcc->callback = NULL;
6722 memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
6723 memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
6724 vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
6725 - atomic_set(&vcc->sk->wmem_alloc,0);
6726 - atomic_set(&vcc->sk->rmem_alloc,0);
6729 vcc->push_oam = NULL;
6730 vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
6731 vcc->atm_options = vcc->aal_options = 0;
6732 init_waitqueue_head(&vcc->sleep);
6733 - skb_queue_head_init(&vcc->listenq);
6734 sk->sleep = &vcc->sleep;
6736 + sk->destruct = vcc_destruct;
6742 -void atm_release_vcc_sk(struct sock *sk,int free_sk)
6743 +void vcc_destroy_socket(struct sock *sk)
6745 - struct atm_vcc *vcc;
6746 + struct atm_vcc *vcc = atm_sk(sk);
6747 + struct atm_dev *dev = vcc->dev;
6748 struct sk_buff *skb;
6750 - vcc = sk->protinfo.af_atm;
6751 clear_bit(ATM_VF_READY,&vcc->flags);
6753 - if (vcc->dev->ops->close) vcc->dev->ops->close(vcc);
6755 + if (dev->ops->close) dev->ops->close(vcc);
6756 if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */
6758 + vcc_remove_socket(dev, sk); /* no more receive */
6760 while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
6761 atm_return(vcc,skb->truesize);
6762 - if (vcc->dev->ops->free_rx_skb)
6763 - vcc->dev->ops->free_rx_skb(vcc,skb);
6764 - else kfree_skb(skb);
6767 - spin_lock (&atm_dev_lock);
6768 - fops_put (vcc->dev->ops);
6769 - if (atomic_read(&vcc->sk->rmem_alloc))
6770 - printk(KERN_WARNING "atm_release_vcc: strange ... "
6771 - "rmem_alloc == %d after closing\n",
6772 - atomic_read(&vcc->sk->rmem_alloc));
6773 - bind_vcc(vcc,NULL);
6775 - spin_lock (&atm_dev_lock);
6777 - if (free_sk) free_atm_vcc_sk(sk);
6778 + fops_put (dev->ops);
6779 + atm_dev_release(dev);
6782 - spin_unlock (&atm_dev_lock);
6787 -int atm_release(struct socket *sock)
6788 +int vcc_release(struct socket *sock)
6791 - atm_release_vcc_sk(sock->sk,1);
6792 + struct sock *sk = sock->sk;
6794 + vcc_destroy_socket(sk);
6799 @@ -212,7 +232,105 @@
6803 -static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
6804 +static int check_ci(struct atm_dev *dev, struct atm_vcc *vcc, short vpi, int vci)
6806 + struct atm_vcc *walk;
6809 + for(s = vcc_sklist; s; s = s->next) {
6811 + if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->dev == dev && walk->vpi == vpi &&
6812 + walk->vci == vci && ((walk->qos.txtp.traffic_class !=
6813 + ATM_NONE && vcc->qos.txtp.traffic_class != ATM_NONE) ||
6814 + (walk->qos.rxtp.traffic_class != ATM_NONE &&
6815 + vcc->qos.rxtp.traffic_class != ATM_NONE))) {
6816 + return -EADDRINUSE;
6818 + /* allow VCCs with same VPI/VCI iff they don't collide on
6819 + TX/RX (but we may refuse such sharing for other reasons,
6820 + e.g. if protocol requires to have both channels) */
6826 +static int claim_ci(struct atm_dev *dev, struct atm_vcc *vcc, short *vpi, int *vci)
6828 + static short p = 0; /* poor man's per-device cache */
6834 + if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY) {
6835 + error = check_ci(dev, vcc, *vpi, *vci);
6838 + /* last scan may have left values out of bounds for current device */
6839 + if (*vpi != ATM_VPI_ANY) p = *vpi;
6840 + else if (p >= 1 << dev->ci_range.vpi_bits) p = 0;
6841 + if (*vci != ATM_VCI_ANY) c = *vci;
6842 + else if (c < ATM_NOT_RSV_VCI || c >= 1 << dev->ci_range.vci_bits)
6843 + c = ATM_NOT_RSV_VCI;
6847 + if (!check_ci(dev, vcc, p, c)) {
6852 + if (*vci == ATM_VCI_ANY) {
6854 + if (c >= 1 << dev->ci_range.vci_bits)
6855 + c = ATM_NOT_RSV_VCI;
6857 + if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
6858 + *vpi == ATM_VPI_ANY) {
6860 + if (p >= 1 << dev->ci_range.vpi_bits) p = 0;
6863 + while (old_p != p || old_c != c);
6864 + return -EADDRINUSE;
6868 +static void __vcc_insert_socket(struct atm_dev *dev, struct sock *sk)
6870 + atm_sk(sk)->dev = dev;
6871 + sk->next = vcc_sklist;
6873 + vcc_sklist->pprev = &sk->next;
6875 + sk->pprev = &vcc_sklist;
6879 +void vcc_insert_socket(struct atm_dev *dev, struct sock *sk)
6881 + write_lock_irq(&vcc_sklist_lock);
6882 + __vcc_insert_socket(dev, sk);
6883 + write_unlock_irq(&vcc_sklist_lock);
6885 +EXPORT_SYMBOL(vcc_insert_socket);
6888 +void vcc_remove_socket(struct atm_dev *dev, struct sock *sk)
6890 + write_lock_irq(&vcc_sklist_lock);
6893 + sk->next->pprev = sk->pprev;
6894 + *sk->pprev = sk->next;
6897 + write_unlock_irq(&vcc_sklist_lock);
6899 +EXPORT_SYMBOL(vcc_remove_socket);
6902 +static int atm_connect_dev(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
6906 @@ -223,8 +341,16 @@
6908 if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
6911 - bind_vcc(vcc,dev);
6912 + write_lock_irq(&vcc_sklist_lock);
6913 + error = claim_ci(dev, vcc, &vpi, &vci);
6915 + write_unlock_irq(&vcc_sklist_lock);
6920 + __vcc_insert_socket(dev, vcc->sk);
6921 + write_unlock_irq(&vcc_sklist_lock);
6922 switch (vcc->qos.aal) {
6924 error = atm_init_aal0(vcc);
6926 if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal);
6927 if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal);
6929 - bind_vcc(vcc,NULL);
6930 + vcc_remove_socket(dev, vcc->sk);
6933 DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal);
6934 @@ -256,43 +382,24 @@
6935 vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
6936 DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
6937 vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
6938 - fops_get (dev->ops);
6939 + if (dev->ops->owner) try_inc_mod_count(dev->ops->owner);
6940 if (dev->ops->open) {
6941 error = dev->ops->open(vcc,vpi,vci);
6943 - fops_put (dev->ops);
6944 - bind_vcc(vcc,NULL);
6945 + if (dev->ops->owner) __MOD_DEC_USE_COUNT(dev->ops->owner);
6946 + vcc_remove_socket(dev, vcc->sk);
6954 -static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci)
6956 - struct atm_dev *dev;
6959 - spin_lock (&atm_dev_lock);
6960 - dev = atm_find_dev(itf);
6962 - return_val = -ENODEV;
6964 - return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
6966 - spin_unlock (&atm_dev_lock);
6968 - return return_val;
6972 int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
6974 if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
6975 clear_bit(ATM_VF_PARTIAL,&vcc->flags);
6976 else if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) return -EINVAL;
6977 - printk(KERN_DEBUG "atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
6978 + DPRINTK("atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
6979 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
6980 vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr,
6981 vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
6982 @@ -306,21 +413,28 @@
6984 if (itf != ATM_ITF_ANY) {
6986 + struct atm_dev *dev;
6988 - error = atm_do_connect(vcc,itf,vpi,vci);
6989 - if (error) return error;
6992 + dev = atm_dev_lookup(itf);
6993 + if (!dev) return -ENODEV;
6995 + error = atm_connect_dev(vcc,dev,vpi,vci);
6997 + atm_dev_release(dev);
7001 struct atm_dev *dev = NULL;
7002 - struct list_head *p;
7003 + struct list_head *p, *next;
7005 - spin_lock (&atm_dev_lock);
7006 - list_for_each(p, &atm_devs) {
7007 + list_for_each_safe(p, next, &atm_devs) {
7008 dev = list_entry(p, struct atm_dev, dev_list);
7009 - if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
7010 + /* i suppose it could race in here CHAS */
7011 + atm_dev_hold(dev);
7012 + if (!atm_connect_dev(vcc,dev,vpi,vci)) break;
7013 + atm_dev_release(dev);
7016 - spin_unlock (&atm_dev_lock);
7017 if (!dev) return -ENODEV;
7019 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
7020 @@ -397,31 +511,8 @@
7021 (unsigned long) buff,eff_len);
7022 DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->sk->rmem_alloc),skb->truesize);
7023 atm_return(vcc,skb->truesize);
7024 - if (ATM_SKB(skb)->iovcnt) { /* @@@ hack */
7025 - /* iovcnt set, use scatter-gather for receive */
7027 - struct iovec *iov = (struct iovec *)skb->data;
7028 - unsigned char *p = (unsigned char *)buff;
7032 - for (cnt = 0; (cnt < ATM_SKB(skb)->iovcnt) && el; cnt++) {
7033 -/*printk("s-g???: %p -> %p (%d)\n",iov->iov_base,p,iov->iov_len);*/
7034 - error = copy_to_user(p,iov->iov_base,
7035 - (iov->iov_len > el) ? el : iov->iov_len) ?
7038 - p += iov->iov_len;
7039 - el -= (iov->iov_len > el)?el:iov->iov_len;
7042 - if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
7043 - else vcc->dev->ops->free_rx_skb(vcc, skb);
7044 - return error ? error : eff_len;
7046 error = copy_to_user(buff,skb->data,eff_len) ? -EFAULT : 0;
7047 - if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
7048 - else vcc->dev->ops->free_rx_skb(vcc, skb);
7050 return error ? error : eff_len;
7054 add_wait_queue(&vcc->sleep,&wait);
7055 set_current_state(TASK_INTERRUPTIBLE);
7057 - while (!(skb = vcc->alloc_tx(vcc,eff))) {
7058 + while (!(skb = alloc_tx(vcc,eff))) {
7059 if (m->msg_flags & MSG_DONTWAIT) {
7063 remove_wait_queue(&vcc->sleep,&wait);
7064 if (error) return error;
7065 skb->dev = NULL; /* for paths shared with net_device interfaces */
7066 - ATM_SKB(skb)->iovcnt = 0;
7067 ATM_SKB(skb)->atm_options = vcc->atm_options;
7068 if (copy_from_user(skb_put(skb,size),buff,size)) {
7070 @@ -498,15 +588,14 @@
7072 poll_wait(file,&vcc->sleep,wait);
7074 - if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq))
7075 + if (skb_peek(&vcc->sk->receive_queue))
7076 mask |= POLLIN | POLLRDNORM;
7077 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
7078 test_bit(ATM_VF_CLOSE,&vcc->flags))
7080 if (sock->state != SS_CONNECTING) {
7081 if (vcc->qos.txtp.traffic_class != ATM_NONE &&
7082 - vcc->qos.txtp.max_sdu+atomic_read(&vcc->sk->wmem_alloc)+
7083 - ATM_PDU_OVHD <= vcc->sk->sndbuf)
7084 + vcc->qos.txtp.max_sdu+atomic_read(&vcc->sk->wmem_alloc) <= vcc->sk->sndbuf)
7085 mask |= POLLOUT | POLLWRNORM;
7087 else if (vcc->reply != WAITING) {
7090 int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
7092 - struct atm_dev *dev;
7093 + struct atm_dev *dev = NULL;
7094 struct list_head *p;
7095 struct atm_vcc *vcc;
7096 int *tmp_buf, *tmp_p;
7098 int error,len,size,number, ret_val;
7101 - spin_lock (&atm_dev_lock);
7108 ret_val = put_user(vcc->sk->sndbuf-
7109 - atomic_read(&vcc->sk->wmem_alloc)-ATM_PDU_OVHD,
7110 + atomic_read(&vcc->sk->wmem_alloc),
7111 (int *) arg) ? -EFAULT : 0;
7114 @@ -601,13 +689,14 @@
7118 + read_lock(&atm_dev_lock);
7119 list_for_each(p, &atm_devs)
7120 size += sizeof(int);
7125 - tmp_buf = kmalloc(size,GFP_KERNEL);
7126 + tmp_buf = kmalloc(size, GFP_ATOMIC);
7131 dev = list_entry(p, struct atm_dev, dev_list);
7132 *tmp_p++ = dev->number;
7134 + read_unlock(&atm_dev_lock);
7136 ret_val = ((copy_to_user(buf, tmp_buf, size)) ||
7137 put_user(size, &((struct atm_iobuf *) arg)->length)
7139 @@ -654,39 +745,50 @@
7140 if (!error) sock->state = SS_CONNECTED;
7143 -#ifdef CONFIG_ATM_CLIP
7144 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
7146 if (!capable(CAP_NET_ADMIN))
7149 - ret_val = clip_create(arg);
7150 + ret_val = atm_clip_ops->clip_create(arg);
7153 if (!capable(CAP_NET_ADMIN)) {
7157 - error = atm_init_atmarp(vcc);
7158 - if (!error) sock->state = SS_CONNECTED;
7159 +#if defined(CONFIG_ATM_CLIP_MODULE)
7160 + if (atm_clip_ops == NULL)
7161 + request_module("clip");
7163 + if (atm_clip_ops && !try_inc_mod_count(atm_clip_ops->owner)) {
7164 + ret_val = -ENOSYS;
7167 + error = atm_clip_ops->atm_init_atmarp(vcc);
7169 + sock->state = SS_CONNECTED;
7171 + __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
7175 if (!capable(CAP_NET_ADMIN))
7178 - ret_val = clip_mkip(vcc,arg);
7179 + ret_val = atm_clip_ops->clip_mkip(vcc,arg);
7181 case ATMARP_SETENTRY:
7182 if (!capable(CAP_NET_ADMIN))
7185 - ret_val = clip_setentry(vcc,arg);
7186 + ret_val = atm_clip_ops->clip_setentry(vcc,arg);
7189 if (!capable(CAP_NET_ADMIN))
7192 - ret_val = clip_encap(vcc,arg);
7193 + ret_val = atm_clip_ops->clip_encap(vcc,arg);
7196 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
7197 @@ -695,27 +797,32 @@
7201 - if (atm_lane_ops.lecd_attach == NULL)
7203 - if (atm_lane_ops.lecd_attach == NULL) { /* try again */
7204 +#if defined(CONFIG_ATM_LANE_MODULE)
7205 + if (atm_lane_ops == NULL)
7206 + request_module("lec");
7208 + if (atm_lane_ops && !try_inc_mod_count(atm_lane_ops->owner)) {
7212 - error = atm_lane_ops.lecd_attach(vcc, (int)arg);
7213 - if (error >= 0) sock->state = SS_CONNECTED;
7214 + error = atm_lane_ops->lecd_attach(vcc, (int)arg);
7216 + sock->state = SS_CONNECTED;
7218 + __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
7222 if (!capable(CAP_NET_ADMIN))
7225 - ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
7226 + ret_val = atm_lane_ops->mcast_attach(vcc, (int)arg);
7229 if (!capable(CAP_NET_ADMIN))
7232 - ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
7233 + ret_val = atm_lane_ops->vcc_attach(vcc, (void*)arg);
7236 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
7237 @@ -724,21 +831,26 @@
7241 - if (atm_mpoa_ops.mpoad_attach == NULL)
7243 - if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */
7244 +#if defined(CONFIG_ATM_MPOA_MODULE)
7245 + if (atm_mpoa_ops == NULL)
7246 + request_module("mpoa");
7248 + if (atm_mpoa_ops && !try_inc_mod_count(atm_mpoa_ops->owner)) {
7252 - error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
7253 - if (error >= 0) sock->state = SS_CONNECTED;
7254 + error = atm_mpoa_ops->mpoad_attach(vcc, (int)arg);
7256 + sock->state = SS_CONNECTED;
7258 + __MOD_DEC_USE_COUNT(atm_mpoa_ops->owner);
7262 if (!capable(CAP_NET_ADMIN))
7265 - ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
7266 + ret_val = atm_mpoa_ops->vcc_attach(vcc, arg);
7269 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
7270 @@ -747,14 +859,14 @@
7274 - if (!atm_tcp_ops.attach) {
7275 + if (!atm_tcp_ops) {
7279 - fops_get (&atm_tcp_ops);
7280 - error = atm_tcp_ops.attach(vcc,(int) arg);
7281 + fops_get(atm_tcp_ops);
7282 + error = atm_tcp_ops->attach(vcc,(int) arg);
7283 if (error >= 0) sock->state = SS_CONNECTED;
7284 - else fops_put (&atm_tcp_ops);
7285 + else fops_put(atm_tcp_ops);
7289 @@ -762,12 +874,12 @@
7293 - if (!atm_tcp_ops.create_persistent) {
7294 + if (!atm_tcp_ops) {
7298 - error = atm_tcp_ops.create_persistent((int) arg);
7299 - if (error < 0) fops_put (&atm_tcp_ops);
7300 + error = atm_tcp_ops->create_persistent((int) arg);
7301 + if (error < 0) fops_put(atm_tcp_ops);
7305 @@ -775,12 +887,12 @@
7309 - if (!atm_tcp_ops.remove_persistent) {
7310 + if (!atm_tcp_ops) {
7314 - error = atm_tcp_ops.remove_persistent((int) arg);
7315 - fops_put (&atm_tcp_ops);
7316 + error = atm_tcp_ops->remove_persistent((int) arg);
7317 + fops_put(atm_tcp_ops);
7325 - if (!(dev = atm_find_dev(number))) {
7326 + if (!(dev = atm_dev_lookup(number))) {
7330 @@ -963,7 +1075,7 @@
7334 - spin_unlock (&atm_dev_lock);
7335 + if (dev) atm_dev_release(dev);
7339 @@ -1034,17 +1146,21 @@
7343 - struct atm_qos qos;
7344 + struct atm_qos *qos;
7346 - if (copy_from_user(&qos,optval,sizeof(qos)))
7347 + qos = kmalloc(sizeof(*qos), GFP_KERNEL);
7350 + if (copy_from_user(qos,optval,sizeof(*qos)))
7352 - error = check_qos(&qos);
7353 + error = check_qos(qos);
7354 if (error) return error;
7355 if (sock->state == SS_CONNECTED)
7356 - return atm_change_qos(vcc,&qos);
7357 + return atm_change_qos(vcc,qos);
7358 if (sock->state != SS_UNCONNECTED)
7363 set_bit(ATM_VF_HASQOS,&vcc->flags);
7366 @@ -1122,40 +1238,6 @@
7371 - * lane_mpoa_init.c: A couple of helper functions
7372 - * to make modular LANE and MPOA client easier to implement
7376 - * This is how it goes:
7378 - * if xxxx is not compiled as module, call atm_xxxx_init_ops()
7380 - * else call atm_mpoa_init_ops() from init_module() within
7381 - * the kernel when xxxx module is loaded
7383 - * In either case function pointers in struct atm_xxxx_ops
7384 - * are initialized to their correct values. Either they
7385 - * point to functions in the module or in the kernel
7388 -extern struct atm_mpoa_ops atm_mpoa_ops; /* in common.c */
7389 -extern struct atm_lane_ops atm_lane_ops; /* in common.c */
7391 -#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
7392 -void atm_mpoa_init(void)
7394 -#ifndef CONFIG_ATM_MPOA_MODULE /* not module */
7395 - atm_mpoa_init_ops(&atm_mpoa_ops);
7397 - request_module("mpoa");
7404 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
7405 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
7406 struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
7407 @@ -1166,15 +1248,33 @@
7408 EXPORT_SYMBOL(br_fdb_put_hook);
7409 #endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
7410 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
7411 +#endif /* defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) */
7414 -void atm_lane_init(void)
7415 +static int __init atm_init(void)
7417 -#ifndef CONFIG_ATM_LANE_MODULE /* not module */
7418 - atm_lane_init_ops(&atm_lane_ops);
7420 - request_module("lec");
7423 + if (atmpvc_init() < 0)
7425 + if (atmsvc_init() < 0)
7427 +#ifdef CONFIG_PROC_FS
7428 + error = atm_proc_init();
7429 + if (error) printk("atm_proc_init fails with %d\n",error);
7436 +static void __exit atm_exit(void)
7438 +#ifdef CONFIG_PROC_FS
7445 +module_init(atm_init);
7446 +module_exit(atm_exit);
7447 +MODULE_LICENSE("GPL");
7448 diff -urN linux-2.4.20/net/atm/common.h linux-2.4.20-atm/net/atm/common.h
7449 --- linux-2.4.20/net/atm/common.h Mon Dec 11 22:33:43 2000
7450 +++ linux-2.4.20-atm/net/atm/common.h Wed May 28 01:58:41 2003
7452 #include <linux/poll.h> /* for poll_table */
7455 -int atm_create(struct socket *sock,int protocol,int family);
7456 -int atm_release(struct socket *sock);
7457 +int vcc_create(struct socket *sock,int protocol,int family);
7458 +int vcc_release(struct socket *sock);
7459 int atm_connect(struct socket *sock,int itf,short vpi,int vci);
7460 int atm_recvmsg(struct socket *sock,struct msghdr *m,int total_len,
7461 int flags,struct scm_cookie *scm);
7465 int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci);
7466 -void atm_release_vcc_sk(struct sock *sk,int free_sk);
7468 void atm_shutdown_dev(struct atm_dev *dev);
7470 +int atmsvc_init(void);
7471 +void atmsvc_exit(void);
7473 +int atmpvc_init(void);
7474 +void atmpvc_exit(void);
7476 int atm_proc_init(void);
7477 +void atm_proc_exit(void);
7481 diff -urN linux-2.4.20/net/atm/ipcommon.c linux-2.4.20-atm/net/atm/ipcommon.c
7482 --- linux-2.4.20/net/atm/ipcommon.c Fri Jul 7 06:37:24 2000
7483 +++ linux-2.4.20-atm/net/atm/ipcommon.c Wed May 28 01:58:41 2003
7485 spin_unlock_irqrestore(&from->lock,flags);
7489 +EXPORT_SYMBOL(llc_oui);
7490 EXPORT_SYMBOL(skb_migrate);
7491 diff -urN linux-2.4.20/net/atm/ipcommon.h linux-2.4.20-atm/net/atm/ipcommon.h
7492 --- linux-2.4.20/net/atm/ipcommon.h Mon Dec 11 22:33:46 2000
7493 +++ linux-2.4.20-atm/net/atm/ipcommon.h Wed May 28 01:58:41 2003
7495 #include <linux/atmdev.h>
7498 -extern struct net_device *clip_devs;
7501 * Appends all skbs from "from" to "to". The operation is atomic with respect
7502 * to all other skb operations on "from" or "to".
7503 diff -urN linux-2.4.20/net/atm/lec.c linux-2.4.20-atm/net/atm/lec.c
7504 --- linux-2.4.20/net/atm/lec.c Wed May 28 01:54:25 2003
7505 +++ linux-2.4.20-atm/net/atm/lec.c Wed May 28 02:12:42 2003
7507 #include <net/arp.h>
7508 #include <net/dst.h>
7509 #include <linux/proc_fs.h>
7510 +#include <linux/spinlock.h>
7512 /* TokenRing if needed */
7515 #include <linux/if_bridge.h>
7516 #include "../bridge/br_private.h"
7517 static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
7519 +extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
7520 + unsigned char *addr);
7521 +extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
7528 #include "lec_arpc.h"
7529 -#include "resources.h" /* for bind_vcc() */
7530 +#include "resources.h"
7533 #define DPRINTK printk
7535 #define DPRINTK(format,args...)
7538 -extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
7539 - unsigned char *addr);
7540 -extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
7542 +static spinlock_t lec_arp_spinlock = SPIN_LOCK_UNLOCKED;
7544 #define DUMP_PACKETS 0 /* 0 = None,
7545 * 1 = 30 first bytes
7546 @@ -196,6 +198,22 @@
7550 +static __inline__ void
7551 +lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
7553 + if (atm_may_send(vcc, skb->len)) {
7554 + atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
7555 + ATM_SKB(skb)->vcc = vcc;
7556 + ATM_SKB(skb)->atm_options = vcc->atm_options;
7557 + priv->stats.tx_packets++;
7558 + priv->stats.tx_bytes += skb->len;
7559 + vcc->send(vcc, skb);
7561 + priv->stats.tx_dropped++;
7562 + dev_kfree_skb(skb);
7567 lec_send_packet(struct sk_buff *skb, struct net_device *dev)
7569 @@ -340,34 +358,10 @@
7570 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
7571 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
7572 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
7573 - ATM_SKB(skb2)->vcc = send_vcc;
7574 - ATM_SKB(skb2)->iovcnt = 0;
7575 - ATM_SKB(skb2)->atm_options = send_vcc->atm_options;
7576 - DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name,
7577 - send_vcc->vpi, send_vcc->vci);
7578 - if (atm_may_send(send_vcc, skb2->len)) {
7579 - atomic_add(skb2->truesize, &send_vcc->sk->wmem_alloc);
7580 - priv->stats.tx_packets++;
7581 - priv->stats.tx_bytes += skb2->len;
7582 - send_vcc->send(send_vcc, skb2);
7584 - priv->stats.tx_dropped++;
7585 - dev_kfree_skb(skb2);
7587 + lec_send(send_vcc, skb2, priv);
7590 - ATM_SKB(skb)->vcc = send_vcc;
7591 - ATM_SKB(skb)->iovcnt = 0;
7592 - ATM_SKB(skb)->atm_options = send_vcc->atm_options;
7593 - if (atm_may_send(send_vcc, skb->len)) {
7594 - atomic_add(skb->truesize, &send_vcc->sk->wmem_alloc);
7595 - priv->stats.tx_packets++;
7596 - priv->stats.tx_bytes += skb->len;
7597 - send_vcc->send(send_vcc, skb);
7599 - priv->stats.tx_dropped++;
7600 - dev_kfree_skb(skb);
7602 + lec_send(send_vcc, skb, priv);
7605 /* Should we wait for card's device driver to notify us? */
7608 char *tmp; /* FIXME */
7610 - atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
7611 + atomic_sub(skb->truesize, &vcc->sk->wmem_alloc);
7612 mesg = (struct atmlec_msg *)skb->data;
7614 tmp += sizeof(struct atmlec_msg);
7615 @@ -548,24 +542,19 @@
7618 printk("%s: Shut down!\n", dev->name);
7619 - MOD_DEC_USE_COUNT;
7620 + __MOD_DEC_USE_COUNT(THIS_MODULE);
7623 static struct atmdev_ops lecdev_ops = {
7624 - close: lec_atm_close,
7625 - send: lec_atm_send
7626 + .close = lec_atm_close,
7627 + .send = lec_atm_send
7630 static struct atm_dev lecatm_dev = {
7634 - 999, /*dummy device number*/
7635 - NULL,NULL, /*no VCCs*/
7636 - NULL,NULL, /*no data*/
7637 - { 0 }, /*no flags*/
7638 - NULL, /* no local address*/
7639 - { 0 } /*no ESI or rest of the atm_dev struct things*/
7640 + .ops = &lecdev_ops,
7643 + .lock = SPIN_LOCK_UNLOCKED,
7648 skb->protocol = eth_type_trans(skb, dev);
7649 priv->stats.rx_packets++;
7650 priv->stats.rx_bytes += skb->len;
7651 + memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
7657 priv->itfnum = i; /* LANE2 addition */
7659 - bind_vcc(vcc, &lecatm_dev);
7660 + vcc_insert_socket(&lecatm_dev, vcc->sk);
7662 vcc->proto_data = dev_lec[i];
7663 set_bit(ATM_VF_META,&vcc->flags);
7664 @@ -833,27 +831,23 @@
7665 if (dev_lec[i]->flags & IFF_UP) {
7666 netif_start_queue(dev_lec[i]);
7668 - MOD_INC_USE_COUNT;
7672 -void atm_lane_init_ops(struct atm_lane_ops *ops)
7674 - ops->lecd_attach = lecd_attach;
7675 - ops->mcast_attach = lec_mcast_attach;
7676 - ops->vcc_attach = lec_vcc_attach;
7677 - ops->get_lecs = get_dev_lec;
7679 - printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
7683 +static struct atm_lane_ops __atm_lane_ops = {
7684 + .lecd_attach = lecd_attach,
7685 + .mcast_attach = lec_mcast_attach,
7686 + .vcc_attach = lec_vcc_attach,
7687 + .get_lecs = get_dev_lec,
7688 + .owner = THIS_MODULE
7691 static int __init lane_module_init(void)
7693 - extern struct atm_lane_ops atm_lane_ops;
7694 + extern struct atm_lane_ops *atm_lane_ops;
7696 - atm_lane_init_ops(&atm_lane_ops);
7697 + atm_lane_ops = &__atm_lane_ops;
7698 + printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
7702 @@ -861,13 +855,10 @@
7703 static void __exit lane_module_cleanup(void)
7706 - extern struct atm_lane_ops atm_lane_ops;
7707 + extern struct atm_lane_ops *atm_lane_ops;
7708 struct lec_priv *priv;
7710 - atm_lane_ops.lecd_attach = NULL;
7711 - atm_lane_ops.mcast_attach = NULL;
7712 - atm_lane_ops.vcc_attach = NULL;
7713 - atm_lane_ops.get_lecs = NULL;
7714 + atm_lane_ops = NULL;
7716 for (i = 0; i < MAX_LEC_ITF; i++) {
7717 if (dev_lec[i] != NULL) {
7719 unregister_netdev(dev_lec[i]);
7727 @@ -1030,7 +1021,7 @@
7728 #include <linux/timer.h>
7729 #include <asm/param.h>
7730 #include <asm/atomic.h>
7731 -#include <linux/inetdevice.h>
7732 +#include <linux/netdevice.h>
7733 #include <net/route.h>
7736 @@ -1055,15 +1046,15 @@
7737 #define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))
7739 static __inline__ void
7740 -lec_arp_lock(struct lec_priv *priv)
7741 +lec_arp_get(struct lec_priv *priv)
7743 - atomic_inc(&priv->lec_arp_lock_var);
7744 + atomic_inc(&priv->lec_arp_users);
7747 static __inline__ void
7748 -lec_arp_unlock(struct lec_priv *priv)
7749 +lec_arp_put(struct lec_priv *priv)
7751 - atomic_dec(&priv->lec_arp_lock_var);
7752 + atomic_dec(&priv->lec_arp_users);
7756 @@ -1114,33 +1105,33 @@
7757 * LANE2: Add to the end of the list to satisfy 8.1.13
7759 static __inline__ void
7760 -lec_arp_put(struct lec_arp_table **lec_arp_tables,
7761 - struct lec_arp_table *to_put)
7762 +lec_arp_add(struct lec_arp_table **lec_arp_tables,
7763 + struct lec_arp_table *to_add)
7765 - unsigned short place;
7766 unsigned long flags;
7767 + unsigned short place;
7768 struct lec_arp_table *tmp;
7770 - save_flags(flags);
7772 + spin_lock_irqsave(&lec_arp_spinlock, flags);
7774 - place = HASH(to_put->mac_addr[ETH_ALEN-1]);
7775 + place = HASH(to_add->mac_addr[ETH_ALEN-1]);
7776 tmp = lec_arp_tables[place];
7777 - to_put->next = NULL;
7778 + to_add->next = NULL;
7780 - lec_arp_tables[place] = to_put;
7781 + lec_arp_tables[place] = to_add;
7783 else { /* add to the end */
7786 - tmp->next = to_put;
7787 + tmp->next = to_add;
7790 - restore_flags(flags);
7791 + spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7793 DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
7794 - 0xff&to_put->mac_addr[0], 0xff&to_put->mac_addr[1],
7795 - 0xff&to_put->mac_addr[2], 0xff&to_put->mac_addr[3],
7796 - 0xff&to_put->mac_addr[4], 0xff&to_put->mac_addr[5]);
7797 + 0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1],
7798 + 0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3],
7799 + 0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]);
7803 @@ -1150,16 +1141,15 @@
7804 lec_arp_remove(struct lec_arp_table **lec_arp_tables,
7805 struct lec_arp_table *to_remove)
7807 + unsigned long flags;
7808 unsigned short place;
7809 struct lec_arp_table *tmp;
7810 - unsigned long flags;
7813 - save_flags(flags);
7815 + spin_lock_irqsave(&lec_arp_spinlock, flags);
7818 - restore_flags(flags);
7819 + spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7822 place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
7823 @@ -1171,7 +1161,7 @@
7826 if (!tmp) {/* Entry was not found */
7827 - restore_flags(flags);
7828 + spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7832 @@ -1197,7 +1187,9 @@
7833 lec_arp_clear_vccs(to_remove);
7835 skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
7836 - restore_flags(flags);
7838 + spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7840 DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
7841 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
7842 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
7843 @@ -1382,12 +1374,8 @@
7844 lec_arp_destroy(struct lec_priv *priv)
7846 struct lec_arp_table *entry, *next;
7847 - unsigned long flags;
7850 - save_flags(flags);
7853 del_timer(&priv->lec_arp_timer);
7856 @@ -1430,7 +1418,6 @@
7857 priv->mcast_vcc = NULL;
7858 memset(priv->lec_arp_tables, 0,
7859 sizeof(struct lec_arp_table*)*LEC_ARP_TABLE_SIZE);
7860 - restore_flags(flags);
7864 @@ -1447,18 +1434,18 @@
7865 DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
7866 mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff,
7867 mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff);
7868 - lec_arp_lock(priv);
7869 + lec_arp_get(priv);
7870 place = HASH(mac_addr[ETH_ALEN-1]);
7872 to_return = priv->lec_arp_tables[place];
7874 if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) {
7875 - lec_arp_unlock(priv);
7876 + lec_arp_put(priv);
7879 to_return = to_return->next;
7881 - lec_arp_unlock(priv);
7882 + lec_arp_put(priv);
7886 @@ -1585,11 +1572,11 @@
7887 del_timer(&priv->lec_arp_timer);
7889 DPRINTK("lec_arp_check_expire %p,%d\n",priv,
7890 - priv->lec_arp_lock_var.counter);
7891 + atomic_read(&priv->lec_arp_users));
7892 DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
7893 priv->lec_no_forward);
7894 - if (!priv->lec_arp_lock_var.counter) {
7895 - lec_arp_lock(priv);
7896 + if (!atomic_read(&priv->lec_arp_users)) {
7897 + lec_arp_get(priv);
7899 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
7900 for(entry = lec_arp_tables[i];entry != NULL;) {
7901 @@ -1627,6 +1614,10 @@
7903 time_after_eq(now, entry->timestamp+
7904 priv->path_switching_delay)) {
7905 + struct sk_buff *skb;
7907 + while ((skb = skb_dequeue(&entry->tx_wait)))
7908 + lec_send(entry->vcc, skb, entry->priv);
7909 entry->last_used = jiffies;
7912 @@ -1635,7 +1626,7 @@
7916 - lec_arp_unlock(priv);
7917 + lec_arp_put(priv);
7919 priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
7920 add_timer(&priv->lec_arp_timer);
7921 @@ -1697,7 +1688,7 @@
7923 return priv->mcast_vcc;
7925 - lec_arp_put(priv->lec_arp_tables, entry);
7926 + lec_arp_add(priv->lec_arp_tables, entry);
7927 /* We want arp-request(s) to be sent */
7928 entry->packets_flooded =1;
7929 entry->status = ESI_ARP_PENDING;
7930 @@ -1722,7 +1713,7 @@
7931 struct lec_arp_table *entry, *next;
7934 - lec_arp_lock(priv);
7935 + lec_arp_get(priv);
7936 DPRINTK("lec_addr_delete\n");
7937 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
7938 for(entry=priv->lec_arp_tables[i];entry != NULL; entry=next) {
7939 @@ -1733,11 +1724,11 @@
7940 lec_arp_remove(priv->lec_arp_tables, entry);
7943 - lec_arp_unlock(priv);
7944 + lec_arp_put(priv);
7948 - lec_arp_unlock(priv);
7949 + lec_arp_put(priv);
7953 @@ -1762,7 +1753,7 @@
7954 return; /* LANE2: ignore targetless LE_ARPs for which
7955 * we have no entry in the cache. 7.1.30
7957 - lec_arp_lock(priv);
7958 + lec_arp_get(priv);
7959 if (priv->lec_arp_empty_ones) {
7960 entry = priv->lec_arp_empty_ones;
7961 if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
7962 @@ -1796,13 +1787,13 @@
7963 entry->status = ESI_FORWARD_DIRECT;
7964 memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
7965 entry->last_used = jiffies;
7966 - lec_arp_put(priv->lec_arp_tables, entry);
7967 + lec_arp_add(priv->lec_arp_tables, entry);
7970 entry->flags|=LEC_REMOTE_FLAG;
7972 entry->flags&=~LEC_REMOTE_FLAG;
7973 - lec_arp_unlock(priv);
7974 + lec_arp_put(priv);
7975 DPRINTK("After update\n");
7976 dump_arp_table(priv);
7978 @@ -1812,11 +1803,11 @@
7980 entry = make_entry(priv, mac_addr);
7982 - lec_arp_unlock(priv);
7983 + lec_arp_put(priv);
7986 entry->status = ESI_UNKNOWN;
7987 - lec_arp_put(priv->lec_arp_tables, entry);
7988 + lec_arp_add(priv->lec_arp_tables, entry);
7989 /* Temporary, changes before end of function */
7991 memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
7992 @@ -1851,7 +1842,7 @@
7994 DPRINTK("After update2\n");
7995 dump_arp_table(priv);
7996 - lec_arp_unlock(priv);
7997 + lec_arp_put(priv);
8001 @@ -1865,7 +1856,7 @@
8002 struct lec_arp_table *entry;
8003 int i, found_entry=0;
8005 - lec_arp_lock(priv);
8006 + lec_arp_get(priv);
8007 if (ioc_data->receive == 2) {
8008 /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
8010 @@ -1874,7 +1865,7 @@
8011 entry = lec_arp_find(priv, bus_mac);
8013 printk("LEC_ARP: Multicast entry not found!\n");
8014 - lec_arp_unlock(priv);
8015 + lec_arp_put(priv);
8018 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
8019 @@ -1883,7 +1874,7 @@
8021 entry = make_entry(priv, bus_mac);
8022 if (entry == NULL) {
8023 - lec_arp_unlock(priv);
8024 + lec_arp_put(priv);
8027 del_timer(&entry->timer);
8028 @@ -1892,7 +1883,7 @@
8029 entry->old_recv_push = old_push;
8030 entry->next = priv->mcast_fwds;
8031 priv->mcast_fwds = entry;
8032 - lec_arp_unlock(priv);
8033 + lec_arp_put(priv);
8035 } else if (ioc_data->receive == 1) {
8036 /* Vcc which we don't want to make default vcc, attach it
8037 @@ -1910,7 +1901,7 @@
8038 ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
8039 entry = make_entry(priv, bus_mac);
8040 if (entry == NULL) {
8041 - lec_arp_unlock(priv);
8042 + lec_arp_put(priv);
8045 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
8046 @@ -1923,7 +1914,7 @@
8047 add_timer(&entry->timer);
8048 entry->next = priv->lec_no_forward;
8049 priv->lec_no_forward = entry;
8050 - lec_arp_unlock(priv);
8051 + lec_arp_put(priv);
8052 dump_arp_table(priv);
8055 @@ -1982,7 +1973,7 @@
8059 - lec_arp_unlock(priv);
8060 + lec_arp_put(priv);
8061 DPRINTK("After vcc was added\n");
8062 dump_arp_table(priv);
8064 @@ -1991,7 +1982,7 @@
8066 entry = make_entry(priv, bus_mac);
8068 - lec_arp_unlock(priv);
8069 + lec_arp_put(priv);
8073 @@ -2004,7 +1995,7 @@
8074 entry->timer.expires = jiffies + priv->vcc_timeout_period;
8075 entry->timer.function = lec_arp_expire_vcc;
8076 add_timer(&entry->timer);
8077 - lec_arp_unlock(priv);
8078 + lec_arp_put(priv);
8079 DPRINTK("After vcc was added\n");
8080 dump_arp_table(priv);
8082 @@ -2020,6 +2011,10 @@
8083 for (entry=priv->lec_arp_tables[i];entry;entry=entry->next) {
8084 if (entry->flush_tran_id == tran_id &&
8085 entry->status == ESI_FLUSH_PENDING) {
8086 + struct sk_buff *skb;
8088 + while ((skb = skb_dequeue(&entry->tx_wait)))
8089 + lec_send(entry->vcc, skb, entry->priv);
8090 entry->status = ESI_FORWARD_DIRECT;
8091 DPRINTK("LEC_ARP: Flushed\n");
8093 @@ -2050,10 +2045,10 @@
8094 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
8095 struct lec_arp_table *to_add;
8097 - lec_arp_lock(priv);
8098 + lec_arp_get(priv);
8099 to_add = make_entry(priv, mac_addr);
8101 - lec_arp_unlock(priv);
8102 + lec_arp_put(priv);
8105 memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
8106 @@ -2063,8 +2058,8 @@
8107 to_add->old_push = vcc->push;
8108 vcc->push = lec_push;
8109 priv->mcast_vcc = vcc;
8110 - lec_arp_put(priv->lec_arp_tables, to_add);
8111 - lec_arp_unlock(priv);
8112 + lec_arp_add(priv->lec_arp_tables, to_add);
8113 + lec_arp_put(priv);
8117 @@ -2076,7 +2071,7 @@
8119 DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci);
8120 dump_arp_table(priv);
8121 - lec_arp_lock(priv);
8122 + lec_arp_get(priv);
8123 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
8124 for(entry = priv->lec_arp_tables[i];entry; entry=next) {
8126 @@ -2138,7 +2133,7 @@
8130 - lec_arp_unlock(priv);
8131 + lec_arp_put(priv);
8132 dump_arp_table(priv);
8135 @@ -2146,9 +2141,9 @@
8136 lec_arp_check_empties(struct lec_priv *priv,
8137 struct atm_vcc *vcc, struct sk_buff *skb)
8139 + unsigned long flags;
8140 struct lec_arp_table *entry, *prev;
8141 struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
8142 - unsigned long flags;
8145 struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
8146 @@ -2158,50 +2153,49 @@
8148 src = hdr->h_source;
8150 - lec_arp_lock(priv);
8151 + lec_arp_get(priv);
8152 entry = priv->lec_arp_empty_ones;
8153 if (vcc == entry->vcc) {
8154 - save_flags(flags);
8156 + spin_lock_irqsave(&lec_arp_spinlock, flags);
8157 del_timer(&entry->timer);
8158 memcpy(entry->mac_addr, src, ETH_ALEN);
8159 entry->status = ESI_FORWARD_DIRECT;
8160 entry->last_used = jiffies;
8161 priv->lec_arp_empty_ones = entry->next;
8162 - restore_flags(flags);
8163 + spin_unlock_irqrestore(&lec_arp_spinlock, flags);
8164 /* We might have got an entry */
8165 if ((prev=lec_arp_find(priv,src))) {
8166 lec_arp_remove(priv->lec_arp_tables, prev);
8169 - lec_arp_put(priv->lec_arp_tables, entry);
8170 - lec_arp_unlock(priv);
8171 + lec_arp_add(priv->lec_arp_tables, entry);
8172 + lec_arp_put(priv);
8175 + spin_lock_irqsave(&lec_arp_spinlock, flags);
8177 entry = entry->next;
8178 while (entry && entry->vcc != vcc) {
8181 entry = entry->next;
8184 DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
8185 - lec_arp_unlock(priv);
8186 + lec_arp_put(priv);
8187 + spin_unlock_irqrestore(&lec_arp_spinlock, flags);
8190 - save_flags(flags);
8192 del_timer(&entry->timer);
8193 memcpy(entry->mac_addr, src, ETH_ALEN);
8194 entry->status = ESI_FORWARD_DIRECT;
8195 entry->last_used = jiffies;
8196 prev->next = entry->next;
8197 - restore_flags(flags);
8198 + spin_unlock_irqrestore(&lec_arp_spinlock, flags);
8199 if ((prev = lec_arp_find(priv, src))) {
8200 lec_arp_remove(priv->lec_arp_tables,prev);
8203 - lec_arp_put(priv->lec_arp_tables,entry);
8204 - lec_arp_unlock(priv);
8205 + lec_arp_add(priv->lec_arp_tables,entry);
8206 + lec_arp_put(priv);
8208 MODULE_LICENSE("GPL");
8209 diff -urN linux-2.4.20/net/atm/lec.h linux-2.4.20-atm/net/atm/lec.h
8210 --- linux-2.4.20/net/atm/lec.h Wed May 28 01:54:25 2003
8211 +++ linux-2.4.20-atm/net/atm/lec.h Wed May 28 01:58:41 2003
8213 int (*mcast_attach)(struct atm_vcc *vcc, int arg);
8214 int (*vcc_attach)(struct atm_vcc *vcc, void *arg);
8215 struct net_device **(*get_lecs)(void);
8216 + struct module *owner;
8221 establishes multiple Multicast Forward VCCs to us. This list
8222 collects all those VCCs. LANEv1 client has only one item in this
8223 list. These entries are not aged out. */
8224 - atomic_t lec_arp_lock_var;
8225 + atomic_t lec_arp_users;
8226 struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
8227 struct atm_vcc *lecd;
8228 struct timer_list lec_arp_timer;
8230 unsigned char *atm_addr, struct sk_buff *data);
8231 void lec_push(struct atm_vcc *vcc, struct sk_buff *skb);
8233 -void atm_lane_init(void);
8234 -void atm_lane_init_ops(struct atm_lane_ops *ops);
8235 #endif /* _LEC_H_ */
8237 diff -urN linux-2.4.20/net/atm/mpc.c linux-2.4.20-atm/net/atm/mpc.c
8238 --- linux-2.4.20/net/atm/mpc.c Wed May 28 01:54:25 2003
8239 +++ linux-2.4.20-atm/net/atm/mpc.c Wed May 28 02:14:40 2003
8244 -#include "resources.h" /* for bind_vcc() */
8245 +#include "resources.h"
8248 * mpc.c: Implementation of MPOA client kernel part
8252 atomic_add(skb->truesize, &entry->shortcut->sk->wmem_alloc);
8253 - ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */
8254 ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
8255 entry->shortcut->send(entry->shortcut, skb);
8256 entry->packets_fwded++;
8259 mpc->eg_ops->put(eg);
8261 + memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
8265 @@ -741,18 +741,10 @@
8268 static struct atm_dev mpc_dev = {
8269 - &mpc_ops, /* device operations */
8270 - NULL, /* PHY operations */
8271 - "mpc", /* device type name */
8272 - 42, /* device index (dummy) */
8273 - NULL, /* VCC table */
8274 - NULL, /* last VCC */
8275 - NULL, /* per-device data */
8276 - NULL, /* private PHY data */
8277 - { 0 }, /* device flags */
8278 - NULL, /* local ATM address */
8279 - { 0 } /* no ESI */
8280 - /* rest of the members will be 0 */
8284 + .lock = SPIN_LOCK_UNLOCKED
8287 int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
8291 mpc->mpoad_vcc = vcc;
8292 - bind_vcc(vcc, &mpc_dev);
8293 + vcc_insert_socket(&mpc_dev, vcc->sk);
8294 set_bit(ATM_VF_META,&vcc->flags);
8295 set_bit(ATM_VF_READY,&vcc->flags);
8298 send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
8301 - MOD_INC_USE_COUNT;
8307 printk("mpoa: (%s) going down\n",
8308 (mpc->dev) ? mpc->dev->name : "<unknown>");
8309 - MOD_DEC_USE_COUNT;
8310 + __MOD_DEC_USE_COUNT(THIS_MODULE);
8316 struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
8317 struct k_message *mesg = (struct k_message*)skb->data;
8318 - atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
8319 + atomic_sub(skb->truesize, &vcc->sk->wmem_alloc);
8322 printk("mpoa: msg_from_mpoad: no mpc found\n");
8323 @@ -1398,11 +1389,17 @@
8327 -void atm_mpoa_init_ops(struct atm_mpoa_ops *ops)
8328 +struct atm_mpoa_ops __atm_mpoa_ops = {
8329 + .mpoad_attach = atm_mpoa_mpoad_attach,
8330 + .vcc_attach = atm_mpoa_vcc_attach,
8331 + .owner = THIS_MODULE
8334 +static int __init atm_mpoa_init(void)
8336 - ops->mpoad_attach = atm_mpoa_mpoad_attach;
8337 - ops->vcc_attach = atm_mpoa_vcc_attach;
8338 + extern struct atm_mpoa_ops *atm_mpoa_ops;
8340 + atm_mpoa_ops = &__atm_mpoa_ops;
8341 #ifdef CONFIG_PROC_FS
8342 if(mpc_proc_init() != 0)
8343 printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
8344 @@ -1412,22 +1409,12 @@
8346 printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
8352 -int init_module(void)
8354 - extern struct atm_mpoa_ops atm_mpoa_ops;
8356 - atm_mpoa_init_ops(&atm_mpoa_ops);
8361 -void cleanup_module(void)
8362 +static void __exit atm_mpoa_cleanup(void)
8364 - extern struct atm_mpoa_ops atm_mpoa_ops;
8365 + extern struct atm_mpoa_ops *atm_mpoa_ops;
8366 struct mpoa_client *mpc, *tmp;
8367 struct atm_mpoa_qos *qos, *nextqos;
8368 struct lec_priv *priv;
8369 @@ -1442,8 +1429,7 @@
8371 del_timer(&mpc_timer);
8372 unregister_netdevice_notifier(&mpoa_notifier);
8373 - atm_mpoa_ops.mpoad_attach = NULL;
8374 - atm_mpoa_ops.vcc_attach = NULL;
8375 + atm_mpoa_ops = NULL;
8379 @@ -1475,8 +1461,9 @@
8386 -#endif /* MODULE */
8388 +module_init(atm_mpoa_init);
8389 +module_exit(atm_mpoa_cleanup);
8391 MODULE_LICENSE("GPL");
8392 diff -urN linux-2.4.20/net/atm/mpc.h linux-2.4.20-atm/net/atm/mpc.h
8393 --- linux-2.4.20/net/atm/mpc.h Mon Dec 11 22:33:43 2000
8394 +++ linux-2.4.20-atm/net/atm/mpc.h Wed May 28 01:58:41 2003
8396 struct atm_mpoa_ops {
8397 int (*mpoad_attach)(struct atm_vcc *vcc, int arg); /* attach mpoa daemon */
8398 int (*vcc_attach)(struct atm_vcc *vcc, long arg); /* attach shortcut vcc */
8399 + struct module *owner;
8402 -/* Boot/module initialization function */
8403 -void atm_mpoa_init(void);
8404 -void atm_mpoa_init_ops(struct atm_mpoa_ops *ops);
8406 /* MPOA QoS operations */
8407 struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos);
8408 diff -urN linux-2.4.20/net/atm/pppoatm.c linux-2.4.20-atm/net/atm/pppoatm.c
8409 --- linux-2.4.20/net/atm/pppoatm.c Wed May 28 01:54:25 2003
8410 +++ linux-2.4.20-atm/net/atm/pppoatm.c Wed May 28 02:15:02 2003
8414 atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->sk->wmem_alloc);
8415 - ATM_SKB(skb)->iovcnt = 0;
8416 ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
8417 DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
8418 pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
8419 diff -urN linux-2.4.20/net/atm/proc.c linux-2.4.20-atm/net/atm/proc.c
8420 --- linux-2.4.20/net/atm/proc.c Wed May 28 01:54:25 2003
8421 +++ linux-2.4.20-atm/net/atm/proc.c Wed May 28 02:46:02 2003
8423 #include "common.h" /* atm_proc_init prototype */
8424 #include "signaling.h" /* to get sigd - ugly too */
8426 -#ifdef CONFIG_ATM_CLIP
8427 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
8428 #include <net/atmclip.h>
8429 -#include "ipcommon.h"
8430 -extern void clip_push(struct atm_vcc *vcc,struct sk_buff *skb);
8431 +extern struct atm_clip_ops *atm_clip_ops; /* in common.c */
8434 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
8436 #include "lec_arpc.h"
8437 -extern struct atm_lane_ops atm_lane_ops; /* in common.c */
8438 +extern struct atm_lane_ops *atm_lane_ops; /* in common.c */
8441 static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
8443 add_stats(buf,"0",&dev->stats.aal0);
8445 add_stats(buf,"5",&dev->stats.aal5);
8446 + sprintf(strchr(buf,0), " %d", atomic_read(&dev->refcnt));
8451 -#ifdef CONFIG_ATM_CLIP
8452 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
8455 static int svc_addr(char *buf,struct sockaddr_atmsvc *addr)
8457 aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr,
8458 class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr,
8459 class_name[vcc->qos.txtp.traffic_class]);
8460 -#ifdef CONFIG_ATM_CLIP
8461 - if (vcc->push == clip_push) {
8462 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
8463 + if (atm_clip_ops && (vcc->push == atm_clip_ops->clip_push)) {
8464 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
8465 struct net_device *dev;
8467 @@ -220,10 +220,11 @@
8469 here += sprintf(here,"%3d",vcc->sk->family);
8471 - here += sprintf(here," %04lx %5d %7d/%7d %7d/%7d\n",vcc->flags.bits,
8472 + here += sprintf(here," %04lx %5d %7d/%7d %7d/%7d %d\n",vcc->flags.bits,
8474 atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf,
8475 - atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf);
8476 + atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf,
8477 + atomic_read(&vcc->sk->refcnt));
8481 @@ -311,26 +312,24 @@
8482 "AAL(TX,err,RX,err,drop) ...\n");
8485 + read_lock(&atm_dev_lock);
8486 list_for_each(p, &atm_devs) {
8487 dev = list_entry(p, struct atm_dev, dev_list);
8490 + read_unlock(&atm_dev_lock);
8494 + read_unlock(&atm_dev_lock);
8499 - * FIXME: it isn't safe to walk the VCC list without turning off interrupts.
8500 - * What is really needed is some lock on the devices. Ditto for ATMARP.
8503 static int atm_pvc_info(loff_t pos,char *buf)
8505 - struct atm_dev *dev;
8506 - struct list_head *p;
8507 struct atm_vcc *vcc;
8512 @@ -338,24 +337,25 @@
8516 - list_for_each(p, &atm_devs) {
8517 - dev = list_entry(p, struct atm_dev, dev_list);
8518 - for (vcc = dev->vccs; vcc; vcc = vcc->next)
8519 - if (vcc->sk->family == PF_ATMPVC &&
8520 - vcc->dev && !left--) {
8521 - pvc_info(vcc,buf);
8522 - return strlen(buf);
8524 + read_lock(&vcc_sklist_lock);
8525 + for(s = vcc_sklist; s; s = s->next) {
8527 + if (vcc->sk->family == PF_ATMPVC &&
8528 + vcc->dev && !left--) {
8529 + pvc_info(vcc,buf);
8530 + read_unlock(&vcc_sklist_lock);
8531 + return strlen(buf);
8534 + read_unlock(&vcc_sklist_lock);
8539 static int atm_vc_info(loff_t pos,char *buf)
8541 - struct atm_dev *dev;
8542 - struct list_head *p;
8543 struct atm_vcc *vcc;
8548 @@ -363,19 +363,16 @@
8549 "Address"," Itf VPI VCI Fam Flags Reply Send buffer"
8552 - list_for_each(p, &atm_devs) {
8553 - dev = list_entry(p, struct atm_dev, dev_list);
8554 - for (vcc = dev->vccs; vcc; vcc = vcc->next)
8557 - return strlen(buf);
8560 - for (vcc = nodev_vccs; vcc; vcc = vcc->next)
8561 + read_lock(&vcc_sklist_lock);
8562 + for(s = vcc_sklist; s; s = s->next) {
8566 + read_unlock(&vcc_sklist_lock);
8570 + read_unlock(&vcc_sklist_lock);
8574 @@ -383,31 +380,28 @@
8576 static int atm_svc_info(loff_t pos,char *buf)
8578 - struct atm_dev *dev;
8579 - struct list_head *p;
8580 struct atm_vcc *vcc;
8585 return sprintf(buf,"Itf VPI VCI State Remote\n");
8587 - list_for_each(p, &atm_devs) {
8588 - dev = list_entry(p, struct atm_dev, dev_list);
8589 - for (vcc = dev->vccs; vcc; vcc = vcc->next)
8590 - if (vcc->sk->family == PF_ATMSVC && !left--) {
8591 - svc_info(vcc,buf);
8592 - return strlen(buf);
8595 - for (vcc = nodev_vccs; vcc; vcc = vcc->next)
8596 + read_lock(&vcc_sklist_lock);
8597 + for(s = vcc_sklist; s; s = s->next) {
8599 if (vcc->sk->family == PF_ATMSVC && !left--) {
8601 + read_unlock(&vcc_sklist_lock);
8605 + read_unlock(&vcc_sklist_lock);
8610 -#ifdef CONFIG_ATM_CLIP
8611 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
8612 static int atm_arp_info(loff_t pos,char *buf)
8614 struct neighbour *n;
8615 @@ -417,28 +411,30 @@
8616 return sprintf(buf,"IPitf TypeEncp Idle IP address "
8619 + if (!clip_tbl_hook)
8622 - read_lock_bh(&clip_tbl.lock);
8623 + read_lock_bh(&clip_tbl_hook->lock);
8624 for (i = 0; i <= NEIGH_HASHMASK; i++)
8625 - for (n = clip_tbl.hash_buckets[i]; n; n = n->next) {
8626 + for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) {
8627 struct atmarp_entry *entry = NEIGH2ENTRY(n);
8628 struct clip_vcc *vcc;
8631 if (--count) continue;
8632 atmarp_info(n->dev,entry,NULL,buf);
8633 - read_unlock_bh(&clip_tbl.lock);
8634 + read_unlock_bh(&clip_tbl_hook->lock);
8637 for (vcc = entry->vccs; vcc;
8639 if (--count) continue;
8640 atmarp_info(n->dev,entry,vcc,buf);
8641 - read_unlock_bh(&clip_tbl.lock);
8642 + read_unlock_bh(&clip_tbl_hook->lock);
8646 - read_unlock_bh(&clip_tbl.lock);
8647 + read_unlock_bh(&clip_tbl_hook->lock);
8651 @@ -456,10 +452,13 @@
8653 "VPI/VCI Recv VPI/VCI\n");
8655 - if (atm_lane_ops.get_lecs == NULL)
8656 + if (!atm_lane_ops)
8657 return 0; /* the lane module is not there yet */
8659 - dev_lec = atm_lane_ops.get_lecs();
8661 + if (!try_inc_mod_count(atm_lane_ops->owner))
8664 + dev_lec = atm_lane_ops->get_lecs();
8667 for(d=0;d<MAX_LEC_ITF;d++) {
8669 e=sprintf(buf,"%s ",
8671 lec_info(entry,buf+e);
8672 + __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
8677 if (--count) continue;
8678 e=sprintf(buf,"%s ",dev_lec[d]->name);
8679 lec_info(entry, buf+e);
8680 + __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
8683 for(entry=priv->lec_no_forward; entry;
8685 if (--count) continue;
8686 e=sprintf(buf,"%s ",dev_lec[d]->name);
8687 lec_info(entry, buf+e);
8688 + __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
8691 for(entry=priv->mcast_fwds; entry;
8692 @@ -494,9 +496,11 @@
8693 if (--count) continue;
8694 e=sprintf(buf,"%s ",dev_lec[d]->name);
8695 lec_info(entry, buf+e);
8696 + __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
8700 + __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
8705 for (num = dev->number; num; num /= 10) digits++;
8706 if (!digits) digits++;
8708 - dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_ATOMIC);
8709 + dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL);
8710 if (!dev->proc_name)
8712 sprintf(dev->proc_name,"%s:%d",dev->type, dev->number);
8713 @@ -599,12 +603,11 @@
8714 name->proc_fops = &proc_spec_atm_operations; \
8715 name->owner = THIS_MODULE
8717 +struct proc_dir_entry *devices = NULL, *pvc = NULL, *svc = NULL;
8718 +struct proc_dir_entry *arp = NULL, *lec = NULL, *vc = NULL;
8720 int __init atm_proc_init(void)
8722 - struct proc_dir_entry *devices = NULL,*pvc = NULL,*svc = NULL;
8723 - struct proc_dir_entry *arp = NULL,*lec = NULL,*vc = NULL;
8725 atm_proc_root = proc_mkdir("net/atm",NULL);
8732 -#ifdef CONFIG_ATM_CLIP
8733 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
8736 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
8737 @@ -629,4 +632,15 @@
8738 if (vc) remove_proc_entry("vc",atm_proc_root);
8739 remove_proc_entry("net/atm",NULL);
8743 +void __exit atm_proc_exit(void)
8745 + if (vc) remove_proc_entry("vc",atm_proc_root);
8746 + if (lec) remove_proc_entry("lec",atm_proc_root);
8747 + if (arp) remove_proc_entry("arp",atm_proc_root);
8748 + if (svc) remove_proc_entry("svc",atm_proc_root);
8749 + if (pvc) remove_proc_entry("pvc",atm_proc_root);
8750 + if (devices) remove_proc_entry("devices",atm_proc_root);
8751 + remove_proc_entry("net/atm",NULL);
8753 diff -urN linux-2.4.20/net/atm/pvc.c linux-2.4.20-atm/net/atm/pvc.c
8754 --- linux-2.4.20/net/atm/pvc.c Thu Apr 12 21:11:39 2001
8755 +++ linux-2.4.20-atm/net/atm/pvc.c Wed May 28 01:58:41 2003
8757 #include <linux/skbuff.h>
8758 #include <linux/bitops.h>
8759 #include <net/sock.h> /* for sock_no_* */
8760 -#ifdef CONFIG_ATM_CLIP
8761 -#include <net/atmclip.h>
8764 #include "resources.h" /* devs and vccs */
8765 #include "common.h" /* common for PVCs and SVCs */
8772 static int pvc_shutdown(struct socket *sock,int how)
8778 -static struct proto_ops SOCKOPS_WRAPPED(pvc_proto_ops) = {
8779 - family: PF_ATMPVC,
8780 +static struct proto_ops pvc_proto_ops = {
8781 + .family = PF_ATMPVC,
8783 - release: atm_release,
8785 - connect: pvc_connect,
8786 - socketpair: sock_no_socketpair,
8787 - accept: sock_no_accept,
8788 - getname: pvc_getname,
8791 - listen: sock_no_listen,
8792 - shutdown: pvc_shutdown,
8793 - setsockopt: atm_setsockopt,
8794 - getsockopt: atm_getsockopt,
8795 - sendmsg: atm_sendmsg,
8796 - recvmsg: atm_recvmsg,
8797 - mmap: sock_no_mmap,
8798 - sendpage: sock_no_sendpage,
8799 + .release = vcc_release,
8801 + .connect = pvc_connect,
8802 + .socketpair = sock_no_socketpair,
8803 + .accept = sock_no_accept,
8804 + .getname = pvc_getname,
8806 + .ioctl = atm_ioctl,
8807 + .listen = sock_no_listen,
8808 + .shutdown = pvc_shutdown,
8809 + .setsockopt = atm_setsockopt,
8810 + .getsockopt = atm_getsockopt,
8811 + .sendmsg = atm_sendmsg,
8812 + .recvmsg = atm_recvmsg,
8813 + .mmap = sock_no_mmap,
8814 + .sendpage = sock_no_sendpage,
8818 -#include <linux/smp_lock.h>
8819 -SOCKOPS_WRAP(pvc_proto, PF_ATMPVC);
8822 static int pvc_create(struct socket *sock,int protocol)
8824 sock->ops = &pvc_proto_ops;
8825 - return atm_create(sock,protocol,PF_ATMPVC);
8826 + return vcc_create(sock,protocol,PF_ATMPVC);
8830 static struct net_proto_family pvc_family_ops = {
8833 - 0, /* no authentication */
8834 - 0, /* no encryption */
8835 - 0 /* no encrypt_net */
8836 + .family = PF_ATMPVC,
8837 + .create = pvc_create,
8841 @@ -124,23 +110,20 @@
8845 -static int __init atmpvc_init(void)
8846 +int __init atmpvc_init(void)
8850 error = sock_register(&pvc_family_ops);
8852 - printk(KERN_ERR "ATMPVC: can't register (%d)",error);
8853 + printk(KERN_ERR "ATMPVC: can't register (%d)", error);
8856 -#ifdef CONFIG_ATM_CLIP
8859 -#ifdef CONFIG_PROC_FS
8860 - error = atm_proc_init();
8861 - if (error) printk("atm_proc_init fails with %d\n",error);
8868 -module_init(atmpvc_init);
8869 +void __exit atmpvc_exit(void)
8871 + sock_unregister(PF_ATMPVC);
8873 diff -urN linux-2.4.20/net/atm/raw.c linux-2.4.20-atm/net/atm/raw.c
8874 --- linux-2.4.20/net/atm/raw.c Wed May 28 01:54:25 2003
8875 +++ linux-2.4.20-atm/net/atm/raw.c Wed May 28 01:58:41 2003
8877 static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
8879 DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->sk->wmem_alloc,skb->truesize);
8880 - atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
8881 + atomic_sub(skb->truesize,&vcc->sk->wmem_alloc);
8882 dev_kfree_skb_any(skb);
8883 wake_up(&vcc->sleep);
8885 diff -urN linux-2.4.20/net/atm/resources.c linux-2.4.20-atm/net/atm/resources.c
8886 --- linux-2.4.20/net/atm/resources.c Wed May 28 01:54:25 2003
8887 +++ linux-2.4.20-atm/net/atm/resources.c Wed May 28 02:38:44 2003
8890 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
8893 #include <linux/config.h>
8894 #include <linux/ctype.h>
8895 #include <linux/string.h>
8896 @@ -11,198 +10,185 @@
8897 #include <linux/module.h>
8898 #include <linux/bitops.h>
8899 #include <net/sock.h> /* for struct sock */
8900 -#include <asm/segment.h> /* for get_fs_long and put_fs_long */
8903 #include "resources.h"
8910 +struct sock *vcc_sklist = NULL;
8911 +rwlock_t vcc_sklist_lock = RW_LOCK_UNLOCKED;
8913 LIST_HEAD(atm_devs);
8914 -struct atm_vcc *nodev_vccs = NULL;
8915 -extern spinlock_t atm_dev_lock;
8916 +rwlock_t atm_dev_lock = RW_LOCK_UNLOCKED;
8919 -static struct atm_dev *alloc_atm_dev(const char *type)
8920 +static struct atm_dev *__alloc_atm_dev(const char *type)
8922 struct atm_dev *dev;
8924 dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
8925 - if (!dev) return NULL;
8926 - memset(dev,0,sizeof(*dev));
8929 + memset(dev, 0, sizeof(*dev));
8931 dev->signal = ATM_PHY_SIG_UNKNOWN;
8932 dev->link_rate = ATM_OC3_PCR;
8933 - list_add_tail(&dev->dev_list, &atm_devs);
8934 + dev->dev_data = NULL;
8935 + memset(&dev->stats, 0, sizeof(dev->stats));
8936 + atomic_set(&dev->refcnt, 0);
8937 + spin_lock_init(&dev->lock);
8943 -static void free_atm_dev(struct atm_dev *dev)
8944 +static void __free_atm_dev(struct atm_dev *dev)
8946 - list_del(&dev->dev_list);
8950 -struct atm_dev *atm_find_dev(int number)
8951 +static struct atm_dev *__atm_dev_lookup(int number)
8953 struct atm_dev *dev;
8954 struct list_head *p;
8956 list_for_each(p, &atm_devs) {
8957 dev = list_entry(p, struct atm_dev, dev_list);
8958 - if (dev->ops && dev->number == number)
8959 + if (dev->ops && dev->number == number) {
8960 + atm_dev_hold(dev);
8967 -struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
8968 - int number,atm_dev_flags_t *flags)
8969 +struct atm_dev *atm_dev_lookup(int number)
8971 - struct atm_dev *dev = NULL;
8972 + struct atm_dev *dev;
8974 + read_lock(&atm_dev_lock);
8975 + dev = __atm_dev_lookup(number);
8976 + read_unlock(&atm_dev_lock);
8980 - spin_lock(&atm_dev_lock);
8981 +void atm_dev_hold(struct atm_dev *dev)
8983 + atomic_inc(&dev->refcnt);
8986 - dev = alloc_atm_dev(type);
8987 +void atm_dev_release(struct atm_dev *dev)
8989 + atomic_dec(&dev->refcnt);
8991 + if ((atomic_read(&dev->refcnt) == 1) &&
8992 + test_bit(ATM_DF_CLOSE,&dev->flags))
8993 + shutdown_atm_dev(dev);
8997 +struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
8998 + int number, atm_dev_flags_t *flags)
9000 + struct atm_dev *dev, *inuse;
9002 + dev = __alloc_atm_dev(type);
9004 printk(KERN_ERR "atm_dev_register: no space for dev %s\n",
9009 + write_lock(&atm_dev_lock);
9011 - if (atm_find_dev(number)) {
9012 - free_atm_dev(dev);
9013 + if ((inuse = __atm_dev_lookup(number))) {
9014 + atm_dev_release(inuse);
9015 + __free_atm_dev(dev);
9016 + write_unlock(&atm_dev_lock);
9019 dev->number = number;
9022 - while (atm_find_dev(dev->number)) dev->number++;
9023 + while ((inuse = __atm_dev_lookup(dev->number))) {
9024 + atm_dev_release(inuse);
9028 - dev->vccs = dev->last = NULL;
9029 - dev->dev_data = NULL;
9035 dev->flags = *flags;
9037 - memset(&dev->flags,0,sizeof(dev->flags));
9038 - memset((void *) &dev->stats,0,sizeof(dev->stats));
9040 + memset(&dev->flags, 0, sizeof(dev->flags));
9041 + atomic_inc(&dev->refcnt);
9042 + list_add_tail(&dev->dev_list, &atm_devs);
9043 + write_unlock(&atm_dev_lock);
9046 #ifdef CONFIG_PROC_FS
9047 - if (ops->proc_read)
9048 + if (ops->proc_read) {
9049 if (atm_proc_dev_register(dev) < 0) {
9050 printk(KERN_ERR "atm_dev_register: "
9051 - "atm_proc_dev_register failed for dev %s\n",type);
9052 - free_atm_dev(dev);
9054 + "atm_proc_dev_register failed for dev %s\n",
9056 + write_lock(&atm_dev_lock);
9057 + list_del(&dev->dev_list);
9058 + write_unlock(&atm_dev_lock);
9059 + __free_atm_dev(dev);
9066 - spin_unlock(&atm_dev_lock);
9071 void atm_dev_deregister(struct atm_dev *dev)
9073 + unsigned long warning_time;
9075 #ifdef CONFIG_PROC_FS
9076 - if (dev->ops->proc_read) atm_proc_dev_deregister(dev);
9077 + if (dev->ops->proc_read)
9078 + atm_proc_dev_deregister(dev);
9080 - spin_lock(&atm_dev_lock);
9081 - free_atm_dev(dev);
9082 - spin_unlock(&atm_dev_lock);
9085 -void shutdown_atm_dev(struct atm_dev *dev)
9088 - set_bit(ATM_DF_CLOSE,&dev->flags);
9091 - if (dev->ops->dev_close) dev->ops->dev_close(dev);
9092 - atm_dev_deregister(dev);
9096 -/* Handler for sk->destruct, invoked by sk_free() */
9097 -static void atm_free_sock(struct sock *sk)
9099 - kfree(sk->protinfo.af_atm);
9102 -struct sock *alloc_atm_vcc_sk(int family)
9105 - struct atm_vcc *vcc;
9107 - sk = sk_alloc(family, GFP_KERNEL, 1);
9108 - if (!sk) return NULL;
9109 - vcc = sk->protinfo.af_atm = kmalloc(sizeof(*vcc),GFP_KERNEL);
9114 - sock_init_data(NULL,sk);
9115 - sk->destruct = atm_free_sock;
9116 - memset(vcc,0,sizeof(*vcc));
9118 - if (nodev_vccs) nodev_vccs->prev = vcc;
9120 - vcc->next = nodev_vccs;
9126 -static void unlink_vcc(struct atm_vcc *vcc,struct atm_dev *hold_dev)
9128 - if (vcc->prev) vcc->prev->next = vcc->next;
9129 - else if (vcc->dev) vcc->dev->vccs = vcc->next;
9130 - else nodev_vccs = vcc->next;
9131 - if (vcc->next) vcc->next->prev = vcc->prev;
9132 - else if (vcc->dev) vcc->dev->last = vcc->prev;
9133 - if (vcc->dev && vcc->dev != hold_dev && !vcc->dev->vccs &&
9134 - test_bit(ATM_DF_CLOSE,&vcc->dev->flags))
9135 - shutdown_atm_dev(vcc->dev);
9137 + write_lock(&atm_dev_lock);
9138 + list_del(&dev->dev_list);
9139 + write_unlock(&atm_dev_lock);
9141 + warning_time = jiffies;
9142 + while (atomic_read(&dev->refcnt) != 1) {
9143 + current->state = TASK_INTERRUPTIBLE;
9144 + schedule_timeout(HZ / 4);
9145 + current->state = TASK_RUNNING;
9146 + if ((jiffies - warning_time) > 10 * HZ) {
9147 + printk(KERN_EMERG "atm_dev_deregister: waiting for "
9148 + "dev %d to become free. Usage count = %d\n",
9149 + dev->number, atomic_read(&dev->refcnt));
9150 + warning_time = jiffies;
9154 -void free_atm_vcc_sk(struct sock *sk)
9156 - unlink_vcc(sk->protinfo.af_atm,NULL);
9158 + __free_atm_dev(dev);
9162 -void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev)
9163 +void shutdown_atm_dev(struct atm_dev *dev)
9165 - unlink_vcc(vcc,dev);
9169 - vcc->prev = dev->last;
9170 - if (dev->vccs) dev->last->next = vcc;
9171 - else dev->vccs = vcc;
9175 - if (nodev_vccs) nodev_vccs->prev = vcc;
9176 - vcc->next = nodev_vccs;
9179 + if (atomic_read(&dev->refcnt) > 1) {
9180 + set_bit(ATM_DF_CLOSE, &dev->flags);
9183 + if (dev->ops->dev_close)
9184 + dev->ops->dev_close(dev);
9185 + atm_dev_deregister(dev);
9189 EXPORT_SYMBOL(atm_dev_register);
9190 EXPORT_SYMBOL(atm_dev_deregister);
9191 -EXPORT_SYMBOL(atm_find_dev);
9192 +EXPORT_SYMBOL(atm_dev_lookup);
9193 +EXPORT_SYMBOL(atm_dev_hold);
9194 +EXPORT_SYMBOL(atm_dev_release);
9195 EXPORT_SYMBOL(shutdown_atm_dev);
9196 -EXPORT_SYMBOL(bind_vcc);
9197 +EXPORT_SYMBOL(vcc_sklist);
9198 +EXPORT_SYMBOL(vcc_sklist_lock);
9199 diff -urN linux-2.4.20/net/atm/resources.h linux-2.4.20-atm/net/atm/resources.h
9200 --- linux-2.4.20/net/atm/resources.h Wed May 28 01:54:25 2003
9201 +++ linux-2.4.20-atm/net/atm/resources.h Wed May 28 02:23:53 2003
9205 extern struct list_head atm_devs;
9206 -extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */
9209 -struct sock *alloc_atm_vcc_sk(int family);
9210 -void free_atm_vcc_sk(struct sock *sk);
9211 +extern rwlock_t atm_dev_lock;
9214 #ifdef CONFIG_PROC_FS
9215 diff -urN linux-2.4.20/net/atm/signaling.c linux-2.4.20-atm/net/atm/signaling.c
9216 --- linux-2.4.20/net/atm/signaling.c Wed May 28 01:54:25 2003
9217 +++ linux-2.4.20-atm/net/atm/signaling.c Wed May 28 02:28:19 2003
9219 struct atm_vcc *sigd = NULL;
9220 static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
9222 -extern spinlock_t atm_dev_lock;
9224 static void sigd_put_skb(struct sk_buff *skb)
9227 struct atm_vcc *session_vcc;
9229 msg = (struct atmsvc_msg *) skb->data;
9230 - atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
9231 + atomic_sub(skb->truesize,&vcc->sk->wmem_alloc);
9232 DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
9233 (unsigned long) msg->vcc);
9234 vcc = *(struct atm_vcc **) &msg->vcc;
9237 session_vcc = vcc->session ? vcc->session : vcc;
9238 if (session_vcc->vpi || session_vcc->vci) break;
9239 - session_vcc->itf = msg->pvc.sap_addr.itf;
9240 + session_vcc->sk->bound_dev_if = msg->pvc.sap_addr.itf;
9241 session_vcc->vpi = msg->pvc.sap_addr.vpi;
9242 session_vcc->vci = msg->pvc.sap_addr.vci;
9243 if (session_vcc->vpi || session_vcc->vci)
9244 @@ -129,12 +128,12 @@
9246 vcc = *(struct atm_vcc **) &msg->listen_vcc;
9247 DPRINTK("as_indicate!!!\n");
9248 - if (!vcc->backlog_quota) {
9249 + if (vcc->sk->ack_backlog == vcc->sk->max_ack_backlog) {
9250 sigd_enq(0,as_reject,vcc,NULL,NULL);
9253 - vcc->backlog_quota--;
9254 - skb_queue_tail(&vcc->listenq,skb);
9255 + vcc->sk->ack_backlog++;
9256 + skb_queue_tail(&vcc->sk->receive_queue,skb);
9257 if (vcc->callback) {
9258 DPRINTK("waking vcc->sleep 0x%p\n",
9260 @@ -195,16 +194,13 @@
9264 -static void purge_vccs(struct atm_vcc *vcc)
9265 +static void purge_vcc(struct atm_vcc *vcc)
9268 - if (vcc->sk->family == PF_ATMSVC &&
9269 - !test_bit(ATM_VF_META,&vcc->flags)) {
9270 - set_bit(ATM_VF_RELEASED,&vcc->flags);
9271 - vcc->reply = -EUNATCH;
9272 - wake_up(&vcc->sleep);
9275 + if (vcc->sk->family == PF_ATMSVC &&
9276 + !test_bit(ATM_VF_META,&vcc->flags)) {
9277 + set_bit(ATM_VF_RELEASED,&vcc->flags);
9278 + vcc->reply = -EUNATCH;
9279 + wake_up(&vcc->sleep);
9283 @@ -213,39 +209,42 @@
9285 struct atm_dev *dev;
9286 struct list_head *p;
9289 DPRINTK("sigd_close\n");
9291 if (skb_peek(&vcc->sk->receive_queue))
9292 printk(KERN_ERR "sigd_close: closing with requests pending\n");
9293 skb_queue_purge(&vcc->sk->receive_queue);
9294 - purge_vccs(nodev_vccs);
9296 - spin_lock (&atm_dev_lock);
9297 + read_lock(&atm_dev_lock);
9298 list_for_each(p, &atm_devs) {
9299 dev = list_entry(p, struct atm_dev, dev_list);
9300 - purge_vccs(dev->vccs);
9302 + read_lock(&vcc_sklist_lock);
9303 + for(s = vcc_sklist; s; s = s->next) {
9304 + struct atm_vcc *vcc = atm_sk(s);
9306 + if (vcc->dev == dev) purge_vcc(vcc);
9308 + read_unlock(&vcc_sklist_lock);
9310 - spin_unlock (&atm_dev_lock);
9311 + read_unlock(&atm_dev_lock);
9315 static struct atmdev_ops sigd_dev_ops = {
9316 - close: sigd_close,
9318 + .close = sigd_close,
9323 static struct atm_dev sigd_dev = {
9325 - NULL, /* no PHY */
9327 - 999, /* dummy device number */
9328 - NULL,NULL, /* pretend not to have any VCCs */
9329 - NULL,NULL, /* no data */
9330 - { 0 }, /* no flags */
9331 - NULL, /* no local address */
9332 - { 0 } /* no ESI, no statistics */
9333 + .ops = &sigd_dev_ops,
9337 + .lock = SPIN_LOCK_UNLOCKED
9342 if (sigd) return -EADDRINUSE;
9343 DPRINTK("sigd_attach\n");
9345 - bind_vcc(vcc,&sigd_dev);
9346 + vcc_insert_socket(&sigd_dev, vcc->sk);
9347 set_bit(ATM_VF_META,&vcc->flags);
9348 set_bit(ATM_VF_READY,&vcc->flags);
9349 wake_up(&sigd_sleep);
9350 diff -urN linux-2.4.20/net/atm/svc.c linux-2.4.20-atm/net/atm/svc.c
9351 --- linux-2.4.20/net/atm/svc.c Thu Apr 12 21:11:39 2001
9352 +++ linux-2.4.20-atm/net/atm/svc.c Wed May 28 01:58:41 2003
9355 DPRINTK("svc_disconnect %p\n",vcc);
9356 if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
9357 - sigd_enq(vcc,as_close,NULL,NULL,NULL);
9358 add_wait_queue(&vcc->sleep,&wait);
9359 + sigd_enq(vcc,as_close,NULL,NULL,NULL);
9360 while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
9361 set_current_state(TASK_UNINTERRUPTIBLE);
9365 /* beware - socket is still in use by atmsigd until the last
9366 as_indicate has been answered */
9367 - while ((skb = skb_dequeue(&vcc->listenq))) {
9368 + while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
9369 DPRINTK("LISTEN REL\n");
9370 sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
9373 static int svc_release(struct socket *sock)
9375 struct atm_vcc *vcc;
9376 + struct sock *sk = sock->sk;
9378 - if (!sock->sk) return 0;
9379 - vcc = ATM_SD(sock);
9380 - DPRINTK("svc_release %p\n",vcc);
9381 - clear_bit(ATM_VF_READY,&vcc->flags);
9382 - atm_release_vcc_sk(sock->sk,0);
9383 - svc_disconnect(vcc);
9384 - /* VCC pointer is used as a reference, so we must not free it
9385 - (thereby subjecting it to re-use) before all pending connections
9387 - free_atm_vcc_sk(sock->sk);
9390 + DPRINTK("svc_release %p\n",vcc);
9392 + vcc_release(sock);
9393 + svc_disconnect(vcc);
9394 + /* VCC pointer is used as a reference, so we must not free it
9395 + (thereby subjecting it to re-use) before all pending
9396 + connections are closed */
9403 if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD;
9405 vcc->reply = WAITING;
9406 - sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local);
9407 add_wait_queue(&vcc->sleep,&wait);
9408 + sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local);
9409 while (vcc->reply == WAITING && sigd) {
9410 set_current_state(TASK_UNINTERRUPTIBLE);
9412 @@ -169,13 +171,14 @@
9413 if (!vcc->qos.txtp.traffic_class &&
9414 !vcc->qos.rxtp.traffic_class) return -EINVAL;
9415 vcc->remote = *addr;
9416 + add_wait_queue(&vcc->sleep,&wait);
9417 vcc->reply = WAITING;
9418 sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote);
9419 if (flags & O_NONBLOCK) {
9420 + remove_wait_queue(&vcc->sleep,&wait);
9421 sock->state = SS_CONNECTING;
9422 return -EINPROGRESS;
9424 - add_wait_queue(&vcc->sleep,&wait);
9426 while (vcc->reply == WAITING && sigd) {
9427 set_current_state(TASK_INTERRUPTIBLE);
9432 - if (!(error = atm_connect(sock,vcc->itf,vcc->vpi,vcc->vci)))
9433 + if (!(error = atm_connect(sock,vcc->sk->bound_dev_if,vcc->vpi,vcc->vci)))
9434 sock->state = SS_CONNECTED;
9435 else (void) svc_disconnect(vcc);
9438 DPRINTK("svc_listen %p\n",vcc);
9439 /* let server handle listen on unbound sockets */
9440 if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL;
9441 + add_wait_queue(&vcc->sleep,&wait);
9442 vcc->reply = WAITING;
9443 sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local);
9444 - add_wait_queue(&vcc->sleep,&wait);
9445 while (vcc->reply == WAITING && sigd) {
9446 set_current_state(TASK_UNINTERRUPTIBLE);
9449 remove_wait_queue(&vcc->sleep,&wait);
9450 if (!sigd) return -EUNATCH;
9451 set_bit(ATM_VF_LISTEN,&vcc->flags);
9452 - vcc->backlog_quota = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
9453 + vcc->sk->max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
9458 DECLARE_WAITQUEUE(wait,current);
9460 add_wait_queue(&old_vcc->sleep,&wait);
9461 - while (!(skb = skb_dequeue(&old_vcc->listenq)) && sigd) {
9462 + while (!(skb = skb_dequeue(&old_vcc->sk->receive_queue)) && sigd) {
9463 if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
9464 if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
9465 error = old_vcc->reply;
9466 @@ -306,16 +309,16 @@
9467 error = atm_connect(newsock,msg->pvc.sap_addr.itf,
9468 msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci);
9470 - old_vcc->backlog_quota++;
9471 + old_vcc->sk->ack_backlog--;
9473 sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
9474 &old_vcc->qos,error);
9475 return error == -EAGAIN ? -EBUSY : error;
9477 /* wait should be short, so we ignore the non-blocking flag */
9478 + add_wait_queue(&new_vcc->sleep,&wait);
9479 new_vcc->reply = WAITING;
9480 sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);
9481 - add_wait_queue(&new_vcc->sleep,&wait);
9482 while (new_vcc->reply == WAITING && sigd) {
9483 set_current_state(TASK_UNINTERRUPTIBLE);
9487 DECLARE_WAITQUEUE(wait,current);
9489 + add_wait_queue(&vcc->sleep,&wait);
9490 vcc->reply = WAITING;
9491 sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);
9492 - add_wait_queue(&vcc->sleep,&wait);
9493 while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags)
9495 set_current_state(TASK_UNINTERRUPTIBLE);
9496 @@ -390,37 +393,34 @@
9500 -static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = {
9501 - family: PF_ATMSVC,
9502 +static struct proto_ops svc_proto_ops = {
9503 + .family = PF_ATMSVC,
9505 - release: svc_release,
9507 - connect: svc_connect,
9508 - socketpair: sock_no_socketpair,
9509 - accept: svc_accept,
9510 - getname: svc_getname,
9513 - listen: svc_listen,
9514 - shutdown: svc_shutdown,
9515 - setsockopt: svc_setsockopt,
9516 - getsockopt: svc_getsockopt,
9517 - sendmsg: atm_sendmsg,
9518 - recvmsg: atm_recvmsg,
9519 - mmap: sock_no_mmap,
9520 - sendpage: sock_no_sendpage,
9521 + .release = svc_release,
9523 + .connect = svc_connect,
9524 + .socketpair = sock_no_socketpair,
9525 + .accept = svc_accept,
9526 + .getname = svc_getname,
9528 + .ioctl = atm_ioctl,
9529 + .listen = svc_listen,
9530 + .shutdown = svc_shutdown,
9531 + .setsockopt = svc_setsockopt,
9532 + .getsockopt = svc_getsockopt,
9533 + .sendmsg = atm_sendmsg,
9534 + .recvmsg = atm_recvmsg,
9535 + .mmap = sock_no_mmap,
9536 + .sendpage = sock_no_sendpage,
9540 -#include <linux/smp_lock.h>
9541 -SOCKOPS_WRAP(svc_proto, PF_ATMSVC);
9543 static int svc_create(struct socket *sock,int protocol)
9547 sock->ops = &svc_proto_ops;
9548 - error = atm_create(sock,protocol,AF_ATMSVC);
9549 + error = vcc_create(sock,protocol,AF_ATMSVC);
9550 if (error) return error;
9551 ATM_SD(sock)->callback = svc_callback;
9552 ATM_SD(sock)->local.sas_family = AF_ATMSVC;
9553 @@ -430,11 +430,8 @@
9556 static struct net_proto_family svc_family_ops = {
9559 - 0, /* no authentication */
9560 - 0, /* no encryption */
9561 - 0 /* no encrypt_net */
9562 + .family = PF_ATMSVC,
9563 + .create = svc_create,
9567 @@ -442,13 +439,19 @@
9568 * Initialize the ATM SVC protocol family
9571 -static int __init atmsvc_init(void)
9572 +int __init atmsvc_init(void)
9574 - if (sock_register(&svc_family_ops) < 0) {
9575 - printk(KERN_ERR "ATMSVC: can't register");
9578 + error = sock_register(&svc_family_ops);
9580 + printk(KERN_ERR "ATMSVC: can't register (%d)\n", error);
9586 -module_init(atmsvc_init);
9587 +void __exit atmsvc_exit(void)
9589 + sock_unregister(PF_ATMSVC);
9591 diff -urN linux-2.4.20/net/ipv4/arp.c linux-2.4.20-atm/net/ipv4/arp.c
9592 --- linux-2.4.20/net/ipv4/arp.c Fri Nov 29 00:53:15 2002
9593 +++ linux-2.4.20-atm/net/ipv4/arp.c Wed May 28 01:58:41 2003
9595 #include <net/netrom.h>
9598 -#ifdef CONFIG_ATM_CLIP
9599 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
9600 #include <net/atmclip.h>
9601 +struct neigh_table *clip_tbl_hook = NULL;
9604 #include <asm/system.h>
9606 if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
9608 n = __neigh_lookup_errno(
9609 -#ifdef CONFIG_ATM_CLIP
9610 - dev->type == ARPHRD_ATM ? &clip_tbl :
9611 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
9612 + dev->type == ARPHRD_ATM ? clip_tbl_hook :
9614 &arp_tbl, &nexthop, dev);
9616 diff -urN linux-2.4.20/net/netsyms.c linux-2.4.20-atm/net/netsyms.c
9617 --- linux-2.4.20/net/netsyms.c Wed May 28 01:54:31 2003
9618 +++ linux-2.4.20-atm/net/netsyms.c Wed May 28 01:58:41 2003
9620 #include <linux/ip.h>
9621 #include <net/protocol.h>
9622 #include <net/arp.h>
9623 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
9624 +#include <net/atmclip.h>
9627 #include <net/udp.h>
9628 #include <net/tcp.h>
9630 EXPORT_SYMBOL(put_cmsg);
9631 EXPORT_SYMBOL(sock_kmalloc);
9632 EXPORT_SYMBOL(sock_kfree_s);
9633 +EXPORT_SYMBOL(sockfd_lookup);
9635 #ifdef CONFIG_FILTER
9636 EXPORT_SYMBOL(sk_run_filter);
9638 EXPORT_SYMBOL(ip_rcv);
9639 EXPORT_SYMBOL(arp_rcv);
9640 EXPORT_SYMBOL(arp_tbl);
9641 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
9642 +EXPORT_SYMBOL(clip_tbl_hook);
9644 EXPORT_SYMBOL(arp_find);
9646 #endif /* CONFIG_INET */
9647 diff -urN linux-2.4.20/net/sched/Config.in linux-2.4.20-atm/net/sched/Config.in
9648 --- linux-2.4.20/net/sched/Config.in Fri Nov 29 00:53:16 2002
9649 +++ linux-2.4.20-atm/net/sched/Config.in Wed May 28 01:58:41 2003
9651 tristate ' CSZ packet scheduler' CONFIG_NET_SCH_CSZ
9652 #tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
9653 #tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
9654 -if [ "$CONFIG_ATM" = "y" ]; then
9655 - bool ' ATM pseudo-scheduler' CONFIG_NET_SCH_ATM
9656 +if [ "$CONFIG_ATM" != "n" ]; then
9657 + dep_tristate ' ATM pseudo-scheduler' CONFIG_NET_SCH_ATM $CONFIG_ATM
9659 tristate ' The simplest PRIO pseudoscheduler' CONFIG_NET_SCH_PRIO
9660 tristate ' RED queue' CONFIG_NET_SCH_RED
9661 diff -urN linux-2.4.20/net/sched/sch_atm.c linux-2.4.20-atm/net/sched/sch_atm.c
9662 --- linux-2.4.20/net/sched/sch_atm.c Wed May 28 01:54:31 2003
9663 +++ linux-2.4.20-atm/net/sched/sch_atm.c Wed May 28 01:59:30 2003
9665 memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
9667 atomic_add(skb->truesize,&flow->vcc->sk->wmem_alloc);
9668 - ATM_SKB(skb)->iovcnt = 0;
9669 /* atm.atm_options are already set by atm_tc_enqueue */
9670 (void) flow->vcc->send(flow->vcc,skb);