Skip to contentSkip to conversation

IA-64 Linux TODO list

Linux-ia64 David Mosberger 7 participants 9 messages Jan 9, 2001 – Jan 25, 2001 USB

lore
Share & tools
lore
#0 lore raw

Since we're getting closer to a real release of various IA-64 Linux distros, I thought it would be a good idea to pass around my TODO list. I'd really appreciate if someone else could maintain this list and mail it out periodically (weekly?) as my bw is pretty limited right now. Here is what comes to mind:

Kernel
- enable kernel unaligned handler
- verify that all on-board hardware is supported and working:
- does cs4281 sound driver work reliably now?
- what to do about eepro100? (currently hangs on > 180MB transfers?)
- investigate and fix test suite failures reported by SCO (Who's the contact person at SCO for this? Please make available simple test cases that reproduce the problem so we can go about fixing them.)
- consider clearing CPU state on an execve() to avoid leaking information to a new program; Alan Cox thinks it would be sufficient to do this when current->dumpable is zero

Libraries
- gprof support?

Apps
- gdb
- NaT bits don't seem to work properly?
- coredump support still broken?
- strace
- 'strace -f' hangs if the program forks a child;
- verify that the new system calls have been added

I'm planning to work on the kernel unaligned handler but if someone else is dying on doing that, let me know. ;-)

If you can think of anything else, please let me know---I'll try keep the list uptodate for now.

	--david
#1 lore raw

(I know I'm going to regret this...)

I'm willing to take on the taks of maintaining this list. For now I'll put David's name next to the kernel unaligned handler' and I'm willing to look into the strace' issues. If anyone else is willing to take on anything let me know and I'll add your name. I think it would be a good idea to have a responsible person for each item if possible.

Quoted 41 lines · David Mosberger

Since we're getting closer to a real release of various IA-64 Linux distros, I thought it would be a good idea to pass around my TODO list. I'd really appreciate if someone else could maintain this list and mail it out periodically (weekly?) as my bw is pretty limited right now. Here is what comes to mind:

Kernel
- enable kernel unaligned handler
- verify that all on-board hardware is supported and working:
- does cs4281 sound driver work reliably now?
- what to do about eepro100? (currently hangs on > 180MB transfers?)
- investigate and fix test suite failures reported by SCO (Who's the contact person at SCO for this? Please make available simple test cases that reproduce the problem so we can go about fixing them.)
- consider clearing CPU state on an execve() to avoid leaking information to a new program; Alan Cox thinks it would be sufficient to do this when current->dumpable is zero

Libraries
- gprof support?

Apps
- gdb
- NaT bits don't seem to work properly?
- coredump support still broken?
- strace
- 'strace -f' hangs if the program forks a child;
- verify that the new system calls have been added

I'm planning to work on the kernel unaligned handler but if someone else is dying on doing that, let me know. ;-)

If you can think of anything else, please let me know---I'll try keep the list uptodate for now.

	--david

_______________________________________________
Linux-IA64 mailing list
[email protected]
http://lists.linuxia64.org/lists/listinfo/linux-ia64

Signature · 4 lines
Don Dugger
"Censeo Toto nos in Kansa esse decisse." - D. Gale
[email protected]
Ph: 303/938-9838
#2 lore raw
In reply to David Mosberger
Quoted 2 lines · David Mosberger

- verify that all on-board hardware is supported and working:
- does cs4281 sound driver work reliably now?

Yes, we use it as a module and it works w/o problems. You need an updated mpg123 and/or xmms RPM, though.

Quoted 2 lines

If you can think of anything else, please let me know---I'll try keep the list uptodate for now.

What's the status of kernel AGP support? Also, the DRI module for ATI Rage128 would be nice.

Uros

--
Uros Prestor
[email protected]

#3 lore raw
In reply to David Mosberger

I've been looking at AGPGART and DRI for the Rage128 and the Matrox G400 for a couple of months.

I have an experimental version of a 460GX AGPGART driver which satisfies the DRI modules in X to a great enough extent that I can boot into X and have glxinfo report that direct rendering is enabled. The GART translation tables look OK and GART translation seems to be occurring, however GL rendering isn't working yet (typical failures involve a DRM module querying the graphics adapter and not getting an adequate response).

If AGPGART for 460GX and a DRI module for Rage128 are going to be on the TODO list, I'll sign up as the owner. Thanks,

Chris

-----Original Message-----
From: Uros Prestor [mailto:[email protected]]
Sent: Tuesday, January 09, 2001 12:06 PM
To: [email protected]
Cc: [email protected]
Subject: Re: [Linux-ia64] IA-64 Linux TODO list

Quoted 2 lines · David Mosberger

- verify that all on-board hardware is supported and working:
- does cs4281 sound driver work reliably now?

Yes, we use it as a module and it works w/o problems. You need an updated mpg123 and/or xmms RPM, though.

Quoted 2 lines

If you can think of anything else, please let me know---I'll try keep the list uptodate for now.

What's the status of kernel AGP support? Also, the DRI module for ATI Rage128
would be nice.

Uros

--
Uros Prestor
[email protected]

_______________________________________________
Linux-IA64 mailing list
[email protected]
http://lists.linuxia64.org/lists/listinfo/linux-ia64

#4 lore raw
In reply to David Mosberger
Quoted 6 lines · Don Dugger

I'm willing to take on the taks of maintaining this list. For now I'll put David's name next to the kernel unaligned handler' and I'm willing to look into the strace' issues. If anyone else is willing to take on anything let me know and I'll add your name. I think it would be a good idea to have a responsible person for each item if possible.

Put me down for gdb.

Quoted 3 lines
Quoted 3 lines

- gdb
- NaT bits don't seem to work properly?
- coredump support still broken?

I have a couple of other items to add to this list of things which isn't working in gdb.

1) Calling inferior functions no longer works. (At least it didn't in the recent Red Hat release. I'm rebuilding gdb now with the TurboLinux release to check it there.) I've done some investigation of this problem and it looks to me like the RSE backing store is changing under us (gdb that is) when bsp is changed.

2) Hardware watchpoints no longer work. Again, the value returned by the kernel looks suspect. There appear to be a couple of bits that were reset...

In general, the state of gdb isn't as good right now as it used to be. There was a time when I was seeing only between 20-30 test suite failures. The number is now over 700.

Kevin

#5 lore raw
In reply to David Mosberger
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line · Kevin Buettner

- gdb > - NaT bits don't seem to work properly? > - coredump

support still broken?

Kevin> I have a couple of other items to add to this list of things Kevin> which isn't working in gdb.

Kevin> 1) Calling inferior functions no longer works. (At least it Kevin> didn't in the recent Red Hat release. I'm rebuilding gdb now Kevin> with the TurboLinux release to check it there.) I've done Kevin> some investigation of this problem and it looks to me like Kevin> the RSE backing store is changing under us (gdb that is) when Kevin> bsp is changed.

Kevin> 2) Hardware watchpoints no longer work. Again, the value Kevin> returned by the kernel looks suspect. There appear to be a Kevin> couple of bits that were reset...

Kevin> In general, the state of gdb isn't as good right now as it Kevin> used to be. There was a time when I was seeing only between Kevin> 20-30 test suite failures. The number is now over 700.

It wouldn't surprise me if some of the issues are due to kernel bugs and I'll certainly be happy to work with you on getting those issues resolved. Getting gdb to be reliable (again) is definitely high on my priority list.

	--david
#6 lore raw
In reply to David Mosberger

All-

OK, I got the web page up with the TODO list on it. You can link to it from www.linuxia64.org' or go directly to the page at www.linuxia64.org/todo.html'. Check it out and let me know if there are any changes or additions. Some obvious changes are we need some volunteers for EEPro100', execve' and `gprof' - any takers?

In addition to the web page I plan on sending out a text copy of the list to this mailing list on a bi-weekly basis.

Quoted 41 lines · David Mosberger

Since we're getting closer to a real release of various IA-64 Linux distros, I thought it would be a good idea to pass around my TODO list. I'd really appreciate if someone else could maintain this list and mail it out periodically (weekly?) as my bw is pretty limited right now. Here is what comes to mind:

Kernel
- enable kernel unaligned handler
- verify that all on-board hardware is supported and working:
- does cs4281 sound driver work reliably now?
- what to do about eepro100? (currently hangs on > 180MB transfers?)
- investigate and fix test suite failures reported by SCO (Who's the contact person at SCO for this? Please make available simple test cases that reproduce the problem so we can go about fixing them.)
- consider clearing CPU state on an execve() to avoid leaking information to a new program; Alan Cox thinks it would be sufficient to do this when current->dumpable is zero

Libraries
- gprof support?

Apps
- gdb
- NaT bits don't seem to work properly?
- coredump support still broken?
- strace
- 'strace -f' hangs if the program forks a child;
- verify that the new system calls have been added

I'm planning to work on the kernel unaligned handler but if someone else is dying on doing that, let me know. ;-)

If you can think of anything else, please let me know---I'll try keep the list uptodate for now.

	--david

_______________________________________________
Linux-IA64 mailing list
[email protected]
http://lists.linuxia64.org/lists/listinfo/linux-ia64

Signature · 4 lines
Don Dugger
"Censeo Toto nos in Kansa esse decisse." - D. Gale
[email protected]
Ph: 303/938-9838
#7 lore raw
In reply to David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"Don" = Don Dugger <[email protected]> writes:

Don> All- OK, I got the web page up with the TODO list on it. You can Don> link to it from www.linuxia64.org' or go directly to the page at Don> www.linuxia64.org/todo.html'. Check it out and let me know if Don> there are any changes or additions. Some obvious changes are we Don> need some volunteers for EEPro100', execve' and `gprof' - any Don> takers?

I have most of the glibc bits and possibly gprof changes done, by relying on David's old patch for gprof. I even did some m4 autoconf code for it (eeep). I have been wanting to do this for a while, but I can't give you a date for it.

Jes

#8 lore raw
In reply to David Mosberger
Quoted 2 lines · David Mosberger

Kernel
- verify that all on-board hardware is supported and working:

A little late, but this patch is modestly tested and it appears to work on ia32 as well as ia64. This patch is a little different than the one I send to the linux-usb-devel list. The only major difference is the patch to set uhci->dev correctly so the PCI DMA API routines work correctly under ia64.

It's a bit large, but there were some large changes necessary to support the PCI DMA API in the driver.

Here's the changelog I sent to linux-usb-devel if anyone cares:

bug fixes
---------
- Don't use nested locks anymore. This could cause deadlocks in drivers which were hard to track down. We use a complete list which is walked through after determining the transfer result of the URB's
- Bulk queueing should work significantly better now. I've fixed some obvious problems with it (order issues, retoggle remaining URB's)
- Enforce memory barriers. I hope this will help some of the people who were having some problems with the driver
- In some situations, the device usage count would be off and the memory would never get freed
- Don't always mark VRH interrupt URB as done
- When forcing unlinking of urb's in uhci_free_dev, make sure they are not done asynchronously

new features
------------
- Use PCI DMA architecture. This is necessary for 64 bit architectures (alpha, ultrasparc, ia64, etc)
- New /proc interface. Dump the status of the schedule
- debug option is more versatile now

clean ups
---------
- Use list_heads when possible now. Makes code cleaner/easier to read
- Added uhci_call_completion function to call the completion handler the same way in multiple places

TODO
----
- The PCI DMA architecture is horribly inefficient on x86 and ia64. The result is a page is allocated for each TD. This is evil. Perhaps a slab cache internally? Or modify the generic slab cache to handle PCI DMA pages instead?
- Cleanup up FIXME's
- Make uhci-debug.h functions respect len
- More testing, I have seen it lock up my machine hard with a CPiA camera after a long period of running
- Figure out why the submit loop (second) of uhci_call_completion causes crashes
- Should we return -EPIPE on BABBLE? Drivers will confuse this with a STALL

JE

drivers/usb/uhci-debug.h +313 -132
diff -urN -X dontdiff linux-2.4.1-pre8.orig/drivers/usb/uhci-debug.h linux-2.4.1-pre8/drivers/usb/uhci-debug.h
@@ -6,20 +6,22 @@
  * visible pointers are surrounded in ()'s
  *
  * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999-2001 Johannes Erdfelt
  */
 
 #include <linux/kernel.h>
+#include <linux/proc_fs.h>
 #include <asm/io.h>
 
 #include "uhci.h"
 
-void uhci_show_td(struct uhci_td *td)
+static int uhci_show_td(struct uhci_td *td, char *buf, int len)
 {
+	char *out = buf;
 	char *spid;
 
-	printk("%08x ", td->link);
-	printk("e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
+	out += sprintf(out, "[%p] link (%08x) ", td, td->link);
+	out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
 		((td->status >> 27) & 3),
 		(td->status & TD_CTRL_SPD) ?      "SPD " : "",
 		(td->status & TD_CTRL_LS) ?       "LS " : "",
@@ -48,19 +50,23 @@
 			break;
 	}
 
-	printk("MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
+	out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
 		td->info >> 21,
 		((td->info >> 19) & 1),
 		(td->info >> 15) & 15,
 		(td->info >> 8) & 127,
 		(td->info & 0xff),
 		spid);
-	printk("(buf=%08x)\n", td->buffer);
+	out += sprintf(out, "(buf=%08x)\n", td->buffer);
+
+	return out - buf;
 }
 
-static void uhci_show_sc(int port, unsigned short status)
+static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
 {
-	printk("  stat%d     =     %04x   %s%s%s%s%s%s%s%s\n",
+	char *out = buf;
+
+	out += sprintf(out, "  stat%d     =     %04x   %s%s%s%s%s%s%s%s\n",
 		port,
 		status,
 		(status & USBPORTSC_SUSP) ? "PortSuspend " : "",
@@ -71,10 +77,13 @@
 		(status & USBPORTSC_PE) ?   "PortEnabled " : "",
 		(status & USBPORTSC_CSC) ?  "ConnectChange " : "",
 		(status & USBPORTSC_CCS) ?  "PortConnected " : "");
+
+	return out - buf;
 }
 
-void uhci_show_status(struct uhci *uhci)
+static int uhci_show_status(struct uhci *uhci, char *buf, int len)
 {
+	char *out = buf;
 	unsigned int io_addr = uhci->io_addr;
 	unsigned short usbcmd, usbstat, usbint, usbfrnum;
 	unsigned int flbaseadd;
@@ -90,7 +99,7 @@
 	portsc1   = inw(io_addr + 16);
 	portsc2   = inw(io_addr + 18);
 
-	printk("  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
+	out += sprintf(out, "  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
 		usbcmd,
 		(usbcmd & USBCMD_MAXP) ?    "Maxp64 " : "Maxp32 ",
 		(usbcmd & USBCMD_CF) ?      "CF " : "",
@@ -101,7 +110,7 @@
 		(usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
 		(usbcmd & USBCMD_RS) ?      "RS " : "");
 
-	printk("  usbstat   =     %04x   %s%s%s%s%s%s\n",
+	out += sprintf(out, "  usbstat   =     %04x   %s%s%s%s%s%s\n",
 		usbstat,
 		(usbstat & USBSTS_HCH) ?    "HCHalted " : "",
 		(usbstat & USBSTS_HCPE) ?   "HostControllerProcessError " : "",
@@ -110,53 +119,66 @@
 		(usbstat & USBSTS_ERROR) ?  "USBError " : "",
 		(usbstat & USBSTS_USBINT) ? "USBINT " : "");
 
-	printk("  usbint    =     %04x\n", usbint);
-	printk("  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1,
+	out += sprintf(out, "  usbint    =     %04x\n", usbint);
+	out += sprintf(out, "  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1,
 		0xfff & (4*(unsigned int)usbfrnum));
-	printk("  flbaseadd = %08x\n", flbaseadd);
-	printk("  sof       =       %02x\n", sof);
-	uhci_show_sc(1, portsc1);
-	uhci_show_sc(2, portsc2);
-}
-
-#define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x))
-
-struct uhci_td *uhci_link_to_td(unsigned int link)
-{
-	if (link & UHCI_PTR_TERM)
-		return NULL;
+	out += sprintf(out, "  flbaseadd = %08x\n", flbaseadd);
+	out += sprintf(out, "  sof       =       %02x\n", sof);
+	out += uhci_show_sc(1, portsc1, out, len - (out - buf));
+	out += uhci_show_sc(2, portsc2, out, len - (out - buf));
 
-	return bus_to_virt(link & ~UHCI_PTR_BITS);
+	return out - buf;
 }
 
-void uhci_show_urb_queue(struct urb *urb)
+static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len)
 {
-	struct urb_priv *urbp = urb->hcpriv;
+	char *out = buf;
+	struct urb_priv *urbp;
 	struct list_head *head, *tmp;
-	int i, checked = 0, prevactive = 0;
+	struct uhci_td *td;
+	int i = 0, checked = 0, prevactive = 0;
+
+	out += sprintf(out, "[%p] link (%08x) element (%08x)\n",
+				qh, qh->link, qh->element);
+	if (qh->element & UHCI_PTR_QH)
+		out += sprintf(out, "      Element points to QH (bug?)\n");
+
+	if (qh->element & UHCI_PTR_DEPTH)
+		out += sprintf(out, "      Depth traverse\n");
 
-	printk("  URB [%p] urbp [%p]\n", urb, urbp);
+	if (qh->element & UHCI_PTR_TERM)
+		out += sprintf(out, "      Terminate\n");
 
-	if (urbp->qh)
-		printk("    QH [%p]\n", urbp->qh);
-	else
-		printk("    QH [%p] element (%08x) link (%08x)\n", urbp->qh,
-			urbp->qh->element, urbp->qh->link);
+	if (!(qh->element & ~UHCI_PTR_BITS)) {
+		out += sprintf(out, "      td 0: [NULL]\n");
+		goto out;
+	}
 
-	i = 0;
+	if (!qh->urbp) {
+		out += sprintf(out, "      urbp == NULL\n");
+		goto out;
+	}
 
-	head = &urbp->list;
+	urbp = qh->urbp;
+
+	head = &urbp->td_list;
 	tmp = head->next;
+
+	td = list_entry(tmp, struct uhci_td, list);
+
+	if (td->dma_handle != (qh->element & ~3))
+		out += sprintf(out, "      Element != First TD\n");
+
 	while (tmp != head) {
 		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
 
 		tmp = tmp->next;
 
-		printk("      td %d: [%p]\n", i++, td);
-		printk("      ");
-		uhci_show_td(td);
+		out += sprintf(out, "      td %d: ", i++);
+		out += uhci_show_td(td, out, len - (out - buf));
 
-		if (i > 10 && !checked && prevactive && tmp != head) {
+		if (i > 10 && !checked && prevactive && tmp != head &&
+		    debug <= 2) {
 			struct list_head *ntmp = tmp;
 			struct uhci_td *ntd = td;
 			int active = 1, ni = i;
@@ -174,7 +196,7 @@
 			}
 
 			if (active && ni > i) {
-				printk("      [skipped %d active TD's]\n", ni - i);
+				out += sprintf(out, "      [skipped %d active TD's]\n", ni - i);
 				tmp = ntmp;
 				td = ntd;
 				i = ni;
@@ -183,60 +205,30 @@
 
 		prevactive = td->status & TD_CTRL_ACTIVE;
 	}
-}
-
-void uhci_show_queue(struct uhci_qh *qh)
-{
-	struct uhci_td *td, *first;
-	int i = 0, count = 1000;
 
-	if (qh->element & UHCI_PTR_QH)
-		printk("      Element points to QH (bug?)\n");
+	/* FIXME: Show queued URB's as well */
 
-	if (qh->element & UHCI_PTR_DEPTH)
-		printk("      Depth traverse\n");
-
-	if (qh->element & UHCI_PTR_TERM)
-		printk("      Terminate\n");
-
-	if (!(qh->element & ~UHCI_PTR_BITS)) {
-		printk("      td 0: [NULL]\n");
-		return;
-	}
-
-	first = uhci_link_to_td(qh->element);
-
-	/* Make sure it doesn't runaway */
-	for (td = first; td && count > 0; 
-	     td = uhci_link_to_td(td->link), --count) {
-		printk("      td %d: [%p]\n", i++, td);
-		printk("      ");
-		uhci_show_td(td);
-
-		if (td == uhci_link_to_td(td->link)) {
-			printk(KERN_ERR "td links to itself!\n");
-			break;
-		}
-	}
+out:
+	return out - buf;
 }
 
-static int uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td)
+static int inline uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td)
 {
-	int j;
+	int i;
 
-	for (j = 0; j < UHCI_NUM_SKELTD; j++)
-		if (td == uhci->skeltd + j)
+	for (i = 0; i < UHCI_NUM_SKELTD; i++)
+		if (td == uhci->skeltd[i])
 			return 1;
 
 	return 0;
 }
 
-static int uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
+static int inline uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
 {
-	int j;
+	int i;
 
-	for (j = 0; j < UHCI_NUM_SKELQH; j++)
-		if (qh == uhci->skelqh + j)
+	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+		if (qh == uhci->skelqh[i])
 			return 1;
 
 	return 0;
@@ -244,73 +236,262 @@
 
 static const char *td_names[] = {"interrupt1", "interrupt2", "interrupt4",
 				 "interrupt8", "interrupt16", "interrupt32",
-				 "interrupt64", "interrupt128", "interrupt256" };
-static const char *qh_names[] = { "control", "bulk" };
+				 "interrupt64", "interrupt128", "interrupt256",
+				 "term" };
+static const char *qh_names[] = { "low speed control", "high speed control",
+				  "bulk", "term" };
+
+#define show_frame_num()	\
+	if (!shown) {		\
+	  shown = 1;		\
+	  out += sprintf(out, "  Frame %d\n", i); \
+	}
 
-void uhci_show_queues(struct uhci *uhci)
+#define show_td_name()		\
+	if (!shown) {		\
+	  shown = 1;		\
+	  out += sprintf(out, "  %s: [%p] (%08x) link (%08x)\n", td_names[i], \
+			td, td->dma_handle, td->link); \
+	}
+
+#define show_qh_name()		\
+	if (!shown) {		\
+	  shown = 1;		\
+	  out += sprintf(out, "  %s: [%p] (%08x) link (%08x) element (%08x)\n", \
+			qh_names[i], qh, qh->dma_handle, qh->link, \
+			qh->element); \
+	}
+
+static int uhci_sprint_schedule(struct uhci *uhci, char *buf, int len)
 {
-	int i, isqh = 0;
+	char *out = buf;
+	int i;
 	struct uhci_qh *qh;
 	struct uhci_td *td;
+	struct list_head *tmp, *head;
 
+	out += sprintf(out, "HC status\n");
+	out += uhci_show_status(uhci, out, len - (out - buf));
+
+	out += sprintf(out, "Frame List\n");
 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
 		int shown = 0;
 
-		td = uhci_link_to_td(uhci->fl->frame[i]);
-		if (td)
-			isqh = uhci->fl->frame[i] & UHCI_PTR_QH;
-		while (td && !isqh) {
-			if (uhci_is_skeleton_td(uhci, td))
-				break;
-
-			if (!shown) {
-				printk("   Frame %d\n", i);
-				shown = 1;
+		td = uhci->fl->frame_cpu[i];
+		if (!td) {
+			show_frame_num();
+			out += sprintf(out, "Frame %d empty?\n", i);
+			continue;
+		}
+
+		if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
+			show_frame_num();
+			out += sprintf(out, "frame_cpu does not match frame\n");
+		}
+
+		if (uhci_is_skeleton_td(uhci, td))
+			continue;
+
+		show_frame_num();
+
+		head = &td->fl_list;
+		tmp = head;
+
+		do {
+			td = list_entry(tmp, struct uhci_td, fl_list);
+
+			tmp = tmp->next;
+
+			out += sprintf(out, "  ");
+			out += uhci_show_td(td, out, len - (out - buf));
+		} while (tmp != head);
+	}
+
+	out += sprintf(out, "Skeleton TD's\n");
+	for (i = UHCI_NUM_SKELTD - 1; i >= 0; i--) {
+		int shown = 0;
+
+		td = uhci->skeltd[i];
+
+		if (debug > 2)
+			show_td_name();
+
+		if (list_empty(&td->fl_list)) {
+			if (i < 8 && i > 0) {
+				if (td->link != uhci->skeltd[i - 1]->dma_handle) {
+					show_td_name();
+					out += sprintf(out, "    Skeleton TD not linked to next skeleton TD!\n");
+				}
+			} else if (!i) {
+				if (td->link !=
+				    (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH)) {
+					show_td_name();
+					out += sprintf(out, "    Skeleton TD not linked to ls_control QH!\n");
+				}
 			}
 
-			printk("[%p] ", td);
+			continue;
+		}
+
+		show_td_name();
+
+		head = &td->fl_list;
+		tmp = head->next;
 
-			uhci_show_td(td);
-			td = uhci_link_to_td(td->link);
-			if (td)
-				isqh = td->link & UHCI_PTR_QH;
+		while (tmp != head) {
+			td = list_entry(tmp, struct uhci_td, fl_list);
+
+			tmp = tmp->next;
+
+			out += sprintf(out, "    ");
+			out += uhci_show_td(td, out, len - (out - buf));
 		}
-	}
-	for (i = 0; i < UHCI_NUM_SKELTD; ++i) {
-		printk("  %s: [%p] (%08x)\n", td_names[i],
-			&uhci->skeltd[i],
-			uhci->skeltd[i].link);
-
-		td = uhci_link_to_td(uhci->skeltd[i].link);
-		if (td)
-			isqh = uhci->skeltd[i].link & UHCI_PTR_QH;
-		while (td && !isqh) {
-			if (uhci_is_skeleton_td(uhci, td))
-				break;
-
-			printk("[%p] ", td);
-
-			uhci_show_td(td);
-			td = uhci_link_to_td(td->link);
-			if (td)
-				isqh = td->link & UHCI_PTR_QH;
+
+		if (i < 8 && i > 0) {
+			if (td->link != uhci->skeltd[i - 1]->dma_handle)
+				out += sprintf(out, "    Last TD not linked to next skeleton!\n");
+		} else if (!i) {
+			if (td->link !=
+			    (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH))
+				out += sprintf(out, "    Last TD not linked to ls_control QH!\n");
 		}
 	}
+
+	out += sprintf(out, "Skeleton QH's\n");
 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
-		printk("  %s: [%p] (%08x) (%08x)\n", qh_names[i],
-			&uhci->skelqh[i],
-			uhci->skelqh[i].link, uhci->skelqh[i].element);
-
-		qh = uhci_link_to_qh(uhci->skelqh[i].link);
-		for (; qh; qh = uhci_link_to_qh(qh->link)) {
-			if (uhci_is_skeleton_qh(uhci, qh))
-				break;
+		int shown = 0;
 
-			printk("    [%p] (%08x) (%08x)\n",
-				qh, qh->link, qh->element);
+		qh = uhci->skelqh[i];
+
+		if (debug > 2)
+			show_qh_name();
+
+		if (list_empty(&qh->list))
+			continue;
+
+		show_qh_name();
 
-			uhci_show_queue(qh);
+		head = &qh->list;
+		tmp = head->next;
+
+		while (tmp != head) {
+			qh = list_entry(tmp, struct uhci_qh, list);
+
+			tmp = tmp->next;
+
+			out += sprintf(out, "    ");
+			out += uhci_show_qh(qh, out, len - (out - buf));
 		}
 	}
+
+	return out - buf;
 }
+
+#ifdef CONFIG_PROC_FS
+#define MAX_OUTPUT	(PAGE_SIZE * 2)
+
+static struct proc_dir_entry *uhci_proc_root = NULL;
+
+struct uhci_proc {
+	int size;
+	char *data;
+	struct uhci *uhci;
+};
+
+static int uhci_proc_open(struct inode *inode, struct file *file)
+{
+	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct uhci *uhci = dp->data;
+	struct uhci_proc *up;
+	unsigned long flags;
+	int ret = -ENOMEM;
+
+	lock_kernel();
+	up = kmalloc(sizeof(*up), GFP_KERNEL);
+	if (!up)
+		goto out;
+
+	up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
+	if (!up->data) {
+		kfree(up);
+		goto out;
+	}
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+
+	file->private_data = up;
+
+	ret = 0;
+out:
+	unlock_kernel();
+	return ret;
+}
+
+static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence)
+{
+	struct uhci_proc *up = file->private_data;
+	loff_t new;
+
+	switch (whence) {
+	case 0:
+		new = off;
+		break;
+	case 1:
+		new = file->f_pos + off;
+		break;
+	case 2:
+	default:
+		return -EINVAL;
+	}
+	if (new < 0 || new > up->size)
+		return -EINVAL;
+	return (file->f_pos = new);
+}
+
+static ssize_t uhci_proc_read(struct file *file, char *buf, size_t nbytes,
+			loff_t *ppos)
+{
+	struct uhci_proc *up = file->private_data;
+	unsigned int pos;
+	unsigned int size;
+
+	pos = *ppos;
+	size = up->size;
+	if (pos >= size)
+		return 0;
+	if (nbytes >= size)
+		nbytes = size;
+	if (pos + nbytes > size)
+		nbytes = size - pos;
+
+	if (!access_ok(VERIFY_WRITE, buf, nbytes))
+		return -EINVAL;
+
+	copy_to_user(buf, up->data + pos, nbytes);
+
+	*ppos += nbytes;
+
+	return nbytes;
+}
+
+static int uhci_proc_release(struct inode *inode, struct file *file)
+{
+	struct uhci_proc *up = file->private_data;
+
+	kfree(up->data);
+	kfree(up);
+
+	return 0;
+}
+
+static struct file_operations uhci_proc_operations = {
+	open:		uhci_proc_open,
+	llseek:		uhci_proc_lseek,
+	read:		uhci_proc_read,
+//	write:		uhci_proc_write,
+	release:	uhci_proc_release,
+};
+#endif
 
drivers/usb/uhci.c +960 -558

2,431 lines not on this page · raw message

drivers/usb/uhci.h +51 -55

106 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.