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 #include #include +#include /* * 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; } _