Merge branch 'stable/broadcom.ibft' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / net / wanrouter / wanproc.c
1 /*****************************************************************************
2 * wanproc.c     WAN Router Module. /proc filesystem interface.
3 *
4 *               This module is completely hardware-independent and provides
5 *               access to the router using Linux /proc filesystem.
6 *
7 * Author:       Gideon Hack
8 *
9 * Copyright:    (c) 1995-1999 Sangoma Technologies Inc.
10 *
11 *               This program is free software; you can redistribute it and/or
12 *               modify it under the terms of the GNU General Public License
13 *               as published by the Free Software Foundation; either version
14 *               2 of the License, or (at your option) any later version.
15 * ============================================================================
16 * Jun 02, 1999  Gideon Hack     Updates for Linux 2.2.X kernels.
17 * Jun 29, 1997  Alan Cox        Merged with 1.0.3 vendor code
18 * Jan 29, 1997  Gene Kozin      v1.0.1. Implemented /proc read routines
19 * Jan 30, 1997  Alan Cox        Hacked around for 2.1
20 * Dec 13, 1996  Gene Kozin      Initial version (based on Sangoma's WANPIPE)
21 *****************************************************************************/
22
23 #include <linux/init.h>         /* __initfunc et al. */
24 #include <linux/stddef.h>       /* offsetof(), etc. */
25 #include <linux/errno.h>        /* return codes */
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/wanrouter.h>    /* WAN router API definitions */
29 #include <linux/seq_file.h>
30 #include <linux/mutex.h>
31
32 #include <net/net_namespace.h>
33 #include <asm/io.h>
34
35 #define PROC_STATS_FORMAT "%30s: %12lu\n"
36
37 /****** Defines and Macros **************************************************/
38
39 #define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
40                               (prot == WANCONFIG_X25) ? " X25" : \
41                                  (prot == WANCONFIG_PPP) ? " PPP" : \
42                                     (prot == WANCONFIG_CHDLC) ? " CHDLC": \
43                                        (prot == WANCONFIG_MPPP) ? " MPPP" : \
44                                            " Unknown" )
45
46 /****** Function Prototypes *************************************************/
47
48 #ifdef CONFIG_PROC_FS
49
50 /* Miscellaneous */
51
52 /*
53  *      Structures for interfacing with the /proc filesystem.
54  *      Router creates its own directory /proc/net/router with the following
55  *      entries:
56  *      config          device configuration
57  *      status          global device statistics
58  *      <device>        entry for each WAN device
59  */
60
61 /*
62  *      Generic /proc/net/router/<file> file and inode operations
63  */
64
65 /*
66  *      /proc/net/router
67  */
68
69 static DEFINE_MUTEX(config_mutex);
70 static struct proc_dir_entry *proc_router;
71
72 /* Strings */
73
74 /*
75  *      Interface functions
76  */
77
78 /****** Proc filesystem entry points ****************************************/
79
80 /*
81  *      Iterator
82  */
83 static void *r_start(struct seq_file *m, loff_t *pos)
84         __acquires(kernel_lock)
85 {
86         struct wan_device *wandev;
87         loff_t l = *pos;
88
89         mutex_lock(&config_mutex);
90         if (!l--)
91                 return SEQ_START_TOKEN;
92         for (wandev = wanrouter_router_devlist; l-- && wandev;
93              wandev = wandev->next)
94                 ;
95         return wandev;
96 }
97
98 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
99 {
100         struct wan_device *wandev = v;
101         (*pos)++;
102         return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next;
103 }
104
105 static void r_stop(struct seq_file *m, void *v)
106         __releases(kernel_lock)
107 {
108         mutex_unlock(&config_mutex);
109 }
110
111 static int config_show(struct seq_file *m, void *v)
112 {
113         struct wan_device *p = v;
114         if (v == SEQ_START_TOKEN) {
115                 seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |"
116                             "mem.size|option1|option2|option3|option4\n");
117                 return 0;
118         }
119         if (!p->state)
120                 return 0;
121         seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
122                         p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
123                         p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
124         return 0;
125 }
126
127 static int status_show(struct seq_file *m, void *v)
128 {
129         struct wan_device *p = v;
130         if (v == SEQ_START_TOKEN) {
131                 seq_puts(m, "Device name    |protocol|station|interface|"
132                             "clocking|baud rate| MTU |ndev|link state\n");
133                 return 0;
134         }
135         if (!p->state)
136                 return 0;
137         seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
138                 p->name,
139                 PROT_DECODE(p->config_id),
140                 p->config_id == WANCONFIG_FR ?
141                         (p->station ? "Node" : "CPE") :
142                         (p->config_id == WANCONFIG_X25 ?
143                         (p->station ? "DCE" : "DTE") :
144                         ("N/A")),
145                 p->interface ? "V.35" : "RS-232",
146                 p->clocking ? "internal" : "external",
147                 p->bps,
148                 p->mtu,
149                 p->ndev);
150
151         switch (p->state) {
152         case WAN_UNCONFIGURED:
153                 seq_printf(m, "%-12s\n", "unconfigured");
154                 break;
155         case WAN_DISCONNECTED:
156                 seq_printf(m, "%-12s\n", "disconnected");
157                 break;
158         case WAN_CONNECTING:
159                 seq_printf(m, "%-12s\n", "connecting");
160                 break;
161         case WAN_CONNECTED:
162                 seq_printf(m, "%-12s\n", "connected");
163                 break;
164         default:
165                 seq_printf(m, "%-12s\n", "invalid");
166                 break;
167         }
168         return 0;
169 }
170
171 static const struct seq_operations config_op = {
172         .start  = r_start,
173         .next   = r_next,
174         .stop   = r_stop,
175         .show   = config_show,
176 };
177
178 static const struct seq_operations status_op = {
179         .start  = r_start,
180         .next   = r_next,
181         .stop   = r_stop,
182         .show   = status_show,
183 };
184
185 static int config_open(struct inode *inode, struct file *file)
186 {
187         return seq_open(file, &config_op);
188 }
189
190 static int status_open(struct inode *inode, struct file *file)
191 {
192         return seq_open(file, &status_op);
193 }
194
195 static const struct file_operations config_fops = {
196         .owner   = THIS_MODULE,
197         .open    = config_open,
198         .read    = seq_read,
199         .llseek  = seq_lseek,
200         .release = seq_release,
201 };
202
203 static const struct file_operations status_fops = {
204         .owner   = THIS_MODULE,
205         .open    = status_open,
206         .read    = seq_read,
207         .llseek  = seq_lseek,
208         .release = seq_release,
209 };
210
211 static int wandev_show(struct seq_file *m, void *v)
212 {
213         struct wan_device *wandev = m->private;
214
215         if (wandev->magic != ROUTER_MAGIC)
216                 return 0;
217
218         if (!wandev->state) {
219                 seq_puts(m, "device is not configured!\n");
220                 return 0;
221         }
222
223         /* Update device statistics */
224         if (wandev->update) {
225                 int err = wandev->update(wandev);
226                 if (err == -EAGAIN) {
227                         seq_puts(m, "Device is busy!\n");
228                         return 0;
229                 }
230                 if (err) {
231                         seq_puts(m, "Device is not configured!\n");
232                         return 0;
233                 }
234         }
235
236         seq_printf(m, PROC_STATS_FORMAT,
237                 "total packets received", wandev->stats.rx_packets);
238         seq_printf(m, PROC_STATS_FORMAT,
239                 "total packets transmitted", wandev->stats.tx_packets);
240         seq_printf(m, PROC_STATS_FORMAT,
241                 "total bytes received", wandev->stats.rx_bytes);
242         seq_printf(m, PROC_STATS_FORMAT,
243                 "total bytes transmitted", wandev->stats.tx_bytes);
244         seq_printf(m, PROC_STATS_FORMAT,
245                 "bad packets received", wandev->stats.rx_errors);
246         seq_printf(m, PROC_STATS_FORMAT,
247                 "packet transmit problems", wandev->stats.tx_errors);
248         seq_printf(m, PROC_STATS_FORMAT,
249                 "received frames dropped", wandev->stats.rx_dropped);
250         seq_printf(m, PROC_STATS_FORMAT,
251                 "transmit frames dropped", wandev->stats.tx_dropped);
252         seq_printf(m, PROC_STATS_FORMAT,
253                 "multicast packets received", wandev->stats.multicast);
254         seq_printf(m, PROC_STATS_FORMAT,
255                 "transmit collisions", wandev->stats.collisions);
256         seq_printf(m, PROC_STATS_FORMAT,
257                 "receive length errors", wandev->stats.rx_length_errors);
258         seq_printf(m, PROC_STATS_FORMAT,
259                 "receiver overrun errors", wandev->stats.rx_over_errors);
260         seq_printf(m, PROC_STATS_FORMAT,
261                 "CRC errors", wandev->stats.rx_crc_errors);
262         seq_printf(m, PROC_STATS_FORMAT,
263                 "frame format errors (aborts)", wandev->stats.rx_frame_errors);
264         seq_printf(m, PROC_STATS_FORMAT,
265                 "receiver fifo overrun", wandev->stats.rx_fifo_errors);
266         seq_printf(m, PROC_STATS_FORMAT,
267                 "receiver missed packet", wandev->stats.rx_missed_errors);
268         seq_printf(m, PROC_STATS_FORMAT,
269                 "aborted frames transmitted", wandev->stats.tx_aborted_errors);
270         return 0;
271 }
272
273 static int wandev_open(struct inode *inode, struct file *file)
274 {
275         return single_open(file, wandev_show, PDE(inode)->data);
276 }
277
278 static const struct file_operations wandev_fops = {
279         .owner   = THIS_MODULE,
280         .open    = wandev_open,
281         .read    = seq_read,
282         .llseek  = seq_lseek,
283         .release = single_release,
284         .unlocked_ioctl  = wanrouter_ioctl,
285 };
286
287 /*
288  *      Initialize router proc interface.
289  */
290
291 int __init wanrouter_proc_init(void)
292 {
293         struct proc_dir_entry *p;
294         proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
295         if (!proc_router)
296                 goto fail;
297
298         p = proc_create("config", S_IRUGO, proc_router, &config_fops);
299         if (!p)
300                 goto fail_config;
301         p = proc_create("status", S_IRUGO, proc_router, &status_fops);
302         if (!p)
303                 goto fail_stat;
304         return 0;
305 fail_stat:
306         remove_proc_entry("config", proc_router);
307 fail_config:
308         remove_proc_entry(ROUTER_NAME, init_net.proc_net);
309 fail:
310         return -ENOMEM;
311 }
312
313 /*
314  *      Clean up router proc interface.
315  */
316
317 void wanrouter_proc_cleanup(void)
318 {
319         remove_proc_entry("config", proc_router);
320         remove_proc_entry("status", proc_router);
321         remove_proc_entry(ROUTER_NAME, init_net.proc_net);
322 }
323
324 /*
325  *      Add directory entry for WAN device.
326  */
327
328 int wanrouter_proc_add(struct wan_device* wandev)
329 {
330         if (wandev->magic != ROUTER_MAGIC)
331                 return -EINVAL;
332
333         wandev->dent = proc_create(wandev->name, S_IRUGO,
334                                    proc_router, &wandev_fops);
335         if (!wandev->dent)
336                 return -ENOMEM;
337         wandev->dent->data      = wandev;
338         return 0;
339 }
340
341 /*
342  *      Delete directory entry for WAN device.
343  */
344 int wanrouter_proc_delete(struct wan_device* wandev)
345 {
346         if (wandev->magic != ROUTER_MAGIC)
347                 return -EINVAL;
348         remove_proc_entry(wandev->name, proc_router);
349         return 0;
350 }
351
352 #else
353
354 /*
355  *      No /proc - output stubs
356  */
357
358 int __init wanrouter_proc_init(void)
359 {
360         return 0;
361 }
362
363 void wanrouter_proc_cleanup(void)
364 {
365 }
366
367 int wanrouter_proc_add(struct wan_device *wandev)
368 {
369         return 0;
370 }
371
372 int wanrouter_proc_delete(struct wan_device *wandev)
373 {
374         return 0;
375 }
376
377 #endif
378
379 /*
380  *      End
381  */
382