linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 3/3]x86_64: early_printk for early debug port support
@ 2007-05-21  5:19 Yinghai Lu
  2007-05-22 19:31 ` Andrew Morton
  2007-07-18 22:10 ` Andi Kleen
  0 siblings, 2 replies; 6+ messages in thread
From: Yinghai Lu @ 2007-05-21  5:19 UTC (permalink / raw)
  To: Andi Kleen, Andrew Morton, Eric W. Biederman, Greg KH,
	Bjorn Helgaas, Vivek Goyal
  Cc: linux kernel mailing list

[-- Attachment #1: Type: text/plain, Size: 202 bytes --]

add early dbgp to early_printk.

kernel command line:
earlyprintk=dbgp
or
earlyprintk=dbgp1

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

[-- Attachment #2: usbdebug_05202007.diff --]
[-- Type: text/x-patch, Size: 19652 bytes --]

diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 56eaa25..f90a5ff 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -3,9 +3,19 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/screen_info.h>
+#include <linux/usb/ch9.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/fcntl.h>
+#include <asm/pci-direct.h>
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#define EARLY_PRINTK
+#include "../../../drivers/usb/host/ehci.h"
+
 
 /* Simple VGA output */
 
@@ -155,6 +165,582 @@ static struct console early_serial_console = {
 	.index =	-1,
 };
 
+
+static struct ehci_caps __iomem *ehci_caps;
+static struct ehci_regs __iomem *ehci_regs;
+static struct ehci_dbg_port __iomem *ehci_debug;
+static unsigned dbgp_endpoint_out;
+
+#define USB_DEBUG_DEVNUM 127
+
+#define DBGP_DATA_TOGGLE	0x8800
+#define DBGP_PID_UPDATE(x, tok) \
+	((((x) ^ DBGP_DATA_TOGGLE) & 0xffff00) | ((tok) & 0xff))
+
+#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))
+/*
+ * USB Packet IDs (PIDs)
+ */
+
+/* token */
+#define USB_PID_OUT		0xe1
+#define USB_PID_IN		0x69
+#define USB_PID_SOF		0xa5
+#define USB_PID_SETUP		0x2d
+/* handshake */
+#define USB_PID_ACK		0xd2
+#define USB_PID_NAK		0x5a
+#define USB_PID_STALL		0x1e
+#define USB_PID_NYET		0x96
+/* data */
+#define USB_PID_DATA0		0xc3
+#define USB_PID_DATA1		0x4b
+#define USB_PID_DATA2		0x87
+#define USB_PID_MDATA		0x0f
+/* Special */
+#define USB_PID_PREAMBLE	0x3c
+#define USB_PID_ERR		0x3c
+#define USB_PID_SPLIT		0x78
+#define USB_PID_PING		0xb4
+#define USB_PID_UNDEF_0		0xf0
+
+#define USB_PID_DATA_TOGGLE	0x88
+#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
+
+#define PCI_CAP_ID_EHCI_DEBUG	0xa
+
+#define HUB_ROOT_RESET_TIME	50	/* times are in msec */
+#define HUB_SHORT_RESET_TIME	10
+#define HUB_LONG_RESET_TIME	200
+#define HUB_RESET_TIMEOUT	500
+
+#define DBGP_MAX_PACKET		8
+
+static int dbgp_wait_until_complete(void)
+{
+	unsigned ctrl;
+	int loop = 0x100000;
+	do {
+		ctrl = readl(&ehci_debug->control);
+		/* Stop when the transaction is finished */
+		if (ctrl & DBGP_DONE)
+			break;
+	} while (--loop > 0);
+	
+	if (!loop) return -1;
+
+	/* Now that we have observed the completed transaction,
+	 * clear the done bit.
+	 */
+	writel(ctrl | DBGP_DONE, &ehci_debug->control);
+	return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
+}
+
+static void dbgp_mdelay(int ms)
+{
+	int i;
+	while (ms--) {
+		for (i = 0; i < 1000; i++)
+			outb(0x1, 0x80);
+	}
+}
+
+static void dbgp_breath(void)
+{
+	/* Sleep to give the debug port a chance to breathe */
+}
+
+static int dbgp_wait_until_done(unsigned ctrl)
+{
+	unsigned pids, lpid;
+	int ret;
+
+	int loop = 3;
+retry:
+	writel(ctrl | DBGP_GO, &ehci_debug->control);
+	ret = dbgp_wait_until_complete();
+	pids = readl(&ehci_debug->pids);
+	lpid = DBGP_PID_GET(pids);
+
+	if (ret < 0)
+		return ret;
+
+	/* If the port is getting full or it has dropped data
+	 * start pacing ourselves, not necessary but it's friendly.
+	 */
+	if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET))
+		dbgp_breath();
+	
+	/* If I get a NACK reissue the transmission */
+	if (lpid == USB_PID_NAK) {
+		if(--loop > 0) goto retry;
+	}
+
+	return ret;
+}
+
+static void dbgp_set_data(const void *buf, int size)
+{
+	const unsigned char *bytes = buf;
+	unsigned lo, hi;
+	int i;
+	lo = hi = 0;
+	for (i = 0; i < 4 && i < size; i++)
+		lo |= bytes[i] << (8*i);
+	for (; i < 8 && i < size; i++)
+		hi |= bytes[i] << (8*(i - 4));
+	writel(lo, &ehci_debug->data03);
+	writel(hi, &ehci_debug->data47);
+}
+
+static void dbgp_get_data(void *buf, int size)
+{
+	unsigned char *bytes = buf;
+	unsigned lo, hi;
+	int i;
+	lo = readl(&ehci_debug->data03);
+	hi = readl(&ehci_debug->data47);
+	for (i = 0; i < 4 && i < size; i++)
+		bytes[i] = (lo >> (8*i)) & 0xff;
+	for (; i < 8 && i < size; i++)
+		bytes[i] = (hi >> (8*(i - 4))) & 0xff;
+}
+
+static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, const char *bytes, int size)
+{
+	unsigned pids, addr, ctrl;
+	int ret;
+	if (size > DBGP_MAX_PACKET)
+		return -1;
+
+	addr = DBGP_EPADDR(devnum, endpoint);
+
+	pids = readl(&ehci_debug->pids);
+	pids = DBGP_PID_UPDATE(pids, USB_PID_OUT);
+	
+	ctrl = readl(&ehci_debug->control);
+	ctrl = DBGP_LEN_UPDATE(ctrl, size);
+	ctrl |= DBGP_OUT;
+	ctrl |= DBGP_GO;
+
+	dbgp_set_data(bytes, size);
+	writel(addr, &ehci_debug->address);
+	writel(pids, &ehci_debug->pids);
+
+	ret = dbgp_wait_until_done(ctrl);
+	if (ret < 0) {
+		return ret;
+	}
+	return ret;
+}
+
+static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, int size)
+{
+	unsigned pids, addr, ctrl;
+	int ret;
+
+	if (size > DBGP_MAX_PACKET)
+		return -1;
+
+	addr = DBGP_EPADDR(devnum, endpoint);
+
+	pids = readl(&ehci_debug->pids);
+	pids = DBGP_PID_UPDATE(pids, USB_PID_IN);
+		
+	ctrl = readl(&ehci_debug->control);
+	ctrl = DBGP_LEN_UPDATE(ctrl, size);
+	ctrl &= ~DBGP_OUT;
+	ctrl |= DBGP_GO;
+		
+	writel(addr, &ehci_debug->address);
+	writel(pids, &ehci_debug->pids);
+	ret = dbgp_wait_until_done(ctrl);
+	if (ret < 0)
+		return ret;
+	if (size > ret)
+		size = ret;
+	dbgp_get_data(data, size);
+	return ret;
+}
+
+static int dbgp_control_msg(unsigned devnum, int requesttype, int request, 
+	int value, int index, void *data, int size)
+{
+	unsigned pids, addr, ctrl;
+	struct usb_ctrlrequest req;
+	int read;
+	int ret;
+
+	read = (requesttype & USB_DIR_IN) != 0;
+	if (size > (read?DBGP_MAX_PACKET:0))
+		return -1;
+	
+	/* Compute the control message */
+	req.bRequestType = requesttype;
+	req.bRequest = request;
+	req.wValue = value;
+	req.wIndex = index;
+	req.wLength = size;
+
+	pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP);
+	addr = DBGP_EPADDR(devnum, 0);
+
+	ctrl = readl(&ehci_debug->control);
+	ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
+	ctrl |= DBGP_OUT;
+	ctrl |= DBGP_GO;
+
+	/* Send the setup message */
+	dbgp_set_data(&req, sizeof(req));
+	writel(addr, &ehci_debug->address);
+	writel(pids, &ehci_debug->pids);
+	ret = dbgp_wait_until_done(ctrl);
+	if (ret < 0)
+		return ret;
+
+
+	/* Read the result */
+	ret = dbgp_bulk_read(devnum, 0, data, size);
+	return ret;
+}
+
+
+/* Find a PCI capability */
+static __u32 __init find_cap(int num, int slot, int func, int cap) 
+{ 
+	u8 pos;
+	int bytes;
+	if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
+		return 0;
+	pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
+	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { 
+		u8 id;
+		pos &= ~3; 
+		id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
+		if (id == 0xff)
+			break;
+		if (id == cap) 
+			return pos; 
+		pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT); 
+	} 
+	return 0;
+} 
+
+static __u32 __init find_dbgp(int ehci_num, unsigned *rbus, unsigned *rslot, unsigned *rfunc)
+{
+	unsigned bus, slot, func;
+	
+	for (bus = 0; bus < 256; bus++) {
+		for (slot = 0; slot < 32; slot++) {
+			for (func = 0; func < 8; func++) {
+				u32 class;
+				unsigned cap;
+				class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION);
+				if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI)
+					continue;
+				cap = find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG);
+				if (!cap)
+					continue;
+				if (ehci_num-- != 0)
+					continue;
+				*rbus = bus;
+				*rslot = slot;
+				*rfunc = func;
+				return cap;
+			}
+		}
+	}
+	return 0;
+}
+
+static int ehci_reset_port(int port)
+{
+	unsigned portsc;
+	unsigned delay_time, delay;
+	int loop;
+
+	/* Reset the usb debug port */
+	portsc = readl(&ehci_regs->port_status[port - 1]);
+	portsc &= ~PORT_PE;
+	portsc |= PORT_RESET;
+	writel(portsc, &ehci_regs->port_status[port - 1]);
+
+	delay = HUB_ROOT_RESET_TIME;
+	for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT;
+	     delay_time += delay) {
+		dbgp_mdelay(delay);
+
+		portsc = readl(&ehci_regs->port_status[port - 1]);
+		if (portsc & PORT_RESET) {
+			/* force reset to complete */
+			loop = 2;
+			writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), 
+				&ehci_regs->port_status[port - 1]);
+			do {
+				portsc = readl(&ehci_regs->port_status[port - 1]);
+			} while ((portsc & PORT_RESET) && (--loop > 0));
+		}
+
+		/* Device went away? */
+		if (!(portsc & PORT_CONNECT))
+			return -ENOTCONN;
+
+		/* bomb out completely if something weird happend */
+		if ((portsc & PORT_CSC))
+			return -EINVAL;
+
+		/* If we've finished resetting, then break out of the loop */
+		if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
+			return 0;
+	}
+	return -EBUSY;
+}
+
+static int ehci_wait_for_port(int port)
+{
+	unsigned status;
+	int ret, reps;
+	for (reps = 0; reps < 3; reps++) {
+		dbgp_mdelay(100);
+		status = readl(&ehci_regs->status);
+		if (status & STS_PCD) {
+			ret = ehci_reset_port(port);
+			if (ret == 0)
+				return 0;
+		}
+	}
+	return -ENOTCONN;
+}
+
+
+#define DBGP_DEBUG 0
+#if DBGP_DEBUG
+void early_printk(const char *fmt, ...);
+# define dbgp_printk early_printk
+#else
+static inline void dbgp_printk(const char *fmt, ...) { }
+#endif
+
+static int ehci_setup(void)
+{
+	unsigned cmd, ctrl, status, portsc, hcs_params, debug_port, n_ports;
+	int ret;
+	int loop;
+
+	hcs_params = readl(&ehci_caps->hcs_params);
+	debug_port = HCS_DEBUG_PORT(hcs_params);
+	n_ports    = HCS_N_PORTS(hcs_params);
+
+	dbgp_printk("debug_port: %d\n", debug_port);
+	dbgp_printk("n_ports:    %d\n", n_ports);
+
+	loop = 10;
+	/* Reset the EHCI controller */
+	cmd = readl(&ehci_regs->command);
+	cmd |= CMD_RESET;
+	writel(cmd, &ehci_regs->command);
+	do {
+		cmd = readl(&ehci_regs->command);
+	} while ((cmd & CMD_RESET) && (--loop > 0));
+
+	/* Claim ownership, but do not enable yet */
+	ctrl = readl(&ehci_debug->control);
+	ctrl |= DBGP_OWNER;
+	ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
+	writel(ctrl, &ehci_debug->control);
+
+	/* Start the ehci running */
+	cmd = readl(&ehci_regs->command);
+	cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
+	cmd |= CMD_RUN;
+	writel(cmd, &ehci_regs->command);
+
+	/* Ensure everything is routed to the EHCI */
+	writel(FLAG_CF, &ehci_regs->configured_flag);
+
+	/* Wait until the controller is no longer halted */
+	loop = 10;
+	do {
+		status = readl(&ehci_regs->status);
+	} while ((status & STS_HALT) && (--loop > 0));
+
+	/* Wait for a device to show up in the debug port */
+	ret = ehci_wait_for_port(debug_port);
+	if (ret < 0) {
+		dbgp_printk("No device found in debug port\n");
+		return -1;
+	}
+
+	/* Enable the debug port */
+	ctrl = readl(&ehci_debug->control);
+	ctrl |= DBGP_CLAIM;
+	writel(ctrl, &ehci_debug->control);
+	ctrl = readl(&ehci_debug->control);
+	if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
+		dbgp_printk("No device in debug port\n");
+		writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control);
+		return -1;
+
+	}
+
+	/* Completely transfer the debug device to the debug controller */
+	portsc = readl(&ehci_regs->port_status[debug_port - 1]);
+	portsc &= ~PORT_PE;
+	writel(portsc, &ehci_regs->port_status[debug_port - 1]);
+
+	return 0;
+}
+
+static int __init early_dbgp_init(char *s)
+{
+	struct usb_debug_descriptor dbgp_desc;
+	void __iomem *ehci_bar;
+	unsigned ctrl, devnum;
+	unsigned bus, slot, func, cap;
+	unsigned debug_port, bar, offset;
+	unsigned bar_val;
+	char *e;
+	int ret;
+	unsigned dbgp_num;
+
+	if (!early_pci_allowed())
+		return -1;
+
+	dbgp_num = 0;
+	if (*s) {
+		dbgp_num = simple_strtoul(s, &e, 10);
+	}
+	dbgp_printk("dbgp_num: %d\n", dbgp_num);
+	cap = find_dbgp(dbgp_num, &bus, &slot, &func);
+	if (!cap)
+		return -1;
+
+	dbgp_printk("Found EHCI debug port\n");
+
+	debug_port = read_pci_config(bus, slot, func, cap);
+	bar = (debug_port >> 29) & 0x7;
+	bar = (bar * 4) + 0xc;
+	offset = (debug_port >> 16) & 0xfff;
+	dbgp_printk("bar: %02x offset: %03x\n", bar, offset);
+	if (bar != PCI_BASE_ADDRESS_0) {
+		dbgp_printk("only debug ports on bar 1 handled.\n");
+		return -1;
+	}
+
+	bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
+	dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset);
+	if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) {
+		dbgp_printk("only simple 32bit mmio bars supported\n");
+		return -1;
+	}
+		
+
+	/* FIXME I don't have the bar size so just guess PAGE_SIZE is more
+	 * than enough.  1K is the biggest I have seen.
+	 */
+	dbgp_printk("dbgp pre-set_fixmap_nocache\n");
+	set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK);
+	dbgp_printk("dbgp post-set_fixmap_nocache\n");
+	ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE);
+	ehci_bar += bar_val & ~PAGE_MASK;
+	dbgp_printk("ehci_bar: %p\n", ehci_bar);
+
+	ehci_caps  = ehci_bar;
+	ehci_regs  = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase));
+	ehci_debug = ehci_bar + offset;
+
+	ret = ehci_setup();
+	if (ret < 0) {
+		dbgp_printk("ehci_setup failed\n");
+		ehci_debug = 0;
+		return -1;
+	}
+	dbgp_mdelay(100);
+
+	/* Find the debug device and make it device number 127 */
+	for (devnum = 0; devnum <= 127; devnum++) {
+		ret = dbgp_control_msg(devnum,
+			USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+			USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
+			&dbgp_desc, sizeof(dbgp_desc));
+		if (ret > 0)
+			break;
+	}
+	if (devnum > 127) {
+		dbgp_printk("Could not find attached debug device\n");
+		goto err;
+	}
+	if (ret < 0) {
+		dbgp_printk("Attached device is not a debug device\n");
+		goto err;
+	}
+	dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
+
+	/* Move the device to 127 if it isn't already there */
+	if (devnum != USB_DEBUG_DEVNUM) {
+		ret = dbgp_control_msg(devnum,
+			USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+			USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
+		if (ret < 0) {
+			dbgp_printk("Could not move attached device to %d\n", 
+				USB_DEBUG_DEVNUM);
+			goto err;
+		}
+		devnum = USB_DEBUG_DEVNUM;
+	}
+
+	/* Enable the debug interface */
+	ret = dbgp_control_msg(USB_DEBUG_DEVNUM,
+		USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+		USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0);
+	if (ret < 0) {
+		dbgp_printk(" Could not enable the debug device\n");
+		goto err;
+	}
+
+	/* Perform a small write to get the even/odd data state in sync
+	 */
+	ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ",1);
+	if (ret < 0) {
+		dbgp_printk("dbgp_bulk_write failed: %d\n", ret);
+		goto err;
+	}
+
+
+	return 0;
+err:
+	/* Things didn't work so remove my claim */
+	ctrl = readl(&ehci_debug->control);
+	ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
+	writel(ctrl, &ehci_debug->control);
+	ehci_debug = 0;
+
+	return -1;
+}
+
+static void early_dbgp_write(struct console *con, const char *str, unsigned n)
+{
+	int chunk, ret;
+	if (!ehci_debug)
+		return;
+	while (n > 0) {
+		chunk = n;
+		if (chunk > DBGP_MAX_PACKET)
+			chunk = DBGP_MAX_PACKET;
+		ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, 
+			dbgp_endpoint_out, str, chunk);
+		str += chunk;
+		n -= chunk;
+	}
+}
+
+static struct console early_dbgp_console = {
+	.name =		"earlydbg",
+	.write =	early_dbgp_write,
+	.flags = 	CON_PRINTBUFFER,
+	.index = 	-1,
+};
+
 /* Console interface to a host file on AMD's SimNow! */
 
 static int simnow_fd;
@@ -242,6 +828,10 @@ static int __init setup_early_printk(char *buf)
  		simnow_init(buf + 6);
  		early_console = &simnow_console;
  		keep_early = 1;
+ 	} else if (!strncmp(buf, "dbgp", 4)) {
+ 		if (early_dbgp_init(buf+4) < 0) 
+			return 0;
+ 		early_console = &early_dbgp_console;
 	}
 
 	if (keep_early)
@@ -251,4 +841,17 @@ static int __init setup_early_printk(char *buf)
 	register_console(early_console);
 	return 0;
 }
+
+void __init enable_debug_console(char *buf)
+{
+#if DBGP_DEBUG
+	if(early_console_initialized && early_console) {
+		unregister_console(early_console);
+		early_console_initialized = 0;
+	}
+	setup_early_printk(buf);
+	keep_early = 1;
+#endif
+}
+ 
 early_param("earlyprintk", setup_early_printk);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 46fa57a..a14260f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -46,6 +46,7 @@ struct ehci_stats {
 
 #define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
 
+#ifndef EARLY_PRINTK
 struct ehci_hcd {			/* one per controller */
 	/* glue to PCI and HCD framework */
 	struct ehci_caps __iomem *caps;
@@ -166,6 +167,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
 		mod_timer (&ehci->watchdog, t);
 	}
 }
+#endif /* EARLY_PRINTK */
 
 /*-------------------------------------------------------------------------*/
 
@@ -305,6 +307,8 @@ struct ehci_dbg_port {
 
 #define	QTD_NEXT(dma)	cpu_to_le32((u32)dma)
 
+#ifndef EARLY_PRINTK
+
 /*
  * EHCI Specification 0.95 Section 3.5
  * QTD: describe data transfer components (buffer, direction, ...)
@@ -340,7 +344,7 @@ struct ehci_qtd {
 	struct urb		*urb;			/* qtd's urb */
 	size_t			length;			/* length of buffer */
 } __attribute__ ((aligned (32)));
-
+#endif
 /* mask NakCnt+T in qh->hw_alt_next */
 #define QTD_MASK __constant_cpu_to_le32 (~0x1f)
 
@@ -390,6 +394,7 @@ union ehci_shadow {
  * These appear in both the async and (for interrupt) periodic schedules.
  */
 
+#ifndef EARLY_PRINTK
 struct ehci_qh {
 	/* first part defined by EHCI spec */
 	__le32			hw_next;	 /* see EHCI 3.6.1 */
@@ -438,6 +443,7 @@ struct ehci_qh {
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
 	struct usb_device	*dev;		/* access to TT */
 } __attribute__ ((aligned (32)));
+#endif /* EARLY_PRITNK */
 
 /*-------------------------------------------------------------------------*/
 
@@ -451,6 +457,7 @@ struct ehci_iso_packet {
 	u32			buf1;
 };
 
+#ifndef EARLY_PRINTK
 /* temporary schedule data for packets from iso urbs (both speeds)
  * each packet is one logical usb transaction to the device (not TT),
  * beginning at stream->next_uframe
@@ -586,6 +593,7 @@ struct ehci_sitd {
 	unsigned		frame;
 	unsigned		index;
 } __attribute__ ((aligned (32)));
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -607,6 +615,8 @@ struct ehci_fstn {
 	union ehci_shadow	fstn_next;	/* ptr to periodic q entry */
 } __attribute__ ((aligned (32)));
 
+#ifndef EARLY_PRINTK
+
 /*-------------------------------------------------------------------------*/
 
 #ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
@@ -704,4 +714,6 @@ static inline void ehci_writel (const struct ehci_hcd *ehci,
 
 /*-------------------------------------------------------------------------*/
 
+#endif /* EARLY_PRINTK */
+
 #endif /* __LINUX_EHCI_HCD_H */
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 80ea052..c644922 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -54,6 +54,7 @@ extern unsigned long __FIXADDR_TOP;
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VDSO,
+	FIX_DBGP_BASE,
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index e90e167..98290c3 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,7 @@ enum fixed_addresses {
 	VSYSCALL_LAST_PAGE,
 	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
 	VSYSCALL_HPET,
+	FIX_DBGP_BASE,
 	FIX_HPET_BASE,
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 	FIX_IO_APIC_BASE_0,
@@ -84,7 +85,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 	if (idx >= __end_of_fixed_addresses)
 		__this_fixmap_does_not_exist();
 
-        return __fix_to_virt(idx);
+	return __fix_to_virt(idx);
 }
 
 #endif

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3]x86_64: early_printk for early debug port support
  2007-05-21  5:19 [PATCH 3/3]x86_64: early_printk for early debug port support Yinghai Lu
@ 2007-05-22 19:31 ` Andrew Morton
  2007-05-22 19:43   ` Yinghai Lu
  2007-07-18 22:10 ` Andi Kleen
  1 sibling, 1 reply; 6+ messages in thread
From: Andrew Morton @ 2007-05-22 19:31 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andi Kleen, Eric W. Biederman, Greg KH, Bjorn Helgaas,
	Vivek Goyal, linux kernel mailing list

On Sun, 20 May 2007 22:19:18 -0700
"Yinghai Lu" <yhlu.kernel@gmail.com> wrote:

> add early dbgp to early_printk.
> 
> kernel command line:
> earlyprintk=dbgp
> or
> earlyprintk=dbgp1
> 
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
> 

Please try to sort out your email client?  MIME attachments are a pain to
reply to and are a pain to merge.

Please include a diffstat in patches so it is easy for people to see which
files are being altered.

The patch adds lots of new trailing whitespace.  Please trim that off
before sending.  Your editor's settings might need some attention.


>  arch/x86_64/kernel/early_printk.c |  600 ++++++++++++++++++++++++++++
>  drivers/usb/host/ehci.h           |   14 
>  include/asm-i386/fixmap.h         |    1 
>  include/asm-x86_64/fixmap.h       |    3 
>  4 files changed, 616 insertions(+), 2 deletions(-)

Please include an update to Documentation/kernel-parameters.txt

> diff -puN arch/x86_64/kernel/early_printk.c~x86_64-early_printk-for-early-debug-port-support arch/x86_64/kernel/early_printk.c
> --- a/arch/x86_64/kernel/early_printk.c~x86_64-early_printk-for-early-debug-port-support
> +++ a/arch/x86_64/kernel/early_printk.c
> @@ -3,9 +3,20 @@
>  #include <linux/init.h>
>  #include <linux/string.h>
>  #include <linux/screen_info.h>
> +#include <linux/usb/ch9.h>
> +#include <linux/pci_regs.h>
> +#include <linux/pci_ids.h>
> +#include <linux/errno.h>
> +
>  #include <asm/io.h>
>  #include <asm/processor.h>
>  #include <asm/fcntl.h>
> +#include <asm/pci-direct.h>
> +#include <asm/pgtable.h>
> +#include <asm/fixmap.h>
> +#define EARLY_PRINTK
> +#include "../../../drivers/usb/host/ehci.h"

err, perhaps we should move ehci.h somewhere more accessible? 
include/linux/usb/ would seem logical.


>  #include <xen/hvc-console.h>
>  
>  /* Simple VGA output */
> @@ -156,6 +167,582 @@ static struct console early_serial_conso
>  	.index =	-1,
>  };
>  
> +
> +static struct ehci_caps __iomem *ehci_caps;
> +static struct ehci_regs __iomem *ehci_regs;
> +static struct ehci_dbg_port __iomem *ehci_debug;
> +static unsigned dbgp_endpoint_out;
> +
> +#define USB_DEBUG_DEVNUM 127

What is this number?  Should it be documented?

> +#define DBGP_DATA_TOGGLE	0x8800
> +#define DBGP_PID_UPDATE(x, tok) \
> +	((((x) ^ DBGP_DATA_TOGGLE) & 0xffff00) | ((tok) & 0xff))
> +
> +#define DBGP_LEN_UPDATE(x, len) (((x) & ~0x0f) | ((len) & 0x0f))

Please convert the above into lowercase-named static inline C functions. 
Only use macros when for some reason regular C cannot be used.

> +static int dbgp_wait_until_complete(void)
> +{
> +	unsigned ctrl;
> +	int loop = 0x100000;
> +	do {

Please put a blank line between the end of the local definitions and the
start of the code.

> +		ctrl = readl(&ehci_debug->control);
> +		/* Stop when the transaction is finished */
> +		if (ctrl & DBGP_DONE)
> +			break;
> +	} while (--loop > 0);
> +
> +	if (!loop) return -1;

This needs a newline.

> +	/* Now that we have observed the completed transaction,
> +	 * clear the done bit.
> +	 */
> +	writel(ctrl | DBGP_DONE, &ehci_debug->control);
> +	return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
> +}
> +
> +static void dbgp_mdelay(int ms)
> +{
> +	int i;
> +	while (ms--) {
> +		for (i = 0; i < 1000; i++)
> +			outb(0x1, 0x80);
> +	}
> +}
> +
> +static void dbgp_breath(void)
> +{
> +	/* Sleep to give the debug port a chance to breathe */
> +}
> +
> +static int dbgp_wait_until_done(unsigned ctrl)
> +{
> +	unsigned pids, lpid;
> +	int ret;
> +
> +	int loop = 3;

Pelase don't put random blank lines in the middle of variable declarations.

> +retry:
> +	writel(ctrl | DBGP_GO, &ehci_debug->control);
> +	ret = dbgp_wait_until_complete();
> +	pids = readl(&ehci_debug->pids);
> +	lpid = DBGP_PID_GET(pids);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	/* If the port is getting full or it has dropped data
> +	 * start pacing ourselves, not necessary but it's friendly.
> +	 */
> +	if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET))
> +		dbgp_breath();
> +
> +	/* If I get a NACK reissue the transmission */
> +	if (lpid == USB_PID_NAK) {
> +		if(--loop > 0) goto retry;

Use "if (", rather that "if(".

Add a newline here.

> +	}

> +	return ret;
> +}
> +
> +static void dbgp_set_data(const void *buf, int size)
> +{
> +	const unsigned char *bytes = buf;
> +	unsigned lo, hi;
> +	int i;
> +	lo = hi = 0;
> +	for (i = 0; i < 4 && i < size; i++)
> +		lo |= bytes[i] << (8*i);
> +	for (; i < 8 && i < size; i++)
> +		hi |= bytes[i] << (8*(i - 4));
> +	writel(lo, &ehci_debug->data03);
> +	writel(hi, &ehci_debug->data47);
> +}
> +
> +static void dbgp_get_data(void *buf, int size)
> +{
> +	unsigned char *bytes = buf;
> +	unsigned lo, hi;
> +	int i;
> +	lo = readl(&ehci_debug->data03);
> +	hi = readl(&ehci_debug->data47);
> +	for (i = 0; i < 4 && i < size; i++)
> +		bytes[i] = (lo >> (8*i)) & 0xff;
> +	for (; i < 8 && i < size; i++)
> +		bytes[i] = (hi >> (8*(i - 4))) & 0xff;
> +}
> +
> +static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, const char *bytes, int size)

This line exceeds 80 columns

> +{
> +	unsigned pids, addr, ctrl;
> +	int ret;
> +	if (size > DBGP_MAX_PACKET)
> +		return -1;
> +
> +	addr = DBGP_EPADDR(devnum, endpoint);
> +
> +	pids = readl(&ehci_debug->pids);
> +	pids = DBGP_PID_UPDATE(pids, USB_PID_OUT);
> +
> +	ctrl = readl(&ehci_debug->control);
> +	ctrl = DBGP_LEN_UPDATE(ctrl, size);
> +	ctrl |= DBGP_OUT;
> +	ctrl |= DBGP_GO;
> +
> +	dbgp_set_data(bytes, size);
> +	writel(addr, &ehci_debug->address);
> +	writel(pids, &ehci_debug->pids);
> +
> +	ret = dbgp_wait_until_done(ctrl);
> +	if (ret < 0) {
> +		return ret;
> +	}

unneeded braces

> +	return ret;
> +}
> +
>
> ...
>
> +static int dbgp_control_msg(unsigned devnum, int requesttype, int request,
> +	int value, int index, void *data, int size)
> +{
> +	unsigned pids, addr, ctrl;
> +	struct usb_ctrlrequest req;
> +	int read;
> +	int ret;
> +
> +	read = (requesttype & USB_DIR_IN) != 0;
> +	if (size > (read?DBGP_MAX_PACKET:0))

Place spaces around the ?

> +		return -1;
> +
> +	/* Compute the control message */
> +	req.bRequestType = requesttype;
> +	req.bRequest = request;
> +	req.wValue = value;
> +	req.wIndex = index;
> +	req.wLength = size;
> +
> +	pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP);
> +	addr = DBGP_EPADDR(devnum, 0);
> +
> +	ctrl = readl(&ehci_debug->control);
> +	ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
> +	ctrl |= DBGP_OUT;
> +	ctrl |= DBGP_GO;
> +
> +	/* Send the setup message */
> +	dbgp_set_data(&req, sizeof(req));
> +	writel(addr, &ehci_debug->address);
> +	writel(pids, &ehci_debug->pids);
> +	ret = dbgp_wait_until_done(ctrl);
> +	if (ret < 0)
> +		return ret;
> +
> +

Only one blank line is needed

> +	/* Read the result */
> +	ret = dbgp_bulk_read(devnum, 0, data, size);
> +	return ret;
> +}
> +
> +
> +/* Find a PCI capability */
> +static __u32 __init find_cap(int num, int slot, int func, int cap)
> +{
> +	u8 pos;
> +	int bytes;
> +	if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
> +		return 0;
> +	pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
> +	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
> +		u8 id;
> +		pos &= ~3;
> +		id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
> +		if (id == 0xff)
> +			break;
> +		if (id == cap)
> +			return pos;
> +		pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
> +	}
> +	return 0;
> +}
> +
>
> ...
>
> +static int __init early_dbgp_init(char *s)

This function has no callers and causes a compiler warning.

> +static void early_dbgp_write(struct console *con, const char *str, unsigned n)

This function has a single reference:

> +{
> +	int chunk, ret;
> +	if (!ehci_debug)
> +		return;
> +	while (n > 0) {
> +		chunk = n;
> +		if (chunk > DBGP_MAX_PACKET)
> +			chunk = DBGP_MAX_PACKET;
> +		ret = dbgp_bulk_write(USB_DEBUG_DEVNUM,
> +			dbgp_endpoint_out, str, chunk);
> +		str += chunk;
> +		n -= chunk;
> +	}
> +}
> +
> +static struct console early_dbgp_console = {
> +	.name =		"earlydbg",
> +	.write =	early_dbgp_write,
> +	.flags = 	CON_PRINTBUFFER,
> +	.index = 	-1,
> +};

in here.  But nothing references early_dbgp_console, and another wraning is
emitted.

>  /* Console interface to a host file on AMD's SimNow! */
>  
>  static int simnow_fd;
> @@ -256,4 +843,17 @@ static int __init setup_early_printk(cha
>  	register_console(early_console);
>  	return 0;
>  }
> +
> +void __init enable_debug_console(char *buf)
> +{
> +#if DBGP_DEBUG
> +	if(early_console_initialized && early_console) {
> +		unregister_console(early_console);
> +		early_console_initialized = 0;
> +	}
> +	setup_early_printk(buf);
> +	keep_early = 1;
> +#endif
> +}

ah, and I guess that explains all the dead code.

>  early_param("earlyprintk", setup_early_printk);
> diff -puN drivers/usb/host/ehci.h~x86_64-early_printk-for-early-debug-port-support drivers/usb/host/ehci.h
> --- a/drivers/usb/host/ehci.h~x86_64-early_printk-for-early-debug-port-support
> +++ a/drivers/usb/host/ehci.h
> @@ -62,6 +62,7 @@ struct ehci_stats {
>  
>  #define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
>  
> +#ifndef EARLY_PRINTK
>  struct ehci_hcd {			/* one per controller */
>  	/* glue to PCI and HCD framework */
>  	struct ehci_caps __iomem *caps;
> @@ -189,6 +190,7 @@ timer_action (struct ehci_hcd *ehci, enu
>  		mod_timer (&ehci->watchdog, t);
>  	}
>  }
> +#endif /* EARLY_PRINTK */
>  
> [lots of similar stuff]
>

Why were all these ifdefs added?


<fiddles>

OK, I went through the exercise of removing all the unused-symbol warnings
which DBGP_DEBUG=0 produces and guess what?  None of the code which you've
added does anything!  It all has to be moved inside DBGP_DEBUG to avoid
unused-symbol warnings.  It's all a big no-op if DBGP_DEBUG=0.  I suspect
you did all your test and devel with DBGP_DEBUG=1, then turned DBGP_DEBUG
off and shipped the code without retesting?





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3]x86_64: early_printk for early debug port support
  2007-05-22 19:31 ` Andrew Morton
@ 2007-05-22 19:43   ` Yinghai Lu
  0 siblings, 0 replies; 6+ messages in thread
From: Yinghai Lu @ 2007-05-22 19:43 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Eric W. Biederman, Greg KH, Bjorn Helgaas,
	Vivek Goyal, linux kernel mailing list

On 5/22/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> OK, I went through the exercise of removing all the unused-symbol warnings
> which DBGP_DEBUG=0 produces and guess what?  None of the code which you've
> added does anything!  It all has to be moved inside DBGP_DEBUG to avoid
> unused-symbol warnings.  It's all a big no-op if DBGP_DEBUG=0.  I suspect
> you did all your test and devel with DBGP_DEBUG=1, then turned DBGP_DEBUG
> off and shipped the code without retesting?

Thanks. will format and test again. also will use KMail to mail it out.

YH

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3]x86_64: early_printk for early debug port support
  2007-05-21  5:19 [PATCH 3/3]x86_64: early_printk for early debug port support Yinghai Lu
  2007-05-22 19:31 ` Andrew Morton
@ 2007-07-18 22:10 ` Andi Kleen
  2007-07-18 22:32   ` Yinghai Lu
  2007-07-19  7:04   ` Yinghai Lu
  1 sibling, 2 replies; 6+ messages in thread
From: Andi Kleen @ 2007-07-18 22:10 UTC (permalink / raw)
  To: Yinghai Lu, Vivek Goyal
  Cc: Andrew Morton, Eric W. Biederman, Greg KH, Bjorn Helgaas,
	linux kernel mailing list

On Monday 21 May 2007 07:19:18 Yinghai Lu wrote:
> add early dbgp to early_printk.
> 
> kernel command line:
> earlyprintk=dbgp
> or
> earlyprintk=dbgp1

Just checking some old patches. Was there ever an update for this one?
What were the testing results? 

-Andi

> 
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
> 



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3]x86_64: early_printk for early debug port support
  2007-07-18 22:10 ` Andi Kleen
@ 2007-07-18 22:32   ` Yinghai Lu
  2007-07-19  7:04   ` Yinghai Lu
  1 sibling, 0 replies; 6+ messages in thread
From: Yinghai Lu @ 2007-07-18 22:32 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Vivek Goyal, Andrew Morton, Eric W. Biederman, Greg KH,
	Bjorn Helgaas, linux kernel mailing list

On 7/18/07, Andi Kleen <ak@suse.de> wrote:
> On Monday 21 May 2007 07:19:18 Yinghai Lu wrote:
> > add early dbgp to early_printk.
> >
> > kernel command line:
> > earlyprintk=dbgp
> > or
> > earlyprintk=dbgp1
>
> Just checking some old patches. Was there ever an update for this one?
> What were the testing results?

not yet.

will create one from my local tree tonight.

YH

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3]x86_64: early_printk for early debug port support
  2007-07-18 22:10 ` Andi Kleen
  2007-07-18 22:32   ` Yinghai Lu
@ 2007-07-19  7:04   ` Yinghai Lu
  1 sibling, 0 replies; 6+ messages in thread
From: Yinghai Lu @ 2007-07-19  7:04 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Vivek Goyal, Andrew Morton, Eric W. Biederman, Greg KH,
	Bjorn Helgaas, linux kernel mailing list

[-- Attachment #1: Type: text/plain, Size: 569 bytes --]

On 7/18/07, Andi Kleen <ak@suse.de> wrote:
> On Monday 21 May 2007 07:19:18 Yinghai Lu wrote:
> > add early dbgp to early_printk.
> >
> > kernel command line:
> > earlyprintk=dbgp
> > or
> > earlyprintk=dbgp1
>
> Just checking some old patches. Was there ever an update for this one?
> What were the testing results?
>
> -Andi
>

please check the attachment. the diff to current Linus'd git.

after remove pci quirks for usb handoff, it could get boot log till
ohci try to reset the port with debug device. --- reset will fail.

Maybe Greg could continue debug it.

YH

[-- Attachment #2: 9xxx.diff --]
[-- Type: text/x-patch, Size: 22720 bytes --]

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 9a54148..956d8dc 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -550,11 +550,12 @@ and is between 256 and 4096 characters. It is defined in the file
 	earlyprintk=	[IA-32,X86-64,SH]
 			earlyprintk=vga
 			earlyprintk=serial[,ttySn[,baudrate]]
+			earlyprintk=dbgp
 
 			Append ",keep" to not disable it when the real console
 			takes over.
 
-			Only vga or serial at a time, not both.
+			Only vga or serial or usb debug port at a time.
 
 			Currently only ttyS0 and ttyS1 are supported.
 
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index fd9aff3..3621d68 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -3,10 +3,19 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/screen_info.h>
+#include <linux/usb/ch9.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/fcntl.h>
 #include <xen/hvc-console.h>
+#include <asm/pci-direct.h>
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#define EARLY_PRINTK
+#include "../../../drivers/usb/host/ehci.h"
 
 /* Simple VGA output */
 
@@ -156,6 +165,594 @@ static struct console early_serial_console = {
 	.index =	-1,
 };
 
+
+static struct ehci_caps __iomem *ehci_caps;
+static struct ehci_regs __iomem *ehci_regs;
+static struct ehci_dbg_port __iomem *ehci_debug;
+static unsigned dbgp_endpoint_out;
+
+#define USB_DEBUG_DEVNUM 127
+
+#define DBGP_DATA_TOGGLE	0x8800
+
+static inline u32 dbgp_pid_update(u32 x, u32 tok)
+{
+	return ((((x) ^ DBGP_DATA_TOGGLE) & 0xffff00) | ((tok) & 0xff));
+}
+
+static inline u32 dbgp_len_update(u32 x, u32 len)
+{
+	return (((x) & ~0x0f) | ((len) & 0x0f));
+}
+
+/*
+ * USB Packet IDs (PIDs)
+ */
+
+/* token */
+#define USB_PID_OUT		0xe1
+#define USB_PID_IN		0x69
+#define USB_PID_SOF		0xa5
+#define USB_PID_SETUP		0x2d
+/* handshake */
+#define USB_PID_ACK		0xd2
+#define USB_PID_NAK		0x5a
+#define USB_PID_STALL		0x1e
+#define USB_PID_NYET		0x96
+/* data */
+#define USB_PID_DATA0		0xc3
+#define USB_PID_DATA1		0x4b
+#define USB_PID_DATA2		0x87
+#define USB_PID_MDATA		0x0f
+/* Special */
+#define USB_PID_PREAMBLE	0x3c
+#define USB_PID_ERR		0x3c
+#define USB_PID_SPLIT		0x78
+#define USB_PID_PING		0xb4
+#define USB_PID_UNDEF_0		0xf0
+
+#define USB_PID_DATA_TOGGLE	0x88
+#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
+
+#define PCI_CAP_ID_EHCI_DEBUG	0xa
+
+#define HUB_ROOT_RESET_TIME	50	/* times are in msec */
+#define HUB_SHORT_RESET_TIME	10
+#define HUB_LONG_RESET_TIME	200
+#define HUB_RESET_TIMEOUT	500
+
+#define DBGP_MAX_PACKET		8
+
+static int dbgp_wait_until_complete(void)
+{
+	unsigned ctrl;
+	int loop = 0x100000;
+
+	do {
+		ctrl = readl(&ehci_debug->control);
+		/* Stop when the transaction is finished */
+		if (ctrl & DBGP_DONE)
+			break;
+	} while (--loop > 0);
+
+	if (!loop)
+		return -1;
+
+	/* Now that we have observed the completed transaction,
+	 * clear the done bit.
+	 */
+	writel(ctrl | DBGP_DONE, &ehci_debug->control);
+	return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
+}
+
+static void dbgp_mdelay(int ms)
+{
+	int i;
+	while (ms--) {
+		for (i = 0; i < 1000; i++)
+			outb(0x1, 0x80);
+	}
+}
+
+static void dbgp_breath(void)
+{
+	/* Sleep to give the debug port a chance to breathe */
+}
+
+static int dbgp_wait_until_done(unsigned ctrl)
+{
+	unsigned pids, lpid;
+	int ret;
+	int loop = 3;
+
+retry:
+	writel(ctrl | DBGP_GO, &ehci_debug->control);
+	ret = dbgp_wait_until_complete();
+	pids = readl(&ehci_debug->pids);
+	lpid = DBGP_PID_GET(pids);
+
+	if (ret < 0)
+		return ret;
+
+	/* If the port is getting full or it has dropped data
+	 * start pacing ourselves, not necessary but it's friendly.
+	 */
+	if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET))
+		dbgp_breath();
+
+	/* If I get a NACK reissue the transmission */
+	if (lpid == USB_PID_NAK) {
+		if(--loop > 0)
+			goto retry;
+	}
+
+	return ret;
+}
+
+static void dbgp_set_data(const void *buf, int size)
+{
+	const unsigned char *bytes = buf;
+	unsigned lo, hi;
+	int i;
+
+	lo = hi = 0;
+	for (i = 0; i < 4 && i < size; i++)
+		lo |= bytes[i] << (8*i);
+	for (; i < 8 && i < size; i++)
+		hi |= bytes[i] << (8*(i - 4));
+	writel(lo, &ehci_debug->data03);
+	writel(hi, &ehci_debug->data47);
+}
+
+static void dbgp_get_data(void *buf, int size)
+{
+	unsigned char *bytes = buf;
+	unsigned lo, hi;
+	int i;
+	lo = readl(&ehci_debug->data03);
+	hi = readl(&ehci_debug->data47);
+	for (i = 0; i < 4 && i < size; i++)
+		bytes[i] = (lo >> (8*i)) & 0xff;
+	for (; i < 8 && i < size; i++)
+		bytes[i] = (hi >> (8*(i - 4))) & 0xff;
+}
+
+static int dbgp_bulk_write(unsigned devnum, unsigned endpoint,
+			 const char *bytes, int size)
+{
+	unsigned pids, addr, ctrl;
+	int ret;
+	if (size > DBGP_MAX_PACKET)
+		return -1;
+
+	addr = DBGP_EPADDR(devnum, endpoint);
+
+	pids = readl(&ehci_debug->pids);
+	pids = dbgp_pid_update(pids, USB_PID_OUT);
+
+	ctrl = readl(&ehci_debug->control);
+	ctrl = dbgp_len_update(ctrl, size);
+	ctrl |= DBGP_OUT;
+	ctrl |= DBGP_GO;
+
+	dbgp_set_data(bytes, size);
+	writel(addr, &ehci_debug->address);
+	writel(pids, &ehci_debug->pids);
+
+	ret = dbgp_wait_until_done(ctrl);
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, int size)
+{
+	unsigned pids, addr, ctrl;
+	int ret;
+
+	if (size > DBGP_MAX_PACKET)
+		return -1;
+
+	addr = DBGP_EPADDR(devnum, endpoint);
+
+	pids = readl(&ehci_debug->pids);
+	pids = dbgp_pid_update(pids, USB_PID_IN);
+
+	ctrl = readl(&ehci_debug->control);
+	ctrl = dbgp_len_update(ctrl, size);
+	ctrl &= ~DBGP_OUT;
+	ctrl |= DBGP_GO;
+
+	writel(addr, &ehci_debug->address);
+	writel(pids, &ehci_debug->pids);
+	ret = dbgp_wait_until_done(ctrl);
+	if (ret < 0)
+		return ret;
+	if (size > ret)
+		size = ret;
+	dbgp_get_data(data, size);
+	return ret;
+}
+
+static int dbgp_control_msg(unsigned devnum, int requesttype, int request,
+	int value, int index, void *data, int size)
+{
+	unsigned pids, addr, ctrl;
+	struct usb_ctrlrequest req;
+	int read;
+	int ret;
+
+	read = (requesttype & USB_DIR_IN) != 0;
+	if (size > (read ? DBGP_MAX_PACKET:0))
+		return -1;
+
+	/* Compute the control message */
+	req.bRequestType = requesttype;
+	req.bRequest = request;
+	req.wValue = value;
+	req.wIndex = index;
+	req.wLength = size;
+
+	pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP);
+	addr = DBGP_EPADDR(devnum, 0);
+
+	ctrl = readl(&ehci_debug->control);
+	ctrl = dbgp_len_update(ctrl, sizeof(req));
+	ctrl |= DBGP_OUT;
+	ctrl |= DBGP_GO;
+
+	/* Send the setup message */
+	dbgp_set_data(&req, sizeof(req));
+	writel(addr, &ehci_debug->address);
+	writel(pids, &ehci_debug->pids);
+	ret = dbgp_wait_until_done(ctrl);
+	if (ret < 0)
+		return ret;
+
+	/* Read the result */
+	ret = dbgp_bulk_read(devnum, 0, data, size);
+	return ret;
+}
+
+
+/* Find a PCI capability */
+static __u32 __init find_cap(int num, int slot, int func, int cap)
+{
+	u8 pos;
+	int bytes;
+	if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
+		return 0;
+	pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
+	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
+		u8 id;
+		pos &= ~3;
+		id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
+	}
+	return 0;
+}
+
+static __u32 __init find_dbgp(int ehci_num, unsigned *rbus, unsigned *rslot, unsigned *rfunc)
+{
+	unsigned bus, slot, func;
+
+	for (bus = 0; bus < 256; bus++) {
+		for (slot = 0; slot < 32; slot++) {
+			for (func = 0; func < 8; func++) {
+				u32 class;
+				unsigned cap;
+				class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION);
+				if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI)
+					continue;
+				cap = find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG);
+				if (!cap)
+					continue;
+				if (ehci_num-- != 0)
+					continue;
+				*rbus = bus;
+				*rslot = slot;
+				*rfunc = func;
+				return cap;
+			}
+		}
+	}
+	return 0;
+}
+
+static int ehci_reset_port(int port)
+{
+	unsigned portsc;
+	unsigned delay_time, delay;
+	int loop;
+
+	/* Reset the usb debug port */
+	portsc = readl(&ehci_regs->port_status[port - 1]);
+	portsc &= ~PORT_PE;
+	portsc |= PORT_RESET;
+	writel(portsc, &ehci_regs->port_status[port - 1]);
+
+	delay = HUB_ROOT_RESET_TIME;
+	for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT;
+	     delay_time += delay) {
+		dbgp_mdelay(delay);
+
+		portsc = readl(&ehci_regs->port_status[port - 1]);
+		if (portsc & PORT_RESET) {
+			/* force reset to complete */
+			loop = 2;
+			writel(portsc & ~(PORT_RWC_BITS | PORT_RESET),
+				&ehci_regs->port_status[port - 1]);
+			do {
+				portsc = readl(&ehci_regs->port_status[port - 1]);
+			} while ((portsc & PORT_RESET) && (--loop > 0));
+		}
+
+		/* Device went away? */
+		if (!(portsc & PORT_CONNECT))
+			return -ENOTCONN;
+
+		/* bomb out completely if something weird happend */
+		if ((portsc & PORT_CSC))
+			return -EINVAL;
+
+		/* If we've finished resetting, then break out of the loop */
+		if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
+			return 0;
+	}
+	return -EBUSY;
+}
+
+static int ehci_wait_for_port(int port)
+{
+	unsigned status;
+	int ret, reps;
+
+	for (reps = 0; reps < 3; reps++) {
+		dbgp_mdelay(100);
+		status = readl(&ehci_regs->status);
+		if (status & STS_PCD) {
+			ret = ehci_reset_port(port);
+			if (ret == 0)
+				return 0;
+		}
+	}
+	return -ENOTCONN;
+}
+
+
+#define DBGP_DEBUG 0
+#if DBGP_DEBUG
+void early_printk(const char *fmt, ...);
+# define dbgp_printk early_printk
+#else
+static inline void dbgp_printk(const char *fmt, ...) { }
+#endif
+
+static int ehci_setup(void)
+{
+	unsigned cmd, ctrl, status, portsc, hcs_params, debug_port, n_ports;
+	int ret;
+	int loop;
+
+	hcs_params = readl(&ehci_caps->hcs_params);
+	debug_port = HCS_DEBUG_PORT(hcs_params);
+	n_ports    = HCS_N_PORTS(hcs_params);
+
+	dbgp_printk("debug_port: %d\n", debug_port);
+	dbgp_printk("n_ports:    %d\n", n_ports);
+
+	loop = 10;
+	/* Reset the EHCI controller */
+	cmd = readl(&ehci_regs->command);
+	cmd |= CMD_RESET;
+	writel(cmd, &ehci_regs->command);
+	do {
+		cmd = readl(&ehci_regs->command);
+	} while ((cmd & CMD_RESET) && (--loop > 0));
+
+	/* Claim ownership, but do not enable yet */
+	ctrl = readl(&ehci_debug->control);
+	ctrl |= DBGP_OWNER;
+	ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
+	writel(ctrl, &ehci_debug->control);
+
+	/* Start the ehci running */
+	cmd = readl(&ehci_regs->command);
+	cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
+	cmd |= CMD_RUN;
+	writel(cmd, &ehci_regs->command);
+
+	/* Ensure everything is routed to the EHCI */
+	writel(FLAG_CF, &ehci_regs->configured_flag);
+
+	/* Wait until the controller is no longer halted */
+	loop = 10;
+	do {
+		status = readl(&ehci_regs->status);
+	} while ((status & STS_HALT) && (--loop > 0));
+
+	/* Wait for a device to show up in the debug port */
+	ret = ehci_wait_for_port(debug_port);
+	if (ret < 0) {
+		dbgp_printk("No device found in debug port\n");
+		return -1;
+	}
+
+	/* Enable the debug port */
+	ctrl = readl(&ehci_debug->control);
+	ctrl |= DBGP_CLAIM;
+	writel(ctrl, &ehci_debug->control);
+	ctrl = readl(&ehci_debug->control);
+	if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
+		dbgp_printk("No device in debug port\n");
+		writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control);
+		return -1;
+
+	}
+
+	/* Completely transfer the debug device to the debug controller */
+	portsc = readl(&ehci_regs->port_status[debug_port - 1]);
+	portsc &= ~PORT_PE;
+	writel(portsc, &ehci_regs->port_status[debug_port - 1]);
+
+	return 0;
+}
+
+static int __init early_dbgp_init(char *s)
+{
+	struct usb_debug_descriptor dbgp_desc;
+	void __iomem *ehci_bar;
+	unsigned ctrl, devnum;
+	unsigned bus, slot, func, cap;
+	unsigned debug_port, bar, offset;
+	unsigned bar_val;
+	char *e;
+	int ret;
+	unsigned dbgp_num;
+
+	if (!early_pci_allowed())
+		return -1;
+
+	dbgp_num = 0;
+	if (*s) {
+		dbgp_num = simple_strtoul(s, &e, 10);
+	}
+	dbgp_printk("dbgp_num: %d\n", dbgp_num);
+	cap = find_dbgp(dbgp_num, &bus, &slot, &func);
+	if (!cap)
+		return -1;
+
+	dbgp_printk("Found EHCI debug port\n");
+
+	debug_port = read_pci_config(bus, slot, func, cap);
+	bar = (debug_port >> 29) & 0x7;
+	bar = (bar * 4) + 0xc;
+	offset = (debug_port >> 16) & 0xfff;
+	dbgp_printk("bar: %02x offset: %03x\n", bar, offset);
+	if (bar != PCI_BASE_ADDRESS_0) {
+		dbgp_printk("only debug ports on bar 1 handled.\n");
+		return -1;
+	}
+
+	bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
+	dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset);
+	if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) {
+		dbgp_printk("only simple 32bit mmio bars supported\n");
+		return -1;
+	}
+
+
+	/* FIXME I don't have the bar size so just guess PAGE_SIZE is more
+	 * than enough.  1K is the biggest I have seen.
+	 */
+	dbgp_printk("dbgp pre-set_fixmap_nocache\n");
+	set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK);
+	dbgp_printk("dbgp post-set_fixmap_nocache\n");
+	ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE);
+	ehci_bar += bar_val & ~PAGE_MASK;
+	dbgp_printk("ehci_bar: %p\n", ehci_bar);
+
+	ehci_caps  = ehci_bar;
+	ehci_regs  = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase));
+	ehci_debug = ehci_bar + offset;
+
+	ret = ehci_setup();
+	if (ret < 0) {
+		dbgp_printk("ehci_setup failed\n");
+		ehci_debug = 0;
+		return -1;
+	}
+	dbgp_mdelay(100);
+
+	/* Find the debug device and make it device number 127 */
+	for (devnum = 0; devnum <= 127; devnum++) {
+		ret = dbgp_control_msg(devnum,
+			USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+			USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
+			&dbgp_desc, sizeof(dbgp_desc));
+		if (ret > 0)
+			break;
+	}
+	if (devnum > 127) {
+		dbgp_printk("Could not find attached debug device\n");
+		goto err;
+	}
+	if (ret < 0) {
+		dbgp_printk("Attached device is not a debug device\n");
+		goto err;
+	}
+	dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
+
+	/* Move the device to 127 if it isn't already there */
+	if (devnum != USB_DEBUG_DEVNUM) {
+		ret = dbgp_control_msg(devnum,
+			USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+			USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
+		if (ret < 0) {
+			dbgp_printk("Could not move attached device to %d\n",
+				USB_DEBUG_DEVNUM);
+			goto err;
+		}
+		devnum = USB_DEBUG_DEVNUM;
+	}
+
+	/* Enable the debug interface */
+	ret = dbgp_control_msg(USB_DEBUG_DEVNUM,
+		USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+		USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0);
+	if (ret < 0) {
+		dbgp_printk(" Could not enable the debug device\n");
+		goto err;
+	}
+
+	/* Perform a small write to get the even/odd data state in sync
+	 */
+	ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ",1);
+	if (ret < 0) {
+		dbgp_printk("dbgp_bulk_write failed: %d\n", ret);
+		goto err;
+	}
+
+
+	return 0;
+err:
+	/* Things didn't work so remove my claim */
+	ctrl = readl(&ehci_debug->control);
+	ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
+	writel(ctrl, &ehci_debug->control);
+	ehci_debug = 0;
+
+	return -1;
+}
+
+static void early_dbgp_write(struct console *con, const char *str, unsigned n)
+{
+	int chunk, ret;
+	if (!ehci_debug)
+		return;
+	while (n > 0) {
+		chunk = n;
+		if (chunk > DBGP_MAX_PACKET)
+			chunk = DBGP_MAX_PACKET;
+		ret = dbgp_bulk_write(USB_DEBUG_DEVNUM,
+			dbgp_endpoint_out, str, chunk);
+		str += chunk;
+		n -= chunk;
+	}
+}
+
+static struct console early_dbgp_console = {
+	.name =		"earlydbg",
+	.write =	early_dbgp_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
 /* Console interface to a host file on AMD's SimNow! */
 
 static int simnow_fd;
@@ -213,10 +810,11 @@ void early_printk(const char *fmt, ...)
 	va_end(ap);
 }
 
-static int __initdata keep_early;
 
 static int __init setup_early_printk(char *buf)
 {
+	int keep_early;
+
 	if (!buf)
 		return 0;
 
@@ -224,8 +822,7 @@ static int __init setup_early_printk(char *buf)
 		return 0;
 	early_console_initialized = 1;
 
-	if (strstr(buf, "keep"))
-		keep_early = 1;
+	keep_early = (strstr(buf, "keep") != NULL);
 
 	if (!strncmp(buf, "serial", 6)) {
 		early_serial_init(buf + 6);
@@ -239,10 +836,14 @@ static int __init setup_early_printk(char *buf)
 		max_ypos = SCREEN_INFO.orig_video_lines;
 		current_ypos = SCREEN_INFO.orig_y;
 		early_console = &early_vga_console;
- 	} else if (!strncmp(buf, "simnow", 6)) {
- 		simnow_init(buf + 6);
- 		early_console = &simnow_console;
- 		keep_early = 1;
+	} else if (!strncmp(buf, "simnow", 6)) {
+		simnow_init(buf + 6);
+		early_console = &simnow_console;
+		keep_early = 1;
+	} else if (!strncmp(buf, "dbgp", 4)) {
+		if (early_dbgp_init(buf+4) < 0)
+			return 0;
+		early_console = &early_dbgp_console;
 #ifdef CONFIG_HVC_XEN
 	} else if (!strncmp(buf, "xen", 3)) {
 		early_console = &xenboot_console;
@@ -256,4 +857,17 @@ static int __init setup_early_printk(char *buf)
 	register_console(early_console);
 	return 0;
 }
+
+void __init enable_debug_console(char *buf)
+{
+#if DBGP_DEBUG
+	if(early_console_initialized && early_console) {
+		unregister_console(early_console);
+		early_console_initialized = 0;
+	}
+
+	setup_early_printk(buf);
+#endif
+}
+
 early_param("earlyprintk", setup_early_printk);
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 6c34bdd..b972f7c 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -58,6 +58,8 @@ static void __init copy_bootdata(char *real_mode_data)
 	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 }
 
+extern void __init enable_debug_console(char *buf);
+
 void __init x86_64_start_kernel(char * real_mode_data)
 {
 	int i;
@@ -74,10 +76,14 @@ void __init x86_64_start_kernel(char * real_mode_data)
 
 	early_printk("Kernel alive\n");
 
- 	for (i = 0; i < NR_CPUS; i++)
- 		cpu_pda(i) = &boot_cpu_pda[i];
+	for (i = 0; i < NR_CPUS; i++)
+		cpu_pda(i) = &boot_cpu_pda[i];
 
 	pda_init(0);
+
+	enable_debug_console("ttyS0,115200");
+	enable_debug_console("dbgp,keep");
+
 	copy_bootdata(__va(real_mode_data));
 #ifdef CONFIG_SMP
 	cpu_set(0, cpu_online_map);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c4e15ed..d772a63 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -213,8 +213,13 @@ static void tdi_reset (struct ehci_hcd *ehci)
 static int ehci_reset (struct ehci_hcd *ehci)
 {
 	int	retval;
-	u32	command = ehci_readl(ehci, &ehci->regs->command);
+	u32	command;
 
+	/* don't reset, if debug port is used */
+	if (ehci->debug)
+		return 0;
+
+	command = ehci_readl(ehci, &ehci->regs->command);
 	command |= CMD_RESET;
 	dbg_cmd (ehci, "reset", command);
 	ehci_writel(ehci, command, &ehci->regs->command);
@@ -396,11 +401,17 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
 		return;
 
 	ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
-	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
+	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+		/* do not touch debug port if it is used */
+		if (ehci->debug && port == HCS_DEBUG_PORT(ehci->hcs_params))
+			continue;
+
 		(void) ehci_hub_control(ehci_to_hcd(ehci),
 				is_on ? SetPortFeature : ClearPortFeature,
 				USB_PORT_FEAT_POWER,
 				port--, NULL, 0);
+	}
+
 	/* Flush those writes */
 	ehci_readl(ehci, &ehci->regs->command);
 	msleep(20);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2c68a04..9842a05 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -62,6 +62,7 @@ struct ehci_stats {
 
 #define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
 
+#ifndef EARLY_PRINTK
 struct ehci_hcd {			/* one per controller */
 	/* glue to PCI and HCD framework */
 	struct ehci_caps __iomem *caps;
@@ -192,6 +193,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
 		mod_timer (&ehci->watchdog, t);
 	}
 }
+#endif /* EARLY_PRINTK */
 
 /*-------------------------------------------------------------------------*/
 
@@ -337,6 +339,8 @@ struct ehci_dbg_port {
 
 #define	QTD_NEXT(ehci, dma)	cpu_to_hc32(ehci, (u32)dma)
 
+#ifndef EARLY_PRINTK
+
 /*
  * EHCI Specification 0.95 Section 3.5
  * QTD: describe data transfer components (buffer, direction, ...)
@@ -377,7 +381,7 @@ struct ehci_qtd {
 	struct urb		*urb;			/* qtd's urb */
 	size_t			length;			/* length of buffer */
 } __attribute__ ((aligned (32)));
-
+#endif
 /* mask NakCnt+T in qh->hw_alt_next */
 #define QTD_MASK(ehci)	cpu_to_hc32 (ehci, ~0x1f)
 
@@ -434,6 +438,7 @@ union ehci_shadow {
  * These appear in both the async and (for interrupt) periodic schedules.
  */
 
+#ifndef EARLY_PRINTK
 struct ehci_qh {
 	/* first part defined by EHCI spec */
 	__hc32			hw_next;	/* see EHCI 3.6.1 */
@@ -497,6 +502,7 @@ struct ehci_qh {
 	__le32			was_active;	/* active bit before "i" set */
 #endif
 } __attribute__ ((aligned (32)));
+#endif /* EARLY_PRITNK */
 
 /*-------------------------------------------------------------------------*/
 
@@ -510,6 +516,7 @@ struct ehci_iso_packet {
 	u32			buf1;
 };
 
+#ifndef EARLY_PRINTK
 /* temporary schedule data for packets from iso urbs (both speeds)
  * each packet is one logical usb transaction to the device (not TT),
  * beginning at stream->next_uframe
@@ -645,6 +652,7 @@ struct ehci_sitd {
 	unsigned		frame;
 	unsigned		index;
 } __attribute__ ((aligned (32)));
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -666,6 +674,8 @@ struct ehci_fstn {
 	union ehci_shadow	fstn_next;	/* ptr to periodic q entry */
 } __attribute__ ((aligned (32)));
 
+#ifndef EARLY_PRINTK
+
 /*-------------------------------------------------------------------------*/
 
 #ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
@@ -832,4 +842,6 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
 
 /*-------------------------------------------------------------------------*/
 
+#endif /* EARLY_PRINTK */
+
 #endif /* __LINUX_EHCI_HCD_H */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index c225159..3b379ff 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -358,4 +358,4 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
 	else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI)
 		quirk_usb_disable_ehci(pdev);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
+//DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-07-19  7:05 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-05-21  5:19 [PATCH 3/3]x86_64: early_printk for early debug port support Yinghai Lu
2007-05-22 19:31 ` Andrew Morton
2007-05-22 19:43   ` Yinghai Lu
2007-07-18 22:10 ` Andi Kleen
2007-07-18 22:32   ` Yinghai Lu
2007-07-19  7:04   ` Yinghai Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).