Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Apr 2012 20:55:21 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   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
Message-ID:  <201204112055.q3BKtLoU095323@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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
 };



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204112055.q3BKtLoU095323>