From OpenBSD:
-- Add a workaround for VIA EHCI controllers which, under load, signal qTD completion before they have performed writeback from the overlay qTD. This condition would exhibit itself as a umass stall that never recovers. -- This fixes the problem reported by Thomas Klausner on current-users@: http://mail-index.netbsd.org/current-users/2006/01/17/0000.html
This commit is contained in:
parent
5d1968b1c0
commit
e2aca22c8e
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ehci_pci.c,v 1.21 2005/11/20 18:44:56 augustss Exp $ */
|
||||
/* $NetBSD: ehci_pci.c,v 1.22 2006/01/17 12:30:00 xtraeme Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.21 2005/11/20 18:44:56 augustss Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.22 2006/01/17 12:30:00 xtraeme Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -48,6 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.21 2005/11/20 18:44:56 augustss Exp $
|
|||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/pci/pcidevs.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/usb_pci.h>
|
||||
|
||||
|
@ -175,6 +176,10 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux)
|
|||
snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
|
||||
"vendor 0x%04x", PCI_VENDOR(pa->pa_id));
|
||||
|
||||
/* Enable workaround for dropped interrupts as required */
|
||||
if (sc->sc.sc_id_vendor == PCI_VENDOR_VIATECH)
|
||||
sc->sc.sc_flags |= EHCIF_DROPPED_INTR_WORKAROUND;
|
||||
|
||||
/*
|
||||
* Find companion controllers. According to the spec they always
|
||||
* have lower function numbers so they should be enumerated already.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ehci.c,v 1.107 2005/11/21 10:15:41 augustss Exp $ */
|
||||
/* $NetBSD: ehci.c,v 1.108 2006/01/17 12:30:00 xtraeme Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004,2005 The NetBSD Foundation, Inc.
|
||||
|
@ -61,7 +61,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.107 2005/11/21 10:15:41 augustss Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.108 2006/01/17 12:30:00 xtraeme Exp $");
|
||||
|
||||
#include "ohci.h"
|
||||
#include "uhci.h"
|
||||
|
@ -139,6 +139,7 @@ Static void ehci_check_intr(ehci_softc_t *, struct ehci_xfer *);
|
|||
Static void ehci_idone(struct ehci_xfer *);
|
||||
Static void ehci_timeout(void *);
|
||||
Static void ehci_timeout_task(void *);
|
||||
Static void ehci_intrlist_timeout(void *);
|
||||
|
||||
Static usbd_status ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
|
||||
Static void ehci_freem(struct usbd_bus *, usb_dma_t *);
|
||||
|
@ -493,6 +494,7 @@ ehci_init(ehci_softc_t *sc)
|
|||
EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH);
|
||||
|
||||
usb_callout_init(sc->sc_tmo_pcd);
|
||||
usb_callout_init(sc->sc_tmo_intrlist);
|
||||
|
||||
lockinit(&sc->sc_doorbell_lock, PZERO, "ehcidb", 0, 0);
|
||||
|
||||
|
@ -697,6 +699,12 @@ ehci_softintr(void *v)
|
|||
ehci_check_intr(sc, ex);
|
||||
}
|
||||
|
||||
/* Schedule a callout to catch any dropped transactions. */
|
||||
if ((sc->sc_flags & EHCIF_DROPPED_INTR_WORKAROUND) &&
|
||||
!LIST_EMPTY(&sc->sc_intrhead))
|
||||
usb_callout(sc->sc_tmo_intrlist, hz,
|
||||
ehci_intrlist_timeout, sc);
|
||||
|
||||
#ifdef USB_USE_SOFTINTR
|
||||
if (sc->sc_softwake) {
|
||||
sc->sc_softwake = 0;
|
||||
|
@ -947,6 +955,7 @@ ehci_detach(struct ehci_softc *sc, int flags)
|
|||
if (rv != 0)
|
||||
return (rv);
|
||||
|
||||
usb_uncallout(sc->sc_tmo_intrlist, ehci_intrlist_timeout, sc);
|
||||
usb_uncallout(sc->sc_tmo_pcd, ehci_pcd_enable, sc);
|
||||
|
||||
if (sc->sc_powerhook != NULL)
|
||||
|
@ -2839,6 +2848,29 @@ ehci_device_request(usbd_xfer_handle xfer)
|
|||
#undef exfer
|
||||
}
|
||||
|
||||
/*
|
||||
* Some EHCI chips from VIA seem to trigger interrupts before writing back the
|
||||
* qTD status, or miss signalling occasionally under heavy load. If the host
|
||||
* machine is too fast, we we can miss transaction completion - when we scan
|
||||
* the active list the transaction still seems to be active. This generally
|
||||
* exhibits itself as a umass stall that never recovers.
|
||||
*
|
||||
* We work around this behaviour by setting up this callback after any softintr
|
||||
* that completes with transactions still pending, giving us another chance to
|
||||
* check for completion after the writeback has taken place.
|
||||
*/
|
||||
void
|
||||
ehci_intrlist_timeout(void *arg)
|
||||
{
|
||||
ehci_softc_t *sc = arg;
|
||||
int s = splusb();
|
||||
|
||||
DPRINTF(("ehci_intrlist_timeout\n"));
|
||||
usb_schedsoftintr(&sc->sc_bus);
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/************************/
|
||||
|
||||
Static usbd_status
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ehcivar.h,v 1.22 2005/12/27 04:06:45 chs Exp $ */
|
||||
/* $NetBSD: ehcivar.h,v 1.23 2006/01/17 12:30:01 xtraeme Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -90,6 +90,8 @@ typedef struct ehci_softc {
|
|||
bus_space_handle_t ioh;
|
||||
bus_size_t sc_size;
|
||||
u_int sc_offs; /* offset to operational regs */
|
||||
int sc_flags; /* misc flags */
|
||||
#define EHCIF_DROPPED_INTR_WORKAROUND 0x01
|
||||
|
||||
char sc_vendor[32]; /* vendor string for root hub */
|
||||
int sc_id_vendor; /* vendor ID for root hub */
|
||||
|
@ -132,6 +134,7 @@ typedef struct ehci_softc {
|
|||
struct lock sc_doorbell_lock;
|
||||
|
||||
usb_callout_t sc_tmo_pcd;
|
||||
usb_callout_t sc_tmo_intrlist;
|
||||
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
device_ptr_t sc_child; /* /dev/usb# device */
|
||||
|
|
Loading…
Reference in New Issue