Dong a breakpoint within netif_rx() doesn't work: we cannot reenter the IRQ
and NIC driver from that context: locks are held and synchronize_irq() hangs.

So put the breakpoint right at the end of do_IRQ() and set a "we need to do a
breakpoint" flag.

We could use a softirq, but this is a bit lower-level, more robust.


 arch/i386/kernel/irq.c  |   12 ++++++++++++
 drivers/net/kgdb_eth.c  |    8 ++++----
 include/asm-i386/kgdb.h |    1 +
 3 files changed, 17 insertions(+), 4 deletions(-)

diff -puN drivers/net/kgdb_eth.c~kgdb-eth-smp-fix drivers/net/kgdb_eth.c
--- 25/drivers/net/kgdb_eth.c~kgdb-eth-smp-fix	2003-09-06 19:47:06.000000000 -0700
+++ 25-akpm/drivers/net/kgdb_eth.c	2003-09-06 19:47:06.000000000 -0700
@@ -54,6 +54,7 @@ int		kgdb_eth = -1; /* Default tty mode 
 unsigned char	kgdb_remotemac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
 unsigned char	kgdb_localmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
 volatile int	kgdb_eth_is_initializing = 0;
+int		kgdb_eth_need_breakpoint[NR_CPUS];
 
 struct net_device *kgdb_netdevice = NULL;
 
@@ -354,9 +355,8 @@ kgdb_net_interrupt(struct sk_buff *skb)
 
 	for (i = 0; i < len; i++) {
 		chr = *data++;
-		if (chr == 3)
-		{
-			BREAKPOINT;
+		if (chr == 3) {
+			kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
 			continue;
 		}
 		if (atomic_read(&kgdb_buf_in_cnt) >= GDB_BUF_SIZE) {
@@ -421,7 +421,7 @@ kgdb_eth_hook(void)
 	 * session.
 	 */
 	kgdb_eth_is_initializing = 1;
-	BREAKPOINT;
+	kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
 	return 0;
 }
 
diff -puN include/asm-i386/kgdb.h~kgdb-eth-smp-fix include/asm-i386/kgdb.h
--- 25/include/asm-i386/kgdb.h~kgdb-eth-smp-fix	2003-09-06 19:47:06.000000000 -0700
+++ 25-akpm/include/asm-i386/kgdb.h	2003-09-06 19:47:06.000000000 -0700
@@ -27,6 +27,7 @@ extern unsigned short kgdb_listenport;
 extern unsigned short kgdb_sendport;
 extern unsigned char kgdb_remotemac[6];
 extern unsigned char kgdb_localmac[6];
+extern int kgdb_eth_need_breakpoint[];
 
 extern int kgdb_tty_hook(void);
 extern int kgdb_eth_hook(void);
diff -puN arch/i386/kernel/irq.c~kgdb-eth-smp-fix arch/i386/kernel/irq.c
--- 25/arch/i386/kernel/irq.c~kgdb-eth-smp-fix	2003-09-06 19:47:06.000000000 -0700
+++ 25-akpm/arch/i386/kernel/irq.c	2003-09-06 19:47:06.000000000 -0700
@@ -44,6 +44,7 @@
 #include <asm/delay.h>
 #include <asm/desc.h>
 #include <asm/irq.h>
+#include <asm/kgdb.h>
 
 /*
  * Linux has a controller-independent x86 interrupt architecture.
@@ -499,6 +500,17 @@ out:
 
 	irq_exit();
 
+#ifdef CONFIG_KGDB
+	/*
+	 * We need to do this after clearing out of all the interrupt
+	 * machinery because kgdb will reenter the NIC driver and the IRQ
+	 * system.  synchronize_irq() (at least) will deadlock.
+	 */
+	if (kgdb_eth_need_breakpoint[smp_processor_id()]) {
+		kgdb_eth_need_breakpoint[smp_processor_id()] = 0;
+		BREAKPOINT;
+	}
+#endif
 	return 1;
 }
 

_