svn commit: r234151 - in stable/8/sys: amd64/amd64 amd64/include
amd64/pci dev/acpica dev/pci i386/conf i386/i386 i386/include
i386/pci x86/x86
John Baldwin
jhb at FreeBSD.org
Wed Apr 11 20:55:22 UTC 2012
Author: jhb
Date: Wed Apr 11 20:55:21 2012
New Revision: 234151
URL: http://svn.freebsd.org/changeset/base/234151
Log:
MFC 219737,219740,233676:
Improve handling of MSI interrupts with HyperTransport devices:
- Always enable the HyperTransport MSI mapping window for HyperTransport
to PCI bridges (these show up as HyperTransport slave devices) on
powerpc.
- Enable the HyperTransport MSI mapping window for HyperTransport to PCI
bridges when an interrupt is configured via the PCIB_MAP_MSI() call
on x86.
Modified:
stable/8/sys/amd64/amd64/legacy.c
stable/8/sys/amd64/include/legacyvar.h
stable/8/sys/amd64/pci/pci_bus.c
stable/8/sys/dev/acpica/acpi_pcib_acpi.c
stable/8/sys/dev/pci/pci.c
stable/8/sys/dev/pci/pcivar.h
stable/8/sys/i386/i386/legacy.c
stable/8/sys/i386/include/legacyvar.h
stable/8/sys/i386/pci/pci_bus.c
stable/8/sys/x86/x86/mptable_pci.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/boot/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/e1000/ (props changed)
stable/8/sys/i386/conf/XENHVM (props changed)
Modified: stable/8/sys/amd64/amd64/legacy.c
==============================================================================
--- stable/8/sys/amd64/amd64/legacy.c Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/amd64/amd64/legacy.c Wed Apr 11 20:55:21 2012 (r234151)
@@ -52,7 +52,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -160,6 +162,8 @@ legacy_add_child(device_t bus, u_int ord
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -183,6 +187,12 @@ legacy_read_ivar(device_t dev, device_t
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -201,6 +211,12 @@ legacy_write_ivar(device_t dev, device_t
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
Modified: stable/8/sys/amd64/include/legacyvar.h
==============================================================================
--- stable/8/sys/amd64/include/legacyvar.h Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/amd64/include/legacyvar.h Wed Apr 11 20:55:21 2012 (r234151)
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
Modified: stable/8/sys/amd64/pci/pci_bus.c
==============================================================================
--- stable/8/sys/amd64/pci/pci_bus.c Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/amd64/pci/pci_bus.c Wed Apr 11 20:55:21 2012 (r234151)
@@ -104,14 +104,28 @@ legacy_pcib_alloc_msix(device_t pcib, de
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -225,6 +239,8 @@ legacy_pcib_identify(driver_t *driver, d
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
Modified: stable/8/sys/dev/acpica/acpi_pcib_acpi.c
==============================================================================
--- stable/8/sys/dev/acpica/acpi_pcib_acpi.c Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/dev/acpica/acpi_pcib_acpi.c Wed Apr 11 20:55:21 2012 (r234151)
@@ -58,8 +58,9 @@ struct acpi_hpcib_softc {
ACPI_HANDLE ap_handle;
int ap_flags;
- int ap_segment; /* analagous to Alpha 'hose' */
+ int ap_segment; /* PCI domain */
int ap_bus; /* bios-assigned bus number */
+ int ap_addr; /* device/func of PCI-Host bridge */
ACPI_BUFFER ap_prt; /* interrupt routing table */
};
@@ -153,7 +154,7 @@ acpi_pcib_acpi_attach(device_t dev)
struct acpi_hpcib_softc *sc;
ACPI_STATUS status;
static int bus0_seen = 0;
- u_int addr, slot, func, busok;
+ u_int slot, func, busok;
uint8_t busno;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -163,7 +164,7 @@ acpi_pcib_acpi_attach(device_t dev)
sc->ap_handle = acpi_get_handle(dev);
/*
- * Get our segment number by evaluating _SEG
+ * Get our segment number by evaluating _SEG.
* It's OK for this to not exist.
*/
status = acpi_GetInteger(sc->ap_handle, "_SEG", &sc->ap_segment);
@@ -178,6 +179,18 @@ acpi_pcib_acpi_attach(device_t dev)
}
/*
+ * Get the address (device and function) of the associated
+ * PCI-Host bridge device from _ADR. Assume we don't have one if
+ * it doesn't exist.
+ */
+ status = acpi_GetInteger(sc->ap_handle, "_ADR", &sc->ap_addr);
+ if (ACPI_FAILURE(status)) {
+ device_printf(dev, "could not evaluate _ADR - %s\n",
+ AcpiFormatException(status));
+ sc->ap_addr = -1;
+ }
+
+ /*
* Get our base bus number by evaluating _BBN.
* If this doesn't work, we assume we're bus number 0.
*
@@ -215,18 +228,10 @@ acpi_pcib_acpi_attach(device_t dev)
busok = 1;
if (sc->ap_segment == 0 && sc->ap_bus == 0 && bus0_seen) {
busok = 0;
- status = acpi_GetInteger(sc->ap_handle, "_ADR", &addr);
- if (ACPI_FAILURE(status)) {
- if (status != AE_NOT_FOUND) {
- device_printf(dev, "could not evaluate _ADR - %s\n",
- AcpiFormatException(status));
- return_VALUE (ENXIO);
- } else
- device_printf(dev, "couldn't find _ADR\n");
- } else {
+ if (sc->ap_addr != -1) {
/* XXX: We assume bus 0. */
- slot = ACPI_ADR_PCI_SLOT(addr);
- func = ACPI_ADR_PCI_FUNC(addr);
+ slot = ACPI_ADR_PCI_SLOT(sc->ap_addr);
+ func = ACPI_ADR_PCI_FUNC(sc->ap_addr);
if (bootverbose)
device_printf(dev, "reading config registers from 0:%d:%d\n",
slot, func);
@@ -349,10 +354,24 @@ static int
acpi_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ struct acpi_hpcib_softc *sc;
+ device_t bus, hostb;
+ int error;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ sc = device_get_softc(dev);
+ if (sc->ap_addr == -1)
+ return (0);
+ /* XXX: Assumes all bridges are on bus 0. */
+ hostb = pci_find_dbsf(sc->ap_segment, 0, ACPI_ADR_PCI_SLOT(sc->ap_addr),
+ ACPI_ADR_PCI_FUNC(sc->ap_addr));
+ if (hostb != NULL)
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
}
static u_long acpi_host_mem_start = 0x80000000;
Modified: stable/8/sys/dev/pci/pci.c
==============================================================================
--- stable/8/sys/dev/pci/pci.c Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/dev/pci/pci.c Wed Apr 11 20:55:21 2012 (r234151)
@@ -632,10 +632,14 @@ pci_read_cap(device_t pcib, pcicfgregs *
cfg->pp.pp_data = ptr + PCIR_POWER_DATA;
}
break;
-#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
case PCIY_HT: /* HyperTransport */
/* Determine HT-specific capability type. */
val = REG(ptr + PCIR_HT_COMMAND, 2);
+
+ if ((val & 0xe000) == PCIM_HTCAP_SLAVE)
+ cfg->ht.ht_slave = ptr;
+
+#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
switch (val & PCIM_HTCMD_CAP_MASK) {
case PCIM_HTCAP_MSI_MAPPING:
if (!(val & PCIM_HTCMD_MSI_FIXED)) {
@@ -647,7 +651,7 @@ pci_read_cap(device_t pcib, pcicfgregs *
4);
if (addr != MSI_INTEL_ADDR_BASE)
device_printf(pcib,
- "HT Bridge at pci%d:%d:%d:%d has non-default MSI window 0x%llx\n",
+ "HT device at pci%d:%d:%d:%d has non-default MSI window 0x%llx\n",
cfg->domain, cfg->bus,
cfg->slot, cfg->func,
(long long)addr);
@@ -659,8 +663,8 @@ pci_read_cap(device_t pcib, pcicfgregs *
cfg->ht.ht_msiaddr = addr;
break;
}
- break;
#endif
+ break;
case PCIY_MSI: /* PCI MSI */
cfg->msi.msi_location = ptr;
cfg->msi.msi_ctrl = REG(ptr + PCIR_MSI_CTRL, 2);
@@ -714,6 +718,23 @@ pci_read_cap(device_t pcib, pcicfgregs *
break;
}
}
+
+#if defined(__powerpc__)
+ /*
+ * Enable the MSI mapping window for all HyperTransport
+ * slaves. PCI-PCI bridges have their windows enabled via
+ * PCIB_MAP_MSI().
+ */
+ if (cfg->ht.ht_slave != 0 && cfg->ht.ht_msimap != 0 &&
+ !(cfg->ht.ht_msictrl & PCIM_HTCMD_MSI_ENABLE)) {
+ device_printf(pcib,
+ "Enabling MSI window for HyperTransport slave at pci%d:%d:%d:%d\n",
+ cfg->domain, cfg->bus, cfg->slot, cfg->func);
+ cfg->ht.ht_msictrl |= PCIM_HTCMD_MSI_ENABLE;
+ WREG(cfg->ht.ht_msimap + PCIR_HT_COMMAND, cfg->ht.ht_msictrl,
+ 2);
+ }
+#endif
/* REG and WREG use carry through to next functions */
}
Modified: stable/8/sys/dev/pci/pcivar.h
==============================================================================
--- stable/8/sys/dev/pci/pcivar.h Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/dev/pci/pcivar.h Wed Apr 11 20:55:21 2012 (r234151)
@@ -110,6 +110,7 @@ struct pcicfg_msix {
/* Interesting values for HyperTransport */
struct pcicfg_ht {
+ uint8_t ht_slave; /* Non-zero if device is an HT slave. */
uint8_t ht_msimap; /* Offset of MSI mapping cap registers. */
uint16_t ht_msictrl; /* MSI mapping control */
uint64_t ht_msiaddr; /* MSI mapping base address */
Modified: stable/8/sys/i386/i386/legacy.c
==============================================================================
--- stable/8/sys/i386/i386/legacy.c Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/i386/i386/legacy.c Wed Apr 11 20:55:21 2012 (r234151)
@@ -57,7 +57,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -181,6 +183,8 @@ legacy_add_child(device_t bus, u_int ord
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -204,6 +208,12 @@ legacy_read_ivar(device_t dev, device_t
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -222,6 +232,12 @@ legacy_write_ivar(device_t dev, device_t
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
Modified: stable/8/sys/i386/include/legacyvar.h
==============================================================================
--- stable/8/sys/i386/include/legacyvar.h Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/i386/include/legacyvar.h Wed Apr 11 20:55:21 2012 (r234151)
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
Modified: stable/8/sys/i386/pci/pci_bus.c
==============================================================================
--- stable/8/sys/i386/pci/pci_bus.c Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/i386/pci/pci_bus.c Wed Apr 11 20:55:21 2012 (r234151)
@@ -100,14 +100,28 @@ legacy_pcib_alloc_msix(device_t pcib, de
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -432,6 +446,8 @@ legacy_pcib_identify(driver_t *driver, d
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
Modified: stable/8/sys/x86/x86/mptable_pci.c
==============================================================================
--- stable/8/sys/x86/x86/mptable_pci.c Wed Apr 11 20:50:17 2012 (r234150)
+++ stable/8/sys/x86/x86/mptable_pci.c Wed Apr 11 20:55:21 2012 (r234151)
@@ -94,16 +94,6 @@ mptable_hostb_alloc_msix(device_t pcib,
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
-mptable_hostb_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
- uint32_t *data)
-{
- device_t bus;
-
- bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
-}
-
static device_method_t mptable_hostb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mptable_hostb_probe),
@@ -132,7 +122,7 @@ static device_method_t mptable_hostb_met
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, mptable_hostb_alloc_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
- DEVMETHOD(pcib_map_msi, mptable_hostb_map_msi),
+ DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
DEVMETHOD_END
};
More information about the svn-src-stable-8
mailing list