
From: Matt Mackall <mpm@selenic.com>

Ok, here's kgdboe via netpoll, on top of 2.6.0, the above rolled kgdb
bits and Jeff's netdrvr-1.

DESC
kgdboe: fix configuration of MAC address
EDESC
From: Matt Mackall <mpm@selenic.com>

This seems to have gotten dropped.  Without it, kgdboe can get into a
half-configured state.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/Documentation/i386/kgdb/kgdbeth.txt |   92 +++++++++++++++
 25-akpm/arch/i386/kernel/irq.c              |    2 
 25-akpm/arch/i386/kernel/kgdb_stub.c        |  166 ++++++++++++++++++++++++----
 25-akpm/arch/i386/lib/kgdb_serial.c         |   36 ++++--
 25-akpm/drivers/net/Makefile                |    1 
 25-akpm/drivers/net/kgdb_eth.c              |  132 ++++++++++++++++++++++
 25-akpm/include/asm-i386/kgdb.h             |   10 +
 25-akpm/net/Kconfig                         |   13 +-
 25-akpm/net/core/dev.c                      |    6 -
 9 files changed, 417 insertions(+), 41 deletions(-)

diff -puN arch/i386/kernel/irq.c~kgdboe-netpoll arch/i386/kernel/irq.c
--- 25/arch/i386/kernel/irq.c~kgdboe-netpoll	2004-11-18 23:47:17.580998000 -0800
+++ 25-akpm/arch/i386/kernel/irq.c	2004-11-18 23:47:17.594995872 -0800
@@ -103,6 +103,8 @@ fastcall unsigned int do_IRQ(struct pt_r
 
 	irq_exit();
 
+	kgdb_process_breakpoint();
+
 	return 1;
 }
 
diff -puN arch/i386/kernel/kgdb_stub.c~kgdboe-netpoll arch/i386/kernel/kgdb_stub.c
--- 25/arch/i386/kernel/kgdb_stub.c~kgdboe-netpoll	2004-11-18 23:47:17.582997696 -0800
+++ 25-akpm/arch/i386/kernel/kgdb_stub.c	2004-11-18 23:47:17.596995568 -0800
@@ -30,6 +30,8 @@
  *
  *  Written by:	     Glenn Engel $
  *  Updated by:	     David Grothe <dave@gcom.com>
+ *  Updated by:	     Robert Walsh <rjwalsh@durables.org>
+ *  Updated by:	     wangdi <wangdi@clusterfs.com>
  *  ModuleState:     Experimental $
  *
  *  NOTES:	     See Below $
@@ -49,6 +51,10 @@
  *	support for ia-32(x86) hardware debugging.
  *	Amit S. Kale ( akale@veritas.com )
  *
+ *  Modified to support debugging over ethernet by Robert Walsh
+ *  <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
+ *  code by San Mehat.
+ *
  *
  *  To enable debugger support, two things need to happen.  One, a
  *  call to set_debug_traps() is necessary in order to allow any breakpoints
@@ -112,6 +118,8 @@
 #include <asm/processor.h>
 #include <linux/irq.h>
 #include <asm/desc.h>
+#include <linux/inet.h>
+#include <linux/netpoll.h>
 
 /************************************************************************
  *
@@ -122,8 +130,12 @@ typedef void (*Function) (void);	/* poin
 /* Thread reference */
 typedef unsigned char threadref[8];
 
-extern void putDebugChar(int);	/* write a single character	 */
-extern int getDebugChar(void);	/* read and return a single char */
+extern int tty_putDebugChar(int);     /* write a single character      */
+extern int tty_getDebugChar(void);    /* read and return a single char */
+extern void tty_flushDebugChar(void); /* flush pending characters      */
+extern int eth_putDebugChar(int);     /* write a single character      */
+extern int eth_getDebugChar(void);    /* read and return a single char */
+extern void eth_flushDebugChar(void); /* flush pending characters      */
 
 /************************************************************************/
 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
@@ -264,6 +276,41 @@ malloc(int size)
 }
 
 /*
+ * I/O dispatch functions...
+ * Based upon kgdboe, either call the ethernet
+ * handler or the serial one..
+ */
+void
+putDebugChar(int c)
+{
+	if (!kgdboe) {
+		tty_putDebugChar(c);
+	} else {
+		eth_putDebugChar(c);
+	}
+}
+
+int
+getDebugChar(void)
+{
+	if (!kgdboe) {
+		return tty_getDebugChar();
+	} else {
+		return eth_getDebugChar();
+	}
+}
+
+void
+flushDebugChar(void)
+{
+	if (!kgdboe) {
+		tty_flushDebugChar();
+	} else {
+		eth_flushDebugChar();
+	}
+}
+
+/*
  * Gdb calls functions by pushing agruments, including a return address
  * on the stack and the adjusting EIP to point to the function.	 The
  * whole assumption in GDB is that we are on a different stack than the
@@ -429,6 +476,7 @@ getpacket(char *buffer)
 
 	if (remote_debug)
 		printk("R:%s\n", buffer);
+	flushDebugChar();
 }
 
 /* send the packet in buffer.  */
@@ -441,25 +489,67 @@ putpacket(char *buffer)
 	char ch;
 
 	/*  $<packet info>#<checksum>. */
-	do {
-		if (remote_debug)
-			printk("T:%s\n", buffer);
-		putDebugChar('$');
-		checksum = 0;
-		count = 0;
 
-		while ((ch = buffer[count])) {
-			putDebugChar(ch);
-			checksum += ch;
-			count += 1;
-		}
+	if (!kgdboe) {
+		do {
+			if (remote_debug)
+				printk("T:%s\n", buffer);
+			putDebugChar('$');
+			checksum = 0;
+			count = 0;
+
+			while ((ch = buffer[count])) {
+				putDebugChar(ch);
+				checksum += ch;
+				count += 1;
+			}
+
+			putDebugChar('#');
+			putDebugChar(hexchars[checksum >> 4]);
+			putDebugChar(hexchars[checksum % 16]);
+			flushDebugChar();
+
+		} while ((getDebugChar() & 0x7f) != '+');
+	} else {
+		/*
+		 * For udp, we can not transfer too much bytes once.
+		 * We only transfer MAX_SEND_COUNT size bytes each time
+		 */
 
-		putDebugChar('#');
-		putDebugChar(hexchars[checksum >> 4]);
-		putDebugChar(hexchars[checksum % 16]);
+#define MAX_SEND_COUNT 30
 
-	} while ((getDebugChar() & 0x7f) != '+');
+		int send_count = 0, i = 0;
+		char send_buf[MAX_SEND_COUNT];
 
+		do {
+			if (remote_debug)
+				printk("T:%s\n", buffer);
+			putDebugChar('$');
+			checksum = 0;
+			count = 0;
+			send_count = 0;
+			while ((ch = buffer[count])) {
+				if (send_count >= MAX_SEND_COUNT) {
+					for(i = 0; i < MAX_SEND_COUNT; i++) {
+						putDebugChar(send_buf[i]);
+					}
+					flushDebugChar();
+					send_count = 0;
+				} else {
+					send_buf[send_count] = ch;
+					checksum += ch;
+					count ++;
+					send_count++;
+				}
+			}
+			for(i = 0; i < send_count; i++)
+				putDebugChar(send_buf[i]);
+			putDebugChar('#');
+			putDebugChar(hexchars[checksum >> 4]);
+			putDebugChar(hexchars[checksum % 16]);
+			flushDebugChar();
+		} while ((getDebugChar() & 0x7f) != '+');
+	}
 }
 
 static char remcomInBuffer[BUFMAX];
@@ -1045,9 +1135,9 @@ in_kgdb(struct pt_regs *regs)
 	 */
 	in_kgdb_entry_log[cpu]++;
 	in_kgdb_here_log[cpu] = regs;
-	if (cpu == spinlock_cpu || waiting_cpus[cpu].task) {
+	if (cpu == spinlock_cpu || waiting_cpus[cpu].task)
 		goto exit_in_kgdb;
-	}
+
 	/*
 	 * For protection of the initilization of the spin locks by kgdb
 	 * it locks the kgdb spinlock before it gets the wait locks set
@@ -1056,16 +1146,18 @@ in_kgdb(struct pt_regs *regs)
 	 * sequence where the wait lock is removed prior to the kgdb lock
 	 * so if kgdb gets unlocked, we just exit.
 	 */
+
 	while (spin_is_locked(&kgdb_spinlock) &&
 	       !spin_is_locked(waitlocks + cpu)) ;
-	if (!spin_is_locked(&kgdb_spinlock)) {
+	if (!spin_is_locked(&kgdb_spinlock))
 		goto exit_in_kgdb;
-	}
+
 	waiting_cpus[cpu].task = current;
 	waiting_cpus[cpu].pid = (current->pid) ? : (PID_MAX + cpu);
 	waiting_cpus[cpu].regs = regs;
 
 	spin_unlock_wait(waitlocks + cpu);
+
 	/*
 	 * log departure of this cpu
 	 */
@@ -1177,6 +1269,12 @@ kgdb_handle_exception(int exceptionVecto
 		print_regs(&regs);
 		return (0);
 	}
+	/*
+	 * If we're using eth mode, set the 'mode' in the netdevice.
+	 */
+
+	if (kgdboe)
+		netpoll_set_trap(1);
 
 	kgdb_local_irq_save(flags);
 
@@ -1231,10 +1329,12 @@ kgdb_handle_exception(int exceptionVecto
 		if (num_online_cpus() > 1) {
 			int me_in_kgdb = in_kgdb_entry_log[smp_processor_id()];
 			smp_send_nmi_allbutself();
+
 			while (i < num_online_cpus() && time != end_time) {
 				int j;
 				for (j = 0; j < MAX_NO_CPUS; j++) {
 					if (waiting_cpus[j].task &&
+					    waiting_cpus[j].task != NOCPU &&
 					    !cpu_logged_in[j]) {
 						i++;
 						cpu_logged_in[j] = 1;
@@ -1623,6 +1723,10 @@ kgdb_handle_exception(int exceptionVecto
 					}
 				}
 			}
+
+			if (kgdboe)
+				netpoll_set_trap(0);
+
 			correct_hw_break();
 			asm volatile ("movl %0, %%db6\n"::"r" (0));
 			goto exit_kgdb;
@@ -2328,3 +2432,23 @@ kgdb_tstamp(int line, char *source, int 
 typedef int gdb_debug_hook(int exceptionVector,
 			   int signo, int err_code, struct pt_regs *linux_regs);
 gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception;	/* histerical reasons... */
+
+static int kgdb_need_breakpoint[NR_CPUS];
+
+void kgdb_schedule_breakpoint(void)
+{
+	kgdb_need_breakpoint[smp_processor_id()] = 1;
+}
+
+void kgdb_process_breakpoint(void)
+{
+	/*
+	 * Handle a breakpoint queued from inside network driver code
+         * to avoid reentrancy issues
+	 */
+	if (kgdb_need_breakpoint[smp_processor_id()]) {
+		kgdb_need_breakpoint[smp_processor_id()] = 0;
+		BREAKPOINT;
+	}
+}
+
diff -puN arch/i386/lib/kgdb_serial.c~kgdboe-netpoll arch/i386/lib/kgdb_serial.c
--- 25/arch/i386/lib/kgdb_serial.c~kgdboe-netpoll	2004-11-18 23:47:17.584997392 -0800
+++ 25-akpm/arch/i386/lib/kgdb_serial.c	2004-11-18 23:47:17.598995264 -0800
@@ -4,6 +4,9 @@
  * Written (hacked together) by David Grothe (dave@gcom.com)
  * Modified to allow invokation early in boot see also
  * kgdb.h for instructions by George Anzinger(george@mvista.com)
+ * Modified to handle debugging over ethernet by Robert Walsh
+ * <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
+ * code by San Mehat.
  *
  */
 
@@ -155,12 +158,12 @@ write_char(struct async_struct *info, in
  * It will receive a limited number of characters of input
  * from the gdb  host machine and save them up in a buffer.
  *
- * When the gdb stub routine getDebugChar() is called it
+ * When the gdb stub routine tty_getDebugChar() is called it
  * draws characters out of the buffer until it is empty and
  * then reads directly from the serial port.
  *
  * We do not attempt to write chars from the interrupt routine
- * since the stubs do all of that via putDebugChar() which
+ * since the stubs do all of that via tty_putDebugChar() which
  * writes one byte after waiting for the interface to become
  * ready.
  *
@@ -226,7 +229,7 @@ extern char *kgdb_version;
 /*
  * Hook an IRQ for KGDB.
  *
- * This routine is called from putDebugChar, below.
+ * This routine is called from tty_putDebugChar, below.
  */
 static int ints_disabled = 1;
 int
@@ -331,7 +334,7 @@ program_uart(struct async_struct *info)
 }
 
 /*
- * getDebugChar
+ * tty_getDebugChar
  *
  * This is a GDB stub routine.	It waits for a character from the
  * serial interface and then returns it.  If there is no serial
@@ -345,11 +348,11 @@ extern spinlock_t kgdb_spinlock;
 /* Caller takes needed protections */
 
 int
-getDebugChar(void)
+tty_getDebugChar(void)
 {
 	volatile int chr, dum, time, end_time;
 
-	dbprintk(("getDebugChar(port %x): ", gdb_async_info->port));
+	dbprintk(("tty_getDebugChar(port %x): ", gdb_async_info->port));
 
 	if (gdb_async_info == NULL) {
 		gdb_hook_interrupt(&local_info, 0);
@@ -375,7 +378,7 @@ getDebugChar(void)
 	dbprintk(("%c\n", chr > ' ' && chr < 0x7F ? chr : ' '));
 	return (chr);
 
-}				/* getDebugChar */
+}				/* tty_getDebugChar */
 
 static int count = 3;
 static spinlock_t one_at_atime = SPIN_LOCK_UNLOCKED;
@@ -383,6 +386,9 @@ static spinlock_t one_at_atime = SPIN_LO
 static int __init
 kgdb_enable_ints(void)
 {
+	if (kgdboe) {
+		return 0;
+	}
 	if (gdb_async_info == NULL) {
 		gdb_hook_interrupt(&local_info, 1);
 	}
@@ -444,7 +450,7 @@ kgdb_enable_ints_now(void)
 }
 
 /*
- * putDebugChar
+ * tty_putDebugChar
  *
  * This is a GDB stub routine.	It waits until the interface is ready
  * to transmit a char and then sends it.  If there is no serial
@@ -452,9 +458,9 @@ kgdb_enable_ints_now(void)
  * pretended to send the char.	Caller takes needed protections.
  */
 void
-putDebugChar(int chr)
+tty_putDebugChar(int chr)
 {
-	dbprintk(("putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n",
+	dbprintk(("tty_putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n",
 		  gdb_async_info->port,
 		  chr,
 		  chr > ' ' && chr < 0x7F ? chr : ' ', ints_disabled ? 0 : 1));
@@ -480,6 +486,14 @@ putDebugChar(int chr)
 		}
 	}
 
-}				/* putDebugChar */
+}				/* tty_putDebugChar */
+
+/*
+ * This does nothing for the serial port, since it doesn't buffer.
+ */
+
+void tty_flushDebugChar(void)
+{
+}
 
 module_init(kgdb_enable_ints);
diff -puN /dev/null Documentation/i386/kgdb/kgdbeth.txt
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/Documentation/i386/kgdb/kgdbeth.txt	2004-11-18 23:47:17.598995264 -0800
@@ -0,0 +1,92 @@
+KGDB over ethernet
+==================
+
+Authors
+-------
+
+Robert Walsh <rjwalsh@durables.org>  (2.6 port)
+wangdi <wangdi@clusterfs.com>        (2.6 port)
+Matt Mackall <mpm@selenic.com>       (netpoll api)
+San Mehat                            (original 2.4 code)
+
+
+Introduction
+------------
+
+KGDB supports debugging over ethernet (kgdboe) via polling of a given
+network interface. Most cards should be supported automatically.
+Debugging facilities are available as soon as the network driver and
+kgdboe have initialized. Unfortunately, this is too late in the boot
+process for debugging some issues, but works quite well for many
+others. This should not interfere with normal network usage and
+doesn't require a dedicated NIC.
+
+Terminology
+-----------
+
+This document uses the following terms:
+
+  TARGET: the machine being debugged.
+  HOST:   the machine running gdb.
+
+
+Usage
+-----
+
+You need to use the following command-line option on the TARGET kernel:
+
+  kgdboe=[tgt-port]@<tgt-ip>/[dev],[host-port]@<host-ip>/[host-macaddr]
+
+    where
+        tgt-port      source for UDP packets (defaults to 6443)
+        tgt-ip        source IP to use (interface address)
+        dev           network interface (eth0)
+        host-port     HOST UDP port (6442) (not really used)
+        host-ip       IP address for HOST machine
+        host-macaddr  ethernet MAC address for HOST (ff:ff:ff:ff:ff:ff)
+
+  examples:
+
+    kgdboe=7000@192.168.0.1/eth1,7001@192.168.0.2/00:05:3C:04:47:5D
+        this machine is 192.168.0.1 on eth1
+        remote machine is 192.168.0.2 with MAC address 00:05:3C:04:47:5D
+        listen for gdb packets on port 7000
+        send unsolicited gdb packets to port 7001
+
+    kgdboe=@192.168.0.1/,@192.168.0.2/
+        this machine is 192.168.0.1 on default interface eth0
+        remote machine is 192.168.0.2, use default broadcast MAC address
+        listen for gdb packets on default port 6443
+        send unsolicited gdb packets to port 6442
+
+Only packets originating from the configured HOST IP address will be
+accepted by the debugger.
+
+On the HOST side, run gdb as normal and use a remote UDP host as the
+target:
+
+   % gdb ./vmlinux
+   GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
+   Copyright 2003 Free Software Foundation, Inc.
+   GDB is free software, covered by the GNU General Public License, and you are
+   welcome to change it and/or distribute copies of it under certain conditions.
+   Type "show copying" to see the conditions.
+   There is absolutely no warranty for GDB.  Type "show warranty" for details.
+   This GDB was configured as "i386-redhat-linux-gnu"...
+   (gdb) target remote udp:HOSTNAME:6443
+
+You can now continue as if you were debugging over a serial line.
+
+Limitations
+-----------
+
+The current release of this code is exclusive of using kgdb on a
+serial interface, so you must boot without the kgdboe option to use
+serial debugging. Trying to debug the network driver while using it
+will prove interesting.
+
+Bug reports
+-----------
+
+Send bug reports to Robert Walsh <rjwalsh@durables.org> and Matt
+Mackall <mpm@selenic.com>.
diff -puN /dev/null drivers/net/kgdb_eth.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/net/kgdb_eth.c	2004-11-18 23:47:17.599995112 -0800
@@ -0,0 +1,132 @@
+/*
+ * Network interface GDB stub
+ *
+ * Written by San Mehat (nettwerk@biodome.org)
+ * Based upon 'gdbserial' by David Grothe (dave@gcom.com)
+ * and Scott Foehner (sfoehner@engr.sgi.com)
+ *
+ * Twiddled for 2.6 by Robert Walsh <rjwalsh@durables.org>
+ * and wangdi <wangdi@clusterfs.com>.
+ *
+ * Refactored for netpoll API by Matt Mackall <mpm@selenic.com>
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/netpoll.h>
+
+#include <asm/system.h>
+#include <asm/kgdb.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+
+#define IN_BUF_SIZE 512 /* power of 2, please */
+#define OUT_BUF_SIZE 256
+
+static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE];
+static int in_head, in_tail, out_count;
+static atomic_t in_count;
+int kgdboe = 0; /* Default to tty mode */
+
+extern void set_debug_traps(void);
+extern void breakpoint(void);
+static void rx_hook(struct netpoll *np, int port, char *msg, int len);
+
+static struct netpoll np = {
+	.name = "kgdboe",
+	.dev_name = "eth0",
+	.rx_hook = rx_hook,
+	.local_port = 6443,
+	.remote_port = 6442,
+	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+};
+static int configured;
+
+int eth_getDebugChar(void)
+{
+	int chr;
+
+	while (atomic_read(&in_count) == 0)
+		netpoll_poll(&np);
+
+	chr = in_buf[in_tail++];
+	in_tail &= (IN_BUF_SIZE - 1);
+	atomic_dec(&in_count);
+	return chr;
+}
+
+void eth_flushDebugChar(void)
+{
+	if(out_count && np.dev) {
+		netpoll_send_udp(&np, out_buf, out_count);
+		out_count = 0;
+	}
+}
+
+void eth_putDebugChar(int chr)
+{
+	out_buf[out_count++] = chr;
+	if(out_count == OUT_BUF_SIZE)
+		eth_flushDebugChar();
+}
+
+static void rx_hook(struct netpoll *np, int port, char *msg, int len)
+{
+	int i;
+
+	np->remote_port = port;
+
+	/* Is this gdb trying to attach? */
+	if (!netpoll_trap() && len == 8 && !strncmp(msg, "$Hc-1#09", 8))
+		kgdb_schedule_breakpoint();
+
+	for (i = 0; i < len; i++) {
+		if (msg[i] == 3)
+			kgdb_schedule_breakpoint();
+
+		if (atomic_read(&in_count) >= IN_BUF_SIZE) {
+			/* buffer overflow, clear it */
+			in_head = in_tail = 0;
+			atomic_set(&in_count, 0);
+			break;
+		}
+		in_buf[in_head++] = msg[i];
+		in_head &= (IN_BUF_SIZE - 1);
+		atomic_inc(&in_count);
+	}
+}
+
+static int option_setup(char *opt)
+{
+	configured = !netpoll_parse_options(&np, opt);
+	return 0;
+}
+__setup("kgdboe=", option_setup);
+
+static int init_kgdboe(void)
+{
+#ifdef CONFIG_SMP
+	if (num_online_cpus() > CONFIG_NO_KGDB_CPUS) {
+		printk("kgdb: too manu cpus. Cannot enable debugger with more than %d cpus\n", CONFIG_NO_KGDB_CPUS);
+		return -1;
+	}
+#endif
+
+	set_debug_traps();
+
+	if(!configured || netpoll_setup(&np))
+		return 1;
+
+	kgdboe = 1;
+	printk(KERN_INFO "kgdb: debugging over ethernet enabled\n");
+
+	return 0;
+}
+
+module_init(init_kgdboe);
diff -puN drivers/net/Makefile~kgdboe-netpoll drivers/net/Makefile
--- 25/drivers/net/Makefile~kgdboe-netpoll	2004-11-18 23:47:17.586997088 -0800
+++ 25-akpm/drivers/net/Makefile	2004-11-18 23:47:17.599995112 -0800
@@ -196,4 +196,5 @@ obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
 obj-$(CONFIG_ETRAX_ETHERNET) += cris/
 
+obj-$(CONFIG_KGDB) += kgdb_eth.o
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
diff -puN include/asm-i386/kgdb.h~kgdboe-netpoll include/asm-i386/kgdb.h
--- 25/include/asm-i386/kgdb.h~kgdboe-netpoll	2004-11-18 23:47:17.587996936 -0800
+++ 25-akpm/include/asm-i386/kgdb.h	2004-11-18 23:47:17.600994960 -0800
@@ -18,6 +18,14 @@ extern void breakpoint(void);
 #ifndef BREAKPOINT
 #define BREAKPOINT   asm("   int $3")
 #endif
+
+extern void kgdb_schedule_breakpoint(void);
+extern void kgdb_process_breakpoint(void);
+
+extern int kgdb_tty_hook(void);
+extern int kgdb_eth_hook(void);
+extern int kgdboe;
+
 /*
  * GDB debug stub (or any debug stub) can point the 'linux_debug_hook'
  * pointer to its routine and it will be entered as the first thing
@@ -55,5 +63,7 @@ void kgdb_tstamp(int line, char *source,
 #define kgdb_handle_exception
 #define breakpoint
 #define INIT_KGDB_INTS
+#define kgdb_process_breakpoint() do {} while(0)
+
 #endif
 #endif				/* __KGDB */
diff -puN net/core/dev.c~kgdboe-netpoll net/core/dev.c
--- 25/net/core/dev.c~kgdboe-netpoll	2004-11-18 23:47:17.588996784 -0800
+++ 25-akpm/net/core/dev.c	2004-11-18 23:47:17.602994656 -0800
@@ -1408,7 +1408,6 @@ static void sample_queue(unsigned long d
 }
 #endif
 
-
 /**
  *	netif_rx	-	post buffer to the network code
  *	@skb: buffer to post
@@ -1774,7 +1773,6 @@ static void net_rx_action(struct softirq
 	unsigned long start_time = jiffies;
 	int budget = netdev_max_backlog;
 
-	
 	local_irq_disable();
 
 	while (!list_empty(&queue->poll_list)) {
@@ -1800,6 +1798,10 @@ static void net_rx_action(struct softirq
 			dev_put(dev);
 			local_irq_disable();
 		}
+
+#ifdef CONFIG_KGDBOE
+		kgdb_process_breakpoint();
+#endif
 	}
 out:
 	local_irq_enable();
diff -puN net/Kconfig~kgdboe-netpoll net/Kconfig
--- 25/net/Kconfig~kgdboe-netpoll	2004-11-18 23:47:17.590996480 -0800
+++ 25-akpm/net/Kconfig	2004-11-18 23:47:17.603994504 -0800
@@ -631,18 +631,17 @@ endmenu
 
 endmenu
 
+config KGDBOE
+	def_bool X86 && KGDB
+
 config NETPOLL
-	def_bool NETCONSOLE
+	def_bool NETCONSOLE || KGDBOE
 
 config NETPOLL_RX
-	bool "Netpoll support for trapping incoming packets"
-	default n
-	depends on NETPOLL
+	def_bool KGDBOE
 
 config NETPOLL_TRAP
-	bool "Netpoll traffic trapping"
-	default n
-	depends on NETPOLL
+	def_bool KGDBOE
 
 config NET_POLL_CONTROLLER
 	def_bool NETPOLL
_
