OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [atm/] [proc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* net/atm/proc.c - ATM /proc interface */
2
 
3
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
 
5
/*
6
 * The mechanism used here isn't designed for speed but rather for convenience
7
 * of implementation. We only return one entry per read system call, so we can
8
 * be reasonably sure not to overrun the page and race conditions may lead to
9
 * the addition or omission of some lines but never to any corruption of a
10
 * line's internal structure.
11
 *
12
 * Making the whole thing slightly more efficient is left as an exercise to the
13
 * reader. (Suggestions: wrapper which loops to get several entries per system
14
 * call; or make --left slightly more clever to avoid O(n^2) characteristics.)
15
 * I find it fast enough on my unloaded 266 MHz Pentium 2 :-)
16
 */
17
 
18
 
19
#include <linux/config.h>
20
#include <linux/module.h> /* for EXPORT_SYMBOL */
21
#include <linux/string.h>
22
#include <linux/types.h>
23
#include <linux/mm.h>
24
#include <linux/fs.h>
25
#include <linux/stat.h>
26
#include <linux/proc_fs.h>
27
#include <linux/errno.h>
28
#include <linux/atm.h>
29
#include <linux/atmdev.h>
30
#include <linux/netdevice.h>
31
#include <linux/atmclip.h>
32
#include <linux/atmarp.h>
33
#include <linux/if_arp.h>
34
#include <linux/init.h> /* for __init */
35
#include <asm/uaccess.h>
36
#include <asm/atomic.h>
37
#include <asm/param.h> /* for HZ */
38
#include "resources.h"
39
#include "common.h" /* atm_proc_init prototype */
40
#include "signaling.h" /* to get sigd - ugly too */
41
 
42
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
43
#include <net/atmclip.h>
44
#include "ipcommon.h"
45
#endif
46
 
47
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
48
#include "lec.h"
49
#include "lec_arpc.h"
50
#endif
51
 
52
static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
53
    loff_t *pos);
54
static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count,
55
    loff_t *pos);
56
 
57
static struct file_operations proc_dev_atm_operations = {
58
        read:           proc_dev_atm_read,
59
};
60
 
61
static struct file_operations proc_spec_atm_operations = {
62
        read:           proc_spec_atm_read,
63
};
64
 
65
static void add_stats(char *buf,const char *aal,
66
  const struct k_atm_aal_stats *stats)
67
{
68
        sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal,
69
            atomic_read(&stats->tx),atomic_read(&stats->tx_err),
70
            atomic_read(&stats->rx),atomic_read(&stats->rx_err),
71
            atomic_read(&stats->rx_drop));
72
}
73
 
74
 
75
static void dev_info(const struct atm_dev *dev,char *buf)
76
{
77
        int off,i;
78
 
79
        off = sprintf(buf,"%3d %-8s",dev->number,dev->type);
80
        for (i = 0; i < ESI_LEN; i++)
81
                off += sprintf(buf+off,"%02x",dev->esi[i]);
82
        strcat(buf,"  ");
83
        add_stats(buf,"0",&dev->stats.aal0);
84
        strcat(buf,"  ");
85
        add_stats(buf,"5",&dev->stats.aal5);
86
        sprintf(strchr(buf,0), "\t[%d]", atomic_read(&dev->refcnt));
87
        strcat(buf,"\n");
88
}
89
 
90
 
91
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
92
 
93
 
94
static int svc_addr(char *buf,struct sockaddr_atmsvc *addr)
95
{
96
        static int code[] = { 1,2,10,6,1,0 };
97
        static int e164[] = { 1,8,4,6,1,0 };
98
        int *fields;
99
        int len,i,j,pos;
100
 
101
        len = 0;
102
        if (*addr->sas_addr.pub) {
103
                strcpy(buf,addr->sas_addr.pub);
104
                len = strlen(addr->sas_addr.pub);
105
                buf += len;
106
                if (*addr->sas_addr.prv) {
107
                        *buf++ = '+';
108
                        len++;
109
                }
110
        }
111
        else if (!*addr->sas_addr.prv) {
112
                        strcpy(buf,"(none)");
113
                        return strlen(buf);
114
                }
115
        if (*addr->sas_addr.prv) {
116
                len += 44;
117
                pos = 0;
118
                fields = *addr->sas_addr.prv == ATM_AFI_E164 ? e164 : code;
119
                for (i = 0; fields[i]; i++) {
120
                        for (j = fields[i]; j; j--) {
121
                                sprintf(buf,"%02X",addr->sas_addr.prv[pos++]);
122
                                buf += 2;
123
                        }
124
                        if (fields[i+1]) *buf++ = '.';
125
                }
126
        }
127
        return len;
128
}
129
 
130
 
131
static void atmarp_info(struct net_device *dev,struct atmarp_entry *entry,
132
    struct clip_vcc *clip_vcc,char *buf)
133
{
134
        unsigned char *ip;
135
        int svc,off,ip_len;
136
 
137
        svc = !clip_vcc || clip_vcc->vcc->sk->family == AF_ATMSVC;
138
        off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC",
139
            !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
140
            (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/
141
            HZ);
142
        ip = (unsigned char *) &entry->ip;
143
        ip_len = sprintf(buf+off,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
144
        off += ip_len;
145
        while (ip_len++ < 16) buf[off++] = ' ';
146
        if (!clip_vcc)
147
                if (time_before(jiffies, entry->expires))
148
                        strcpy(buf+off,"(resolving)\n");
149
                else sprintf(buf+off,"(expired, ref %d)\n",
150
                            atomic_read(&entry->neigh->refcnt));
151
        else if (!svc)
152
                        sprintf(buf+off,"%d.%d.%d\n",clip_vcc->vcc->dev->number,
153
                            clip_vcc->vcc->vpi,clip_vcc->vcc->vci);
154
                else {
155
                        off += svc_addr(buf+off,&clip_vcc->vcc->remote);
156
                        strcpy(buf+off,"\n");
157
                }
158
}
159
 
160
 
161
#endif
162
 
163
 
164
static void pvc_info(struct atm_vcc *vcc, char *buf, int clip_info)
165
{
166
        static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
167
        static const char *aal_name[] = {
168
                "---",  "1",    "2",    "3/4",  /*  0- 3 */
169
                "???",  "5",    "???",  "???",  /*  4- 7 */
170
                "???",  "???",  "???",  "???",  /*  8-11 */
171
                "???",  "0",     "???",  "???"}; /* 12-15 */
172
        int off;
173
 
174
        off = sprintf(buf,"%3d %3d %5d %-3s %7d %-5s %7d %-6s",
175
            vcc->dev->number,vcc->vpi,vcc->vci,
176
            vcc->qos.aal >= sizeof(aal_name)/sizeof(aal_name[0]) ? "err" :
177
            aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr,
178
            class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr,
179
            class_name[vcc->qos.txtp.traffic_class]);
180
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
181
        if (clip_info && (vcc->push == atm_clip_ops->clip_push)) {
182
                struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
183
                struct net_device *dev;
184
 
185
                dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL;
186
                off += sprintf(buf+off,"CLIP, Itf:%s, Encap:",
187
                    dev ? dev->name : "none?");
188
                if (clip_vcc->encap)
189
                        off += sprintf(buf+off,"LLC/SNAP");
190
                else
191
                        off += sprintf(buf+off,"None");
192
        }
193
#endif
194
        strcpy(buf+off,"\n");
195
}
196
 
197
 
198
static const char *vcc_state(struct atm_vcc *vcc)
199
{
200
        static const char *map[] = { ATM_VS2TXT_MAP };
201
 
202
        return map[ATM_VF2VS(vcc->flags)];
203
}
204
 
205
 
206
static void vc_info(struct atm_vcc *vcc,char *buf)
207
{
208
        char *here;
209
 
210
        here = buf+sprintf(buf,"%p ",vcc);
211
        if (!vcc->dev) here += sprintf(here,"Unassigned    ");
212
        else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,
213
                    vcc->vci);
214
        switch (vcc->sk->family) {
215
                case AF_ATMPVC:
216
                        here += sprintf(here,"PVC");
217
                        break;
218
                case AF_ATMSVC:
219
                        here += sprintf(here,"SVC");
220
                        break;
221
                default:
222
                        here += sprintf(here,"%3d",vcc->sk->family);
223
        }
224
        here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags.bits,
225
            vcc->reply,
226
            atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf,
227
            atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf);
228
}
229
 
230
 
231
static void svc_info(struct atm_vcc *vcc,char *buf)
232
{
233
        char *here;
234
        int i;
235
 
236
        if (!vcc->dev)
237
                sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%10s" : "N/A@%p%2s",
238
                    vcc,"");
239
        else sprintf(buf,"%3d %3d %5d         ",vcc->dev->number,vcc->vpi,
240
                    vcc->vci);
241
        here = strchr(buf,0);
242
        here += sprintf(here,"%-10s ",vcc_state(vcc));
243
        here += sprintf(here,"%s%s",vcc->remote.sas_addr.pub,
244
            *vcc->remote.sas_addr.pub && *vcc->remote.sas_addr.prv ? "+" : "");
245
        if (*vcc->remote.sas_addr.prv)
246
                for (i = 0; i < ATM_ESA_LEN; i++)
247
                        here += sprintf(here,"%02x",
248
                            vcc->remote.sas_addr.prv[i]);
249
        strcat(here,"\n");
250
}
251
 
252
 
253
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
254
 
255
static char*
256
lec_arp_get_status_string(unsigned char status)
257
{
258
  switch(status) {
259
  case ESI_UNKNOWN:
260
    return "ESI_UNKNOWN       ";
261
  case ESI_ARP_PENDING:
262
    return "ESI_ARP_PENDING   ";
263
  case ESI_VC_PENDING:
264
    return "ESI_VC_PENDING    ";
265
  case ESI_FLUSH_PENDING:
266
    return "ESI_FLUSH_PENDING ";
267
  case ESI_FORWARD_DIRECT:
268
    return "ESI_FORWARD_DIRECT";
269
  default:
270
    return "<Unknown>         ";
271
  }
272
}
273
 
274
static void
275
lec_info(struct lec_arp_table *entry, char *buf)
276
{
277
        int j, offset=0;
278
 
279
        for(j=0;j<ETH_ALEN;j++) {
280
                offset+=sprintf(buf+offset,"%2.2x",0xff&entry->mac_addr[j]);
281
        }
282
        offset+=sprintf(buf+offset, " ");
283
        for(j=0;j<ATM_ESA_LEN;j++) {
284
                offset+=sprintf(buf+offset,"%2.2x",0xff&entry->atm_addr[j]);
285
        }
286
        offset+=sprintf(buf+offset, " %s %4.4x",
287
                        lec_arp_get_status_string(entry->status),
288
                        entry->flags&0xffff);
289
        if (entry->vcc) {
290
                offset+=sprintf(buf+offset, "%3d %3d ", entry->vcc->vpi,
291
                                entry->vcc->vci);
292
        } else
293
                offset+=sprintf(buf+offset, "        ");
294
        if (entry->recv_vcc) {
295
                offset+=sprintf(buf+offset, "     %3d %3d",
296
                                entry->recv_vcc->vpi, entry->recv_vcc->vci);
297
        }
298
 
299
        sprintf(buf+offset,"\n");
300
}
301
 
302
#endif
303
 
304
static int atm_devices_info(loff_t pos,char *buf)
305
{
306
        struct atm_dev *dev;
307
        struct list_head *p;
308
        int left;
309
 
310
        if (!pos) {
311
                return sprintf(buf,"Itf Type    ESI/\"MAC\"addr "
312
                    "AAL(TX,err,RX,err,drop) ...               [refcnt]\n");
313
        }
314
        left = pos-1;
315
        spin_lock(&atm_dev_lock);
316
        list_for_each(p, &atm_devs) {
317
                dev = list_entry(p, struct atm_dev, dev_list);
318
                if (left-- == 0) {
319
                        dev_info(dev,buf);
320
                        spin_unlock(&atm_dev_lock);
321
                        return strlen(buf);
322
                }
323
        }
324
        spin_unlock(&atm_dev_lock);
325
        return 0;
326
}
327
 
328
/*
329
 * FIXME: it isn't safe to walk the VCC list without turning off interrupts.
330
 * What is really needed is some lock on the devices. Ditto for ATMARP.
331
 */
332
 
333
static int atm_pvc_info(loff_t pos,char *buf)
334
{
335
        struct sock *s;
336
        struct atm_vcc *vcc;
337
        int left, clip_info = 0;
338
 
339
        if (!pos) {
340
                return sprintf(buf,"Itf VPI VCI   AAL RX(PCR,Class) "
341
                    "TX(PCR,Class)\n");
342
        }
343
        left = pos-1;
344
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
345
        if (try_atm_clip_ops())
346
                clip_info = 1;
347
#endif
348
        read_lock(&vcc_sklist_lock);
349
        for(s = vcc_sklist; s; s = s->next) {
350
                vcc = s->protinfo.af_atm;
351
                if (vcc->sk->family == PF_ATMPVC && vcc->dev && !left--) {
352
                        pvc_info(vcc,buf,clip_info);
353
                        read_unlock(&vcc_sklist_lock);
354
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
355
                        if (clip_info && atm_clip_ops->owner)
356
                                __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
357
#endif
358
                        return strlen(buf);
359
                }
360
        }
361
        read_unlock(&vcc_sklist_lock);
362
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
363
        if (clip_info && atm_clip_ops->owner)
364
                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
365
#endif
366
        return 0;
367
}
368
 
369
 
370
static int atm_vc_info(loff_t pos,char *buf)
371
{
372
        struct atm_vcc *vcc;
373
        struct sock *s;
374
        int left;
375
 
376
        if (!pos)
377
                return sprintf(buf,sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
378
                    "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
379
                    "     Recv buffer\n");
380
        left = pos-1;
381
        read_lock(&vcc_sklist_lock);
382
        for(s = vcc_sklist; s; s = s->next) {
383
                vcc = s->protinfo.af_atm;
384
                if (!left--) {
385
                        vc_info(vcc,buf);
386
                        read_unlock(&vcc_sklist_lock);
387
                        return strlen(buf);
388
                }
389
        }
390
        read_unlock(&vcc_sklist_lock);
391
 
392
        return 0;
393
}
394
 
395
 
396
static int atm_svc_info(loff_t pos,char *buf)
397
{
398
        struct sock *s;
399
        struct atm_vcc *vcc;
400
        int left;
401
 
402
        if (!pos)
403
                return sprintf(buf,"Itf VPI VCI           State      Remote\n");
404
        left = pos-1;
405
        read_lock(&vcc_sklist_lock);
406
        for(s = vcc_sklist; s; s = s->next) {
407
                vcc = s->protinfo.af_atm;
408
                if (vcc->sk->family == PF_ATMSVC && !left--) {
409
                        svc_info(vcc,buf);
410
                        read_unlock(&vcc_sklist_lock);
411
                        return strlen(buf);
412
                }
413
        }
414
        read_unlock(&vcc_sklist_lock);
415
 
416
        return 0;
417
}
418
 
419
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
420
static int atm_arp_info(loff_t pos,char *buf)
421
{
422
        struct neighbour *n;
423
        int i,count;
424
 
425
        if (!pos) {
426
                return sprintf(buf,"IPitf TypeEncp Idle IP address      "
427
                    "ATM address\n");
428
        }
429
        if (!try_atm_clip_ops())
430
                return 0;
431
        count = pos;
432
        read_lock_bh(&clip_tbl_hook->lock);
433
        for (i = 0; i <= NEIGH_HASHMASK; i++)
434
                for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) {
435
                        struct atmarp_entry *entry = NEIGH2ENTRY(n);
436
                        struct clip_vcc *vcc;
437
 
438
                        if (!entry->vccs) {
439
                                if (--count) continue;
440
                                atmarp_info(n->dev,entry,NULL,buf);
441
                                read_unlock_bh(&clip_tbl_hook->lock);
442
                                if (atm_clip_ops->owner)
443
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
444
                                return strlen(buf);
445
                        }
446
                        for (vcc = entry->vccs; vcc;
447
                            vcc = vcc->next) {
448
                                if (--count) continue;
449
                                atmarp_info(n->dev,entry,vcc,buf);
450
                                read_unlock_bh(&clip_tbl_hook->lock);
451
                                if (atm_clip_ops->owner)
452
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
453
                                return strlen(buf);
454
                        }
455
                }
456
        read_unlock_bh(&clip_tbl_hook->lock);
457
        if (atm_clip_ops->owner)
458
                __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
459
        return 0;
460
}
461
#endif
462
 
463
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
464
static int atm_lec_info(loff_t pos,char *buf)
465
{
466
        unsigned long flags;
467
        struct lec_priv *priv;
468
        struct lec_arp_table *entry;
469
        int i, count, d, e;
470
        struct net_device *dev;
471
 
472
        if (!pos) {
473
                return sprintf(buf,"Itf  MAC          ATM destination"
474
                    "                          Status            Flags "
475
                    "VPI/VCI Recv VPI/VCI\n");
476
        }
477
        if (!try_atm_lane_ops())
478
                return 0; /* the lane module is not there yet */
479
 
480
        count = pos;
481
        for(d = 0; d < MAX_LEC_ITF; d++) {
482
                dev = atm_lane_ops->get_lec(d);
483
                if (!dev || !(priv = (struct lec_priv *) dev->priv))
484
                        continue;
485
                spin_lock_irqsave(&priv->lec_arp_lock, flags);
486
                for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
487
                        for(entry = priv->lec_arp_tables[i]; entry; entry = entry->next) {
488
                                if (--count)
489
                                        continue;
490
                                e = sprintf(buf,"%s ", dev->name);
491
                                lec_info(entry, buf+e);
492
                                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
493
                                dev_put(dev);
494
                                if (atm_lane_ops->owner)
495
                                        __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
496
                                return strlen(buf);
497
                        }
498
                }
499
                for(entry = priv->lec_arp_empty_ones; entry; entry = entry->next) {
500
                        if (--count)
501
                                continue;
502
                        e = sprintf(buf,"%s ", dev->name);
503
                        lec_info(entry, buf+e);
504
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
505
                        dev_put(dev);
506
                        if (atm_lane_ops->owner)
507
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
508
                        return strlen(buf);
509
                }
510
                for(entry = priv->lec_no_forward; entry; entry=entry->next) {
511
                        if (--count)
512
                                continue;
513
                        e = sprintf(buf,"%s ", dev->name);
514
                        lec_info(entry, buf+e);
515
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
516
                        dev_put(dev);
517
                        if (atm_lane_ops->owner)
518
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
519
                        return strlen(buf);
520
                }
521
                for(entry = priv->mcast_fwds; entry; entry = entry->next) {
522
                        if (--count)
523
                                continue;
524
                        e = sprintf(buf,"%s ", dev->name);
525
                        lec_info(entry, buf+e);
526
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
527
                        dev_put(dev);
528
                        if (atm_lane_ops->owner)
529
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
530
                        return strlen(buf);
531
                }
532
                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
533
                dev_put(dev);
534
        }
535
        if (atm_lane_ops->owner)
536
                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
537
        return 0;
538
}
539
#endif
540
 
541
 
542
static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
543
    loff_t *pos)
544
{
545
        struct atm_dev *dev;
546
        unsigned long page;
547
        int length;
548
 
549
        if (count == 0) return 0;
550
        page = get_free_page(GFP_KERNEL);
551
        if (!page) return -ENOMEM;
552
        dev = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
553
            ->data;
554
        if (!dev->ops->proc_read)
555
                length = -EINVAL;
556
        else {
557
                length = dev->ops->proc_read(dev,pos,(char *) page);
558
                if (length > count) length = -EINVAL;
559
        }
560
        if (length >= 0) {
561
                if (copy_to_user(buf,(char *) page,length)) length = -EFAULT;
562
                (*pos)++;
563
        }
564
        free_page(page);
565
        return length;
566
}
567
 
568
 
569
static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count,
570
    loff_t *pos)
571
{
572
        unsigned long page;
573
        int length;
574
        int (*info)(loff_t,char *);
575
        info = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
576
            ->data;
577
 
578
        if (count == 0) return 0;
579
        page = get_free_page(GFP_KERNEL);
580
        if (!page) return -ENOMEM;
581
        length = (*info)(*pos,(char *) page);
582
        if (length > count) length = -EINVAL;
583
        if (length >= 0) {
584
                if (copy_to_user(buf,(char *) page,length)) length = -EFAULT;
585
                (*pos)++;
586
        }
587
        free_page(page);
588
        return length;
589
}
590
 
591
 
592
struct proc_dir_entry *atm_proc_root;
593
EXPORT_SYMBOL(atm_proc_root);
594
 
595
 
596
int atm_proc_dev_register(struct atm_dev *dev)
597
{
598
        int digits,num;
599
        int error;
600
 
601
        error = -ENOMEM;
602
        digits = 0;
603
        for (num = dev->number; num; num /= 10) digits++;
604
        if (!digits) digits++;
605
 
606
        dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_ATOMIC);
607
        if (!dev->proc_name)
608
                goto fail1;
609
        sprintf(dev->proc_name,"%s:%d",dev->type, dev->number);
610
 
611
        dev->proc_entry = create_proc_entry(dev->proc_name, 0, atm_proc_root);
612
        if (!dev->proc_entry)
613
                goto fail0;
614
        dev->proc_entry->data = dev;
615
        dev->proc_entry->proc_fops = &proc_dev_atm_operations;
616
        dev->proc_entry->owner = THIS_MODULE;
617
        return 0;
618
fail0:
619
        kfree(dev->proc_name);
620
fail1:
621
        return error;
622
}
623
 
624
 
625
void atm_proc_dev_deregister(struct atm_dev *dev)
626
{
627
        remove_proc_entry(dev->proc_name, atm_proc_root);
628
        kfree(dev->proc_name);
629
}
630
 
631
 
632
#define CREATE_ENTRY(name) \
633
    name = create_proc_entry(#name,0,atm_proc_root); \
634
    if (!name) goto cleanup; \
635
    name->data = atm_##name##_info; \
636
    name->proc_fops = &proc_spec_atm_operations; \
637
    name->owner = THIS_MODULE
638
 
639
static struct proc_dir_entry *devices = NULL, *pvc = NULL,
640
                *svc = NULL, *arp = NULL, *lec = NULL, *vc = NULL;
641
 
642
static void atm_proc_cleanup(void)
643
{
644
        if (devices)
645
                remove_proc_entry("devices",atm_proc_root);
646
        if (pvc)
647
                remove_proc_entry("pvc",atm_proc_root);
648
        if (svc)
649
                remove_proc_entry("svc",atm_proc_root);
650
        if (arp)
651
                remove_proc_entry("arp",atm_proc_root);
652
        if (lec)
653
                remove_proc_entry("lec",atm_proc_root);
654
        if (vc)
655
                remove_proc_entry("vc",atm_proc_root);
656
        remove_proc_entry("net/atm",NULL);
657
}
658
 
659
int atm_proc_init(void)
660
{
661
        atm_proc_root = proc_mkdir("net/atm",NULL);
662
        if (!atm_proc_root)
663
                return -ENOMEM;
664
        CREATE_ENTRY(devices);
665
        CREATE_ENTRY(pvc);
666
        CREATE_ENTRY(svc);
667
        CREATE_ENTRY(vc);
668
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
669
        CREATE_ENTRY(arp);
670
#endif
671
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
672
        CREATE_ENTRY(lec);
673
#endif
674
        return 0;
675
 
676
cleanup:
677
        atm_proc_cleanup();
678
        return -ENOMEM;
679
}
680
 
681
void atm_proc_exit(void)
682
{
683
        atm_proc_cleanup();
684
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.