From: Robert Walsh wangdi sent me the attached patch to the tg3 driver to get it working with kgdb. As you can see, it's a significantly more complicated chunk of code than all the other drivers, and actually makes references into the kgdb code itself. I'm not familiar with tg3's, but I wonder if it's anything to do with the fact that tg3 is a NAPI driver? I wonder if this patch could be significantly simplified by simply having the poll_controller code call the tg3_poll code? drivers/net/tg3.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 117 insertions(+), 2 deletions(-) diff -puN drivers/net/tg3.c~tg3-poll_controller drivers/net/tg3.c --- 25/drivers/net/tg3.c~tg3-poll_controller 2003-09-07 20:45:33.000000000 -0700 +++ 25-akpm/drivers/net/tg3.c 2003-09-07 21:06:10.000000000 -0700 @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef CONFIG_SPARC64 #include @@ -1454,6 +1455,17 @@ static int tg3_setup_copper_phy(struct t return 0; } +static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs); +#ifdef CONFIG_KGDB +static void tg3_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + tg3_interrupt(dev->irq, (void *)dev, 0); + enable_irq(dev->irq); +} +#endif + + struct tg3_fiber_aneginfo { int state; #define ANEG_STATE_UNKNOWN 0 @@ -2183,6 +2195,100 @@ static int tg3_vlan_rx(struct tg3 *tp, s } #endif +#ifdef CONFIG_KGDB +/* Get skb from receive buffer */ +static void upcall_kgdb_hook(struct net_device *dev, int* drop) +{ + struct tg3 *tp = dev->priv; + u32 rx_rcb_ptr = tp->rx_rcb_ptr; + u16 hw_idx, sw_idx; + + hw_idx = tp->hw_status->idx[0].rx_producer; + sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); + while (sw_idx != hw_idx) { + struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx]; + unsigned int len; + struct sk_buff *skb; + dma_addr_t dma_addr; + u32 opaque_key, desc_idx ; + + desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; + opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; + if (opaque_key == RXD_OPAQUE_RING_STD) { + dma_addr = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], + mapping); + skb = tp->rx_std_buffers[desc_idx].skb; + } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { + dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], + mapping); + skb = tp->rx_jumbo_buffers[desc_idx].skb; + } + else { + goto next_pkt; + } + + + if ((desc->err_vlan & RXD_ERR_MASK) != 0 && + (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) { + goto next_pkt; + } + + len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ + + if (len > RX_COPY_THRESHOLD) { + int skb_size; + if (opaque_key == RXD_OPAQUE_RING_STD) + skb_size = RX_PKT_BUF_SZ; + else if (opaque_key == RXD_OPAQUE_RING_JUMBO) + skb_size = RX_JUMBO_PKT_BUF_SZ; + else + goto next_pkt; + skb = dev_alloc_skb(skb_size); + if (skb == NULL) + goto next_pkt; + skb->dev = tp->dev; + skb_reserve(skb, tp->rx_offset); + skb_put(skb, len); + } else { + struct sk_buff *copy_skb; + copy_skb = dev_alloc_skb(len + 2); + if (copy_skb == NULL) + goto next_pkt; + + copy_skb->dev = tp->dev; + skb_reserve(copy_skb, 2); + skb_put(copy_skb, len); + memcpy(copy_skb->data, skb->data, len); + + /* We'll reuse the original ring buffer. */ + skb = copy_skb; + } + if ((tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) && + (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && + (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK) + >> RXD_TCPCSUM_SHIFT) == 0xffff)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + skb->protocol = eth_type_trans(skb, tp->dev); +/*into gdb driver*/ + if (!kgdb_net_interrupt(skb)) { + /* No.. if we're 'trapped' then junk it */ + if (kgdb_eth_is_trapped()) + *drop=1; + } else { + /* kgdb_eth ate the packet... drop it silently */ + *drop=1; + } + kfree_skb(skb); +next_pkt: + rx_rcb_ptr++; + sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); + } +} +#endif + /* The RX ring scheme is composed of multiple rings which post fresh * buffers to the chip, and one special ring the chip uses to report * status back to the host. @@ -2453,9 +2559,15 @@ static irqreturn_t tg3_interrupt(int irq tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); sblk->status &= ~SD_STATUS_UPDATED; - if (likely(tg3_has_work(dev, tp))) + if (likely(tg3_has_work(dev, tp))) { +#ifdef CONFIG_KGDB + if (dev->poll_controller != NULL) { + int drop=0; + upcall_kgdb_hook(dev, &drop); /*drop may be used later */ + } +#endif netif_rx_schedule(dev); /* schedule NAPI poll */ - else { + } else { /* no work, shared interrupt perhaps? re-enable * interrupts, and flush that PCI write */ @@ -7632,6 +7744,9 @@ static int __devinit tg3_init_one(struct dev->watchdog_timeo = TG3_TX_TIMEOUT; dev->change_mtu = tg3_change_mtu; dev->irq = pdev->irq; +#ifdef CONFIG_KGDB + dev->poll_controller = tg3_poll_controller; +#endif err = tg3_get_invariants(tp); if (err) { _