From owner-svn-src-head@FreeBSD.ORG Wed Mar 14 23:25:47 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 7BECA106564A; Wed, 14 Mar 2012 23:25:47 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6B54A8FC17; Wed, 14 Mar 2012 23:25:47 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q2ENPlaY036645; Wed, 14 Mar 2012 23:25:47 GMT (envelope-from jkim@svn.freebsd.org) Received: (from jkim@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q2ENPlVs036643; Wed, 14 Mar 2012 23:25:47 GMT (envelope-from jkim@svn.freebsd.org) Message-Id: <201203142325.q2ENPlVs036643@svn.freebsd.org> From: Jung-uk Kim Date: Wed, 14 Mar 2012 23:25:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r232991 - head/sys/dev/pci X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Mar 2012 23:25:47 -0000 Author: jkim Date: Wed Mar 14 23:25:46 2012 New Revision: 232991 URL: http://svn.freebsd.org/changeset/base/232991 Log: Add a PCI quirk to ignore PCI map registers from configuration space. For example, some BIOS for AMD SB600 south bridge may map HPET MMIO base address as a memory BAR for SMBus controller depending on a PM register configuration. Before r231161 (and r232086, subsequent MFC to stable/9), it was not fatal but hpet(4) just failed to attach. Since we probe and attach HPET earlier than PCI devices now, it caused unfortunate hard lockup. With this patch, it does not hang any more and HPET works at the same time. Clean up some style nits while I am in the neighborhood. PR: kern/165647 Reviewed by: jhb MFC after: 3 days Modified: head/sys/dev/pci/pci.c Modified: head/sys/dev/pci/pci.c ============================================================================== --- head/sys/dev/pci/pci.c Wed Mar 14 22:44:56 2012 (r232990) +++ head/sys/dev/pci/pci.c Wed Mar 14 23:25:46 2012 (r232991) @@ -196,6 +196,7 @@ struct pci_quirk { #define PCI_QUIRK_MAP_REG 1 /* PCI map register in weird place */ #define PCI_QUIRK_DISABLE_MSI 2 /* MSI/MSI-X doesn't work */ #define PCI_QUIRK_ENABLE_MSI_VM 3 /* Older chipset in VM where MSI works */ +#define PCI_QUIRK_UNMAP_REG 4 /* Ignore PCI map register */ int arg1; int arg2; }; @@ -244,6 +245,16 @@ static const struct pci_quirk const pci_ */ { 0x12378086, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 }, + /* + * HPET MMIO base address may appear in Bar1 for AMD SB600 SMBus + * controller depending on SoftPciRst register (PM_IO 0x55 [7]). + * It prevents us from attaching hpet(4) when the bit is unset. + * Note this quirk only affects SB600 revision A13 and earlier. + * For SB600 A21 and later, firmware must set the bit to hide it. + * For SB700 and later, it is unused and hardcoded to zero. + */ + { 0x43851002, PCI_QUIRK_UNMAP_REG, 0x14, 0 }, + { 0 } }; @@ -3111,12 +3122,18 @@ xhci_early_takeover(device_t self) void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) { - struct pci_devinfo *dinfo = device_get_ivars(dev); - pcicfgregs *cfg = &dinfo->cfg; - struct resource_list *rl = &dinfo->resources; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + struct resource_list *rl; const struct pci_quirk *q; + uint32_t devid; int i; + dinfo = device_get_ivars(dev); + cfg = &dinfo->cfg; + rl = &dinfo->resources; + devid = (cfg->device << 16) | cfg->vendor; + /* ATA devices needs special map treatment */ if ((pci_get_class(dev) == PCIC_STORAGE) && (pci_get_subclass(dev) == PCIS_STORAGE_IDE) && @@ -3125,18 +3142,29 @@ pci_add_resources(device_t bus, device_t !pci_read_config(dev, PCIR_BAR(2), 4))) ) pci_ata_maps(bus, dev, rl, force, prefetchmask); else - for (i = 0; i < cfg->nummaps;) + for (i = 0; i < cfg->nummaps;) { + /* + * Skip quirked resources. + */ + for (q = &pci_quirks[0]; q->devid != 0; q++) + if (q->devid == devid && + q->type == PCI_QUIRK_UNMAP_REG && + q->arg1 == PCIR_BAR(i)) + break; + if (q->devid != 0) { + i++; + continue; + } i += pci_add_map(bus, dev, PCIR_BAR(i), rl, force, prefetchmask & (1 << i)); + } /* * Add additional, quirked resources. */ - for (q = &pci_quirks[0]; q->devid; q++) { - if (q->devid == ((cfg->device << 16) | cfg->vendor) - && q->type == PCI_QUIRK_MAP_REG) + for (q = &pci_quirks[0]; q->devid != 0; q++) + if (q->devid == devid && q->type == PCI_QUIRK_MAP_REG) pci_add_map(bus, dev, q->arg1, rl, force, 0); - } if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) { #ifdef __PCI_REROUTE_INTERRUPT