]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.21-atm_diffs.patch
- CONFIG_AGP_ATI=y
[packages/kernel.git] / linux-2.4.21-atm_diffs.patch
CommitLineData
2e17a577
JR
1diff -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
13diff -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
25diff -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
37diff -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
49diff -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
61diff -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
73diff -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
85diff -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
106diff -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
118diff -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
135diff -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
217diff -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
231diff -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);
249diff -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
931284e9
JR
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>
2e17a577
JR
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");
457diff -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;
602diff -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)
618diff -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 }
904diff -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;
915diff -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");
4201diff -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_ */
5115diff -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
b12c7f0e
JR
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)",
2e17a577
JR
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);
5150diff -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))
5330diff -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)
5476diff -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 */
b12c7f0e
JR
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
2e17a577
JR
5596diff -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
5844diff -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 {
5870diff -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
b12c7f0e
JR
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;
2e17a577
JR
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)
5895diff -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 */
5919diff -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
5931diff -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);
6112diff -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);
6123diff -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
6156diff -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
6185diff -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
6233diff -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 }
6340diff -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);
6415diff -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;
6426diff -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");
6595diff -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
931284e9
JR
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 */
2e17a577
JR
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:
9e7cf1f7
JR
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:
2e17a577
JR
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");
7448diff -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
7481diff -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);
7491diff -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".
7503diff -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 /*
2e17a577
JR
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");
8209diff -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
8237diff -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");
8392diff -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);
8408diff -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,
8419diff -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 }
8753diff -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+}
8873diff -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 }
8885diff -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);
9199diff -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
9215diff -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);
9350diff -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+}
9591diff -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))
9616diff -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 */
9647diff -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
9661diff -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 1.424711 seconds and 4 git commands to generate.