1 Index: linux-2.4.20-rh/drivers/net/netconsole.c
2 ===================================================================
3 --- linux-2.4.20-rh.orig/drivers/net/netconsole.c 2003-07-22 16:02:23.000000000 +0800
4 +++ linux-2.4.20-rh/drivers/net/netconsole.c 2003-11-11 07:42:33.000000000 +0800
7 * 2001-09-17 started by Ingo Molnar.
8 * 2002-03-14 simultaneous syslog packet option by Michael K. Johnson
9 + * 2003-10-30 Add sysrq command processing by Wangdi <wangdi@clusterfs.com>
13 /****************************************************************
15 #include <linux/tty_driver.h>
16 #include <linux/etherdevice.h>
17 #include <linux/elf.h>
18 +#include "netconsole.h"
20 static struct net_device *netconsole_dev;
21 static u16 source_port, netdump_target_port, netlog_target_port, syslog_target_port;
23 static unsigned int mhz = 500, idle_timeout;
24 static unsigned long long mhz_cycles, jiffy_cycles;
26 -#include "netconsole.h"
28 #define MAX_UDP_CHUNK 1460
29 #define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
34 # define Dprintk(x...) printk(KERN_INFO x)
40 +void (*irqfunc)(int, void *, struct pt_regs *);
42 +static void netdump_poll(struct net_device *dev)
46 + disable_irq(dev->irq);
48 + irqfunc(dev->irq, dev, 0);
50 + if(dev->poll && test_bit(__LINK_STATE_RX_SCHED, &dev->state))
51 + dev->poll(dev, &budget);
53 + enable_irq(dev->irq);
57 static struct sk_buff * alloc_netconsole_skb(struct net_device *dev, int len, int reserve)
62 Dprintk("alloc skb: polling controller ...\n");
63 - dev->poll_controller(dev);
69 spin_unlock(&dev->xmit_lock);
71 Dprintk("xmit skb: polling controller ...\n");
72 - dev->poll_controller(dev);
74 zap_completion_queue();
78 static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
79 static unsigned int log_offset;
81 +static int thread_stopped = 0;
82 +/*Interrupt function for netdump */
83 +static int sysrq_mode = 0;
84 +static int stop_sysrq_thread = 0;
85 +#define Set_Sysrq_mode() (sysrq_mode = 1)
86 +#define Clear_Sysrq_mode() (sysrq_mode = 0)
87 +static char send_cache[MAX_PRINT_CHUNK];
88 +static unsigned int send_cache_pos = 0;
89 +wait_queue_head_t sysrq_thread_queue;
90 +wait_queue_head_t sysrq_thread_waiter_queue;
92 +#define SEND_MSG_BUFFER(buf, len) \
96 + unsigned int flags; \
97 + __save_flags(flags); \
99 + reply.code = REPLY_LOG; \
102 + spin_lock(&sequence_lock); \
103 + send_netlog_skb(dev, buf, len, &reply); \
104 + spin_unlock(&sequence_lock); \
105 + __restore_flags(flags); \
108 +void netconsole_do_sysrq(req_t *req)
110 + struct pt_regs regs;
111 + struct net_device *dev = netconsole_dev;
116 + get_current_regs(®s);
117 + handle_sysrq((int)req->from, ®s, NULL);
119 + if (send_cache_pos != 0){
120 + SEND_MSG_BUFFER(send_cache, send_cache_pos);
121 + memset(send_cache, 0, MAX_PRINT_CHUNK);
122 + send_cache_pos = 0;
125 + Clear_Sysrq_mode();
127 static void write_netconsole_msg(struct console *con, const char *msg0, unsigned int msg_len)
130 struct net_device *dev;
131 const char *msg = msg0;
135 dev = netconsole_dev;
136 if (!dev || netdump_mode)
139 - if (dev->poll_controller && netif_running(dev)) {
141 + unsigned long total_len = send_cache_pos + msg_len;
142 + unsigned long left_len = msg_len;
143 + while (total_len >= MAX_PRINT_CHUNK){
144 + unsigned long send_len = MAX_PRINT_CHUNK - send_cache_pos;
145 + memcpy(send_cache + send_cache_pos, msg, send_len);
146 + SEND_MSG_BUFFER(send_cache, MAX_PRINT_CHUNK);
147 + send_cache_pos = 0;
148 + total_len -= MAX_PRINT_CHUNK;
149 + left_len -= send_len;
152 + memcpy(send_cache + send_cache_pos, msg + (msg_len -left_len), left_len);
153 + send_cache_pos += left_len;
156 + }else if (netif_running(dev)) {
162 struct net_device *dev;
165 - return NET_RX_SUCCESS;
168 static int packet_count;
170 Dprintk("... netdump from: %08x.\n", req->from);
171 Dprintk("... netdump to: %08x.\n", req->to);
176 + else if (req->command == COMM_SYSRQ){
178 + wake_up(&sysrq_thread_queue);
179 + return NET_RX_DROP;
183 + return NET_RX_SUCCESS;
188 kunmap_atomic(kaddr, KM_NETDUMP);
193 * This function waits for the client to acknowledge the receipt
194 * of the netdump startup reply, with the possibility of packets
198 Dprintk("handshake: polling controller ...\n");
199 - dev->poll_controller(dev);
201 zap_completion_queue();
205 while (netdump_mode) {
207 Dprintk("main netdump loop: polling controller ...\n");
208 - dev->poll_controller(dev);
210 zap_completion_queue();
213 @@ -1009,6 +1095,32 @@
214 printk("NETDUMP END!\n");
215 __restore_flags(flags);
217 +static int netconsole_sysrq_schedule(void *arg)
219 + struct task_struct *tsk = current;
221 + sprintf(tsk->comm, "sysrq_schedule");
222 + sigfillset(&tsk->blocked);
225 + thread_stopped = 0;
227 + wait_event_interruptible(sysrq_thread_queue,
228 + !list_empty(&request_list) || stop_sysrq_thread);
229 + while (!list_empty(&request_list)) {
230 + req_t *req = get_new_req();
231 + if (req->command == COMM_SYSRQ)
232 + netconsole_do_sysrq(req);
234 + if (stop_sysrq_thread)
236 + wake_up(&sysrq_thread_waiter_queue);
238 + thread_stopped = 1;
239 + wake_up(&sysrq_thread_waiter_queue);
245 static int netdump_target_eth_byte0 = 255;
246 @@ -1087,11 +1199,12 @@
248 static struct console netconsole =
249 { flags: CON_ENABLED, write: write_netconsole_msg };
251 static int init_netconsole(void)
253 struct net_device *ndev = NULL;
254 struct in_device *in_dev;
255 + struct irqaction *action;
258 printk(KERN_INFO "netlog: using network device <%s>\n", dev);
259 // this will be valid once the device goes up.
260 @@ -1101,10 +1214,6 @@
261 printk(KERN_ERR "netlog: network device %s does not exist, aborting.\n", dev);
264 - if (!ndev->poll_controller) {
265 - printk(KERN_ERR "netlog: %s's network driver does not implement netlogging yet, aborting.\n", dev);
268 in_dev = in_dev_get(ndev);
270 printk(KERN_ERR "netlog: network device %s is not an IP protocol device, aborting.\n", dev);
271 @@ -1137,8 +1246,6 @@
272 if (!netdump_target_ip && !netlog_target_ip && !syslog_target_ip) {
273 printk(KERN_ERR "netlog: target_ip parameter not specified, aborting.\n");
276 - if (netdump_target_ip) {
277 #define IP(x) ((unsigned char *)&netdump_target_ip)[x]
278 printk(KERN_INFO "netlog: using netdump target IP %u.%u.%u.%u\n",
279 IP(3), IP(2), IP(1), IP(0));
280 @@ -1214,12 +1321,27 @@
282 mhz_cycles = (unsigned long long)mhz * 1000000ULL;
283 jiffy_cycles = (unsigned long long)mhz * (1000000/HZ);
285 - INIT_LIST_HEAD(&request_list);
288 ndev->rx_hook = netconsole_rx_hook;
289 netdump_func = netconsole_netdump;
290 netconsole_dev = ndev;
291 + /* find irq function of the ndev*/
292 + action=find_irq_action(ndev->irq, ndev);
294 + printk(KERN_ERR "couldn't find irq handler for <%s>", dev);
297 + irqfunc = action->handler;
299 + stop_sysrq_thread = 0;
300 + INIT_LIST_HEAD(&request_list);
301 + init_waitqueue_head(&sysrq_thread_queue);
302 + init_waitqueue_head(&sysrq_thread_waiter_queue);
303 + if ((rc = kernel_thread(netconsole_sysrq_schedule, NULL, 0)) < 0 ){
304 + printk(KERN_ERR "Can not start netconsole sysrq thread: rc %d\n", rc);
308 #define STARTUP_MSG "[...network console startup...]\n"
309 write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
311 @@ -1230,7 +1352,11 @@
313 static void cleanup_netconsole(void)
315 - printk(KERN_INFO "netlog: network logging shut down.\n");
316 + stop_sysrq_thread = 1;
318 + wake_up(&sysrq_thread_queue);
319 + wait_event(sysrq_thread_waiter_queue, thread_stopped);
320 + printk(KERN_INFO"netlog: network logging shut down.\n");
321 unregister_console(&netconsole);
323 #define SHUTDOWN_MSG "[...network console shutdown...]\n"
324 Index: linux-2.4.20-rh/drivers/net/netconsole.h
325 ===================================================================
326 --- linux-2.4.20-rh.orig/drivers/net/netconsole.h 2003-07-22 16:02:23.000000000 +0800
327 +++ linux-2.4.20-rh/drivers/net/netconsole.h 2003-10-30 01:48:45.000000000 +0800
330 ****************************************************************/
332 -#define NETCONSOLE_VERSION 0x04
333 +#define NETCONSOLE_VERSION 0x03
335 enum netdump_commands {
338 COMM_START_NETDUMP_ACK = 7,
341 + COMM_START_WRITE_NETDUMP_ACK = 10,
345 #define NETDUMP_REQ_SIZE (8+4*4)
349 REPLY_SHOW_STATE = 12,
353 typedef struct netdump_reply_s {
357 #define HEADER_LEN (1 + sizeof(reply_t))
359 +/* for netconsole */
360 +static inline void get_current_regs(struct pt_regs *regs)
362 + __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
363 + __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
364 + __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
365 + __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
366 + __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
367 + __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
368 + __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
369 + __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
370 + __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
371 + __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
372 + __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
373 + __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
374 + __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
375 + regs->eip = (unsigned long)current_text_addr();
378 Index: linux-2.4.20-rh/arch/i386/kernel/irq.c
379 ===================================================================
380 --- linux-2.4.20-rh.orig/arch/i386/kernel/irq.c 2003-10-30 08:29:38.000000000 +0800
381 +++ linux-2.4.20-rh/arch/i386/kernel/irq.c 2003-10-30 08:30:13.000000000 +0800
382 @@ -1043,7 +1043,20 @@
383 register_irq_proc(irq);
386 +struct irqaction *find_irq_action(unsigned int irq, void *dev_id)
388 + struct irqaction *a, *r=0;
390 + spin_lock_irq(&irq_desc[irq].lock);
391 + for(a=irq_desc[irq].action; a; a=a->next) {
392 + if(a->dev_id == dev_id) {
397 + spin_unlock_irq(&irq_desc[irq].lock);
401 static struct proc_dir_entry * root_irq_dir;
402 static struct proc_dir_entry * irq_dir [NR_IRQS];
403 Index: linux-2.4.20-rh/net/core/dev.c
404 ===================================================================
405 --- linux-2.4.20-rh.orig/net/core/dev.c 2003-10-29 01:40:26.000000000 +0800
406 +++ linux-2.4.20-rh/net/core/dev.c 2003-10-30 01:48:45.000000000 +0800
407 @@ -1475,6 +1475,16 @@
411 + if (unlikely(skb->dev->rx_hook != NULL)) {
414 + ret = skb->dev->rx_hook(skb);
415 + if (ret == NET_RX_DROP){
421 netdev_rx_stat[smp_processor_id()].total++;
423 #ifdef CONFIG_NET_FASTROUTE
424 Index: linux-2.4.20-rh/include/asm-i386/irq.h
425 ===================================================================
426 --- linux-2.4.20-rh.orig/include/asm-i386/irq.h 2003-10-28 16:18:18.000000000 +0800
427 +++ linux-2.4.20-rh/include/asm-i386/irq.h 2003-10-30 10:24:49.000000000 +0800
429 extern void disable_irq_nosync(unsigned int);
430 extern void enable_irq(unsigned int);
431 extern void release_x86_irqs(struct task_struct *);
433 +extern struct irqaction *find_irq_action(unsigned int irq, void *dev_id);
434 #ifdef CONFIG_X86_LOCAL_APIC
435 #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
437 Index: linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c
438 ===================================================================
439 --- linux-2.4.20-rh.orig/arch/i386/kernel/i386_ksyms.c 2003-10-28 19:44:57.000000000 +0800
440 +++ linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c 2003-10-30 11:14:55.000000000 +0800
442 EXPORT_SYMBOL(iounmap);
443 EXPORT_SYMBOL(enable_irq);
444 EXPORT_SYMBOL(disable_irq);
445 +EXPORT_SYMBOL(find_irq_action);
446 EXPORT_SYMBOL(disable_irq_nosync);
447 EXPORT_SYMBOL(probe_irq_mask);
448 EXPORT_SYMBOL(kernel_thread);
451 EXPORT_SYMBOL(eddnr);
454 EXPORT_SYMBOL_GPL(show_mem);
455 EXPORT_SYMBOL_GPL(show_state);
456 EXPORT_SYMBOL_GPL(show_regs);
457 Index: linux-2.4.20-rh/kernel/panic.c
458 ===================================================================
459 --- linux-2.4.20-rh.orig/kernel/panic.c 2003-10-31 07:25:19.000000000 +0800
460 +++ linux-2.4.20-rh/kernel/panic.c 2003-10-31 07:25:59.000000000 +0800
468 printk(KERN_EMERG "In interrupt handler - not syncing\n");
469 else if (!current->pid)