+++ /dev/null
- drivers/net/3c59x.c | 27 +++++++++++++++++++++++++++
- drivers/net/e100/e100_main.c | 19 +++++++++++++++++++
- drivers/net/e1000/e1000_main.c | 13 +++++++++++++
- drivers/net/eepro100.c | 21 +++++++++++++++++++++
- drivers/net/smc-ultra.c | 11 +++++++++++
- drivers/net/tlan.c | 14 +++++++++++++-
- drivers/net/tulip/tulip_core.c | 22 ++++++++++++++++++++++
- include/linux/netdevice.h | 3 +++
- net/core/dev.c | 18 ++++++++++++++++--
- 9 files changed, 145 insertions(+), 3 deletions(-)
-
---- linux-2.6.0-test1/drivers/net/3c59x.c~dump_netdev 2003-07-22 01:14:04.000000000 -0600
-+++ linux-2.6.0-test1-braam/drivers/net/3c59x.c 2003-07-22 01:15:10.000000000 -0600
-@@ -900,6 +900,7 @@ static void set_rx_mode(struct net_devic
- static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
- static void vortex_tx_timeout(struct net_device *dev);
- static void acpi_set_WOL(struct net_device *dev);
-+static void vorboom_poll(struct net_device *dev);
- \f
- /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
- /* Option count limit only -- unlimited interfaces are supported. */
-@@ -1448,6 +1449,9 @@ static int __devinit vortex_probe1(struc
- dev->set_multicast_list = set_rx_mode;
- dev->tx_timeout = vortex_tx_timeout;
- dev->watchdog_timeo = (watchdog * HZ) / 1000;
-+#ifdef HAVE_POLL_CONTROLLER
-+ dev->poll_controller = &vorboom_poll;
-+#endif
- if (pdev) {
- vp->pm_state_valid = 1;
- pci_save_state(VORTEX_PCI(vp), vp->power_state);
-@@ -2438,6 +2442,29 @@ handler_exit:
- return IRQ_HANDLED;
- }
-
-+#ifdef HAVE_POLL_CONTROLLER
-+
-+/*
-+ * Polling 'interrupt' - used by things like netconsole to send skbs
-+ * without having to re-enable interrupts. It's not called while
-+ * the interrupt routine is executing.
-+ */
-+
-+static void vorboom_poll (struct net_device *dev)
-+{
-+ struct vortex_private *vp = (struct vortex_private *)dev->priv;
-+
-+ disable_irq(dev->irq);
-+ if (vp->full_bus_master_tx)
-+ boomerang_interrupt(dev->irq, dev, 0);
-+ else
-+ vortex_interrupt(dev->irq, dev, 0);
-+ enable_irq(dev->irq);
-+}
-+
-+#endif
-+
-+
- static int vortex_rx(struct net_device *dev)
- {
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
---- linux-2.6.0-test1/drivers/net/e100/e100_main.c~dump_netdev 2003-07-13 21:34:02.000000000 -0600
-+++ linux-2.6.0-test1-braam/drivers/net/e100/e100_main.c 2003-07-22 01:14:38.000000000 -0600
-@@ -551,6 +551,22 @@ e100_trigger_SWI(struct e100_private *bd
- readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */
- }
-
-+#ifdef HAVE_POLL_CONTROLLER
-+
-+/*
-+ * Polling 'interrupt' - used by things like netconsole to send skbs
-+ * without having to re-enable interrupts. It's not called while
-+ * the interrupt routine is executing.
-+ */
-+static void
-+e100_poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ e100intr(dev->irq, dev, NULL);
-+ enable_irq(dev->irq);
-+}
-+#endif
-+
- static int __devinit
- e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
- {
-@@ -569,6 +585,9 @@ e100_found1(struct pci_dev *pcid, const
-
- SET_MODULE_OWNER(dev);
-
-+#ifdef HAVE_POLL_CONTROLLER
-+ dev->poll_controller = &e100_poll;
-+#endif
- if (first_time) {
- first_time = false;
- printk(KERN_NOTICE "%s - version %s\n",
---- linux-2.6.0-test1/drivers/net/e1000/e1000_main.c~dump_netdev 2003-07-13 21:32:43.000000000 -0600
-+++ linux-2.6.0-test1-braam/drivers/net/e1000/e1000_main.c 2003-07-22 01:14:38.000000000 -0600
-@@ -138,6 +138,7 @@ static void e1000_leave_82542_rst(struct
- static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
- struct e1000_rx_desc *rx_desc,
- struct sk_buff *skb);
-+static void e1000_Poll(struct net_device *dev);
- static void e1000_tx_timeout(struct net_device *dev);
- static void e1000_tx_timeout_task(struct net_device *dev);
- static void e1000_smartspeed(struct e1000_adapter *adapter);
-@@ -402,6 +403,9 @@ e1000_probe(struct pci_dev *pdev,
-
- adapter->bd_number = cards_found;
-
-+#ifdef HAVE_POLL_CONTROLLER
-+ netdev->poll_controller = &e1000_Poll;
-+#endif
- /* setup the private structure */
-
- if(e1000_sw_init(adapter))
-@@ -1700,6 +1704,15 @@ e1000_xmit_frame(struct sk_buff *skb, st
- return 0;
- }
-
-+#ifdef HAVE_POLL_CONTROLLER
-+static void e1000_Poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ e1000_intr(dev->irq, dev, NULL);
-+ enable_irq(dev->irq);
-+}
-+#endif
-+
- /**
- * e1000_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
---- linux-2.6.0-test1/drivers/net/eepro100.c~dump_netdev 2003-07-13 21:35:52.000000000 -0600
-+++ linux-2.6.0-test1-braam/drivers/net/eepro100.c 2003-07-22 01:14:38.000000000 -0600
-@@ -543,6 +543,7 @@ static void speedo_refill_rx_buffers(str
- static int speedo_rx(struct net_device *dev);
- static void speedo_tx_buffer_gc(struct net_device *dev);
- static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-+static void poll_speedo (struct net_device *dev);
- static int speedo_close(struct net_device *dev);
- static struct net_device_stats *speedo_get_stats(struct net_device *dev);
- static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-@@ -885,6 +886,9 @@ static int __devinit speedo_found1(struc
- dev->get_stats = &speedo_get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &speedo_ioctl;
-+#ifdef HAVE_POLL_CONTROLLER
-+ dev->poll_controller = &poll_speedo;
-+#endif
-
- if (register_netdevice(dev))
- goto err_free_unlock;
-@@ -1675,6 +1679,23 @@ static irqreturn_t speedo_interrupt(int
- return IRQ_RETVAL(handled);
- }
-
-+#ifdef HAVE_POLL_CONTROLLER
-+
-+/*
-+ * Polling 'interrupt' - used by things like netconsole to send skbs
-+ * without having to re-enable interrupts. It's not called while
-+ * the interrupt routine is executing.
-+ */
-+
-+static void poll_speedo (struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ speedo_interrupt (dev->irq, dev, NULL);
-+ enable_irq(dev->irq);
-+}
-+
-+#endif
-+
- static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
- {
- struct speedo_private *sp = (struct speedo_private *)dev->priv;
---- linux-2.6.0-test1/drivers/net/smc-ultra.c~dump_netdev 2003-07-13 21:30:47.000000000 -0600
-+++ linux-2.6.0-test1-braam/drivers/net/smc-ultra.c 2003-07-22 01:14:38.000000000 -0600
-@@ -122,6 +122,14 @@ MODULE_DEVICE_TABLE(isapnp, ultra_device
- #define ULTRA_IO_EXTENT 32
- #define EN0_ERWCNT 0x08 /* Early receive warning count. */
- \f
-+
-+static void ultra_poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ ei_interrupt(dev->irq, dev, NULL);
-+ enable_irq(dev->irq);
-+}
-+
- /* Probe for the Ultra. This looks like a 8013 with the station
- address PROM at I/O ports <base>+8 to <base>+13, with a checksum
- following.
-@@ -134,6 +142,9 @@ int __init ultra_probe(struct net_device
-
- SET_MODULE_OWNER(dev);
-
-+#ifdef HAVE_POLL_CONTROLLER
-+ dev->poll_controller = &ultra_poll;
-+#endif
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ultra_probe1(dev, base_addr);
- else if (base_addr != 0) /* Don't probe at all. */
---- linux-2.6.0-test1/drivers/net/tlan.c~dump_netdev 2003-07-13 21:30:42.000000000 -0600
-+++ linux-2.6.0-test1-braam/drivers/net/tlan.c 2003-07-22 01:14:38.000000000 -0600
-@@ -345,6 +345,8 @@ static int TLan_EeSendByte( u16, u8, int
- static void TLan_EeReceiveByte( u16, u8 *, int );
- static int TLan_EeReadByte( struct net_device *, u8, u8 * );
-
-+static void TLan_Poll(struct net_device *);
-+
-
- static void
- TLan_StoreSKB( struct tlan_list_tag *tag, struct sk_buff *skb)
-@@ -890,6 +892,9 @@ static int TLan_Init( struct net_device
- dev->get_stats = &TLan_GetStats;
- dev->set_multicast_list = &TLan_SetMulticastList;
- dev->do_ioctl = &TLan_ioctl;
-+#ifdef HAVE_POLL_CONTROLLER
-+ dev->poll_controller = &TLan_Poll;
-+#endif
- dev->tx_timeout = &TLan_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
-@@ -1173,7 +1178,14 @@ static irqreturn_t TLan_HandleInterrupt(
- return IRQ_HANDLED;
- } /* TLan_HandleInterrupts */
-
--
-+#ifdef HAVE_POLL_CONTROLLER
-+static void TLan_Poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ TLan_HandleInterrupt(dev->irq, dev, NULL);
-+ enable_irq(dev->irq);
-+}
-+#endif
-
-
- /***************************************************************
---- linux-2.6.0-test1/drivers/net/tulip/tulip_core.c~dump_netdev 2003-07-13 21:34:48.000000000 -0600
-+++ linux-2.6.0-test1-braam/drivers/net/tulip/tulip_core.c 2003-07-22 01:14:38.000000000 -0600
-@@ -245,6 +245,7 @@ static void tulip_down(struct net_device
- static struct net_device_stats *tulip_get_stats(struct net_device *dev);
- static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
- static void set_rx_mode(struct net_device *dev);
-+static void poll_tulip(struct net_device *dev);
-
-
-
-@@ -1630,6 +1631,9 @@ static int __devinit tulip_init_one (str
- dev->get_stats = tulip_get_stats;
- dev->do_ioctl = private_ioctl;
- dev->set_multicast_list = set_rx_mode;
-+#ifdef HAVE_POLL_CONTROLLER
-+ dev->poll_controller = &poll_tulip;
-+#endif
-
- if (register_netdev(dev))
- goto err_out_free_ring;
-@@ -1787,6 +1791,24 @@ static void __devexit tulip_remove_one (
- }
-
-
-+#ifdef HAVE_POLL_CONTROLLER
-+
-+/*
-+ * Polling 'interrupt' - used by things like netconsole to send skbs
-+ * without having to re-enable interrupts. It's not called while
-+ * the interrupt routine is executing.
-+ */
-+
-+static void poll_tulip (struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ tulip_interrupt (dev->irq, dev, NULL);
-+ enable_irq(dev->irq);
-+}
-+
-+#endif
-+
-+
- static struct pci_driver tulip_driver = {
- .name = DRV_NAME,
- .id_table = tulip_pci_tbl,
---- linux-2.6.0-test1/include/linux/netdevice.h~dump_netdev 2003-07-22 01:14:05.000000000 -0600
-+++ linux-2.6.0-test1-braam/include/linux/netdevice.h 2003-07-22 01:14:38.000000000 -0600
-@@ -446,6 +446,9 @@ struct net_device
- unsigned char *haddr);
- int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
- int (*accept_fastpath)(struct net_device *, struct dst_entry*);
-+#define HAVE_POLL_CONTROLLER
-+ void (*poll_controller)(struct net_device *dev);
-+ int (*rx_hook)(struct sk_buff *skb);
-
- /* bridge stuff */
- struct net_bridge_port *br_port;
---- linux-2.6.0-test1/net/core/dev.c~dump_netdev 2003-07-22 01:14:05.000000000 -0600
-+++ linux-2.6.0-test1-braam/net/core/dev.c 2003-07-22 01:14:38.000000000 -0600
-@@ -1349,8 +1349,6 @@ int netif_rx(struct sk_buff *skb)
- struct softnet_data *queue;
- unsigned long flags;
-
-- if (!skb->stamp.tv_sec)
-- do_gettimeofday(&skb->stamp);
-
- /*
- * The code is rearranged so that the path is the most
-@@ -1360,6 +1358,13 @@ int netif_rx(struct sk_buff *skb)
- this_cpu = smp_processor_id();
- queue = &__get_cpu_var(softnet_data);
-
-+ if (skb->dev->rx_hook)
-+ goto rx_hook;
-+rx_hook_continue:
-+
-+ if (!skb->stamp.tv_sec )
-+ do_gettimeofday(&skb->stamp);
-+
- netdev_rx_stat[this_cpu].total++;
- if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
- if (queue->input_pkt_queue.qlen) {
-@@ -1402,6 +1407,15 @@ drop:
-
- kfree_skb(skb);
- return NET_RX_DROP;
-+rx_hook:
-+ {
-+ int ret;
-+
-+ ret = skb->dev->rx_hook(skb);
-+ if (ret == NET_RX_DROP)
-+ goto drop;
-+ goto rx_hook_continue;
-+ }
- }
-
- /* Deliver skb to an old protocol, which is not threaded well
-
-_
+++ /dev/null
-Index: linux-2.6.0-test6/drivers/dump/dump_netdev.c
-===================================================================
---- linux-2.6.0-test6.orig/drivers/dump/dump_netdev.c 2003-10-07 16:08:57.000000000 +0800
-+++ linux-2.6.0-test6/drivers/dump/dump_netdev.c 2003-10-09 17:36:18.000000000 +0800
-@@ -14,6 +14,7 @@
- *
- * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com>
- * Copyright (C) 2002 International Business Machines Corp.
-+ * Rewrited with netpoll by wangdi <wangdi@clusterfs.com>
- *
- * This code is released under version 2 of the GNU GPL.
- */
-@@ -26,29 +27,19 @@
- #include <linux/module.h>
- #include <linux/dump.h>
- #include <linux/dump_netdev.h>
-+#include <linux/netpoll.h>
-
- #include <asm/unaligned.h>
-
- static int startup_handshake;
- static int page_counter;
--static struct net_device *dump_ndev;
- static struct in_device *dump_in_dev;
--static u16 source_port, target_port;
--static u32 source_ip, target_ip;
--static unsigned char daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
--static spinlock_t dump_skb_lock = SPIN_LOCK_UNLOCKED;
--static int dump_nr_skbs;
--static struct sk_buff *dump_skb;
- static unsigned long flags_global;
- static int netdump_in_progress;
- static char device_name[IFNAMSIZ];
-+int new_req = 0;
-+static req_t req;
-
--/*
-- * security depends on the trusted path between the netconsole
-- * server and netconsole client, since none of the packets are
-- * encrypted. The random magic number protects the protocol
-- * against spoofing.
-- */
- static u64 dump_magic;
-
- #define MAX_UDP_CHUNK 1460
-@@ -64,300 +55,28 @@
- #define MAX_SKB_SIZE \
- (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
- sizeof(struct iphdr) + sizeof(struct ethhdr))
-+static char send_buffer[MAX_UDP_CHUNK];
-
--static void
--dump_refill_skbs(void)
--{
-- struct sk_buff *skb;
-- unsigned long flags;
--
-- spin_lock_irqsave(&dump_skb_lock, flags);
-- while (dump_nr_skbs < DUMP_MAX_SKBS) {
-- skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
-- if (!skb)
-- break;
-- if (dump_skb)
-- skb->next = dump_skb;
-- else
-- skb->next = NULL;
-- dump_skb = skb;
-- dump_nr_skbs++;
-- }
-- spin_unlock_irqrestore(&dump_skb_lock, flags);
--}
--
--static struct
--sk_buff * dump_get_skb(void)
--{
-- struct sk_buff *skb;
-- unsigned long flags;
--
-- spin_lock_irqsave(&dump_skb_lock, flags);
-- skb = dump_skb;
-- if (skb) {
-- dump_skb = skb->next;
-- skb->next = NULL;
-- dump_nr_skbs--;
-- }
-- spin_unlock_irqrestore(&dump_skb_lock, flags);
--
-- return skb;
--}
--
--/*
-- * Zap completed output skbs.
-- */
--static void
--zap_completion_queue(void)
--{
-- int count;
-- unsigned long flags;
-- int cpu = smp_processor_id();
-- struct softnet_data *softnet_data;
--
--
-- softnet_data = &__get_cpu_var(softnet_data);
-- count=0;
-- if (softnet_data[cpu].completion_queue) {
-- struct sk_buff *clist;
--
-- local_irq_save(flags);
-- clist = softnet_data[cpu].completion_queue;
-- softnet_data[cpu].completion_queue = NULL;
-- local_irq_restore(flags);
--
-- while (clist != NULL) {
-- struct sk_buff *skb = clist;
-- clist = clist->next;
-- __kfree_skb(skb);
-- count++;
-- if (count > 10000)
-- printk("Error in sk list\n");
-- }
-- }
--}
--
--static void
--dump_send_skb(struct net_device *dev, const char *msg, unsigned int msg_len,
-- reply_t *reply)
--{
-- int once = 1;
-- int total_len, eth_len, ip_len, udp_len, count = 0;
-- struct sk_buff *skb;
-- struct udphdr *udph;
-- struct iphdr *iph;
-- struct ethhdr *eth;
--
-- udp_len = msg_len + HEADER_LEN + sizeof(*udph);
-- ip_len = eth_len = udp_len + sizeof(*iph);
-- total_len = eth_len + ETH_HLEN;
--
--repeat_loop:
-- zap_completion_queue();
-- if (dump_nr_skbs < DUMP_MAX_SKBS)
-- dump_refill_skbs();
--
-- skb = alloc_skb(total_len, GFP_ATOMIC);
-- if (!skb) {
-- skb = dump_get_skb();
-- if (!skb) {
-- count++;
-- if (once && (count == 1000000)) {
-- printk("possibly FATAL: out of netconsole "
-- "skbs!!! will keep retrying.\n");
-- once = 0;
-- }
-- dev->poll_controller(dev);
-- goto repeat_loop;
-- }
-- }
--
-- atomic_set(&skb->users, 1);
-- skb_reserve(skb, total_len - msg_len - HEADER_LEN);
-- skb->data[0] = NETCONSOLE_VERSION;
--
-- put_unaligned(htonl(reply->nr), (u32 *) (skb->data + 1));
-- put_unaligned(htonl(reply->code), (u32 *) (skb->data + 5));
-- put_unaligned(htonl(reply->info), (u32 *) (skb->data + 9));
--
-- memcpy(skb->data + HEADER_LEN, msg, msg_len);
-- skb->len += msg_len + HEADER_LEN;
--
-- udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
-- udph->source = source_port;
-- udph->dest = target_port;
-- udph->len = htons(udp_len);
-- udph->check = 0;
--
-- iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
--
-- iph->version = 4;
-- iph->ihl = 5;
-- iph->tos = 0;
-- iph->tot_len = htons(ip_len);
-- iph->id = 0;
-- iph->frag_off = 0;
-- iph->ttl = 64;
-- iph->protocol = IPPROTO_UDP;
-- iph->check = 0;
-- iph->saddr = source_ip;
-- iph->daddr = target_ip;
-- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
--
-- eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
--
-- eth->h_proto = htons(ETH_P_IP);
-- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-- memcpy(eth->h_dest, daddr, dev->addr_len);
-+extern void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty);
-+static void dump_rx_hook(struct netpoll *np, int port, char *msg, int len);
-
-- count=0;
--repeat_poll:
-- spin_lock(&dev->xmit_lock);
-- dev->xmit_lock_owner = smp_processor_id();
--
-- count++;
--
--
-- if (netif_queue_stopped(dev)) {
-- dev->xmit_lock_owner = -1;
-- spin_unlock(&dev->xmit_lock);
--
-- dev->poll_controller(dev);
-- zap_completion_queue();
--
--
-- goto repeat_poll;
-- }
--
-- dev->hard_start_xmit(skb, dev);
--
-- dev->xmit_lock_owner = -1;
-- spin_unlock(&dev->xmit_lock);
--}
--
--static unsigned short
--udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr,
-- unsigned long base)
--{
-- return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base);
--}
--
--static int
--udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
-- unsigned short ulen, u32 saddr, u32 daddr)
--{
-- if (uh->check == 0) {
-- skb->ip_summed = CHECKSUM_UNNECESSARY;
-- } else if (skb->ip_summed == CHECKSUM_HW) {
-- skb->ip_summed = CHECKSUM_UNNECESSARY;
-- if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
-- return 0;
-- skb->ip_summed = CHECKSUM_NONE;
-- }
-- if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-- skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen,
-- IPPROTO_UDP, 0);
-- /* Probably, we should checksum udp header (it should be in cache
-- * in any case) and data in tiny packets (< rx copybreak).
-- */
-- return 0;
--}
--
--static __inline__ int
--__udp_checksum_complete(struct sk_buff *skb)
--{
-- return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len,
-- skb->csum));
--}
--
--static __inline__
--int udp_checksum_complete(struct sk_buff *skb)
--{
-- return skb->ip_summed != CHECKSUM_UNNECESSARY &&
-- __udp_checksum_complete(skb);
--}
--
--int new_req = 0;
--static req_t req;
-+static struct netpoll np = {
-+ .name = "netdumpoe",
-+ .dev_name = "eth0",
-+ .rx_hook = dump_rx_hook,
-+ .local_port = 0,
-+ .remote_port = 0,
-+ .remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-+};
-
--static int
--dump_rx_hook(struct sk_buff *skb)
-+static void dump_rx_hook(struct netpoll *np, int port, char *msg, int len)
- {
-- int proto;
-- struct iphdr *iph;
-- struct udphdr *uh;
-- __u32 len, saddr, daddr, ulen;
- req_t *__req;
--
-- /*
-- * First check if were are dumping or doing startup handshake, if
-- * not quickly return.
-- */
-+
- if (!netdump_in_progress)
-- return NET_RX_SUCCESS;
-+ goto out;
-+ __req = (req_t *)msg;
-
-- if (skb->dev->type != ARPHRD_ETHER)
-- goto out;
--
-- proto = ntohs(skb->mac.ethernet->h_proto);
-- if (proto != ETH_P_IP)
-- goto out;
--
-- if (skb->pkt_type == PACKET_OTHERHOST)
-- goto out;
--
-- if (skb_shared(skb))
-- goto out;
--
-- /* IP header correctness testing: */
-- iph = (struct iphdr *)skb->data;
-- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-- goto out;
--
-- if (iph->ihl < 5 || iph->version != 4)
-- goto out;
--
-- if (!pskb_may_pull(skb, iph->ihl*4))
-- goto out;
--
-- if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
-- goto out;
--
-- len = ntohs(iph->tot_len);
-- if (skb->len < len || len < iph->ihl*4)
-- goto out;
--
-- saddr = iph->saddr;
-- daddr = iph->daddr;
-- if (iph->protocol != IPPROTO_UDP)
-- goto out;
--
-- if (source_ip != daddr)
-- goto out;
--
-- if (target_ip != saddr)
-- goto out;
--
-- len -= iph->ihl*4;
-- uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
-- ulen = ntohs(uh->len);
--
-- if (ulen != len || ulen < (sizeof(*uh) + sizeof(*__req)))
-- goto out;
--
-- if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
-- goto out;
--
-- if (udp_checksum_complete(skb))
-- goto out;
--
-- if (source_port != uh->dest)
-- goto out;
--
-- if (target_port != uh->source)
-- goto out;
--
-- __req = (req_t *)(uh + 1);
- if ((ntohl(__req->command) != COMM_GET_MAGIC) &&
- (ntohl(__req->command) != COMM_HELLO) &&
- (ntohl(__req->command) != COMM_START_WRITE_NETDUMP_ACK) &&
-@@ -372,11 +91,27 @@
- req.nr = ntohl(__req->nr);
- new_req = 1;
- out:
-- return NET_RX_DROP;
-+ return;
- }
-
- static void
--dump_send_mem(struct net_device *dev, req_t *req, const char* buff, size_t len)
-+dump_send_skb(const char *msg, unsigned int msg_len, reply_t *reply)
-+{
-+ /*copy the msg to send buffer*/
-+ send_buffer[0] = NETCONSOLE_VERSION;
-+
-+ put_unaligned(htonl(reply->nr), (u32 *) (send_buffer + 1));
-+ put_unaligned(htonl(reply->code), (u32 *) (send_buffer + 5));
-+ put_unaligned(htonl(reply->info), (u32 *) (send_buffer + 9));
-+ memcpy(send_buffer + 1 + sizeof(reply_t), msg, msg_len);
-+
-+ if (!np.dev)
-+ return;
-+ netpoll_send_udp(&np, send_buffer, (msg_len + 1 + sizeof(reply_t)));
-+}
-+
-+static void
-+dump_send_mem( req_t *req, const char* buff, size_t len)
- {
- int i;
-
-@@ -392,7 +127,7 @@
- unsigned int offset = i*1024;
- reply.code = REPLY_MEM;
- reply.info = offset;
-- dump_send_skb(dev, buff + offset, 1024, &reply);
-+ dump_send_skb(buff + offset, 1024, &reply);
- }
- }
- static void dump_do_sysrq(int key)
-@@ -400,9 +135,16 @@
- struct pt_regs regs;
-
- get_current_regs(®s);
-- handle_sysrq(key, ®s, NULL, NULL);
-+ handle_sysrq(key, ®s, NULL);
- }
-
-+static void netdump_netpoll_poll(struct netpoll *np)
-+{
-+ /*FIXME netpoll_set_trap(0) may have impacts to other parts */
-+ netpoll_set_trap(1);
-+ netpoll_poll(np);
-+ netpoll_set_trap(0);
-+}
- /*
- * This function waits for the client to acknowledge the receipt
- * of the netdump startup reply, with the possibility of packets
-@@ -433,24 +175,27 @@
-
- /* send 300 handshake packets before declaring failure */
- for (i = 0; i < 300; i++) {
-- dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
--
-+ dump_send_skb(tmp, strlen(tmp), &reply);
-+#if 0
- /* wait 1 sec */
-+ udelay(100);
-+ netpoll_poll(&np);
-+ if (new_req)
-+ break;
-+ }
-+#endif
- for (j = 0; j < 10000; j++) {
- udelay(100);
-- dump_ndev->poll_controller(dump_ndev);
-- zap_completion_queue();
-+ netdump_netpoll_poll(&np);
- if (new_req)
- break;
- }
--
- /*
- * if there is no new request, try sending the handshaking
- * packet again
- */
- if (!new_req)
- continue;
--
- /*
- * check if the new request is of the expected type,
- * if so, return, else try sending the handshaking
-@@ -504,10 +249,12 @@
- repeatCounter = 0;
- total_loop = 0;
- while (1) {
-- if (!new_req) {
-- dump_ndev->poll_controller(dump_ndev);
-- zap_completion_queue();
-+ while (!new_req) {
-+ netdump_netpoll_poll(&np);
-+ if (new_req)
-+ break;
- }
-+#if 0
- if (!new_req) {
- repeatCounter++;
-
-@@ -532,13 +279,15 @@
- repeatCounter = 0;
- counter = 0;
- total_loop = 0;
-+#endif
-+
- new_req = 0;
- switch (req.command) {
- case COMM_NONE:
- break;
-
- case COMM_SEND_MEM:
-- dump_send_mem(dump_ndev, &req, buff, len);
-+ dump_send_mem(&req, buff, len);
- break;
-
- case COMM_EXIT:
-@@ -549,10 +298,11 @@
- case COMM_HELLO:
- sprintf(tmp, "Hello, this is netdump version "
- "0.%02d\n", NETCONSOLE_VERSION);
-+
- reply.code = REPLY_HELLO;
- reply.nr = req.nr;
- reply.info = net_dev->curr_offset;
-- dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
-+ dump_send_skb(tmp, strlen(tmp), &reply);
- break;
-
- case COMM_GET_PAGE_SIZE:
-@@ -560,7 +310,7 @@
- reply.code = REPLY_PAGE_SIZE;
- reply.nr = req.nr;
- reply.info = PAGE_SIZE;
-- dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
-+ dump_send_skb(tmp, strlen(tmp), &reply);
- break;
-
- case COMM_GET_NR_PAGES:
-@@ -569,15 +319,14 @@
- reply.info = num_physpages;
- reply.info = page_counter;
- sprintf(tmp, "Number of pages: %ld\n", num_physpages);
-- dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
-+ dump_send_skb(tmp, strlen(tmp), &reply);
- break;
-
- case COMM_GET_MAGIC:
- reply.code = REPLY_MAGIC;
- reply.nr = req.nr;
- reply.info = NETCONSOLE_VERSION;
-- dump_send_skb(dump_ndev, (char *)&dump_magic,
-- sizeof(dump_magic), &reply);
-+ dump_send_skb((char *)&dump_magic, sizeof(dump_magic), &reply);
- break;
- case COMM_SYSRQ:
- dump_do_sysrq(req.from);
-@@ -585,7 +334,7 @@
- reply.nr = req.nr;
- reply.info = req.from;
- sprintf(tmp, "SYSRQ command %d \n", req.from);
-- dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
-+ dump_send_skb(tmp, strlen(tmp), &reply);
- break;
- default:
- reply.code = REPLY_ERROR;
-@@ -593,7 +342,7 @@
- reply.info = req.command;
- sprintf(tmp, "Got unknown command code %d!\n",
- req.command);
-- dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
-+ dump_send_skb(tmp, strlen(tmp), &reply);
- break;
- }
- }
-@@ -605,45 +354,45 @@
- static int
- dump_validate_config(void)
- {
-- source_ip = dump_in_dev->ifa_list->ifa_local;
-- if (!source_ip) {
-+#if 0
-+ np.local_ip = dump_in_dev->ifa_list->ifa_local;
-+ if (!np.local_ip) {
- printk("network device %s has no local address, "
- "aborting.\n", device_name);
- return -1;
- }
--
--#define IP(x) ((unsigned char *)&source_ip)[x]
-+#endif
-+#define IP(x) ((unsigned char *)&np.local_ip)[x]
- printk("Source %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
- #undef IP
-
-- if (!source_port) {
-+ if (!np.local_port) {
- printk("source_port parameter not specified, aborting.\n");
- return -1;
- }
-- printk(":%i\n", source_port);
-- source_port = htons(source_port);
-+ printk(":%i\n", np.local_port);
-
-- if (!target_ip) {
-+ if (!np.remote_ip) {
- printk("target_ip parameter not specified, aborting.\n");
- return -1;
- }
-
--#define IP(x) ((unsigned char *)&target_ip)[x]
-+#define IP(x) ((unsigned char *)&np.remote_ip)[x]
- printk("Target %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
- #undef IP
-
-- if (!target_port) {
-+ if (!np.remote_port) {
- printk("target_port parameter not specified, aborting.\n");
- return -1;
- }
-- printk(":%i\n", target_port);
-- target_port = htons(target_port);
-+ printk(":%i\n", np.remote_port);
-
- printk("Target Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x",
-- daddr[0], daddr[1], daddr[2], daddr[3], daddr[4], daddr[5]);
-+ np.remote_mac[0], np.remote_mac[1], np.remote_mac[2],
-+ np.remote_mac[3], np.remote_mac[4], np.remote_mac[5]);
-
-- if ((daddr[0] & daddr[1] & daddr[2] & daddr[3] & daddr[4] &
-- daddr[5]) == 255)
-+ if ((np.remote_mac[0] & np.remote_mac[1] & np.remote_mac[2] &
-+ np.remote_mac[3] & np.remote_mac[4] & np.remote_mac[5]) == 255)
- printk("(Broadcast)");
- printk("\n");
- return 0;
-@@ -659,31 +408,24 @@
- dump_net_open(struct dump_dev *net_dev, unsigned long arg)
- {
- int retval = 0;
--
-+#if 0
- /* get the interface name */
- if (copy_from_user(device_name, (void *)arg, IFNAMSIZ))
- return -EFAULT;
-
-- if (!(dump_ndev = dev_get_by_name(device_name))) {
-+ if (!(np.dev = dev_get_by_name(device_name))) {
- printk("network device %s does not exist, aborting.\n",
- device_name);
- return -ENODEV;
- }
--
-- if (!dump_ndev->poll_controller) {
-- printk("network device %s does not implement polling yet, "
-- "aborting.\n", device_name);
-- retval = -1; /* return proper error */
-- goto err1;
-- }
--
-- if (!(dump_in_dev = in_dev_get(dump_ndev))) {
-+#endif
-+ if (!(dump_in_dev = in_dev_get(np.dev))) {
- printk("network device %s is not an IP protocol device, "
- "aborting.\n", device_name);
- retval = -EINVAL;
- goto err1;
- }
--
-+
- if ((retval = dump_validate_config()) < 0)
- goto err2;
-
-@@ -694,7 +436,7 @@
- err2:
- in_dev_put(dump_in_dev);
- err1:
-- dev_put(dump_ndev);
-+ dev_put(np.dev);
- return retval;
- }
-
-@@ -707,8 +449,8 @@
- {
- if (dump_in_dev)
- in_dev_put(dump_in_dev);
-- if (dump_ndev)
-- dev_put(dump_ndev);
-+ if (np.dev)
-+ dev_put(np.dev);
- return 0;
- }
-
-@@ -720,7 +462,6 @@
- dump_net_silence(struct dump_dev *net_dev)
- {
- local_irq_save(flags_global);
-- dump_ndev->rx_hook = dump_rx_hook;
- startup_handshake = 1;
- net_dev->curr_offset = 0;
- printk("Dumping to network device %s on CPU %d ...\n", device_name,
-@@ -740,7 +481,7 @@
- reply_t reply;
- char tmp[200];
-
-- if (!dump_ndev)
-+ if (!np.dev)
- return (0);
-
- sprintf(tmp, "NETDUMP end.\n");
-@@ -748,11 +489,10 @@
- reply.code = REPLY_END_NETDUMP;
- reply.nr = 0;
- reply.info = 0;
-- dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
-+ dump_send_skb(tmp, strlen(tmp), &reply);
- }
- printk("NETDUMP END!\n");
- local_irq_restore(flags_global);
-- dump_ndev->rx_hook = NULL;
- startup_handshake = 0;
- return 0;
- }
-@@ -809,18 +549,19 @@
- static int
- dump_net_ioctl(struct dump_dev *net_dev, unsigned int cmd, unsigned long arg)
- {
-+ #if 0
- switch (cmd) {
- case DIOSTARGETIP:
-- target_ip = arg;
-+ np.remote_ip = arg;
- break;
- case DIOSTARGETPORT:
-- target_port = (u16)arg;
-+ np.remote_port = (u16)arg;
- break;
- case DIOSSOURCEPORT:
-- source_port = (u16)arg;
-+ np.local_port = (u16)arg;
- break;
- case DIOSETHADDR:
-- return copy_from_user(daddr, (void *)arg, 6);
-+ return copy_from_user(np.remote_mac, (void *)arg, 6);
- break;
- case DIOGTARGETIP:
- case DIOGTARGETPORT:
-@@ -830,6 +571,7 @@
- default:
- return -EINVAL;
- }
-+ #endif
- return 0;
- }
-
-@@ -851,17 +593,28 @@
- .curr_offset = 0
- };
-
-+static int option_setup(char *opt)
-+{
-+ return netpoll_parse_options(&np, opt);
-+}
-+
-+__setup("netdumpoe=", option_setup);
-+
-+
- static int __init
- dump_netdev_init(void)
- {
- default_dump_netdev.curr_offset = 0;
-
-+ if(!np.remote_ip || netpoll_setup(&np))
-+ return 1;
-+
- if (dump_register_device(&default_dump_netdev) < 0) {
- printk("network dump device driver registration failed\n");
- return -1;
- }
- printk("network device driver for LKCD registered\n");
--
-+
- get_random_bytes(&dump_magic, sizeof(dump_magic));
- return 0;
- }
-@@ -870,6 +623,7 @@
- dump_netdev_cleanup(void)
- {
- dump_unregister_device(&default_dump_netdev);
-+ netpoll_cleanup(&np);
- }
-
- MODULE_AUTHOR("LKCD Development Team <lkcd-devel@lists.sourceforge.net>");
+++ /dev/null
-Index: linux-2.6.0-test5/net/core/netpoll.c
-===================================================================
---- linux-2.6.0-test5.orig/net/core/netpoll.c 2003-09-26 15:42:10.000000000 +0800
-+++ linux-2.6.0-test5/net/core/netpoll.c 2003-09-26 15:42:32.000000000 +0800
-@@ -630,3 +630,11 @@
- {
- trapped = trap;
- }
-+EXPORT_SYMBOL(netpoll_set_trap);
-+EXPORT_SYMBOL(netpoll_trap);
-+EXPORT_SYMBOL(netpoll_parse_options);
-+EXPORT_SYMBOL(netpoll_setup);
-+EXPORT_SYMBOL(netpoll_cleanup);
-+EXPORT_SYMBOL(netpoll_send_skb);
-+EXPORT_SYMBOL(netpoll_send_udp);
-+EXPORT_SYMBOL(netpoll_poll);
+++ /dev/null
- l-mpm/Documentation/i386/kgdb/kgdbeth.txt | 88 +----
- l-mpm/arch/i386/kernel/irq.c | 10
- l-mpm/arch/i386/kernel/kgdb_stub.c | 107 +-----
- l-mpm/arch/i386/lib/kgdb_serial.c | 2
- l-mpm/drivers/net/Makefile | 5
- l-mpm/drivers/net/kgdb_eth.c | 464 ++++--------------------------
- l-mpm/include/asm-i386/kgdb.h | 11
- l-mpm/net/core/dev.c | 4
- 8 files changed, 129 insertions(+), 562 deletions(-)
-
-Index: linux-2.6.0-test6/drivers/net/kgdb_eth.c
-===================================================================
---- linux-2.6.0-test6.orig/drivers/net/kgdb_eth.c 2003-10-12 13:12:22.000000000 +0800
-+++ linux-2.6.0-test6/drivers/net/kgdb_eth.c 2003-10-12 13:12:25.000000000 +0800
-@@ -7,36 +7,26 @@
- *
- * 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/module.h>
--#include <linux/errno.h>
--#include <linux/signal.h>
- #include <linux/sched.h>
--#include <linux/timer.h>
- #include <linux/interrupt.h>
- #include <linux/config.h>
--#include <linux/major.h>
- #include <linux/string.h>
--#include <linux/fcntl.h>
--#include <linux/termios.h>
--#include <asm/kgdb.h>
--#include <linux/if_ether.h>
--#include <linux/netdevice.h>
--#include <linux/etherdevice.h>
--#include <linux/skbuff.h>
--#include <linux/delay.h>
--#include <net/tcp.h>
--#include <net/udp.h>
-+#include <linux/netpoll.h>
-
- #include <asm/system.h>
-+#include <asm/kgdb.h>
- #include <asm/io.h>
--#include <asm/segment.h>
- #include <asm/bitops.h>
- #include <asm/system.h>
- #include <asm/irq.h>
- #include <asm/atomic.h>
-
-+
- #define GDB_BUF_SIZE 512 /* power of 2, please */
-
- static char kgdb_buf[GDB_BUF_SIZE] ;
-@@ -44,26 +34,28 @@
- static atomic_t kgdb_buf_in_cnt ;
- static int kgdb_buf_out_inx ;
-
-+#define ETH_QUEUE_SIZE 256
-+static char eth_queue[ETH_QUEUE_SIZE];
-+static int outgoing_queue;
-+
- extern void set_debug_traps(void) ; /* GDB routine */
- extern void breakpoint(void);
-
--unsigned int kgdb_remoteip = 0;
--unsigned short kgdb_listenport = 6443;
--unsigned short kgdb_sendport= 6442;
--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];
-+int kgdboe = 0; /* Default tty mode */
-+int kgdb_eth_need_breakpoint[NR_CPUS];
-
--struct net_device *kgdb_netdevice = NULL;
-+static void rx_hook(struct netpoll *np, int port, char *msg, int len);
-
--/*
-- * Get a char if available, return -1 if nothing available.
-- * Empty the receive buffer first, then look at the interface hardware.
-- */
--static int
--read_char(void)
-+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 read_char(void)
- {
- /* intr routine has queued chars */
- if (atomic_read(&kgdb_buf_in_cnt) != 0)
-@@ -79,287 +71,32 @@
- return -1; /* no data */
- }
-
--/*
-- * Wait until the interface can accept a char, then write it.
-- */
--static void
--write_buffer(char *buf, int len)
-+static void write_buffer(char *buf, int len)
- {
-- int total_len, eth_len, ip_len, udp_len;
-- struct in_device *in_dev;
-- struct sk_buff *skb;
-- struct udphdr *udph;
-- struct iphdr *iph;
-- struct ethhdr *eth;
--
-- if (!(in_dev = (struct in_device *) kgdb_netdevice->ip_ptr)) {
-- panic("No in_device available for interface!\n");
-- }
--
-- if (!(in_dev->ifa_list)) {
-- panic("No interface address set for interface!\n");
-- }
--
-- udp_len = len + sizeof(struct udphdr);
-- ip_len = eth_len = udp_len + sizeof(struct iphdr);
-- total_len = eth_len + ETH_HLEN;
--
-- if (!(skb = alloc_skb(total_len, GFP_ATOMIC))) {
-+ if (!np.dev)
- return;
-- }
--
-- atomic_set(&skb->users, 1);
-- skb_reserve(skb, total_len - len);
--
-- memcpy(skb->data, (unsigned char *) buf, len);
-- skb->len += len;
--
-- udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
-- udph->source = htons(kgdb_listenport);
-- udph->dest = htons(kgdb_sendport);
-- udph->len = htons(udp_len);
-- udph->check = 0;
--
-- iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
-- iph->version = 4;
-- iph->ihl = 5;
-- iph->tos = 0;
-- iph->tot_len = htons(ip_len);
-- iph->id = 0;
-- iph->frag_off = 0;
-- iph->ttl = 64;
-- iph->protocol = IPPROTO_UDP;
-- iph->check = 0;
-- iph->saddr = in_dev->ifa_list->ifa_address;
-- iph->daddr = kgdb_remoteip;
-- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
--
-- eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-- eth->h_proto = htons(ETH_P_IP);
-- memcpy(eth->h_source, kgdb_localmac, kgdb_netdevice->addr_len);
-- memcpy(eth->h_dest, kgdb_remotemac, kgdb_netdevice->addr_len);
--
--repeat:
-- spin_lock(&kgdb_netdevice->xmit_lock);
-- kgdb_netdevice->xmit_lock_owner = smp_processor_id();
--
-- if (netif_queue_stopped(kgdb_netdevice)) {
-- kgdb_netdevice->xmit_lock_owner = -1;
-- spin_unlock(&kgdb_netdevice->xmit_lock);
--
-- kgdb_netdevice->poll_controller(kgdb_netdevice);
-- goto repeat;
-- }
--
-- kgdb_netdevice->hard_start_xmit(skb, kgdb_netdevice);
-- kgdb_netdevice->xmit_lock_owner = -1;
-- spin_unlock(&kgdb_netdevice->xmit_lock);
-+ netpoll_send_udp(&np, buf, len);
- }
-
- /*
-- * In the interrupt state the target machine will not respond to any
-- * arp requests, so handle them here.
-- */
--
--static struct sk_buff *send_skb = NULL;
--
--void
--kgdb_eth_reply_arp(void)
--{
-- if (send_skb) {
-- spin_lock(&kgdb_netdevice->xmit_lock);
-- kgdb_netdevice->xmit_lock_owner = smp_processor_id();
-- kgdb_netdevice->hard_start_xmit(send_skb, kgdb_netdevice);
-- kgdb_netdevice->xmit_lock_owner = -1;
-- spin_unlock(&kgdb_netdevice->xmit_lock);
-- send_skb = NULL;
-- }
--}
--
--static int
--make_arp_request(struct sk_buff *skb)
--{
-- struct arphdr *arp;
-- unsigned char *arp_ptr;
-- int type = ARPOP_REPLY;
-- int ptype = ETH_P_ARP;
-- u32 sip, tip;
-- unsigned char *sha, *tha;
-- struct in_device *in_dev = (struct in_device *) kgdb_netdevice->ip_ptr;
--
-- /* No arp on this interface */
--
-- if (kgdb_netdevice->flags & IFF_NOARP) {
-- return 0;
-- }
--
-- if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
-- (2 * kgdb_netdevice->addr_len) +
-- (2 * sizeof(u32))))) {
-- return 0;
-- }
--
-- skb->h.raw = skb->nh.raw = skb->data;
-- arp = skb->nh.arph;
--
-- if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
-- arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
-- arp->ar_pro != htons(ETH_P_IP)) {
-- return 0;
-- }
--
-- /* Understand only these message types */
--
-- if (arp->ar_op != htons(ARPOP_REQUEST)) {
-- return 0;
-- }
--
-- /* Extract fields */
--
-- arp_ptr= (unsigned char *)(arp+1);
-- sha = arp_ptr;
-- arp_ptr += kgdb_netdevice->addr_len;
-- memcpy(&sip, arp_ptr, 4);
-- arp_ptr += 4;
-- tha = arp_ptr;
-- arp_ptr += kgdb_netdevice->addr_len;
-- memcpy(&tip, arp_ptr, 4);
--
-- if (tip != in_dev->ifa_list->ifa_address) {
-- return 0;
-- }
--
-- if (kgdb_remoteip != sip) {
-- return 0;
-- }
--
-- /*
-- * Check for bad requests for 127.x.x.x and requests for multicast
-- * addresses. If this is one such, delete it.
-- */
--
-- if (LOOPBACK(tip) || MULTICAST(tip)) {
-- return 0;
-- }
--
-- /* reply to the ARP request */
--
-- send_skb = alloc_skb(sizeof(struct arphdr) + 2 * (kgdb_netdevice->addr_len + 4) + LL_RESERVED_SPACE(kgdb_netdevice), GFP_ATOMIC);
--
-- if (send_skb == NULL) {
-- return 0;
-- }
--
-- skb_reserve(send_skb, LL_RESERVED_SPACE(kgdb_netdevice));
-- send_skb->nh.raw = send_skb->data;
-- arp = (struct arphdr *) skb_put(send_skb, sizeof(struct arphdr) + 2 * (kgdb_netdevice->addr_len + 4));
-- send_skb->dev = kgdb_netdevice;
-- send_skb->protocol = htons(ETH_P_ARP);
--
-- /* Fill the device header for the ARP frame */
--
-- if (kgdb_netdevice->hard_header &&
-- kgdb_netdevice->hard_header(send_skb, kgdb_netdevice, ptype,
-- kgdb_remotemac, kgdb_localmac,
-- send_skb->len) < 0) {
-- kfree_skb(send_skb);
-- return 0;
-- }
--
-- /*
-- * Fill out the arp protocol part.
-- *
-- * we only support ethernet device type,
-- * which (according to RFC 1390) should always equal 1 (Ethernet).
-- */
--
-- arp->ar_hrd = htons(kgdb_netdevice->type);
-- arp->ar_pro = htons(ETH_P_IP);
--
-- arp->ar_hln = kgdb_netdevice->addr_len;
-- arp->ar_pln = 4;
-- arp->ar_op = htons(type);
--
-- arp_ptr=(unsigned char *)(arp + 1);
--
-- memcpy(arp_ptr, kgdb_netdevice->dev_addr, kgdb_netdevice->addr_len);
-- arp_ptr += kgdb_netdevice->addr_len;
-- memcpy(arp_ptr, &tip, 4);
-- arp_ptr += 4;
-- memcpy(arp_ptr, kgdb_localmac, kgdb_netdevice->addr_len);
-- arp_ptr += kgdb_netdevice->addr_len;
-- memcpy(arp_ptr, &sip, 4);
-- return 0;
--}
--
--
--/*
- * Accept an skbuff from net_device layer and add the payload onto
- * kgdb buffer
-- *
-- * When the kgdb stub routine 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 writes one byte
-- * after waiting for the interface to become ready.
-- *
-- * The debug stubs like to run with interrupts disabled since, after all,
-- * they run as a consequence of a breakpoint in the kernel.
-- *
-- * NOTE: Return value of 1 means it was for us and is an indication to
-- * the calling driver to destroy the sk_buff and not send it up the stack.
- */
--int
--kgdb_net_interrupt(struct sk_buff *skb)
-+static void rx_hook(struct netpoll *np, int port, char *msg, int len)
- {
-- unsigned char chr;
-- struct iphdr *iph = (struct iphdr*)skb->data;
-- struct udphdr *udph= (struct udphdr*)(skb->data+(iph->ihl<<2));
-- unsigned char *data = (unsigned char *) udph + sizeof(struct udphdr);
-- int len;
-- int i;
--
-- if ((kgdb_eth != -1) && (!kgdb_netdevice) &&
-- (iph->protocol == IPPROTO_UDP) &&
-- (be16_to_cpu(udph->dest) == kgdb_listenport)) {
-- kgdb_sendport = be16_to_cpu(udph->source);
--
-- while (kgdb_eth_is_initializing)
-- ;
-- if (!kgdb_netdevice)
-- kgdb_eth_hook();
-- if (!kgdb_netdevice) {
-- /* Lets not even try again. */
-- kgdb_eth = -1;
-- return 0;
-- }
-- }
-- if (!kgdb_netdevice) {
-- return 0;
-- }
-- if (skb->protocol == __constant_htons(ETH_P_ARP) && !send_skb) {
-- make_arp_request(skb);
-- return 0;
-- }
-- if (iph->protocol != IPPROTO_UDP) {
-- return 0;
-- }
-+ int i, chr;
-
-- if (be16_to_cpu(udph->dest) != kgdb_listenport) {
-- return 0;
-- }
-+ np->remote_port = port;
-
-- len = (be16_to_cpu(iph->tot_len) -
-- (sizeof(struct udphdr) + sizeof(struct iphdr)));
-+ /* 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++) {
-- chr = data[i];
-- if (chr == 3) {
-- kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
-- continue;
-- }
-+ chr = msg[i];
-+ if (chr == 3)
-+ kgdb_schedule_breakpoint();
-+
- if (atomic_read(&kgdb_buf_in_cnt) >= GDB_BUF_SIZE) {
- /* buffer overflow, clear it */
- kgdb_buf_in_inx = 0;
-@@ -371,112 +108,54 @@
- kgdb_buf_in_inx &= (GDB_BUF_SIZE - 1);
- atomic_inc(&kgdb_buf_in_cnt);
- }
--
-- if (!kgdb_netdevice->kgdb_is_trapped) {
-- /*
-- * If a new gdb instance is trying to attach, we need to
-- * break here.
-- */
-- if (!strncmp(data, "$Hc-1#09", 8))
-- kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
-- }
-- return 1;
- }
--EXPORT_SYMBOL(kgdb_net_interrupt);
-
--int
--kgdb_eth_hook(void)
-+static int option_setup(char *opt)
- {
-- char kgdb_netdev[16];
-- extern void kgdb_respond_ok(void);
--
-- if (kgdb_remotemac[0] == 0xff) {
-- panic("ERROR! 'gdbeth_remotemac' option not set!\n");
-- }
-- if (kgdb_localmac[0] == 0xff) {
-- panic("ERROR! 'gdbeth_localmac' option not set!\n");
-- }
-- if (kgdb_remoteip == 0) {
-- panic("ERROR! 'gdbeth_remoteip' option not set!\n");
-- }
-+ return netpoll_parse_options(&np, opt);
-+}
-
-- sprintf(kgdb_netdev,"eth%d",kgdb_eth);
-+__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
-- for (kgdb_netdevice = dev_base;
-- kgdb_netdevice != NULL;
-- kgdb_netdevice = kgdb_netdevice->next) {
-- if (strncmp(kgdb_netdevice->name, kgdb_netdev, IFNAMSIZ) == 0) {
-- break;
-- }
-- }
-- if (!kgdb_netdevice) {
-- printk("KGDB NET : Unable to find interface %s\n",kgdb_netdev);
-- return -ENODEV;
-- }
-
-- /*
-- * Call GDB routine to setup the exception vectors for the debugger
-- */
- set_debug_traps();
-
-- /*
-- * Call the breakpoint() routine in GDB to start the debugging
-- * session.
-- */
-- kgdb_eth_is_initializing = 1;
-- kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
-+ if(!np.remote_ip || netpoll_setup(&np))
-+ return 1;
-+
-+ kgdboe = 1;
-+
-+ printk(KERN_INFO "kgdb: debugging over ethernet enabled\n");
-+
- return 0;
- }
-
--/*
-- * 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
-- * interface connection then it returns a bogus value which will
-- * almost certainly cause the system to hang.
-- */
--int
--eth_getDebugChar(void)
-+int eth_getDebugChar(void)
- {
-- volatile int chr;
-+ int chr;
-
-- while ((chr = read_char()) < 0) {
-- if (send_skb) {
-- kgdb_eth_reply_arp();
-- }
-- if (kgdb_netdevice->poll_controller) {
-- kgdb_netdevice->poll_controller(kgdb_netdevice);
-- } else {
-- printk("KGDB NET: Error - Device %s is not supported!\n", kgdb_netdevice->name);
-- panic("Please add support for kgdb net to this driver");
-- }
-- }
-+ while ((chr = read_char()) < 0)
-+ netpoll_poll(&np);
- return chr;
- }
-
--#define ETH_QUEUE_SIZE 256
--static char eth_queue[ETH_QUEUE_SIZE];
--static int outgoing_queue;
--
--void
--eth_flushDebugChar(void)
-+void eth_flushDebugChar(void)
- {
- if(outgoing_queue) {
- write_buffer(eth_queue, outgoing_queue);
--
- outgoing_queue = 0;
- }
- }
-
--static void
--put_char_on_queue(int chr)
-+static void put_char_on_queue(int chr)
- {
- eth_queue[outgoing_queue++] = chr;
- if(outgoing_queue == ETH_QUEUE_SIZE)
-@@ -485,33 +164,26 @@
- }
- }
-
--/*
-- * eth_putDebugChar
-- *
-- * This is a GDB stub routine. It waits until the interface is ready
-- * to transmit a char and then sends it.
-- */
--void
--eth_putDebugChar(int chr)
-+void eth_putDebugChar(int chr)
- {
- put_char_on_queue(chr); /* this routine will wait */
- }
-
--void
--kgdb_eth_set_trapmode(int mode)
-+void kgdb_schedule_breakpoint(void)
- {
-- if (!kgdb_netdevice) {
-- return;
-- }
-- kgdb_netdevice->kgdb_is_trapped = mode;
-+ kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
- }
-
--int
--kgdb_eth_is_trapped()
-+void kgdb_process_breakpoint(void)
- {
-- if (!kgdb_netdevice) {
-- return 0;
-+ /*
-+ * Handle a breakpoint queued from inside network driver code
-+ * to avoid reentrancy issues
-+ */
-+ if (kgdb_eth_need_breakpoint[smp_processor_id()]) {
-+ kgdb_eth_need_breakpoint[smp_processor_id()] = 0;
-+ BREAKPOINT;
- }
-- return kgdb_netdevice->kgdb_is_trapped;
- }
--EXPORT_SYMBOL(kgdb_eth_is_trapped);
-+
-+module_init(init_kgdboe);
-Index: linux-2.6.0-test6/arch/i386/kernel/kgdb_stub.c
-===================================================================
---- linux-2.6.0-test6.orig/arch/i386/kernel/kgdb_stub.c 2003-10-12 13:12:22.000000000 +0800
-+++ linux-2.6.0-test6/arch/i386/kernel/kgdb_stub.c 2003-10-12 18:57:21.625083056 +0800
-@@ -120,6 +120,7 @@
- #include <asm/desc.h>
- #include <linux/inet.h>
- #include <linux/kallsyms.h>
-+#include <linux/netpoll.h>
-
- /************************************************************************
- *
-@@ -136,10 +137,6 @@
- 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 */
--extern void kgdb_eth_set_trapmode(int);
--extern void kgdb_eth_reply_arp(void); /*send arp request */
--extern volatile int kgdb_eth_is_initializing;
--
-
- /************************************************************************/
- /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-@@ -281,13 +278,13 @@
-
- /*
- * I/O dispatch functions...
-- * Based upon kgdb_eth, either call the ethernet
-+ * Based upon kgdboe, either call the ethernet
- * handler or the serial one..
- */
- void
- putDebugChar(int c)
- {
-- if (kgdb_eth == -1) {
-+ if (!kgdboe) {
- tty_putDebugChar(c);
- } else {
- eth_putDebugChar(c);
-@@ -297,7 +294,7 @@
- int
- getDebugChar(void)
- {
-- if (kgdb_eth == -1) {
-+ if (!kgdboe) {
- return tty_getDebugChar();
- } else {
- return eth_getDebugChar();
-@@ -307,7 +304,7 @@
- void
- flushDebugChar(void)
- {
-- if (kgdb_eth == -1) {
-+ if (!kgdboe) {
- tty_flushDebugChar();
- } else {
- eth_flushDebugChar();
-@@ -494,66 +491,24 @@
-
- /* $<packet info>#<checksum>. */
-
-- if (kgdb_eth == -1) {
-- 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
-- */
--
--#define MAX_SEND_COUNT 30
--
-- 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;
-+ while ((ch = buffer[count])) {
-+ putDebugChar(ch);
-+ checksum += ch;
-+ count += 1;
-+ }
-+
-+ putDebugChar('#');
-+ putDebugChar(hexchars[checksum >> 4]);
-+ putDebugChar(hexchars[checksum % 16]);
-+ flushDebugChar();
-
-- 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) != '+');
-- }
-+ } while ((getDebugChar() & 0x7f) != '+');
- }
-
- static char remcomInBuffer[BUFMAX];
-@@ -1142,9 +1097,9 @@
- */
- 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
-@@ -1153,16 +1108,18 @@
- * 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
- */
-@@ -1281,9 +1238,8 @@
-
- __asm__("movl %%cr2,%0":"=r" (address));
-
-- if (kgdb_eth != -1) {
-- kgdb_eth_set_trapmode(1);
-- }
-+ if (kgdboe)
-+ netpoll_set_trap(1);
-
- kgdb_local_irq_save(flags);
-
-@@ -1338,10 +1294,12 @@
- 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;
-@@ -1526,13 +1484,8 @@
- remcomOutBuffer[2] = hexchars[signo % 16];
- remcomOutBuffer[3] = 0;
-
-- if (kgdb_eth_is_initializing) {
-- kgdb_eth_is_initializing = 0;
-- } else {
-- putpacket(remcomOutBuffer);
-- }
-+ putpacket(remcomOutBuffer);
-
-- kgdb_eth_reply_arp();
- while (1 == 1) {
- error = 0;
- remcomOutBuffer[0] = 0;
-@@ -1689,10 +1642,6 @@
-
- newPC = regs.eip;
-
-- if (kgdb_eth != -1) {
-- kgdb_eth_set_trapmode(0);
-- }
--
- /* clear the trace bit */
- regs.eflags &= 0xfffffeff;
-
-@@ -1724,6 +1673,10 @@
- }
- }
- }
-+
-+ if (kgdboe)
-+ netpoll_set_trap(0);
-+
- correct_hw_break();
- asm volatile ("movl %0, %%db6\n"::"r" (0));
- goto exit_kgdb;
-@@ -2430,63 +2383,3 @@
- int signo, int err_code, struct pt_regs *linux_regs);
- gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception; /* histerical reasons... */
-
--static int __init kgdb_opt_kgdbeth(char *str)
--{
-- kgdb_eth = simple_strtoul(str, NULL, 10);
-- return 1;
--}
--
--static int __init kgdb_opt_kgdbeth_remoteip(char *str)
--{
-- kgdb_remoteip = in_aton(str);
-- return 1;
--}
--
--static int __init kgdb_opt_kgdbeth_listenport(char *str)
--{
-- kgdb_listenport = simple_strtoul(str, NULL, 10);
-- kgdb_sendport = kgdb_listenport - 1;
-- return 1;
--}
--
--static int __init parse_hw_addr(char *str, unsigned char *addr)
--{
-- int i;
-- char *p;
--
-- p = str;
-- i = 0;
-- while(1)
-- {
-- unsigned int c;
--
-- sscanf(p, "%x:", &c);
-- addr[i++] = c;
-- while((*p != 0) && (*p != ':')) {
-- p++;
-- }
-- if (*p == 0) {
-- break;
-- }
-- p++;
-- }
--
-- return 1;
--}
--
--static int __init kgdb_opt_kgdbeth_remotemac(char *str)
--{
-- return parse_hw_addr(str, kgdb_remotemac);
--}
--static int __init kgdb_opt_kgdbeth_localmac(char *str)
--{
-- return parse_hw_addr(str, kgdb_localmac);
--}
--
--
--__setup("gdbeth=", kgdb_opt_kgdbeth);
--__setup("gdbeth_remoteip=", kgdb_opt_kgdbeth_remoteip);
--__setup("gdbeth_listenport=", kgdb_opt_kgdbeth_listenport);
--__setup("gdbeth_remotemac=", kgdb_opt_kgdbeth_remotemac);
--__setup("gdbeth_localmac=", kgdb_opt_kgdbeth_localmac);
--
-Index: linux-2.6.0-test6/arch/i386/lib/kgdb_serial.c
-===================================================================
---- linux-2.6.0-test6.orig/arch/i386/lib/kgdb_serial.c 2003-10-12 13:12:22.000000000 +0800
-+++ linux-2.6.0-test6/arch/i386/lib/kgdb_serial.c 2003-10-12 13:12:25.000000000 +0800
-@@ -386,7 +386,7 @@
- static int __init
- kgdb_enable_ints(void)
- {
-- if (kgdb_eth != -1) {
-+ if (kgdboe) {
- return 0;
- }
- if (gdb_async_info == NULL) {
-Index: linux-2.6.0-test6/drivers/net/Makefile
-===================================================================
---- linux-2.6.0-test6.orig/drivers/net/Makefile 2003-10-12 13:12:22.000000000 +0800
-+++ linux-2.6.0-test6/drivers/net/Makefile 2003-10-12 13:12:25.000000000 +0800
-@@ -32,8 +32,6 @@
-
- obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
-
--obj-$(CONFIG_KGDB) += kgdb_eth.o
--
- obj-$(CONFIG_DGRS) += dgrs.o
- obj-$(CONFIG_RCPCI) += rcpci.o
- obj-$(CONFIG_VORTEX) += 3c59x.o
-@@ -109,6 +107,8 @@
- ifeq ($(CONFIG_SLIP_COMPRESSED),y)
- obj-$(CONFIG_SLIP) += slhc.o
- endif
-+# Must come after all NICs it might use
-+obj-$(CONFIG_KGDB) += kgdb_eth.o
-
- obj-$(CONFIG_DUMMY) += dummy.o
- obj-$(CONFIG_DE600) += de600.o
-Index: linux-2.6.0-test6/include/asm-i386/kgdb.h
-===================================================================
---- linux-2.6.0-test6.orig/include/asm-i386/kgdb.h 2003-10-12 13:12:23.000000000 +0800
-+++ linux-2.6.0-test6/include/asm-i386/kgdb.h 2003-10-12 13:12:25.000000000 +0800
-@@ -21,17 +21,13 @@
-
- struct sk_buff;
-
--extern int kgdb_eth;
--extern unsigned kgdb_remoteip;
--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 kgdboe;
-+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 gdb_net_interrupt(struct sk_buff *skb);
-
- /*
- * GDB debug stub (or any debug stub) can point the 'linux_debug_hook'
-Index: linux-2.6.0-test6/Documentation/i386/kgdb/kgdbeth.txt
-===================================================================
---- linux-2.6.0-test6.orig/Documentation/i386/kgdb/kgdbeth.txt 2003-10-12 13:12:22.000000000 +0800
-+++ linux-2.6.0-test6/Documentation/i386/kgdb/kgdbeth.txt 2003-10-12 13:12:25.000000000 +0800
-@@ -6,16 +6,20 @@
-
- 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. Only a limited set of ethernet
--devices are supported right now, but adding support for new devices
--should not be too complicated. See "New Devices" below for details.
--
-+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
- -----------
-@@ -29,33 +33,25 @@
- Usage
- -----
-
--You need to use the following command-line options on the TARGET kernel:
--
-- gdbeth=DEVICENUM
-- gdbeth_remoteip=HOSTIPADDR
-- gdbeth_remotemac=REMOTEMAC
-- gdbeth_localmac=LOCALMAC
--
--kgdbeth=DEVICENUM sets the ethernet device number to listen on for
--debugging packets. e.g. kgdbeth=0 listens on eth0.
--
--kgdbeth_remoteip=HOSTIPADDR sets the IP address of the HOST machine.
--Only packets originating from this IP address will be accepted by the
--debugger. e.g. kgdbeth_remoteip=192.168.2.2
-+You need to use the following command-line option on the TARGET kernel:
-
--kgdbeth_remotemac=REMOTEMAC sets the ethernet address of the HOST machine.
--e.g. kgdbeth_remotemac=00:07:70:12:4E:F5
-+ kgdboe=[tgt-port]@<tgt-ip>/[dev],[host-port]@<host-ip>/[host-macaddr]
-
--kgdbeth_localmac=LOCALMAC sets the ethernet address of the TARGET machine.
--e.g. kgdbeth_localmac=00:10:9F:18:21:3C
-+ 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)
-
--You can also set the following command-line option on the TARGET kernel:
-+ examples:
-
-- kgdbeth_listenport=PORT
-+ kgdboe=7000@192.168.0.1/wlan0,7001@192.168.0.2/00:05:3C:04:47:5D
-+ kgdboe=@192.168.0.1/,@192.168.0.2/
-
--kgdbeth_listenport sets the UDP port to listen on for gdb debugging
--packets. The default value is "6443". e.g. kgdbeth_listenport=7654
--causes the kernel to listen on UDP port 7654 for debugging packets.
-+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:
-@@ -72,47 +68,16 @@
-
- You can now continue as if you were debugging over a serial line.
-
--Observations
--------------
--
--I've used this with NFS and various other network applications (ssh,
--etc.) and it's doesn't appear to interfere with their operation in
--any way. It doesn't seem to effect the NIC it uses - i.e. you don't
--need a dedicated NIC for this.
--
- Limitations
- -----------
-
--In the inital release of this code you _must_ break into the system with the
--debugger by hand, early after boot, as described above.
--
--Otherwise, the first time the kernel tries to enter the debugger (say, via an
--oops or a BUG), the kgdb stub will doublefault and die because things aren't
--fully set up yet.
--
--Supported devices
-------------------
--
--Right now, the following drivers are supported:
--
-- e100 driver (drivers/net/e100/*)
-- 3c59x driver (drivers/net/3c59x.c)
--
--
--New devices
-------------
--
--Supporting a new device is straightforward. Just add a "poll" routine to
--the driver and hook it into the poll_controller field in the netdevice
--structure. For an example, look in drivers/net/3c59x.c and search
--for CONFIG_KGDB (two places.)
--
--The poll routine is usually quite simple - it's usually enough to just
--disable interrupts, call the device's interrupt routine and re-enable
--interrupts again.
--
-+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>.
-+Send bug reports to Robert Walsh <rjwalsh@durables.org> Matt
-+Mackall <mpm@selenic.com> and wangdi <wangdi@clusterfs.com>.
+++ /dev/null
-Index: linux-2.6.0-test1/arch/i386/kernel/kgdb_stub.c
-===================================================================
---- linux-2.6.0-test1.orig/arch/i386/kernel/kgdb_stub.c 2003-09-02 14:16:10.000000000 +0800
-+++ linux-2.6.0-test1/arch/i386/kernel/kgdb_stub.c 2003-09-02 14:32:02.000000000 +0800
-@@ -30,6 +30,7 @@
- *
- * Written by: Glenn Engel $
- * Updated by: David Grothe <dave@gcom.com>
-+ * Updated by: Robert Walsh <rjwalsh@durables.org>
- * ModuleState: Experimental $
- *
- * NOTES: See Below $
-@@ -112,6 +113,7 @@
- #include <asm/processor.h>
- #include <linux/irq.h>
- #include <asm/desc.h>
-+#include <linux/inet.h>
-
- /************************************************************************
- *
-@@ -122,8 +124,16 @@
- /* 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 */
-+extern void gdb_eth_set_trapmode(int);
-+extern void gdb_eth_reply_arp(void); /*send arp request */
-+extern int gdb_eth_is_initializing;
-+
-
- /************************************************************************/
- /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-@@ -264,6 +274,35 @@
- }
-
- /*
-+ * I/O dispatch functions...
-+ * Based upon gdb_eth, either call the ethernet
-+ * handler or the serial one..
-+ */
-+void putDebugChar(int c)
-+{
-+ if (gdb_eth == -1)
-+ tty_putDebugChar(c);
-+ else
-+ eth_putDebugChar(c);
-+}
-+
-+int getDebugChar(void)
-+{
-+ if (gdb_eth == -1)
-+ return tty_getDebugChar();
-+ else
-+ return eth_getDebugChar();
-+}
-+
-+void flushDebugChar(void)
-+{
-+ if (gdb_eth == -1)
-+ 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
-@@ -389,7 +428,6 @@
- xmitcsum = -1;
-
- count = 0;
--
- /* now, read until a # or end of buffer is found */
- while (count < BUFMAX) {
- ch = getDebugChar() & 0x7f;
-@@ -429,6 +467,7 @@
-
- if (remote_debug)
- printk("R:%s\n", buffer);
-+ flushDebugChar();
- }
-
- /* send the packet in buffer. */
-@@ -441,25 +480,64 @@
- 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;
-- }
-
-- putDebugChar('#');
-- putDebugChar(hexchars[checksum >> 4]);
-- putDebugChar(hexchars[checksum % 16]);
--
-- } while ((getDebugChar() & 0x7f) != '+');
-+ if (gdb_eth == -1){
-+ 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 byts each time */
-+#define MAX_SEND_COUNT 30
-+ int send_count=0, i=0;
-+ char send_buf[30];
-
-+ 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];
-@@ -1143,6 +1221,13 @@
- print_regs(®s);
- return (0);
- }
-+ /*
-+ * If we're using eth mode, set the 'mode' in the netdevice.
-+ */
-+
-+ if(gdb_eth != -1) {
-+ gdb_eth_set_trapmode(1);
-+ }
-
- kgdb_local_irq_save(flags);
-
-@@ -1156,8 +1241,8 @@
- * NMI and will wait there for the following spin locks to be
- * released.
- */
-+
- #ifdef CONFIG_SMP
--
- #if 0
- if (cpu_callout_map & ~MAX_CPU_MASK) {
- printk("kgdb : too many cpus, possibly not mapped"
-@@ -1372,6 +1457,7 @@
- gdb_i386vector = exceptionVector;
- gdb_i386errcode = err_code;
- kgdb_info.called_from = __builtin_return_address(0);
-+
- #ifdef CONFIG_SMP
- /*
- * OK, we can now communicate, lets tell gdb about the sync.
-@@ -1400,8 +1486,13 @@
- remcomOutBuffer[2] = hexchars[signo % 16];
- remcomOutBuffer[3] = 0;
-
-- putpacket(remcomOutBuffer);
-+ if (gdb_eth_is_initializing) {
-+ gdb_eth_is_initializing = 0;
-+ } else {
-+ putpacket(remcomOutBuffer);
-+ }
-
-+ gdb_eth_reply_arp();
- while (1 == 1) {
- error = 0;
- remcomOutBuffer[0] = 0;
-@@ -1419,7 +1510,9 @@
- remote_debug ? "on" : "off");
- break;
- case 'g': /* return the value of the CPU registers */
-+
- get_gdb_regs(usethread, ®s, gdb_regs);
-+
- mem2hex((char *) gdb_regs,
- remcomOutBuffer, NUMREGBYTES, 0);
- break;
-@@ -1536,6 +1629,10 @@
-
- newPC = regs.eip;
-
-+ if (gdb_eth != -1) {
-+ gdb_eth_set_trapmode(0);
-+ }
-+
- /* clear the trace bit */
- regs.eflags &= 0xfffffeff;
-
-@@ -1856,9 +1953,7 @@
- kgdb_local_irq_restore(flags);
- return (0);
- }
--#if 0
--exit_just_unlock:
--#endif
-+ exit_just_unlock:
- #endif
- /* Release kgdb spinlock */
- KGDB_SPIN_UNLOCK(&kgdb_spinlock);
-@@ -2213,3 +2308,72 @@
- 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 __init kgdb_opt_gdbeth(char *str)
-+{
-+ gdb_eth = simple_strtoul(str,NULL,10);
-+ return 1;
-+}
-+
-+static int __init kgdb_opt_gdbeth_remote(char *str)
-+{
-+ gdb_ethremote = in_aton(str);
-+ return 1;
-+}
-+
-+static int __init kgdb_opt_gdbeth_listen(char *str)
-+{
-+ gdb_listenport = simple_strtoul(str,NULL,10);
-+ return 1;
-+}
-+
-+static int __init kgdb_opt_gdbeth_hwaddr(char *str)
-+{
-+ int i;
-+ char *p;
-+
-+ p = str;
-+ i = 0;
-+ while(1)
-+ {
-+ unsigned int c;
-+ sscanf(p, "%x:", &c);
-+ gdb_sendhwaddr[i++] = c;
-+ while((*p != 0) && (*p != ':'))
-+ p++;
-+ if (*p == 0)
-+ break;
-+ p++;
-+ }
-+
-+ return 1;
-+}
-+static int __init kgdb_opt_gdbeth_rchwaddr(char *str)
-+{
-+ int i;
-+ char *p;
-+
-+ p = str;
-+ i = 0;
-+ while(1)
-+ {
-+ unsigned int c;
-+ sscanf(p, "%x:", &c);
-+ gdb_receivehwaddr[i++] = c;
-+ while((*p != 0) && (*p != ':'))
-+ p++;
-+ if (*p == 0)
-+ break;
-+ p++;
-+ }
-+
-+ return 1;
-+}
-+
-+
-+__setup("gdbeth=", kgdb_opt_gdbeth);
-+__setup("gdbeth_remote=", kgdb_opt_gdbeth_remote);
-+__setup("gdbeth_listenport=", kgdb_opt_gdbeth_listen);
-+__setup("gdbeth_sendhwaddr=", kgdb_opt_gdbeth_hwaddr);
-+__setup("gdbeth_receivehwaddr=", kgdb_opt_gdbeth_rchwaddr);
-+
-Index: linux-2.6.0-test1/arch/i386/lib/kgdb_serial.c
-===================================================================
---- linux-2.6.0-test1.orig/arch/i386/lib/kgdb_serial.c 2003-09-02 14:16:11.000000000 +0800
-+++ linux-2.6.0-test1/arch/i386/lib/kgdb_serial.c 2003-09-02 14:32:02.000000000 +0800
-@@ -155,12 +155,12 @@
- * 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 +226,7 @@
- /*
- * 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 +331,7 @@
- }
-
- /*
-- * 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 +345,11 @@
- /* 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 +375,7 @@
- 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 +383,9 @@
- static int __init
- kgdb_enable_ints(void)
- {
-+ if (gdb_eth != -1) {
-+ return 0;
-+ }
- if (gdb_async_info == NULL) {
- gdb_hook_interrupt(&local_info, 1);
- }
-@@ -444,7 +447,7 @@
- }
-
- /*
-- * 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 +455,9 @@
- * 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 +483,14 @@
- }
- }
-
--} /* putDebugChar */
-+} /* tty_putDebugChar */
-+
-+/*
-+ * This does nothing for the serial port, since it doesn't buffer.
-+ */
-+
-+void tty_flushDebugChar(void)
-+{
-+}
-
- module_init(kgdb_enable_ints);
-Index: linux-2.6.0-test1/include/linux/netdevice.h
-===================================================================
---- linux-2.6.0-test1.orig/include/linux/netdevice.h 2003-09-02 14:29:27.000000000 +0800
-+++ linux-2.6.0-test1/include/linux/netdevice.h 2003-09-02 14:32:02.000000000 +0800
-@@ -469,6 +469,11 @@
-
- /* statistics sub-directory */
- struct kobject stats_kobj;
-+
-+#ifdef CONFIG_KGDB
-+ int kgdb_is_trapped;
-+ void (*kgdb_net_poll_rx)(struct net_device *);
-+#endif
- };
-
- #define SET_MODULE_OWNER(dev) do { } while (0)
-@@ -524,6 +529,11 @@
- extern struct net_device *dev_get_by_index(int ifindex);
- extern struct net_device *__dev_get_by_index(int ifindex);
- extern int dev_restart(struct net_device *dev);
-+#ifdef CONFIG_KGDB
-+int gdb_eth_is_trapped(void);
-+int gdb_net_interrupt(struct sk_buff *skb);
-+void gdb_send_arp_request(void);
-+#endif
-
- typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len);
- extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf);
-@@ -582,12 +592,20 @@
-
- static inline void netif_wake_queue(struct net_device *dev)
- {
-+#ifdef CONFIG_KGDB
-+ if (gdb_eth_is_trapped())
-+ return;
-+#endif
- if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state))
- __netif_schedule(dev);
- }
-
- static inline void netif_stop_queue(struct net_device *dev)
- {
-+#ifdef CONFIG_KGDB
-+ if (gdb_eth_is_trapped())
-+ return;
-+#endif
- set_bit(__LINK_STATE_XOFF, &dev->state);
- }
-
-Index: linux-2.6.0-test1/include/asm-i386/kgdb.h
-===================================================================
---- linux-2.6.0-test1.orig/include/asm-i386/kgdb.h 2003-09-02 14:16:20.000000000 +0800
-+++ linux-2.6.0-test1/include/asm-i386/kgdb.h 2003-09-02 14:32:03.000000000 +0800
-@@ -18,6 +18,16 @@
- #ifndef BREAKPOINT
- #define BREAKPOINT asm(" int $3")
- #endif
-+
-+extern int gdb_eth;
-+extern unsigned gdb_ethremote;
-+extern unsigned short gdb_listenport;
-+extern unsigned char gdb_sendhwaddr[6];
-+extern unsigned char gdb_receivehwaddr[6];
-+
-+extern int gdb_tty_hook(void);
-+extern int gdb_eth_hook(void);
-+
- /*
- * 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
-@@ -34,6 +44,7 @@
- extern int kgdb_handle_exception(int trapno,
- int signo, int err_code, struct pt_regs *regs);
- extern int in_kgdb(struct pt_regs *regs);
-+extern void kgdb_null(void);
-
- #ifdef CONFIG_KGDB_TS
- void kgdb_tstamp(int line, char *source, int data0, int data1);
-Index: linux-2.6.0-test1/drivers/net/e100/e100_main.c
-===================================================================
---- linux-2.6.0-test1.orig/drivers/net/e100/e100_main.c 2003-09-02 14:29:27.000000000 +0800
-+++ linux-2.6.0-test1/drivers/net/e100/e100_main.c 2003-09-02 14:32:03.000000000 +0800
-@@ -567,6 +567,15 @@
- }
- #endif
-
-+#ifdef CONFIG_KGDB
-+static void e100_rx_poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ e100intr(dev->irq, (void *)dev, 0);
-+ enable_irq(dev->irq);
-+}
-+#endif
-+
- static int __devinit
- e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
- {
-@@ -662,7 +671,9 @@
- dev->set_multicast_list = &e100_set_multi;
- dev->set_mac_address = &e100_set_mac;
- dev->do_ioctl = &e100_ioctl;
--
-+#ifdef CONFIG_KGDB
-+ dev->kgdb_net_poll_rx = e100_rx_poll;
-+#endif
- if (bdp->flags & USE_IPCB)
- dev->features = NETIF_F_SG | NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-Index: linux-2.6.0-test1/drivers/net/3c59x.c
-===================================================================
---- linux-2.6.0-test1.orig/drivers/net/3c59x.c 2003-09-02 14:29:27.000000000 +0800
-+++ linux-2.6.0-test1/drivers/net/3c59x.c 2003-09-02 14:32:03.000000000 +0800
-@@ -1063,6 +1063,22 @@
- return rc;
- }
-
-+#ifdef CONFIG_KGDB
-+static void vortex_rx_poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ vortex_interrupt(dev->irq, (void *)dev, 0);
-+ enable_irq(dev->irq);
-+}
-+
-+static void boomerang_rx_poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ boomerang_interrupt(dev->irq, (void *)dev, 0);
-+ enable_irq(dev->irq);
-+}
-+#endif
-+
- /*
- * Start up the PCI/EISA device which is described by *gendev.
- * Return 0 on success.
-@@ -1449,6 +1465,14 @@
- dev->set_multicast_list = set_rx_mode;
- dev->tx_timeout = vortex_tx_timeout;
- dev->watchdog_timeo = (watchdog * HZ) / 1000;
-+#ifdef CONFIG_KGDB
-+ if (vp->full_bus_master_tx) {
-+ dev->kgdb_net_poll_rx = boomerang_rx_poll;
-+ } else {
-+ dev->kgdb_net_poll_rx = vortex_rx_poll;
-+ }
-+#endif
-+
- #ifdef HAVE_POLL_CONTROLLER
- dev->poll_controller = &vorboom_poll;
- #endif
-Index: linux-2.6.0-test1/drivers/net/Makefile
-===================================================================
---- linux-2.6.0-test1.orig/drivers/net/Makefile 2003-07-14 11:32:32.000000000 +0800
-+++ linux-2.6.0-test1/drivers/net/Makefile 2003-09-02 14:32:03.000000000 +0800
-@@ -32,6 +32,8 @@
-
- obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
-
-+obj-$(CONFIG_KGDB) += kgdb_eth.o
-+
- obj-$(CONFIG_DGRS) += dgrs.o
- obj-$(CONFIG_RCPCI) += rcpci.o
- obj-$(CONFIG_VORTEX) += 3c59x.o
-Index: linux-2.6.0-test1/drivers/net/kgdb_eth.c
-===================================================================
---- linux-2.6.0-test1.orig/drivers/net/kgdb_eth.c 2003-09-02 14:32:02.000000000 +0800
-+++ linux-2.6.0-test1/drivers/net/kgdb_eth.c 2003-09-02 21:41:42.000000000 +0800
-@@ -0,0 +1,547 @@
-+/*
-+ * 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.5 by Robert Walsh (rjwalsh@durables.org)
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/interrupt.h>
-+#include <linux/config.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/termios.h>
-+#include <linux/workqueue.h>
-+#include <asm/kgdb.h>
-+#include <linux/if_ether.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/delay.h>
-+#include <net/tcp.h>
-+#include <net/udp.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/segment.h>
-+#include <asm/bitops.h>
-+#include <asm/system.h>
-+#include <asm/irq.h>
-+#include <asm/atomic.h>
-+
-+#undef PRNT /* define for debug printing */
-+
-+#define GDB_BUF_SIZE 512 /* power of 2, please */
-+
-+static char gdb_buf[GDB_BUF_SIZE] ;
-+static int gdb_buf_in_inx ;
-+static atomic_t gdb_buf_in_cnt ;
-+static int gdb_buf_out_inx ;
-+
-+extern void set_debug_traps(void) ; /* GDB routine */
-+extern void breakpoint(void);
-+
-+unsigned int gdb_ethremote = 0;
-+unsigned short gdb_listenport = 6443;
-+unsigned short gdb_sendport= 6442;
-+int gdb_eth = -1; /* Default tty mode */
-+unsigned char gdb_sendhwaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
-+unsigned char gdb_receivehwaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
-+int gdb_eth_is_initializing = 0;
-+int gdb_eth_debug = 0;
-+
-+struct net_device *gdb_netdevice = NULL;
-+
-+//static int initialized = -1;
-+//static struct work_struct irq_bp;
-+
-+static void bpwork_func(void *p)
-+{
-+ udelay(500);
-+ BREAKPOINT;
-+}
-+
-+static struct workqueue_struct *irq_bp;
-+DECLARE_WORK(bpwork, bpwork_func, NULL);
-+
-+/*
-+ * Get a char if available, return -1 if nothing available.
-+ * Empty the receive buffer first, then look at the interface hardware.
-+ */
-+static int read_char(void)
-+{
-+
-+ if (atomic_read(&gdb_buf_in_cnt) != 0) /* intr routine has q'd chars */
-+ {
-+ int chr ;
-+
-+ chr = gdb_buf[gdb_buf_out_inx++] ;
-+ gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ;
-+ atomic_dec(&gdb_buf_in_cnt) ;
-+ return chr;
-+ }
-+ return -1; // no data
-+} /* read_char */
-+
-+//static unsigned char daddr[6] = {0x00,0x06,0x25,0xA9,0x9F,0x6A};
-+//static unsigned char daddr[6] = {0x00,0x50,0xFC,0xB8,0x22,0x03};
-+//static unsigned char daddr[6] = {0x00,0x08,0x74,0x96,0x6D,0x9B};
-+//static unsigned char daddr[6] = {0x00,0x07,0xE9,0xD4,0xBE,0x85};
-+//static unsigned char daddr[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-+
-+/*
-+ * Wait until the interface can accept a char, then write it.
-+ */
-+static void write_buffer(char *buf, int len)
-+{
-+ int total_len, eth_len, ip_len, udp_len;
-+ struct in_device *in_dev;
-+ struct sk_buff *skb;
-+ struct udphdr *udph;
-+ struct iphdr *iph;
-+ struct ethhdr *eth;
-+
-+ if (!(in_dev = (struct in_device *) gdb_netdevice->ip_ptr))
-+ panic("No in_device available for interface!\n");
-+ if (!(in_dev->ifa_list))
-+ panic("No interface address set for interface!\n");
-+ udp_len = len + sizeof(struct udphdr);
-+ ip_len = eth_len = udp_len + sizeof(struct iphdr);
-+ total_len = eth_len + ETH_HLEN;
-+
-+ if (!(skb = alloc_skb(total_len, GFP_ATOMIC)))
-+ return;
-+
-+ atomic_set(&skb->users, 1);
-+ skb_reserve(skb, total_len - 1);
-+
-+ memcpy(skb->data , (unsigned char *) buf, len);
-+ skb->len += len;
-+
-+ udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
-+ udph->source = htons(gdb_listenport);
-+ udph->dest = htons(gdb_sendport);
-+ udph->len = htons(udp_len);
-+ udph->check = 0;
-+
-+ iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
-+ iph->version = 4;
-+ iph->ihl = 5;
-+ iph->tos = 0;
-+ iph->tot_len = htons(ip_len);
-+ iph->id = 0;
-+ iph->frag_off= 0;
-+ iph->ttl = 64;
-+ iph->protocol= IPPROTO_UDP;
-+ iph->check = 0;
-+ iph->saddr = in_dev->ifa_list->ifa_address;
-+ iph->daddr = gdb_ethremote;
-+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-+
-+ eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-+ eth->h_proto = htons(ETH_P_IP);
-+ memcpy(eth->h_source, gdb_sendhwaddr, gdb_netdevice->addr_len);
-+// memcpy(eth->h_dest, daddr, gdb_netdevice->addr_len);
-+ memcpy(eth->h_dest, gdb_receivehwaddr, gdb_netdevice->addr_len);
-+
-+#if 0
-+repeat_poll:
-+#endif
-+ spin_lock(&gdb_netdevice->xmit_lock);
-+ gdb_netdevice->xmit_lock_owner = smp_processor_id();
-+#if 0
-+ if (netif_queue_stopped(gdb_netdevice))
-+ {
-+ gdb_netdevice->xmit_lock_owner = -1;
-+ spin_unlock(&gdb_netdevice->xmit_lock);
-+ gdb_netdevice->poll_controller(gdb_netdevice);
-+ zap_completion_queue();
-+ goto repeat_poll;
-+ }
-+#endif
-+ gdb_netdevice->hard_start_xmit(skb, gdb_netdevice);
-+ gdb_netdevice->xmit_lock_owner = -1;
-+ spin_unlock(&gdb_netdevice->xmit_lock);
-+
-+ // kfree_skb(skb);
-+} /* write_char */
-+/* in interrupt state the target machine will not response the arp request */
-+
-+static struct sk_buff *send_skb = NULL;
-+void gdb_eth_reply_arp(void)
-+{
-+ if (send_skb){
-+#if 0
-+repeat_poll:
-+#endif
-+ spin_lock(&gdb_netdevice->xmit_lock);
-+ gdb_netdevice->xmit_lock_owner = smp_processor_id();
-+#if 0
-+ if (netif_queue_stopped(gdb_netdevice)){
-+ gdb_netdevice->xmit_lock_owner = -1;
-+ spin_unlock(&gdb_netdevice->xmit_lock);
-+ gdb_netdevice->poll_controller(gdb_netdevice);
-+ zap_completion_queue();
-+ goto repeat_poll;
-+ }
-+#endif
-+ gdb_netdevice->hard_start_xmit(send_skb, gdb_netdevice);
-+ gdb_netdevice->xmit_lock_owner = -1;
-+ spin_unlock(&gdb_netdevice->xmit_lock);
-+ send_skb = NULL;
-+
-+ }
-+}
-+static int make_arp_request( struct sk_buff *skb)
-+{
-+ struct arphdr *arp;
-+ unsigned char *arp_ptr;
-+ int type = ARPOP_REPLY;
-+ int ptype = ETH_P_ARP;
-+ u32 sip, tip;
-+ unsigned char *sha, *tha;
-+ struct in_device *in_dev = (struct in_device *) gdb_netdevice->ip_ptr;
-+ /*
-+ * No arp on this interface.
-+ */
-+ if (gdb_netdevice->flags &IFF_NOARP)
-+ return 0;
-+ if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
-+ (2 * gdb_netdevice->addr_len) +
-+ (2 * sizeof(u32)))))
-+ return 0;
-+
-+ skb->h.raw = skb->nh.raw = skb->data;
-+ arp = skb->nh.arph;
-+
-+ if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
-+ arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
-+ arp->ar_pro != htons(ETH_P_IP))
-+ return 0;
-+
-+/* Understand only these message types */
-+
-+ if (arp->ar_op != htons(ARPOP_REQUEST))
-+ return 0;
-+/*
-+ * Extract fields
-+ */
-+ arp_ptr= (unsigned char *)(arp+1);
-+ sha = arp_ptr;
-+ arp_ptr += gdb_netdevice->addr_len;
-+ memcpy(&sip, arp_ptr, 4);
-+ arp_ptr += 4;
-+ tha = arp_ptr;
-+ arp_ptr += gdb_netdevice->addr_len;
-+ memcpy(&tip, arp_ptr, 4);
-+ if (tip != in_dev->ifa_list->ifa_address){
-+ return 0;
-+ }
-+ if (gdb_ethremote != sip){
-+ return 0;
-+ }
-+/*
-+ * Check for bad requests for 127.x.x.x and requests for multicast
-+ * addresses. If this is one such, delete it.
-+ */
-+
-+ if (LOOPBACK(tip) || MULTICAST(tip))
-+ return 0;
-+
-+/*
-+ * reply the arp request
-+ */
-+ send_skb = alloc_skb(sizeof(struct arphdr)+ 2*(gdb_netdevice->addr_len+4)
-+ + LL_RESERVED_SPACE(gdb_netdevice), GFP_ATOMIC);
-+ if (send_skb == NULL)
-+ return 0;
-+
-+ skb_reserve(send_skb, LL_RESERVED_SPACE(gdb_netdevice));
-+ send_skb->nh.raw = send_skb->data;
-+ arp = (struct arphdr *) skb_put(send_skb,sizeof(struct arphdr) + 2*(gdb_netdevice->addr_len+4));
-+ send_skb->dev = gdb_netdevice;
-+ send_skb->protocol = htons(ETH_P_ARP);
-+
-+ /*
-+ * Fill the device header for the ARP frame
-+ */
-+ if (gdb_netdevice->hard_header &&
-+ gdb_netdevice->hard_header(send_skb, gdb_netdevice, ptype, gdb_receivehwaddr, gdb_sendhwaddr, send_skb->len) < 0){
-+ kfree_skb(send_skb);
-+ return 0;
-+ }
-+ /*
-+ * Fill out the arp protocol part.
-+ *
-+ * we only support ethernet device type,
-+ * which (according to RFC 1390) should always equal 1 (Ethernet).
-+ */
-+ arp->ar_hrd = htons(gdb_netdevice->type);
-+ arp->ar_pro = htons(ETH_P_IP);
-+
-+ arp->ar_hln = gdb_netdevice->addr_len;
-+ arp->ar_pln = 4;
-+ arp->ar_op = htons(type);
-+
-+ arp_ptr=(unsigned char *)(arp+1);
-+
-+ memcpy(arp_ptr, gdb_netdevice->dev_addr, gdb_netdevice->addr_len);
-+ arp_ptr += gdb_netdevice->addr_len;
-+ memcpy(arp_ptr, &tip, 4);
-+ arp_ptr += 4;
-+ memcpy(arp_ptr, gdb_sendhwaddr, gdb_netdevice->addr_len);
-+ arp_ptr+=gdb_netdevice->addr_len;
-+ memcpy(arp_ptr, &sip, 4);
-+ return 0;
-+}
-+/*
-+ * Accept an skbuff from net_device layer and
-+ * add the payload onto gdb buffer
-+ *
-+ * When the gdb stub routine 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
-+ * writes one byte after waiting for the interface to become
-+ * ready.
-+ *
-+ * The debug stubs like to run with interrupts disabled since,
-+ * after all, they run as a consequence of a breakpoint in
-+ * the kernel.
-+ *
-+ * NOTE: Return value of 1 means it was for us and is an
-+ * indication to the calling driver to destroy the sk_buff
-+ * and not send it up the stack
-+ */
-+
-+int gdb_net_interrupt(struct sk_buff *skb)
-+{
-+ unsigned char chr;
-+ struct iphdr *iph = (struct iphdr*)skb->data;
-+ struct udphdr *udph= (struct udphdr*)(skb->data+(iph->ihl<<2));
-+ unsigned char *data = (unsigned char *) udph + sizeof(struct udphdr);
-+ int len;
-+ int i;
-+
-+ if ((gdb_eth != -1) && (!gdb_netdevice) &&
-+ (iph->protocol == IPPROTO_UDP) &&
-+ (be16_to_cpu(udph->dest) == gdb_listenport)) {
-+ gdb_sendport = be16_to_cpu(udph->source);
-+
-+ while(gdb_eth_is_initializing);
-+ if(!gdb_netdevice)
-+ gdb_eth_hook();
-+ if (!gdb_netdevice) {
-+ /* Lets not even try again. */
-+ gdb_eth = -1;
-+ return 0;
-+ }
-+ }
-+ if (!gdb_netdevice) {
-+ return 0;
-+ }
-+ if (skb->protocol == __constant_htons(ETH_P_ARP) && !send_skb){
-+ make_arp_request(skb);
-+ return 0;
-+ }
-+ if (iph->protocol != IPPROTO_UDP)
-+ return 0;
-+
-+ if (be16_to_cpu(udph->dest) != gdb_listenport)
-+ return 0;
-+
-+ len = be16_to_cpu(iph->tot_len) - (sizeof(struct udphdr) +
-+ sizeof(struct iphdr));
-+ for (i = 0; i < len; i++)
-+ {
-+ chr = *data++;
-+ if (chr == 3)
-+ {
-+ queue_work(irq_bp, &bpwork);
-+// flush_workqueue(irq_bp);
-+ continue;
-+/*
-+ if (!in_interrupt())
-+ {
-+ breakpoint();
-+ }
-+ else
-+ {
-+ schedule_work(&irq_bp); // XXX: is this really necessary??
-+ }
-+ continue;
-+*/
-+ }
-+ if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE)
-+ { /* buffer overflow, clear it */
-+ gdb_buf_in_inx = 0 ;
-+ atomic_set(&gdb_buf_in_cnt, 0) ;
-+ gdb_buf_out_inx = 0 ;
-+ break ;
-+ }
-+ gdb_buf[gdb_buf_in_inx++] = chr ;
-+ gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ;
-+ atomic_inc(&gdb_buf_in_cnt) ;
-+ }
-+
-+ return 1;
-+} /* gdb_interrupt */
-+
-+
-+int gdb_eth_hook(void)
-+{
-+ char gdb_netdev[16];
-+ extern void kgdb_respond_ok(void);
-+
-+ if (gdb_sendhwaddr[0] == 0xff)
-+ panic("ERROR! 'gdbeth_sendhwaddr' option not set!\n");
-+ if (gdb_receivehwaddr[0] == 0xff)
-+ panic("ERROR! 'gdbeth_receivehwaddr' option not set!\n");
-+ if (gdb_ethremote == 0)
-+ panic("ERROR! 'gdbeth_remote' option not set!\n");
-+
-+ sprintf(gdb_netdev,"eth%d",gdb_eth);
-+
-+#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
-+ for (gdb_netdevice = dev_base;
-+ gdb_netdevice != NULL;
-+ gdb_netdevice = gdb_netdevice->next){
-+ if (strncmp(gdb_netdevice->name, gdb_netdev, IFNAMSIZ) == 0)
-+ break;
-+ }
-+ if (!gdb_netdevice){
-+ printk("KGDB NET : Unable to find interface %s\n",gdb_netdev);
-+ return -ENODEV;
-+ }
-+
-+ /*
-+ * Call GDB routine to setup the exception vectors for the debugger
-+ */
-+ set_debug_traps() ;
-+
-+ /*
-+ * Call the breakpoint() routine in GDB to start the debugging
-+ * session.
-+ */
-+ if (gdb_eth_debug){
-+ printk(KERN_INFO "Waiting for remote gdb connection from %x on local port %d\n",
-+ gdb_ethremote, gdb_listenport);
-+ printk(KERN_INFO "We are sending on port %d to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-+ gdb_sendport,
-+ gdb_sendhwaddr[0],
-+ gdb_sendhwaddr[1],
-+ gdb_sendhwaddr[2],
-+ gdb_sendhwaddr[3],
-+ gdb_sendhwaddr[4],
-+ gdb_sendhwaddr[5]);
-+ printk("Connected.\n");
-+ }
-+ gdb_eth_is_initializing = 1;
-+ queue_work(irq_bp, &bpwork);
-+ return 0;
-+} /* gdb_hook_interrupt2 */
-+
-+/*
-+ * 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
-+ * interface connection then it returns a bogus value which will
-+ * almost certainly cause the system to hang.
-+ */
-+int eth_getDebugChar(void)
-+{
-+ volatile int chr ;
-+
-+ while((chr = read_char()) < 0)
-+ {
-+ if (send_skb){
-+ gdb_eth_reply_arp();
-+ }
-+ if (gdb_netdevice->kgdb_net_poll_rx)
-+ gdb_netdevice->kgdb_net_poll_rx(gdb_netdevice);
-+ else
-+ {
-+ printk("KGDB NET: Error - Device %s is not supported!\n",
-+ gdb_netdevice->name);
-+ panic("Please add support for kgdb net to this driver");
-+ }
-+ }
-+ return chr;
-+
-+} /* eth_getDebugChar */
-+
-+#define ETH_QUEUE_SIZE 256
-+static char eth_queue[ETH_QUEUE_SIZE];
-+static int outgoing_queue;
-+
-+void eth_flushDebugChar(void)
-+{
-+ if(outgoing_queue) {
-+ write_buffer(eth_queue, outgoing_queue);
-+
-+ outgoing_queue = 0;
-+ }
-+}
-+
-+static void put_char_on_queue(int chr)
-+{
-+ eth_queue[outgoing_queue++] = chr;
-+ if(outgoing_queue == ETH_QUEUE_SIZE)
-+ {
-+ eth_flushDebugChar();
-+ }
-+}
-+
-+/*
-+ * eth_putDebugChar
-+ *
-+ * This is a GDB stub routine. It waits until the interface is ready
-+ * to transmit a char and then sends it.
-+ */
-+void eth_putDebugChar(int chr)
-+{
-+ if (gdb_eth_debug)
-+ printk(KERN_INFO "eth_putDebugChar: chr=%02x '%c'\n", chr,
-+ chr > ' ' && chr < 0x7F ? chr : ' ') ;
-+ put_char_on_queue(chr) ; /* this routine will wait */
-+} /* putDebugChar */
-+
-+void gdb_eth_set_trapmode(int mode)
-+{
-+ if (!gdb_netdevice)
-+ return;
-+ gdb_netdevice->kgdb_is_trapped = mode;
-+}
-+
-+int gdb_eth_is_trapped()
-+{
-+ if (!gdb_netdevice)
-+ return 0;
-+ return gdb_netdevice->kgdb_is_trapped;
-+}
-+
-+static int __init
-+kgdb_eth_init(void)
-+{
-+ irq_bp = create_workqueue("kgdb");
-+ return 0;
-+}
-+
-+module_init(kgdb_eth_init);
-Index: linux-2.6.0-test1/net/core/dev.c
-===================================================================
---- linux-2.6.0-test1.orig/net/core/dev.c 2003-09-02 14:29:27.000000000 +0800
-+++ linux-2.6.0-test1/net/core/dev.c 2003-09-02 14:32:03.000000000 +0800
-@@ -188,7 +188,9 @@
- extern int netdev_sysfs_init(void);
- extern int netdev_register_sysfs(struct net_device *);
- extern void netdev_unregister_sysfs(struct net_device *);
--
-+#ifdef CONFIG_KGDB
-+extern int gdb_net_interrupt(struct sk_buff *skb);
-+#endif
-
- /*******************************************************************************
-
-@@ -1349,6 +1351,21 @@
- struct softnet_data *queue;
- unsigned long flags;
-
-+#ifdef CONFIG_KGDB
-+ /* See if kgdb_eth wants this packet */
-+ if (!gdb_net_interrupt(skb)) {
-+ /* No.. if we're 'trapped' then junk it */
-+ if (gdb_eth_is_trapped()) {
-+ kfree_skb(skb);
-+ return NET_RX_DROP;
-+ }
-+ } else {
-+ /* kgdb_eth ate the packet... drop it silently */
-+ kfree_skb(skb);
-+ return NET_RX_DROP;
-+ }
-+#endif
-+
-
- /*
- * The code is rearranged so that the path is the most
+++ /dev/null
- l-mpm/arch/i386/kernel/irq.c | 15
- l-mpm/include/asm-i386/irq.h | 1
- l-mpm/include/linux/netdevice.h | 22 -
- l-mpm/include/linux/netpoll.h | 37 ++
- l-mpm/net/Kconfig | 3
- l-mpm/net/core/Makefile | 1
- l-mpm/net/core/dev.c | 22 -
- l-mpm/net/core/netpoll.c | 632 ++++++++++++++++++++++++++++++++++++++++
- 8 files changed, 707 insertions(+), 26 deletions(-)
-
-Index: linux-2.6.0-test6/net/core/netpoll.c
-===================================================================
---- linux-2.6.0-test6.orig/net/core/netpoll.c 2003-10-07 16:08:51.000000000 +0800
-+++ linux-2.6.0-test6/net/core/netpoll.c 2003-10-09 20:40:07.769057232 +0800
-@@ -0,0 +1,633 @@
-+/*
-+ * Common framework for low-level network console, dump, and debugger code
-+ *
-+ * Sep 8 2003 Matt Mackall <mpm@selenic.com>
-+ */
-+
-+#include <linux/smp_lock.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/string.h>
-+#include <linux/inetdevice.h>
-+#include <linux/inet.h>
-+#include <linux/interrupt.h>
-+#include <linux/netpoll.h>
-+#include <linux/sched.h>
-+#include <net/tcp.h>
-+#include <net/udp.h>
-+
-+/*
-+ * We maintain a small pool of fully-sized skbs, to make sure the
-+ * message gets out even in extreme OOM situations.
-+ */
-+
-+#define MAX_SKBS 32
-+#define MAX_UDP_CHUNK 1460
-+
-+static spinlock_t skb_list_lock = SPIN_LOCK_UNLOCKED;
-+static int nr_skbs;
-+static struct sk_buff *skbs;
-+
-+static spinlock_t rx_list_lock = SPIN_LOCK_UNLOCKED;
-+static LIST_HEAD(rx_list);
-+
-+static int trapped;
-+
-+#define MAX_SKB_SIZE \
-+ (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
-+ sizeof(struct iphdr) + sizeof(struct ethhdr))
-+
-+static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
-+ unsigned short ulen, u32 saddr, u32 daddr)
-+{
-+ if (uh->check == 0)
-+ return 0;
-+
-+ if (skb->ip_summed == CHECKSUM_HW)
-+ return csum_tcpudp_magic(
-+ saddr, daddr, ulen, IPPROTO_UDP, skb->csum);
-+
-+ skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
-+
-+ return csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
-+}
-+
-+void netpoll_poll(struct netpoll *np)
-+{
-+ int budget = 1;
-+
-+ if(!np || !np->dev || !(np->dev->flags & IFF_UP))
-+ return;
-+
-+ disable_irq(np->dev->irq);
-+
-+ /* Process pending work on NIC */
-+ np->irqfunc(np->dev->irq, np->dev, 0);
-+
-+ /* If scheduling is stopped, tickle NAPI bits */
-+ if(trapped && np->dev->poll &&
-+ test_bit(__LINK_STATE_RX_SCHED, &np->dev->state))
-+ np->dev->poll(np->dev, &budget);
-+
-+ enable_irq(np->dev->irq);
-+}
-+
-+static void refill_skbs(void)
-+{
-+ struct sk_buff *skb;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&skb_list_lock, flags);
-+ while (nr_skbs < MAX_SKBS) {
-+ skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
-+ if (!skb)
-+ break;
-+
-+ skb->next = skbs;
-+ skbs = skb;
-+ nr_skbs++;
-+ }
-+ spin_unlock_irqrestore(&skb_list_lock, flags);
-+}
-+
-+static void zap_completion_queue(void)
-+{
-+ unsigned long flags;
-+ struct softnet_data *sd = &get_cpu_var(softnet_data);
-+
-+ if (sd->completion_queue) {
-+ struct sk_buff *clist;
-+
-+ local_irq_save(flags);
-+ clist = sd->completion_queue;
-+ sd->completion_queue = NULL;
-+ local_irq_restore(flags);
-+
-+ while (clist != NULL) {
-+ struct sk_buff *skb = clist;
-+ clist = clist->next;
-+ __kfree_skb(skb);
-+ }
-+ }
-+
-+ put_cpu_var(softnet_data);
-+}
-+
-+static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve)
-+{
-+ int once = 1, count = 0;
-+ unsigned long flags;
-+ struct sk_buff *skb = NULL;
-+
-+repeat:
-+ zap_completion_queue();
-+ if (nr_skbs < MAX_SKBS)
-+ refill_skbs();
-+
-+ skb = alloc_skb(len, GFP_ATOMIC);
-+
-+ if (!skb) {
-+ spin_lock_irqsave(&skb_list_lock, flags);
-+ skb = skbs;
-+ if (skb)
-+ skbs = skb->next;
-+ skb->next = NULL;
-+ nr_skbs--;
-+ spin_unlock_irqrestore(&skb_list_lock, flags);
-+ }
-+
-+ if(!skb) {
-+ count++;
-+ if (once && (count == 1000000)) {
-+ printk("out of netpoll skbs!\n");
-+ once = 0;
-+ }
-+ netpoll_poll(np);
-+ goto repeat;
-+ }
-+
-+ atomic_set(&skb->users, 1);
-+ skb_reserve(skb, reserve);
-+ return skb;
-+}
-+
-+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
-+{
-+ int status;
-+
-+repeat:
-+ if(!np || !np->dev || !(np->dev->flags & IFF_UP)) {
-+ __kfree_skb(skb);
-+ return;
-+ }
-+
-+ spin_lock(&np->dev->xmit_lock);
-+ np->dev->xmit_lock_owner = smp_processor_id();
-+
-+ if (netif_queue_stopped(np->dev)) {
-+ np->dev->xmit_lock_owner = -1;
-+ spin_unlock(&np->dev->xmit_lock);
-+
-+ netpoll_poll(np);
-+ zap_completion_queue();
-+ goto repeat;
-+ }
-+
-+ status = np->dev->hard_start_xmit(skb, np->dev);
-+ np->dev->xmit_lock_owner = -1;
-+ spin_unlock(&np->dev->xmit_lock);
-+
-+ /* transmit busy */
-+ if(status)
-+ goto repeat;
-+}
-+
-+void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
-+{
-+ int total_len, eth_len, ip_len, udp_len;
-+ struct sk_buff *skb;
-+ struct udphdr *udph;
-+ struct iphdr *iph;
-+ struct ethhdr *eth;
-+
-+ udp_len = len + sizeof(*udph);
-+ ip_len = eth_len = udp_len + sizeof(*iph);
-+ total_len = eth_len + ETH_HLEN;
-+
-+ skb = find_skb(np, total_len, total_len - len);
-+ if (!skb)
-+ return;
-+
-+ memcpy(skb->data, msg, len);
-+ skb->len += len;
-+
-+ udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
-+ udph->source = htons(np->local_port);
-+ udph->dest = htons(np->remote_port);
-+ udph->len = htons(udp_len);
-+ udph->check = 0;
-+
-+ iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
-+
-+ iph->version = 4;
-+ iph->ihl = 5;
-+ iph->tos = 0;
-+ iph->tot_len = htons(ip_len);
-+ iph->id = 0;
-+ iph->frag_off = 0;
-+ iph->ttl = 64;
-+ iph->protocol = IPPROTO_UDP;
-+ iph->check = 0;
-+ iph->saddr = htonl(np->local_ip);
-+ iph->daddr = htonl(np->remote_ip);
-+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-+
-+ eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-+
-+ eth->h_proto = htons(ETH_P_IP);
-+ memcpy(eth->h_source, np->local_mac, 6);
-+ memcpy(eth->h_dest, np->remote_mac, 6);
-+
-+ netpoll_send_skb(np, skb);
-+}
-+
-+static void arp_reply(struct sk_buff *skb)
-+{
-+ struct in_device *in_dev = (struct in_device *) skb->dev->ip_ptr;
-+ struct arphdr *arp;
-+ unsigned char *arp_ptr, *sha, *tha;
-+ int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
-+ u32 sip, tip;
-+ struct sk_buff *send_skb;
-+ unsigned long flags;
-+ struct list_head *p;
-+ struct netpoll *np = 0;
-+
-+ spin_lock_irqsave(&rx_list_lock, flags);
-+ list_for_each(p, &rx_list) {
-+ np = list_entry(p, struct netpoll, rx_list);
-+ if ( np->dev == skb->dev )
-+ break;
-+ np = 0;
-+ }
-+ spin_unlock_irqrestore(&rx_list_lock, flags);
-+
-+ if (!np) return;
-+
-+ /* No arp on this interface */
-+ if (!in_dev || skb->dev->flags & IFF_NOARP)
-+ return;
-+
-+ if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
-+ (2 * skb->dev->addr_len) +
-+ (2 * sizeof(u32)))))
-+ return;
-+
-+ skb->h.raw = skb->nh.raw = skb->data;
-+ arp = skb->nh.arph;
-+
-+ if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
-+ arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
-+ arp->ar_pro != htons(ETH_P_IP) ||
-+ arp->ar_op != htons(ARPOP_REQUEST))
-+ return;
-+
-+ arp_ptr= (unsigned char *)(arp+1);
-+ sha = arp_ptr;
-+ arp_ptr += skb->dev->addr_len;
-+ memcpy(&sip, arp_ptr, 4);
-+ arp_ptr += 4;
-+ tha = arp_ptr;
-+ arp_ptr += skb->dev->addr_len;
-+ memcpy(&tip, arp_ptr, 4);
-+
-+ /* Should we ignore arp? */
-+ if (tip != in_dev->ifa_list->ifa_address ||
-+ LOOPBACK(tip) || MULTICAST(tip))
-+ return;
-+
-+
-+ size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
-+ send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
-+ LL_RESERVED_SPACE(np->dev));
-+
-+ if (!send_skb)
-+ return;
-+
-+ send_skb->nh.raw = send_skb->data;
-+ arp = (struct arphdr *) skb_put(send_skb, size);
-+ send_skb->dev = skb->dev;
-+ send_skb->protocol = htons(ETH_P_ARP);
-+
-+ /* Fill the device header for the ARP frame */
-+
-+ if (np->dev->hard_header &&
-+ np->dev->hard_header(send_skb, skb->dev, ptype,
-+ np->remote_mac, np->local_mac,
-+ send_skb->len) < 0) {
-+ kfree_skb(send_skb);
-+ return;
-+ }
-+
-+ /*
-+ * Fill out the arp protocol part.
-+ *
-+ * we only support ethernet device type,
-+ * which (according to RFC 1390) should always equal 1 (Ethernet).
-+ */
-+
-+ arp->ar_hrd = htons(np->dev->type);
-+ arp->ar_pro = htons(ETH_P_IP);
-+ arp->ar_hln = np->dev->addr_len;
-+ arp->ar_pln = 4;
-+ arp->ar_op = htons(type);
-+
-+ arp_ptr=(unsigned char *)(arp + 1);
-+ memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);
-+ arp_ptr += np->dev->addr_len;
-+ memcpy(arp_ptr, &tip, 4);
-+ arp_ptr += 4;
-+ memcpy(arp_ptr, np->local_mac, np->dev->addr_len);
-+ arp_ptr += np->dev->addr_len;
-+ memcpy(arp_ptr, &sip, 4);
-+
-+ netpoll_send_skb(np, send_skb);
-+}
-+
-+static int rx_hook(struct sk_buff *skb)
-+{
-+ int proto, len, ulen;
-+ struct iphdr *iph;
-+ struct udphdr *uh;
-+ struct netpoll *np;
-+ struct list_head *p;
-+ unsigned long flags;
-+ int rx_hook_called = 0;
-+
-+ if (skb->dev->type != ARPHRD_ETHER)
-+ goto out;
-+
-+ /* check if netpoll clients need ARP */
-+ if (skb->protocol == __constant_htons(ETH_P_ARP) && trapped) {
-+ arp_reply(skb);
-+ return 1;
-+ }
-+
-+ proto = ntohs(skb->mac.ethernet->h_proto);
-+ if (proto != ETH_P_IP)
-+ goto out;
-+ if (skb->pkt_type == PACKET_OTHERHOST)
-+ goto out;
-+ if (skb_shared(skb))
-+ goto out;
-+
-+ iph = (struct iphdr *)skb->data;
-+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-+ goto out;
-+ if (iph->ihl < 5 || iph->version != 4)
-+ goto out;
-+ if (!pskb_may_pull(skb, iph->ihl*4))
-+ goto out;
-+ if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
-+ goto out;
-+
-+ len = ntohs(iph->tot_len);
-+ if (skb->len < len || len < iph->ihl*4)
-+ goto out;
-+
-+ if (iph->protocol != IPPROTO_UDP)
-+ goto out;
-+
-+ len -= iph->ihl*4;
-+ uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
-+ ulen = ntohs(uh->len);
-+
-+ if (ulen != len)
-+ goto out;
-+ if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0)
-+ goto out;
-+
-+ spin_lock_irqsave(&rx_list_lock, flags);
-+ list_for_each(p, &rx_list) {
-+ np = list_entry(p, struct netpoll, rx_list);
-+ if (np->dev && np->dev != skb->dev)
-+ continue;
-+ if (np->local_ip && np->local_ip != ntohl(iph->daddr))
-+ continue;
-+ if (np->remote_ip && np->remote_ip != ntohl(iph->saddr))
-+ continue;
-+ if (np->local_port && np->local_port != ntohs(uh->dest))
-+ continue;
-+
-+ if (np->rx_hook){
-+ np->rx_hook(np, ntohs(uh->source),
-+ (char *)(uh+1), ulen-sizeof(uh)-4);
-+ rx_hook_called = 1;
-+ }
-+ }
-+ spin_unlock_irqrestore(&rx_list_lock, flags);
-+
-+ if (rx_hook_called)
-+ return 1;
-+out:
-+ return trapped;
-+}
-+
-+int netpoll_parse_options(struct netpoll *np, char *opt)
-+{
-+ char *cur=opt, *delim;
-+
-+ if(*cur != '@') {
-+ if ((delim = strchr(cur, '@')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->local_port=simple_strtol(cur, 0, 10);
-+ cur=delim;
-+ }
-+ cur++;
-+ printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port);
-+
-+ if(*cur != '/') {
-+ if ((delim = strchr(cur, '/')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->local_ip=ntohl(in_aton(cur));
-+ cur=delim;
-+
-+ printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
-+ np->name, HIPQUAD(np->local_ip));
-+ }
-+ cur++;
-+
-+ if ( *cur != ',') {
-+ /* parse out dev name */
-+ if ((delim = strchr(cur, ',')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ strlcpy(np->dev_name, cur, sizeof(np->dev_name));
-+ cur=delim;
-+ }
-+ cur++;
-+
-+ printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name);
-+
-+ if ( *cur != '@' ) {
-+ /* dst port */
-+ if ((delim = strchr(cur, '@')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->remote_port=simple_strtol(cur, 0, 10);
-+ cur=delim;
-+ }
-+ cur++;
-+ printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port);
-+
-+ /* dst ip */
-+ if ((delim = strchr(cur, '/')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->remote_ip=ntohl(in_aton(cur));
-+ cur=delim+1;
-+
-+ printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",
-+ np->name, HIPQUAD(np->remote_ip));
-+
-+ if( *cur != 0 )
-+ {
-+ /* MAC address */
-+ if ((delim = strchr(cur, ':')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->remote_mac[0]=simple_strtol(cur, 0, 16);
-+ cur=delim+1;
-+ if ((delim = strchr(cur, ':')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->remote_mac[1]=simple_strtol(cur, 0, 16);
-+ cur=delim+1;
-+ if ((delim = strchr(cur, ':')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->remote_mac[2]=simple_strtol(cur, 0, 16);
-+ cur=delim+1;
-+ if ((delim = strchr(cur, ':')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->remote_mac[3]=simple_strtol(cur, 0, 16);
-+ cur=delim+1;
-+ if ((delim = strchr(cur, ':')) == NULL)
-+ goto parse_failed;
-+ *delim=0;
-+ np->remote_mac[4]=simple_strtol(cur, 0, 16);
-+ cur=delim+1;
-+ np->remote_mac[5]=simple_strtol(cur, 0, 16);
-+ }
-+
-+ printk(KERN_INFO "%s: remote ethernet address "
-+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
-+ np->name,
-+ np->remote_mac[0],
-+ np->remote_mac[1],
-+ np->remote_mac[2],
-+ np->remote_mac[3],
-+ np->remote_mac[4],
-+ np->remote_mac[5]);
-+
-+ return 0;
-+
-+ parse_failed:
-+ printk(KERN_INFO "%s: couldn't parse config at %s!\n",
-+ np->name, cur);
-+ return -1;
-+}
-+
-+int netpoll_setup(struct netpoll *np)
-+{
-+ struct net_device *ndev = NULL;
-+ struct in_device *in_dev;
-+ struct irqaction *a;
-+
-+ if (np->dev_name)
-+ ndev = dev_get_by_name(np->dev_name);
-+ if (!ndev) {
-+ printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
-+ np->name, np->dev_name);
-+ return -1;
-+ }
-+
-+ if (!(ndev->flags & IFF_UP)) {
-+ unsigned short oflags;
-+ unsigned long jiff;
-+
-+ printk(KERN_INFO "%s: device %s not up yet, forcing it\n",
-+ np->name, np->dev_name);
-+
-+ oflags = ndev->flags;
-+
-+ rtnl_shlock();
-+ if (dev_change_flags(ndev, oflags | IFF_UP) < 0) {
-+ printk(KERN_ERR "%s: failed to open %s\n",
-+ np->name, np->dev_name);
-+ rtnl_shunlock();
-+ return -1;
-+ }
-+ rtnl_shunlock();
-+
-+ jiff = jiffies + 6*HZ;
-+ while(!netif_carrier_ok(ndev)) {
-+ if (!time_before(jiffies, jiff)) {
-+ printk(KERN_NOTICE
-+ "%s: timeout waiting for carrier\n",
-+ np->name);
-+ break;
-+ }
-+ cond_resched();
-+ }
-+
-+ }
-+
-+ if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr)
-+ memcpy(np->local_mac, ndev->dev_addr, 6);
-+
-+ if (!np->local_ip)
-+ {
-+ in_dev = in_dev_get(ndev);
-+
-+ if (!in_dev) {
-+ printk(KERN_ERR "%s: no IP address for %s, aborting\n",
-+ np->name, np->dev_name);
-+ return -1;
-+ }
-+
-+ np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
-+ in_dev_put(in_dev);
-+ printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
-+ np->name, HIPQUAD(np->local_ip));
-+ }
-+
-+ a=find_irq_action(ndev->irq, ndev);
-+ if (!a) {
-+ printk(KERN_ERR "%s: couldn't find irq handler for %s, "
-+ "aborting\n", np->name, np->dev_name);
-+ return -1;
-+ }
-+
-+ np->irqfunc = a->handler;
-+ np->dev = ndev;
-+
-+ if(np->rx_hook) {
-+ unsigned long flags;
-+
-+ np->dev->rx_hook = rx_hook;
-+
-+ spin_lock_irqsave(&rx_list_lock, flags);
-+ list_add(&np->rx_list, &rx_list);
-+ spin_unlock_irqrestore(&rx_list_lock, flags);
-+ }
-+
-+ return 0;
-+}
-+
-+void netpoll_cleanup(struct netpoll *np)
-+{
-+ if(np->rx_hook) {
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&rx_list_lock, flags);
-+ list_del(&np->rx_list);
-+ np->dev->rx_hook = 0;
-+ spin_unlock_irqrestore(&rx_list_lock, flags);
-+ }
-+
-+ np->dev = 0;
-+}
-+
-+int netpoll_trap()
-+{
-+ return trapped;
-+}
-+
-+void netpoll_set_trap(int trap)
-+{
-+ trapped = trap;
-+}
-Index: linux-2.6.0-test6/include/linux/netpoll.h
-===================================================================
---- linux-2.6.0-test6.orig/include/linux/netpoll.h 2003-10-07 16:08:51.000000000 +0800
-+++ linux-2.6.0-test6/include/linux/netpoll.h 2003-10-07 16:08:51.000000000 +0800
-@@ -0,0 +1,37 @@
-+/*
-+ * Common code for low-level network console, dump, and debugger code
-+ *
-+ * Derived from netconsole, kgdb-over-ethernet, and netdump patches
-+ */
-+
-+#ifndef _LINUX_NETPOLL_H
-+#define _LINUX_NETPOLL_H
-+
-+#include <linux/netdevice.h>
-+#include <linux/irq.h>
-+#include <linux/list.h>
-+
-+struct netpoll;
-+
-+struct netpoll {
-+ struct net_device *dev;
-+ char dev_name[16], *name;
-+ irqreturn_t (*irqfunc)(int, void *, struct pt_regs *);
-+ void (*rx_hook)(struct netpoll *, int, char *, int);
-+ u32 local_ip, remote_ip;
-+ u16 local_port, remote_port;
-+ unsigned char local_mac[6], remote_mac[6];
-+ struct list_head rx_list;
-+};
-+
-+void netpoll_poll(struct netpoll *np);
-+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
-+void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
-+int netpoll_parse_options(struct netpoll *np, char *opt);
-+int netpoll_setup(struct netpoll *np);
-+int netpoll_trap(void);
-+void netpoll_set_trap(int trap);
-+void netpoll_cleanup(struct netpoll *np);
-+
-+
-+#endif
-Index: linux-2.6.0-test6/net/core/Makefile
-===================================================================
---- linux-2.6.0-test6.orig/net/core/Makefile 2003-09-28 08:51:03.000000000 +0800
-+++ linux-2.6.0-test6/net/core/Makefile 2003-10-07 16:08:51.000000000 +0800
-@@ -13,3 +13,4 @@
- obj-$(CONFIG_NET_DIVERT) += dv.o
- obj-$(CONFIG_NET_PKTGEN) += pktgen.o
- obj-$(CONFIG_NET_RADIO) += wireless.o
-+obj-$(CONFIG_NETPOLL) += netpoll.o
-Index: linux-2.6.0-test6/net/Kconfig
-===================================================================
---- linux-2.6.0-test6.orig/net/Kconfig 2003-09-28 08:50:07.000000000 +0800
-+++ linux-2.6.0-test6/net/Kconfig 2003-10-09 20:36:23.429162080 +0800
-@@ -670,4 +670,7 @@
-
- source "net/bluetooth/Kconfig"
-
-+config NETPOLL
-+ def_bool KGDB
-+
- endmenu
-Index: linux-2.6.0-test6/include/linux/netdevice.h
-===================================================================
---- linux-2.6.0-test6.orig/include/linux/netdevice.h 2003-10-07 16:08:42.000000000 +0800
-+++ linux-2.6.0-test6/include/linux/netdevice.h 2003-10-07 16:08:51.000000000 +0800
-@@ -452,13 +452,13 @@
- unsigned char *haddr);
- int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
- int (*accept_fastpath)(struct net_device *, struct dst_entry*);
-+#ifdef CONFIG_NETPOLL
-+ int (*rx_hook)(struct sk_buff *skb);
-+#endif
-
- /* bridge stuff */
- struct net_bridge_port *br_port;
-
--#ifdef CONFIG_KGDB
-- int kgdb_is_trapped;
--#endif
- #ifdef CONFIG_NET_POLL_CONTROLLER
- void (*poll_controller)(struct net_device *);
- #endif
-@@ -537,10 +537,8 @@
- extern struct net_device *dev_get_by_index(int ifindex);
- extern struct net_device *__dev_get_by_index(int ifindex);
- extern int dev_restart(struct net_device *dev);
--#ifdef CONFIG_KGDB
--extern int kgdb_eth_is_trapped(void);
--extern int kgdb_net_interrupt(struct sk_buff *skb);
--extern void kgdb_send_arp_request(void);
-+#ifdef CONFIG_NETPOLL
-+extern int netpoll_trap(void);
- #endif
-
- typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len);
-@@ -600,10 +598,9 @@
-
- static inline void netif_wake_queue(struct net_device *dev)
- {
--#ifdef CONFIG_KGDB
-- if (kgdb_eth_is_trapped()) {
-+#ifdef CONFIG_NETPOLL
-+ if (netpoll_trap())
- return;
-- }
- #endif
- if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state))
- __netif_schedule(dev);
-@@ -611,10 +608,9 @@
-
- static inline void netif_stop_queue(struct net_device *dev)
- {
--#ifdef CONFIG_KGDB
-- if (kgdb_eth_is_trapped()) {
-+#ifdef CONFIG_NETPOLL
-+ if (netpoll_trap())
- return;
-- }
- #endif
- set_bit(__LINK_STATE_XOFF, &dev->state);
- }
-Index: linux-2.6.0-test6/net/core/dev.c
-===================================================================
---- linux-2.6.0-test6.orig/net/core/dev.c 2003-10-07 16:08:42.000000000 +0800
-+++ linux-2.6.0-test6/net/core/dev.c 2003-10-09 20:36:23.436161016 +0800
-@@ -1352,16 +1352,8 @@
- struct softnet_data *queue;
- unsigned long flags;
-
--#ifdef CONFIG_KGDB
-- /* See if kgdb_eth wants this packet */
-- if (!kgdb_net_interrupt(skb)) {
-- /* No.. if we're 'trapped' then junk it */
-- if (kgdb_eth_is_trapped()) {
-- kfree_skb(skb);
-- return NET_RX_DROP;
-- }
-- } else {
-- /* kgdb_eth ate the packet... drop it silently */
-+#ifdef CONFIG_NETPOLL
-+ if (skb->dev->rx_hook && skb->dev->rx_hook(skb)) {
- kfree_skb(skb);
- return NET_RX_DROP;
- }
-@@ -1556,6 +1548,13 @@
- int ret = NET_RX_DROP;
- unsigned short type = skb->protocol;
-
-+#ifdef CONFIG_NETPOLL
-+ if (skb->dev->rx_hook && skb->dev->rx_hook(skb)) {
-+ kfree_skb(skb);
-+ return NET_RX_DROP;
-+ }
-+#endif
-+
- if (!skb->stamp.tv_sec)
- do_gettimeofday(&skb->stamp);
-
-Index: linux-2.6.0-test6/include/asm-i386/irq.h
-===================================================================
---- linux-2.6.0-test6.orig/include/asm-i386/irq.h 2003-09-28 08:50:36.000000000 +0800
-+++ linux-2.6.0-test6/include/asm-i386/irq.h 2003-10-07 16:08:51.000000000 +0800
-@@ -24,6 +24,7 @@
- extern void disable_irq_nosync(unsigned int);
- extern void enable_irq(unsigned int);
- extern void release_x86_irqs(struct task_struct *);
-+struct irqaction *find_irq_action(unsigned int irq, void *dev_id);
-
- #ifdef CONFIG_X86_LOCAL_APIC
- #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
-Index: linux-2.6.0-test6/arch/i386/kernel/irq.c
-===================================================================
---- linux-2.6.0-test6.orig/arch/i386/kernel/irq.c 2003-10-07 16:08:34.000000000 +0800
-+++ linux-2.6.0-test6/arch/i386/kernel/irq.c 2003-10-09 20:36:23.433161472 +0800
-@@ -396,7 +396,6 @@
- }
- spin_unlock_irqrestore(&desc->lock, flags);
- }
--
- /*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
-@@ -896,6 +895,21 @@
- return 0;
- }
-
-+struct irqaction *find_irq_action(unsigned int irq, void *dev_id)
-+{
-+ struct irqaction *a, *r=0;
-+
-+ spin_lock_irq(&irq_desc[irq].lock);
-+ for(a=irq_desc[irq].action; a; a=a->next) {
-+ if(a->dev_id == dev_id) {
-+ r=a;
-+ break;
-+ }
-+ }
-+ spin_unlock_irq(&irq_desc[irq].lock);
-+ return r;
-+}
-+
- static struct proc_dir_entry * root_irq_dir;
- static struct proc_dir_entry * irq_dir [NR_IRQS];
-
+++ /dev/null
- drivers/net/pcnet32.c | 16 ++++++++++++++++
- 1 files changed, 16 insertions(+)
-
-diff -puN drivers/net/pcnet32.c~kgdbeth-pcnet32-support drivers/net/pcnet32.c
---- linux-2.6.0-test6-mm/drivers/net/pcnet32.c~kgdbeth-pcnet32-support 2003-10-06 00:45:54.000000000 +0400
-+++ linux-2.6.0-test6-mm-alexey/drivers/net/pcnet32.c 2003-10-06 00:54:55.000000000 +0400
-@@ -331,6 +331,9 @@ static int pcnet32_init_ring(struct net
- static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
- static int pcnet32_rx(struct net_device *);
- static void pcnet32_tx_timeout (struct net_device *dev);
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+static void pcnet32_rx_poll(struct net_device *);
-+#endif
- static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
- static int pcnet32_close(struct net_device *);
- static struct net_device_stats *pcnet32_get_stats(struct net_device *);
-@@ -806,6 +809,10 @@ pcnet32_probe1(unsigned long ioaddr, uns
- dev->tx_timeout = pcnet32_tx_timeout;
- dev->watchdog_timeo = (5*HZ);
-
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+ dev->poll_controller = pcnet32_rx_poll;
-+#endif
-+
- lp->next = pcnet32_dev;
- pcnet32_dev = dev;
-
-@@ -1152,6 +1159,15 @@ pcnet32_start_xmit(struct sk_buff *skb,
- return 0;
- }
-
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+static void pcnet32_rx_poll(struct net_device *dev)
-+{
-+ disable_irq(dev->irq);
-+ pcnet32_interrupt(dev->irq, (void *)dev, 0);
-+ enable_irq(dev->irq);
-+}
-+#endif
-+
- /* The PCNET32 interrupt handler. */
- static irqreturn_t
- pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-
-_