11 #include <linux/module.h>
12 #include <linux/string.h>
13 #include <linux/types.h>
16 #include <linux/stat.h>
19 #include <linux/errno.h>
20 #include <linux/atm.h>
21 #include <linux/atmdev.h>
22 #include <linux/netdevice.h>
25 #include <linux/slab.h>
40 .read = proc_dev_atm_read,
44 static void add_stats(
struct seq_file *seq,
const char *aal,
61 add_stats(seq,
"0", &dev->
stats.aal0);
63 add_stats(seq,
"5", &dev->
stats.aal5);
74 static inline int compare_family(
struct sock *
sk,
int family)
76 return !family || (sk->sk_family ==
family);
79 static int __vcc_walk(
struct sock **
sock,
int family,
int *bucket, loff_t
l)
87 sk = hlist_empty(head) ?
NULL : __sk_head(head);
94 for (;
sk; sk = sk_next(sk)) {
95 l -= compare_family(sk, family);
99 if (!sk && ++*bucket < VCC_HTABLE_SIZE) {
128 static void *vcc_seq_start(
struct seq_file *seq, loff_t *
pos)
139 static void vcc_seq_stop(
struct seq_file *seq,
void *
v)
145 static void *vcc_seq_next(
struct seq_file *seq,
void *
v, loff_t *
pos)
149 v = vcc_walk(state, 1);
150 *pos += !!PTR_ERR(v);
156 static const char *
const class_name[] = {
157 "off",
"UBR",
"CBR",
"VBR",
"ABR"};
158 static const char *
const aal_name[] = {
159 "---",
"1",
"2",
"3/4",
160 "???",
"5",
"???",
"???",
161 "???",
"???",
"???",
"???",
162 "???",
"0",
"???",
"???"};
164 seq_printf(seq,
"%3d %3d %5d %-3s %7d %-5s %7d %-6s",
167 aal_name[vcc->
qos.aal], vcc->
qos.rxtp.min_pcr,
168 class_name[vcc->
qos.rxtp.traffic_class],
169 vcc->
qos.txtp.min_pcr,
170 class_name[vcc->
qos.txtp.traffic_class]);
177 dev ? dev->
name :
"none?");
192 struct sock *sk = sk_atm(vcc);
200 switch (sk->sk_family) {
210 seq_printf(seq,
" %04lx %5d %7d/%7d %7d/%7d [%d]\n",
221 "N/A@%pK%10s" :
"N/A@%pK%2s", vcc,
"");
227 *vcc->
remote.sas_addr.pub && *vcc->
remote.sas_addr.prv ?
"+" :
"");
228 if (*vcc->
remote.sas_addr.prv) {
237 static int atm_dev_seq_show(
struct seq_file *seq,
void *
v)
239 static char atm_dev_banner[] =
240 "Itf Type ESI/\"MAC\"addr "
241 "AAL(TX,err,RX,err,drop) ... [refcnt]\n";
248 atm_dev_info(seq, dev);
257 .show = atm_dev_seq_show,
260 static int atm_dev_seq_open(
struct inode *inode,
struct file *file)
262 return seq_open(file, &atm_dev_seq_ops);
266 .open = atm_dev_seq_open,
272 static int pvc_seq_show(
struct seq_file *seq,
void *v)
274 static char atm_pvc_banner[] =
275 "Itf VPI VCI AAL RX(PCR,Class) TX(PCR,Class)\n";
289 .start = vcc_seq_start,
290 .next = vcc_seq_next,
291 .stop = vcc_seq_stop,
292 .show = pvc_seq_show,
295 static int pvc_seq_open(
struct inode *inode,
struct file *file)
297 return __vcc_seq_open(inode, file,
PF_ATMPVC, &pvc_seq_ops);
301 .open = pvc_seq_open,
307 static int vcc_seq_show(
struct seq_file *seq,
void *v)
310 seq_printf(seq,
sizeof(
void *) == 4 ?
"%-8s%s" :
"%-16s%s",
311 "Address ",
"Itf VPI VCI Fam Flags Reply "
312 "Send buffer Recv buffer [refcnt]\n");
323 .start = vcc_seq_start,
324 .next = vcc_seq_next,
325 .stop = vcc_seq_stop,
326 .show = vcc_seq_show,
329 static int vcc_seq_open(
struct inode *inode,
struct file *file)
331 return __vcc_seq_open(inode, file, 0, &vcc_seq_ops);
335 .open = vcc_seq_open,
343 static const char atm_svc_banner[] =
344 "Itf VPI VCI State Remote\n";
358 .start = vcc_seq_start,
359 .next = vcc_seq_next,
360 .stop = vcc_seq_stop,
364 static int svc_seq_open(
struct inode *inode,
struct file *file)
366 return __vcc_seq_open(inode, file,
PF_ATMSVC, &svc_seq_ops);
370 .open = svc_seq_open,
376 static ssize_t proc_dev_atm_read(
struct file *file,
char __user *
buf,
388 dev = PDE(file->
f_path.dentry->d_inode)->data;
389 if (!dev->
ops->proc_read)
392 length = dev->
ops->proc_read(dev, pos, (
char *)page);
414 if (!dev->
ops->proc_read)
423 &proc_atm_dev_ops, dev);
424 if (!dev->proc_entry)
429 kfree(dev->proc_name);
436 if (!dev->
ops->proc_read)
440 kfree(dev->proc_name);
443 static struct atm_proc_entry {
447 } atm_proc_ents[] = {
448 { .name =
"devices", .proc_fops = &devices_seq_fops },
449 { .name =
"pvc", .proc_fops = &pvc_seq_fops },
450 { .name =
"svc", .proc_fops = &svc_seq_fops },
451 { .name =
"vc", .proc_fops = &vcc_seq_fops },
455 static void atm_proc_dirs_remove(
void)
457 static struct atm_proc_entry *
e;
459 for (e = atm_proc_ents; e->name; e++) {
468 static struct atm_proc_entry *
e;
474 for (e = atm_proc_ents; e->name; e++) {
477 dirent = proc_create(e->name,
S_IRUGO,
478 atm_proc_root, e->proc_fops);
488 atm_proc_dirs_remove();
496 atm_proc_dirs_remove();