MFC: synchronise the EHCI driver with HEAD:
o Add workaround for dropped interrupts on VIA and ATI controllers o Add various identification strings and vendor IDs o Set sc_dying to 1 when detaching o Don't bother clearing the unused transfer `hcpriv' field
This commit is contained in:
parent
885f415f1b
commit
9724a76382
@ -153,6 +153,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 *);
|
||||
@ -489,6 +490,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);
|
||||
|
||||
@ -692,6 +694,12 @@ ehci_softintr(void *v)
|
||||
ehci_check_intr(sc, ex);
|
||||
}
|
||||
|
||||
/* Schedule a callout to catch any dropped transactions. */
|
||||
if ((sc->sc_flags & EHCI_SCFLG_LOSTINTRBUG) &&
|
||||
!LIST_EMPTY(&sc->sc_intrhead))
|
||||
usb_callout(sc->sc_tmo_intrlist, hz / 5, ehci_intrlist_timeout,
|
||||
sc);
|
||||
|
||||
#ifdef USB_USE_SOFTINTR
|
||||
if (sc->sc_softwake) {
|
||||
sc->sc_softwake = 0;
|
||||
@ -935,11 +943,14 @@ ehci_detach(struct ehci_softc *sc, int flags)
|
||||
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
#else
|
||||
sc->sc_dying = 1;
|
||||
#endif
|
||||
|
||||
EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
|
||||
EOWRITE4(sc, EHCI_USBCMD, 0);
|
||||
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
|
||||
usb_uncallout(sc->sc_tmo_intrlist, ehci_intrlist_timeout, sc);
|
||||
usb_uncallout(sc->sc_tmo_pcd, ehci_pcd_enable, sc);
|
||||
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
@ -2186,7 +2197,6 @@ ehci_root_intr_close(usbd_pipe_handle pipe)
|
||||
void
|
||||
ehci_root_ctrl_done(usbd_xfer_handle xfer)
|
||||
{
|
||||
xfer->hcpriv = NULL;
|
||||
}
|
||||
|
||||
/************************/
|
||||
@ -2699,6 +2709,29 @@ ehci_timeout_task(void *addr)
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some EHCI chips from VIA / ATI 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 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();
|
||||
|
||||
DPRINTFN(3, ("ehci_intrlist_timeout\n"));
|
||||
usb_schedsoftintr(&sc->sc_bus);
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/************************/
|
||||
|
||||
Static usbd_status
|
||||
|
@ -79,24 +79,66 @@ __FBSDID("$FreeBSD$");
|
||||
#define PCI_EHCI_VENDORID_ACERLABS 0x10b9
|
||||
#define PCI_EHCI_VENDORID_AMD 0x1022
|
||||
#define PCI_EHCI_VENDORID_APPLE 0x106b
|
||||
#define PCI_EHCI_VENDORID_ATI 0x1002
|
||||
#define PCI_EHCI_VENDORID_CMDTECH 0x1095
|
||||
#define PCI_EHCI_VENDORID_INTEL 0x8086
|
||||
#define PCI_EHCI_VENDORID_NEC 0x1033
|
||||
#define PCI_EHCI_VENDORID_OPTI 0x1045
|
||||
#define PCI_EHCI_VENDORID_PHILIPS 0x1131
|
||||
#define PCI_EHCI_VENDORID_SIS 0x1039
|
||||
#define PCI_EHCI_VENDORID_NVIDIA 0x12D2
|
||||
#define PCI_EHCI_VENDORID_NVIDIA2 0x10DE
|
||||
#define PCI_EHCI_VENDORID_VIA 0x1106
|
||||
|
||||
/* AcerLabs/ALi */
|
||||
#define PCI_EHCI_DEVICEID_M5239 0x523910b9
|
||||
static const char *ehci_device_m5239 = "ALi M5239 USB 2.0 controller";
|
||||
|
||||
/* AMD */
|
||||
#define PCI_EHCI_DEVICEID_8111 0x10227463
|
||||
static const char *ehci_device_8111 = "AMD 8111 USB 2.0 controller";
|
||||
|
||||
/* ATI */
|
||||
#define PCI_EHCI_DEVICEID_SB200 0x43451002
|
||||
static const char *ehci_device_sb200 = "ATI SB200 USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_SB400 0x43731002
|
||||
static const char *ehci_device_sb400 = "ATI SB400 USB 2.0 controller";
|
||||
|
||||
/* Intel */
|
||||
#define PCI_EHCI_DEVICEID_6300 0x25ad8086
|
||||
static const char *ehci_device_6300 = "Intel 6300ESB USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_ICH4 0x24cd8086
|
||||
static const char *ehci_device_ich4 = "Intel 82801DB/L/M (ICH4) USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_ICH5 0x24dd8086
|
||||
static const char *ehci_device_ich5 = "Intel 82801EB/R (ICH5) USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_ICH6 0x265c8086
|
||||
static const char *ehci_device_ich6 = "Intel 82801FB (ICH6) USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_ICH7 0x27cc8086
|
||||
static const char *ehci_device_ich7 = "Intel 82801GB/R (ICH7) USB 2.0 controller";
|
||||
|
||||
/* NEC */
|
||||
#define PCI_EHCI_DEVICEID_NEC 0x00e01033
|
||||
static const char *ehci_device_nec = "NEC uPD 720100 USB 2.0 controller";
|
||||
|
||||
/* NVIDIA */
|
||||
#define PCI_EHCI_DEVICEID_NF2 0x006810de
|
||||
static const char *ehci_device_nf2 = "NVIDIA nForce2 USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_NF2_400 0x008810de
|
||||
static const char *ehci_device_nf2_400 = "NVIDIA nForce2 Ultra 400 USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_NF3 0x00d810de
|
||||
static const char *ehci_device_nf3 = "NVIDIA nForce3 USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_NF3_250 0x00e810de
|
||||
static const char *ehci_device_nf3_250 = "NVIDIA nForce3 250 USB 2.0 controller";
|
||||
#define PCI_EHCI_DEVICEID_NF4 0x005b10de
|
||||
static const char *ehci_device_nf4 = "NVIDIA nForce4 USB 2.0 controller";
|
||||
|
||||
/* Philips */
|
||||
#define PCI_EHCI_DEVICEID_ISP156X 0x15621131
|
||||
static const char *ehci_device_isp156x = "Philips ISP156x USB 2.0 controller";
|
||||
|
||||
#define PCI_EHCI_DEVICEID_VIA 0x31041106
|
||||
static const char *ehci_device_via = "VIA VT6202 USB 2.0 controller";
|
||||
|
||||
#define PCI_EHCI_DEVICEID_ICH4 0x24cd8086
|
||||
static const char *ehci_device_ich4 = "Intel 82801DB/DBL/DBM (ICH4) USB 2.0 controller";
|
||||
|
||||
static const char *ehci_device_generic = "EHCI (generic) USB 2.0 controller";
|
||||
|
||||
#define PCI_EHCI_BASE_REG 0x10
|
||||
@ -164,12 +206,40 @@ ehci_pci_match(device_t self)
|
||||
u_int32_t device_id = pci_get_devid(self);
|
||||
|
||||
switch (device_id) {
|
||||
case PCI_EHCI_DEVICEID_NEC:
|
||||
return (ehci_device_nec);
|
||||
case PCI_EHCI_DEVICEID_VIA:
|
||||
return (ehci_device_via);
|
||||
case PCI_EHCI_DEVICEID_M5239:
|
||||
return (ehci_device_m5239);
|
||||
case PCI_EHCI_DEVICEID_8111:
|
||||
return (ehci_device_8111);
|
||||
case PCI_EHCI_DEVICEID_SB200:
|
||||
return (ehci_device_sb200);
|
||||
case PCI_EHCI_DEVICEID_SB400:
|
||||
return (ehci_device_sb400);
|
||||
case PCI_EHCI_DEVICEID_6300:
|
||||
return (ehci_device_6300);
|
||||
case PCI_EHCI_DEVICEID_ICH4:
|
||||
return (ehci_device_ich4);
|
||||
case PCI_EHCI_DEVICEID_ICH5:
|
||||
return (ehci_device_ich5);
|
||||
case PCI_EHCI_DEVICEID_ICH6:
|
||||
return (ehci_device_ich6);
|
||||
case PCI_EHCI_DEVICEID_ICH7:
|
||||
return (ehci_device_ich7);
|
||||
case PCI_EHCI_DEVICEID_NEC:
|
||||
return (ehci_device_nec);
|
||||
case PCI_EHCI_DEVICEID_NF2:
|
||||
return (ehci_device_nf2);
|
||||
case PCI_EHCI_DEVICEID_NF2_400:
|
||||
return (ehci_device_nf2_400);
|
||||
case PCI_EHCI_DEVICEID_NF3:
|
||||
return (ehci_device_nf3);
|
||||
case PCI_EHCI_DEVICEID_NF3_250:
|
||||
return (ehci_device_nf3_250);
|
||||
case PCI_EHCI_DEVICEID_NF4:
|
||||
return (ehci_device_nf4);
|
||||
case PCI_EHCI_DEVICEID_ISP156X:
|
||||
return (ehci_device_isp156x);
|
||||
case PCI_EHCI_DEVICEID_VIA:
|
||||
return (ehci_device_via);
|
||||
default:
|
||||
if (pci_get_class(self) == PCIC_SERIALBUS
|
||||
&& pci_get_subclass(self) == PCIS_SERIALBUS_USB
|
||||
@ -265,6 +335,9 @@ ehci_pci_attach(device_t self)
|
||||
case PCI_EHCI_VENDORID_APPLE:
|
||||
sprintf(sc->sc_vendor, "Apple");
|
||||
break;
|
||||
case PCI_EHCI_VENDORID_ATI:
|
||||
sprintf(sc->sc_vendor, "ATI");
|
||||
break;
|
||||
case PCI_EHCI_VENDORID_CMDTECH:
|
||||
sprintf(sc->sc_vendor, "CMDTECH");
|
||||
break;
|
||||
@ -303,6 +376,19 @@ ehci_pci_attach(device_t self)
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
/* Enable workaround for dropped interrupts as required */
|
||||
switch (pci_get_vendor(self)) {
|
||||
case PCI_EHCI_VENDORID_ATI:
|
||||
case PCI_EHCI_VENDORID_VIA:
|
||||
sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG;
|
||||
if (bootverbose)
|
||||
device_printf(self,
|
||||
"Dropped interrupts workaround enabled\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find companion controllers. According to the spec they always
|
||||
* have lower function numbers so they should be enumerated already.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ehcireg.h,v 1.17 2004/06/23 06:45:56 mycroft Exp $ */
|
||||
/* $NetBSD: ehcireg.h,v 1.18 2004/10/22 10:38:17 augustss Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*-
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ehcivar.h,v 1.12 2001/12/31 12:16:57 augustss Exp $ */
|
||||
/* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*-
|
||||
@ -85,6 +85,7 @@ struct ehci_soft_islot {
|
||||
#define EHCI_FRAMELIST_MAXCOUNT 1024
|
||||
#define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 ... 128) */
|
||||
#define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1)
|
||||
#define EHCI_MAX_POLLRATE (1 << (EHCI_IPOLLRATES - 1))
|
||||
#define EHCI_IQHIDX(lev, pos) \
|
||||
((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1)
|
||||
#define EHCI_ILEV_IVAL(lev) (1 << (lev))
|
||||
@ -93,6 +94,7 @@ struct ehci_soft_islot {
|
||||
#define EHCI_COMPANION_MAX 8
|
||||
|
||||
#define EHCI_SCFLG_DONEINIT 0x0001 /* ehci_init() has been called. */
|
||||
#define EHCI_SCFLG_LOSTINTRBUG 0x0002 /* workaround for VIA / ATI chipsets */
|
||||
|
||||
typedef struct ehci_softc {
|
||||
struct usbd_bus sc_bus; /* base device */
|
||||
@ -108,7 +110,7 @@ typedef struct ehci_softc {
|
||||
#endif
|
||||
u_int sc_offs; /* offset to operational regs */
|
||||
|
||||
char sc_vendor[16]; /* vendor string for root hub */
|
||||
char sc_vendor[32]; /* vendor string for root hub */
|
||||
int sc_id_vendor; /* vendor ID for root hub */
|
||||
|
||||
u_int32_t sc_cmd; /* shadow of cmd reg during suspend */
|
||||
@ -124,6 +126,9 @@ typedef struct ehci_softc {
|
||||
usb_dma_t sc_fldma;
|
||||
ehci_link_t *sc_flist;
|
||||
u_int sc_flsize;
|
||||
#ifndef __FreeBSD__
|
||||
u_int sc_rand; /* XXX need proper intr scheduling */
|
||||
#endif
|
||||
|
||||
struct ehci_soft_islot sc_islots[EHCI_INTRQHS];
|
||||
|
||||
@ -149,11 +154,15 @@ 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 */
|
||||
#endif
|
||||
char sc_dying;
|
||||
#if defined(__NetBSD__)
|
||||
struct usb_dma_reserve sc_dma_reserve;
|
||||
#endif
|
||||
} ehci_softc_t;
|
||||
|
||||
#define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a))
|
||||
|
Loading…
x
Reference in New Issue
Block a user