Re: sb600/sb700 ohci experimental patch

From: Andriy Gapon <avg_at_icyb.net.ua>
Date: Fri, 25 Sep 2009 09:34:21 +0300
on 24/09/2009 17:51 Hans Petter Selasky said the following:
> 
> Your patch looks good. Send me the final version when it is ready and testers 
> report OK. I will then review and commit it.
> 
> I think that if you need to reload the control head, you will also need to 
> reload the other head list pointers? Could you check that?

I am just thinking that maybe there is a more clever / proper approach to fixing
this.

I did some additional debugging, maybe you'd find this interesting.
First debugging setup:

diff --git a/sys/dev/usb/controller/ohci.c b/sys/dev/usb/controller/ohci.c
index fb6ba34..83cb4bb 100644
--- a/sys/dev/usb/controller/ohci.c
+++ b/sys/dev/usb/controller/ohci.c
_at__at_ -80,6 +80,8 _at__at_ __FBSDID("$FreeBSD$");
 #ifdef USB_DEBUG
 static int ohcidebug = 0;

+extern devclass_t ohci_devclass; /* XXX */
+
 SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
 SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW,
     &ohcidebug, 0, "ohci debug level");
_at__at_ -227,9 +229,9 _at__at_ reset:
 		return (USB_ERR_IOERROR);
 	}
 #ifdef USB_DEBUG
-	if (ohcidebug > 15) {
+//	if (ohcidebug > 15) {
 		ohci_dumpregs(sc);
-	}
+//	}
 #endif

 	/* The controller is now in SUSPEND state, we have 2ms to finish. */
_at__at_ -286,8 +289,15 _at__at_ reset:
 	}

 #ifdef USB_DEBUG
-	if (ohcidebug > 5) {
+//	if (ohcidebug > 5) {
 		ohci_dumpregs(sc);
+//	}
+	int unit = device_get_unit(sc->sc_dev);
+	if (unit != 0) {
+		DPRINTFN(0, "dump of ohci0 regs:\n");
+		sc = devclass_get_softc(ohci_devclass, 0);
+		if (sc != NULL)
+			ohci_dumpregs(sc);
 	}
 #endif
 	return (USB_ERR_NORMAL_COMPLETION);
diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c
index 3be6e42..755a90b 100644
--- a/sys/dev/usb/controller/ohci_pci.c
+++ b/sys/dev/usb/controller/ohci_pci.c
_at__at_ -400,7 +400,7 _at__at_ static driver_t ohci_driver =
 	.size = sizeof(struct ohci_softc),
 };

-static devclass_t ohci_devclass;
+devclass_t ohci_devclass; /* XXX */

 DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0);
 MODULE_DEPEND(ohci, usb, 1, 1, 1);


The idea is to always dump all HW regs just after reset, after HW programming
and additionally dump HW regs of ohci0 after each of the subsequent controllers
gets programmed.

So, now the results:
ohci0: <OHCI (generic) USB controller> mem 0xfe02e000-0xfe02efff irq 16 at
device 18.0 on pci0
ohci0: [ITHREAD]
ohci_dumpregs:540: ohci_dumpregs: rev=0x00000110 control=0x000000c0
command=0x00000000
ohci_dumpregs:544:                intrstat=0x00000040 intre=0x00000000
intrd=0x00000000
ohci_dumpregs:548:                hcca=0x00000000 percur=0x00000000
ctrlhd=0x00000000
ohci_dumpregs:552:                ctrlcur=0x00000000 bulkhd=0x00000000
bulkcur=0x00000000
ohci_dumpregs:556:                done=0x00000000 fmival=0x00002edf fmrem=0x00000000
ohci_dumpregs:560:                fmnum=0x00000000 perst=0x00000000
lsthrs=0x00000628
ohci_dumpregs:564:                desca=0x02000b03 descb=0x00000000 stat=0x00000000
ohci_dumpregs:567:                port1=0x00010301 port2=0x00000100
ohci_dumpregs:573:          HCCA: frame_number=0x0000 done_head=0x00000000
ohci_dumpregs:540: ohci_dumpregs: rev=0x00000110 control=0x000000af
command=0x00000000
ohci_dumpregs:544:                intrstat=0x00000044 intre=0x8000005a
intrd=0x8000005a
ohci_dumpregs:548:                hcca=0x0304b000 percur=0x00000000
ctrlhd=0x03082000
ohci_dumpregs:552:                ctrlcur=0x00000000 bulkhd=0x03083000
bulkcur=0x00000000
ohci_dumpregs:556:                done=0x00000000 fmival=0xa7782edf fmrem=0x800013dd
ohci_dumpregs:560:                fmnum=0x0000000d perst=0x00002a2f
lsthrs=0x00000628
ohci_dumpregs:564:                desca=0x02000b03 descb=0x00000000 stat=0x00000000
ohci_dumpregs:567:                port1=0x00010301 port2=0x00000100
ohci_dumpregs:573:          HCCA: frame_number=0x000e done_head=0x00000000
usbus0: <OHCI (generic) USB controller> on ohci0
ohci1: <OHCI (generic) USB controller> mem 0xfe02d000-0xfe02dfff irq 16 at
device 18.1 on pci0
ohci1: [ITHREAD]
ohci_dumpregs:540: ohci_dumpregs: rev=0x00000110 control=0x000000c0
command=0x00000000
ohci_dumpregs:544:                intrstat=0x00000000 intre=0x00000000
intrd=0x00000000
ohci_dumpregs:548:                hcca=0x00000000 percur=0x00000000
ctrlhd=0x00000000
ohci_dumpregs:552:                ctrlcur=0x00000000 bulkhd=0x00000000
bulkcur=0x00000000
ohci_dumpregs:556:                done=0x00000000 fmival=0x00002edf fmrem=0x00000000
ohci_dumpregs:560:                fmnum=0x00000000 perst=0x00000000
lsthrs=0x00000628
ohci_dumpregs:564:                desca=0x02000b03 descb=0x00000000 stat=0x00000000
ohci_dumpregs:567:                port1=0x00000100 port2=0x00000100
ohci_dumpregs:573:          HCCA: frame_number=0x0000 done_head=0x00000000
ohci_dumpregs:540: ohci_dumpregs: rev=0x00000110 control=0x000000af
command=0x00000000
ohci_dumpregs:544:                intrstat=0x00000004 intre=0x8000005a
intrd=0x8000005a
ohci_dumpregs:548:                hcca=0x030a8000 percur=0x00000000
ctrlhd=0x030a9000
ohci_dumpregs:552:                ctrlcur=0x00000000 bulkhd=0x030b1000
bulkcur=0x00000000
ohci_dumpregs:556:                done=0x00000000 fmival=0xa7782edf fmrem=0x800013d5
ohci_dumpregs:560:                fmnum=0x0000000d perst=0x00002a2f
lsthrs=0x00000628
ohci_dumpregs:564:                desca=0x02000b03 descb=0x00000000 stat=0x00000000
ohci_dumpregs:567:                port1=0x00000100 port2=0x00000100
ohci_dumpregs:573:          HCCA: frame_number=0x000e done_head=0x00000000
ohci_controller_init:297: dump of ohci0 regs:
ohci_dumpregs:540: ohci_dumpregs: rev=0x00000110 control=0x000000af
command=0x00000000
ohci_dumpregs:544:                intrstat=0x00000004 intre=0x8000005a
intrd=0x8000005a
ohci_dumpregs:548:                hcca=0x0304b000 percur=0x00000000
ctrlhd=0xbfdf1c50
ohci_dumpregs:552:                ctrlcur=0x00000000 bulkhd=0x03083000
bulkcur=0x00000000
ohci_dumpregs:556:                done=0xbfdf1ca0 fmival=0xa7782edf fmrem=0x80002e51
ohci_dumpregs:560:                fmnum=0x0000019f perst=0x00002a2f
lsthrs=0x00000628
ohci_dumpregs:564:                desca=0x02000b03 descb=0x00000000 stat=0x00000000
ohci_dumpregs:567:                port1=0x00000303 port2=0x00000100
ohci_dumpregs:573:          HCCA: frame_number=0x019f done_head=0x00000000

So, as expected, reset does clear the registers, programming does set them
correctly.
But as soon as we are done programming ohci1, ctrlhd of ohci0 gets re-programmed
to  0xbfdf1c50.

BTW, to answer your question, other lists seem to be unaffected, head/cur values
seem to be preserved intact. hcca register is also OK.

Not sure how to interpret this.
Either a timing issue, i.e. the register gets over-written some time after we
program it.
Or perhaps a bug in SMM code, i.e. when we generate an SMI (e.g. while doing
ohci1 takeover) SMM code erroneously writes something to ohci0 ctrlhead.
Or something else... :)

-- 
Andriy Gapon
Received on Fri Sep 25 2009 - 04:34:27 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:56 UTC