+++ /dev/null
-Index: linux-2.4.20-rh/drivers/net/netconsole.c
-===================================================================
---- linux-2.4.20-rh.orig/drivers/net/netconsole.c 2003-07-22 16:02:23.000000000 +0800
-+++ linux-2.4.20-rh/drivers/net/netconsole.c 2003-11-11 07:42:33.000000000 +0800
-@@ -12,6 +12,8 @@
- *
- * 2001-09-17 started by Ingo Molnar.
- * 2002-03-14 simultaneous syslog packet option by Michael K. Johnson
-+ * 2003-10-30 Add sysrq command processing by Wangdi <wangdi@clusterfs.com>
-+ *
- */
-
- /****************************************************************
-@@ -51,6 +53,7 @@
- #include <linux/tty_driver.h>
- #include <linux/etherdevice.h>
- #include <linux/elf.h>
-+#include "netconsole.h"
-
- static struct net_device *netconsole_dev;
- static u16 source_port, netdump_target_port, netlog_target_port, syslog_target_port;
-@@ -62,12 +65,11 @@
- static unsigned int mhz = 500, idle_timeout;
- static unsigned long long mhz_cycles, jiffy_cycles;
-
--#include "netconsole.h"
-
- #define MAX_UDP_CHUNK 1460
- #define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
-
--#define DEBUG 0
-+#define DEBUG 0
- #if DEBUG
- # define Dprintk(x...) printk(KERN_INFO x)
- #else
-@@ -187,6 +189,22 @@
- }
- }
- }
-+void (*irqfunc)(int, void *, struct pt_regs *);
-+
-+static void netdump_poll(struct net_device *dev)
-+{
-+ int budget = 1;
-+
-+ disable_irq(dev->irq);
-+
-+ irqfunc(dev->irq, dev, 0);
-+
-+ if(dev->poll && test_bit(__LINK_STATE_RX_SCHED, &dev->state))
-+ dev->poll(dev, &budget);
-+
-+ enable_irq(dev->irq);
-+
-+}
-
- static struct sk_buff * alloc_netconsole_skb(struct net_device *dev, int len, int reserve)
- {
-@@ -209,7 +227,7 @@
- once = 0;
- }
- Dprintk("alloc skb: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- goto repeat;
- }
- }
-@@ -231,7 +249,7 @@
- spin_unlock(&dev->xmit_lock);
-
- Dprintk("xmit skb: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- zap_completion_queue();
- goto repeat_poll;
- }
-@@ -426,18 +444,79 @@
- static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
- static unsigned int log_offset;
-
-+static int thread_stopped = 0;
-+/*Interrupt function for netdump */
-+static int sysrq_mode = 0;
-+static int stop_sysrq_thread = 0;
-+#define Set_Sysrq_mode() (sysrq_mode = 1)
-+#define Clear_Sysrq_mode() (sysrq_mode = 0)
-+static char send_cache[MAX_PRINT_CHUNK];
-+static unsigned int send_cache_pos = 0;
-+wait_queue_head_t sysrq_thread_queue;
-+wait_queue_head_t sysrq_thread_waiter_queue;
-+
-+#define SEND_MSG_BUFFER(buf, len) \
-+do \
-+{ \
-+ reply_t reply; \
-+ unsigned int flags; \
-+ __save_flags(flags); \
-+ __cli(); \
-+ reply.code = REPLY_LOG; \
-+ reply.nr = 0; \
-+ reply.info = 0; \
-+ spin_lock(&sequence_lock); \
-+ send_netlog_skb(dev, buf, len, &reply); \
-+ spin_unlock(&sequence_lock); \
-+ __restore_flags(flags); \
-+}while(0);
-+
-+void netconsole_do_sysrq(req_t *req)
-+{
-+ struct pt_regs regs;
-+ struct net_device *dev = netconsole_dev;
-+
-+ if (!dev)
-+ return;
-+ Set_Sysrq_mode();
-+ get_current_regs(®s);
-+ handle_sysrq((int)req->from, ®s, NULL);
-+
-+ if (send_cache_pos != 0){
-+ SEND_MSG_BUFFER(send_cache, send_cache_pos);
-+ memset(send_cache, 0, MAX_PRINT_CHUNK);
-+ send_cache_pos = 0;
-+ }
-+
-+ Clear_Sysrq_mode();
-+}
- static void write_netconsole_msg(struct console *con, const char *msg0, unsigned int msg_len)
- {
- int len, left, i;
- struct net_device *dev;
- const char *msg = msg0;
- reply_t reply;
--
-+
- dev = netconsole_dev;
- if (!dev || netdump_mode)
- return;
--
-- if (dev->poll_controller && netif_running(dev)) {
-+ if (sysrq_mode){
-+ unsigned long total_len = send_cache_pos + msg_len;
-+ unsigned long left_len = msg_len;
-+ while (total_len >= MAX_PRINT_CHUNK){
-+ unsigned long send_len = MAX_PRINT_CHUNK - send_cache_pos;
-+ memcpy(send_cache + send_cache_pos, msg, send_len);
-+ SEND_MSG_BUFFER(send_cache, MAX_PRINT_CHUNK);
-+ send_cache_pos = 0;
-+ total_len -= MAX_PRINT_CHUNK;
-+ left_len -= send_len;
-+ }
-+ if (left_len > 0){
-+ memcpy(send_cache + send_cache_pos, msg + (msg_len -left_len), left_len);
-+ send_cache_pos += left_len;
-+ }
-+ return;
-+ }else if (netif_running(dev)) {
- unsigned long flags;
-
- __save_flags(flags);
-@@ -567,8 +646,6 @@
- req_t *req;
- struct net_device *dev;
-
-- if (!netdump_mode)
-- return NET_RX_SUCCESS;
- #if DEBUG
- {
- static int packet_count;
-@@ -722,8 +799,16 @@
- Dprintk("... netdump from: %08x.\n", req->from);
- Dprintk("... netdump to: %08x.\n", req->to);
-
-- add_new_req(req);
-+ if (netdump_mode)
-+ add_new_req(req);
-+ else if (req->command == COMM_SYSRQ){
-+ add_new_req(req);
-+ wake_up(&sysrq_thread_queue);
-+ return NET_RX_DROP;
-+ }
- out:
-+ if (!netdump_mode)
-+ return NET_RX_SUCCESS;
- return NET_RX_DROP;
- }
-
-@@ -763,6 +848,7 @@
- kunmap_atomic(kaddr, KM_NETDUMP);
- }
-
-+
- /*
- * This function waits for the client to acknowledge the receipt
- * of the netdump startup reply, with the possibility of packets
-@@ -792,7 +878,7 @@
- // wait 1 sec.
- udelay(100);
- Dprintk("handshake: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- zap_completion_queue();
- req = get_new_req();
- if (req)
-@@ -904,7 +990,7 @@
- while (netdump_mode) {
- __cli();
- Dprintk("main netdump loop: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- zap_completion_queue();
- #if !CLI
- __sti();
-@@ -1009,6 +1095,32 @@
- printk("NETDUMP END!\n");
- __restore_flags(flags);
- }
-+static int netconsole_sysrq_schedule(void *arg)
-+{
-+ struct task_struct *tsk = current;
-+
-+ sprintf(tsk->comm, "sysrq_schedule");
-+ sigfillset(&tsk->blocked);
-+
-+ /* main loop */
-+ thread_stopped = 0;
-+ for (;;) {
-+ wait_event_interruptible(sysrq_thread_queue,
-+ !list_empty(&request_list) || stop_sysrq_thread);
-+ while (!list_empty(&request_list)) {
-+ req_t *req = get_new_req();
-+ if (req->command == COMM_SYSRQ)
-+ netconsole_do_sysrq(req);
-+ }
-+ if (stop_sysrq_thread)
-+ break;
-+ wake_up(&sysrq_thread_waiter_queue);
-+ }
-+ thread_stopped = 1;
-+ wake_up(&sysrq_thread_waiter_queue);
-+ return 0;
-+}
-+
-
- static char *dev;
- static int netdump_target_eth_byte0 = 255;
-@@ -1087,11 +1199,12 @@
-
- static struct console netconsole =
- { flags: CON_ENABLED, write: write_netconsole_msg };
--
- static int init_netconsole(void)
- {
- struct net_device *ndev = NULL;
- struct in_device *in_dev;
-+ struct irqaction *action;
-+ int rc = 0;
-
- printk(KERN_INFO "netlog: using network device <%s>\n", dev);
- // this will be valid once the device goes up.
-@@ -1101,10 +1214,6 @@
- printk(KERN_ERR "netlog: network device %s does not exist, aborting.\n", dev);
- return -1;
- }
-- if (!ndev->poll_controller) {
-- printk(KERN_ERR "netlog: %s's network driver does not implement netlogging yet, aborting.\n", dev);
-- return -1;
-- }
- in_dev = in_dev_get(ndev);
- if (!in_dev) {
- printk(KERN_ERR "netlog: network device %s is not an IP protocol device, aborting.\n", dev);
-@@ -1137,8 +1246,6 @@
- if (!netdump_target_ip && !netlog_target_ip && !syslog_target_ip) {
- printk(KERN_ERR "netlog: target_ip parameter not specified, aborting.\n");
- return -1;
-- }
-- if (netdump_target_ip) {
- #define IP(x) ((unsigned char *)&netdump_target_ip)[x]
- printk(KERN_INFO "netlog: using netdump target IP %u.%u.%u.%u\n",
- IP(3), IP(2), IP(1), IP(0));
-@@ -1214,12 +1321,27 @@
-
- mhz_cycles = (unsigned long long)mhz * 1000000ULL;
- jiffy_cycles = (unsigned long long)mhz * (1000000/HZ);
--
-- INIT_LIST_HEAD(&request_list);
--
-+
- ndev->rx_hook = netconsole_rx_hook;
- netdump_func = netconsole_netdump;
- netconsole_dev = ndev;
-+ /* find irq function of the ndev*/
-+ action=find_irq_action(ndev->irq, ndev);
-+ if (!action) {
-+ printk(KERN_ERR "couldn't find irq handler for <%s>", dev);
-+ return -1;
-+ }
-+ irqfunc = action->handler;
-+
-+ stop_sysrq_thread = 0;
-+ INIT_LIST_HEAD(&request_list);
-+ init_waitqueue_head(&sysrq_thread_queue);
-+ init_waitqueue_head(&sysrq_thread_waiter_queue);
-+ if ((rc = kernel_thread(netconsole_sysrq_schedule, NULL, 0)) < 0 ){
-+ printk(KERN_ERR "Can not start netconsole sysrq thread: rc %d\n", rc);
-+ return -1;
-+ }
-+
- #define STARTUP_MSG "[...network console startup...]\n"
- write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
-
-@@ -1230,7 +1352,11 @@
-
- static void cleanup_netconsole(void)
- {
-- printk(KERN_INFO "netlog: network logging shut down.\n");
-+ stop_sysrq_thread = 1;
-+
-+ wake_up(&sysrq_thread_queue);
-+ wait_event(sysrq_thread_waiter_queue, thread_stopped);
-+ printk(KERN_INFO"netlog: network logging shut down.\n");
- unregister_console(&netconsole);
-
- #define SHUTDOWN_MSG "[...network console shutdown...]\n"
-Index: linux-2.4.20-rh/drivers/net/netconsole.h
-===================================================================
---- linux-2.4.20-rh.orig/drivers/net/netconsole.h 2003-07-22 16:02:23.000000000 +0800
-+++ linux-2.4.20-rh/drivers/net/netconsole.h 2003-10-30 01:48:45.000000000 +0800
-@@ -29,7 +29,7 @@
- *
- ****************************************************************/
-
--#define NETCONSOLE_VERSION 0x04
-+#define NETCONSOLE_VERSION 0x03
-
- enum netdump_commands {
- COMM_NONE = 0,
-@@ -42,6 +42,8 @@
- COMM_START_NETDUMP_ACK = 7,
- COMM_GET_REGS = 8,
- COMM_SHOW_STATE = 9,
-+ COMM_START_WRITE_NETDUMP_ACK = 10,
-+ COMM_SYSRQ = 11,
- };
-
- #define NETDUMP_REQ_SIZE (8+4*4)
-@@ -69,6 +71,7 @@
- REPLY_REGS = 10,
- REPLY_MAGIC = 11,
- REPLY_SHOW_STATE = 12,
-+ REPLY_SYSRQ = 13,
- };
-
- typedef struct netdump_reply_s {
-@@ -78,4 +81,22 @@
- } reply_t;
-
- #define HEADER_LEN (1 + sizeof(reply_t))
--
-+/* for netconsole */
-+static inline void get_current_regs(struct pt_regs *regs)
-+{
-+ __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
-+ __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
-+ __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
-+ __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
-+ __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
-+ __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
-+ __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
-+ __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
-+ __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
-+ __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
-+ __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
-+ __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
-+ __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
-+ regs->eip = (unsigned long)current_text_addr();
-+}
-+
-Index: linux-2.4.20-rh/arch/i386/kernel/irq.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/irq.c 2003-10-30 08:29:38.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/irq.c 2003-10-30 08:30:13.000000000 +0800
-@@ -1043,7 +1043,20 @@
- register_irq_proc(irq);
- return 0;
- }
-+struct irqaction *find_irq_action(unsigned int irq, void *dev_id)
-+{
-+ struct irqaction *a, *r=0;
-
-+ spin_lock_irq(&irq_desc[irq].lock);
-+ for(a=irq_desc[irq].action; a; a=a->next) {
-+ if(a->dev_id == dev_id) {
-+ r=a;
-+ break;
-+ }
-+ }
-+ spin_unlock_irq(&irq_desc[irq].lock);
-+ return r;
-+}
-
- static struct proc_dir_entry * root_irq_dir;
- static struct proc_dir_entry * irq_dir [NR_IRQS];
-Index: linux-2.4.20-rh/net/core/dev.c
-===================================================================
---- linux-2.4.20-rh.orig/net/core/dev.c 2003-10-29 01:40:26.000000000 +0800
-+++ linux-2.4.20-rh/net/core/dev.c 2003-10-30 01:48:45.000000000 +0800
-@@ -1475,6 +1475,16 @@
-
- skb_bond(skb);
-
-+ if (unlikely(skb->dev->rx_hook != NULL)) {
-+ int ret;
-+
-+ ret = skb->dev->rx_hook(skb);
-+ if (ret == NET_RX_DROP){
-+ kfree_skb(skb);
-+ return ret;
-+ }
-+ }
-+
- netdev_rx_stat[smp_processor_id()].total++;
-
- #ifdef CONFIG_NET_FASTROUTE
-Index: linux-2.4.20-rh/include/asm-i386/irq.h
-===================================================================
---- linux-2.4.20-rh.orig/include/asm-i386/irq.h 2003-10-28 16:18:18.000000000 +0800
-+++ linux-2.4.20-rh/include/asm-i386/irq.h 2003-10-30 10:24:49.000000000 +0800
-@@ -38,7 +38,7 @@
- extern void disable_irq_nosync(unsigned int);
- extern void enable_irq(unsigned int);
- extern void release_x86_irqs(struct task_struct *);
--
-+extern struct irqaction *find_irq_action(unsigned int irq, void *dev_id);
- #ifdef CONFIG_X86_LOCAL_APIC
- #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
- #endif
-Index: linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/i386_ksyms.c 2003-10-28 19:44:57.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c 2003-10-30 11:14:55.000000000 +0800
-@@ -68,6 +68,7 @@
- EXPORT_SYMBOL(iounmap);
- EXPORT_SYMBOL(enable_irq);
- EXPORT_SYMBOL(disable_irq);
-+EXPORT_SYMBOL(find_irq_action);
- EXPORT_SYMBOL(disable_irq_nosync);
- EXPORT_SYMBOL(probe_irq_mask);
- EXPORT_SYMBOL(kernel_thread);
-@@ -199,7 +200,6 @@
- EXPORT_SYMBOL(edd);
- EXPORT_SYMBOL(eddnr);
- #endif
--
- EXPORT_SYMBOL_GPL(show_mem);
- EXPORT_SYMBOL_GPL(show_state);
- EXPORT_SYMBOL_GPL(show_regs);
-Index: linux-2.4.20-rh/kernel/panic.c
-===================================================================
---- linux-2.4.20-rh.orig/kernel/panic.c 2003-10-31 07:25:19.000000000 +0800
-+++ linux-2.4.20-rh/kernel/panic.c 2003-10-31 07:25:59.000000000 +0800
-@@ -219,8 +219,6 @@
- }
- #endif
-
-- if (netdump_func)
-- BUG();
- if (in_interrupt())
- printk(KERN_EMERG "In interrupt handler - not syncing\n");
- else if (!current->pid)