Title: [6688] trunk: merge kgdboe patch
Revision
6688
Author
vapier
Date
2009-06-12 08:56:17 -0500 (Fri, 12 Jun 2009)

Log Message

merge kgdboe patch

Modified Paths


Added Paths

Diff

Modified: trunk/drivers/net/Makefile (6687 => 6688)


--- trunk/drivers/net/Makefile	2009-06-12 13:55:33 UTC (rev 6687)
+++ trunk/drivers/net/Makefile	2009-06-12 13:56:17 UTC (rev 6688)
@@ -263,6 +263,7 @@
 obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
+obj-$(CONFIG_KGDBOE) += kgdboe.o
 
 obj-$(CONFIG_FS_ENET) += fs_enet/
 

Added: trunk/drivers/net/kgdboe.c (0 => 6688)


--- trunk/drivers/net/kgdboe.c	                        (rev 0)
+++ trunk/drivers/net/kgdboe.c	2009-06-12 13:56:17 UTC (rev 6688)
@@ -0,0 +1,312 @@
+/*
+ * drivers/net/kgdboe.c
+ *
+ * A network interface for GDB.
+ * Based upon 'gdbserial' by David Grothe <[email protected]>
+ * and Scott Foehner <[email protected]>
+ *
+ * Maintainer: Jason Wessel <[email protected]>
+ *
+ * 2004 (c) Amit S. Kale <[email protected]>
+ * 2004-2005 (c) MontaVista Software, Inc.
+ * 2005-2008 (c) Wind River Systems, Inc.
+ *
+ * Contributors at various stages not listed above:
+ * San Mehat <[email protected]>, Robert Walsh <[email protected]>,
+ * wangdi <[email protected]>, Matt Mackall <[email protected]>,
+ * Pavel Machek <[email protected]>, Jason Wessel <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/kgdb.h>
+#include <linux/netpoll.h>
+#include <linux/init.h>
+
+#include <asm/atomic.h>
+
+#define IN_BUF_SIZE 512		/* power of 2, please */
+#define OUT_BUF_SIZE 30		/* We don't want to send too big of a packet. */
+#define MAX_CONFIG_LEN 256
+
+static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE];
+static int in_head, in_tail, out_count;
+static atomic_t in_count;
+/* 0 = unconfigured, 1 = netpoll options parsed, 2 = fully configured. */
+static int configured;
+static struct kgdb_io local_kgdb_io_ops;
+static int use_dynamic_mac;
+
+static atomic_t                 kgdb_break_tasklet_var;
+
+/*
+ * There are times a tasklet needs to be used vs a compiled in in
+ * break point so as to cause an exception outside a kgdb I/O module,
+ * such as is the case with kgdboe, where calling a breakpoint in the
+ * I/O driver itself would be fatal.
+ */
+static void kgdb_tasklet_bpt(unsigned long ing)
+{
+	kgdb_breakpoint();
+	atomic_set(&kgdb_break_tasklet_var, 0);
+}
+
+static DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0);
+
+static void kgdb_schedule_breakpoint(void)
+{
+	if (atomic_read(&kgdb_break_tasklet_var) ||
+		atomic_read(&kgdb_active) != -1 ||
+		atomic_read(&kgdb_setting_breakpoint))
+		return;
+	atomic_inc(&kgdb_break_tasklet_var);
+	tasklet_schedule(&kgdb_tasklet_breakpoint);
+}
+
+MODULE_DESCRIPTION("KGDB driver for network interfaces");
+MODULE_LICENSE("GPL");
+static char config[MAX_CONFIG_LEN];
+static struct kparam_string kps = {
+	.string = config,
+	.maxlen = MAX_CONFIG_LEN,
+};
+
+static void rx_hook(struct netpoll *np, int port, char *msg, int len,
+		    struct sk_buff *skb)
+{
+	int i;
+
+	np->remote_port = port;
+
+	/* Copy the MAC address if we need to. */
+	if (use_dynamic_mac) {
+		memcpy(np->remote_mac, eth_hdr(skb)->h_source,
+				sizeof(np->remote_mac));
+		use_dynamic_mac = 0;
+	}
+
+	/*
+	 * This could be GDB trying to attach.  But it could also be GDB
+	 * finishing up a session, with kgdb_connected=0 but GDB sending
+	 * an ACK for the final packet.  To make sure we don't try and
+	 * make a breakpoint when GDB is leaving, make sure that if
+	 * !kgdb_connected the only len == 1 packet we allow is ^C.
+	 */
+	if (!kgdb_connected && (len != 1 || msg[0] == 3))
+		kgdb_schedule_breakpoint();
+
+	for (i = 0; i < len; i++) {
+		if (msg[i] == 3)
+			kgdb_schedule_breakpoint();
+
+		if (atomic_read(&in_count) >= IN_BUF_SIZE) {
+			/* buffer overflow, clear it */
+			in_head = 0;
+			in_tail = 0;
+			atomic_set(&in_count, 0);
+			break;
+		}
+		in_buf[in_head++] = msg[i];
+		in_head &= (IN_BUF_SIZE - 1);
+		atomic_inc(&in_count);
+	}
+}
+
+static struct netpoll np = {
+	.dev_name = "eth0",
+	.name = "kgdboe",
+	.rx_hook = rx_hook,
+	.local_port = 6443,
+	.remote_port = 6442,
+	.remote_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+};
+
+static void eth_pre_exception_handler(void)
+{
+	/* Increment the module count when the debugger is active */
+	if (!kgdb_connected)
+		try_module_get(THIS_MODULE);
+	netpoll_set_trap(1);
+}
+
+static void eth_post_exception_handler(void)
+{
+	/* decrement the module count when the debugger detaches */
+	if (!kgdb_connected)
+		module_put(THIS_MODULE);
+	netpoll_set_trap(0);
+}
+
+static int eth_get_char(void)
+{
+	int chr;
+
+	while (atomic_read(&in_count) == 0)
+		netpoll_poll(&np);
+
+	chr = in_buf[in_tail++];
+	in_tail &= (IN_BUF_SIZE - 1);
+	atomic_dec(&in_count);
+	return chr;
+}
+
+static void eth_flush_buf(void)
+{
+	if (out_count && np.dev) {
+		netpoll_send_udp(&np, out_buf, out_count);
+		memset(out_buf, 0, sizeof(out_buf));
+		out_count = 0;
+	}
+}
+
+static void eth_put_char(u8 chr)
+{
+	out_buf[out_count++] = chr;
+	if (out_count == OUT_BUF_SIZE)
+		eth_flush_buf();
+}
+
+static int option_setup(char *opt)
+{
+	char opt_scratch[MAX_CONFIG_LEN];
+
+	configured = 0;
+	/* If we're being given a new configuration, copy it in. */
+	if (opt != config)
+		strcpy(config, opt);
+
+	if (opt[0] == '\0')
+		return 1;
+
+	/* But work on a copy as netpoll_parse_options will eat it. */
+	strcpy(opt_scratch, opt);
+	configured = !netpoll_parse_options(&np, opt_scratch);
+
+	use_dynamic_mac = 1;
+
+	return 0;
+}
+__setup("kgdboe=", option_setup);
+
+/* With our config string set by some means, configure kgdboe. */
+static int configure_kgdboe(void)
+{
+	if (option_setup(config))
+		return 0;
+
+	if (!configured) {
+		printk(KERN_ERR "kgdboe: configuration incorrect - kgdboe not "
+		       "loaded.\n");
+		printk(KERN_ERR "  Usage: kgdboe=[src-po...@[src-ip]/[dev],"
+				"[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
+		return -EINVAL;
+	}
+
+	/* Bring it up. */
+	if (netpoll_setup(&np)) {
+		printk(KERN_ERR "kgdboe: netpoll_setup failed kgdboe failed\n");
+		return -EINVAL;
+	}
+
+	if (kgdb_register_io_module(&local_kgdb_io_ops)) {
+		netpoll_cleanup(&np);
+		return -EINVAL;
+	}
+
+	configured = 2;
+
+	return 0;
+}
+
+static int init_kgdboe(void)
+{
+	int ret;
+
+	/* Already done? */
+	if (configured == 2)
+		return 0;
+
+	/* OK, go ahead and do it. */
+	ret = configure_kgdboe();
+
+	if (configured == 2)
+		printk(KERN_INFO "kgdboe: debugging over ethernet enabled\n");
+
+	return ret;
+}
+
+static void cleanup_kgdboe(void)
+{
+	netpoll_cleanup(&np);
+	configured = 0;
+	kgdb_unregister_io_module(&local_kgdb_io_ops);
+}
+
+static int param_set_kgdboe_var(const char *kmessage, struct kernel_param *kp)
+{
+	char kmessage_save[MAX_CONFIG_LEN];
+	int len = strlen(kmessage);
+
+	if (len >= MAX_CONFIG_LEN) {
+		printk(KERN_ERR "kgdboc: config string too long\n");
+		return -ENOSPC;
+	}
+
+	if (kgdb_connected) {
+		printk(KERN_ERR "kgdboe: Cannot reconfigure while KGDB is "
+				"connected.\n");
+		return 0;
+	}
+
+	/* Start the reconfiguration process by saving the old string */
+	strncpy(kmessage_save, config, sizeof(kmessage_save));
+
+
+	/* Copy in the new param and strip out invalid characters so we
+	 * can optionally specify the MAC.
+	 */
+	strcpy(config, kmessage);
+	/* Chop out \n char as a result of echo */
+	if (config[len - 1] == '\n')
+		config[len - 1] = '\0';
+
+	len--;
+	while (len > 0 && (config[len] < ',' || config[len] > 'f')) {
+		config[len] = '\0';
+		len--;
+	}
+
+	if (configured == 2) {
+		cleanup_kgdboe();
+		configured = 0;
+	}
+	if (config[0] == '\0')
+		return 0;
+
+	configure_kgdboe();
+
+	if (configured != 2)
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct kgdb_io local_kgdb_io_ops = {
+	.name = "kgdboe",
+	.read_char = eth_get_char,
+	.write_char = eth_put_char,
+	.flush = eth_flush_buf,
+	.pre_exception = eth_pre_exception_handler,
+	.post_exception = eth_post_exception_handler
+};
+
+module_init(init_kgdboe);
+module_exit(cleanup_kgdboe);
+module_param_call(kgdboe, param_set_kgdboe_var, param_get_string, &kps, 0644);
+MODULE_PARM_DESC(kgdboe, "[src-po...@[src-ip]/[dev],"
+		 "[tgt-port]@<tgt-ip>/<tgt-macaddr>");

Modified: trunk/include/linux/netpoll.h (6687 => 6688)


--- trunk/include/linux/netpoll.h	2009-06-12 13:55:33 UTC (rev 6687)
+++ trunk/include/linux/netpoll.h	2009-06-12 13:56:17 UTC (rev 6688)
@@ -16,7 +16,7 @@
 	struct net_device *dev;
 	char dev_name[IFNAMSIZ];
 	const char *name;
-	void (*rx_hook)(struct netpoll *, int, char *, int);
+	void (*rx_hook)(struct netpoll *, int, char *, int, struct sk_buff *);
 
 	__be32 local_ip, remote_ip;
 	u16 local_port, remote_port;

Modified: trunk/lib/Kconfig.kgdb (6687 => 6688)


--- trunk/lib/Kconfig.kgdb	2009-06-12 13:55:33 UTC (rev 6687)
+++ trunk/lib/Kconfig.kgdb	2009-06-12 13:56:17 UTC (rev 6688)
@@ -27,6 +27,17 @@
 	  Share a serial console with kgdb. Sysrq-g must be used
 	  to break in initially.
 
+config KGDBOE
+	tristate "KGDB: On ethernet"
+	depends on KGDB
+	select NETPOLL
+	select NETPOLL_TRAP
+	help
+	  Uses the NETPOLL API to communicate with the host GDB via UDP.
+	  In order for this to work, the ethernet interface specified must
+	  support the NETPOLL API, and this must be initialized at boot.
+	  See the documentation for syntax.
+
 config KGDB_TESTS
 	bool "KGDB: internal test suite"
 	default n

Modified: trunk/net/core/netpoll.c (6687 => 6688)


--- trunk/net/core/netpoll.c	2009-06-12 13:55:33 UTC (rev 6687)
+++ trunk/net/core/netpoll.c	2009-06-12 13:56:17 UTC (rev 6688)
@@ -546,7 +546,8 @@
 
 	np->rx_hook(np, ntohs(uh->source),
 		    (char *)(uh+1),
-		    ulen - sizeof(struct udphdr));
+		    ulen - sizeof(struct udphdr),
+		    skb);
 
 	kfree_skb(skb);
 	return 1;
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to