<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Robert Walsh &lt;rjwalsh@durables.org&gt;

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?



 25-akpm/drivers/net/tg3.c |  122 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 120 insertions(+), 2 deletions(-)

diff -puN drivers/net/tg3.c~tg3-poll_controller drivers/net/tg3.c
--- 25/drivers/net/tg3.c~tg3-poll_controller	Fri Nov  7 14:35:52 2003
+++ 25-akpm/drivers/net/tg3.c	Fri Nov  7 14:35:52 2003
@@ -34,6 +34,10 @@
 #include &lt;asm/byteorder.h&gt;
 #include &lt;asm/uaccess.h&gt;
 
+#ifdef CONFIG_KGDB
+#include &lt;asm/kgdb.h&gt;
+#endif
+
 #ifdef CONFIG_SPARC64
 #include &lt;asm/idprom.h&gt;
 #include &lt;asm/oplib.h&gt;
@@ -1454,6 +1458,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-&gt;irq);
+	tg3_interrupt(dev-&gt;irq, (void *)dev, 0);
+	enable_irq(dev-&gt;irq);
+}
+#endif
+
+
 struct tg3_fiber_aneginfo {
 	int state;
 #define ANEG_STATE_UNKNOWN		0
@@ -2183,6 +2198,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-&gt;priv;
+	u32 rx_rcb_ptr = tp-&gt;rx_rcb_ptr;
+	u16 hw_idx, sw_idx;
+
+	hw_idx = tp-&gt;hw_status-&gt;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 = &amp;tp-&gt;rx_rcb[sw_idx];
+		unsigned int len;
+		struct sk_buff *skb;
+		dma_addr_t dma_addr;
+		u32 opaque_key, desc_idx ;
+
+		desc_idx = desc-&gt;opaque &amp; RXD_OPAQUE_INDEX_MASK;
+		opaque_key = desc-&gt;opaque &amp; RXD_OPAQUE_RING_MASK;
+		if (opaque_key == RXD_OPAQUE_RING_STD) {
+			dma_addr = pci_unmap_addr(&amp;tp-&gt;rx_std_buffers[desc_idx],
+						  mapping);
+			skb = tp-&gt;rx_std_buffers[desc_idx].skb;
+		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
+			dma_addr = pci_unmap_addr(&amp;tp-&gt;rx_jumbo_buffers[desc_idx],
+						  mapping);
+			skb = tp-&gt;rx_jumbo_buffers[desc_idx].skb;
+		}
+		else {
+			goto next_pkt;
+		}
+
+
+		if ((desc-&gt;err_vlan &amp; RXD_ERR_MASK) != 0 &amp;&amp;
+		    (desc-&gt;err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
+			goto next_pkt;
+		}
+
+		len = ((desc-&gt;idx_len &amp; RXD_LEN_MASK) &gt;&gt; RXD_LEN_SHIFT) - 4; /* omit crc */
+
+		if (len &gt; 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-&gt;dev = tp-&gt;dev;
+			skb_reserve(skb, tp-&gt;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-&gt;dev = tp-&gt;dev;
+			skb_reserve(copy_skb, 2);
+			skb_put(copy_skb, len);
+			memcpy(copy_skb-&gt;data, skb-&gt;data, len);
+
+			/* We'll reuse the original ring buffer. */
+			skb = copy_skb;
+		}
+		if ((tp-&gt;tg3_flags &amp; TG3_FLAG_RX_CHECKSUMS) &amp;&amp;
+		    (desc-&gt;type_flags &amp; RXD_FLAG_TCPUDP_CSUM) &amp;&amp;
+		    (((desc-&gt;ip_tcp_csum &amp; RXD_TCPCSUM_MASK)
+		      &gt;&gt; RXD_TCPCSUM_SHIFT) == 0xffff))
+			skb-&gt;ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb-&gt;ip_summed = CHECKSUM_NONE;
+
+		skb-&gt;protocol = eth_type_trans(skb, tp-&gt;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 +2562,15 @@ static irqreturn_t tg3_interrupt(int irq
 		tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
 		sblk-&gt;status &amp;= ~SD_STATUS_UPDATED;
 
-		if (likely(tg3_has_work(dev, tp)))
+		if (likely(tg3_has_work(dev, tp))) {
+#ifdef CONFIG_KGDB
+			if (dev-&gt;poll_controller != NULL) {
+				int drop=0;
+				upcall_kgdb_hook(dev, &amp;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
 			 */
@@ -7636,6 +7751,9 @@ static int __devinit tg3_init_one(struct
 	dev-&gt;watchdog_timeo = TG3_TX_TIMEOUT;
 	dev-&gt;change_mtu = tg3_change_mtu;
 	dev-&gt;irq = pdev-&gt;irq;
+#ifdef CONFIG_KGDB
+ 	dev-&gt;poll_controller = tg3_poll_controller;
+#endif
 
 	err = tg3_get_invariants(tp);
 	if (err) {

_
</pre></body></html>