]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.21-atm_diffs.patch
- argh, back (used by kernel24.spec@HEAD)
[packages/kernel.git] / linux-2.4.21-atm_diffs.patch
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
4 @@ -355,7 +355,7 @@
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
11      fi
12    fi
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
16 @@ -199,7 +199,7 @@
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
23        fi
24    fi
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
28 @@ -399,7 +399,7 @@
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
35        fi
36     fi
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
40 @@ -136,7 +136,7 @@
41  
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
47        fi
48     fi
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
52 @@ -297,7 +297,7 @@
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
59      fi
60    fi
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
64 @@ -136,7 +136,7 @@
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
71        fi
72     fi
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
76 @@ -259,7 +259,7 @@
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
83        fi
84     fi
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
88 @@ -209,7 +209,7 @@
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
95           fi
96         fi
97 @@ -235,7 +235,7 @@
98  #      if [ "$CONFIG_FDDI" = "y" ]; then
99  #      fi
100  
101 -      if [ "$CONFIG_ATM" = "y" ]; then
102 +      if [ "$CONFIG_ATM" != "n" ]; then
103          source drivers/atm/Config.in
104        fi
105     fi
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
109 @@ -234,7 +234,7 @@
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
116        fi
117     fi
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
121 @@ -172,10 +172,9 @@
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
128 -#      fi
129 +      if [ "$CONFIG_ATM" != "n" ]; then
130 +         source drivers/atm/Config.in
131 +      fi
132     fi
133     endmenu
134  fi
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
138 @@ -4,11 +4,11 @@
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
144  fi
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
153 @@ -23,8 +23,8 @@
154          bool '    Enable 2W RX bursts (optional)' CONFIG_ATM_ENI_BURST_RX_2W
155        fi
156     fi
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
164 @@ -35,32 +35,32 @@
165  #   if [ "$CONFIG_ATM_TNETA1570" = "y" ]; then
166  #      bool '  Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n
167  #   fi
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
173     fi
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
180     fi
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
185     fi
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
190     fi
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
194 -    fi
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
198 +   fi
199  fi
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
206 @@ -90,6 +90,10 @@
207      else
208        define_tristate CONFIG_ATM_FORE200E m
209      fi
210 +  fi
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
214    fi
215  fi
216  endmenu
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
220 @@ -32,6 +32,10 @@
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
227 +endif
228  
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 @@
235    }
236  #endif
237    
238 -  // deal with possibly wildcarded VCs
239 -  error = atm_find_ci (atm_vcc, &vpi, &vci);
240 -  if (error) {
241 -    PRINTD (DBG_WARN|DBG_VCC, "atm_find_ci failed!");
242 -    return error;
243 -  }
244 -  PRINTD (DBG_VCC, "atm_find_ci gives %x %x", vpi, vci);
245 -  
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
252 @@ -4,6 +4,7 @@
253  
254  
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>
260 @@ -125,8 +125,6 @@
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;
268         msg.qos = vcc->qos;
269 @@ -155,6 +153,7 @@
270  {
271         struct atm_cirange ci;
272         struct atm_vcc *vcc;
273 +       struct sock *s;
274  
275         if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
276         if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
277 @@ -162,9 +161,17 @@
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) {
284 +               vcc = atm_sk(s);
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);
290 +                       return -EBUSY;
291 +               }
292 +       }
293 +       read_unlock(&vcc_sklist_lock);
294         dev->ci_range = ci;
295         return 0;
296  }
297 @@ -230,6 +237,7 @@
298         struct atm_dev *atmtcp_dev;
299         struct atmtcp_dev_data *dev_data;
300         struct atm_vcc *walk;
301 +       struct sock *s;
302  
303         atmtcp_dev = (struct atm_dev *) vcc->dev_data;
304         dev_data = PRIV(atmtcp_dev);
305 @@ -239,8 +247,12 @@
306         kfree(dev_data);
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) {
313 +               walk = atm_sk(s);
314 +               if (walk->dev == atmtcp_dev) wake_up(&walk->sleep);
315 +       }
316 +       read_unlock(&vcc_sklist_lock);
317  }
318  
319  
320 @@ -248,7 +260,8 @@
321  {
322         struct atm_dev *dev;
323         struct atmtcp_hdr *hdr;
324 -       struct atm_vcc *out_vcc;
325 +       struct atm_vcc *out_vcc = NULL;
326 +       struct sock *s;
327         struct sk_buff *new_skb;
328         int result = 0;
329  
330 @@ -260,11 +273,17 @@
331                     (struct atmtcp_control *) skb->data);
332                 goto done;
333         }
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)
342                         break;
343 +               out_vcc = NULL;
344 +       }
345 +       read_unlock(&vcc_sklist_lock);
346         if (!out_vcc) {
347                 atomic_inc(&vcc->stats->tx_err);
348                 goto done;
349 @@ -315,15 +334,10 @@
350  
351  
352  static struct atm_dev atmtcp_control_dev = {
353 -       &atmtcp_c_dev_ops,
354 -       NULL,           /* no PHY */
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,
363 +       .type           = "atmtcp",
364 +       .number         = 999,
365 +       .lock           = SPIN_LOCK_UNLOCKED
366  };
367  
368  
369 @@ -356,9 +370,12 @@
370         struct atm_dev *dev;
371  
372         dev = NULL;
373 -       if (itf != -1) dev = atm_find_dev(itf);
374 +       if (itf != -1) dev = atm_dev_lookup(itf);
375         if (dev) {
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;
380 +               }
381                 if (PRIV(dev)->vcc) return -EBUSY;
382         }
383         else {
384 @@ -368,7 +385,7 @@
385                 if (error) return error;
386         }
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);
392         vcc->dev_data = dev;
393 @@ -389,44 +406,42 @@
394         struct atm_dev *dev;
395         struct atmtcp_dev_data *dev_data;
396  
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;
404 +       }
405         dev_data = PRIV(dev);
406         if (!dev_data->persist) return 0;
407         dev_data->persist = 0;
408         if (PRIV(dev)->vcc) return 0;
409         kfree(dev_data);
410 +       atm_dev_release(dev);
411         shutdown_atm_dev(dev);
412         return 0;
413  }
414  
415  
416 -#ifdef MODULE
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 */
421 +};
422 +
423  
424 -int init_module(void)
425 +static int __init atmtcp_init(void)
426  {
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;
431         return 0;
432  }
433  
434 -
435 -void cleanup_module(void)
436 +static void __exit atmtcp_cleanup(void)
437  {
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;
442  }
443  
444 -MODULE_LICENSE("GPL");
445 -#else
446 +module_init(atmtcp_init);
447 +module_exit(atmtcp_cleanup);
448  
449 -struct atm_tcp_ops atm_tcp_ops = {
450 -       atmtcp_attach,                  /* attach */
451 -       atmtcp_create_persistent,       /* create_persistent */
452 -       atmtcp_remove_persistent        /* remove_persistent */
453 -};
454 -
455 -#endif
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
460 @@ -829,6 +829,7 @@
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);
464 +       vcc_hold(vcc);
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 |
468 @@ -858,7 +859,11 @@
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;
474 +               barrier();
475 +               tasklet_enable(&eni_dev->task);
476 +               vcc_put(vcc);
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
483                          mis-alignment fix */
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) |
495              MID_DT_JK;
496         j++;
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);
501         else {
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);
510         }
511         if (skb->len & 3)
512                 put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
513 @@ -1880,43 +1885,6 @@
514  }
515  
516  
517 -static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci)
518 -{
519 -       struct atm_vcc *walk;
520 -
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])
526 -                               continue;
527 -                       if (vcc->qos.txtp.traffic_class != ATM_NONE) {
528 -                               for (walk = vcc->dev->vccs; walk;
529 -                                   walk = walk->next)
530 -                                       if (test_bit(ATM_VF_ADDR,&walk->flags)
531 -                                           && walk->vci == *vci &&
532 -                                           walk->qos.txtp.traffic_class !=
533 -                                           ATM_NONE)
534 -                                               break;
535 -                               if (walk) continue;
536 -                       }
537 -                       break;
538 -               }
539 -               return *vci == NR_VCI ? -EADDRINUSE : 0;
540 -       }
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;
550 -       return 0;
551 -}
552 -
553 -
554  static int eni_open(struct atm_vcc *vcc,short vpi,int vci)
555  {
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;
563         vcc->vpi = vpi;
564         vcc->vci = vci;
565         if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
566 @@ -2122,8 +2088,8 @@
567  {
568         static const char *signal[] = { "LOST","unknown","okay" };
569         struct eni_dev *eni_dev = ENI_DEV(dev);
570 -       struct atm_vcc *vcc;
571         int left,i;
572 +       struct sock *s;
573  
574         left = *pos;
575         if (!left)
576 @@ -2192,10 +2158,13 @@
577                 return sprintf(page,"%10sbacklog %u packets\n","",
578                     skb_queue_len(&tx->backlog));
579         }
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);
585                 int length;
586  
587 +               if (vcc->dev != dev) continue;
588                 if (--left) continue;
589                 length = sprintf(page,"vcc %4d: ",vcc->vci);
590                 if (eni_vcc->rx) {
591 @@ -2210,8 +2179,10 @@
592                         length += sprintf(page+length,"tx[%d], txing %d bytes",
593                             eni_vcc->tx->index,eni_vcc->txing);
594                 page[length] = '\n';
595 +               spin_unlock(&dev->lock);
596                 return length+1;
597         }
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
605 @@ -874,12 +874,6 @@
606         fs_dprintk (FS_DEBUG_OPEN, "fs: open on dev: %p, vcc at %p\n", 
607                     dev, atm_vcc);
608  
609 -       error = atm_find_ci(atm_vcc, &vpi, &vci);
610 -       if (error) {
611 -               fs_dprintk (FS_DEBUG_OPEN, "fs: find_ci failed.\n");
612 -               return error;
613 -       }
614 -
615         atm_vcc->vpi = vpi;
616         atm_vcc->vci = vci;
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
621 @@ -65,7 +65,7 @@
622  #define FORE200E_52BYTE_AAL0_SDU
623  #endif
624  
625 -#define FORE200E_VERSION "0.2d"
626 +#define FORE200E_VERSION "0.2f"
627  
628  
629  #define FORE200E         "fore200e: "
630 @@ -1077,15 +1077,7 @@
631  static struct atm_vcc* 
632  fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
633  {
634 -    struct atm_vcc* vcc;
635 -
636 -    for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {
637 -
638 -       if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci)
639 -           break;
640 -    }
641 -    
642 -    return vcc;
643 +    return vcc_lookup(fore200e->atm_dev, rpd->atm_header.vpi, rpd->atm_header.vci);
644  }
645  
646  
647 @@ -1132,6 +1124,7 @@
648         
649         printk(FORE200E "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
650         atomic_inc(&vcc->stats->rx_drop);
651 +       vcc_put(vcc);
652         return;
653      } 
654  
655 @@ -1166,14 +1159,16 @@
656      if (atm_charge(vcc, skb->truesize) == 0) {
657  
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);
661  
662         dev_kfree_skb_irq(skb);
663 +       vcc_put(vcc);
664         return;
665      }
666  
667      vcc->push(vcc, skb);
668      atomic_inc(&vcc->stats->rx);
669 +    vcc_put(vcc);
670  }
671  
672  
673 @@ -1215,8 +1210,8 @@
674             fore200e_push_rpd(fore200e, entry->rpd);
675         }
676         else {
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); 
681         }
682  
683         fore200e_collect_rpd(fore200e, entry->rpd);
684 @@ -1281,7 +1276,7 @@
685  #endif
686      
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");
690  
691      return scheme;
692  }
693 @@ -1351,39 +1346,6 @@
694  }
695  
696  
697 -static int
698 -fore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci)
699 -{
700 -    struct atm_vcc* walk;
701 -
702 -    /* find a free VPI */
703 -    if (*vpi == ATM_VPI_ANY) {
704 -
705 -       for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) {
706 -
707 -           if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
708 -               (*vpi)++;
709 -               walk = vcc->dev->vccs;
710 -           }
711 -       }
712 -    }
713 -
714 -    /* find a free VCI */
715 -    if (*vci == ATM_VCI_ANY) {
716 -       
717 -       for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk; walk = walk->next) {
718 -
719 -           if ((walk->vpi = *vpi) && (walk->vci == *vci)) {
720 -               *vci = walk->vci + 1;
721 -               walk = vcc->dev->vccs;
722 -           }
723 -       }
724 -    }
725 -
726 -    return 0;
727 -}
728 -
729 -
730  #define FORE200E_MAX_BACK2BACK_CELLS 255    /* XXX depends on CDVT */
731  
732  static void
733 @@ -1408,9 +1370,6 @@
734      struct fore200e*     fore200e = FORE200E_DEV(vcc->dev);
735      struct fore200e_vcc* fore200e_vcc;
736      
737 -    /* find a free VPI/VCI */
738 -    fore200e_walk_vccs(vcc, &vpi, &vci);
739 -
740      vcc->vpi = vpi;
741      vcc->vci = vci;
742  
743 @@ -1419,11 +1378,11 @@
744         return 0;
745  
746      set_bit(ATM_VF_ADDR, &vcc->flags);
747 -    vcc->itf    = vcc->dev->number;
748 +    vcc->sk->bound_dev_if = vcc->dev->number;
749  
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);
759  
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);
765      }
766 @@ -1488,7 +1447,7 @@
767  {
768      struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
769      
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));
772      
773      fore200e_activate_vcin(fore200e, 0, vcc, 0);
774      
775 @@ -1543,7 +1502,7 @@
776      
777    retry_here:
778      
779 -    tasklet_disable(&fore200e->tasklet);
780 +    spin_lock_bh(&fore200e->tx_lock);
781  
782      entry = &txq->host_entry[ txq->head ];
783      
784 @@ -1553,8 +1512,8 @@
785         fore200e_irq_tx(fore200e);
786         
787         if (*entry->status != STATUS_FREE) {
788 -           
789 -           tasklet_enable(&fore200e->tasklet);
790 +
791 +           spin_unlock_bh(&fore200e->tx_lock);
792  
793             /* retry once again? */
794             if(--retry > 0)
795 @@ -1593,8 +1552,9 @@
796         
797         entry->data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);
798         if (entry->data == NULL) {
799 -           
800 -           tasklet_enable(&fore200e->tasklet);
801 +
802 +           spin_unlock_bh(&fore200e->tx_lock);
803 +
804             if (vcc->pop)
805                 vcc->pop(vcc, skb);
806             else
807 @@ -1618,13 +1578,13 @@
808      FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
809      txq->txing++;
810  
811 -    tasklet_enable(&fore200e->tasklet);
812 +    spin_unlock_bh(&fore200e->tx_lock);
813  
814      /* ensure DMA synchronisation */
815      fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
816      
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);
821  
822      if (skb_len < fore200e_vcc->tx_min_pdu)
823 @@ -1690,14 +1650,14 @@
824             dev_kfree_skb(skb);
825  
826         if (ok == 0) {
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);
829  
830             atomic_inc(&entry->vcc->stats->tx_err);
831             return -EIO;
832         }
833         atomic_inc(&entry->vcc->stats->tx);
834  
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);
837  
838      }
839  #endif
840 @@ -1755,7 +1715,7 @@
841      // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
842  
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);
846  
847      return -EINVAL;
848  }
849 @@ -1767,7 +1727,7 @@
850      // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
851      
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);
855      
856      return -EINVAL;
857  }
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 @@
868  
869      DPRINTK(2, "device %s being initialized\n", fore200e->name);
870  
871 +    spin_lock_init(&fore200e->tx_lock);
872      init_MUTEX(&fore200e->rate_sf);
873      
874      cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
875 @@ -2642,6 +2603,7 @@
876  {
877      struct fore200e* fore200e  = FORE200E_DEV(dev);
878      int              len, left = *pos;
879 +    struct sock *s;
880  
881      if (!left--) {
882  
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");
886         
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) {
890 +           vcc = atm_sk(s);
891 +
892 +           if (vcc->dev != fore200e->atm_dev) continue;
893  
894             fore200e_vcc = FORE200E_VCC(vcc);
895             
896 @@ -2900,6 +2866,7 @@
897                            fore200e_vcc->rx_max_pdu
898                 );
899         }
900 +       read_unlock(&vcc_sklist_lock);
901  
902         return len;
903      }
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
907 @@ -879,6 +879,7 @@
908      struct stats*              stats;                  /* last snapshot of the stats         */
909      
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            */
913  
914  } fore200e_t;
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
918 @@ -0,0 +1,3282 @@
919 +/* $Id$ */
920 +
921 +/*
922 +
923 +  he.c
924 +
925 +  ForeRunnerHE ATM Adapter driver for ATM on Linux
926 +  Copyright (C) 1999-2001  Naval Research Laboratory
927 +
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.
932 +
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.
937 +
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
941 +
942 +*/
943 +
944 +/*
945 +
946 +  he.c
947 +
948 +  ForeRunnerHE ATM Adapter driver for ATM on Linux
949 +  Copyright (C) 1999-2001  Naval Research Laboratory
950 +
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.
956 +
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.
960 +
961 +  This driver was written using the "Programmer's Reference Manual for
962 +  ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98.
963 +
964 +  AUTHORS:
965 +       chas williams <chas@cmf.nrl.navy.mil>
966 +       eric kinzie <ekinzie@cmf.nrl.navy.mil>
967 +
968 +  NOTES:
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
973 +
974 + */
975 +
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>
991 +#include <asm/io.h>
992 +#include <asm/byteorder.h>
993 +#include <asm/uaccess.h>
994 +
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)
1000 +#endif
1001 +
1002 +#ifdef BUS_INT_WAR
1003 +void sn_add_polled_interrupt(int irq, int interval);
1004 +void sn_delete_polled_interrupt(int irq);
1005 +#endif
1006 +
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
1013 +
1014 +#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
1015 +#define CONFIG_ATM_HE_USE_SUNI
1016 +#endif
1017 +
1018 +/* 2.2 kernel support */
1019 +
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)
1023 +#endif
1024 +
1025 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
1026 +#define set_current_state(x)           current->state = (x);
1027 +#endif
1028 +
1029 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
1030 +#undef USE_TASKLET
1031 +#endif
1032 +
1033 +#include "he.h"
1034 +
1035 +#include "suni.h"
1036 +
1037 +#include <linux/atm_he.h>
1038 +
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)
1041 +
1042 +#undef DEBUG
1043 +#ifdef DEBUG
1044 +#define HPRINTK(fmt,args...)   hprintk(fmt,args)
1045 +#define HPRINTK1(fmt)          hprintk1(fmt)
1046 +#else
1047 +#define HPRINTK(fmt,args...)
1048 +#define HPRINTK1(fmt,args...)
1049 +#endif /* DEBUG */
1050 +
1051 +
1052 +/* version definition */
1053 +
1054 +static char *version = "$Id$";
1055 +
1056 +/* defines */
1057 +#define ALIGN_ADDRESS(addr, alignment) \
1058 +       ((((unsigned long) (addr)) + (((unsigned long) (alignment)) - 1)) & ~(((unsigned long) (alignment)) - 1))
1059 +
1060 +/* declarations */
1061 +
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);
1074 +
1075 +static u8 read_prom_byte(struct he_dev *he_dev, int addr);
1076 +
1077 +/* globals */
1078 +
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;
1086 +
1087 +static struct atmdev_ops he_ops =
1088 +{
1089 +   open:       he_open,
1090 +   close:      he_close,       
1091 +   ioctl:      he_ioctl,       
1092 +   send:       he_send,
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
1099 +#endif
1100 +};
1101 +
1102 +/* see the comments in he.h about global_lock */
1103 +
1104 +#ifdef CONFIG_SMP
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)
1107 +#else
1108 +#define HE_SPIN_LOCK(dev, flags)       do { flags = 0; } while(0)
1109 +#define HE_SPIN_UNLOCK(dev, flags)     do { flags = 0; } while(0)
1110 +#endif
1111 +
1112 +
1113 +#define he_writel(dev, val, reg)       writel(val, (dev)->membase + (reg))
1114 +#define he_readl(dev, reg)             readl((dev)->membase + (reg))
1115 +
1116 +/* section 2.12 connection memory access */
1117 +
1118 +static __inline__ void
1119 +he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr,
1120 +                                                               unsigned flags)
1121 +{
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);
1125 +}
1126 +
1127 +#define he_writel_rcm(dev, val, reg)                           \
1128 +                       he_writel_internal(dev, val, reg, CON_CTL_RCM)
1129 +
1130 +#define he_writel_tcm(dev, val, reg)                           \
1131 +                       he_writel_internal(dev, val, reg, CON_CTL_TCM)
1132 +
1133 +#define he_writel_mbox(dev, val, reg)                          \
1134 +                       he_writel_internal(dev, val, reg, CON_CTL_MBOX)
1135 +
1136 +static unsigned
1137 +he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
1138 +{
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);
1142 +}
1143 +
1144 +#define he_readl_rcm(dev, reg) \
1145 +                       he_readl_internal(dev, reg, CON_CTL_RCM)
1146 +
1147 +#define he_readl_tcm(dev, reg) \
1148 +                       he_readl_internal(dev, reg, CON_CTL_TCM)
1149 +
1150 +#define he_readl_mbox(dev, reg) \
1151 +                       he_readl_internal(dev, reg, CON_CTL_MBOX)
1152 +
1153 +
1154 +/* figure 2.2 connection id */
1155 +
1156 +#define he_mkcid(dev, vpi, vci)                (((vpi<<(dev)->vcibits) | vci) & 0x1fff)
1157 +
1158 +/* 2.5.1 per connection transmit state registers */
1159 +
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)
1164 +
1165 +#define he_writel_tsr1(dev, val, cid) \
1166 +               he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 1)
1167 +
1168 +#define he_writel_tsr2(dev, val, cid) \
1169 +               he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 2)
1170 +
1171 +#define he_writel_tsr3(dev, val, cid) \
1172 +               he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 3)
1173 +
1174 +#define he_writel_tsr4(dev, val, cid) \
1175 +               he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 4)
1176 +
1177 +       /* from page 2-20
1178 +        *
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.
1183 +        */
1184 +
1185 +#define he_writel_tsr4_upper(dev, val, cid) \
1186 +               he_writel_internal(dev, val, CONFIG_TSRA | (cid<<3) | 4, \
1187 +                                                       CON_CTL_TCM \
1188 +                                                       | CON_BYTE_DISABLE_2 \
1189 +                                                       | CON_BYTE_DISABLE_1 \
1190 +                                                       | CON_BYTE_DISABLE_0)
1191 +
1192 +#define he_readl_tsr4(dev, cid) \
1193 +               he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 4)
1194 +
1195 +#define he_writel_tsr5(dev, val, cid) \
1196 +               he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 5)
1197 +
1198 +#define he_writel_tsr6(dev, val, cid) \
1199 +               he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 6)
1200 +
1201 +#define he_writel_tsr7(dev, val, cid) \
1202 +               he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 7)
1203 +
1204 +
1205 +#define he_writel_tsr8(dev, val, cid) \
1206 +               he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<1) | 0)
1207 +
1208 +#define he_writel_tsr9(dev, val, cid) \
1209 +               he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<1) | 1)
1210 +
1211 +
1212 +#define he_writel_tsr10(dev, val, cid) \
1213 +               he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 0)
1214 +
1215 +#define he_writel_tsr11(dev, val, cid) \
1216 +               he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 1)
1217 +
1218 +#define he_writel_tsr12(dev, val, cid) \
1219 +               he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 2)
1220 +
1221 +#define he_writel_tsr13(dev, val, cid) \
1222 +               he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<2) | 3)
1223 +
1224 +
1225 +#define he_writel_tsr14(dev, val, cid) \
1226 +               he_writel_tcm(dev, val, CONFIG_TSRD | cid)
1227 +
1228 +#define he_writel_tsr14_upper(dev, val, cid) \
1229 +               he_writel_internal(dev, val, CONFIG_TSRD | cid, \
1230 +                                                       CON_CTL_TCM \
1231 +                                                       | CON_BYTE_DISABLE_2 \
1232 +                                                       | CON_BYTE_DISABLE_1 \
1233 +                                                       | CON_BYTE_DISABLE_0)
1234 +
1235 +/* 2.7.1 per connection receive state registers */
1236 +
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)
1241 +
1242 +#define he_writel_rsr1(dev, val, cid) \
1243 +               he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 1)
1244 +
1245 +#define he_writel_rsr2(dev, val, cid) \
1246 +               he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 2)
1247 +
1248 +#define he_writel_rsr3(dev, val, cid) \
1249 +               he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 3)
1250 +
1251 +#define he_writel_rsr4(dev, val, cid) \
1252 +               he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 4)
1253 +
1254 +#define he_writel_rsr5(dev, val, cid) \
1255 +               he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 5)
1256 +
1257 +#define he_writel_rsr6(dev, val, cid) \
1258 +               he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 6)
1259 +
1260 +#define he_writel_rsr7(dev, val, cid) \
1261 +               he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 7)
1262 +
1263 +static __inline__ struct atm_vcc*
1264 +he_find_vcc(struct he_dev *he_dev, unsigned cid)
1265 +{
1266 +       short vpi;
1267 +       int vci;
1268 +
1269 +       vpi = cid >> he_dev->vcibits;
1270 +       vci = cid & ((1<<he_dev->vcibits)-1);
1271 +
1272 +       return __vcc_lookup(he_dev->atm_dev, vpi, vci);
1273 +}
1274 +
1275 +static int __devinit
1276 +he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
1277 +{
1278 +       struct atm_dev *atm_dev;
1279 +       struct he_dev *he_dev;
1280 +
1281 +       printk(KERN_INFO "he: %s\n", version);
1282 +
1283 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,43)
1284 +       if (pci_enable_device(pci_dev)) return -EIO;
1285 +#endif
1286 +       if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0)
1287 +       {
1288 +               printk(KERN_WARNING "he: no suitable dma available\n");
1289 +               return -EIO;
1290 +       }
1291 +
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);
1296 +#else
1297 +       pci_dev->driver_data = atm_dev;
1298 +#endif
1299 +
1300 +       he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev),
1301 +                                                       GFP_KERNEL);
1302 +       if (!he_dev) return -ENOMEM;
1303 +       memset(he_dev, 0, sizeof(struct he_dev));
1304 +
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);
1312 +               he_stop(he_dev);
1313 +               kfree(he_dev);
1314 +               return -ENODEV;
1315 +       }
1316 +       he_dev->next = NULL;
1317 +       if (he_devs) he_dev->next = he_devs;
1318 +       he_devs = he_dev;
1319 +
1320 +       return 0;
1321 +}
1322 +
1323 +static void __devexit
1324 +he_remove_one (struct pci_dev *pci_dev)
1325 +{
1326 +       struct atm_dev *atm_dev;
1327 +       struct he_dev *he_dev;
1328 +
1329 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
1330 +       atm_dev = pci_get_drvdata(pci_dev);
1331 +#else
1332 +       atm_dev = pci_dev->driver_data;
1333 +#endif
1334 +       he_dev = HE_DEV(atm_dev);
1335 +
1336 +       /* need to remove from he_devs */
1337 +
1338 +       he_stop(he_dev);
1339 +       atm_dev_deregister(atm_dev);
1340 +       kfree(he_dev);
1341 +
1342 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
1343 +       pci_set_drvdata(pci_dev, NULL);
1344 +#else
1345 +       pci_dev->driver_data = NULL;
1346 +#endif
1347 +}
1348 +
1349 +
1350 +static unsigned
1351 +rate_to_atmf(unsigned rate)            /* cps to atm forum format */
1352 +{
1353 +#define NONZERO (1<<14)
1354 +
1355 +        unsigned exp = 0;
1356 +
1357 +        if (rate == 0) return(0);
1358 +
1359 +        rate <<= 9;
1360 +        while (rate > 0x3ff)
1361 +        {
1362 +                ++exp;
1363 +                rate >>= 1;
1364 +        }
1365 +
1366 +        return (NONZERO | (exp << 9) | (rate & 0x1ff));
1367 +}
1368 +
1369 +static void __init
1370 +he_init_rx_lbfp0(struct he_dev *he_dev)
1371 +{
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;
1376 +        
1377 +       lbufd_index = 0;
1378 +        lbm_offset = he_readl(he_dev, RCMLBM_BA);
1379 +
1380 +       he_writel(he_dev, lbufd_index, RLBF0_H);
1381 +
1382 +        for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i)
1383 +        {
1384 +               lbufd_index += 2;
1385 +                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
1386 +
1387 +               he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
1388 +               he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
1389 +
1390 +                if (++lbuf_count == lbufs_per_row)
1391 +                {
1392 +                        lbuf_count = 0;
1393 +                        row_offset += he_dev->bytes_per_row;
1394 +                }
1395 +               lbm_offset += 4;
1396 +        }
1397 +                
1398 +        he_writel(he_dev, lbufd_index - 2, RLBF0_T);
1399 +       he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
1400 +}
1401 +
1402 +static void __init
1403 +he_init_rx_lbfp1(struct he_dev *he_dev)
1404 +{
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;
1409 +        
1410 +       lbufd_index = 1;
1411 +        lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
1412 +
1413 +       he_writel(he_dev, lbufd_index, RLBF1_H);
1414 +
1415 +        for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i)
1416 +        {
1417 +               lbufd_index += 2;
1418 +                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
1419 +
1420 +               he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
1421 +               he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
1422 +
1423 +                if (++lbuf_count == lbufs_per_row)
1424 +                {
1425 +                        lbuf_count = 0;
1426 +                        row_offset += he_dev->bytes_per_row;
1427 +                }
1428 +               lbm_offset += 4;
1429 +        }
1430 +                
1431 +        he_writel(he_dev, lbufd_index - 2, RLBF1_T);
1432 +       he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
1433 +}
1434 +
1435 +static void __init
1436 +he_init_tx_lbfp(struct he_dev *he_dev)
1437 +{
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;
1442 +        
1443 +       lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs;
1444 +        lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
1445 +
1446 +       he_writel(he_dev, lbufd_index, TLBF_H);
1447 +
1448 +        for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i)
1449 +        {
1450 +               lbufd_index += 1;
1451 +                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
1452 +
1453 +               he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
1454 +               he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
1455 +
1456 +                if (++lbuf_count == lbufs_per_row)
1457 +                {
1458 +                        lbuf_count = 0;
1459 +                        row_offset += he_dev->bytes_per_row;
1460 +                }
1461 +               lbm_offset += 2;
1462 +        }
1463 +                
1464 +        he_writel(he_dev, lbufd_index - 1, TLBF_T);
1465 +}
1466 +
1467 +static int __init
1468 +he_init_tpdrq(struct he_dev *he_dev)
1469 +{
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) 
1473 +       {
1474 +               hprintk1("failed to alloc tpdrq\n");
1475 +               return -ENOMEM;
1476 +       }
1477 +       memset(he_dev->tpdrq_base, 0,
1478 +                               CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq));
1479 +
1480 +       he_dev->tpdrq_tail = he_dev->tpdrq_base;
1481 +       he_dev->tpdrq_head = he_dev->tpdrq_base;
1482 +
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);
1486 +
1487 +       return 0;
1488 +}
1489 +
1490 +static void __init
1491 +he_init_cs_block(struct he_dev *he_dev)
1492 +{
1493 +       unsigned clock, rate, delta;
1494 +       int reg;
1495 +
1496 +       /* 5.1.7 cs block initialization */
1497 +
1498 +       for(reg = 0; reg < 0x20; ++reg)
1499 +               he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg);
1500 +
1501 +       /* rate grid timer reload values */
1502 +
1503 +       clock = he_is622(he_dev) ? 66667000 : 50000000;
1504 +       rate = he_dev->atm_dev->link_rate;
1505 +       delta = rate / 16 / 2;
1506 +
1507 +       for(reg = 0; reg < 0x10; ++reg)
1508 +       {
1509 +               /* 2.4 internal transmit function
1510 +                *
1511 +                * we initialize the first row in the rate grid.
1512 +                * values are period (in clock cycles) of timer
1513 +                */
1514 +               unsigned period = clock / rate;
1515 +
1516 +               he_writel_mbox(he_dev, period, CS_TGRLD0 + reg);
1517 +               rate -= delta;
1518 +       }
1519 +
1520 +       if (he_is622(he_dev))
1521 +       {
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);
1528 +
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);
1536 +
1537 +               he_writel_mbox(he_dev, 0x4680, CS_RTATR);
1538 +
1539 +               /* table 5.8 */
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);
1546 +
1547 +               /* table 5.9 */
1548 +               he_writel_mbox(he_dev, 0x5, CS_OTPPER);
1549 +               he_writel_mbox(he_dev, 0x14, CS_OTWPER);
1550 +       }
1551 +       else
1552 +       {
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);
1559 +
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);
1567 +
1568 +               he_writel_mbox(he_dev, 0x4680, CS_RTATR);
1569 +
1570 +               /* table 5.8 */
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);
1577 +
1578 +               /* table 5.9 */
1579 +               he_writel_mbox(he_dev, 0x6, CS_OTPPER);
1580 +               he_writel_mbox(he_dev, 0x1e, CS_OTWPER);
1581 +
1582 +       }
1583 +
1584 +       he_writel_mbox(he_dev, 0x8, CS_OTTLIM);
1585 +
1586 +       for(reg = 0; reg < 0x8; ++reg)
1587 +               he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg);
1588 +
1589 +}
1590 +
1591 +static void __init
1592 +he_init_cs_block_rcm(struct he_dev *he_dev)
1593 +{
1594 +       unsigned rategrid[16][16];
1595 +       unsigned rate, delta;
1596 +       int i, j, reg;
1597 +
1598 +       unsigned rate_atmf, exp, man;
1599 +       unsigned long long rate_cps;
1600 +        int mult, buf, buf_limit = 4;
1601 +
1602 +       /* initialize rate grid group table */
1603 +
1604 +       for (reg = 0x0; reg < 0xff; ++reg)
1605 +               he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
1606 +
1607 +       /* initialize rate controller groups */
1608 +
1609 +       for (reg = 0x100; reg < 0x1ff; ++reg)
1610 +               he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
1611 +       
1612 +       /* initialize tNrm lookup table */
1613 +
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 */
1617 +       
1618 +       /* initialize rate to group table */
1619 +
1620 +       rate = he_dev->atm_dev->link_rate;
1621 +       delta = rate / 32;
1622 +
1623 +       /*
1624 +        * 2.4 transmit internal functions
1625 +        * 
1626 +        * we construct a copy of the rate grid used by the scheduler
1627 +        * in order to construct the rate to group table below
1628 +        */
1629 +
1630 +       for (j = 0; j < 16; j++)
1631 +       {
1632 +               rategrid[0][j] = rate;
1633 +               rate -= delta;
1634 +       }
1635 +
1636 +       for (i = 1; i < 16; i++)
1637 +               for (j = 0; j < 16; j++)
1638 +                       if (i > 14)
1639 +                               rategrid[i][j] = rategrid[i - 1][j] / 4;
1640 +                       else
1641 +                               rategrid[i][j] = rategrid[i - 1][j] / 2;
1642 +
1643 +       /*
1644 +        * 2.4 transmit internal function
1645 +        *
1646 +        * this table maps the upper 5 bits of exponent and mantissa
1647 +        * of the atm forum representation of the rate into an index
1648 +        * on rate grid  
1649 +        */
1650 +
1651 +       rate_atmf = 0;
1652 +       while (rate_atmf < 0x400)
1653 +       {
1654 +               man = (rate_atmf & 0x1f) << 4;
1655 +               exp = rate_atmf >> 5;
1656 +
1657 +               /* 
1658 +                       instead of '/ 512', use '>> 9' to prevent a call
1659 +                       to divdu3 on x86 platforms
1660 +               */
1661 +               rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
1662 +
1663 +               if (rate_cps < 10) rate_cps = 10;
1664 +                               /* 2.2.1 minimum payload rate is 10 cps */
1665 +
1666 +               for (i = 255; i > 0; i--)
1667 +                       if (rategrid[i/16][i%16] >= rate_cps) break;
1668 +                               /* pick nearest rate instead? */
1669 +
1670 +               /*
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
1674 +                */
1675 +
1676 +#ifdef notdef
1677 +                buf = rate_cps * he_dev->tx_numbuffs /
1678 +                               (he_dev->atm_dev->link_rate * 2);
1679 +#else
1680 +               /* this is pretty, but avoids _divdu3 and is mostly correct */
1681 +                buf = 0;
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;
1687 +#endif
1688 +                if (buf > buf_limit) buf = buf_limit;
1689 +               reg = (reg<<16) | ((i<<8) | buf);
1690 +
1691 +#define RTGTBL_OFFSET 0x400
1692 +         
1693 +               if (rate_atmf & 0x1)
1694 +                       he_writel_rcm(he_dev, reg,
1695 +                               CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf>>1));
1696 +
1697 +               ++rate_atmf;
1698 +       }
1699 +}
1700 +
1701 +
1702 +static int __init
1703 +he_init_group(struct he_dev *he_dev, int group)
1704 +{
1705 +       int i;
1706 +
1707 +#ifdef USE_RBPS
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);
1712 +#else
1713 +       he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
1714 +                       CONFIG_RBPS_BUFSIZE, 8, 0);
1715 +#endif
1716 +       if (he_dev->rbps_pool == NULL)
1717 +       {
1718 +               hprintk1("unable to create rbpl pool\n");
1719 +               return -ENOMEM;
1720 +       }
1721 +
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)
1725 +       {
1726 +               hprintk1("failed to alloc rbps\n");
1727 +               return -ENOMEM;
1728 +       }
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);
1731 +
1732 +       for (i = 0; i < CONFIG_RBPS_SIZE; ++i)
1733 +       {
1734 +               dma_addr_t dma_handle;
1735 +               void *cpuaddr;
1736 +
1737 +               cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
1738 +               if (cpuaddr == NULL)
1739 +                       return -ENOMEM;
1740 +
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;
1744 +
1745 +       }
1746 +       he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE-1];
1747 +
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));
1753 +       he_writel(he_dev,
1754 +                       RBP_THRESH(CONFIG_RBPS_THRESH) |
1755 +                       RBP_QSIZE(CONFIG_RBPS_SIZE-1) |
1756 +                       RBP_INT_ENB,
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 */
1765 +
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);
1771 +#else
1772 +       he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
1773 +                       CONFIG_RBPL_BUFSIZE, 8, 0);
1774 +#endif
1775 +       if (he_dev->rbpl_pool == NULL)
1776 +       {
1777 +               hprintk1("unable to create rbpl pool\n");
1778 +               return -ENOMEM;
1779 +       }
1780 +#endif
1781 +
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)
1785 +       {
1786 +               hprintk1("failed to alloc rbpl\n");
1787 +               return -ENOMEM;
1788 +       }
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);
1791 +
1792 +       for (i = 0; i < CONFIG_RBPL_SIZE; ++i)
1793 +       {
1794 +               dma_addr_t dma_handle;
1795 +               void *cpuaddr;
1796 +
1797 +#ifdef USE_RBPL_POOL
1798 +               cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
1799 +#else
1800 +               cpuaddr = pci_alloc_consistent(he_dev->pci_dev, CONFIG_RBPL_BUFSIZE, &dma_handle);
1801 +#endif
1802 +               if (cpuaddr == NULL)
1803 +                       return -ENOMEM;
1804 +
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;
1808 +
1809 +       }
1810 +       he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE-1];
1811 +
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));
1817 +       he_writel(he_dev,
1818 +                       RBP_THRESH(CONFIG_RBPL_THRESH) |
1819 +                       RBP_QSIZE(CONFIG_RBPL_SIZE-1) |
1820 +                       RBP_INT_ENB,
1821 +                                               G0_RBPL_QI + (group * 32));
1822 +
1823 +       /* rx buffer ready queue */
1824 +
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)
1828 +       {
1829 +               hprintk1("failed to allocate rbrq\n");
1830 +               return -ENOMEM;
1831 +       }
1832 +       memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
1833 +
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));
1837 +       he_writel(he_dev,
1838 +               RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE-1),
1839 +                                               G0_RBRQ_Q + (group * 16));
1840 +       if (irq_coalesce)
1841 +       {
1842 +               hprintk1("coalescing interrupts\n");
1843 +               he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7),
1844 +                                               G0_RBRQ_I + (group * 16));
1845 +       }
1846 +       else
1847 +               he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1),
1848 +                                               G0_RBRQ_I + (group * 16));
1849 +
1850 +       /* tx buffer ready queue */
1851 +
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)
1855 +       {
1856 +               hprintk1("failed to allocate tbrq\n");
1857 +               return -ENOMEM;
1858 +       }
1859 +       memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
1860 +
1861 +       he_dev->tbrq_head = he_dev->tbrq_base;
1862 +
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));
1867 +
1868 +       return 0;
1869 +}
1870 +
1871 +static int __init
1872 +he_init_irq(struct he_dev *he_dev)
1873 +{
1874 +       int i;
1875 +
1876 +       /* 2.9.3.5  tail offset for each interrupt queue is located after the
1877 +                   end of the interrupt queue */
1878 +
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)
1882 +       {
1883 +               hprintk1("failed to allocate irq\n");
1884 +               return -ENOMEM;
1885 +       }
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;
1891 +
1892 +       for(i=0; i < CONFIG_IRQ_SIZE; ++i)
1893 +               he_dev->irq_base[i].isw = ITYPE_INVALID;
1894 +
1895 +       he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE);
1896 +       he_writel(he_dev,
1897 +               IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH),
1898 +                                                               IRQ0_HEAD);
1899 +       he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL);
1900 +       he_writel(he_dev, 0x0, IRQ0_DATA);
1901 +
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);
1906 +
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);
1911 +
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);
1916 +
1917 +       /* 2.9.3.2 interrupt queue mapping registers */
1918 +
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);
1923 +
1924 +       if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev))
1925 +       {
1926 +               hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
1927 +               return -EINVAL;
1928 +        }   
1929 +
1930 +       he_dev->irq = he_dev->pci_dev->irq;
1931 +
1932 +#ifdef BUS_INT_WAR
1933 +        HPRINTK("sn_add_polled_interrupt(irq %d, 1)\n", he_dev->irq);
1934 +        sn_add_polled_interrupt(he_dev->irq, 1);
1935 +#endif
1936 +
1937 +       return 0;
1938 +}
1939 +
1940 +static int __init
1941 +he_start(struct atm_dev *dev)
1942 +{
1943 +        struct he_dev *he_dev;
1944 +        struct pci_dev *pci_dev;
1945 +
1946 +       u16 command;
1947 +       u32 gen_cntl_0, host_cntl, lb_swap;
1948 +       u8 cache_size, timer;
1949 +       
1950 +       unsigned err;
1951 +       unsigned int status, reg;
1952 +       int i, group;
1953 +
1954 +        he_dev = HE_DEV(dev);
1955 +        pci_dev = he_dev->pci_dev;
1956 +
1957 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,3)
1958 +       he_dev->membase = pci_dev->resource[0].start;
1959 +#else
1960 +       he_dev->membase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
1961 +#endif
1962 +       HPRINTK("membase = 0x%x  irq = %d.\n", he_dev->membase, pci_dev->irq);
1963 +
1964 +       /*
1965 +        * pci bus controller initialization 
1966 +        */
1967 +
1968 +       /* 4.3 pci bus controller-specific initialization */
1969 +       if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0)
1970 +       {
1971 +               hprintk1("can't read GEN_CNTL_0\n");
1972 +               return -EINVAL;
1973 +       }
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)
1976 +       {
1977 +               hprintk1("can't write GEN_CNTL_0.\n");
1978 +               return -EINVAL;
1979 +       }
1980 +
1981 +       if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0)
1982 +       {
1983 +               hprintk1("can't read PCI_COMMAND.\n");
1984 +               return -EINVAL;
1985 +       }
1986 +
1987 +       command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
1988 +       if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0)
1989 +       {
1990 +               hprintk1("can't enable memory.\n");
1991 +               return -EINVAL;
1992 +       }
1993 +
1994 +       if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size))
1995 +       {
1996 +               hprintk1("can't read cache line size?\n");
1997 +               return -EINVAL;
1998 +       }
1999 +
2000 +       if (cache_size < 16)
2001 +       {
2002 +               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);
2005 +       }
2006 +
2007 +       if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer))
2008 +       {
2009 +               hprintk1("can't read latency timer?\n");
2010 +               return -EINVAL;
2011 +       }
2012 +
2013 +       /* from table 3.9
2014 +        *
2015 +        * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE
2016 +        * 
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]
2019 +        *
2020 +        */ 
2021 +#define LAT_TIMER 209
2022 +       if (timer < LAT_TIMER)
2023 +       {
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);
2028 +       }
2029 +
2030 +       if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
2031 +               hprintk1("can't set up page mapping\n");
2032 +               return -EINVAL;
2033 +       }
2034 +             
2035 +       /* 4.4 card reset */
2036 +       he_writel(he_dev, 0x0, RESET_CNTL);
2037 +       he_writel(he_dev, 0xff, RESET_CNTL);
2038 +
2039 +       udelay(16*1000);        /* 16 ms */
2040 +       status = he_readl(he_dev, RESET_CNTL);
2041 +       if ((status & BOARD_RST_STATUS) == 0)
2042 +       {
2043 +               hprintk1("reset failed\n");
2044 +               return -EINVAL;
2045 +       }
2046 +
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;
2051 +       else
2052 +               gen_cntl_0 &= ~ENBL_64;
2053 +
2054 +       if (disable64 == 1)
2055 +       {
2056 +               hprintk1("disabling 64-bit pci bus transfers\n");
2057 +               gen_cntl_0 &= ~ENBL_64;
2058 +       }
2059 +
2060 +       if (gen_cntl_0 & ENBL_64) hprintk1("64-bit transfers enabled\n");
2061 +
2062 +       pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
2063 +
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);
2067 +
2068 +       he_dev->media = read_prom_byte(he_dev, MEDIA);
2069 +
2070 +       for(i=0; i<6; ++i)
2071 +               dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i);
2072 +
2073 +       hprintk("%s%s, %x:%x:%x:%x:%x:%x\n",
2074 +                               he_dev->prod_id,
2075 +                                       he_dev->media & 0x40 ? "SM" : "MM",
2076 +                                               dev->esi[0],
2077 +                                               dev->esi[1],
2078 +                                               dev->esi[2],
2079 +                                               dev->esi[3],
2080 +                                               dev->esi[4],
2081 +                                               dev->esi[5]);
2082 +       he_dev->atm_dev->link_rate = he_is622(he_dev) ?
2083 +                                               ATM_OC12_PCR : ATM_OC3_PCR;
2084 +
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 */
2089 +       else
2090 +               lb_swap |= XFER_SIZE;           /* 8 cells */
2091 +#ifdef __BIG_ENDIAN
2092 +       lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST;
2093 +#else
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);
2098 +
2099 +       /* 4.8 sdram controller initialization */
2100 +       he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL);
2101 +
2102 +       /* 4.9 initialize rnum value */
2103 +       lb_swap |= SWAP_RNUM_MAX(0xf);
2104 +       he_writel(he_dev, lb_swap, LB_SWAP);
2105 +
2106 +       /* 4.10 initialize the interrupt queues */
2107 +       if ((err = he_init_irq(he_dev)) != 0) return err;
2108 +
2109 +#ifdef USE_TASKLET
2110 +       tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
2111 +#endif
2112 +       spin_lock_init(&he_dev->global_lock);
2113 +       spin_lock_init(&he_dev->tpdrq_lock);
2114 +
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);
2119 +
2120 +       gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB;
2121 +       pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
2122 +
2123 +       /*
2124 +        * atm network controller initialization
2125 +        */
2126 +
2127 +       /* 5.1.1 generic configuration state */
2128 +
2129 +       /*
2130 +        *              local (cell) buffer memory map
2131 +        *                    
2132 +        *             HE155                          HE622
2133 +        *                                                      
2134 +        *        0 ____________1023 bytes  0 _______________________2047 bytes
2135 +        *         |            |            |                   |   |
2136 +        *         |  utility   |            |        rx0        |   |
2137 +        *        5|____________|         255|___________________| u |
2138 +        *        6|            |         256|                   | t |
2139 +        *         |            |            |                   | i |
2140 +        *         |    rx0     |     row    |        tx         | l |
2141 +        *         |            |            |                   | i |
2142 +        *         |            |         767|___________________| t |
2143 +        *      517|____________|         768|                   | y |
2144 +        * row  518|            |            |        rx1        |   |
2145 +        *         |            |        1023|___________________|___|
2146 +        *         |            |
2147 +        *         |    tx      |
2148 +        *         |            |
2149 +        *         |            |
2150 +        *     1535|____________|
2151 +        *     1536|            |
2152 +        *         |    rx1     |
2153 +        *     2047|____________|
2154 +        *
2155 +        */
2156 +
2157 +       /* total 4096 connections */
2158 +       he_dev->vcibits = CONFIG_DEFAULT_VCIBITS;
2159 +       he_dev->vpibits = CONFIG_DEFAULT_VPIBITS;
2160 +
2161 +       if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS)
2162 +       {
2163 +               hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS);
2164 +               return -ENODEV;
2165 +       }
2166 +
2167 +       if (nvpibits != -1)
2168 +       {
2169 +               he_dev->vpibits = nvpibits;
2170 +               he_dev->vcibits = HE_MAXCIDBITS - nvpibits;
2171 +       }
2172 +
2173 +       if (nvcibits != -1)
2174 +       {
2175 +               he_dev->vcibits = nvcibits;
2176 +               he_dev->vpibits = HE_MAXCIDBITS - nvcibits;
2177 +       }
2178 +
2179 +
2180 +       if (he_is622(he_dev))
2181 +       {
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;
2190 +       }
2191 +       else
2192 +       {
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;
2201 +       }
2202 +
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;
2208 +
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;
2212 +
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;
2216 +
2217 +       /* 5.1.2 configure hardware dependent registers */
2218 +
2219 +       he_writel(he_dev, 
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)),
2224 +                                                               LBARB);
2225 +
2226 +       he_writel(he_dev, BANK_ON |
2227 +               (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)),
2228 +                                                               SDRAMCON);
2229 +
2230 +       he_writel(he_dev,
2231 +               (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) |
2232 +                                               RM_RW_WAIT(1), RCMCONFIG);
2233 +       he_writel(he_dev,
2234 +               (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) |
2235 +                                               TM_RW_WAIT(1), TCMCONFIG);
2236 +
2237 +       he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG);
2238 +
2239 +       he_writel(he_dev, 
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);
2244 +
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);
2249 +
2250 +       he_writel(he_dev, 0x0, TXAAL5_PROTO);
2251 +
2252 +       he_writel(he_dev, PHY_INT_ENB |
2253 +               (he_is622(he_dev) ? PTMR_PRE(67-1) : PTMR_PRE(50-1)),
2254 +                                                               RH_CONFIG);
2255 +
2256 +       /* 5.1.3 initialize connection memory */
2257 +
2258 +       for(i=0; i < TCM_MEM_SIZE; ++i)
2259 +               he_writel_tcm(he_dev, 0, i);
2260 +
2261 +       for(i=0; i < RCM_MEM_SIZE; ++i)
2262 +               he_writel_rcm(he_dev, 0, i);
2263 +
2264 +       /*
2265 +        *      transmit connection memory map
2266 +        *
2267 +        *                  tx memory
2268 +        *          0x0 ___________________
2269 +        *             |                   |
2270 +        *             |                   |
2271 +        *             |       TSRa        |
2272 +        *             |                   |
2273 +        *             |                   |
2274 +        *       0x8000|___________________|
2275 +        *             |                   |
2276 +        *             |       TSRb        |
2277 +        *       0xc000|___________________|
2278 +        *             |                   |
2279 +        *             |       TSRc        |
2280 +        *       0xe000|___________________|
2281 +        *             |       TSRd        |
2282 +        *       0xf000|___________________|
2283 +        *             |       tmABR       |
2284 +        *      0x10000|___________________|
2285 +        *             |                   |
2286 +        *             |       tmTPD       |
2287 +        *             |___________________|
2288 +        *             |                   |
2289 +        *                      ....
2290 +        *      0x1ffff|___________________|
2291 +        *
2292 +        *
2293 +        */
2294 +
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);
2300 +
2301 +
2302 +       /*
2303 +        *      receive connection memory map
2304 +        *
2305 +        *          0x0 ___________________
2306 +        *             |                   |
2307 +        *             |                   |
2308 +        *             |       RSRa        |
2309 +        *             |                   |
2310 +        *             |                   |
2311 +        *       0x8000|___________________|
2312 +        *             |                   |
2313 +        *             |             rx0/1 |
2314 +        *             |       LBM         |   link lists of local
2315 +        *             |             tx    |   buffer memory 
2316 +        *             |                   |
2317 +        *       0xd000|___________________|
2318 +        *             |                   |
2319 +        *             |      rmABR        |
2320 +        *       0xe000|___________________|
2321 +        *             |                   |
2322 +        *             |       RSRb        |
2323 +        *             |___________________|
2324 +        *             |                   |
2325 +        *                      ....
2326 +        *       0xffff|___________________|
2327 +        */
2328 +
2329 +       he_writel(he_dev, 0x08000, RCMLBM_BA);
2330 +       he_writel(he_dev, 0x0e000, RCMRSRB_BA);
2331 +       he_writel(he_dev, 0x0d800, RCMABR_BA);
2332 +
2333 +       /* 5.1.4 initialize local buffer free pools linked lists */
2334 +
2335 +       he_init_rx_lbfp0(he_dev);
2336 +       he_init_rx_lbfp1(he_dev);
2337 +
2338 +       he_writel(he_dev, 0x0, RLBC_H);
2339 +       he_writel(he_dev, 0x0, RLBC_T);
2340 +       he_writel(he_dev, 0x0, RLBC_H2);
2341 +
2342 +       he_writel(he_dev, 512, RXTHRSH);        /* 10% of r0+r1 buffers */
2343 +       he_writel(he_dev, 256, LITHRSH);        /* 5% of r0+r1 buffers */
2344 +
2345 +       he_init_tx_lbfp(he_dev);
2346 +
2347 +       he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA);
2348 +
2349 +       /* 5.1.5 initialize intermediate receive queues */
2350 +
2351 +       if (he_is622(he_dev))
2352 +       {
2353 +               he_writel(he_dev, 0x000f, G0_INMQ_S);
2354 +               he_writel(he_dev, 0x200f, G0_INMQ_L);
2355 +
2356 +               he_writel(he_dev, 0x001f, G1_INMQ_S);
2357 +               he_writel(he_dev, 0x201f, G1_INMQ_L);
2358 +
2359 +               he_writel(he_dev, 0x002f, G2_INMQ_S);
2360 +               he_writel(he_dev, 0x202f, G2_INMQ_L);
2361 +
2362 +               he_writel(he_dev, 0x003f, G3_INMQ_S);
2363 +               he_writel(he_dev, 0x203f, G3_INMQ_L);
2364 +
2365 +               he_writel(he_dev, 0x004f, G4_INMQ_S);
2366 +               he_writel(he_dev, 0x204f, G4_INMQ_L);
2367 +
2368 +               he_writel(he_dev, 0x005f, G5_INMQ_S);
2369 +               he_writel(he_dev, 0x205f, G5_INMQ_L);
2370 +
2371 +               he_writel(he_dev, 0x006f, G6_INMQ_S);
2372 +               he_writel(he_dev, 0x206f, G6_INMQ_L);
2373 +
2374 +               he_writel(he_dev, 0x007f, G7_INMQ_S);
2375 +               he_writel(he_dev, 0x207f, G7_INMQ_L);
2376 +       }
2377 +       else
2378 +       {
2379 +               he_writel(he_dev, 0x0000, G0_INMQ_S);
2380 +               he_writel(he_dev, 0x0008, G0_INMQ_L);
2381 +
2382 +               he_writel(he_dev, 0x0001, G1_INMQ_S);
2383 +               he_writel(he_dev, 0x0009, G1_INMQ_L);
2384 +
2385 +               he_writel(he_dev, 0x0002, G2_INMQ_S);
2386 +               he_writel(he_dev, 0x000a, G2_INMQ_L);
2387 +
2388 +               he_writel(he_dev, 0x0003, G3_INMQ_S);
2389 +               he_writel(he_dev, 0x000b, G3_INMQ_L);
2390 +
2391 +               he_writel(he_dev, 0x0004, G4_INMQ_S);
2392 +               he_writel(he_dev, 0x000c, G4_INMQ_L);
2393 +
2394 +               he_writel(he_dev, 0x0005, G5_INMQ_S);
2395 +               he_writel(he_dev, 0x000d, G5_INMQ_L);
2396 +
2397 +               he_writel(he_dev, 0x0006, G6_INMQ_S);
2398 +               he_writel(he_dev, 0x000e, G6_INMQ_L);
2399 +
2400 +               he_writel(he_dev, 0x0007, G7_INMQ_S);
2401 +               he_writel(he_dev, 0x000f, G7_INMQ_L);
2402 +       }
2403 +
2404 +       /* 5.1.6 application tunable parameters */
2405 +
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);
2410 +       
2411 +       /* 5.1.7 cs block initialization */
2412 +
2413 +       he_init_cs_block(he_dev);
2414 +
2415 +       /* 5.1.8 cs block connection memory initialization */
2416 +       
2417 +       he_init_cs_block_rcm(he_dev);
2418 +
2419 +       /* 5.1.10 initialize host structures */
2420 +
2421 +       he_init_tpdrq(he_dev);
2422 +
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);
2426 +#else
2427 +       he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
2428 +                       sizeof(struct he_tpd), TPD_ALIGNMENT, 0);
2429 +#endif
2430 +       if (he_dev->tpd_pool == NULL)
2431 +       {
2432 +               hprintk1("unable to create tpd pci_pool\n");
2433 +               return -ENOMEM;
2434 +       }
2435 +       INIT_LIST_HEAD(&he_dev->outstanding_tpds);
2436 +
2437 +       if (he_init_group(he_dev, 0) != 0)
2438 +               return -ENOMEM;
2439 +
2440 +       for (group = 1; group < HE_NUM_GROUPS; ++group)
2441 +       {
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));
2447 +
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));
2453 +
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));
2459 +
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));
2465 +       }
2466 +
2467 +       /* host status page */
2468 +
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)
2472 +       {
2473 +               hprintk1("failed to allocate host status page\n");
2474 +               return -ENOMEM;
2475 +       }
2476 +       memset(he_dev->hsp, 0, sizeof(struct he_hsp));
2477 +       he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
2478 +
2479 +       /* initialize framer */
2480 +
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 */
2486 +
2487 +       if (sdh)
2488 +       {
2489 +               /* this really should be in suni.c but for now... */
2490 +
2491 +               int val;
2492 +
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);
2496 +       }
2497 +
2498 +       /* 5.1.12 enable transmit and receive */
2499 +
2500 +       reg = he_readl_mbox(he_dev, CS_ERCTL0);
2501 +       reg |= TX_ENABLE|ER_ENABLE;
2502 +       he_writel_mbox(he_dev, reg, CS_ERCTL0);
2503 +
2504 +       reg = he_readl(he_dev, RC_CONFIG);
2505 +       reg |= RX_ENABLE;
2506 +       he_writel(he_dev, reg, RC_CONFIG);
2507 +
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)
2512 +       {
2513 +               hprintk1("failed to alloc he_vcc_table\n");
2514 +               return -ENOMEM;
2515 +       }
2516 +       memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) *
2517 +                               (1 << (he_dev->vcibits + he_dev->vpibits)));
2518 +#endif
2519 +
2520 +       for (i = 0; i < HE_NUM_CS_STPER; ++i)
2521 +       {
2522 +               he_dev->cs_stper[i].inuse = 0;
2523 +               he_dev->cs_stper[i].pcr = -1;
2524 +       }
2525 +       he_dev->total_bw = 0;
2526 +
2527 +
2528 +       /* atm linux initialization */
2529 +
2530 +       he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits;
2531 +       he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits;
2532 +
2533 +       he_dev->irq_peak = 0;
2534 +       he_dev->rbrq_peak = 0;
2535 +        he_dev->rbpl_peak = 0;
2536 +        he_dev->tbrq_peak = 0;
2537 +
2538 +       hprintk1("hell bent for leather!\n");
2539 +
2540 +       return 0;
2541 +}
2542 +
2543 +static void
2544 +he_stop(struct he_dev *he_dev)
2545 +{
2546 +       u16 command;
2547 +       u32 gen_cntl_0, reg;
2548 +       struct pci_dev *pci_dev;
2549 +       int i;
2550 +
2551 +       pci_dev = he_dev->pci_dev;
2552 +
2553 +       /* disable interrupts */
2554 +
2555 +       if (he_dev->membase)
2556 +       {
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);
2560 +
2561 +#ifdef USE_TASKLET
2562 +               tasklet_disable(&he_dev->tasklet);
2563 +#endif
2564 +
2565 +               /* disable recv and transmit */
2566 +
2567 +               reg = he_readl_mbox(he_dev, CS_ERCTL0);
2568 +               reg &= ~(TX_ENABLE|ER_ENABLE);
2569 +               he_writel_mbox(he_dev, reg, CS_ERCTL0);
2570 +
2571 +               reg = he_readl(he_dev, RC_CONFIG);
2572 +               reg &= ~(RX_ENABLE);
2573 +               he_writel(he_dev, reg, RC_CONFIG);
2574 +       }
2575 +
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 */
2580 +
2581 +       if (he_dev->irq)
2582 +       {
2583 +#ifdef BUS_INT_WAR
2584 +               sn_delete_polled_interrupt(he_dev->irq);
2585 +#endif
2586 +               free_irq(he_dev->irq, he_dev);
2587 +       }
2588 +
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);
2592 +
2593 +       if (he_dev->hsp)
2594 +               pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp),
2595 +                                               he_dev->hsp, he_dev->hsp_phys);
2596 +
2597 +       if (he_dev->rbpl_base)
2598 +       {
2599 +               for (i=0; i<CONFIG_RBPL_SIZE; ++i)
2600 +               {
2601 +                       void *cpuaddr = he_dev->rbpl_virt[i].virt;
2602 +                       dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
2603 +
2604 +#ifdef USE_RBPL_POOL
2605 +                       pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle);
2606 +#else
2607 +                       pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_BUFSIZE, cpuaddr, dma_handle);
2608 +#endif
2609 +               }
2610 +               pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
2611 +                       * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);
2612 +       }
2613 +
2614 +#ifdef USE_RBPL_POOL
2615 +       if (he_dev->rbpl_pool)
2616 +               pci_pool_destroy(he_dev->rbpl_pool);
2617 +#endif
2618 +
2619 +#ifdef USE_RBPS
2620 +       if (he_dev->rbps_base)
2621 +       {
2622 +               for (i=0; i<CONFIG_RBPS_SIZE; ++i)
2623 +               {
2624 +                       void *cpuaddr = he_dev->rbps_virt[i].virt;
2625 +                       dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
2626 +
2627 +                       pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle);
2628 +               }
2629 +               pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
2630 +                       * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys);
2631 +       }
2632 +#endif /* USE_RBPS */
2633 +
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);
2637 +
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);
2641 +
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);
2645 +
2646 +       if (he_dev->tpd_pool)
2647 +               pci_pool_destroy(he_dev->tpd_pool);
2648 +
2649 +#ifndef USE_HE_FIND_VCC
2650 +       if (he_dev->he_vcc_table)
2651 +               kfree(he_dev->he_vcc_table);
2652 +#endif
2653 +
2654 +       if (he_dev->pci_dev)
2655 +       {
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);
2659 +       }
2660 +       
2661 +       if (he_dev->membase) iounmap((void *) he_dev->membase);
2662 +}
2663 +
2664 +static __inline__ struct he_tpd *
2665 +he_alloc_tpd(struct he_dev *he_dev)
2666 +{
2667 +       struct he_tpd *tpd;
2668 +       dma_addr_t dma_handle;
2669 +
2670 +       tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle);
2671 +       if (tpd == NULL)
2672 +               return NULL;
2673 +
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;
2679 +
2680 +       return tpd;
2681 +}
2682 +
2683 +
2684 +#define AAL5_LEN(buf,len)                                              \
2685 +                       ((((unsigned char *)(buf))[(len)-6]<<8) |       \
2686 +                               (((unsigned char *)(buf))[(len)-5]))
2687 +
2688 +/* 2.10.1.2 receive
2689 + *
2690 + * aal5 packets can optionally return the tcp checksum in the lower
2691 + * 16 bits of the crc (RSR0_TCP_CKSUM)
2692 + */
2693 +
2694 +#define TCP_CKSUM(buf,len)                                             \
2695 +                       ((((unsigned char *)(buf))[(len)-2]<<8) |       \
2696 +                               (((unsigned char *)(buf))[(len-1)]))
2697 +
2698 +static int
2699 +he_service_rbrq(struct he_dev *he_dev, int group)
2700 +{
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;
2712 +       int updated = 0;
2713 +
2714 +       read_lock(&vcc_sklist_lock);
2715 +       while (he_dev->rbrq_head != rbrq_tail)
2716 +       {
2717 +               ++updated;
2718 +
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" : "");
2730 +
2731 +#ifdef USE_RBPS
2732 +               if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF)
2733 +                       rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
2734 +               else
2735 +#endif
2736 +                       rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
2737 +               
2738 +               buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
2739 +               cid = RBRQ_CID(he_dev->rbrq_head);
2740 +
2741 +#ifdef USE_HE_FIND_VCC
2742 +               if (cid != lastcid)
2743 +                       vcc = he_find_vcc(he_dev, cid);
2744 +               lastcid = cid;
2745 +#else
2746 +               vcc = HE_LOOKUP_VCC(he_dev, cid);
2747 +#endif
2748 +               if (vcc == NULL)
2749 +               {
2750 +                       hprintk("vcc == NULL  (cid 0x%x)\n", cid);
2751 +                       if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
2752 +                                       rbp->status &= ~RBP_LOANED;
2753 +                                       
2754 +                       goto next_rbrq_entry;
2755 +               }
2756 +
2757 +               he_vcc = HE_VCC(vcc);
2758 +               if (he_vcc == NULL)
2759 +               {
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;
2764 +               }
2765 +
2766 +               if (RBRQ_HBUF_ERR(he_dev->rbrq_head))
2767 +               {
2768 +                       hprintk("HBUF_ERR!  (cid 0x%x)\n", cid);
2769 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
2770 +                               ++vcc->stats->rx_drop;
2771 +#else
2772 +                               atomic_inc(&vcc->stats->rx_drop);
2773 +#endif
2774 +                       goto return_host_buffers;
2775 +               }
2776 +
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;
2781 +
2782 +               if (RBRQ_CON_CLOSED(he_dev->rbrq_head))
2783 +               {
2784 +                       lastcid = -1;
2785 +                       HPRINTK("wake_up rx_waitq  (cid 0x%x)\n", cid);
2786 +                       wake_up(&he_vcc->rx_waitq);
2787 +                       goto return_host_buffers;
2788 +               }
2789 +
2790 +#ifdef notdef
2791 +               if (he_vcc->iov_tail - he_vcc->iov_head > 32)
2792 +               {
2793 +                       hprintk("iovec full!  cid 0x%x\n", cid);
2794 +                       goto return_host_buffers;
2795 +               }
2796 +#endif
2797 +               if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry;
2798 +
2799 +               if (RBRQ_LEN_ERR(he_dev->rbrq_head)
2800 +                               || RBRQ_CRC_ERR(he_dev->rbrq_head))
2801 +               {
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)
2806 +                                                       ? "LEN_ERR" : "",
2807 +                                                       vcc->vpi, vcc->vci);
2808 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
2809 +                       ++vcc->stats->rx_err;
2810 +#else
2811 +                       atomic_inc(&vcc->stats->rx_err);
2812 +#endif
2813 +                       goto return_host_buffers;
2814 +               }
2815 +
2816 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,15)
2817 +               skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve,
2818 +                                                       GFP_ATOMIC);
2819 +#else
2820 +               if (!atm_charge(vcc, atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve)))
2821 +                       skb = NULL;
2822 +               else
2823 +               {
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));
2827 +               }
2828 +#endif
2829 +               if (!skb)
2830 +               {
2831 +                       HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci);
2832 +                       goto return_host_buffers;
2833 +               }
2834 +
2835 +               if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve);
2836 +
2837 +               do_gettimeofday(&skb->stamp);
2838 +
2839 +               for(iov = he_vcc->iov_head;
2840 +                               iov < he_vcc->iov_tail; ++iov)
2841 +               {
2842 +#ifdef USE_RBPS
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);
2846 +                       else
2847 +#endif
2848 +                               memcpy(skb_put(skb, iov->iov_len),
2849 +                                       he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
2850 +               }
2851 +
2852 +               switch(vcc->qos.aal)
2853 +               {
2854 +                       case ATM_AAL0:
2855 +                               /* 2.10.1.5 raw cell receive */
2856 +                               skb->len = ATM_AAL0_SDU;
2857 +                               skb->tail = skb->data + skb->len;
2858 +                               break;
2859 +                       case ATM_AAL5:
2860 +                               /* 2.10.1.2 aal5 receive */
2861 +
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) 
2866 +                               {
2867 +                                       skb->ip_summed = CHECKSUM_HW;
2868 +                                       skb->csum = TCP_CKSUM(skb->data,
2869 +                                                       he_vcc->pdu_len);
2870 +                               }
2871 +#endif
2872 +                               break;
2873 +               }
2874 +
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);
2878 +#endif
2879 +
2880 +#ifdef notdef
2881 +               ATM_SKB(skb)->vcc = vcc;
2882 +#endif
2883 +               vcc->push(vcc, skb);
2884 +
2885 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
2886 +               ++vcc->stats->rx;
2887 +#else
2888 +               atomic_inc(&vcc->stats->rx);
2889 +#endif
2890 +
2891 +return_host_buffers:
2892 +               ++pdus_assembled;
2893 +
2894 +               for(iov = he_vcc->iov_head;
2895 +                               iov < he_vcc->iov_tail; ++iov)
2896 +               {
2897 +#ifdef USE_RBPS
2898 +                       if ((u32)iov->iov_base & RBP_SMALLBUF)
2899 +                               rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)];
2900 +                       else
2901 +#endif
2902 +                               rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)];
2903 +
2904 +                       rbp->status &= ~RBP_LOANED;
2905 +               }
2906 +
2907 +               he_vcc->iov_tail = he_vcc->iov_head;
2908 +               he_vcc->pdu_len = 0;
2909 +
2910 +next_rbrq_entry:
2911 +               he_dev->rbrq_head = (struct he_rbrq *)
2912 +                               ((unsigned long) he_dev->rbrq_base |
2913 +                                       RBRQ_MASK(++he_dev->rbrq_head));
2914 +
2915 +       }
2916 +       read_unlock(&vcc_sklist_lock);
2917 +
2918 +       if (updated)
2919 +       {
2920 +               if (updated > he_dev->rbrq_peak) he_dev->rbrq_peak = updated;
2921 +
2922 +               he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head),
2923 +                                               G0_RBRQ_H + (group * 16));
2924 +       }
2925 +
2926 +       return pdus_assembled;
2927 +}
2928 +
2929 +static void
2930 +he_service_tbrq(struct he_dev *he_dev, int group)
2931 +{
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;
2938 +
2939 +       /* 2.1.6 transmit buffer return queue */
2940 +
2941 +       while (he_dev->tbrq_head != tbrq_tail)
2942 +       {
2943 +               ++updated;
2944 +
2945 +               HPRINTK("tbrq%d 0x%x%s%s\n",
2946 +                       group,
2947 +                       TBRQ_TPD(he_dev->tbrq_head), 
2948 +                       TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "",
2949 +                       TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
2950 +
2951 +               tpd = NULL;
2952 +               list = &he_dev->outstanding_tpds;
2953 +               while ((list = list->next) != &he_dev->outstanding_tpds)
2954 +               {
2955 +                       struct he_tpd *_tpd = list_entry(list, struct he_tpd, entry);
2956 +                       if (TPD_ADDR(_tpd->status) == TBRQ_TPD(he_dev->tbrq_head))
2957 +                       {
2958 +                               tpd = _tpd;
2959 +                               list_del(&_tpd->entry);
2960 +                               break;
2961 +                       }
2962 +               }
2963 +
2964 +               if (tpd == NULL)
2965 +               {
2966 +                       hprintk("unable to locate tpd for dma buffer %x\n",
2967 +                                               TBRQ_TPD(he_dev->tbrq_head));
2968 +                       goto next_tbrq_entry;
2969 +               }
2970 +
2971 +               if (TBRQ_EOS(he_dev->tbrq_head))
2972 +               {
2973 +                       HPRINTK("wake_up(tx_waitq) cid 0x%x\n",
2974 +                               he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci));
2975 +                       if (tpd->vcc)
2976 +                               wake_up(&HE_VCC(tpd->vcc)->tx_waitq);
2977 +
2978 +                       goto next_tbrq_entry;
2979 +               }
2980 +
2981 +               for(slot = 0; slot < TPD_MAXIOV; ++slot)
2982 +               {
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;
2989 +                               
2990 +               }
2991 +
2992 +               if (tpd->skb)   /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */
2993 +               {
2994 +                       if (tpd->vcc && tpd->vcc->pop)
2995 +                               tpd->vcc->pop(tpd->vcc, tpd->skb);
2996 +                       else
2997 +                               dev_kfree_skb_any(tpd->skb);
2998 +               }
2999 +
3000 +
3001 +next_tbrq_entry:
3002 +               pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
3003 +
3004 +               he_dev->tbrq_head = (struct he_tbrq *)
3005 +                               ((unsigned long) he_dev->tbrq_base |
3006 +                                       TBRQ_MASK(++he_dev->tbrq_head));
3007 +       }
3008 +
3009 +       if (updated)
3010 +       {
3011 +               if (updated > he_dev->tbrq_peak) he_dev->tbrq_peak = updated;
3012 +
3013 +               he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head),
3014 +                                               G0_TBRQ_H + (group * 16));
3015 +       }
3016 +}
3017 +
3018 +
3019 +static void
3020 +he_service_rbpl(struct he_dev *he_dev, int group)
3021 +{
3022 +       struct he_rbp *newtail;
3023 +       struct he_rbp *rbpl_head;
3024 +       int moved = 0;
3025 +
3026 +       rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
3027 +                                       RBPL_MASK(he_readl(he_dev, G0_RBPL_S)));
3028 +
3029 +       for(;;)
3030 +       {
3031 +               newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
3032 +                                               RBPL_MASK(he_dev->rbpl_tail+1));
3033 +
3034 +               /* table 3.42 -- rbpl_tail should never be set to rbpl_head */
3035 +               if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED))
3036 +                       break;
3037 +
3038 +               newtail->status |= RBP_LOANED;
3039 +               he_dev->rbpl_tail = newtail;
3040 +               ++moved;
3041 +
3042 +       } 
3043 +
3044 +       if (moved)
3045 +               he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
3046 +}
3047 +
3048 +#ifdef USE_RBPS
3049 +static void
3050 +he_service_rbps(struct he_dev *he_dev, int group)
3051 +{
3052 +       struct he_rbp *newtail;
3053 +       struct he_rbp *rbps_head;
3054 +       int moved = 0;
3055 +
3056 +       rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
3057 +                                       RBPS_MASK(he_readl(he_dev, G0_RBPS_S)));
3058 +
3059 +       for(;;)
3060 +       {
3061 +               newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
3062 +                                               RBPS_MASK(he_dev->rbps_tail+1));
3063 +
3064 +               /* table 3.42 -- rbps_tail should never be set to rbps_head */
3065 +               if ((newtail == rbps_head) || (newtail->status & RBP_LOANED))
3066 +                       break;
3067 +
3068 +               newtail->status |= RBP_LOANED;
3069 +               he_dev->rbps_tail = newtail;
3070 +               ++moved;
3071 +
3072 +       } 
3073 +
3074 +       if (moved)
3075 +               he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T);
3076 +}
3077 +#endif /* USE_RBPS */
3078 +
3079 +static void
3080 +he_tasklet(unsigned long data)
3081 +{
3082 +       unsigned long flags;
3083 +       struct he_dev *he_dev = (struct he_dev *) data;
3084 +       int group, type;
3085 +       int updated = 0;
3086 +
3087 +       HPRINTK("tasklet (0x%lx)\n", data);
3088 +#ifdef USE_TASKLET
3089 +       HE_SPIN_LOCK(he_dev, flags);
3090 +#endif
3091 +
3092 +       while(he_dev->irq_head != he_dev->irq_tail)
3093 +       {
3094 +               ++updated;
3095 +
3096 +               type = ITYPE_TYPE(he_dev->irq_head->isw);
3097 +               group = ITYPE_GROUP(he_dev->irq_head->isw);
3098 +
3099 +               switch (type)
3100 +               {
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))
3105 +                               {
3106 +                                       he_service_rbpl(he_dev, group);
3107 +#ifdef USE_RBPS
3108 +                                       he_service_rbps(he_dev, group);
3109 +#endif /* USE_RBPS */
3110 +                               }
3111 +                               break;
3112 +                       case ITYPE_TBRQ_THRESH:
3113 +                               hprintk("tbrq%d threshold\n", group);
3114 +                       case ITYPE_TPD_COMPLETE:
3115 +                               he_service_tbrq(he_dev, group);
3116 +                               break;
3117 +                       case ITYPE_RBPL_THRESH:
3118 +                               he_service_rbpl(he_dev, group);
3119 +                               break;
3120 +                       case ITYPE_RBPS_THRESH:
3121 +#ifdef USE_RBPS
3122 +                               he_service_rbps(he_dev, group);
3123 +#endif /* USE_RBPS */
3124 +                               break;
3125 +                       case ITYPE_PHY:
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);
3129 +#endif
3130 +                               HPRINTK1("phy interrupt\n");
3131 +                               break;
3132 +                       case ITYPE_OTHER:
3133 +                               switch (type|group)
3134 +                               {
3135 +                                       case ITYPE_PARITY:
3136 +                                               hprintk1("parity error\n");
3137 +                                               break;
3138 +                                       case ITYPE_ABORT:
3139 +                                               hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR));
3140 +                                               break;
3141 +                               }
3142 +                               break;
3143 +                       default:
3144 +                               if (he_dev->irq_head->isw == ITYPE_INVALID)
3145 +                               {
3146 +                                       /* see 8.1.1 -- check all queues */
3147 +
3148 +                                       HPRINTK("isw not updated 0x%x\n",
3149 +                                               he_dev->irq_head->isw);
3150 +
3151 +                                       he_service_rbrq(he_dev, 0);
3152 +                                       he_service_rbpl(he_dev, 0);
3153 +#ifdef USE_RBPS
3154 +                                       he_service_rbps(he_dev, 0);
3155 +#endif /* USE_RBPS */
3156 +                                       he_service_tbrq(he_dev, 0);
3157 +                               }
3158 +                               else
3159 +                                       hprintk("bad isw = 0x%x?\n",
3160 +                                               he_dev->irq_head->isw);
3161 +               }
3162 +
3163 +               he_dev->irq_head->isw = ITYPE_INVALID;
3164 +
3165 +               he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK);
3166 +       }
3167 +
3168 +       if (updated)
3169 +       {
3170 +               if (updated > he_dev->irq_peak) he_dev->irq_peak = updated;
3171 +
3172 +               he_writel(he_dev,
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 */
3177 +       }
3178 +#ifdef USE_TASKLET
3179 +       HE_SPIN_UNLOCK(he_dev, flags);
3180 +#endif
3181 +}
3182 +
3183 +static void
3184 +he_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
3185 +{
3186 +       unsigned long flags;
3187 +       struct he_dev *he_dev = (struct he_dev * )dev_id;
3188 +
3189 +       if (he_dev == NULL) return;
3190 +
3191 +       HE_SPIN_LOCK(he_dev, flags);
3192 +
3193 +       he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) |
3194 +                                               (*he_dev->irq_tailoffset << 2));
3195 +
3196 +       if (he_dev->irq_tail == he_dev->irq_head)
3197 +       {
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 */
3202 +       }
3203 +
3204 +#ifdef notdef
3205 +       if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */)
3206 +               hprintk1("spurious interrupt?\n");
3207 +#endif
3208 +
3209 +       if (he_dev->irq_head != he_dev->irq_tail)
3210 +       {
3211 +#ifdef USE_TASKLET
3212 +               tasklet_schedule(&he_dev->tasklet);
3213 +#else
3214 +               he_tasklet((unsigned long) he_dev);
3215 +#endif
3216 +               he_writel(he_dev, INT_CLEAR_A, INT_FIFO);
3217 +                                                       /* clear interrupt */
3218 +       }
3219 +
3220 +       HE_SPIN_UNLOCK(he_dev, flags);
3221 +}
3222 +
3223 +static __inline__ void
3224 +he_enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
3225 +{
3226 +       struct he_tpdrq *new_tail;
3227 +       unsigned flags;
3228 +
3229 +       spin_lock_irqsave(&he_dev->tpdrq_lock, flags);
3230 +
3231 +       HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n",
3232 +                                       tpd, cid, he_dev->tpdrq_tail);
3233 +
3234 +       new_tail = he_dev->tpdrq_tail;
3235 +       new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base |
3236 +                                       TPDRQ_MASK(++new_tail));
3237 +
3238 +       /*
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)
3243 +        */
3244 +
3245 +       if (new_tail == he_dev->tpdrq_head)
3246 +       {
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)));
3250 +
3251 +               if (new_tail == he_dev->tpdrq_head)
3252 +               {
3253 +                       hprintk("tpdrq full (cid 0x%x)\n", cid);
3254 +                       /*
3255 +                        * FIXME
3256 +                        * push tpd onto a transmit backlog queue
3257 +                        * after service_tbrq, service the backlog
3258 +                        * for now, we just drop the pdu
3259 +                        */
3260 +                       if (tpd->skb)
3261 +                       {
3262 +                               if (tpd->vcc->pop)
3263 +                                       tpd->vcc->pop(tpd->vcc, tpd->skb);
3264 +                               else
3265 +                                       dev_kfree_skb_any(tpd->skb);
3266 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3267 +                               ++tpd->vcc->stats->tx_err;
3268 +#else
3269 +                               atomic_inc(&tpd->vcc->stats->tx_err);
3270 +#endif
3271 +                       }
3272 +                       pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
3273 +                       spin_unlock_irqrestore(&he_dev->tpdrq_lock, flags);
3274 +                       return;
3275 +               }
3276 +       }
3277 +
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;
3281 +       mb();
3282 +       list_add_tail(&tpd->entry, &he_dev->outstanding_tpds);
3283 +
3284 +       he_dev->tpdrq_tail = new_tail;
3285 +
3286 +       he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T);
3287 +       spin_unlock_irqrestore(&he_dev->tpdrq_lock, flags);
3288 +}
3289 +
3290 +static int
3291 +he_open(struct atm_vcc *vcc, short vpi, int vci)
3292 +{
3293 +       unsigned long flags;
3294 +       struct he_dev *he_dev = HE_DEV(vcc->dev);
3295 +       struct he_vcc *he_vcc;
3296 +       int err = 0;
3297 +       unsigned cid, rsr0, rsr1, rsr4, tsr0, period, reg, clock;
3298 +       int first_open = 0;
3299 +
3300 +       if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0;
3301 +       vcc->vpi = vpi;
3302 +       vcc->vci = vci;
3303 +
3304 +       HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci);
3305 +
3306 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3307 +       vcc->flags |= ATM_VF_ADDR;
3308 +#else
3309 +       set_bit(ATM_VF_ADDR, &vcc->flags);
3310 +#endif
3311 +
3312 +       cid = he_mkcid(he_dev, vpi, vci);
3313 +
3314 +       he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_KERNEL);
3315 +       if (he_vcc == NULL)
3316 +       {
3317 +               hprintk1("unable to allocate he_vcc during open\n");
3318 +               return -ENOMEM;
3319 +       }
3320 +
3321 +       he_vcc->iov_tail = he_vcc->iov_head;
3322 +       he_vcc->pdu_len = 0;
3323 +       he_vcc->rc_index = -1;
3324 +
3325 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3326 +       init_waitqueue(&he_vcc->rx_waitq);
3327 +       init_waitqueue(&he_vcc->tx_waitq);
3328 +#else
3329 +       init_waitqueue_head(&he_vcc->rx_waitq);
3330 +       init_waitqueue_head(&he_vcc->tx_waitq);
3331 +#endif
3332 +
3333 +       HE_VCC(vcc) = he_vcc;
3334 +
3335 +       if (vcc->qos.txtp.traffic_class != ATM_NONE)
3336 +       {
3337 +               int pcr_goal;
3338 +
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;
3344 +
3345 +               HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal);
3346 +
3347 +               /* no transmit support for AAL0 -- FIXME */
3348 +
3349 +               if (vcc->qos.aal != ATM_AAL5)
3350 +               {
3351 +                       err = -EINVAL;
3352 +                       goto open_failed;
3353 +               }
3354 +
3355 +               HE_SPIN_LOCK(he_dev, flags);
3356 +               tsr0 = he_readl_tsr0(he_dev, cid);
3357 +               HE_SPIN_UNLOCK(he_dev, flags);
3358 +
3359 +               if (tsr0 == 0 && vcc->qos.aal == ATM_AAL5) first_open = 1;
3360 +
3361 +               if (TSR0_CONN_STATE(tsr0) != 0)
3362 +               {
3363 +                       hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0);
3364 +#ifdef notdef
3365 +                       err = -EBUSY;
3366 +                       goto open_failed;
3367 +#endif
3368 +               }
3369 +
3370 +               switch(vcc->qos.txtp.traffic_class)
3371 +               {
3372 +                       case ATM_UBR:
3373 +                               /* 2.3.3.1 open connection ubr */
3374 +
3375 +                               tsr0 = TSR0_UBR | TSR0_GROUP(0) | TSR0_AAL5 |
3376 +                                       TSR0_USE_WMIN | TSR0_UPDATE_GER;
3377 +                               break;
3378 +
3379 +                       case ATM_CBR:
3380 +                               /* 2.3.3.2 open connection cbr */
3381 +
3382 +                               clock = he_is622(he_dev) ? 66667000 : 50000000;
3383 +                               period = clock / pcr_goal;
3384 +                               
3385 +                               /* find an unused cs_stper register */
3386 +
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)
3390 +                                       break;
3391 +
3392 +                               if (reg == HE_NUM_CS_STPER)
3393 +                               {
3394 +                                       err = -EBUSY;
3395 +                                       goto open_failed;
3396 +                               }
3397 +
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))
3401 +                               {
3402 +                                       err = -EBUSY;
3403 +                                       goto open_failed;
3404 +                               }
3405 +                               he_dev->total_bw += pcr_goal;
3406 +
3407 +                               he_vcc->rc_index = reg;
3408 +                               ++he_dev->cs_stper[reg].inuse;
3409 +                               he_dev->cs_stper[reg].pcr = pcr_goal;
3410 +
3411 +                               HPRINTK("rc_index = %d period = %d\n",
3412 +                                                               reg, period);
3413 +
3414 +                               HE_SPIN_LOCK(he_dev, flags);
3415 +                               he_writel_mbox(he_dev, rate_to_atmf(period/2),
3416 +                                                       CS_STPER0 + reg);
3417 +                               HE_SPIN_UNLOCK(he_dev, flags);
3418 +
3419 +                               tsr0 = TSR0_CBR | TSR0_GROUP(0) | TSR0_AAL5 |
3420 +                                                       TSR0_RC_INDEX(reg);
3421 +
3422 +                               break;
3423 +                       default:
3424 +                               err = -EINVAL;
3425 +                               goto open_failed;
3426 +               }
3427 +
3428 +               HE_SPIN_LOCK(he_dev, flags);
3429 +
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);
3436 +
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);
3447 +
3448 +               /* work around:
3449 +                *
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
3453 +                * a reset.
3454 +                */
3455 +                   
3456 +               if (first_open)
3457 +               {
3458 +#define BADCRCMESG "BAD CRC WORKAROUND"
3459 +                       static char *badcrc = NULL;
3460 +                       struct he_tpd *tpd;
3461 +
3462 +                       tpd = he_alloc_tpd(he_dev);
3463
3464 +                       if (!badcrc)
3465 +                       { 
3466 +                               badcrc = kmalloc(strlen(BADCRCMESG), GFP_DMA);
3467 +                               memcpy(badcrc, BADCRCMESG, strlen(BADCRCMESG));
3468 +                       } 
3469 +
3470 +                        HPRINTK("bad crc workaround cid = 0x%x\n", cid);
3471 +
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;
3476 +                       mb();
3477 +                       tpd->skb = NULL;
3478 +                       tpd->vcc = vcc;
3479 +
3480 +                       he_enqueue_tpd(he_dev, tpd, cid);
3481 +               }
3482 +
3483 +               HE_SPIN_UNLOCK(he_dev, flags);
3484 +       }
3485 +
3486 +       if (vcc->qos.rxtp.traffic_class != ATM_NONE)
3487 +       {
3488 +               unsigned aal;
3489 +
3490 +               HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid,
3491 +                                               &HE_VCC(vcc)->rx_waitq);
3492 +
3493 +               switch (vcc->qos.aal)
3494 +               {
3495 +                       case ATM_AAL5:
3496 +                               aal = RSR0_AAL5;
3497 +                               break;
3498 +                       case ATM_AAL0:
3499 +                               aal = RSR0_RAWCELL;
3500 +                               break;
3501 +                       default:
3502 +                               err = -EINVAL;
3503 +                               goto open_failed;
3504 +               }
3505 +
3506 +               HE_SPIN_LOCK(he_dev, flags);
3507 +
3508 +               rsr0 = he_readl_rsr0(he_dev, cid);
3509 +               if (rsr0 & RSR0_OPEN_CONN)
3510 +               {
3511 +                       HE_SPIN_UNLOCK(he_dev, flags);
3512 +
3513 +                       hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0);
3514 +                       err = -EBUSY;
3515 +                       goto open_failed;
3516 +               }
3517 +
3518 +#ifdef USE_RBPS
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;
3527 +
3528 +#ifdef USE_CHECKSUM_HW
3529 +               if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) rsr0 |= RSR0_TCP_CKSUM;
3530 +#endif
3531 +
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);
3538 +
3539 +               HE_SPIN_UNLOCK(he_dev, flags);
3540 +
3541 +#ifndef USE_HE_FIND_VCC
3542 +               HE_LOOKUP_VCC(he_dev, cid) = vcc;
3543 +#endif
3544 +       }
3545 +
3546 +open_failed:
3547 +
3548 +       if (err)
3549 +       {
3550 +               if (he_vcc) kfree(he_vcc);
3551 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3552 +               vcc->flags &= ~ATM_VF_ADDR;
3553 +#else
3554 +               clear_bit(ATM_VF_ADDR, &vcc->flags);
3555 +#endif
3556 +       }
3557 +       else
3558 +       {
3559 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3560 +               vcc->flags |= ATM_VF_READY;
3561 +#else
3562 +               set_bit(ATM_VF_READY, &vcc->flags);
3563 +#endif
3564 +       }
3565 +
3566 +       return err;
3567 +}
3568 +
3569 +static void
3570 +he_close(struct atm_vcc *vcc)
3571 +{
3572 +       unsigned long flags;
3573 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
3574 +       DECLARE_WAITQUEUE(wait, current);
3575 +#else
3576 +       struct wait_queue wait = { current, NULL };
3577 +#endif
3578 +       struct he_dev *he_dev = HE_DEV(vcc->dev);
3579 +       struct he_tpd *tpd;
3580 +       unsigned cid;
3581 +       struct he_vcc *he_vcc = HE_VCC(vcc);
3582 +#define MAX_RETRY 30
3583 +       int retry = 0, sleep = 1, tx_inuse;
3584 +
3585 +       HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci);
3586 +
3587 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3588 +       vcc->flags &= ~ATM_VF_READY;
3589 +#else
3590 +       clear_bit(ATM_VF_READY, &vcc->flags);
3591 +#endif
3592 +       cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
3593 +
3594 +       HE_SPIN_LOCK(he_dev, flags);
3595 +
3596 +       if (vcc->qos.rxtp.traffic_class != ATM_NONE)
3597 +       {
3598 +               int timeout;
3599 +
3600 +               HPRINTK("close rx cid 0x%x\n", cid);
3601 +
3602 +               /* 2.7.2.2 close receive operation */
3603 +
3604 +               /* wait for previous close (if any) to finish */
3605 +
3606 +               while(he_readl(he_dev, RCC_STAT) & RCC_BUSY)
3607 +               {
3608 +                       HPRINTK("close cid 0x%x RCC_BUSY\n", cid);
3609 +                       udelay(250);
3610 +               }
3611 +
3612 +               add_wait_queue(&he_vcc->rx_waitq, &wait);
3613 +               set_current_state(TASK_UNINTERRUPTIBLE);
3614 +
3615 +               he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid);
3616 +               he_writel_mbox(he_dev, cid, RXCON_CLOSE);
3617 +
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);
3623 +
3624 +               if (timeout == 0)
3625 +                       hprintk("close rx timeout cid 0x%x\n", cid);
3626 +
3627 +#ifndef USE_HE_FIND_VCC
3628 +               HE_LOOKUP_VCC(he_dev, cid) = NULL;
3629 +#endif
3630 +               HPRINTK("close rx cid 0x%x complete\n", cid);
3631 +
3632 +       }
3633 +
3634 +       if (vcc->qos.txtp.traffic_class != ATM_NONE)
3635 +       {
3636 +               volatile unsigned tsr4, tsr0;
3637 +               int timeout;
3638 +
3639 +               HPRINTK("close tx cid 0x%x\n", cid);
3640 +               
3641 +               /* 2.1.2
3642 +                *
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.
3648 +                */
3649 +
3650 +               HE_SPIN_UNLOCK(he_dev, flags);
3651 +               while (((tx_inuse = atomic_read(&vcc->sk->wmem_alloc)) > 0)
3652 +                                                       && (retry < MAX_RETRY))
3653 +               {
3654 +                       set_current_state(TASK_UNINTERRUPTIBLE);
3655 +                       (void) schedule_timeout(sleep);
3656 +                       set_current_state(TASK_RUNNING);
3657 +                       if (sleep < HZ) sleep = sleep * 2;
3658 +
3659 +                       ++retry;
3660 +               }
3661 +
3662 +               if (tx_inuse) hprintk("close tx cid 0x%x tx_inuse = %d\n",
3663 +                                                               cid, tx_inuse);
3664 +               HE_SPIN_LOCK(he_dev, flags);
3665 +
3666 +               /* 2.3.1.1 generic close operations with flush */
3667 +
3668 +               he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid);
3669 +                                       /* also clears TSR4_SESSION_ENDED */
3670 +
3671 +               switch(vcc->qos.txtp.traffic_class)
3672 +               {
3673 +                       case ATM_UBR:
3674 +                               he_writel_tsr1(he_dev, 
3675 +                                       TSR1_MCR(rate_to_atmf(200000))
3676 +                                       | TSR1_PCR(0), cid);
3677 +                               break;
3678 +                       case ATM_CBR:
3679 +                               he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid);
3680 +                               break;
3681 +               }
3682 +
3683 +
3684 +               tpd = he_alloc_tpd(he_dev);
3685 +               if (tpd == NULL)
3686 +               {
3687 +                       hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid);
3688 +                       goto close_tx_incomplete;
3689 +               }
3690 +               tpd->status |= TPD_EOS | TPD_INT;
3691 +               tpd->skb = NULL;
3692 +               tpd->vcc = vcc;
3693 +               mb();
3694 +
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);
3703 +
3704 +               if (timeout == 0)
3705 +               {
3706 +                       hprintk("close tx timeout cid 0x%x\n", cid);
3707 +                       goto close_tx_incomplete;
3708 +               }
3709 +
3710 +               while (!((tsr4 = he_readl_tsr4(he_dev, cid))
3711 +                                                       & TSR4_SESSION_ENDED))
3712 +               {
3713 +                       HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4);
3714 +                       udelay(250);
3715 +               }
3716 +
3717 +               while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0)
3718 +               {
3719 +                       HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0);
3720 +                       udelay(250);
3721 +               }
3722 +
3723 +close_tx_incomplete:
3724 +
3725 +               if (vcc->qos.txtp.traffic_class == ATM_CBR)
3726 +               {
3727 +                       int reg = he_vcc->rc_index;
3728 +
3729 +                       HPRINTK("cs_stper reg = %d\n", reg);
3730 +
3731 +                       if (he_dev->cs_stper[reg].inuse == 0)
3732 +                               hprintk("cs_stper[%d].inuse = 0!\n", reg);
3733 +                       else
3734 +                               --he_dev->cs_stper[reg].inuse;
3735 +
3736 +                       he_dev->total_bw -= he_dev->cs_stper[reg].pcr;
3737 +               }
3738 +
3739 +               HPRINTK("close tx cid 0x%x complete\n", cid);
3740 +       }
3741 +
3742 +       kfree(he_vcc);
3743 +       HE_SPIN_UNLOCK(he_dev, flags);
3744 +
3745 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
3746 +       vcc->flags &= ~ATM_VF_ADDR;
3747 +#else
3748 +       clear_bit(ATM_VF_ADDR, &vcc->flags);
3749 +#endif
3750 +}
3751 +
3752 +static int
3753 +he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size)
3754 +{
3755 +#ifdef USE_SCATTERGATHER
3756 +       return 1;
3757 +#else
3758 +       return 0;
3759 +#endif
3760 +}
3761 +
3762 +static int
3763 +he_send(struct atm_vcc *vcc, struct sk_buff *skb)
3764 +{
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
3770 +       int i, slot = 0;
3771 +#endif
3772 +
3773 +#define HE_TPD_BUFSIZE 0xffff
3774 +
3775 +       HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci);
3776 +
3777 +       if (skb->len > HE_TPD_BUFSIZE )
3778 +       {
3779 +               hprintk("buffer too large (%d bytes)\n", skb->len );
3780 +               if (vcc->pop)
3781 +                       vcc->pop(vcc, skb);
3782 +               else
3783 +                       dev_kfree_skb_any(skb);
3784 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3785 +               ++vcc->stats->tx_err;
3786 +#else
3787 +               atomic_inc(&vcc->stats->tx_err);
3788 +#endif
3789 +               return -EINVAL;
3790 +       }
3791 +
3792 +#ifndef USE_SCATTERGATHER
3793 +       if (skb_shinfo(skb)->nr_frags)
3794 +       {
3795 +               hprintk1("no scatter/gather support\n");
3796 +               if (vcc->pop)
3797 +                       vcc->pop(vcc, skb);
3798 +               else
3799 +                       dev_kfree_skb_any(skb);
3800 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3801 +               ++vcc->stats->tx_err;
3802 +#else
3803 +               atomic_inc(&vcc->stats->tx_err);
3804 +#endif
3805 +               return -EINVAL;
3806 +       }
3807 +#endif
3808 +
3809 +       tpd = he_alloc_tpd(he_dev);
3810 +       if (tpd == NULL)
3811 +       {
3812 +               if (vcc->pop)
3813 +                       vcc->pop(vcc, skb);
3814 +               else
3815 +                       dev_kfree_skb_any(skb);
3816 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3817 +               ++vcc->stats->tx_err;
3818 +#else
3819 +               atomic_inc(&vcc->stats->tx_err);
3820 +#endif
3821 +               return -ENOMEM;
3822 +       }
3823 +       tpd->status |= TPD_USERCELL;
3824 +
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;
3829 +       ++slot;
3830 +
3831 +       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
3832 +       {
3833 +               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
3834 +
3835 +               if (slot == TPD_MAXIOV)         /* send tpd; start new tpd */
3836 +               {
3837 +                       tpd->vcc = vcc;
3838 +                       tpd->skb = NULL;        /* not the last fragment
3839 +                                                  so dont ->push() yet */
3840 +                       mb();
3841 +
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);
3846 +                       if (tpd == NULL)
3847 +                       {
3848 +                               if (vcc->pop)
3849 +                                       vcc->pop(vcc, skb);
3850 +                               else
3851 +                                       dev_kfree_skb_any(skb);
3852 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3853 +                               ++vcc->stats->tx_err;
3854 +#else
3855 +                               atomic_inc(&vcc->stats->tx_err);
3856 +#endif
3857 +                               return -ENOMEM;
3858 +                       }
3859 +                       tpd->status |= TPD_USERCELL;
3860 +                       slot = 0;
3861 +               }
3862 +
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;
3867 +               ++slot;
3868 +
3869 +       }
3870 +
3871 +       tpd->iovec[slot-1].len |= TPD_LST;
3872 +#else
3873 +       tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
3874 +       tpd->length0 = skb->len | TPD_LST;
3875 +#endif
3876 +       tpd->status |= TPD_INT;
3877 +
3878 +       tpd->vcc = vcc;
3879 +       tpd->skb = skb;
3880 +       mb();
3881 +       ATM_SKB(skb)->vcc = vcc;
3882 +
3883 +       HE_SPIN_LOCK(he_dev, flags);
3884 +       he_enqueue_tpd(he_dev, tpd, cid);
3885 +       HE_SPIN_UNLOCK(he_dev, flags);
3886 +
3887 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
3888 +       ++vcc->stats->tx;
3889 +#else
3890 +       atomic_inc(&vcc->stats->tx);
3891 +#endif
3892 +
3893 +       return 0;
3894 +}
3895 +
3896 +static int
3897 +he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void *arg)
3898 +{
3899 +       unsigned long flags;
3900 +       struct he_dev *he_dev = HE_DEV(atm_dev);
3901 +       struct he_ioctl_reg reg;
3902 +       int err = 0;
3903 +
3904 +       switch (cmd)
3905 +       {
3906 +               case HE_GET_REG:
3907 +                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
3908 +
3909 +                       copy_from_user(&reg, (struct he_ioctl_reg *) arg,
3910 +                                               sizeof(struct he_ioctl_reg));
3911 +                       HE_SPIN_LOCK(he_dev, flags);
3912 +                       switch (reg.type)
3913 +                       {
3914 +                               case HE_REGTYPE_PCI:
3915 +                                       reg.val = he_readl(he_dev, reg.addr);
3916 +                                       break;
3917 +                               case HE_REGTYPE_RCM:
3918 +                                       reg.val =
3919 +                                               he_readl_rcm(he_dev, reg.addr);
3920 +                                       break;
3921 +                               case HE_REGTYPE_TCM:
3922 +                                       reg.val =
3923 +                                               he_readl_tcm(he_dev, reg.addr);
3924 +                                       break;
3925 +                               case HE_REGTYPE_MBOX:
3926 +                                       reg.val =
3927 +                                               he_readl_mbox(he_dev, reg.addr);
3928 +                                       break;
3929 +                               default:
3930 +                                       HE_SPIN_UNLOCK(he_dev, flags);
3931 +                                       return -EINVAL;
3932 +                       }
3933 +                       HE_SPIN_UNLOCK(he_dev, flags);
3934 +                       copy_to_user((struct he_ioctl_reg *) arg, &reg,
3935 +                                               sizeof(struct he_ioctl_reg));
3936 +                       break;
3937 +               default:
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 */
3944 +                       return -EINVAL;
3945 +#endif /* CONFIG_ATM_HE_USE_SUNI */
3946 +                       break;
3947 +       }
3948 +
3949 +       return err;
3950 +}
3951 +
3952 +static void
3953 +he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr)
3954 +{
3955 +       struct he_dev *he_dev = HE_DEV(atm_dev);
3956 +
3957 +       HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr);
3958 +
3959 +        he_writel(he_dev, val, FRAMER + (addr*4));
3960 +}
3961
3962 +        
3963 +static unsigned char
3964 +he_phy_get(struct atm_dev *atm_dev, unsigned long addr)
3965 +{ 
3966 +       struct he_dev *he_dev = HE_DEV(atm_dev);
3967 +       unsigned reg;
3968 +
3969 +        reg = he_readl(he_dev, FRAMER + (addr*4));
3970 +
3971 +       HPRINTK("phy_get(addr 0x%lx) =0x%lx\n", addr, reg);
3972 +       return reg;
3973 +}
3974 +
3975 +static int
3976 +he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
3977 +{
3978 +       unsigned long flags;
3979 +       struct he_dev *he_dev = HE_DEV(dev);
3980 +       int left, i;
3981 +#ifdef notdef
3982 +       struct he_rbrq *rbrq_tail;
3983 +       struct he_tpdrq *tpdrq_head;
3984 +        int rbpl_head, rbpl_tail;
3985 +#endif
3986 +       static long mcc = 0, oec = 0, dcc = 0, cec = 0;
3987 +
3988 +
3989 +       left = *pos;
3990 +       if (!left--)
3991 +               return sprintf(page, "%s\n", version);
3992 +
3993 +       if (!left--)
3994 +               return sprintf(page, "%s%s\n\n",
3995 +                       he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM");
3996 +
3997 +       if (!left--)
3998 +               return sprintf(page, "Mismatched Cells  VPI/VCI Not Open  Dropped Cells  RCM Dropped Cells\n");
3999 +
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);
4006 +
4007 +       if (!left--)
4008 +               return sprintf(page, "%16ld  %16ld  %13ld  %17ld\n\n", 
4009 +                                                       mcc, oec, dcc, cec);
4010 +
4011 +       if (!left--)
4012 +               return sprintf(page, "irq_size = %d  inuse = ?  peak = %d\n",
4013 +                               CONFIG_IRQ_SIZE, he_dev->irq_peak);
4014 +
4015 +       if (!left--)
4016 +               return sprintf(page, "tpdrq_size = %d  inuse = ?\n",
4017 +                                               CONFIG_TPDRQ_SIZE);
4018 +
4019 +       if (!left--)
4020 +               return sprintf(page, "rbrq_size = %d  inuse = ?  peak = %d\n",
4021 +                               CONFIG_RBRQ_SIZE, he_dev->rbrq_peak);
4022 +
4023 +       if (!left--)
4024 +               return sprintf(page, "tbrq_size = %d  peak = %d\n",
4025 +                                       CONFIG_TBRQ_SIZE, he_dev->tbrq_peak);
4026 +
4027 +
4028 +#ifdef notdef
4029 +        rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S));
4030 +        rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T));
4031 +
4032 +       inuse = rbpl_head - rbpl_tail;
4033 +       if (inuse < 0) inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp);
4034 +       inuse /= sizeof(struct he_rbp);
4035 +
4036 +       if (!left--)
4037 +               return sprintf(page, "rbpl_size = %d  inuse = %d\n\n",
4038 +                                               CONFIG_RBPL_SIZE, inuse);
4039 +#endif
4040 +
4041 +       if (!left--)
4042 +               return sprintf(page, "rate controller periods (cbr)\n                 pcr  #vc\n");
4043 +
4044 +       for (i = 0; i < HE_NUM_CS_STPER; ++i)
4045 +               if (!left--)
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);
4049 +
4050 +       if (!left--)
4051 +               return sprintf(page, "total bw (cbr): %d  (limit %d)\n",
4052 +                       he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9);
4053 +
4054 +       return 0;
4055 +}
4056 +
4057 +/* eeprom routines  -- see 4.7 */
4058 +
4059 +u8
4060 +read_prom_byte(struct he_dev *he_dev, int addr)
4061 +{
4062 +       u32 val = 0, tmp_read = 0;
4063 +       int i, j = 0;
4064 +       u8 byte_read = 0;
4065 +
4066 +       val = readl(he_dev->membase + HOST_CNTL);
4067 +       val &= 0xFFFFE0FF;
4068 +       
4069 +       /* Turn on write enable */
4070 +       val |= 0x800;
4071 +       writel(val, he_dev->membase + HOST_CNTL);
4072 +       
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);
4077 +       }
4078 +       
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);
4087 +       }
4088 +       
4089 +       j=0;
4090 +
4091 +       val &= 0xFFFFF7FF;      /* Turn off write enable */
4092 +       writel(val, he_dev->membase + HOST_CNTL);
4093 +       
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);
4105 +       }
4106 +       
4107 +       writel(val | clocktab[j++], he_dev->membase + HOST_CNTL);
4108 +       udelay(EEPROM_DELAY);
4109 +
4110 +        return (byte_read);
4111 +}
4112 +
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)");
4127 +
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,
4131 +         0, 0, 0 },
4132 +        { 0, }
4133 +};
4134 +
4135 +static struct pci_driver he_driver = {
4136 +       .name =         "he",
4137 +       .probe =        he_init_one,
4138 +       .remove =       __devexit_p(he_remove_one),
4139 +       .id_table =     he_pci_tbl,
4140 +};
4141 +
4142 +static int __init he_init(void)
4143 +{
4144 +        return pci_module_init(&he_driver);
4145 +}
4146 +
4147 +static void __exit he_cleanup(void)
4148 +{
4149 +        pci_unregister_driver(&he_driver);
4150 +}
4151 +
4152 +module_init(he_init);
4153 +module_exit(he_cleanup);
4154 +#else
4155 +static int __init
4156 +he_init()
4157 +{
4158 +       if (!pci_present())
4159 +               return -EIO;
4160 +
4161 +#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
4162 +       /* request_module("suni"); */
4163 +#endif
4164 +
4165 +       pci_dev = NULL;
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)
4169 +                       ++ndevs;
4170 +
4171 +       return (ndevs ? 0 : -ENODEV);
4172 +}
4173 +
4174 +static void __devexit
4175 +he_cleanup(void)
4176 +{
4177 +       while (he_devs)
4178 +       {
4179 +               struct he_dev *next = he_devs->next;
4180 +               he_stop(he_devs);
4181 +               atm_dev_deregister(he_devs->atm_dev);
4182 +               kfree(he_devs);
4183 +
4184 +               he_devs = next;
4185 +       }
4186 +
4187 +}
4188 +
4189 +int init_module(void)
4190 +{
4191 +       return he_init();
4192 +}
4193 +
4194 +void cleanup_module(void)
4195 +{
4196 +       he_cleanup();
4197 +}
4198 +#endif
4199 +
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
4204 @@ -0,0 +1,910 @@
4205 +/* $Id$ */
4206 +
4207 +/*
4208 +
4209 +  he.h
4210 +
4211 +  ForeRunnerHE ATM Adapter driver for ATM on Linux
4212 +  Copyright (C) 1999-2001  Naval Research Laboratory
4213 +
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.
4218 +
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.
4223 +
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
4227 +
4228 +*/
4229 +
4230 +/*
4231 +
4232 +  he.h
4233 +
4234 +  ForeRunnerHE ATM Adapter driver for ATM on Linux
4235 +  Copyright (C) 1999-2000  Naval Research Laboratory
4236 +
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.
4242 +
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.
4246 +
4247 + */
4248 +
4249 +#ifndef _HE_H_
4250 +#define _HE_H_
4251 +
4252 +#define DEV_LABEL       "he"
4253 +
4254 +#define CONFIG_DEFAULT_VCIBITS 12
4255 +#define CONFIG_DEFAULT_VPIBITS 0
4256 +
4257 +#define CONFIG_IRQ_SIZE                128
4258 +#define CONFIG_IRQ_THRESH      (CONFIG_IRQ_SIZE/2)
4259 +
4260 +#define CONFIG_TPDRQ_SIZE      512
4261 +#define TPDRQ_MASK(x)          (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1))
4262 +
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))
4266 +
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))
4270 +
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))
4275 +
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))
4280 +
4281 +/* 5.1.3 initialize connection memory */
4282 +
4283 +#define CONFIG_RSRA            0x00000
4284 +#define CONFIG_RCMLBM          0x08000
4285 +#define CONFIG_RCMABR          0x0d800
4286 +#define CONFIG_RSRB            0x0e000
4287 +
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
4294 +
4295 +#define HE_MAXCIDBITS          12
4296 +
4297 +/* 2.9.3.3 interrupt encodings */
4298 +
4299 +struct he_irq {
4300 +       volatile u32 isw;
4301 +};
4302 +
4303 +#define IRQ_ALIGNMENT          0x1000
4304 +
4305 +#define NEXT_ENTRY(base, tail, mask) \
4306 +                               (((unsigned long)base)|(((unsigned long)(tail+1))&mask))
4307 +
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
4319 +
4320 +#define ITYPE_GROUP(x)         (x & 0x7)
4321 +#define ITYPE_TYPE(x)          (x & 0xf8)
4322 +
4323 +#define HE_NUM_GROUPS 8
4324 +
4325 +/* 2.1.4 transmit packet descriptor */
4326 +
4327 +struct he_tpd {
4328 +
4329 +       /* read by the adapter */
4330 +
4331 +       volatile u32 status;
4332 +       volatile u32 reserved;
4333 +
4334 +#define TPD_MAXIOV     3
4335 +       struct {
4336 +               u32 addr, len;
4337 +       } iovec[TPD_MAXIOV];
4338 +
4339 +
4340 +#define address0 iovec[0].addr
4341 +#define length0 iovec[0].len
4342 +
4343 +       /* linux-atm extensions */
4344 +
4345 +       struct sk_buff *skb;
4346 +       struct atm_vcc *vcc;
4347 +
4348 +       struct list_head entry;
4349 +};
4350 +
4351 +#define TPD_ALIGNMENT  64
4352 +#define TPD_LEN_MASK   0xffff
4353 +
4354 +#define TPD_ADDR(x)    ((x) & 0xffffffc0)
4355 +
4356 +
4357 +/* table 2.3 transmit buffer return elements */
4358 +
4359 +struct he_tbrq {
4360 +       volatile u32 tbre;
4361 +};
4362 +
4363 +#define TBRQ_ALIGNMENT CONFIG_TBRQ_SIZE
4364 +
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))
4368 +
4369 +/* table 2.21 receive buffer return queue element field organization */
4370 +
4371 +struct he_rbrq {
4372 +       volatile u32 addr;
4373 +       volatile u32 cidlen;
4374 +};
4375 +
4376 +#define RBRQ_ALIGNMENT CONFIG_RBRQ_SIZE
4377 +
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)
4387 +
4388 +/* figure 2.3 transmit packet descriptor ready queue */
4389 +
4390 +struct he_tpdrq {
4391 +       volatile u32 tpd;
4392 +       volatile u32 cid;
4393 +};
4394 +
4395 +#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE
4396 +
4397 +/* table 2.30 host status page detail */
4398 +
4399 +#define HSP_ALIGNMENT  0x400           /* must align on 1k boundary */
4400 +
4401 +struct he_hsp {
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];
4408 +};
4409 +
4410 +/* figure 2.9 receive buffer pools */
4411 +
4412 +struct he_rbp {
4413 +       volatile u32 phys;
4414 +       volatile u32 status;
4415 +};
4416 +
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.
4421 +*/
4422 +
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
4427 +
4428 +struct he_virt {
4429 +       void *virt;
4430 +};
4431 +
4432 +#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE
4433 +#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE
4434 +
4435 +#ifdef notyet
4436 +struct he_group {
4437 +       u32 rpbs_size, rpbs_qsize;
4438 +       struct he_rbp rbps_ba;
4439 +
4440 +       u32 rpbl_size, rpbl_qsize;
4441 +       struct he_rpb_entry *rbpl_ba;
4442 +};
4443 +#endif
4444 +
4445 +#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc)
4446 +
4447 +struct he_vcc_table 
4448 +{
4449 +       struct atm_vcc *vcc;
4450 +};
4451 +
4452 +struct he_cs_stper
4453 +{
4454 +       long pcr;
4455 +       int inuse;
4456 +};
4457 +
4458 +#define HE_NUM_CS_STPER                16
4459 +
4460 +struct he_dev {
4461 +       unsigned int number;
4462 +       unsigned int irq;
4463 +       unsigned long membase;
4464 +
4465 +       char prod_id[30];
4466 +       char mac_addr[6];
4467 +       int media;                      /*  
4468 +                                        *  0x26 = HE155 MM 
4469 +                                        *  0x27 = HE622 MM 
4470 +                                        *  0x46 = HE155 SM 
4471 +                                        *  0x47 = HE622 SM 
4472 +                                        */
4473 +
4474 +
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;
4483 +
4484 +       struct he_vcc_table *he_vcc_table;
4485 +
4486 +#ifdef notyet
4487 +       struct he_group group[HE_NUM_GROUPS];
4488 +#endif
4489 +       struct he_cs_stper cs_stper[HE_NUM_CS_STPER];
4490 +       unsigned total_bw;
4491 +
4492 +       dma_addr_t irq_phys;
4493 +       struct he_irq *irq_base, *irq_head, *irq_tail;
4494 +       volatile unsigned *irq_tailoffset;
4495 +       int irq_peak;
4496 +
4497 +#ifdef USE_TASKLET
4498 +       struct tasklet_struct tasklet;
4499 +#endif
4500 +
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 */
4506 +
4507 +       spinlock_t global_lock;         /* 8.1.5 pci transaction ordering
4508 +                                         error problem */
4509 +       dma_addr_t rbrq_phys;
4510 +       struct he_rbrq *rbrq_base, *rbrq_head;
4511 +       int rbrq_peak;
4512 +
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;
4517 +       int rbpl_peak;
4518 +
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;
4523 +       int rbps_peak;
4524 +
4525 +       dma_addr_t tbrq_phys;
4526 +       struct he_tbrq *tbrq_base, *tbrq_head;
4527 +       int tbrq_peak;
4528 +
4529 +       dma_addr_t hsp_phys;
4530 +       struct he_hsp *hsp;
4531 +
4532 +       struct pci_dev *pci_dev;
4533 +       struct atm_dev *atm_dev;
4534 +       struct he_dev *next;
4535 +};
4536 +
4537 +struct he_vcc
4538 +{
4539 +       struct iovec iov_head[32];
4540 +       struct iovec *iov_tail;
4541 +       int pdu_len;
4542 +
4543 +       int rc_index;
4544 +
4545 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
4546 +       struct wait_queue *rx_waitq;
4547 +       atruct wait_queue *tx_waitq;
4548 +#else
4549 +       wait_queue_head_t rx_waitq;
4550 +       wait_queue_head_t tx_waitq;
4551 +#endif
4552 +};
4553 +
4554 +#define HE_VCC(vcc)    ((struct he_vcc *)(vcc->dev_data))
4555 +
4556 +#define PCI_VENDOR_ID_FORE     0x1127
4557 +#define PCI_DEVICE_ID_FORE_HE  0x400
4558 +
4559 +#define HE_DMA_MASK            0xffffffff
4560 +
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)
4569 +
4570 +#define MIN_PCI_LATENCY                32      /* errata 8.1.3 */
4571 +
4572 +#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data)
4573 +
4574 +#define he_is622(dev)  ((dev)->media & 0x1)
4575 +
4576 +#define HE_REGMAP_SIZE 0x100000
4577 +
4578 +#define RESET_CNTL     0x80000
4579 +#define  BOARD_RST_STATUS      (1<<6)
4580 +
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)
4598 +
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)
4609 +
4610 +#define LB_MEM_ADDR    0x8000c
4611 +#define LB_MEM_DATA    0x80010
4612 +
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)
4617 +
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)
4623 +
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)
4633 +
4634 +#define ABORT_ADDR     0x80020
4635 +
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
4654 +
4655 +#define IRQ1_BASE      0x80090
4656 +#define IRQ1_HEAD      0x80094
4657 +#define IRQ1_CNTL      0x80098
4658 +#define IRQ1_DATA      0x8009c
4659 +
4660 +#define IRQ2_BASE      0x800a0
4661 +#define IRQ2_HEAD      0x800a4
4662 +#define IRQ2_CNTL      0x800a8
4663 +#define IRQ2_DATA      0x800ac
4664 +
4665 +#define IRQ3_BASE      0x800b0
4666 +#define IRQ3_HEAD      0x800b4
4667 +#define IRQ3_CNTL      0x800b8
4668 +#define IRQ3_DATA      0x800bc
4669 +
4670 +#define GRP_10_MAP     0x800c0
4671 +#define GRP_32_MAP     0x800c4
4672 +#define GRP_54_MAP     0x800c8
4673 +#define GRP_76_MAP     0x800cc
4674 +
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
4688 +
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
4697 +
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
4706 +
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
4715 +
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
4724 +
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
4733 +
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
4742 +
4743 +#define        G7_RBPS_S       0x804e0
4744 +#define G7_RBPS_T      0x804e4
4745 +#define G7_RBPS_QI     0x804e8
4746 +#define G7_RBPS_BS     0x804ec
4747 +
4748 +#define G7_RBPL_S      0x804f0
4749 +#define G7_RBPL_T      0x804f4
4750 +#define G7_RBPL_QI     0x804f8
4751 +#define G7_RBPL_BS     0x804fc
4752 +
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)
4761 +
4762 +/* fill in 1 ... 7 later */
4763 +
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)
4769 +
4770 +/* fill in 1 ... 7 later */
4771 +
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)
4776 +
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
4793 +
4794 +#define TPDRQ_B_H      0x80680
4795 +#define TPDRQ_T                0x80684
4796 +#define TPDRQ_S                0x80688
4797 +
4798 +#define UBUFF_BA       0x8068c
4799 +
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
4813 +
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)
4823 +
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)
4831 +
4832 +#define LBSTAT         0x80708
4833 +
4834 +#define RCC_STAT       0x8070c
4835 +#define  RCC_BUSY              (1)
4836 +
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)
4844 +
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 
4850 +
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)
4856 +
4857 +#define TXAAL5_PROTO   0x80764
4858 +#define  CPCS_UU(x)            (x<<8)
4859 +#define  CPI(x)                        (x)
4860 +
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)
4868 +
4869 +#define RCMRSRB_BA     0x80784
4870 +#define RCMLBM_BA      0x80788
4871 +#define RCMABR_BA      0x8078c
4872 +
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)
4880 +
4881 +#define MCC            0x807c4
4882 +#define OEC            0x807c8
4883 +#define DCC            0x807cc
4884 +#define CEC            0x807d0
4885 +
4886 +#define HSP_BA         0x807f0
4887 +
4888 +#define LB_CONFIG      0x807f4
4889 +#define  LB_SIZE(x)            (x)
4890 +
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)
4904 +
4905 +#define FRAMER         0x80800         /* to 0x80bfc */
4906 +
4907 +/* 3.3 network controller (internal) mailbox registers */
4908 +
4909 +#define CS_STPER0      0x0
4910 +       /* ... */
4911 +#define CS_STPER31     0x01f
4912 +
4913 +#define CS_STTIM0      0x020
4914 +       /* ... */
4915 +#define CS_STTIM31     0x03f
4916 +
4917 +#define CS_TGRLD0      0x040
4918 +       /* ... */
4919 +#define CS_TGRLD15     0x04f
4920 +
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
4933 +
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
4939 +
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
4949 +
4950 +#define CS_OTPPER      0x080
4951 +#define CS_OTWPER      0x081
4952 +#define CS_OTTLIM      0x082
4953 +#define CS_OTTCNT      0x083
4954 +
4955 +#define CS_HGRRT0      0x090
4956 +       /* ... */
4957 +#define CS_HGRRT7      0x097
4958 +
4959 +#define CS_ORPTRS      0x0a0
4960 +
4961 +#define RXCON_CLOSE    0x100
4962 +
4963 +
4964 +#define RCM_MEM_SIZE   0x10000         /* 1M of 32-bit registers */
4965 +#define TCM_MEM_SIZE   0x20000         /* 2M of 32-bit registers */
4966 +
4967 +/* 2.5 transmit connection memory registers */
4968 +
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)
4984 +
4985 +#define TSR1_PCR(x)            ((x & 0x7FFF)<<16)
4986 +#define TSR1_MCR(x)            (x & 0x7FFF)
4987 +
4988 +#define TSR2_ACR(x)            ((x & 0x7FFF)<<16)
4989 +
4990 +#define TSR3_NRM_CNT(x)                ((x & 0xFF)<<24)
4991 +#define TSR3_CRM_CNT(x)                (x & 0xFFFF)
4992 +
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)
5001 +
5002 +#define TSR9_OPEN_CONN         (1<<20)
5003 +
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)
5008 +
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)
5013 +
5014 +#define TSR14_DELETE           (1<<31)
5015 +#define TSR14_ABR_CLOSE                (1<<16)
5016 +
5017 +/* 2.7.1 per connection receieve state registers */
5018 +
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)
5030 +
5031 +#define RSR1_AQI_ENABLE        (1<<20)
5032 +#define RSR1_RBPL_ONLY (1<<19)
5033 +#define RSR1_GROUP(x)  ((x)<<16)
5034 +
5035 +#define RSR4_AQI_ENABLE (1<<30)
5036 +#define RSR4_GROUP(x)  ((x)<<27)
5037 +#define RSR4_RBPL_ONLY (1<<26)
5038 +
5039 +/* 2.1.4 transmit packet descriptor */
5040 +
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)
5050 +
5051 +/* table 4.3 serial eeprom information */
5052 +
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[] */
5063 +
5064 +#define CS_LOW         0x0
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 */
5070 +
5071 +/* Read from EEPROM = 0000 0011b */
5072 +unsigned int readtab[] = {
5073 +       CS_HIGH | CLK_HIGH,
5074 +       CS_LOW | CLK_LOW,
5075 +       CLK_HIGH,               /* 0 */
5076 +       CLK_LOW,
5077 +       CLK_HIGH,               /* 0 */
5078 +       CLK_LOW,
5079 +       CLK_HIGH,               /* 0 */
5080 +       CLK_LOW,
5081 +       CLK_HIGH,               /* 0 */
5082 +       CLK_LOW,
5083 +       CLK_HIGH,               /* 0 */
5084 +       CLK_LOW,
5085 +       CLK_HIGH,               /* 0 */
5086 +       CLK_LOW | SI_HIGH,
5087 +       CLK_HIGH | SI_HIGH,     /* 1 */
5088 +       CLK_LOW | SI_HIGH,
5089 +       CLK_HIGH | SI_HIGH      /* 1 */
5090 +};     
5091
5092 +/* Clock to read from/write to the EEPROM */
5093 +unsigned int clocktab[] = {
5094 +       CLK_LOW,
5095 +       CLK_HIGH,
5096 +       CLK_LOW,
5097 +       CLK_HIGH,
5098 +       CLK_LOW,
5099 +       CLK_HIGH,
5100 +       CLK_LOW,
5101 +       CLK_HIGH,
5102 +       CLK_LOW,
5103 +       CLK_HIGH,
5104 +       CLK_LOW,
5105 +       CLK_HIGH,
5106 +       CLK_LOW,
5107 +       CLK_HIGH,
5108 +       CLK_LOW,
5109 +       CLK_HIGH,
5110 +       CLK_LOW
5111 +};     
5112 +
5113 +
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 @@
5119    
5120    {
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
5125      dev->tx_skb = skb;
5126      
5127 -    if (tx_iovcnt) {
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;
5133        dev->tx_bytes = 0;
5134        PRINTD (DBG_TX|DBG_BUS, "TX start scatter-gather transfer (iovec %p, len %d)",
5135 @@ -2189,14 +2189,6 @@
5136    }
5137  #endif
5138    
5139 -  // deal with possibly wildcarded VCs
5140 -  error = atm_find_ci (atm_vcc, &vpi, &vci);
5141 -  if (error) {
5142 -    PRINTD (DBG_WARN|DBG_VCC, "atm_find_ci failed!");
5143 -    return error;
5144 -  }
5145 -  PRINTD (DBG_VCC, "atm_find_ci gives %x %x", vpi, vci);
5146 -  
5147    error = vpivci_to_channel (&channel, vpi, vci);
5148    if (error) {
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 @@
5154                 return;
5155         }
5156  
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);
5165                 return;
5166         }
5167 -
5168 -       vcc = vc->rx_vcc;
5169 +       vcc_hold(vcc);
5170 +       read_unlock(&vcc_sklist_lock);
5171  
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;
5176                 }
5177  
5178 +               vcc_put(vcc);
5179                 recycle_rx_skb(card, skb);
5180                 return;
5181         }
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);
5186 +               vcc_put(vcc);
5187                 return;
5188         }
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);
5194 +                       vcc_put(vcc);
5195                         return;
5196                 }
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);
5201 +                       vcc_put(vcc);
5202                         return;
5203                 }
5204                 if (rpp->count > 1) {
5205 @@ -1159,9 +1165,11 @@
5206                                          card->name);
5207                                 recycle_rx_pool_skb(card, rpp);
5208                                 atomic_inc(&vcc->stats->rx_err);
5209 +                               vcc_put(vcc);
5210                                 return;
5211                         }
5212                         if (!atm_charge(vcc, skb->truesize)) {
5213 +                               vcc_put(vcc);
5214                                 recycle_rx_pool_skb(card, rpp);
5215                                 dev_kfree_skb(skb);
5216                                 return;
5217 @@ -1181,6 +1189,7 @@
5218  
5219                         vcc->push(vcc, skb);
5220                         atomic_inc(&vcc->stats->rx);
5221 +                       vcc_put(vcc);
5222  
5223                         return;
5224                 }
5225 @@ -1189,6 +1198,7 @@
5226                 flush_rx_pool(card, rpp);
5227  
5228                 if (!atm_charge(vcc, skb->truesize)) {
5229 +                       vcc_put(vcc);
5230                         recycle_rx_skb(card, skb);
5231                         return;
5232                 }
5233 @@ -1212,8 +1222,10 @@
5234                         add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
5235                 else
5236                         add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
5237 +               vcc_put(vcc);
5238                 return;
5239         }
5240 +       vcc_put(vcc);
5241  }
5242  
5243  static void
5244 @@ -1988,7 +2000,7 @@
5245                 return -EINVAL;
5246         }
5247  
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);
5252                 dev_kfree_skb(skb);
5253 @@ -2025,8 +2037,7 @@
5254                 atomic_inc(&vcc->stats->tx_err);
5255                 return -ENOMEM;
5256         }
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);
5260  
5261         memcpy(skb_put(skb, 52), cell, 52);
5262  
5263 @@ -2349,6 +2360,7 @@
5264         if (test_bit(VCF_RX, &vc->flags))
5265                 return -EBUSY;
5266  
5267 +       vcc_hold(vcc);
5268         vc->rx_vcc = vcc;
5269         set_bit(VCF_RX, &vc->flags);
5270  
5271 @@ -2403,40 +2415,6 @@
5272  }
5273  
5274  static int
5275 -idt77252_find_vcc(struct atm_vcc *vcc, short *vpi, int *vci)
5276 -{
5277 -       struct atm_vcc *walk;
5278 -
5279 -       if (*vpi == ATM_VPI_ANY) {
5280 -               *vpi = 0;
5281 -               walk = vcc->dev->vccs;
5282 -               while (walk) {
5283 -                       if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
5284 -                               (*vpi)++;
5285 -                               walk = vcc->dev->vccs;
5286 -                               continue;
5287 -                       }
5288 -                       walk = walk->next;
5289 -               }
5290 -       }
5291 -
5292 -       if (*vci == ATM_VCI_ANY) {
5293 -               *vci = ATM_NOT_RSV_VCI;
5294 -               walk = vcc->dev->vccs;
5295 -               while (walk) {
5296 -                       if ((walk->vci == *vci) && (walk->vpi == *vpi)) {
5297 -                               (*vci)++;
5298 -                               walk = vcc->dev->vccs;
5299 -                               continue;
5300 -                       }
5301 -                       walk = walk->next;
5302 -               }
5303 -       }
5304 -
5305 -       return 0;
5306 -}
5307 -
5308 -static int
5309  idt77252_open(struct atm_vcc *vcc, short vpi, int vci)
5310  {
5311         struct atm_dev *dev = vcc->dev;
5312 @@ -2446,8 +2424,6 @@
5313         unsigned int inuse;
5314         int error;
5315  
5316 -       idt77252_find_vcc(vcc, &vpi, &vci);
5317 -
5318         if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
5319                 return 0;
5320  
5321 @@ -2565,6 +2541,8 @@
5322                 spin_lock_irqsave(&vc->lock, flags);
5323                 clear_bit(VCF_RX, &vc->flags);
5324                 vc->rx_vcc = NULL;
5325 +               barrier();
5326 +               vcc_put(vcc);
5327                 spin_unlock_irqrestore(&vc->lock, flags);
5328  
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);)
5335              return -1;
5336          }
5337 +        read_lock(&vcc_sklist_lock);
5338         vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];  
5339         if (!vcc)  
5340         {      
5341 +                read_unlock(&vcc_sklist_lock);
5342                  free_desc(dev, desc); 
5343                 printk("IA: null vcc, drop PDU\n");  
5344                 return -1;  
5345         }  
5346 +        vcc_hold(vcc);
5347 +        read_unlock(&vcc_sklist_lock);
5348           
5349    
5350         /* might want to check the status bits for errors */  
5351 @@ -1185,8 +1189,6 @@
5352          }
5353         skb_put(skb,len);  
5354          // pwang_test
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);  
5359  
5360 @@ -1205,7 +1207,8 @@
5361         udelay(1);  
5362         /* Increment transaction counter */  
5363         writel(1, iadev->dma+IPHASE5575_RX_COUNTER);   
5364 -out:   return 0;  
5365 +out:    vcc_put(vcc);
5366 +       return 0;  
5367  out_free_desc:
5368          free_desc(dev, desc);
5369          goto out;
5370 @@ -1283,6 +1286,7 @@
5371    struct dle *dle, *cur_dle;  
5372    u_int dle_lp;  
5373    int len;
5374 +  struct rx_buf_desc *buf_desc_ptr;  
5375    iadev = INPH_IA_DEV(dev);  
5376   
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)  
5384    {  
5385        /* free the DMAed skb */  
5386 @@ -1300,6 +1305,9 @@
5387        if (!skb)  
5388           goto INCR_DLE;
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);  
5394                 
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;
5401           if (!vcc) {
5402               printk("IA: null vcc\n");  
5403                dev_kfree_skb_any(skb);
5404 @@ -1360,6 +1367,7 @@
5405            printk("\n");)
5406  
5407           IF_RX(printk("rx_dle_intr: skb push");)  
5408 +         ATM_SKB(skb)->vcc = vcc;
5409           vcc->push(vcc,skb);  
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;  
5415    }  
5416 +  read_unlock(&vcc_sklist_lock);
5417    iadev->rx_dle_q.read = dle;  
5418    
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);  
5424 +       vcc_hold(vcc);
5425         iadev->rx_open[vcc->vci] = vcc;  
5426         return 0;  
5427  }  
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);
5432 -
5433 -                  return;
5434 +                  goto cont_loop;
5435              }
5436              iavcc = INPH_IA_VCC(vcc);
5437              if (!iavcc) {
5438                    printk("tx_dle_intr: iavcc is null\n");
5439                   spin_unlock_irqrestore(&iadev->tx_lock, flags);
5440                    dev_kfree_skb_any(skb);
5441 -                  return;
5442 +                  goto cont_loop;
5443              }
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);
5448              }
5449              IF_EVENT(printk("tx_dle_intr: enque skb = 0x%x \n", (u32)skb);)
5450 +cont_loop:
5451              if (++dle == iadev->tx_dle_q.end)
5452                   dle = iadev->tx_dle_q.start;
5453          }
5454 @@ -2705,6 +2715,8 @@
5455             // Drain the packets
5456             rx_dle_intr(vcc->dev); 
5457             iadev->rx_open[vcc->vci] = 0;
5458 +           barrier();
5459 +           vcc_put(vcc);
5460          }
5461         kfree(INPH_IA_VCC(vcc));  
5462          ia_vcc = NULL;
5463 @@ -2724,12 +2736,6 @@
5464                 INPH_IA_VCC(vcc) = NULL;  
5465         }  
5466         iadev = INPH_IA_DEV(vcc->dev);  
5467 -       error = atm_find_ci(vcc, &vpi, &vci);  
5468 -       if (error)   
5469 -       {  
5470 -           printk("iadev: atm_find_ci returned error %d\n", error);  
5471 -           return error;  
5472 -       }  
5473         vcc->vpi = vpi;  
5474         vcc->vci = vci;  
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 @@
5480  {
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];
5486         if (lvcc == NULL) {
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);
5491                 if (s & SERVICE_TX)
5492 @@ -1834,7 +1834,7 @@
5493         }
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 @@
5502                 }
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);
5507                 return 1;
5508         }
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++;
5515                 return 0;
5516         }
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 @@
5524         }
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);
5529                 return 0;
5530         }
5531         if (s & SERVICE_TRASH) {
5532                 int bytes;
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 @@
5539                 return 0;
5540         }
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);
5553         return 0;
5554  }
5555  
5556 @@ -1924,11 +1924,11 @@
5557         reg_write(lanai, wreg, ServRead_Reg);
5558         if (ntx != 0) {
5559                 spin_lock(&lanai->txlock);
5560 -               vcclist_read_lock();
5561 +               read_lock(&vcc_sklist_lock);
5562                 vci_bitfield_iterate(lanai, &lanai->transmit_ready,
5563                     iter_transmit);
5564                 vci_bitfield_init(&lanai->transmit_ready);
5565 -               vcclist_read_unlock();
5566 +               read_unlock(&vcc_sklist_lock);
5567                 spin_unlock(&lanai->txlock);
5568         }
5569  }
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);
5576         for (; ; left++) {
5577                 if (left >= NUM_VCI) {
5578                         left = 0;
5579 @@ -2821,7 +2821,7 @@
5580         page[left++] = '\n';
5581         page[left] = '\0';
5582      out:
5583 -       vcclist_read_unlock();
5584 +       read_unlock(&vcc_sklist_lock);
5585         return left;
5586  }
5587  #endif /* CONFIG_PROC_FS */
5588 @@ -2842,7 +2842,6 @@
5589         phy_get:        NULL,
5590         feedback:       NULL,
5591         change_qos:     lanai_change_qos,
5592 -       free_rx_skb:    NULL,
5593         proc_read:      lanai_proc_read
5594  };
5595  
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 @@
5600        return error;
5601     }
5602        
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);
5610 +      }
5611 +   }
5612 +
5613  
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 @@
5617  {
5618     ns_dev *card;
5619     vc_map *vc;
5620 -   int error;
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 @@
5625        return -EINVAL;
5626     }
5627  
5628 -   if ((error = atm_find_ci(vcc, &vpi, &vci)))
5629 -   {
5630 -      PRINTK("nicstar%d: error in atm_find_ci().\n", card->index);
5631 -      return error;
5632 -   }
5633     vc = &(card->vcmap[vpi << card->vcibits | vci]);
5634     vcc->vpi = vpi;
5635     vcc->vci = vci;
5636 @@ -1597,6 +1597,7 @@
5637           u32 status;
5638        
5639           vc->rx = 1;
5640 +         vcc_hold(vcc);
5641           vc->rx_vcc = vcc;
5642           vc->rx_iov = NULL;
5643  
5644 @@ -1646,6 +1647,9 @@
5645        spin_unlock_irqrestore(&card->res_lock, flags);
5646        
5647        vc->rx = 0;
5648 +      vc->rx_vcc = NULL;
5649 +      barrier();
5650 +      vcc_put(vcc);
5651        if (vc->rx_iov != NULL)
5652        {
5653          struct sk_buff *iovb;
5654 @@ -1659,9 +1663,9 @@
5655                 card->index);
5656           iovb = vc->rx_iov;
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 @@
5668        return -EINVAL;
5669     }
5670     
5671 -   if (ATM_SKB(skb)->iovcnt != 0)
5672 +   if (skb_shinfo(skb)->nr_frags != 0)
5673     {
5674        printk("nicstar%d: No scatter-gather yet.\n", card->index);
5675        atomic_inc(&vcc->stats->tx_err);
5676 @@ -2203,16 +2207,18 @@
5677        return;
5678     }
5679     
5680 +   read_lock(&vcc_sklist_lock);
5681     vc = &(card->vcmap[vpi << card->vcibits | vci]);
5682 -   if (!vc->rx)
5683 +   if (!vc->rx || !(vcc = vc->rx_vcc))
5684     {
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);
5689        return;
5690     }
5691 -
5692 -   vcc = vc->rx_vcc;
5693 +   vcc_hold(vcc);
5694 +   read_unlock(&vcc_sklist_lock);
5695  
5696     if (vcc->qos.aal == ATM_AAL0)
5697     {
5698 @@ -2252,7 +2258,7 @@
5699           atomic_inc(&vcc->stats->rx);
5700           cell += ATM_CELL_PAYLOAD;
5701        }
5702 -
5703 +      vcc_put(vcc);
5704        recycle_rx_buf(card, skb);
5705        return;
5706     }
5707 @@ -2269,6 +2275,7 @@
5708          {
5709             printk("nicstar%d: Out of iovec buffers.\n", card->index);
5710              atomic_inc(&vcc->stats->rx_drop);
5711 +            vcc_put(vcc);
5712              recycle_rx_buf(card, skb);
5713              return;
5714          }
5715 @@ -2284,30 +2291,30 @@
5716             }
5717          }
5718        vc->rx_iov = iovb;
5719 -      ATM_SKB(iovb)->iovcnt = 0;
5720 +      NS_SKB(iovb)->iovcnt = 0;
5721        iovb->len = 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. */
5728     }
5729 -   else if (ATM_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)
5730 +   else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)
5731     {
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;
5737        iovb->len = 0;
5738        iovb->tail = iovb->data = iovb->head;
5739 -      ATM_SKB(iovb)->vcc = vcc;
5740 +      NS_SKB(iovb)->vcc = vcc;
5741     }
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;
5747  
5748 -   if (ATM_SKB(iovb)->iovcnt == 1)
5749 +   if (NS_SKB(iovb)->iovcnt == 1)
5750     {
5751        if (skb->list != &card->sbpool.queue)
5752        {
5753 @@ -2317,11 +2324,12 @@
5754           atomic_inc(&vcc->stats->rx_err);
5755           recycle_rx_buf(card, skb);
5756           vc->rx_iov = NULL;
5757 +         vcc_put(vcc);
5758           recycle_iov_buf(card, iovb);
5759           return;
5760        }
5761     }
5762 -   else /* ATM_SKB(iovb)->iovcnt >= 2 */
5763 +   else /* NS_SKB(iovb)->iovcnt >= 2 */
5764     {
5765        if (skb->list != &card->lbpool.queue)
5766        {
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);
5773           vc->rx_iov = NULL;
5774 +         vcc_put(vcc);
5775           recycle_iov_buf(card, iovb);
5776          return;
5777        }
5778 @@ -2354,15 +2363,16 @@
5779              printk(".\n");
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);
5784          vc->rx_iov = NULL;
5785 +         vcc_put(vcc);
5786           recycle_iov_buf(card, iovb);
5787          return;
5788        }
5789  
5790        /* By this point we (hopefully) have a complete SDU without errors. */
5791  
5792 -      if (ATM_SKB(iovb)->iovcnt == 1)  /* Just a small buffer */
5793 +      if (NS_SKB(iovb)->iovcnt == 1)   /* Just a small buffer */
5794        {
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);
5799           }
5800        }
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 */
5803        {
5804           struct sk_buff *sb;
5805  
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);
5812                 vc->rx_iov = NULL;
5813 +               vcc_put(vcc);
5814                 recycle_iov_buf(card, iovb);
5815                 return;
5816              }
5817 @@ -2499,7 +2510,7 @@
5818  
5819           if (!atm_charge(vcc, hb->truesize))
5820          {
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)
5824              {
5825                 skb_queue_tail(&card->hbpool.queue, hb);
5826 @@ -2522,7 +2533,7 @@
5827                          0, 0);
5828  
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++)
5832              {
5833                 lb = (struct sk_buff *) iov->iov_base;
5834                 tocopy = MIN(remaining, iov->iov_len);
5835 @@ -2550,7 +2561,7 @@
5836        vc->rx_iov = NULL;
5837        recycle_iov_buf(card, iovb);
5838     }
5839 -
5840 +   vcc_put(vcc);
5841  }
5842  
5843  
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
5847 @@ -96,6 +96,7 @@
5848  /* ESI stuff ******************************************************************/
5849  
5850  #define NICSTAR_EPROM_MAC_ADDR_OFFSET 0x6C
5851 +#define NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT 0xF6
5852  
5853  
5854  /* #defines *******************************************************************/
5855 @@ -748,6 +749,14 @@
5856     int tbd_count;
5857  } vc_map;
5858  
5859 +
5860 +struct ns_skb_data
5861 +{
5862 +       struct atm_vcc *vcc;
5863 +       int iovcnt;
5864 +};
5865 +
5866 +#define NS_SKB(skb) (((struct ns_skb_data *) (skb)->cb))
5867  
5868  typedef struct ns_dev
5869  {
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);
5879         save_flags(flags);
5880         cli();
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);
5885                         return RING_BUSY;
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;
5892         vcc->vpi = vpi;
5893         vcc->vci = vci;
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
5898 @@ -0,0 +1,20 @@
5899 +/* atm_he.h */
5900 +
5901 +#ifndef LINUX_ATM_HE_H
5902 +#define LINUX_ATM_HE_H
5903 +
5904 +#include <linux/atmioc.h>
5905 +
5906 +#define HE_GET_REG     _IOW('a', ATMIOC_SARPRV, struct atmif_sioc)
5907 +
5908 +#define HE_REGTYPE_PCI 1
5909 +#define HE_REGTYPE_RCM 2
5910 +#define HE_REGTYPE_TCM 3
5911 +#define HE_REGTYPE_MBOX        4
5912 +
5913 +struct he_ioctl_reg {
5914 +       unsigned addr, val;
5915 +       char type;
5916 +};
5917 +
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
5922 @@ -68,7 +68,7 @@
5923         struct module *owner;
5924  };
5925  
5926 -extern struct atm_tcp_ops atm_tcp_ops;
5927 +extern struct atm_tcp_ops *atm_tcp_ops;
5928  
5929  #endif
5930  
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
5934 @@ -30,10 +30,9 @@
5935  #define ATM_DS3_PCR    (8000*12)
5936                         /* DS3: 12 cells in a 125 usec time slot */
5937  
5938 -#define ATM_PDU_OVHD   0       /* number of bytes to charge against buffer
5939 -                                  quota per PDU */
5940  
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))
5944  
5945  
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 */
5974 @@ -337,8 +327,6 @@
5975                                         /* (NULL) */
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_*) */
5983 @@ -348,6 +336,8 @@
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 */
5992 @@ -388,8 +378,6 @@
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;
6000  };
6001 @@ -404,53 +392,94 @@
6002  
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 */
6007  };
6008  
6009 +extern struct sock *vcc_sklist;
6010 +extern rwlock_t vcc_sklist_lock;
6011 +
6012  #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
6013  
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);
6025  
6026  
6027 -/*
6028 - * This is approximately the algorithm used by alloc_skb.
6029 - *
6030 - */
6031 +static inline int atm_guess_pdu2truesize(int pdu_size)
6032 +{
6033 +       /* must match allocation in alloc_skb */
6034 +       return SKB_DATA_ALIGN(pdu_size) + sizeof(struct sk_buff);
6035 +}
6036 +
6037  
6038 -static __inline__ int atm_guess_pdu2truesize(int pdu_size)
6039 +static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
6040  {
6041 -       return ((pdu_size+15) & ~15) + sizeof(struct sk_buff);
6042 +       atomic_add(truesize, &vcc->sk->rmem_alloc);
6043  }
6044  
6045  
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)
6048  {
6049 -       atomic_add(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
6050 +       atomic_sub(truesize, &vcc->sk->rmem_alloc);
6051 +}
6052 +
6053 +
6054 +static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
6055 +{
6056 +       return (size+atomic_read(&vcc->sk->wmem_alloc)) < vcc->sk->sndbuf;
6057 +}
6058 +
6059 +
6060 +static inline struct atm_vcc *__vcc_lookup(struct atm_dev *dev, short vpi, int vci)
6061 +{
6062 +       struct atm_vcc *vcc;
6063 +       struct sock *s;
6064 +
6065 +       for(s = vcc_sklist; s; s = s->next) {
6066 +               vcc = atm_sk(s);
6067 +               if (vcc->vci == vci && vcc->vpi == vpi && vcc->dev == dev) return vcc;
6068 +       }
6069 +
6070 +       return NULL;
6071 +}
6072 +
6073 +
6074 +static inline struct atm_vcc *vcc_lookup(struct atm_dev *dev, short vpi, int vci)
6075 +{
6076 +       struct atm_vcc *vcc;
6077 +
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);
6082 +               return vcc;
6083 +       }
6084 +       read_unlock(&vcc_sklist_lock);
6085 +       return NULL;
6086  }
6087  
6088  
6089 -static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
6090 +static inline void vcc_hold(struct atm_vcc *vcc)
6091  {
6092 -       atomic_sub(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
6093 +       sock_hold(vcc->sk);
6094  }
6095  
6096  
6097 -static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size)
6098 +static inline void vcc_put(struct atm_vcc *vcc)
6099  {
6100 -       return size+atomic_read(&vcc->sk->wmem_alloc)+ATM_PDU_OVHD < vcc->sk->sndbuf;
6101 +       sock_put(vcc->sk);
6102  }
6103  
6104  
6105  int atm_charge(struct atm_vcc *vcc,int truesize);
6106  struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
6107      int gfp_flags);
6108 -int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci);
6109  int atm_pcr_goal(struct atm_trafprm *tp);
6110  
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
6115 @@ -139,6 +139,7 @@
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);
6120  
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
6126 @@ -55,13 +55,27 @@
6127  };
6128  
6129  
6130 -extern struct atm_vcc *atmarpd; /* ugly */
6131  extern struct neigh_table clip_tbl;
6132 +extern struct atm_vcc *atmarpd; /* ugly */
6133  
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);
6139 +
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;
6148 +};
6149 +
6150 +#ifdef __KERNEL__
6151 +extern struct neigh_table *clip_tbl_hook;
6152 +extern struct atm_clip_ops *atm_clip_ops;
6153 +#endif
6154  
6155  #endif
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
6159 @@ -31,19 +31,19 @@
6160     fi
6161  fi
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
6172          fi
6173        fi
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
6179        fi
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
6184        fi
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
6188 @@ -14,32 +14,24 @@
6189  list-multi     := mpoa.o
6190  mpoa-objs      := mpc.o mpoa_caches.o mpoa_proc.o
6191  
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)
6195  
6196 -ifeq ($(CONFIG_ATM_CLIP),y)
6197 -obj-y += clip.o
6198 -NEED_IPCOM = ipcommon.o
6199 -endif
6200 -
6201 -ifeq ($(CONFIG_ATM_BR2684),y)
6202 -  NEED_IPCOM = ipcommon.o
6203 -else
6204 -  ifeq ($(CONFIG_ATM_BR2684),m)
6205 -       NEED_IPCOM = ipcommon.o
6206 -  endif
6207 -endif
6208 +obj-$(CONFIG_ATM_CLIP) += clip.o
6209  obj-$(CONFIG_ATM_BR2684) += br2684.o
6210  
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
6215  endif
6216 -
6217 -obj-y += $(NEED_IPCOM)
6218 -
6219 -ifeq ($(CONFIG_PROC_FS),y)
6220 -obj-y += proc.o
6221 +ifneq ($(CONFIG_ATM_BR2684),n)
6222 +  ip-common-obj-y = ipcommon.o
6223 +endif
6224 +ifneq ($(CONFIG_NET_SCH_ATM),n)
6225 +  ip-common-obj-y = ipcommon.o
6226  endif
6227 +obj-y += $(ip-common-obj-y)
6228  
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
6236 @@ -36,14 +36,6 @@
6237  }
6238  
6239  
6240 -/*
6241 - * Avoid modification of any list of local interfaces while reading it
6242 - * (which may involve page faults and therefore rescheduling)
6243 - */
6244 -
6245 -static DECLARE_MUTEX(local_lock);
6246 -extern  spinlock_t atm_dev_lock;
6247 -
6248  static void notify_sigd(struct atm_dev *dev)
6249  {
6250         struct sockaddr_atmpvc pvc;
6251 @@ -60,13 +52,13 @@
6252  {
6253         struct atm_dev_addr *this;
6254  
6255 -       down(&local_lock);
6256 +       spin_lock(&dev->lock);
6257         while (dev->local) {
6258                 this = dev->local;
6259                 dev->local = this->next;
6260                 kfree(this);
6261         }
6262 -       up(&local_lock);
6263 +       spin_unlock(&dev->lock);
6264         notify_sigd(dev);
6265  }
6266  
6267 @@ -78,20 +70,20 @@
6268  
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)) {
6275 -                       up(&local_lock);
6276 +                       spin_unlock(&dev->lock);
6277                         return -EEXIST;
6278                 }
6279 -       *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_KERNEL);
6280 +       *walk = kmalloc(sizeof(struct atm_dev_addr),GFP_ATOMIC);
6281         if (!*walk) {
6282 -               up(&local_lock);
6283 +               spin_unlock(&dev->lock);
6284                 return -ENOMEM;
6285         }
6286         (*walk)->addr = *addr;
6287         (*walk)->next = NULL;
6288 -       up(&local_lock);
6289 +       spin_unlock(&dev->lock);
6290         notify_sigd(dev);
6291         return 0;
6292  }
6293 @@ -104,17 +96,17 @@
6294  
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;
6301         if (!*walk) {
6302 -               up(&local_lock);
6303 +               spin_unlock(&dev->lock);
6304                 return -ENOENT;
6305         }
6306         this = *walk;
6307         *walk = this->next;
6308 +       spin_unlock(&dev->lock);
6309         kfree(this);
6310 -       up(&local_lock);
6311         notify_sigd(dev);
6312         return 0;
6313  }
6314 @@ -125,21 +117,21 @@
6315         struct atm_dev_addr *walk;
6316         int total;
6317  
6318 -       down(&local_lock);
6319 +       spin_lock(&dev->lock);
6320         total = 0;
6321         for (walk = dev->local; walk; walk = walk->next) {
6322                 total += sizeof(struct sockaddr_atmsvc);
6323                 if (total > size) {
6324 -                       up(&local_lock);
6325 +                       spin_unlock(&dev->lock);
6326                         return -E2BIG;
6327                 }
6328                 if (copy_to_user(u_buf,&walk->addr,
6329                     sizeof(struct sockaddr_atmsvc))) {
6330 -                       up(&local_lock);
6331 +                       spin_unlock(&dev->lock);
6332                         return -EFAULT;
6333                 }
6334                 u_buf++;
6335         }
6336 -       up(&local_lock);
6337 +       spin_unlock(&dev->lock);
6338         return total;
6339  }
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
6343 @@ -43,63 +43,6 @@
6344  }
6345  
6346  
6347 -static int check_ci(struct atm_vcc *vcc,short vpi,int vci)
6348 -{
6349 -       struct atm_vcc *walk;
6350 -
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) */
6361 -       return 0;
6362 -}
6363 -
6364 -
6365 -int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
6366 -{
6367 -       static short p = 0; /* poor man's per-device cache */
6368 -       static int c = 0;
6369 -       short old_p;
6370 -       int old_c;
6371 -
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;
6380 -       old_p = p;
6381 -       old_c = c;
6382 -       do {
6383 -               if (!check_ci(vcc,p,c)) {
6384 -                       *vpi = p;
6385 -                       *vci = c;
6386 -                       return 0;
6387 -               }
6388 -               if (*vci == ATM_VCI_ANY) {
6389 -                       c++;
6390 -                       if (c >= 1 << vcc->dev->ci_range.vci_bits)
6391 -                               c = ATM_NOT_RSV_VCI;
6392 -               }
6393 -               if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
6394 -                   *vpi == ATM_VPI_ANY) {
6395 -                       p++;
6396 -                       if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
6397 -               }
6398 -       }
6399 -       while (old_p != p || old_c != c);
6400 -       return -EADDRINUSE;
6401 -}
6402 -
6403 -
6404  /*
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
6407 @@ -155,7 +98,6 @@
6408  
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
6418 @@ -189,7 +189,6 @@
6419                 return 0;
6420                 }
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
6429 @@ -7,6 +7,7 @@
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>
6437 @@ -48,7 +49,6 @@
6438  static struct timer_list idle_timer;
6439  static int start_timer = 1;
6440  
6441 -
6442  static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
6443  {
6444         struct atmarp_ctrl *ctrl;
6445 @@ -127,6 +127,8 @@
6446                         struct atmarp_entry *entry = NEIGH2ENTRY(n);
6447                         struct clip_vcc *clip_vcc;
6448  
6449 +                       write_lock(&n->lock);
6450 +
6451                         for (clip_vcc = entry->vccs; clip_vcc;
6452                             clip_vcc = clip_vcc->next)
6453                                 if (clip_vcc->idle_timeout &&
6454 @@ -140,6 +142,7 @@
6455                                 }
6456                         if (entry->vccs ||
6457                             time_before(jiffies, entry->expires)) {
6458 +                               write_unlock(&n->lock);
6459                                 np = &n->next;
6460                                 continue;
6461                         }
6462 @@ -151,12 +154,14 @@
6463                                 while ((skb = skb_dequeue(&n->arp_queue)) !=
6464                                      NULL) 
6465                                         dev_kfree_skb(skb);
6466 +                               write_unlock(&n->lock);
6467                                 np = &n->next;
6468                                 continue;
6469                         }
6470                         *np = n->next;
6471                         DPRINTK("expired neigh %p\n",n);
6472                         n->dead = 1;
6473 +                       write_unlock(&n->lock);
6474                         neigh_release(n);
6475                 }
6476         }
6477 @@ -218,6 +223,7 @@
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));
6482         netif_rx(skb);
6483  }
6484  
6485 @@ -427,7 +433,6 @@
6486                 ((u16 *) here)[3] = skb->protocol;
6487         }
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 "
6495                     "pending\n");
6496         skb_queue_purge(&vcc->sk->receive_queue);
6497 +       MOD_DEC_USE_COUNT;
6498         DPRINTK("(done)\n");
6499  }
6500  
6501  
6502  static struct atmdev_ops atmarpd_dev_ops = {
6503 -       close:  atmarpd_close,
6504 +       .close = atmarpd_close,
6505  };
6506  
6507  
6508  static struct atm_dev atmarpd_dev = {
6509 -       &atmarpd_dev_ops,
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,
6519 +       .type =                 "arpd",
6520 +       .number =               999,
6521 +       .lock =                 SPIN_LOCK_UNLOCKED
6522  };
6523  
6524  
6525 @@ -732,7 +733,7 @@
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);
6531         vcc->push = NULL;
6532         vcc->pop = NULL; /* crash */
6533         vcc->push_oam = NULL; /* crash */
6534 @@ -746,10 +747,59 @@
6535         return 0;
6536  }
6537  
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
6546 +};
6547  
6548 -void atm_clip_init(void)
6549 +static int __init atm_clip_init(void)
6550  {
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);
6555 +
6556 +
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);
6562 +
6563 +
6564 +       atm_clip_ops = &__atm_clip_ops;
6565 +
6566 +       clip_tbl_hook = &clip_tbl;
6567 +
6568 +       return 0;
6569  }
6570 +
6571 +static void __exit atm_clip_exit(void)
6572 +{
6573 +       struct net_device *dev, *next;
6574 +
6575 +       atm_clip_ops = NULL;
6576 +       clip_tbl_hook = NULL;
6577 +
6578 +       neigh_ifdown(&clip_tbl, NULL);
6579 +       dev = clip_devs;
6580 +       while (dev) {
6581 +               next = PRIV(dev)->next;
6582 +               unregister_netdev(dev);
6583 +               kfree(dev);
6584 +               dev = next;
6585 +       }
6586 +       if (start_timer == 0) del_timer(&idle_timer);
6587 +
6588 +       kmem_cache_destroy(clip_tbl.kmem_cachep);
6589 +}
6590 +
6591 +module_init(atm_clip_init);
6592 +module_exit(atm_clip_exit);
6593 +
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
6598 @@ -5,6 +5,7 @@
6599  
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
6605                                    proto_ops */
6606 @@ -27,21 +27,22 @@
6607  #include <asm/atomic.h>
6608  #include <asm/poll.h>
6609  #include <asm/ioctls.h>
6610 +#include <asm/semaphore.h>
6611  
6612  #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
6613  #include <linux/atmlec.h>
6614  #include "lec.h"
6615  #include "lec_arpc.h"
6616 -struct atm_lane_ops atm_lane_ops;
6617 -#endif
6618 +struct atm_lane_ops *atm_lane_ops;
6619  #ifdef CONFIG_ATM_LANE_MODULE
6620  EXPORT_SYMBOL(atm_lane_ops);
6621  #endif
6622 +#endif
6623  
6624  #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
6625  #include <linux/atmmpc.h>
6626  #include "mpc.h"
6627 -struct atm_mpoa_ops atm_mpoa_ops;
6628 +struct atm_mpoa_ops *atm_mpoa_ops;
6629  #endif
6630  #ifdef CONFIG_ATM_MPOA_MODULE
6631  EXPORT_SYMBOL(atm_mpoa_ops);
6632 @@ -52,12 +53,20 @@
6633  
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);
6640  #endif
6641  #endif
6642  
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);
6648 +#endif
6649 +#endif
6650 +
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);
6654 @@ -74,9 +83,6 @@
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 */
6660 -#endif
6661  #include "signaling.h"         /* for WAITING and sigd_attach */
6662  
6663  
6664 @@ -86,8 +92,6 @@
6665  #define DPRINTK(format,args...)
6666  #endif
6667  
6668 -spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
6669 -
6670  static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
6671  {
6672         struct sk_buff *skb;
6673 @@ -99,78 +103,94 @@
6674         }
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);
6679         return skb;
6680  }
6681  
6682  
6683 -int atm_create(struct socket *sock,int protocol,int family)
6684 +static void vcc_destruct(struct sock *sk)
6685 +{
6686 +       if (atomic_read(&sk->rmem_alloc))
6687 +               printk(KERN_WARNING "rmem leakage (%d bytes) detected.\n", atomic_read(&sk->rmem_alloc));
6688 +
6689 +       if (atomic_read(&sk->wmem_alloc))
6690 +               printk(KERN_WARNING "wmem leakage (%d bytes) detected.\n", atomic_read(&sk->wmem_alloc));
6691 +
6692 +       kfree(sk->protinfo.af_atm);
6693 +}
6694 +
6695 +
6696 +int vcc_create(struct socket *sock,int protocol,int family)
6697  {
6698         struct sock *sk;
6699         struct atm_vcc *vcc;
6700  
6701         sock->sk = NULL;
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);
6706 +       if (!sk)
6707 +               return -ENOMEM;
6708 +       sock_init_data(NULL, sk);
6709 +
6710 +       vcc = atm_sk(sk) = kmalloc(sizeof(*vcc), GFP_KERNEL);
6711 +       if (!vcc) {
6712 +               sk_free(sk);
6713 +               return -ENOMEM;
6714 +       }
6715 +       memset(vcc, 0, sizeof(*vcc));
6716 +
6717 +       vcc->sk = sk;
6718         memset(&vcc->flags,0,sizeof(vcc->flags));
6719         vcc->dev = NULL;
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);
6727         vcc->push = NULL;
6728         vcc->pop = NULL;
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;
6735 +
6736 +       sk->destruct = vcc_destruct;
6737         sock->sk = sk;
6738         return 0;
6739  }
6740  
6741  
6742 -void atm_release_vcc_sk(struct sock *sk,int free_sk)
6743 +void vcc_destroy_socket(struct sock *sk)
6744  {
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;
6749  
6750 -       vcc = sk->protinfo.af_atm;
6751         clear_bit(ATM_VF_READY,&vcc->flags);
6752 -       if (vcc->dev) {
6753 -               if (vcc->dev->ops->close) vcc->dev->ops->close(vcc);
6754 +       if (dev) {
6755 +               if (dev->ops->close) dev->ops->close(vcc);
6756                 if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */
6757 +
6758 +               vcc_remove_socket(dev, sk);     /* no more receive */
6759 +
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);
6765 +                       kfree_skb(skb);
6766                 }
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);
6774 -       } else
6775 -               spin_lock (&atm_dev_lock);      
6776  
6777 -       if (free_sk) free_atm_vcc_sk(sk);
6778 +               fops_put (dev->ops);
6779 +               atm_dev_release(dev);
6780 +       }
6781  
6782 -       spin_unlock (&atm_dev_lock);
6783 +       sock_put(sk);
6784  }
6785  
6786 -
6787 -int atm_release(struct socket *sock)
6788 +int vcc_release(struct socket *sock)
6789  {
6790 -       if (sock->sk)
6791 -               atm_release_vcc_sk(sock->sk,1);
6792 +       struct sock *sk = sock->sk;
6793 +       if (sk) {
6794 +               vcc_destroy_socket(sk);
6795 +       }
6796         return 0;
6797  }
6798  
6799 @@ -212,7 +232,105 @@
6800  }
6801  
6802  
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)
6805 +{
6806 +       struct atm_vcc *walk;
6807 +       struct sock *s;
6808 +
6809 +       for(s = vcc_sklist; s; s = s->next) {
6810 +               walk = atm_sk(s);
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;
6817 +               }
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) */
6821 +       }
6822 +       return 0;
6823 +}
6824 +
6825 +
6826 +static int claim_ci(struct atm_dev *dev, struct atm_vcc *vcc, short *vpi, int *vci)
6827 +{
6828 +       static short p = 0; /* poor man's per-device cache */
6829 +       static int c = 0;
6830 +       short old_p;
6831 +       int old_c;
6832 +       int error;
6833 +
6834 +       if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY) {
6835 +               error = check_ci(dev, vcc, *vpi, *vci);
6836 +               return error;
6837 +       }
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;
6844 +       old_p = p;
6845 +       old_c = c;
6846 +       do {
6847 +               if (!check_ci(dev, vcc, p, c)) {
6848 +                       *vpi = p;
6849 +                       *vci = c;
6850 +                       return 0;
6851 +               }
6852 +               if (*vci == ATM_VCI_ANY) {
6853 +                       c++;
6854 +                       if (c >= 1 << dev->ci_range.vci_bits)
6855 +                               c = ATM_NOT_RSV_VCI;
6856 +               }
6857 +               if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
6858 +                   *vpi == ATM_VPI_ANY) {
6859 +                       p++;
6860 +                       if (p >= 1 << dev->ci_range.vpi_bits) p = 0;
6861 +               }
6862 +       }
6863 +       while (old_p != p || old_c != c);
6864 +       return -EADDRINUSE;
6865 +}
6866 +
6867 +
6868 +static void __vcc_insert_socket(struct atm_dev *dev, struct sock *sk)
6869 +{
6870 +       atm_sk(sk)->dev = dev;
6871 +       sk->next = vcc_sklist;
6872 +       if (sk->next)
6873 +               vcc_sklist->pprev = &sk->next;
6874 +       vcc_sklist = sk;
6875 +       sk->pprev = &vcc_sklist;
6876 +}
6877 +
6878 +
6879 +void vcc_insert_socket(struct atm_dev *dev, struct sock *sk)
6880 +{
6881 +       write_lock_irq(&vcc_sklist_lock);
6882 +       __vcc_insert_socket(dev, sk);
6883 +       write_unlock_irq(&vcc_sklist_lock);
6884 +}
6885 +EXPORT_SYMBOL(vcc_insert_socket);
6886 +
6887 +
6888 +void vcc_remove_socket(struct atm_dev *dev, struct sock *sk)
6889 +{
6890 +       write_lock_irq(&vcc_sklist_lock);
6891 +       if (sk->pprev) {
6892 +               if (sk->next)
6893 +                       sk->next->pprev = sk->pprev;
6894 +               *sk->pprev = sk->next;
6895 +               sk->pprev = NULL;
6896 +       }
6897 +       write_unlock_irq(&vcc_sklist_lock);
6898 +}
6899 +EXPORT_SYMBOL(vcc_remove_socket);
6900 +
6901 +
6902 +static int atm_connect_dev(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
6903      int vci)
6904  {
6905         int error;
6906 @@ -223,8 +341,16 @@
6907                 return -EINVAL;
6908         if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
6909                 return -EPERM;
6910 -       error = 0;
6911 -       bind_vcc(vcc,dev);
6912 +       write_lock_irq(&vcc_sklist_lock);
6913 +       error = claim_ci(dev, vcc, &vpi, &vci);
6914 +       if (error) {
6915 +               write_unlock_irq(&vcc_sklist_lock);
6916 +               return error;
6917 +       }
6918 +       vcc->vpi = vpi;
6919 +       vcc->vci = vci;
6920 +       __vcc_insert_socket(dev, vcc->sk);
6921 +       write_unlock_irq(&vcc_sklist_lock);
6922         switch (vcc->qos.aal) {
6923                 case ATM_AAL0:
6924                         error = atm_init_aal0(vcc);
6925 @@ -248,7 +374,7 @@
6926         if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal);
6927         if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal);
6928         if (error) {
6929 -               bind_vcc(vcc,NULL);
6930 +               vcc_remove_socket(dev, vcc->sk);
6931                 return error;
6932         }
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);
6942                 if (error) {
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);
6947                         return error;
6948                 }
6949         }
6950         return 0;
6951  }
6952  
6953 -
6954 -static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci)
6955 -{
6956 -       struct atm_dev *dev;
6957 -       int return_val;
6958 -
6959 -       spin_lock (&atm_dev_lock);
6960 -       dev = atm_find_dev(itf);
6961 -       if (!dev)
6962 -               return_val =  -ENODEV;
6963 -       else
6964 -               return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
6965 -
6966 -       spin_unlock (&atm_dev_lock);
6967 -
6968 -       return return_val;
6969 -}
6970 -
6971 -
6972  int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
6973  {
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 @@
6983                 return -EINVAL;
6984         if (itf != ATM_ITF_ANY) {
6985                 int error;
6986 +               struct atm_dev *dev;
6987  
6988 -               error = atm_do_connect(vcc,itf,vpi,vci);
6989 -               if (error) return error;
6990 -       }
6991 -       else {
6992 +               dev = atm_dev_lookup(itf);
6993 +               if (!dev) return -ENODEV;
6994 +
6995 +               error = atm_connect_dev(vcc,dev,vpi,vci);
6996 +               if (error) {
6997 +                       atm_dev_release(dev);
6998 +                       return error;
6999 +               }
7000 +       } else {
7001                 struct atm_dev *dev = NULL;
7002 -               struct list_head *p;
7003 +               struct list_head *p, *next;
7004  
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);
7014                         dev = NULL;
7015                 }
7016 -               spin_unlock (&atm_dev_lock);
7017                 if (!dev) return -ENODEV;
7018         }
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 */
7026 -               int el, cnt;
7027 -               struct iovec *iov = (struct iovec *)skb->data;
7028 -               unsigned char *p = (unsigned char *)buff;
7029 -
7030 -               el = eff_len;
7031 -               error = 0;
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) ?
7036 -                           -EFAULT : 0;
7037 -                       if (error) break;
7038 -                       p += iov->iov_len;
7039 -                       el -= (iov->iov_len > el)?el:iov->iov_len;
7040 -                       iov++;
7041 -               }
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;
7045 -       }
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);
7049 +       kfree_skb(skb);
7050         return error ? error : eff_len;
7051  }
7052  
7053 @@ -453,7 +544,7 @@
7054         add_wait_queue(&vcc->sleep,&wait);
7055         set_current_state(TASK_INTERRUPTIBLE);
7056         error = 0;
7057 -       while (!(skb = vcc->alloc_tx(vcc,eff))) {
7058 +       while (!(skb = alloc_tx(vcc,eff))) {
7059                 if (m->msg_flags & MSG_DONTWAIT) {
7060                         error = -EAGAIN;
7061                         break;
7062 @@ -478,7 +569,6 @@
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)) {
7069                 kfree_skb(skb);
7070 @@ -498,15 +588,14 @@
7071         vcc = ATM_SD(sock);
7072         poll_wait(file,&vcc->sleep,wait);
7073         mask = 0;
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))
7079                 mask |= POLLHUP;
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;
7086         }
7087         else if (vcc->reply != WAITING) {
7088 @@ -555,7 +644,7 @@
7089  
7090  int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
7091  {
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;
7097 @@ -563,7 +652,6 @@
7098         int error,len,size,number, ret_val;
7099  
7100         ret_val = 0;
7101 -       spin_lock (&atm_dev_lock);
7102         vcc = ATM_SD(sock);
7103         switch (cmd) {
7104                 case SIOCOUTQ:
7105 @@ -581,7 +661,7 @@
7106                                 goto done;
7107                         }
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;
7112                         goto done;
7113                 case SIOCINQ:
7114 @@ -601,13 +689,14 @@
7115                                 goto done;
7116                         }
7117                         size = 0;
7118 +                       read_lock(&atm_dev_lock);
7119                         list_for_each(p, &atm_devs)
7120                                 size += sizeof(int);
7121                         if (size > len) {
7122                                 ret_val = -E2BIG;
7123                                 goto done;
7124                         }
7125 -                       tmp_buf = kmalloc(size,GFP_KERNEL);
7126 +                       tmp_buf = kmalloc(size, GFP_ATOMIC);
7127                         if (!tmp_buf) {
7128                                 ret_val = -ENOMEM;
7129                                 goto done;
7130 @@ -617,6 +706,8 @@
7131                                 dev = list_entry(p, struct atm_dev, dev_list);
7132                                 *tmp_p++ = dev->number;
7133                         }
7134 +                       read_unlock(&atm_dev_lock);
7135 +                       dev = NULL;
7136                         ret_val = ((copy_to_user(buf, tmp_buf, size)) ||
7137                             put_user(size, &((struct atm_iobuf *) arg)->length)
7138                             ) ? -EFAULT : 0;
7139 @@ -654,39 +745,50 @@
7140                         if (!error) sock->state = SS_CONNECTED;
7141                         ret_val = error;
7142                         goto done;
7143 -#ifdef CONFIG_ATM_CLIP
7144 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
7145                 case SIOCMKCLIP:
7146                         if (!capable(CAP_NET_ADMIN))
7147                                 ret_val = -EPERM;
7148                         else 
7149 -                               ret_val = clip_create(arg);
7150 +                               ret_val = atm_clip_ops->clip_create(arg);
7151                         goto done;
7152                 case ATMARPD_CTRL:
7153                         if (!capable(CAP_NET_ADMIN)) {
7154                                 ret_val = -EPERM;
7155                                 goto done;
7156                         }
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");
7162 +#endif
7163 +                       if (atm_clip_ops && !try_inc_mod_count(atm_clip_ops->owner)) {
7164 +                               ret_val = -ENOSYS;
7165 +                               goto done;
7166 +                       }
7167 +                       error = atm_clip_ops->atm_init_atmarp(vcc);
7168 +                       if (!error)
7169 +                               sock->state = SS_CONNECTED;
7170 +                       else
7171 +                               __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
7172                         ret_val = error;
7173                         goto done;
7174                 case ATMARP_MKIP:
7175                         if (!capable(CAP_NET_ADMIN)) 
7176                                 ret_val = -EPERM;
7177                         else 
7178 -                               ret_val = clip_mkip(vcc,arg);
7179 +                               ret_val = atm_clip_ops->clip_mkip(vcc,arg);
7180                         goto done;
7181                 case ATMARP_SETENTRY:
7182                         if (!capable(CAP_NET_ADMIN)) 
7183                                 ret_val = -EPERM;
7184                         else
7185 -                               ret_val = clip_setentry(vcc,arg);
7186 +                               ret_val = atm_clip_ops->clip_setentry(vcc,arg);
7187                         goto done;
7188                 case ATMARP_ENCAP:
7189                         if (!capable(CAP_NET_ADMIN)) 
7190                                 ret_val = -EPERM;
7191                         else
7192 -                               ret_val = clip_encap(vcc,arg);
7193 +                               ret_val = atm_clip_ops->clip_encap(vcc,arg);
7194                         goto done;
7195  #endif
7196  #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
7197 @@ -695,27 +797,32 @@
7198                                 ret_val = -EPERM;
7199                                 goto done;
7200                         }
7201 -                        if (atm_lane_ops.lecd_attach == NULL)
7202 -                               atm_lane_init();
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");
7207 +#endif
7208 +                        if (atm_lane_ops && !try_inc_mod_count(atm_lane_ops->owner)) {
7209                                 ret_val = -ENOSYS;
7210                                 goto done;
7211                         }
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);
7215 +                       if (error >= 0)
7216 +                               sock->state = SS_CONNECTED;
7217 +                       else
7218 +                               __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
7219                         ret_val =  error;
7220                         goto done;
7221                  case ATMLEC_MCAST:
7222                         if (!capable(CAP_NET_ADMIN))
7223                                 ret_val = -EPERM;
7224                         else
7225 -                               ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
7226 +                               ret_val = atm_lane_ops->mcast_attach(vcc, (int)arg);
7227                         goto done;
7228                  case ATMLEC_DATA:
7229                         if (!capable(CAP_NET_ADMIN))
7230                                 ret_val = -EPERM;
7231                         else
7232 -                               ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
7233 +                               ret_val = atm_lane_ops->vcc_attach(vcc, (void*)arg);
7234                         goto done;
7235  #endif
7236  #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
7237 @@ -724,21 +831,26 @@
7238                                 ret_val = -EPERM;
7239                                 goto done;
7240                         }
7241 -                       if (atm_mpoa_ops.mpoad_attach == NULL)
7242 -                                atm_mpoa_init();
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");
7247 +#endif
7248 +                       if (atm_mpoa_ops && !try_inc_mod_count(atm_mpoa_ops->owner)) {
7249                                 ret_val = -ENOSYS;
7250                                 goto done;
7251                         }
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);
7255 +                       if (error >= 0)
7256 +                               sock->state = SS_CONNECTED;
7257 +                       else
7258 +                               __MOD_DEC_USE_COUNT(atm_mpoa_ops->owner);
7259                         ret_val = error;
7260                         goto done;
7261                 case ATMMPC_DATA:
7262                         if (!capable(CAP_NET_ADMIN)) 
7263                                 ret_val = -EPERM;
7264                         else
7265 -                               ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
7266 +                               ret_val = atm_mpoa_ops->vcc_attach(vcc, arg);
7267                         goto done;
7268  #endif
7269  #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
7270 @@ -747,14 +859,14 @@
7271                                 ret_val = -EPERM;
7272                                 goto done;
7273                         }
7274 -                       if (!atm_tcp_ops.attach) {
7275 +                       if (!atm_tcp_ops) {
7276                                 ret_val = -ENOPKG;
7277                                 goto done;
7278                         }
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);
7286                         ret_val = error;
7287                         goto done;
7288                 case ATMTCP_CREATE:
7289 @@ -762,12 +874,12 @@
7290                                 ret_val = -EPERM;
7291                                 goto done;
7292                         }
7293 -                       if (!atm_tcp_ops.create_persistent) {
7294 +                       if (!atm_tcp_ops) {
7295                                 ret_val = -ENOPKG;
7296                                 goto done;
7297                         }
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);
7302                         ret_val = error;
7303                         goto done;
7304                 case ATMTCP_REMOVE:
7305 @@ -775,12 +887,12 @@
7306                                 ret_val = -EPERM;
7307                                 goto done;
7308                         }
7309 -                       if (!atm_tcp_ops.remove_persistent) {
7310 +                       if (!atm_tcp_ops) {
7311                                 ret_val = -ENOPKG;
7312                                 goto done;
7313                         }
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);
7318                         ret_val = error;
7319                         goto done;
7320  #endif
7321 @@ -814,7 +926,7 @@
7322                 ret_val = -EFAULT;
7323                 goto done;
7324         }
7325 -       if (!(dev = atm_find_dev(number))) {
7326 +       if (!(dev = atm_dev_lookup(number))) {
7327                 ret_val = -ENODEV;
7328                 goto done;
7329         }
7330 @@ -963,7 +1075,7 @@
7331                 ret_val = 0;
7332  
7333   done:
7334 -       spin_unlock (&atm_dev_lock); 
7335 +       if (dev) atm_dev_release(dev);
7336         return ret_val;
7337  }
7338  
7339 @@ -1034,17 +1146,21 @@
7340         switch (optname) {
7341                 case SO_ATMQOS:
7342                         {
7343 -                               struct atm_qos qos;
7344 +                               struct atm_qos *qos;
7345  
7346 -                               if (copy_from_user(&qos,optval,sizeof(qos)))
7347 +                               qos = kmalloc(sizeof(*qos), GFP_KERNEL);
7348 +                               if (!qos)
7349 +                                       return -ENOMEM;
7350 +                               if (copy_from_user(qos,optval,sizeof(*qos)))
7351                                         return -EFAULT;
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)
7359                                         return -EBADFD;
7360 -                               vcc->qos = qos;
7361 +                               vcc->qos = *qos;
7362 +                               kfree(qos);
7363                                 set_bit(ATM_VF_HASQOS,&vcc->flags);
7364                                 return 0;
7365                         }
7366 @@ -1122,40 +1238,6 @@
7367  }
7368  
7369  
7370 -/*
7371 - * lane_mpoa_init.c: A couple of helper functions
7372 - * to make modular LANE and MPOA client easier to implement
7373 - */
7374 -
7375 -/*
7376 - * This is how it goes:
7377 - *
7378 - * if xxxx is not compiled as module, call atm_xxxx_init_ops()
7379 - *    from here
7380 - * else call atm_mpoa_init_ops() from init_module() within
7381 - *    the kernel when xxxx module is loaded
7382 - *
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
7386 - */
7387
7388 -extern struct atm_mpoa_ops atm_mpoa_ops; /* in common.c */
7389 -extern struct atm_lane_ops atm_lane_ops; /* in common.c */
7390 -
7391 -#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
7392 -void atm_mpoa_init(void)
7393 -{
7394 -#ifndef CONFIG_ATM_MPOA_MODULE /* not module */
7395 -        atm_mpoa_init_ops(&atm_mpoa_ops);
7396 -#else
7397 -       request_module("mpoa");
7398 -#endif
7399 -
7400 -        return;
7401 -}
7402 -#endif
7403 -
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) */
7412 +
7413  
7414 -void atm_lane_init(void)
7415 +static int __init atm_init(void)
7416  {
7417 -#ifndef CONFIG_ATM_LANE_MODULE /* not module */
7418 -        atm_lane_init_ops(&atm_lane_ops);
7419 -#else
7420 -       request_module("lec");
7421 +       int error = 0;
7422 +
7423 +       if (atmpvc_init() < 0)
7424 +               return -1;
7425 +       if (atmsvc_init() < 0)
7426 +               return -1;
7427 +#ifdef CONFIG_PROC_FS
7428 +        error = atm_proc_init();
7429 +        if (error) printk("atm_proc_init fails with %d\n",error);
7430  #endif
7431 +       return error;
7432 +}
7433  
7434 -        return;
7435 -}        
7436 +static void __exit atm_exit(void)
7437 +{
7438 +#ifdef CONFIG_PROC_FS
7439 +       atm_proc_exit();
7440  #endif
7441 +       atmsvc_exit();
7442 +       atmpvc_exit();
7443 +}
7444 +
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
7451 @@ -10,8 +10,8 @@
7452  #include <linux/poll.h> /* for poll_table */
7453  
7454  
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);
7462 @@ -25,10 +25,17 @@
7463      int *optlen);
7464  
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);
7467 +
7468  void atm_shutdown_dev(struct atm_dev *dev);
7469  
7470 +int atmsvc_init(void);
7471 +void atmsvc_exit(void);
7472 +
7473 +int atmpvc_init(void);
7474 +void atmpvc_exit(void);
7475 +
7476  int atm_proc_init(void);
7477 +void atm_proc_exit(void);
7478  
7479  /* SVC */
7480  
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
7484 @@ -66,5 +66,5 @@
7485         spin_unlock_irqrestore(&from->lock,flags);
7486  }
7487  
7488 -
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
7494 @@ -13,8 +13,6 @@
7495  #include <linux/atmdev.h>
7496  
7497  
7498 -extern struct net_device *clip_devs;
7499 -
7500  /*
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
7506 @@ -20,6 +20,7 @@
7507  #include <net/arp.h>
7508  #include <net/dst.h>
7509  #include <linux/proc_fs.h>
7510 +#include <linux/spinlock.h>
7511  
7512  /* TokenRing if needed */
7513  #ifdef CONFIG_TR
7514 @@ -35,6 +36,10 @@
7515  #include <linux/if_bridge.h>
7516  #include "../bridge/br_private.h"
7517  static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
7518 +
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);
7522  #endif
7523  
7524  /* Modular too */
7525 @@ -43,7 +48,7 @@
7526  
7527  #include "lec.h"
7528  #include "lec_arpc.h"
7529 -#include "resources.h"  /* for bind_vcc() */
7530 +#include "resources.h"
7531  
7532  #if 0
7533  #define DPRINTK printk
7534 @@ -51,10 +56,7 @@
7535  #define DPRINTK(format,args...)
7536  #endif
7537  
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);
7541 -
7542 +static spinlock_t lec_arp_spinlock = SPIN_LOCK_UNLOCKED;
7543  
7544  #define DUMP_PACKETS 0 /* 0 = None,
7545                          * 1 = 30 first bytes
7546 @@ -196,6 +198,22 @@
7547          return 0;
7548  }
7549  
7550 +static __inline__ void
7551 +lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
7552 +{
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);
7560 +       } else {
7561 +               priv->stats.tx_dropped++;
7562 +               dev_kfree_skb(skb);
7563 +       }
7564 +}
7565 +
7566  static int 
7567  lec_send_packet(struct sk_buff *skb, struct net_device *dev)
7568  {
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);
7583 -                } else {
7584 -                        priv->stats.tx_dropped++;
7585 -                        dev_kfree_skb(skb2);
7586 -               }
7587 +               lec_send(send_vcc, skb2, priv);
7588          }
7589  
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);
7598 -        } else {
7599 -                priv->stats.tx_dropped++;
7600 -                dev_kfree_skb(skb);
7601 -       }
7602 +       lec_send(send_vcc, skb, priv);
7603  
7604  #if 0
7605          /* Should we wait for card's device driver to notify us? */
7606 @@ -404,7 +398,7 @@
7607          int i;
7608          char *tmp; /* FIXME */
7609  
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;
7613          tmp = skb->data;
7614          tmp += sizeof(struct atmlec_msg);
7615 @@ -548,24 +542,19 @@
7616          }
7617    
7618         printk("%s: Shut down!\n", dev->name);
7619 -        MOD_DEC_USE_COUNT;
7620 +       __MOD_DEC_USE_COUNT(THIS_MODULE);
7621  }
7622  
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
7628  };
7629  
7630  static struct atm_dev lecatm_dev = {
7631 -        &lecdev_ops,
7632 -        NULL,      /*PHY*/
7633 -        "lec",     /*type*/
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,
7641 +       .type =                 "lec",
7642 +       .number =               999,
7643 +       .lock =                 SPIN_LOCK_UNLOCKED,
7644  };
7645  
7646  /*
7647 @@ -726,6 +723,7 @@
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));
7652                  netif_rx(skb);
7653          }
7654  }
7655 @@ -812,7 +810,7 @@
7656          lec_arp_init(priv);
7657         priv->itfnum = i;  /* LANE2 addition */
7658          priv->lecd = vcc;
7659 -        bind_vcc(vcc, &lecatm_dev);
7660 +        vcc_insert_socket(&lecatm_dev, vcc->sk);
7661          
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]);
7667          }
7668 -        MOD_INC_USE_COUNT;
7669          return i;
7670  }
7671  
7672 -void atm_lane_init_ops(struct atm_lane_ops *ops)
7673 -{
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;
7678 -
7679 -        printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
7680 -
7681 -       return;
7682 -}
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
7689 +};
7690  
7691  static int __init lane_module_init(void)
7692  {
7693 -        extern struct atm_lane_ops atm_lane_ops;
7694 +        extern struct atm_lane_ops *atm_lane_ops;
7695  
7696 -        atm_lane_init_ops(&atm_lane_ops);
7697 +        atm_lane_ops = &__atm_lane_ops;
7698 +        printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
7699  
7700          return 0;
7701  }
7702 @@ -861,13 +855,10 @@
7703  static void __exit lane_module_cleanup(void)
7704  {
7705          int i;
7706 -        extern struct atm_lane_ops atm_lane_ops;
7707 +        extern struct atm_lane_ops *atm_lane_ops;
7708          struct lec_priv *priv;
7709  
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;
7715  
7716          for (i = 0; i < MAX_LEC_ITF; i++) {
7717                  if (dev_lec[i] != NULL) {
7718 @@ -880,7 +871,7 @@
7719                          unregister_netdev(dev_lec[i]);
7720                          kfree(dev_lec[i]);
7721                          dev_lec[i] = NULL;
7722 -                }
7723 +              }
7724          }
7725  
7726          return;                                    
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>
7734  
7735  
7736 @@ -1055,15 +1046,15 @@
7737  #define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))
7738  
7739  static __inline__ void 
7740 -lec_arp_lock(struct lec_priv *priv)
7741 +lec_arp_get(struct lec_priv *priv)
7742  {
7743 -        atomic_inc(&priv->lec_arp_lock_var);
7744 +        atomic_inc(&priv->lec_arp_users);
7745  }
7746  
7747  static __inline__ void 
7748 -lec_arp_unlock(struct lec_priv *priv)
7749 +lec_arp_put(struct lec_priv *priv)
7750  {
7751 -        atomic_dec(&priv->lec_arp_lock_var);
7752 +        atomic_dec(&priv->lec_arp_users);
7753  }
7754  
7755  /*
7756 @@ -1114,33 +1105,33 @@
7757   * LANE2: Add to the end of the list to satisfy 8.1.13
7758   */
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)
7764  {
7765 -        unsigned short place;
7766          unsigned long flags;
7767 +        unsigned short place;
7768          struct lec_arp_table *tmp;
7769  
7770 -        save_flags(flags);
7771 -        cli();
7772 +        spin_lock_irqsave(&lec_arp_spinlock, flags);
7773  
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;
7779          if (tmp == NULL)
7780 -                lec_arp_tables[place] = to_put;
7781 +                lec_arp_tables[place] = to_add;
7782    
7783          else {  /* add to the end */
7784                  while (tmp->next)
7785                          tmp = tmp->next;
7786 -                tmp->next = to_put;
7787 +                tmp->next = to_add;
7788          }
7789  
7790 -        restore_flags(flags);
7791 +        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7792 +
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]);
7800  }
7801  
7802  /*
7803 @@ -1150,16 +1141,15 @@
7804  lec_arp_remove(struct lec_arp_table **lec_arp_tables,
7805                 struct lec_arp_table *to_remove)
7806  {
7807 +        unsigned long flags;
7808          unsigned short place;
7809          struct lec_arp_table *tmp;
7810 -        unsigned long flags;
7811          int remove_vcc=1;
7812  
7813 -        save_flags(flags);
7814 -        cli();
7815 +        spin_lock_irqsave(&lec_arp_spinlock, flags);
7816  
7817          if (!to_remove) {
7818 -                restore_flags(flags);
7819 +                spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7820                  return -1;
7821          }
7822          place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
7823 @@ -1171,7 +1161,7 @@
7824                          tmp = tmp->next;
7825                  }
7826                  if (!tmp) {/* Entry was not found */
7827 -                        restore_flags(flags);
7828 +                        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7829                          return -1;
7830                  }
7831          }
7832 @@ -1197,7 +1187,9 @@
7833                          lec_arp_clear_vccs(to_remove);
7834          }
7835          skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
7836 -        restore_flags(flags);
7837 +
7838 +        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
7839 +
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)
7845  {
7846          struct lec_arp_table *entry, *next;
7847 -        unsigned long flags;
7848          int i;
7849  
7850 -        save_flags(flags);
7851 -        cli();
7852 -
7853          del_timer(&priv->lec_arp_timer);
7854          
7855          /*
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);
7861  }
7862  
7863  
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]);
7871    
7872          to_return = priv->lec_arp_tables[place];
7873          while(to_return) {
7874                  if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) {
7875 -                        lec_arp_unlock(priv);
7876 +                        lec_arp_put(priv);
7877                          return to_return;
7878                  }
7879                  to_return = to_return->next;
7880          }
7881 -        lec_arp_unlock(priv);
7882 +        lec_arp_put(priv);
7883          return NULL;
7884  }
7885  
7886 @@ -1585,11 +1572,11 @@
7887          del_timer(&priv->lec_arp_timer);
7888  
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);
7898                  now = jiffies;
7899                  for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
7900                          for(entry = lec_arp_tables[i];entry != NULL;) {
7901 @@ -1627,6 +1614,10 @@
7902                                             &&
7903                                             time_after_eq(now, entry->timestamp+
7904                                             priv->path_switching_delay)) {
7905 +                                               struct sk_buff *skb;
7906 +
7907 +                                               while ((skb = skb_dequeue(&entry->tx_wait)))
7908 +                                                       lec_send(entry->vcc, skb, entry->priv);
7909                                                  entry->last_used = jiffies;
7910                                                  entry->status = 
7911                                                          ESI_FORWARD_DIRECT;
7912 @@ -1635,7 +1626,7 @@
7913                                  }
7914                          }
7915                  }
7916 -                lec_arp_unlock(priv);
7917 +                lec_arp_put(priv);
7918          }
7919          priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
7920          add_timer(&priv->lec_arp_timer);
7921 @@ -1697,7 +1688,7 @@
7922                  if (!entry) {
7923                          return priv->mcast_vcc;
7924                  }
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;
7932          int i;
7933  
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);
7941                                  kfree(entry);
7942                          }
7943 -                        lec_arp_unlock(priv);
7944 +                        lec_arp_put(priv);
7945                          return 0;
7946                  }
7947          }
7948 -        lec_arp_unlock(priv);
7949 +        lec_arp_put(priv);
7950          return -1;
7951  }
7952  
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
7956                             */
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);
7968                          }
7969                          if (remoteflag)
7970                                  entry->flags|=LEC_REMOTE_FLAG;
7971                          else
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);
7977                          return;
7978 @@ -1812,11 +1803,11 @@
7979          if (!entry) {
7980                  entry = make_entry(priv, mac_addr);
7981                  if (!entry) {
7982 -                        lec_arp_unlock(priv);
7983 +                        lec_arp_put(priv);
7984                          return;
7985                  }
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 */
7990          }
7991          memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
7992 @@ -1851,7 +1842,7 @@
7993          }
7994          DPRINTK("After update2\n");
7995          dump_arp_table(priv);
7996 -        lec_arp_unlock(priv);
7997 +        lec_arp_put(priv);
7998  }
7999  
8000  /*
8001 @@ -1865,7 +1856,7 @@
8002          struct lec_arp_table *entry;
8003          int i, found_entry=0;
8004  
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 */
8009  
8010 @@ -1874,7 +1865,7 @@
8011                  entry = lec_arp_find(priv, bus_mac);
8012                  if (!entry) {
8013                          printk("LEC_ARP: Multicast entry not found!\n");
8014 -                        lec_arp_unlock(priv);
8015 +                        lec_arp_put(priv);
8016                          return;
8017                  }
8018                  memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
8019 @@ -1883,7 +1874,7 @@
8020  #endif
8021                  entry = make_entry(priv, bus_mac);
8022                  if (entry == NULL) {
8023 -                        lec_arp_unlock(priv);
8024 +                        lec_arp_put(priv);
8025                          return;
8026                  }
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);
8034                  return;
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);
8043                          return;
8044                  }
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);
8053                  return;
8054          }
8055 @@ -1982,7 +1973,7 @@
8056                  }
8057          }
8058          if (found_entry) {
8059 -                lec_arp_unlock(priv);
8060 +                lec_arp_put(priv);
8061                  DPRINTK("After vcc was added\n");
8062                  dump_arp_table(priv);
8063                  return;
8064 @@ -1991,7 +1982,7 @@
8065             this vcc */
8066          entry = make_entry(priv, bus_mac);
8067          if (!entry) {
8068 -                lec_arp_unlock(priv);
8069 +                lec_arp_put(priv);
8070                  return;
8071          }
8072          entry->vcc = vcc;
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);
8081  }
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;
8087 +
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");
8092                          }
8093 @@ -2050,10 +2045,10 @@
8094                  0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
8095          struct lec_arp_table *to_add;
8096    
8097 -        lec_arp_lock(priv);
8098 +        lec_arp_get(priv);
8099          to_add = make_entry(priv, mac_addr);
8100          if (!to_add) {
8101 -                lec_arp_unlock(priv);
8102 +                lec_arp_put(priv);
8103                  return -ENOMEM;
8104          }
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);
8114          return 0;
8115  }
8116  
8117 @@ -2076,7 +2071,7 @@
8118  
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) {
8125                          next = entry->next;
8126 @@ -2138,7 +2133,7 @@
8127                  entry = next;
8128          }
8129  
8130 -        lec_arp_unlock(priv);
8131 +        lec_arp_put(priv);
8132         dump_arp_table(priv);
8133  }
8134  
8135 @@ -2146,9 +2141,9 @@
8136  lec_arp_check_empties(struct lec_priv *priv,
8137                        struct atm_vcc *vcc, struct sk_buff *skb)
8138  {
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;
8143          unsigned char *src;
8144  #ifdef CONFIG_TR
8145          struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
8146 @@ -2158,50 +2153,49 @@
8147  #endif
8148          src = hdr->h_source;
8149  
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);
8155 -                cli();
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);
8167                          kfree(prev);
8168                  }
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);
8173                  return;
8174          }
8175 +        spin_lock_irqsave(&lec_arp_spinlock, flags);
8176          prev = entry;
8177          entry = entry->next;
8178          while (entry && entry->vcc != vcc) {
8179 -                prev= entry;
8180 +                prev = entry;
8181                  entry = entry->next;
8182          }
8183          if (!entry) {
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);
8188                  return;
8189          }
8190 -        save_flags(flags);
8191 -        cli();
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);
8201                  kfree(prev);
8202          }
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);  
8207  }
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
8212 @@ -65,6 +65,7 @@
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;
8217  };
8218  
8219  /*
8220 @@ -101,7 +102,7 @@
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;
8229 @@ -155,7 +156,5 @@
8230                   unsigned char *atm_addr, struct sk_buff *data);
8231  void lec_push(struct atm_vcc *vcc, struct sk_buff *skb);
8232  
8233 -void atm_lane_init(void);
8234 -void atm_lane_init_ops(struct atm_lane_ops *ops);
8235  #endif /* _LEC_H_ */
8236  
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
8240 @@ -28,7 +28,7 @@
8241  
8242  #include "lec.h"
8243  #include "mpc.h"
8244 -#include "resources.h"  /* for bind_vcc() */
8245 +#include "resources.h"
8246  
8247  /*
8248   * mpc.c: Implementation of MPOA client kernel part 
8249 @@ -521,7 +521,6 @@
8250         }
8251  
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++;
8257 @@ -730,6 +729,7 @@
8258         eg->packets_rcvd++;
8259         mpc->eg_ops->put(eg);
8260  
8261 +       memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
8262         netif_rx(new_skb);
8263  
8264         return;
8265 @@ -741,18 +741,10 @@
8266  };
8267  
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 */
8281 +       .ops =                  &mpc_ops,
8282 +       .type =                 "mpc",
8283 +       .number =               42,
8284 +       .lock =                 SPIN_LOCK_UNLOCKED
8285  };
8286  
8287  int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
8288 @@ -791,7 +783,7 @@
8289         }
8290  
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);
8296  
8297 @@ -807,7 +799,6 @@
8298                         send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
8299         }
8300  
8301 -       MOD_INC_USE_COUNT;
8302         return arg;
8303  }
8304  
8305 @@ -856,7 +847,7 @@
8306         
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);
8311  
8312         return;
8313  }
8314 @@ -869,7 +860,7 @@
8315         
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);
8320         
8321         if (mpc == NULL) {
8322                 printk("mpoa: msg_from_mpoad: no mpc found\n");
8323 @@ -1398,11 +1389,17 @@
8324         return;
8325  }
8326  
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
8332 +};
8333 +
8334 +static int __init atm_mpoa_init(void)
8335  {
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;
8339  
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 @@
8345  
8346         printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
8347  
8348 -       return;
8349 -}
8350 -
8351 -#ifdef MODULE
8352 -int init_module(void)
8353 -{
8354 -       extern struct atm_mpoa_ops atm_mpoa_ops;
8355 -
8356 -       atm_mpoa_init_ops(&atm_mpoa_ops);
8357 -
8358         return 0;
8359  }
8360  
8361 -void cleanup_module(void)
8362 +static void __exit atm_mpoa_cleanup(void)
8363  {
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 @@
8370  
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;
8376  
8377         mpc = mpcs;
8378         mpcs = NULL;
8379 @@ -1475,8 +1461,9 @@
8380                 kfree(qos);
8381                 qos = nextqos;
8382         }
8383 -
8384 -       return;
8385  }
8386 -#endif /* MODULE */
8387 +
8388 +module_init(atm_mpoa_init);
8389 +module_exit(atm_mpoa_cleanup);
8390 +
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
8395 @@ -48,11 +48,8 @@
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;
8400  };
8401 -
8402 -/* Boot/module initialization function */
8403 -void atm_mpoa_init(void);
8404 -void atm_mpoa_init_ops(struct atm_mpoa_ops *ops);
8405  
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
8411 @@ -232,7 +232,6 @@
8412                 return 1;
8413         }
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
8422 @@ -39,16 +39,15 @@
8423  #include "common.h" /* atm_proc_init prototype */
8424  #include "signaling.h" /* to get sigd - ugly too */
8425  
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 */
8432  #endif
8433  
8434  #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
8435  #include "lec.h"
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 */
8439  #endif
8440  
8441  static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
8442 @@ -85,11 +84,12 @@
8443         add_stats(buf,"0",&dev->stats.aal0);
8444         strcat(buf,"  ");
8445         add_stats(buf,"5",&dev->stats.aal5);
8446 +       sprintf(strchr(buf,0), "        %d", atomic_read(&dev->refcnt));
8447         strcat(buf,"\n");
8448  }
8449  
8450  
8451 -#ifdef CONFIG_ATM_CLIP
8452 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
8453  
8454  
8455  static int svc_addr(char *buf,struct sockaddr_atmsvc *addr)
8456 @@ -178,8 +178,8 @@
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;
8466  
8467 @@ -220,10 +220,11 @@
8468                 default:
8469                         here += sprintf(here,"%3d",vcc->sk->family);
8470         }
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,
8473             vcc->reply,
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));
8478  }
8479  
8480  
8481 @@ -311,26 +312,24 @@
8482                     "AAL(TX,err,RX,err,drop) ...\n");
8483         }
8484         left = pos-1;
8485 +       read_lock(&atm_dev_lock);
8486         list_for_each(p, &atm_devs) {
8487                 dev = list_entry(p, struct atm_dev, dev_list);
8488                 if (left-- == 0) {
8489                         dev_info(dev,buf);
8490 +                       read_unlock(&atm_dev_lock);
8491                         return strlen(buf);
8492                 }
8493         }
8494 +       read_unlock(&atm_dev_lock);
8495         return 0;
8496  }
8497  
8498 -/*
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.
8501 - */
8502  
8503  static int atm_pvc_info(loff_t pos,char *buf)
8504  {
8505 -       struct atm_dev *dev;
8506 -       struct list_head *p;
8507         struct atm_vcc *vcc;
8508 +       struct sock *s;
8509         int left;
8510  
8511         if (!pos) {
8512 @@ -338,24 +337,25 @@
8513                     "TX(PCR,Class)\n");
8514         }
8515         left = pos-1;
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);
8523 -                       }
8524 +       read_lock(&vcc_sklist_lock);
8525 +       for(s = vcc_sklist; s; s = s->next) {
8526 +               vcc = atm_sk(s);
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);
8532 +               }
8533         }
8534 +       read_unlock(&vcc_sklist_lock);
8535         return 0;
8536  }
8537  
8538  
8539  static int atm_vc_info(loff_t pos,char *buf)
8540  {
8541 -       struct atm_dev *dev;
8542 -       struct list_head *p;
8543         struct atm_vcc *vcc;
8544 +       struct sock *s;
8545         int left;
8546  
8547         if (!pos)
8548 @@ -363,19 +363,16 @@
8549                     "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
8550                     "     Recv buffer\n");
8551         left = pos-1;
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)
8555 -                       if (!left--) {
8556 -                               vc_info(vcc,buf);
8557 -                               return strlen(buf);
8558 -                       }
8559 -       }
8560 -       for (vcc = nodev_vccs; vcc; vcc = vcc->next)
8561 +       read_lock(&vcc_sklist_lock);
8562 +       for(s = vcc_sklist; s; s = s->next) {
8563 +               vcc = atm_sk(s);
8564                 if (!left--) {
8565                         vc_info(vcc,buf);
8566 +                       read_unlock(&vcc_sklist_lock);
8567                         return strlen(buf);
8568                 }
8569 +       }
8570 +       read_unlock(&vcc_sklist_lock);
8571  
8572         return 0;
8573  }
8574 @@ -383,31 +380,28 @@
8575  
8576  static int atm_svc_info(loff_t pos,char *buf)
8577  {
8578 -       struct atm_dev *dev;
8579 -       struct list_head *p;
8580         struct atm_vcc *vcc;
8581 +       struct sock *s;
8582         int left;
8583  
8584         if (!pos)
8585                 return sprintf(buf,"Itf VPI VCI           State      Remote\n");
8586         left = pos-1;
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);
8593 -                       }
8594 -       }
8595 -       for (vcc = nodev_vccs; vcc; vcc = vcc->next)
8596 +       read_lock(&vcc_sklist_lock);
8597 +       for(s = vcc_sklist; s; s = s->next) {
8598 +               vcc = atm_sk(s);
8599                 if (vcc->sk->family == PF_ATMSVC && !left--) {
8600                         svc_info(vcc,buf);
8601 +                       read_unlock(&vcc_sklist_lock);
8602                         return strlen(buf);
8603                 }
8604 +       }
8605 +       read_unlock(&vcc_sklist_lock);
8606 +
8607         return 0;
8608  }
8609  
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)
8613  {
8614         struct neighbour *n;
8615 @@ -417,28 +411,30 @@
8616                 return sprintf(buf,"IPitf TypeEncp Idle IP address      "
8617                     "ATM address\n");
8618         }
8619 +       if (!clip_tbl_hook)
8620 +               return 0;
8621         count = pos;
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;
8629  
8630                         if (!entry->vccs) {
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);
8635                                 return strlen(buf);
8636                         }
8637                         for (vcc = entry->vccs; vcc;
8638                             vcc = vcc->next) {
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);
8643                                 return strlen(buf);
8644                         }
8645                 }
8646 -       read_unlock_bh(&clip_tbl.lock);
8647 +       read_unlock_bh(&clip_tbl_hook->lock);
8648         return 0;
8649  }
8650  #endif
8651 @@ -456,10 +452,13 @@
8652                     "                          Status            Flags "
8653                     "VPI/VCI Recv VPI/VCI\n");
8654         }
8655 -       if (atm_lane_ops.get_lecs == NULL)
8656 +       if (!atm_lane_ops)
8657                 return 0; /* the lane module is not there yet */
8658 -       else
8659 -               dev_lec = atm_lane_ops.get_lecs();
8660 +
8661 +       if (!try_inc_mod_count(atm_lane_ops->owner))
8662 +               return 0;
8663 +
8664 +       dev_lec = atm_lane_ops->get_lecs();
8665  
8666         count = pos;
8667         for(d=0;d<MAX_LEC_ITF;d++) {
8668 @@ -472,6 +471,7 @@
8669                                 e=sprintf(buf,"%s ",
8670                                     dev_lec[d]->name);
8671                                 lec_info(entry,buf+e);
8672 +                               __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
8673                                 return strlen(buf);
8674                         }
8675                 }
8676 @@ -480,6 +480,7 @@
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);
8681                         return strlen(buf);
8682                 }
8683                 for(entry=priv->lec_no_forward; entry;
8684 @@ -487,6 +488,7 @@
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);
8689                         return strlen(buf);
8690                 }
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);
8697                         return strlen(buf);
8698                 }
8699         }
8700 +       __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
8701         return 0;
8702  }
8703  #endif
8704 @@ -566,7 +570,7 @@
8705         for (num = dev->number; num; num /= 10) digits++;
8706         if (!digits) digits++;
8707  
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)
8711                 goto fail1;
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
8716  
8717 +struct proc_dir_entry *devices = NULL, *pvc = NULL, *svc = NULL;
8718 +struct proc_dir_entry *arp = NULL, *lec = NULL, *vc = NULL;
8719  
8720  int __init atm_proc_init(void)
8721  {
8722 -       struct proc_dir_entry *devices = NULL,*pvc = NULL,*svc = NULL;
8723 -       struct proc_dir_entry *arp = NULL,*lec = NULL,*vc = NULL;
8724 -
8725         atm_proc_root = proc_mkdir("net/atm",NULL);
8726         if (!atm_proc_root)
8727                 return -ENOMEM;
8728 @@ -612,7 +615,7 @@
8729         CREATE_ENTRY(pvc);
8730         CREATE_ENTRY(svc);
8731         CREATE_ENTRY(vc);
8732 -#ifdef CONFIG_ATM_CLIP
8733 +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
8734         CREATE_ENTRY(arp);
8735  #endif
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);
8740         return -ENOMEM;
8741 +}
8742 +
8743 +void __exit atm_proc_exit(void)
8744 +{
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);
8752  }
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
8756 @@ -15,17 +15,10 @@
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>
8762 -#endif
8763  
8764  #include "resources.h"         /* devs and vccs */
8765  #include "common.h"            /* common for PVCs and SVCs */
8766  
8767 -#ifndef NULL
8768 -#define NULL 0
8769 -#endif
8770 -
8771  
8772  static int pvc_shutdown(struct socket *sock,int how)
8773  {
8774 @@ -77,45 +70,38 @@
8775  }
8776  
8777  
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,
8782  
8783 -       release:        atm_release,
8784 -       bind:           pvc_bind,
8785 -       connect:        pvc_connect,
8786 -       socketpair:     sock_no_socketpair,
8787 -       accept:         sock_no_accept,
8788 -       getname:        pvc_getname,
8789 -       poll:           atm_poll,
8790 -       ioctl:          atm_ioctl,
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,
8800 +       .bind =         pvc_bind,
8801 +       .connect =      pvc_connect,
8802 +       .socketpair =   sock_no_socketpair,
8803 +       .accept =       sock_no_accept,
8804 +       .getname =      pvc_getname,
8805 +       .poll =         atm_poll,
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,
8815  };
8816  
8817  
8818 -#include <linux/smp_lock.h>
8819 -SOCKOPS_WRAP(pvc_proto, PF_ATMPVC);
8820 -
8821 -
8822  static int pvc_create(struct socket *sock,int protocol)
8823  {
8824         sock->ops = &pvc_proto_ops;
8825 -       return atm_create(sock,protocol,PF_ATMPVC);
8826 +       return vcc_create(sock,protocol,PF_ATMPVC);
8827  }
8828  
8829  
8830  static struct net_proto_family pvc_family_ops = {
8831 -       PF_ATMPVC,
8832 -       pvc_create,
8833 -       0,                      /* no authentication */
8834 -       0,                      /* no encryption */
8835 -       0                       /* no encrypt_net */
8836 +       .family = PF_ATMPVC,
8837 +       .create = pvc_create,
8838  };
8839  
8840  
8841 @@ -124,23 +110,20 @@
8842   */
8843  
8844  
8845 -static int __init atmpvc_init(void)
8846 +int __init atmpvc_init(void)
8847  {
8848         int error;
8849  
8850         error = sock_register(&pvc_family_ops);
8851         if (error < 0) {
8852 -               printk(KERN_ERR "ATMPVC: can't register (%d)",error);
8853 +               printk(KERN_ERR "ATMPVC: can't register (%d)", error);
8854                 return error;
8855         }
8856 -#ifdef CONFIG_ATM_CLIP
8857 -       atm_clip_init();
8858 -#endif
8859 -#ifdef CONFIG_PROC_FS
8860 -       error = atm_proc_init();
8861 -       if (error) printk("atm_proc_init fails with %d\n",error);
8862 -#endif
8863 -       return 0;
8864 +
8865 +       return error;
8866  }
8867  
8868 -module_init(atmpvc_init);
8869 +void __exit atmpvc_exit(void)
8870 +{
8871 +       sock_unregister(PF_ATMPVC);
8872 +}
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
8876 @@ -37,7 +37,7 @@
8877  static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
8878  {
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);
8884  }
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
8888 @@ -2,7 +2,6 @@
8889  
8890  /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
8891  
8892 -
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 */
8901  
8902  #include "common.h"
8903  #include "resources.h"
8904  
8905 -
8906 -#ifndef NULL
8907 -#define NULL 0
8908 -#endif
8909 -
8910 +struct sock *vcc_sklist = NULL;
8911 +rwlock_t vcc_sklist_lock = RW_LOCK_UNLOCKED;
8912  
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;
8917  
8918  
8919 -static struct atm_dev *alloc_atm_dev(const char *type)
8920 +static struct atm_dev *__alloc_atm_dev(const char *type)
8921  {
8922         struct atm_dev *dev;
8923  
8924         dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
8925 -       if (!dev) return NULL;
8926 -       memset(dev,0,sizeof(*dev));
8927 +       if (!dev)
8928 +               return NULL;
8929 +       memset(dev, 0, sizeof(*dev));
8930         dev->type = type;
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);
8938  
8939         return dev;
8940  }
8941  
8942  
8943 -static void free_atm_dev(struct atm_dev *dev)
8944 +static void __free_atm_dev(struct atm_dev *dev)
8945  {
8946 -       list_del(&dev->dev_list);
8947         kfree(dev);
8948  }
8949  
8950 -struct atm_dev *atm_find_dev(int number)
8951 +static struct atm_dev *__atm_dev_lookup(int number)
8952  {
8953         struct atm_dev *dev;
8954         struct list_head *p;
8955  
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);
8961                         return dev;
8962 +               }
8963         }
8964         return NULL;
8965  }
8966  
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)
8970  {
8971 -       struct atm_dev *dev = NULL;
8972 +       struct atm_dev *dev;
8973 +
8974 +       read_lock(&atm_dev_lock);
8975 +       dev = __atm_dev_lookup(number);
8976 +       read_unlock(&atm_dev_lock);
8977 +       return dev;
8978 +}
8979  
8980 -       spin_lock(&atm_dev_lock);
8981 +void atm_dev_hold(struct atm_dev *dev)
8982 +{
8983 +       atomic_inc(&dev->refcnt);
8984 +}
8985  
8986 -       dev = alloc_atm_dev(type);
8987 +void atm_dev_release(struct atm_dev *dev)
8988 +{
8989 +       atomic_dec(&dev->refcnt);
8990 +
8991 +       if ((atomic_read(&dev->refcnt) == 1) &&
8992 +           test_bit(ATM_DF_CLOSE,&dev->flags))
8993 +               shutdown_atm_dev(dev);
8994 +}
8995 +
8996 +
8997 +struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
8998 +                                int number, atm_dev_flags_t *flags)
8999 +{
9000 +       struct atm_dev *dev, *inuse;
9001 +
9002 +       dev = __alloc_atm_dev(type);
9003         if (!dev) {
9004                 printk(KERN_ERR "atm_dev_register: no space for dev %s\n",
9005                     type);
9006 -               goto done;
9007 +               return NULL;
9008         }
9009 +       write_lock(&atm_dev_lock);
9010         if (number != -1) {
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);
9017                         return NULL;
9018                 }
9019                 dev->number = number;
9020         } else {
9021                 dev->number = 0;
9022 -               while (atm_find_dev(dev->number)) dev->number++;
9023 +               while ((inuse = __atm_dev_lookup(dev->number))) {
9024 +                       atm_dev_release(inuse);
9025 +                       dev->number++;
9026 +               }
9027         }
9028 -       dev->vccs = dev->last = NULL;
9029 -       dev->dev_data = NULL;
9030 -       barrier();
9031 +
9032         dev->ops = ops;
9033 -       if (flags) 
9034 +       if (flags)
9035                 dev->flags = *flags;
9036 -       else 
9037 -               memset(&dev->flags,0,sizeof(dev->flags));
9038 -       memset((void *) &dev->stats,0,sizeof(dev->stats));
9039 +       else
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);
9044 +       barrier();
9045 +
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);
9053 -                       goto done;
9054 +                              "atm_proc_dev_register failed for dev %s\n",
9055 +                              type);
9056 +                       write_lock(&atm_dev_lock);
9057 +                       list_del(&dev->dev_list);
9058 +                       write_unlock(&atm_dev_lock);
9059 +                       __free_atm_dev(dev);
9060 +                       return NULL;
9061                 }
9062 +       }
9063  #endif
9064  
9065 -done:
9066 -       spin_unlock(&atm_dev_lock);
9067         return dev;
9068  }
9069  
9070  
9071  void atm_dev_deregister(struct atm_dev *dev)
9072  {
9073 +       unsigned long warning_time;
9074 +
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);
9079  #endif
9080 -       spin_lock(&atm_dev_lock);
9081 -       free_atm_dev(dev);
9082 -       spin_unlock(&atm_dev_lock);
9083 -}
9084 -
9085 -void shutdown_atm_dev(struct atm_dev *dev)
9086 -{
9087 -       if (dev->vccs) {
9088 -               set_bit(ATM_DF_CLOSE,&dev->flags);
9089 -               return;
9090 -       }
9091 -       if (dev->ops->dev_close) dev->ops->dev_close(dev);
9092 -       atm_dev_deregister(dev);
9093 -}
9094 -
9095 -
9096 -/* Handler for sk->destruct, invoked by sk_free() */
9097 -static void atm_free_sock(struct sock *sk)
9098 -{
9099 -       kfree(sk->protinfo.af_atm);
9100 -}
9101 -
9102 -struct sock *alloc_atm_vcc_sk(int family)
9103 -{
9104 -       struct sock *sk;
9105 -       struct atm_vcc *vcc;
9106 -
9107 -       sk = sk_alloc(family, GFP_KERNEL, 1);
9108 -       if (!sk) return NULL;
9109 -       vcc = sk->protinfo.af_atm = kmalloc(sizeof(*vcc),GFP_KERNEL);
9110 -       if (!vcc) {
9111 -               sk_free(sk);
9112 -               return NULL;
9113 -       }
9114 -       sock_init_data(NULL,sk);
9115 -       sk->destruct = atm_free_sock;
9116 -       memset(vcc,0,sizeof(*vcc));
9117 -       vcc->sk = sk;
9118 -       if (nodev_vccs) nodev_vccs->prev = vcc;
9119 -       vcc->prev = NULL;
9120 -       vcc->next = nodev_vccs;
9121 -       nodev_vccs = vcc;
9122 -       return sk;
9123 -}
9124 -
9125 -
9126 -static void unlink_vcc(struct atm_vcc *vcc,struct atm_dev *hold_dev)
9127 -{
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);
9136 -}
9137 +       write_lock(&atm_dev_lock);
9138 +       list_del(&dev->dev_list);
9139 +       write_unlock(&atm_dev_lock);
9140  
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;
9151 +                }
9152 +        }
9153  
9154 -void free_atm_vcc_sk(struct sock *sk)
9155 -{
9156 -       unlink_vcc(sk->protinfo.af_atm,NULL);
9157 -       sk_free(sk);
9158 +       __free_atm_dev(dev);
9159  }
9160  
9161  
9162 -void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev)
9163 +void shutdown_atm_dev(struct atm_dev *dev)
9164  {
9165 -       unlink_vcc(vcc,dev);
9166 -       vcc->dev = dev;
9167 -       if (dev) {
9168 -               vcc->next = NULL;
9169 -               vcc->prev = dev->last;
9170 -               if (dev->vccs) dev->last->next = vcc;
9171 -               else dev->vccs = vcc;
9172 -               dev->last = vcc;
9173 -       }
9174 -       else {
9175 -               if (nodev_vccs) nodev_vccs->prev = vcc;
9176 -               vcc->next = nodev_vccs;
9177 -               vcc->prev = NULL;
9178 -               nodev_vccs = vcc;
9179 +       if (atomic_read(&dev->refcnt) > 1) {
9180 +               set_bit(ATM_DF_CLOSE, &dev->flags);
9181 +               return;
9182         }
9183 +       if (dev->ops->dev_close)
9184 +               dev->ops->dev_close(dev);
9185 +       atm_dev_deregister(dev);
9186  }
9187  
9188  
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
9202 @@ -11,11 +11,7 @@
9203  
9204  
9205  extern struct list_head atm_devs;
9206 -extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */
9207 -
9208 -
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;
9212  
9213  
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
9218 @@ -33,7 +33,6 @@
9219  struct atm_vcc *sigd = NULL;
9220  static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
9221  
9222 -extern spinlock_t atm_dev_lock;
9223  
9224  static void sigd_put_skb(struct sk_buff *skb)
9225  {
9226 @@ -98,7 +97,7 @@
9227         struct atm_vcc *session_vcc;
9228  
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;
9235 @@ -115,7 +114,7 @@
9236                         }
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 @@
9245                 case as_indicate:
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);
9251                                 return 0;
9252                         }
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",
9259                                     &vcc->sleep);
9260 @@ -195,16 +194,13 @@
9261  }
9262  
9263  
9264 -static void purge_vccs(struct atm_vcc *vcc)
9265 +static void purge_vcc(struct atm_vcc *vcc)
9266  {
9267 -       while (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);
9273 -               }
9274 -               vcc = vcc->next;
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);
9280         }
9281  }
9282  
9283 @@ -213,39 +209,42 @@
9284  {
9285         struct atm_dev *dev;
9286         struct list_head *p;
9287 +       struct sock *s;
9288  
9289         DPRINTK("sigd_close\n");
9290         sigd = NULL;
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);
9295  
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);
9301 +
9302 +               read_lock(&vcc_sklist_lock);
9303 +               for(s = vcc_sklist; s; s = s->next) {
9304 +                       struct atm_vcc *vcc = atm_sk(s);
9305 +
9306 +                       if (vcc->dev == dev) purge_vcc(vcc);
9307 +               }
9308 +               read_unlock(&vcc_sklist_lock);
9309         }
9310 -       spin_unlock (&atm_dev_lock);
9311 +       read_unlock(&atm_dev_lock);
9312  }
9313  
9314  
9315  static struct atmdev_ops sigd_dev_ops = {
9316 -       close:  sigd_close,
9317 -       send:   sigd_send
9318 +       .close =        sigd_close,
9319 +       .send =         sigd_send
9320  };
9321  
9322  
9323  static struct atm_dev sigd_dev = {
9324 -       &sigd_dev_ops,
9325 -       NULL,           /* no PHY */
9326 -       "sig",          /* type */
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,
9334 +       .phy =                  NULL,
9335 +       .type =                 "sig",
9336 +       .number =               999,
9337 +       .lock =                 SPIN_LOCK_UNLOCKED
9338  };
9339  
9340  
9341 @@ -254,7 +253,7 @@
9342         if (sigd) return -EADDRINUSE;
9343         DPRINTK("sigd_attach\n");
9344         sigd = vcc;
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
9353 @@ -65,8 +65,8 @@
9354  
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);
9362                         schedule();
9363 @@ -75,7 +75,7 @@
9364         }
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);
9371                 dev_kfree_skb(skb);
9372 @@ -90,17 +90,19 @@
9373  static int svc_release(struct socket *sock)
9374  {
9375         struct atm_vcc *vcc;
9376 +       struct sock *sk = sock->sk;
9377  
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
9386 -               are closed */
9387 -       free_atm_vcc_sk(sock->sk);
9388 +       if (sk) {
9389 +               vcc = atm_sk(sk);
9390 +               DPRINTK("svc_release %p\n",vcc);
9391 +               sock_hold(sk);
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 */
9397 +               sock_put(sk);
9398 +       }
9399         return 0;
9400  }
9401  
9402 @@ -125,8 +127,8 @@
9403         if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD;
9404         vcc->local = *addr;
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);
9411                 schedule();
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;
9423                 }
9424 -               add_wait_queue(&vcc->sleep,&wait);
9425                 error = 0;
9426                 while (vcc->reply == WAITING && sigd) {
9427                         set_current_state(TASK_INTERRUPTIBLE);
9428 @@ -228,7 +231,7 @@
9429  /*
9430   * #endif
9431   */
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);
9436         return error;
9437 @@ -243,9 +246,9 @@
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);
9447                 schedule();
9448 @@ -253,7 +256,7 @@
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;
9454         return vcc->reply;
9455  }
9456  
9457 @@ -277,7 +280,7 @@
9458                 DECLARE_WAITQUEUE(wait,current);
9459  
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);
9469                 dev_kfree_skb(skb);
9470 -               old_vcc->backlog_quota++;
9471 +               old_vcc->sk->ack_backlog--;
9472                 if (error) {
9473                         sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
9474                             &old_vcc->qos,error);
9475                         return error == -EAGAIN ? -EBUSY : error;
9476                 }
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);
9484                         schedule();
9485 @@ -347,9 +350,9 @@
9486  {
9487         DECLARE_WAITQUEUE(wait,current);
9488  
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)
9494             && sigd) {
9495                 set_current_state(TASK_UNINTERRUPTIBLE);
9496 @@ -390,37 +393,34 @@
9497  }
9498  
9499  
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,
9504  
9505 -       release:        svc_release,
9506 -       bind:           svc_bind,
9507 -       connect:        svc_connect,
9508 -       socketpair:     sock_no_socketpair,
9509 -       accept:         svc_accept,
9510 -       getname:        svc_getname,
9511 -       poll:           atm_poll,
9512 -       ioctl:          atm_ioctl,
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,
9522 +       .bind =         svc_bind,
9523 +       .connect =      svc_connect,
9524 +       .socketpair =   sock_no_socketpair,
9525 +       .accept =       svc_accept,
9526 +       .getname =      svc_getname,
9527 +       .poll =         atm_poll,
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,
9537  };
9538  
9539  
9540 -#include <linux/smp_lock.h>
9541 -SOCKOPS_WRAP(svc_proto, PF_ATMSVC);
9542 -
9543  static int svc_create(struct socket *sock,int protocol)
9544  {
9545         int error;
9546  
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 @@
9554  
9555  
9556  static struct net_proto_family svc_family_ops = {
9557 -       PF_ATMSVC,
9558 -       svc_create,
9559 -       0,                      /* no authentication */
9560 -       0,                      /* no encryption */
9561 -       0                       /* no encrypt_net */
9562 +       .family = PF_ATMSVC,
9563 +       .create = svc_create,
9564  };
9565  
9566  
9567 @@ -442,13 +439,19 @@
9568   *     Initialize the ATM SVC protocol family
9569   */
9570  
9571 -static int __init atmsvc_init(void)
9572 +int __init atmsvc_init(void)
9573  {
9574 -       if (sock_register(&svc_family_ops) < 0) {
9575 -               printk(KERN_ERR "ATMSVC: can't register");
9576 +       int error;
9577 +
9578 +       error = sock_register(&svc_family_ops);
9579 +       if (error < 0) {
9580 +               printk(KERN_ERR "ATMSVC: can't register (%d)\n", error);
9581                 return -1;
9582         }
9583         return 0;
9584  }
9585  
9586 -module_init(atmsvc_init);
9587 +void __exit atmsvc_exit(void)
9588 +{
9589 +       sock_unregister(PF_ATMSVC);
9590 +}
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
9594 @@ -105,8 +105,9 @@
9595  #include <net/netrom.h>
9596  #endif
9597  #endif
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;
9602  #endif
9603  
9604  #include <asm/system.h>
9605 @@ -438,8 +439,8 @@
9606                 if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
9607                         nexthop = 0;
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 :
9613  #endif
9614                     &arp_tbl, &nexthop, dev);
9615                 if (IS_ERR(n))
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
9619 @@ -45,6 +45,9 @@
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>
9625 +#endif
9626  #include <net/ip.h>
9627  #include <net/udp.h>
9628  #include <net/tcp.h>
9629 @@ -160,6 +163,7 @@
9630  EXPORT_SYMBOL(put_cmsg);
9631  EXPORT_SYMBOL(sock_kmalloc);
9632  EXPORT_SYMBOL(sock_kfree_s);
9633 +EXPORT_SYMBOL(sockfd_lookup);
9634  
9635  #ifdef CONFIG_FILTER
9636  EXPORT_SYMBOL(sk_run_filter);
9637 @@ -461,6 +465,9 @@
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);
9643 +#endif
9644  EXPORT_SYMBOL(arp_find);
9645  
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
9650 @@ -6,8 +6,8 @@
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
9658  fi
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
9664 @@ -512,7 +512,6 @@
9665                         memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
9666                             flow->hdr_len);
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);
9671                 }
This page took 0.765489 seconds and 3 git commands to generate.