zaurus-2.6.inc: force creation of jffs2 images
[openembedded.git] / recipes / linux / unslung-kernel / netconsole.patch
1 diff -Naur linux-2.4.22/drivers/net/Config.in.orig linux-2.4.22/drivers/net/Config.in
2 --- linux-2.4.22/drivers/net/Config.in.orig     2006-02-26 11:49:28.000000000 -0600
3 +++ linux-2.4.22/drivers/net/Config.in  2006-02-26 11:40:31.000000000 -0600
4 @@ -338,6 +338,8 @@
5     dep_tristate '  SysKonnect FDDI PCI support' CONFIG_SKFP $CONFIG_PCI
6  fi
7  
8 +dep_tristate 'Network logging support' CONFIG_NETCONSOLE
9 +
10  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
11     if [ "$CONFIG_INET" = "y" ]; then
12        bool 'HIPPI driver support (EXPERIMENTAL)' CONFIG_HIPPI
13 diff -Naur linux-2.4.22/drivers/net/Makefile.orig linux-2.4.22/drivers/net/Makefile
14 --- linux-2.4.22/drivers/net/Makefile.orig      2006-02-26 11:49:45.000000000 -0600
15 +++ linux-2.4.22/drivers/net/Makefile   2006-02-26 11:38:58.000000000 -0600
16 @@ -272,6 +272,8 @@
17  obj-y          += ../acorn/net/acorn-net.o
18  endif
19  
20 +obj-$(CONFIG_NETCONSOLE) += netconsole.o
21 +
22  #
23  # HIPPI adapters
24  #
25 diff -Naur linux-2.4.22/drivers/net/netconsole.c.orig linux-2.4.22/drivers/net/netconsole.c
26 --- linux-2.4.22/drivers/net/netconsole.c.orig  2006-07-02 23:40:44.597695500 -0500
27 +++ linux-2.4.22/drivers/net/netconsole.c       2006-07-10 15:58:44.000000000 -0500
28 @@ -0,0 +1,353 @@
29 +/*  linux/drivers/net/netconsole.c
30 + *
31 + *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
32 + *
33 + *  This file contains the implementation of an IRQ-safe, crash-safe
34 + *  kernel console implementation that outputs kernel messages to the
35 + *  network.
36 + *
37 + * Modification history:
38 + *
39 + * 2001-09-17    started by Ingo Molnar.
40 + * 2006-02-26    very minor modifications to suit the NSLU2 w/Unslung -- Mike Westerhof.
41 + * 2006-07-10    usability mods for Unslung (text only, and IP addrs) -- Mike Westerhof.
42 + */
43 +
44 +/****************************************************************
45 + *      This program is free software; you can redistribute it and/or modify
46 + *      it under the terms of the GNU General Public License as published by
47 + *      the Free Software Foundation; either version 2, or (at your option)
48 + *      any later version.
49 + *
50 + *      This program is distributed in the hope that it will be useful,
51 + *      but WITHOUT ANY WARRANTY; without even the implied warranty of
52 + *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
53 + *      GNU General Public License for more details.
54 + *
55 + *      You should have received a copy of the GNU General Public License
56 + *      along with this program; if not, write to the Free Software
57 + *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
58 + *
59 + ****************************************************************/
60 +
61 +#include <net/tcp.h>
62 +#include <net/udp.h>
63 +#include <linux/mm.h>
64 +#include <linux/tty.h>
65 +#include <linux/init.h>
66 +#include <linux/module.h>
67 +#include <asm/unaligned.h>
68 +#include <linux/console.h>
69 +#include <linux/smp_lock.h>
70 +#include <linux/netdevice.h>
71 +#include <linux/tty_driver.h>
72 +#include <linux/etherdevice.h>
73 +
74 +static struct net_device *netconsole_dev;
75 +static u16 source_port, target_port;
76 +static u32 source_ip, target_ip, target_ipaddr;
77 +static unsigned char daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
78 +
79 +#define NETCONSOLE_VERSION 0x01
80 +/* HEADER_LEN was "5" -- it's zero for Unslung; makes it work better with netcat */
81 +#define HEADER_LEN 0
82 +
83 +#define MAX_UDP_CHUNK 1460
84 +#define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
85 +
86 +/*
87 + * We maintain a small pool of fully-sized skbs,
88 + * to make sure the message gets out even in
89 + * extreme OOM situations.
90 + */
91 +/* Was 32, lowered to 16 for Unslung (to save memory) */
92 +#define MAX_NETCONSOLE_SKBS 16
93 +
94 +
95 +static spinlock_t netconsole_lock = SPIN_LOCK_UNLOCKED;
96 +static int nr_netconsole_skbs;
97 +static struct sk_buff *netconsole_skbs;
98 +
99 +#define MAX_SKB_SIZE \
100 +               (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
101 +                               sizeof(struct iphdr) + sizeof(struct ethhdr))
102 +
103 +static void __refill_netconsole_skbs(void)
104 +{
105 +       struct sk_buff *skb;
106 +       unsigned long flags;
107 +
108 +       spin_lock_irqsave(&netconsole_lock, flags);
109 +       while (nr_netconsole_skbs < MAX_NETCONSOLE_SKBS) {
110 +               skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
111 +               if (!skb)
112 +                       break;
113 +               if (netconsole_skbs)
114 +                       skb->next = netconsole_skbs;
115 +               else
116 +                       skb->next = NULL;
117 +               netconsole_skbs = skb;
118 +               nr_netconsole_skbs++;
119 +       }
120 +       spin_unlock_irqrestore(&netconsole_lock, flags);
121 +}
122 +
123 +static struct sk_buff * get_netconsole_skb(void)
124 +{
125 +       struct sk_buff *skb;
126 +
127 +       unsigned long flags;
128 +
129 +       spin_lock_irqsave(&netconsole_lock, flags);
130 +       skb = netconsole_skbs;
131 +       if (skb)
132 +               netconsole_skbs = skb->next;
133 +       skb->next = NULL;
134 +       nr_netconsole_skbs--;
135 +       spin_unlock_irqrestore(&netconsole_lock, flags);
136 +
137 +       return skb;
138 +}
139 +
140 +static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
141 +static unsigned int offset;
142 +
143 +static void send_netconsole_skb(struct net_device *dev, const char *msg, unsigned int msg_len)
144 +{
145 +       int total_len, eth_len, ip_len, udp_len;
146 +       unsigned long flags;
147 +       struct sk_buff *skb;
148 +       struct udphdr *udph;
149 +       struct iphdr *iph;
150 +       struct ethhdr *eth;
151 +
152 +       udp_len = msg_len + HEADER_LEN + sizeof(*udph);
153 +       ip_len = eth_len = udp_len + sizeof(*iph);
154 +       total_len = eth_len + ETH_HLEN;
155 +
156 +       if (nr_netconsole_skbs < MAX_NETCONSOLE_SKBS)
157 +               __refill_netconsole_skbs();
158 +
159 +       skb = alloc_skb(total_len, GFP_ATOMIC);
160 +       if (!skb) {
161 +               skb = get_netconsole_skb();
162 +               if (!skb)
163 +                       /* tough! */
164 +                       return;
165 +       }
166 +
167 +       atomic_set(&skb->users, 1);
168 +       skb_reserve(skb, total_len - msg_len - HEADER_LEN);
169 +/* Header data removed for Unslung -- its presence makes netcat less useful
170 + *     skb->data[0] = NETCONSOLE_VERSION;
171 + *
172 + *     spin_lock_irqsave(&sequence_lock, flags);
173 + *     put_unaligned(htonl(offset), (u32 *) (skb->data + 1));
174 + *     offset += msg_len;
175 + *     spin_unlock_irqrestore(&sequence_lock, flags);
176 + */
177 +       memcpy(skb->data + HEADER_LEN, msg, msg_len);
178 +       skb->len += msg_len + HEADER_LEN;
179 +
180 +       udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
181 +       udph->source = source_port;
182 +       udph->dest = target_port;
183 +       udph->len = htons(udp_len);
184 +       udph->check = 0;
185 +
186 +       iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
187 +
188 +       iph->version  = 4;
189 +       iph->ihl      = 5;
190 +       iph->tos      = 0;
191 +        iph->tot_len  = htons(ip_len);
192 +       iph->id       = 0;
193 +       iph->frag_off = 0;
194 +       iph->ttl      = 64;
195 +        iph->protocol = IPPROTO_UDP;
196 +       iph->check    = 0;
197 +        iph->saddr    = source_ip;
198 +        iph->daddr    = target_ip;
199 +       iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
200 +
201 +       eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
202 +
203 +       eth->h_proto = htons(ETH_P_IP);
204 +       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
205 +       memcpy(eth->h_dest, daddr, dev->addr_len);
206 +
207 +repeat:
208 +       spin_lock(&dev->xmit_lock);
209 +       dev->xmit_lock_owner = smp_processor_id();
210 +
211 +       if (netif_queue_stopped(dev)) {
212 +               dev->xmit_lock_owner = -1;
213 +               spin_unlock(&dev->xmit_lock);
214 +
215 +               dev->poll_controller(dev);
216 +               goto repeat;
217 +       }
218 +
219 +       dev->hard_start_xmit(skb, dev);
220 +
221 +       dev->xmit_lock_owner = -1;
222 +       spin_unlock(&dev->xmit_lock);
223 +}
224 +
225 +static void write_netconsole_msg(struct console *con, const char *msg, unsigned int msg_len)
226 +{
227 +       int len, left;
228 +       struct net_device *dev;
229 +
230 +       dev = netconsole_dev;
231 +       if (!dev)
232 +               return;
233 +
234 +       if (dev->poll_controller && netif_running(dev)) {
235 +               unsigned long flags;
236 +
237 +               __save_flags(flags);
238 +               __cli();
239 +               left = msg_len;
240 +repeat:
241 +               if (left > MAX_PRINT_CHUNK)
242 +                       len = MAX_PRINT_CHUNK;
243 +               else
244 +                       len = left;
245 +               send_netconsole_skb(dev, msg, len);
246 +               msg += len;
247 +               left -= len;
248 +               if (left)
249 +                       goto repeat;
250 +               __restore_flags(flags);
251 +       }
252 +}
253 +
254 +static char *dev;
255 +static int target_eth_byte0 = 255;
256 +static int target_eth_byte1 = 255;
257 +static int target_eth_byte2 = 255;
258 +static int target_eth_byte3 = 255;
259 +static int target_eth_byte4 = 255;
260 +static int target_eth_byte5 = 255;
261 +
262 +MODULE_AUTHOR("Ingo Molnar <mingo@redhat.com>");
263 +MODULE_DESCRIPTION("kernel network console implementation");
264 +MODULE_LICENSE("GPL");
265 +MODULE_PARM(target_ip, "i");
266 +MODULE_PARM(target_ipaddr, "s");
267 +MODULE_PARM(target_eth_byte0, "i");
268 +MODULE_PARM(target_eth_byte1, "i");
269 +MODULE_PARM(target_eth_byte2, "i");
270 +MODULE_PARM(target_eth_byte3, "i");
271 +MODULE_PARM(target_eth_byte4, "i");
272 +MODULE_PARM(target_eth_byte5, "i");
273 +MODULE_PARM(source_port, "h");
274 +MODULE_PARM(target_port, "h");
275 +MODULE_PARM(dev, "s");
276 +
277 +static struct console netconsole =
278 +        { flags: CON_ENABLED, write: write_netconsole_msg };
279 +
280 +static int init_netconsole(void)
281 +{
282 +       struct net_device *ndev = NULL;
283 +       struct in_device *in_dev;
284 +
285 +       // Set some reasonable defaults, at least for the NSLU2 device
286 +       if (!target_port)
287 +               target_port = 6666;
288 +       if (!source_port)
289 +               source_port = 6665;
290 +       if (!dev)
291 +               dev = "ixp0";
292 +
293 +       printk(KERN_INFO "netconsole: using network device <%s>\n", dev);
294 +       // this will be valid once the device goes up.
295 +       if (dev)
296 +               ndev = dev_get_by_name(dev);
297 +       if (!ndev) {
298 +               printk(KERN_ERR "netconsole: network device %s does not exist, aborting.\n", dev);
299 +               return -1;
300 +       }
301 +       if (!ndev->poll_controller) {
302 +               printk(KERN_ERR "netconsole: %s's network driver does not implement netlogging yet, aborting.\n", dev);
303 +               return -1;
304 +       }
305 +        in_dev = in_dev_get(ndev);
306 +       if (!in_dev) {
307 +               printk(KERN_ERR "netconsole: network device %s is not an IP protocol device, aborting.\n", dev);
308 +               return -1;
309 +       }
310 +       source_ip = ntohl(in_dev->ifa_list->ifa_local);
311 +       if (!source_ip) {
312 +               printk(KERN_ERR "netconsole: network device %s has no local address, aborting.\n", dev);
313 +               return -1;
314 +       }
315 +       source_ip = htonl(source_ip);
316 +#define IP(x) ((char *)&source_ip)[x]
317 +       printk(KERN_INFO "netconsole: using source IP %i.%i.%i.%i\n",
318 +               IP(0), IP(1), IP(2), IP(3));
319 +#undef IP
320 +       if (!target_ipaddr) {
321 +               if (!target_ip) {
322 +                       printk(KERN_ERR "netconsole: neither target_ipaddr nor target_ip parameter not specified, aborting.\n");
323 +                       return -1;
324 +               } else {
325 +                       target_ip = htonl(target_ip);
326 +               }
327 +       } else {
328 +               target_ip = in_aton(target_ipaddr);
329 +       }
330 +#define IP(x) ((char *)&target_ip)[x]
331 +       printk(KERN_INFO "netconsole: using target IP %i.%i.%i.%i\n",
332 +               IP(0), IP(1), IP(2), IP(3));
333 +#undef IP
334 +       if (!source_port) {
335 +               printk(KERN_ERR "netconsole: source_port parameter not specified, aborting.\n");
336 +               return -1;
337 +       }
338 +       printk(KERN_INFO "netconsole: using source UDP port: %i\n", source_port);
339 +       source_port = htons(source_port);
340 +       if (!target_port) {
341 +               printk(KERN_ERR "netconsole: target_port parameter not specified, aborting.\n");
342 +               return -1;
343 +       }
344 +       printk(KERN_INFO "netconsole: using target UDP port: %i\n", target_port);
345 +       target_port = htons(target_port);
346 +
347 +       daddr[0] = target_eth_byte0;
348 +       daddr[1] = target_eth_byte1;
349 +       daddr[2] = target_eth_byte2;
350 +       daddr[3] = target_eth_byte3;
351 +       daddr[4] = target_eth_byte4;
352 +       daddr[5] = target_eth_byte5;
353 +
354 +       if ((daddr[0] & daddr[1] & daddr[2] & daddr[3] & daddr[4] & daddr[5]) == 255)
355 +               printk(KERN_INFO "netconsole: using broadcast ethernet frames to send packets.\n");
356 +       else
357 +               printk(KERN_INFO "netconsole: using target ethernet address %02x:%02x:%02x:%02x:%02x:%02x.\n", daddr[0], daddr[1], daddr[2], daddr[3], daddr[4], daddr[5]);
358 +               
359 +       netconsole_dev = ndev;
360 +#define STARTUP_MSG "[...network console startup...]\n"
361 +       write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
362 +
363 +       register_console(&netconsole);
364 +       printk(KERN_INFO "netconsole: network logging started up successfully!\n");
365 +       return 0;
366 +}
367 +
368 +static void cleanup_netconsole(void)
369 +{
370 +       printk(KERN_INFO "netconsole: network logging shut down.\n");
371 +       unregister_console(&netconsole);
372 +
373 +#define SHUTDOWN_MSG "[...network console shutdown...]\n"
374 +       write_netconsole_msg(NULL, SHUTDOWN_MSG, strlen(SHUTDOWN_MSG));
375 +       netconsole_dev = NULL;
376 +}
377 +
378 +module_init(init_netconsole);
379 +module_exit(cleanup_netconsole);
380 +
381 +int dummy = MAX_SKB_SIZE;
382 diff -Naur linux-2.4.22/include/linux/netdevice.h.orig linux-2.4.22/include/linux/netdevice.h
383 --- linux-2.4.22/include/linux/netdevice.h.orig 2006-02-26 11:50:24.000000000 -0600
384 +++ linux-2.4.22/include/linux/netdevice.h      2006-02-26 11:37:14.000000000 -0600
385 @@ -428,6 +428,9 @@
386         int                     (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
387         int                     (*accept_fastpath)(struct net_device *, struct dst_entry*);
388  
389 +#define HAVE_POLL_CONTROLLER
390 +       void                    (*poll_controller)(struct net_device *dev);
391 +
392         /* open/release and usage marking */
393         struct module *owner;
394