LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* RE: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
@ 2006-12-07  3:20 Lu, Yinghai
  2006-12-09  1:17 ` Greg KH
  0 siblings, 1 reply; 10+ messages in thread
From: Lu, Yinghai @ 2006-12-07  3:20 UTC (permalink / raw)
  To: Greg KH, Eric W. Biederman
  Cc: USB development list, Stefan Reinauer, Peter Stuge, linux-kernel,
	Andi Kleen

Greg,

I wonder why the netconsole could print all boot log from beginning with
buffer. But your usb serial console can not.

YH



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

* Re: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
  2006-12-07  3:20 [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support Lu, Yinghai
@ 2006-12-09  1:17 ` Greg KH
  0 siblings, 0 replies; 10+ messages in thread
From: Greg KH @ 2006-12-09  1:17 UTC (permalink / raw)
  To: Lu, Yinghai
  Cc: Eric W. Biederman, USB development list, Stefan Reinauer,
	Peter Stuge, linux-kernel, Andi Kleen

On Wed, Dec 06, 2006 at 07:20:16PM -0800, Lu, Yinghai wrote:
> Greg,
> 
> I wonder why the netconsole could print all boot log from beginning with
> buffer. But your usb serial console can not.

Buffer size?  flow control?  the fact that the buffer has already
overflowed?  Who knows, don't trust usb-serial as a real "console"
please :)

thanks,

greg k-h

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

* RE: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
@ 2006-12-09  1:20 Lu, Yinghai
  0 siblings, 0 replies; 10+ messages in thread
From: Lu, Yinghai @ 2006-12-09  1:20 UTC (permalink / raw)
  To: Greg KH
  Cc: Eric W. Biederman, USB development list, Stefan Reinauer,
	Peter Stuge, linux-kernel, Andi Kleen


-----Original Message-----
From: Greg KH [mailto:gregkh@suse.de] 
Sent: Friday, December 08, 2006 5:17 PM

>Buffer size?  flow control?  the fact that the buffer has already
>overflowed?  Who knows, don't trust usb-serial as a real "console"
>please :)

I set buffer size to 128k, and can get all.

Thanks

YH



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

* RE: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
@ 2006-12-05  3:18 Lu, Yinghai
  0 siblings, 0 replies; 10+ messages in thread
From: Lu, Yinghai @ 2006-12-05  3:18 UTC (permalink / raw)
  To: Greg KH, Eric W. Biederman
  Cc: USB development list, Stefan Reinauer, Peter Stuge, linuxbios,
	linux-kernel, Andi Kleen

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

-----Original Message-----
From: Greg KH [mailto:gregkh@suse.de] 
Sent: Monday, December 04, 2006 4:45 PM
To: Eric W. Biederman
Cc: Lu, Yinghai; USB development list; Stefan Reinauer; Peter Stuge;
linuxbios@linuxbios.org; linux-kernel@vger.kernel.org; Andi Kleen
Subject: Re: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device
support.

On Mon, Dec 04, 2006 at 02:26:52PM -0700, Eric W. Biederman wrote:
> Greg KH <gregkh@suse.de> writes:
> 

> Anyway next time I touch this the project will be how to integrate
> this into the kernel cleanly.  This round was to figure out how
> to get some working code.

Please check the adapted version for LinuxBIOS with your kernel patch.
Hope your next version could have more good shape ...

YH

[-- Attachment #2: usbdebug_direct.h --]
[-- Type: application/octet-stream, Size: 590 bytes --]

#ifndef USBDEBUG_DIRECT_H
#define USBDEBUG_DIRECT_H

struct ehci_debug_info {
        void *ehci_caps;
        void *ehci_regs;
        void *ehci_debug;
        unsigned devnum;
        unsigned endpoint_out;
        unsigned endpoint_in;
};
extern int dbgp_bulk_write_x(struct ehci_debug_info *dbg_info, const char *bytes, int size);
extern int dbgp_bulk_read_x(struct ehci_debug_info *dbg_info, void *data, int size);
extern void usbdebug_direct_init(unsigned ehci_bar, unsigned ehci_debug_offset, struct ehci_debug_info *dbg_info);
extern void set_ehci_base(unsigned ehci_base);
#endif

[-- Attachment #3: usbdebug_direct.c --]
[-- Type: application/octet-stream, Size: 12250 bytes --]

/*
 * Copyright (C) 2006 Eric Biederman (ebiederm@xmission.com)
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License version
 *	2 as published by the Free Software Foundation.
 *
 */
#ifndef __ROMCC__
#include <console/console.h>
#else
#if CONFIG_USE_PRINTK_IN_CAR==0
#define printk_debug(fmt, arg...)   do {} while(0)
#endif
#endif


#include <arch/io.h>

#include <usb_ch9.h>
#include <ehci.h>
#include <usbdebug_direct.h>

#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(struct ehci_dbg_port *ehci_debug)
{
	unsigned ctrl;
	for (;;) {
		ctrl = readl(&ehci_debug->control);
		/* Stop when the transaction is finished */
		if (ctrl & DBGP_DONE)
			break;
	}
	/* 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(struct ehci_dbg_port *ehci_debug, unsigned ctrl)
{
	unsigned pids, lpid;
	int ret;

retry:
	writel(ctrl | DBGP_GO, &ehci_debug->control);
	ret = dbgp_wait_until_complete(ehci_debug);
	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)
		goto retry;

	return ret;
}

static void dbgp_set_data(struct ehci_dbg_port *ehci_debug, 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(struct ehci_dbg_port *ehci_debug, 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(struct ehci_dbg_port *ehci_debug, 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(ehci_debug, bytes, size);
	writel(addr, &ehci_debug->address);
	writel(pids, &ehci_debug->pids);

	ret = dbgp_wait_until_done(ehci_debug, ctrl);
	if (ret < 0) {
		return ret;
	}
	return ret;
}

int dbgp_bulk_write_x(struct ehci_debug_info *dbg_info, const char *bytes, int size)
{
	return dbgp_bulk_write(dbg_info->ehci_debug, dbg_info->devnum, dbg_info->endpoint_out, bytes, size);
}

static int dbgp_bulk_read(struct ehci_dbg_port *ehci_debug, 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(ehci_debug, ctrl);
	if (ret < 0)
		return ret;
	if (size > ret)
		size = ret;
	dbgp_get_data(ehci_debug, data, size);
	return ret;
}
int dbgp_bulk_read_x(struct ehci_debug_info *dbg_info, void *data, int size)
{
	return dbgp_bulk_read(dbg_info->ehci_debug, dbg_info->devnum, dbg_info->endpoint_in, data, size);
}

static int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, 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(ehci_debug, &req, sizeof(req));
	writel(addr, &ehci_debug->address);
	writel(pids, &ehci_debug->pids);
	ret = dbgp_wait_until_done(ehci_debug, ctrl);
	if (ret < 0)
		return ret;


	/* Read the result */
	ret = dbgp_bulk_read(ehci_debug, devnum, 0, data, size);
	return ret;
}

static int ehci_reset_port(struct ehci_regs *ehci_regs, int port)
{
	unsigned portsc;
	unsigned delay_time, delay;

	/* 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 */
			writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), 
				&ehci_regs->port_status[port - 1]);
			while (portsc & PORT_RESET)
				portsc = readl(&ehci_regs->port_status[port - 1]);
		}

		/* Device went away? */
		if (!(portsc & PORT_CONNECT))
			return -107;//-ENOTCONN;

		/* bomb out completely if something weird happend */
		if ((portsc & PORT_CSC))
			return -22;//-EINVAL;

		/* If we've finished resetting, then break out of the loop */
		if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
			return 0;
	}
	return -16;//-EBUSY;
}

static int ehci_wait_for_port(struct ehci_regs *ehci_regs, int port)
{
	unsigned status;
	int ret, reps;
	for (reps = 0; reps <1000; reps++) {
		status = readl(&ehci_regs->status);
		if (status & STS_PCD) {
			ret = ehci_reset_port(ehci_regs, port);
			if (ret == 0)
				return 0;
		}
	}
	return -107; //-ENOTCONN;
}


#define DBGP_DEBUG 1
#if DBGP_DEBUG
# define dbgp_printk printk_debug
#else
#define dbgp_printk(fmt, arg...)   do {} while(0)
#endif

static int ehci_setup( struct ehci_caps *ehci_caps, 
	struct ehci_regs *ehci_regs, 
	struct ehci_dbg_port *ehci_debug)
{
	unsigned cmd, ctrl, status, portsc, hcs_params, debug_port, n_ports;
	int ret;

	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);

	/* Reset the EHCI controller */
	cmd = readl(&ehci_regs->command);
	cmd |=CMD_RESET;
	writel(cmd, &ehci_regs->command);
	while (cmd & CMD_RESET)
		cmd = readl(&ehci_regs->command);
	
	/* 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 */
	do {
		status = readl(&ehci_regs->status);
	} while (status & STS_HALT);

	/* Wait for a device to show up in the debug port */
	ret = ehci_wait_for_port(ehci_regs, debug_port);
	if (ret < 0) {
		dbgp_printk("No device found in debug port\n");
		return -1;
	}
	dbgp_printk("3");

	/* 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;
}

void usbdebug_direct_init(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info)
{
	struct ehci_caps *ehci_caps;
	struct ehci_regs *ehci_regs;
	struct ehci_dbg_port *ehci_debug;
	unsigned dbgp_endpoint_out;
	unsigned dbgp_endpoint_in;
	struct usb_debug_descriptor dbgp_desc;
	unsigned ctrl, devnum;
	int ret;

	ehci_caps  = (struct ehci_caps *)ehci_bar;
	ehci_regs  = (struct ehci_regs *)(ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase)));
	ehci_debug = (struct ehci_dbg_port *)(ehci_bar + offset);

	ret = ehci_setup(ehci_caps, ehci_regs, ehci_debug);
	if (ret < 0) {
		dbgp_printk("ehci_setup failed\n");
		return;
	}

	/* Find the debug device and make it device number 127 */
	for (devnum = 0; devnum <= 127; devnum++) {
		ret = dbgp_control_msg(ehci_debug, 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;
	dbgp_endpoint_in = dbgp_desc.bDebugInEndpoint;

	/* Move the device to 127 if it isn't already there */
	if (devnum != USB_DEBUG_DEVNUM) {
		ret = dbgp_control_msg(ehci_debug, devnum,
			USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
			USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, (void *)0, 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(ehci_debug, USB_DEBUG_DEVNUM,
		USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
		USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, (void *)0, 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(ehci_debug, USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ",1);
	if (ret < 0) {
		dbgp_printk("dbgp_bulk_write failed: %d\n", ret);
		goto err;
	}

	info->ehci_caps = ehci_caps;
	info->ehci_regs = ehci_regs;
	info->ehci_debug = ehci_debug;
	info->devnum = devnum;
	info->endpoint_out = dbgp_endpoint_out;
	info->endpoint_in = dbgp_endpoint_in;
	
	return;
err:
	/* Things didn't work so remove my claim */
	ctrl = readl(&ehci_debug->control);
	ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
	writel(ctrl, &ehci_debug->control);
	return;
}



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

* Re: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
  2006-12-04 21:26   ` Eric W. Biederman
@ 2006-12-05  0:45     ` Greg KH
  0 siblings, 0 replies; 10+ messages in thread
From: Greg KH @ 2006-12-05  0:45 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Lu, Yinghai, USB development list, Stefan Reinauer, Peter Stuge,
	linuxbios, linux-kernel, Andi Kleen

On Mon, Dec 04, 2006 at 02:26:52PM -0700, Eric W. Biederman wrote:
> Greg KH <gregkh@suse.de> writes:
> 
> > On Mon, Dec 04, 2006 at 12:18:30PM -0800, Lu, Yinghai wrote:
> >> -----Original Message-----
> >> From: ebiederm@xmission.com [mailto:ebiederm@xmission.com] 
> >> 
> >> >arch/x86_64/kernel/early_printk.c |  574
> >> +++++++++++++++++++++++++++++++++++++
> >> > drivers/usb/host/ehci.h           |    8 +
> >> > include/asm-x86_64/fixmap.h       |    1 
> >> 
> >> Can you separate usbdebug handle out from early_printk? 
> >
> > Yeah, at least tear it out of x86-64, so those of us stuck on different
> > platforms can use this :)
> >
> > Other than that minor issue, this looks great.  I don't have a x86-64
> > box set up here at the moment, so I can't test it, but it looks
> > acceptable at first glance.
> 
> Makes sense.  I'm curious now what architecture do you have?

i386

My main development box these days is a mac mini due to it's great form
factor and ability to suspend to ram easily.  Unfortunately they don't
come with a working 64bit processor just yet.

> Anyway next time I touch this the project will be how to integrate
> this into the kernel cleanly.  This round was to figure out how
> to get some working code.
> 
> If someone beats me to the punch on generalizing this code I won't
> mind.
> 
> The first pass was a success.  And the performance is reasonable
> assuming you don't plug the end you are watching into a usb1 only
> port.
> 
> Given that I didn't really know anything about usb a week ago I think
> I did pretty well :)

Yes, you certainly did, no complaint from me at all about that :)

thanks,

greg k-h

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

* Re: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
  2006-12-04 20:33 ` Greg KH
@ 2006-12-04 21:26   ` Eric W. Biederman
  2006-12-05  0:45     ` Greg KH
  0 siblings, 1 reply; 10+ messages in thread
From: Eric W. Biederman @ 2006-12-04 21:26 UTC (permalink / raw)
  To: Greg KH
  Cc: Lu, Yinghai, USB development list, Stefan Reinauer, Peter Stuge,
	linuxbios, linux-kernel, Andi Kleen

Greg KH <gregkh@suse.de> writes:

> On Mon, Dec 04, 2006 at 12:18:30PM -0800, Lu, Yinghai wrote:
>> -----Original Message-----
>> From: ebiederm@xmission.com [mailto:ebiederm@xmission.com] 
>> 
>> >arch/x86_64/kernel/early_printk.c |  574
>> +++++++++++++++++++++++++++++++++++++
>> > drivers/usb/host/ehci.h           |    8 +
>> > include/asm-x86_64/fixmap.h       |    1 
>> 
>> Can you separate usbdebug handle out from early_printk? 
>
> Yeah, at least tear it out of x86-64, so those of us stuck on different
> platforms can use this :)
>
> Other than that minor issue, this looks great.  I don't have a x86-64
> box set up here at the moment, so I can't test it, but it looks
> acceptable at first glance.

Makes sense.  I'm curious now what architecture do you have?

Anyway next time I touch this the project will be how to integrate
this into the kernel cleanly.  This round was to figure out how
to get some working code.

If someone beats me to the punch on generalizing this code I won't
mind.

The first pass was a success.  And the performance is reasonable
assuming you don't plug the end you are watching into a usb1 only
port.

Given that I didn't really know anything about usb a week ago I think
I did pretty well :)

Eric

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

* RE: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
@ 2006-12-04 20:52 Lu, Yinghai
  0 siblings, 0 replies; 10+ messages in thread
From: Lu, Yinghai @ 2006-12-04 20:52 UTC (permalink / raw)
  To: ebiederm, Greg KH
  Cc: USB development list, Stefan Reinauer, Peter Stuge, linuxbios,
	linux-kernel, Andi Kleen

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

Eric,

Please check the version I modified for LinuxBIOS from your
usbdebug_direct.

Put the related info in
struct ehci_debug_info {
        void *ehci_base;
        void *ehci_op_base;
        void *ehci_debug_base;
        unsigned devnum;
        unsigned endpoint_out;
        unsigned endpoint_in;
	int inited;
};

So for CAR stage code, I could put it the range after stack and easy to
retrieve.

YH

[-- Attachment #2: usbdebug_direct.h --]
[-- Type: application/octet-stream, Size: 608 bytes --]

#ifndef USBDEBUG_DIRECT_H
#define USBDEBUG_DIRECT_H

struct ehci_debug_info {
        void *ehci_base;
        void *ehci_op_base;
        void *ehci_debug_base;
        unsigned devnum;
        unsigned endpoint_out;
        unsigned endpoint_in;
	int inited;
};
extern int usb_bulk_write_x(struct ehci_debug_info *dbg_info, const char *bytes, int size);
extern int usb_bulk_read_x(struct ehci_debug_info *dbg_info, void *data, int size);
extern int usbdebug_direct_init(unsigned ehci_bar, unsigned ehci_debug_offset, struct ehci_debug_info *dbg_info);
extern void set_ehci_base(unsigned ehci_base);
#endif

[-- Attachment #3: usbdebug_direct.c --]
[-- Type: application/octet-stream, Size: 14476 bytes --]

/*
 * Copyright (C) 2006 Eric Biederman (ebiederm@xmission.com)
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License version
 *	2 as published by the Free Software Foundation.
 *
 */
#ifndef __ROMCC__
#include <console/console.h>
#else
#if CONFIG_USE_PRINTK_IN_CAR==0
#define printk_debug(fmt, arg...)   do {} while(0)
#endif
#endif


#include <arch/io.h>

#include <usbdebug_direct.h>

//#define EHCI_BAR 0xbfce0000
#define EHCI_BAR_BYTES 4096
//#define EHCI_DEBUG_OFFSET 0x98

/* Off of ehci_base */
#define EHCI_CAPLENGTH		0x00
#define EHCI_HCIVERSION		0x02
#define EHCI_HCSPARAMS		0x04
#define EHCI_HCCPARAMS		0x08
#define EHCI_HCSP_PORTROUTE	0x0c
/* Off of ehci_op_base */
#define EHCI_USBCMD		0x00
#define  EHCI_USBCMD_RUN		(1 << 0)
#define EHCI_USBSTS		0x04
#define  EHCI_USBSTS_HCHALTED		(1 << 12)
#define EHCI_USBINTR		0x08
#define EHCI_FRINDEX		0x0c
#define EHCI_CTRLDSSEGMENT	0x10
#define EHCI_PERIODICLISTBASE	0x14
#define EHCI_ASYNCLISTADDR	0x18
#define EHCI_CONFIGFLAG		0x40
#define  EHCI_CONFIGFLAG_FLAG		(1 << 0)
#define EHCI_PORTSC		0x44
#define  EHCI_PORTSC_PORT_OWNER			(1 << 13)
#define  EHCI_PORTSC_PORT_RESET			(1 << 12)
#define  EHCI_PORTSC_PORT_ENABLED		(1 << 2)
#define  EHCI_PORTSC_CONNECT_STATUS_CHANGED	(1 << 1)
#define  EHCI_PORTSC_CONNECTED			(1 << 0)
/* Off of ehci_debug_base */
#define EHCI_CTRL	0x00
#define  EHCI_CTRL_OWNER			(1 << 30)
#define  EHCI_CTRL_ENABLED			(1 << 28)
#define  EHCI_CTRL_DONE				(1 << 16)
#define  EHCI_CTRL_INUSE			(1 << 10)
#define  EHCI_CTRL_EXCEPTION_MASK		7
#define  EHCI_CTRL_EXCEPTION_SHIFT		7
#define  EHCI_CTRL_EXCEPTION_NONE		0
#define  EHCI_CTRL_EXCEPTION_TRANSACTION	1
#define  EHCI_CTRL_EXCEPTION_HARDWARE		2
#define  EHCI_CTRL_ERROR			(1 << 6)
#define  EHCI_CTRL_GO				(1 << 5)
#define  EHCI_CTRL_WRITE			(1 << 4)
#define  EHCI_CTRL_LENGTH_MASK			(0xf << 0)
#define EHCI_PID		0x04
#define  EHCI_PID_RECEIVED_SHIFT	16
#define  EHCI_PID_SEND_SHIFT		8
#define  EHCI_PID_TOKEN_SHIFT		0
#define EHCI_DATA0	0x08
#define EHCI_DATA1	0x0c
#define EHCI_ADDR	0x10
#define  EHCI_ADDR_DEVNUM_SHIFT   8
#define  EHCI_ADDR_ENDPOINT_SHIFT 0
#define MKPID(x) (((x) & 0xf) | ((~(x) & 0xf) << 4))
/* token */
#define PID_OUT	MKPID(0x1)
#define PID_IN	MKPID(0x9)
#define PID_SOF	MKPID(0x5)
#define PID_SETUP	MKPID(0xd)
/* data */
#define PID_DATA0	MKPID(0x3)
#define PID_DATA1	MKPID(0xb)
#define PID_DATA2	MKPID(0x7)
#define PID_MDATA	MKPID(0xf)
#define PID_DATA_TOGGLE	(0x88)
/* handshake */
#define PID_ACK	MKPID(0x2)
#define PID_NAK	MKPID(0xa)
#define PID_STALL	MKPID(0xe)
#define PID_NYET	MKPID(0x6)
/* Special */
#define PID_PRE	MKPID(0xc)
#define PID_ERR	MKPID(0xc)
#define PID_SPLIT	MKPID(0x8)
#define PID_PING	MKPID(0x4)
#define PID_RESERVED	MKPID(0x0)
/*
 * Standard requests
 */
#define USB_REQ_GET_STATUS              0x00
#define USB_REQ_CLEAR_FEATURE           0x01
/* 0x02 is reserved */
#define USB_REQ_SET_FEATURE             0x03
/* 0x04 is reserved */
#define USB_REQ_SET_ADDRESS             0x05
#define USB_REQ_GET_DESCRIPTOR          0x06
#define USB_REQ_SET_DESCRIPTOR          0x07
#define USB_REQ_GET_CONFIGURATION       0x08
#define USB_REQ_SET_CONFIGURATION       0x09
#define USB_REQ_GET_INTERFACE           0x0A
#define USB_REQ_SET_INTERFACE           0x0B
#define USB_REQ_SYNCH_FRAME             0x0C
#define USB_TYPE_STANDARD	(0x00 << 5)
#define USB_TYPE_CLASS		(0x01 << 5)
#define USB_TYPE_VENDOR		(0x02 << 5)
#define USB_TYPE_RESERVED	(0x03 << 5)

#define USB_RECIP_DEVICE                0x00
#define USB_RECIP_INTERFACE             0x01
#define USB_RECIP_ENDPOINT              0x02
#define USB_RECIP_OTHER                 0x03

/*
 * Various libusb API related stuff
 */
#define USB_ENDPOINT_IN                 0x80
#define USB_ENDPOINT_OUT                0x00

#ifndef USB_DT_DEBUG
#define USB_DT_DEBUG	10
#endif
#ifndef USB_FT_DEBUG_MODE
#define USB_FT_DEBUG_MODE	6
#endif 

struct usb_debug_descriptor {
	uint8_t	bLength;
	uint8_t bDescriptorType;
	uint8_t bDebugInEndpoint;
	uint8_t bDebugOutEndpoint;
} __attribute__ ((packed));
struct usb_status {
	uint16_t status;
} __attribute__ ((packed));

struct usb_request {
	uint8_t  bmRequestType;
	uint8_t  bRequest;
	uint16_t wValue;
	uint16_t wIndex;
	uint16_t wLength;
} __attribute__ ((packed));
static int usb_wait_until_complete(void *ehci_debug_base)
{
	unsigned ctrl;
	for (;;) {
		ctrl = readl(ehci_debug_base + EHCI_CTRL);
		/* Stop when the transaction is finished */
		if (ctrl & EHCI_CTRL_DONE)
			break;
	}
	/* Now that we have observed the completed transaction,
	 * clear the done bit.
	 */
	writel(ctrl | EHCI_CTRL_DONE, ehci_debug_base + EHCI_CTRL);
	return (ctrl & EHCI_CTRL_ERROR) ? 
		-((ctrl >> EHCI_CTRL_EXCEPTION_SHIFT) & EHCI_CTRL_EXCEPTION_MASK):
		ctrl & 0xf;
}
static void usb_breath(void)
{
// with out_port 80? in CAR stage
// or tsc?
	mdelay(10);
}
static int usb_wait_until_done(void *ehci_debug_base, unsigned ctrl)
{
	unsigned pids, lpid;
	int ret;
retry:
	writel(ctrl | EHCI_CTRL_GO, ehci_debug_base + EHCI_CTRL);
	ret = usb_wait_until_complete(ehci_debug_base);
	pids = readl(ehci_debug_base + EHCI_PID);
	lpid = (pids >> EHCI_PID_RECEIVED_SHIFT) & 0xff;
#if 1
	if ((ret >= 0) && lpid != PID_ACK)
		printk_debug("lpid: %02x ret: %d\n", lpid, ret);
#endif
	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 == PID_NAK) || (lpid == PID_NYET))
		usb_breath();
	/* If I get a NACK reissue the transmission */
	if (lpid == PID_NAK)
		goto retry;
	return ret;
}
static void usb_set_data(void *ehci_debug_base, const void *buf, int size)
{
	const unsigned char *bytes = buf;
	uint32_t 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_base + EHCI_DATA0);
	writel(hi, ehci_debug_base + EHCI_DATA1);
}
static void usb_get_data(void *ehci_debug_base, void *buf, int size)
{
	unsigned char *bytes = buf;
	uint32_t lo, hi;
	int i;
	lo = readl(ehci_debug_base + EHCI_DATA0);
	hi = readl(ehci_debug_base + EHCI_DATA1);
#if 0
	printf("data: %08x%08x\n", hi, lo);
#endif
	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 usb_bulk_write(void *ehci_debug_base, int address, int endpoint, const char *bytes, int size)
{
	unsigned pids, addr, ctrl;
	int ret;
	if (size > 8)
		return -1;
	addr = ((address & 0x7f) << EHCI_ADDR_DEVNUM_SHIFT) | (endpoint & 0xf);
	pids = readl(ehci_debug_base + EHCI_PID);
	pids &= ~(0xff << EHCI_PID_TOKEN_SHIFT);
	pids |= PID_OUT << EHCI_PID_TOKEN_SHIFT;
	pids ^= (PID_DATA_TOGGLE << EHCI_PID_SEND_SHIFT);
	ctrl = readl(ehci_debug_base + EHCI_CTRL);
	ctrl &= ~EHCI_CTRL_LENGTH_MASK;
	ctrl |= EHCI_CTRL_WRITE;
	ctrl |= size & EHCI_CTRL_LENGTH_MASK;
	ctrl |= EHCI_CTRL_GO;
	usb_set_data(ehci_debug_base, bytes, size);
	writel(addr, ehci_debug_base + EHCI_ADDR);
	writel(pids, ehci_debug_base + EHCI_PID);

	ret = usb_wait_until_done(ehci_debug_base, ctrl);
	if (ret < 0) {
		printk_debug("out failed!: %d\n", ret);
		return ret;
	}
	return ret;
}
int usb_bulk_write_x(struct ehci_debug_info *dbg_info, const char *bytes, int size)
{
	return usb_bulk_write(dbg_info->ehci_debug_base, dbg_info->devnum, dbg_info->endpoint_out, bytes, size);
}
static int usb_bulk_read(void *ehci_debug_base, int address, int endpoint, void *data, int size)
{
	unsigned pids, addr, ctrl;
	int ret;
	if (size > 8)
		return -1;
	addr = ((address & 0x7f) << EHCI_ADDR_DEVNUM_SHIFT) | (endpoint & 0xf);
	pids = readl(ehci_debug_base + EHCI_PID);
	pids &= ~(0xff << EHCI_PID_TOKEN_SHIFT);
	pids |= PID_IN << EHCI_PID_TOKEN_SHIFT;
	pids ^= (PID_DATA_TOGGLE << EHCI_PID_SEND_SHIFT);
	ctrl = readl(ehci_debug_base + EHCI_CTRL);
	ctrl &= ~EHCI_CTRL_LENGTH_MASK;
	ctrl &= ~EHCI_CTRL_WRITE;
	ctrl |= size & EHCI_CTRL_LENGTH_MASK;
	ctrl |= EHCI_CTRL_GO;
	writel(addr, ehci_debug_base + EHCI_ADDR);
	writel(pids, ehci_debug_base + EHCI_PID);
	ret = usb_wait_until_done(ehci_debug_base, ctrl);
	if (ret < 0) {
		printk_debug("in failed!: %d\n", ret);
		return ret;
	}
	if (size > ret)
		size = ret;
	usb_get_data(ehci_debug_base, data, size);
	return ret;
}

int usb_bulk_read_x(struct ehci_debug_info *dbg_info, void *data, int size)
{
	return usb_bulk_read(dbg_info->ehci_debug_base, dbg_info->devnum, dbg_info->endpoint_in, data, size);
}

static int usb_control_msg(void *ehci_debug_base, int address, int requesttype, int request, 
	int value, int index, void *data, int size)
{
	unsigned pids, addr, ctrl;
	struct usb_request req;
	int read;
	int ret;
	read = (requesttype & USB_ENDPOINT_IN) != 0;
	if (size > (read?8:0))
		return -1;
	/* Compute the control message */
	req.bmRequestType = requesttype;
	req.bRequest = request;
	req.wValue = value;
	req.wIndex = index;
	req.wLength = size;
	pids = PID_SETUP << EHCI_PID_TOKEN_SHIFT;
	pids |= PID_DATA0 << EHCI_PID_SEND_SHIFT;
	addr = ((address & 0x7f) << EHCI_ADDR_DEVNUM_SHIFT) | 0;
	ctrl = readl(ehci_debug_base + EHCI_CTRL);
	ctrl &= ~EHCI_CTRL_LENGTH_MASK;
	ctrl |= EHCI_CTRL_WRITE;
	ctrl |= sizeof(req) & EHCI_CTRL_LENGTH_MASK;
	ctrl |= EHCI_CTRL_GO;
	/* Send the setup message */
	usb_set_data(ehci_debug_base, &req, sizeof(req));
	writel(addr, ehci_debug_base + EHCI_ADDR);
	writel(pids, ehci_debug_base + EHCI_PID);
	ret = usb_wait_until_done(ehci_debug_base, ctrl);
	if (ret < 0) {
		//printk_debug("setup failed!: %d\n", ret);
		return ret;
	}

	/* Read the result */
	ret = usb_bulk_read(ehci_debug_base, address, 0, data, size);
#if 0
	pids = readl(ehci_debug_base + EHCI_PID);
	printf("final pids: %08x ret: %d, size: %d\n", pids, ret, size);
#endif
	return ret;
}
static int usb_control_msg0(void *ehci_debug_base, int address, int requesttype, int request, 
	int value, int index)
{
	return usb_control_msg(ehci_debug_base, address, requesttype, request, value, index, (void *)0, 0);
}
int usbdebug_direct_init(unsigned ehci_bar, unsigned ehci_debug_offset, struct ehci_debug_info *dbg_info)
{
	void *ehci_base, *ehci_op_base, *ehci_debug_base;

	struct usb_debug_descriptor debug;
	unsigned endpoint_out, endpoint_in;
	unsigned devnum;
	unsigned hcsparams;
	unsigned debug_port, n_ports;
	unsigned val;
	int result = -1;
	int ret, i;

	ehci_base = ehci_bar;
	val = readb(ehci_base + EHCI_CAPLENGTH);
	ehci_op_base = ehci_base + val;
	ehci_debug_base = ehci_base + ehci_debug_offset;

	hcsparams = readl(ehci_base + EHCI_HCSPARAMS);
	debug_port = (hcsparams >> 20) & 0xf;
	n_ports = hcsparams & 0xf;

	printk_debug("debug_port: %d\n", debug_port);
	printk_debug("n_ports:    %d\n", n_ports);

	for (i = 1; i <= n_ports; i++) {
		val = readl(ehci_op_base + EHCI_PORTSC + (4*(i - 1)));
		printk_debug("portsc%d: %08x\n", i, val);
	}

#define EHCI_CTRL_CLAIM (EHCI_CTRL_OWNER | EHCI_CTRL_ENABLED | EHCI_CTRL_INUSE)
	val  = readl(ehci_debug_base + EHCI_CTRL);
	printk_debug("ctrl: %04x\n", val);
	writel(val | EHCI_CTRL_CLAIM, ehci_debug_base + EHCI_CTRL);
	val  = readl(ehci_debug_base + EHCI_CTRL);
	printk_debug("ctrl: %04x\n", val);
	if ((val & EHCI_CTRL_CLAIM) != EHCI_CTRL_CLAIM) {
		printk_debug("No device in debug port\n");
		writel(val & ~EHCI_CTRL_CLAIM, ehci_debug_base + EHCI_CTRL);
		return -1;
	}

	printk_debug("Find the debug device!\n");

	/* Find the debug device and make it device number 127 */
	for (devnum = 0; devnum <= 127; devnum++) {
		//printf("devnum: %d\n", devnum);
		ret = usb_control_msg(ehci_debug_base, devnum, 
			USB_ENDPOINT_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
			USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
			&debug, sizeof(debug));
		if (ret > 0)
			break;
	}
	if (devnum > 127) {
		printk_debug("Could not find attached debug device\n");
		goto err;
	}
	if (ret < 0) {
		printk_debug("Attach device is not a debug device\n");
		goto err;
	}
	printk_debug("devnum: %d\n", devnum);
	endpoint_out = debug.bDebugOutEndpoint;
	endpoint_in = debug.bDebugInEndpoint;
	
	

	/* Move the device to 127 if it isn't already there */
	if (devnum != 127) {
		ret = usb_control_msg0(ehci_debug_base, devnum,
			USB_TYPE_STANDARD | USB_RECIP_DEVICE,
			USB_REQ_SET_ADDRESS, 127, 0);
		printk_debug("set_address: %d\n", ret);
		if (ret < 0) {
			printk_debug("Could not move attached device to 127\n");
			goto err;
		}
		devnum = 127;
	}
	/* Enable the debug interface */
	ret = usb_control_msg0(ehci_debug_base, devnum, USB_TYPE_STANDARD | USB_RECIP_DEVICE,
		USB_REQ_SET_FEATURE, USB_FT_DEBUG_MODE, 0);
	printk_debug("set_feature_debug_mode: %d\n", ret);
	if (ret < 0) {
		printk_debug(" Could not enable the debug device\n");
		goto err;
	}

	dbg_info->ehci_base = ehci_base;
	dbg_info->ehci_op_base = ehci_op_base;
	dbg_info->ehci_debug_base = ehci_debug_base;
	dbg_info->devnum = devnum;
	dbg_info->endpoint_out = endpoint_out;
	dbg_info->endpoint_in = endpoint_in;
#if 0
	{
		//unsigned devnum = 2;
		//unsigned endpoint_out = 1;
		//unsigned endpoint_in = 0x82;
		char *test_strings[] = {
			"zero000\n",
			"one1111\n",
			"two2222\n",
			"three33\n",
			"four444\n",
			"five555\n",
			"six6666\n",
			"seven77\n",
			"eight88\n",
			"nine999\n",
			"tenaaaa\n",
			"elevenb\n",
			(void *)0,
		};
		char **ptr;
		/* Perform a small write to get the even/odd data state in sync
		 */
		ret = usb_bulk_write(ehci_debug_base, devnum, endpoint_out, " ",1);
		printk_debug("usb_bulk_write: %d\n", ret);
		/* Write the test messages */
		for (ptr = test_strings; *ptr; ptr++) {
			/* Write a test message */
			ret = usb_bulk_write(ehci_debug_base, devnum, endpoint_out,
				*ptr, 8);
			printk_debug("usb_bulk_write: %d\n", ret);
		}
	}
#endif
#if 0
	/* Read some test messages */
	for (;;) {
		char buf[8];
		ret = usb_bulk_read(ehci_debug_base, devnum, endpoint_in, 
			buf, sizeof(buf));
		if (ret > 0)
			printk_debug("%d:%*.*s", ret, ret, ret, buf);
	}
#endif
#if 0
	for (i = 0; i < 256; i+=1) {
		val = readb(ehci_base + i);
		printk_debug("%02x ", val);
		if ((i & 0xf) == 0xf)
			printk_debug("\n");
	}
	printk_debug("\n");
#endif
	result = 0;
	dbg_info->inited = 1;
	return result;
err:
#ifdef EHCI_CTRL_CLAIM
	val = readl(ehci_debug_base + EHCI_CTRL);
	printk_debug("ctrl: %08x\n", val);
	val &= ~(EHCI_CTRL_CLAIM | EHCI_CTRL_WRITE);
	writel(val, ehci_debug_base + EHCI_CTRL);
	val = readl(ehci_debug_base + EHCI_CTRL);
	printk_debug("ctrl: %08x\n", val);
#endif
	return result;
}

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

* Re: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
  2006-12-04 20:18 Lu, Yinghai
@ 2006-12-04 20:33 ` Greg KH
  2006-12-04 21:26   ` Eric W. Biederman
  0 siblings, 1 reply; 10+ messages in thread
From: Greg KH @ 2006-12-04 20:33 UTC (permalink / raw)
  To: Lu, Yinghai
  Cc: ebiederm, USB development list, Stefan Reinauer, Peter Stuge,
	linuxbios, linux-kernel, Andi Kleen

On Mon, Dec 04, 2006 at 12:18:30PM -0800, Lu, Yinghai wrote:
> -----Original Message-----
> From: ebiederm@xmission.com [mailto:ebiederm@xmission.com] 
> 
> >arch/x86_64/kernel/early_printk.c |  574
> +++++++++++++++++++++++++++++++++++++
> > drivers/usb/host/ehci.h           |    8 +
> > include/asm-x86_64/fixmap.h       |    1 
> 
> Can you separate usbdebug handle out from early_printk? 

Yeah, at least tear it out of x86-64, so those of us stuck on different
platforms can use this :)

Other than that minor issue, this looks great.  I don't have a x86-64
box set up here at the moment, so I can't test it, but it looks
acceptable at first glance.

thanks,

greg k-h

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

* RE: [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
@ 2006-12-04 20:18 Lu, Yinghai
  2006-12-04 20:33 ` Greg KH
  0 siblings, 1 reply; 10+ messages in thread
From: Lu, Yinghai @ 2006-12-04 20:18 UTC (permalink / raw)
  To: ebiederm, USB development list
  Cc: Greg KH, Stefan Reinauer, Peter Stuge, linuxbios, linux-kernel,
	Andi Kleen

-----Original Message-----
From: ebiederm@xmission.com [mailto:ebiederm@xmission.com] 

>arch/x86_64/kernel/early_printk.c |  574
+++++++++++++++++++++++++++++++++++++
> drivers/usb/host/ehci.h           |    8 +
> include/asm-x86_64/fixmap.h       |    1 

Can you separate usbdebug handle out from early_printk? 
So We can share the code in LinuxBIOS easier. I like the version like
usbdebug_direct.c.
Also separate related USB debug port defines in one separate header file
too.

YH




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

* [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support.
  2006-12-04  5:13       ` [RFC][PATCH 1/2] x86_64: Preallocate the fixmap pud and pmd entries Eric W. Biederman
@ 2006-12-04  5:18         ` Eric W. Biederman
  0 siblings, 0 replies; 10+ messages in thread
From: Eric W. Biederman @ 2006-12-04  5:18 UTC (permalink / raw)
  To: USB development list
  Cc: Greg KH, Lu, Yinghai, Stefan Reinauer, Peter Stuge, linuxbios,
	linux-kernel, Andi Kleen


This patch is still a little rough but it gets all of the major pieces
correct.  With a little more work this should become a maintainable
driver.

In particular I believe the ehci debug port code is fairly solid
(with rough edges).  However there are several nasty bits that
need to be resolved before we can push this upstream.  Like
my include of ehci.h  And general early kernel space dependency
problems.

But the code works for me so it should at least be a reasonable starting
point for others looking to make the debug port work in a reasonable fashion.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 arch/x86_64/kernel/early_printk.c |  574 +++++++++++++++++++++++++++++++++++++
 drivers/usb/host/ehci.h           |    8 +
 include/asm-x86_64/fixmap.h       |    1 
 3 files changed, 583 insertions(+), 0 deletions(-)

diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index d4050a5..cb5182d 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -3,9 +3,19 @@ #include <linux/kernel.h>
 #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,558 @@ 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
+
+#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;
+	for (;;) {
+		ctrl = readl(&ehci_debug->control);
+		/* Stop when the transaction is finished */
+		if (ctrl & DBGP_DONE)
+			break;
+	}
+	/* 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;
+
+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)
+		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;
+
+	/* 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 */
+			writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), 
+				&ehci_regs->port_status[port - 1]);
+			while (portsc & PORT_RESET)
+				portsc = readl(&ehci_regs->port_status[port - 1]);
+		}
+
+		/* 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 >= 0; reps++) {
+		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 i;
+
+	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);
+
+	/* Reset the EHCI controller */
+	cmd = readl(&ehci_regs->command);
+	cmd |=CMD_RESET;
+	writel(cmd, &ehci_regs->command);
+	while (cmd & CMD_RESET)
+		cmd = readl(&ehci_regs->command);
+
+	/* 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 */
+	do {
+		status = readl(&ehci_regs->status);
+	} while (status & STS_HALT);
+
+	/* 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 __init void 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;
+	unsigned dbgp_num;
+	char *e;
+	int ret;
+
+	if (!early_pci_allowed())
+		return;
+
+	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;
+
+	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;
+	if (bar != PCI_BASE_ADDRESS_0) {
+		dbgp_printk("only debug ports on bar 1 handled.\n");
+		return;
+	}
+
+	/* FIXME this assumes the bar is a 32bit mmio bar */
+	bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
+
+	/* FIXME I don't have the bar size so just guess PAGE_SIZE is more
+	 * than enough.  1K is the biggest I have seen.
+	 */
+	set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK);
+	ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE);
+	ehci_bar += bar_val & ~PAGE_MASK;
+
+	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");
+		return;
+	}
+
+	/* 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;
+err:
+	/* Things didn't work so remove my claim */
+	ctrl = readl(&ehci_debug->control);
+	ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
+	writel(ctrl, &ehci_debug->control);
+	return;
+}
+
+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,
+};
+
+#endif
+
 /* Console interface to a host file on AMD's SimNow! */
 
 static int simnow_fd;
@@ -242,8 +804,20 @@ static int __init setup_early_printk(cha
  		simnow_init(buf + 6);
  		early_console = &simnow_console;
  		keep_early = 1;
+	} else if (!strncmp(buf, "dbgp", 4)) {
+		early_dbgp_init(buf + 4);
+		early_console = &early_dbgp_console;
 	}
 	register_console(early_console);
+#if DBGP_DEBUG
+	{
+		static const char dbgp_test_str[] = 
+			"The quick brown fox jumped over the lazy dog!\n";
+		early_dbgp_init("");
+		early_dbgp_write(&early_dbgp_console, 
+			dbgp_test_str, sizeof(dbgp_test_str) - 1);
+	}
+#endif
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bbc3082..0a67192 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;
@@ -160,6 +161,7 @@ timer_action (struct ehci_hcd *ehci, enu
 		mod_timer (&ehci->watchdog, t);
 	}
 }
+#endif /* EARLY_PRINTK */
 
 /*-------------------------------------------------------------------------*/
 
@@ -384,6 +386,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 */
@@ -432,6 +435,7 @@ #define	QH_STATE_COMPLETING	5		/* don't 
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
 	struct usb_device	*dev;		/* access to TT */
 } __attribute__ ((aligned (32)));
+#endif /* EARLY_PRITNK */
 
 /*-------------------------------------------------------------------------*/
 
@@ -601,6 +605,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
@@ -659,4 +665,6 @@ #endif	/* DEBUG */
 
 /*-------------------------------------------------------------------------*/
 
+#endif /* EARLY_PRINTK */
+
 #endif /* __LINUX_EHCI_HCD_H */
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index 1b620db..1f2978a 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -36,6 +36,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,
-- 
1.4.2.rc3.g7e18e-dirty


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

end of thread, other threads:[~2006-12-09  1:21 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-07  3:20 [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support Lu, Yinghai
2006-12-09  1:17 ` Greg KH
  -- strict thread matches above, loose matches on Subject: below --
2006-12-09  1:20 Lu, Yinghai
2006-12-05  3:18 Lu, Yinghai
2006-12-04 20:52 Lu, Yinghai
2006-12-04 20:18 Lu, Yinghai
2006-12-04 20:33 ` Greg KH
2006-12-04 21:26   ` Eric W. Biederman
2006-12-05  0:45     ` Greg KH
2006-12-01 18:55 [LinuxBIOS] #57: libusb host program for PLX NET20DC debug device Lu, Yinghai
2006-12-01 19:19 ` Greg KH
2006-12-03 15:49   ` Eric W. Biederman
2006-12-04  5:09     ` [RFC][PATCH 0/2] x86_64 Early usb debug port support Eric W. Biederman
2006-12-04  5:13       ` [RFC][PATCH 1/2] x86_64: Preallocate the fixmap pud and pmd entries Eric W. Biederman
2006-12-04  5:18         ` [RFC][PATCH 2/2] x86_64: earlyprintk usb debug device support Eric W. Biederman

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).