Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: USB troubles with SB600/SB700 chipsets
Hi,
a new version of this patch. It mainly avoids a lot of code duplication.
The orders how test it still apply.
Christoph
Christoph Egger wrote:
> Hi,
>
> everyone with an AMD SB600 or SB700 chipset, please test attached patch!
>
> Attached patch is intended to avoid USB subsystem hang symptoms on
> all AMD SB600 revisions and AMD SB700 south bridge revision A12 and A13.
>
> The USB subsystem hang symptom is observed when the system has multiple
> USB devices connected to it. In some cases a USB hub may be required to
> observe this symptom.
>
> This patch works around the problem by correcting the internal register
> setting that will help by changing the behavior of the internal logic to
> avoid the USB subsystem hang issue. The change in the behavior of the
> logic does not impact the normal operation of the USB subsystem.
>
> This should also address PR 40056
> (I put the submitter of PR 40056 on CC).
>
>
> In order to test this patch,
>
> apply the patch and add to the kernel config
>
> amdehci* at pci? dev ? function ?
>
> and when you boot, you should see
>
> amdehci0 at pci
>
> instead of
>
> ehci0 at pci
>
> in the dmesg. Then test if you still encounter any USB problems.
>
>
> Christoph
>
Index: sys/dev/pci/ehci_pci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/ehci_pci.c,v
retrieving revision 1.44
diff -u -p -r1.44 ehci_pci.c
--- sys/dev/pci/ehci_pci.c 26 Apr 2009 09:47:31 -0000 1.44
+++ sys/dev/pci/ehci_pci.c 17 May 2009 21:36:48 -0000
@@ -74,9 +74,87 @@ struct ehci_pci_softc {
void *sc_ih; /* interrupt vectoring */
};
+static int (*ehci_pci_applyquirks)(struct ehci_pci_softc *) = NULL;
+
#define EHCI_MAX_BIOS_WAIT 1000 /* ms */
static int
+ehci_pci_match(device_t, cfdata_t, void *);
+static void ehci_pci_attach(device_t, device_t, void *);
+static int ehci_pci_detach(device_t, int);
+
+CFATTACH_DECL3_NEW(ehci_pci, sizeof(struct ehci_pci_softc),
+ ehci_pci_match, ehci_pci_attach, ehci_pci_detach, ehci_activate, NULL,
+ ehci_childdet, DVF_DETACH_SHUTDOWN);
+
+
+static int amdehci_match(device_t, cfdata_t, void *);
+static void amdehci_attach(device_t, device_t, void *);
+
+CFATTACH_DECL3_NEW(amdehci, sizeof(struct ehci_pci_softc),
+ amdehci_match, amdehci_attach, ehci_pci_detach, ehci_activate, NULL,
+ ehci_childdet, DVF_DETACH_SHUTDOWN);
+
+
+static int
+amdehci_sb700_match(struct pci_attach_args *pa)
+{
+ if (!(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_SMB))
+ return 0;
+
+ switch (PCI_REVISION(pa->pa_id)) {
+ case 0x3a:
+ case 0x3b:
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+amdehci_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct pci_attach_args *pa = (struct pci_attach_args *) aux;
+
+ if (!(PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS &&
+ PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB &&
+ PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_EHCI &&
+ PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI))
+ return 0;
+
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_ATI_SB600_USB_EHCI:
+ return 10; /* beat ehci_pci */
+ case PCI_PRODUCT_ATI_SB700_USB_EHCI:
+ if (pci_find_device(NULL, amdehci_sb700_match))
+ return 10; /* beat ehci_pci */
+ default:
+ return 0;
+ }
+}
+
+static int
+amdehci_applyquirks(struct ehci_pci_softc *sc)
+{
+ uint8_t value;
+
+ aprint_normal_dev(sc->sc.sc_dev,
+ "applying AMD SB600/SB700 USB freeze workaround\n");
+ value = pci_conf_read(sc->sc_pc, sc->sc_tag, 0x53);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, 0x53, value | (1U << 3));
+
+ return 0;
+}
+
+static void
+amdehci_attach(device_t parent, device_t self, void *aux)
+{
+ ehci_pci_applyquirks = amdehci_applyquirks;
+ ehci_pci_attach(parent, self, aux);
+}
+
+static int
ehci_pci_match(device_t parent, cfdata_t match, void *aux)
{
struct pci_attach_args *pa = (struct pci_attach_args *) aux;
@@ -209,6 +287,9 @@ ehci_pci_attach(device_t parent, device_
ehci_get_ownership(&sc->sc, pc, tag);
+ if (ehci_pci_applyquirks)
+ ehci_pci_applyquirks(sc);
+
r = ehci_init(&sc->sc);
if (r != USBD_NORMAL_COMPLETION) {
aprint_error_dev(self, "init failed, error=%d\n", r);
@@ -265,10 +346,6 @@ ehci_pci_detach(device_t self, int flags
return 0;
}
-CFATTACH_DECL3_NEW(ehci_pci, sizeof(struct ehci_pci_softc),
- ehci_pci_match, ehci_pci_attach, ehci_pci_detach, ehci_activate, NULL,
- ehci_childdet, DVF_DETACH_SHUTDOWN);
-
#ifdef EHCI_DEBUG
static void
ehci_dump_caps(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag)
Index: sys/dev/pci/files.pci
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/files.pci,v
retrieving revision 1.314
diff -u -p -r1.314 files.pci
--- sys/dev/pci/files.pci 21 Apr 2009 03:00:29 -0000 1.314
+++ sys/dev/pci/files.pci 17 May 2009 21:36:48 -0000
@@ -588,9 +588,13 @@ file dev/pci/uhci_pci.c uhci_pci
attach ohci at pci with ohci_pci
file dev/pci/ohci_pci.c ohci_pci
+# AMD SB600/SB700 EHCI USB controller
+device amdehci: usbus, usbroothub
+attach amdehci at pci
+
# EHCI USB controller
attach ehci at pci with ehci_pci
-file dev/pci/ehci_pci.c ehci_pci
+file dev/pci/ehci_pci.c ehci_pci | amdehci
file dev/pci/usb_pci.c ehci_pci | ehci_cardbus
Home |
Main Index |
Thread Index |
Old Index