Sat Jul 30 13:19:21 2011 UTC ()
ehci_get_ownership: clear BIOS semaphore when setting OS semaphore, slow
down poll rate, and make sure to clear all SMI bits when we're done


(jmcneill)
diff -r1.52 -r1.53 src/sys/dev/pci/ehci_pci.c

cvs diff -r1.52 -r1.53 src/sys/dev/pci/ehci_pci.c (expand / switch to unified diff)

--- src/sys/dev/pci/ehci_pci.c 2011/04/04 22:48:15 1.52
+++ src/sys/dev/pci/ehci_pci.c 2011/07/30 13:19:21 1.53
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ehci_pci.c,v 1.52 2011/04/04 22:48:15 dyoung Exp $ */ 1/* $NetBSD: ehci_pci.c,v 1.53 2011/07/30 13:19:21 jmcneill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net). 8 * by Lennart Augustsson (lennart@augustsson.net).
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.52 2011/04/04 22:48:15 dyoung Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.53 2011/07/30 13:19:21 jmcneill Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38#include <sys/device.h> 38#include <sys/device.h>
39#include <sys/proc.h> 39#include <sys/proc.h>
40#include <sys/queue.h> 40#include <sys/queue.h>
41 41
42#include <sys/bus.h> 42#include <sys/bus.h>
43 43
44#include <dev/pci/pcidevs.h> 44#include <dev/pci/pcidevs.h>
45#include <dev/pci/pcivar.h> 45#include <dev/pci/pcivar.h>
46#include <dev/pci/usb_pci.h> 46#include <dev/pci/usb_pci.h>
@@ -81,27 +81,27 @@ static bool ehci_pci_resume(device_t, co @@ -81,27 +81,27 @@ static bool ehci_pci_resume(device_t, co
81 81
82struct ehci_pci_softc { 82struct ehci_pci_softc {
83 ehci_softc_t sc; 83 ehci_softc_t sc;
84 pci_chipset_tag_t sc_pc; 84 pci_chipset_tag_t sc_pc;
85 pcitag_t sc_tag; 85 pcitag_t sc_tag;
86 void *sc_ih; /* interrupt vectoring */ 86 void *sc_ih; /* interrupt vectoring */
87}; 87};
88 88
89static int ehci_sb700_match(const struct pci_attach_args *pa); 89static int ehci_sb700_match(const struct pci_attach_args *pa);
90static int ehci_apply_amd_quirks(struct ehci_pci_softc *sc); 90static int ehci_apply_amd_quirks(struct ehci_pci_softc *sc);
91enum ehci_pci_quirk_flags ehci_pci_lookup_quirkdata(pci_vendor_id_t, 91enum ehci_pci_quirk_flags ehci_pci_lookup_quirkdata(pci_vendor_id_t,
92 pci_product_id_t); 92 pci_product_id_t);
93 93
94#define EHCI_MAX_BIOS_WAIT 1000 /* ms */ 94#define EHCI_MAX_BIOS_WAIT 100 /* ms*10 */
95#define EHCI_SBx00_WORKAROUND_REG 0x50 95#define EHCI_SBx00_WORKAROUND_REG 0x50
96#define EHCI_SBx00_WORKAROUND_ENABLE __BIT(27) 96#define EHCI_SBx00_WORKAROUND_ENABLE __BIT(27)
97 97
98 98
99static int 99static int
100ehci_pci_match(device_t parent, cfdata_t match, void *aux) 100ehci_pci_match(device_t parent, cfdata_t match, void *aux)
101{ 101{
102 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 102 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
103 103
104 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS && 104 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS &&
105 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB && 105 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB &&
106 PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_EHCI) 106 PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_EHCI)
107 return 1; 107 return 1;
@@ -379,51 +379,51 @@ ehci_get_ownership(ehci_softc_t *sc, pci @@ -379,51 +379,51 @@ ehci_get_ownership(ehci_softc_t *sc, pci
379 int ms; 379 int ms;
380 380
381#ifdef EHCI_DEBUG 381#ifdef EHCI_DEBUG
382 if (ehcidebug) 382 if (ehcidebug)
383 ehci_dump_caps(sc, pc, tag); 383 ehci_dump_caps(sc, pc, tag);
384#endif 384#endif
385 cparams = EREAD4(sc, EHCI_HCCPARAMS); 385 cparams = EREAD4(sc, EHCI_HCCPARAMS);
386 addr = EHCI_HCC_EECP(cparams); 386 addr = EHCI_HCC_EECP(cparams);
387 while (addr != 0) { 387 while (addr != 0) {
388 cap = pci_conf_read(pc, tag, addr); 388 cap = pci_conf_read(pc, tag, addr);
389 if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY) 389 if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY)
390 goto next; 390 goto next;
391 legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP); 391 legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP);
392 /* Ask BIOS to give up ownership */ 
393 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP, 
394 legsup | EHCI_LEG_HC_OS_OWNED); 
395 if (legsup & EHCI_LEG_HC_BIOS_OWNED) { 392 if (legsup & EHCI_LEG_HC_BIOS_OWNED) {
 393 /* Ask BIOS to give up ownership */
 394 legsup &= ~EHCI_LEG_HC_BIOS_OWNED;
 395 legsup |= EHCI_LEG_HC_OS_OWNED;
 396 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP,
 397 legsup);
396 for (ms = 0; ms < EHCI_MAX_BIOS_WAIT; ms++) { 398 for (ms = 0; ms < EHCI_MAX_BIOS_WAIT; ms++) {
397 legsup = pci_conf_read(pc, tag, 399 legsup = pci_conf_read(pc, tag,
398 addr + PCI_EHCI_USBLEGSUP); 400 addr + PCI_EHCI_USBLEGSUP);
399 if (!(legsup & EHCI_LEG_HC_BIOS_OWNED)) 401 if (!(legsup & EHCI_LEG_HC_BIOS_OWNED))
400 break; 402 break;
401 delay(1000); 403 delay(10000);
402 } 404 }
403 if (ms == EHCI_MAX_BIOS_WAIT) { 405 if (ms == EHCI_MAX_BIOS_WAIT) {
404 aprint_normal("%s: BIOS refuses to give up " 406 aprint_normal("%s: BIOS refuses to give up "
405 "ownership, using force\n", devname); 407 "ownership, using force\n", devname);
406 pci_conf_write(pc, tag, 408 pci_conf_write(pc, tag,
407 addr + PCI_EHCI_USBLEGSUP, 0); 409 addr + PCI_EHCI_USBLEGSUP, 0);
408 } else 410 } else
409 aprint_verbose("%s: BIOS has given up " 411 aprint_verbose("%s: BIOS has given up "
410 "ownership\n", devname); 412 "ownership\n", devname);
411 } 413 }
412 414
413 /* Disable SMIs */ 415 /* Disable SMIs */
414 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGCTLSTS, 416 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGCTLSTS, 0);
415 EHCI_LEG_EXT_SMI_BAR | EHCI_LEG_EXT_SMI_PCICMD | 
416 EHCI_LEG_EXT_SMI_OS_CHANGE); 
417 417
418next: 418next:
419 if (--maxcap < 0) { 419 if (--maxcap < 0) {
420 aprint_normal("%s: broken extended capabilities " 420 aprint_normal("%s: broken extended capabilities "
421 "ignored\n", devname); 421 "ignored\n", devname);
422 return; 422 return;
423 } 423 }
424 addr = EHCI_CAP_GET_NEXT(cap); 424 addr = EHCI_CAP_GET_NEXT(cap);
425 } 425 }
426 426
427} 427}
428 428
429static bool 429static bool