[VLAN]: Fix promiscous/allmulti synchronization races
[linux-2.6/openmoko-kernel/knife-kernel.git] / net / wanrouter / wanproc.c
blob236e7eaf1b7f4d6069efa61b16b4aedcc1ef238e
1 /*****************************************************************************
2 * wanproc.c WAN Router Module. /proc filesystem interface.
4 * This module is completely hardware-independent and provides
5 * access to the router using Linux /proc filesystem.
7 * Author: Gideon Hack
9 * Copyright: (c) 1995-1999 Sangoma Technologies Inc.
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 *****************************************************************************/
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/smp_lock.h>
32 #include <asm/io.h>
34 #define PROC_STATS_FORMAT "%30s: %12lu\n"
36 /****** Defines and Macros **************************************************/
38 #define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
39 (prot == WANCONFIG_X25) ? " X25" : \
40 (prot == WANCONFIG_PPP) ? " PPP" : \
41 (prot == WANCONFIG_CHDLC) ? " CHDLC": \
42 (prot == WANCONFIG_MPPP) ? " MPPP" : \
43 " Unknown" )
45 /****** Function Prototypes *************************************************/
47 #ifdef CONFIG_PROC_FS
49 /* Miscellaneous */
52 * Structures for interfacing with the /proc filesystem.
53 * Router creates its own directory /proc/net/router with the folowing
54 * entries:
55 * config device configuration
56 * status global device statistics
57 * <device> entry for each WAN device
61 * Generic /proc/net/router/<file> file and inode operations
65 * /proc/net/router
68 static struct proc_dir_entry *proc_router;
70 /* Strings */
73 * Interface functions
76 /****** Proc filesystem entry points ****************************************/
79 * Iterator
81 static void *r_start(struct seq_file *m, loff_t *pos)
83 struct wan_device *wandev;
84 loff_t l = *pos;
86 lock_kernel();
87 if (!l--)
88 return SEQ_START_TOKEN;
89 for (wandev = wanrouter_router_devlist; l-- && wandev;
90 wandev = wandev->next)
92 return wandev;
95 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
97 struct wan_device *wandev = v;
98 (*pos)++;
99 return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next;
102 static void r_stop(struct seq_file *m, void *v)
104 unlock_kernel();
107 static int config_show(struct seq_file *m, void *v)
109 struct wan_device *p = v;
110 if (v == SEQ_START_TOKEN) {
111 seq_puts(m, "Device name | port |IRQ|DMA| mem.addr |"
112 "mem.size|option1|option2|option3|option4\n");
113 return 0;
115 if (!p->state)
116 return 0;
117 seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
118 p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
119 p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
120 return 0;
123 static int status_show(struct seq_file *m, void *v)
125 struct wan_device *p = v;
126 if (v == SEQ_START_TOKEN) {
127 seq_puts(m, "Device name |protocol|station|interface|"
128 "clocking|baud rate| MTU |ndev|link state\n");
129 return 0;
131 if (!p->state)
132 return 0;
133 seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
134 p->name,
135 PROT_DECODE(p->config_id),
136 p->config_id == WANCONFIG_FR ?
137 (p->station ? "Node" : "CPE") :
138 (p->config_id == WANCONFIG_X25 ?
139 (p->station ? "DCE" : "DTE") :
140 ("N/A")),
141 p->interface ? "V.35" : "RS-232",
142 p->clocking ? "internal" : "external",
143 p->bps,
144 p->mtu,
145 p->ndev);
147 switch (p->state) {
148 case WAN_UNCONFIGURED:
149 seq_printf(m, "%-12s\n", "unconfigured");
150 break;
151 case WAN_DISCONNECTED:
152 seq_printf(m, "%-12s\n", "disconnected");
153 break;
154 case WAN_CONNECTING:
155 seq_printf(m, "%-12s\n", "connecting");
156 break;
157 case WAN_CONNECTED:
158 seq_printf(m, "%-12s\n", "connected");
159 break;
160 default:
161 seq_printf(m, "%-12s\n", "invalid");
162 break;
164 return 0;
167 static const struct seq_operations config_op = {
168 .start = r_start,
169 .next = r_next,
170 .stop = r_stop,
171 .show = config_show,
174 static const struct seq_operations status_op = {
175 .start = r_start,
176 .next = r_next,
177 .stop = r_stop,
178 .show = status_show,
181 static int config_open(struct inode *inode, struct file *file)
183 return seq_open(file, &config_op);
186 static int status_open(struct inode *inode, struct file *file)
188 return seq_open(file, &status_op);
191 static const struct file_operations config_fops = {
192 .owner = THIS_MODULE,
193 .open = config_open,
194 .read = seq_read,
195 .llseek = seq_lseek,
196 .release = seq_release,
199 static const struct file_operations status_fops = {
200 .owner = THIS_MODULE,
201 .open = status_open,
202 .read = seq_read,
203 .llseek = seq_lseek,
204 .release = seq_release,
207 static int wandev_show(struct seq_file *m, void *v)
209 struct wan_device *wandev = m->private;
211 if (wandev->magic != ROUTER_MAGIC)
212 return 0;
214 if (!wandev->state) {
215 seq_puts(m, "device is not configured!\n");
216 return 0;
219 /* Update device statistics */
220 if (wandev->update) {
221 int err = wandev->update(wandev);
222 if (err == -EAGAIN) {
223 seq_puts(m, "Device is busy!\n");
224 return 0;
226 if (err) {
227 seq_puts(m, "Device is not configured!\n");
228 return 0;
232 seq_printf(m, PROC_STATS_FORMAT,
233 "total packets received", wandev->stats.rx_packets);
234 seq_printf(m, PROC_STATS_FORMAT,
235 "total packets transmitted", wandev->stats.tx_packets);
236 seq_printf(m, PROC_STATS_FORMAT,
237 "total bytes received", wandev->stats.rx_bytes);
238 seq_printf(m, PROC_STATS_FORMAT,
239 "total bytes transmitted", wandev->stats.tx_bytes);
240 seq_printf(m, PROC_STATS_FORMAT,
241 "bad packets received", wandev->stats.rx_errors);
242 seq_printf(m, PROC_STATS_FORMAT,
243 "packet transmit problems", wandev->stats.tx_errors);
244 seq_printf(m, PROC_STATS_FORMAT,
245 "received frames dropped", wandev->stats.rx_dropped);
246 seq_printf(m, PROC_STATS_FORMAT,
247 "transmit frames dropped", wandev->stats.tx_dropped);
248 seq_printf(m, PROC_STATS_FORMAT,
249 "multicast packets received", wandev->stats.multicast);
250 seq_printf(m, PROC_STATS_FORMAT,
251 "transmit collisions", wandev->stats.collisions);
252 seq_printf(m, PROC_STATS_FORMAT,
253 "receive length errors", wandev->stats.rx_length_errors);
254 seq_printf(m, PROC_STATS_FORMAT,
255 "receiver overrun errors", wandev->stats.rx_over_errors);
256 seq_printf(m, PROC_STATS_FORMAT,
257 "CRC errors", wandev->stats.rx_crc_errors);
258 seq_printf(m, PROC_STATS_FORMAT,
259 "frame format errors (aborts)", wandev->stats.rx_frame_errors);
260 seq_printf(m, PROC_STATS_FORMAT,
261 "receiver fifo overrun", wandev->stats.rx_fifo_errors);
262 seq_printf(m, PROC_STATS_FORMAT,
263 "receiver missed packet", wandev->stats.rx_missed_errors);
264 seq_printf(m, PROC_STATS_FORMAT,
265 "aborted frames transmitted", wandev->stats.tx_aborted_errors);
266 return 0;
269 static int wandev_open(struct inode *inode, struct file *file)
271 return single_open(file, wandev_show, PDE(inode)->data);
274 static const struct file_operations wandev_fops = {
275 .owner = THIS_MODULE,
276 .open = wandev_open,
277 .read = seq_read,
278 .llseek = seq_lseek,
279 .release = single_release,
280 .ioctl = wanrouter_ioctl,
284 * Initialize router proc interface.
287 int __init wanrouter_proc_init(void)
289 struct proc_dir_entry *p;
290 proc_router = proc_mkdir(ROUTER_NAME, proc_net);
291 if (!proc_router)
292 goto fail;
294 p = create_proc_entry("config", S_IRUGO, proc_router);
295 if (!p)
296 goto fail_config;
297 p->proc_fops = &config_fops;
298 p = create_proc_entry("status", S_IRUGO, proc_router);
299 if (!p)
300 goto fail_stat;
301 p->proc_fops = &status_fops;
302 return 0;
303 fail_stat:
304 remove_proc_entry("config", proc_router);
305 fail_config:
306 remove_proc_entry(ROUTER_NAME, proc_net);
307 fail:
308 return -ENOMEM;
312 * Clean up router proc interface.
315 void wanrouter_proc_cleanup(void)
317 remove_proc_entry("config", proc_router);
318 remove_proc_entry("status", proc_router);
319 remove_proc_entry(ROUTER_NAME, proc_net);
323 * Add directory entry for WAN device.
326 int wanrouter_proc_add(struct wan_device* wandev)
328 if (wandev->magic != ROUTER_MAGIC)
329 return -EINVAL;
331 wandev->dent = create_proc_entry(wandev->name, S_IRUGO, proc_router);
332 if (!wandev->dent)
333 return -ENOMEM;
334 wandev->dent->proc_fops = &wandev_fops;
335 wandev->dent->data = wandev;
336 return 0;
340 * Delete directory entry for WAN device.
342 int wanrouter_proc_delete(struct wan_device* wandev)
344 if (wandev->magic != ROUTER_MAGIC)
345 return -EINVAL;
346 remove_proc_entry(wandev->name, proc_router);
347 return 0;
350 #else
353 * No /proc - output stubs
356 int __init wanrouter_proc_init(void)
358 return 0;
361 void wanrouter_proc_cleanup(void)
365 int wanrouter_proc_add(struct wan_device *wandev)
367 return 0;
370 int wanrouter_proc_delete(struct wan_device *wandev)
372 return 0;
375 #endif
378 * End