Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 May 2016 09:31:44 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r299932 - in head: share/man/man9 sys/arm64/arm64 sys/arm64/cavium sys/dev/ofw sys/dev/pci
Message-ID:  <201605160931.u4G9ViUB019204@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Mon May 16 09:31:44 2016
New Revision: 299932
URL: https://svnweb.freebsd.org/changeset/base/299932

Log:
  Add a pcib interface for use by interrupt controllers that need to
  translate the pci rid to a controller ID. The translation could be based
  on the 'msi-map' OFW property, a similar ACPI option, or hard-coded for
  hardware lacking the above options.
  
  Reviewed by:	wma
  Obtained from:	ABT Systems Ltd
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/share/man/man9/pci.9
  head/sys/arm64/arm64/gic_v3_its.c
  head/sys/arm64/arm64/gic_v3_var.h
  head/sys/arm64/cavium/thunder_pcie_fdt.c
  head/sys/arm64/cavium/thunder_pcie_pem.c
  head/sys/arm64/cavium/thunder_pcie_pem_fdt.c
  head/sys/dev/ofw/ofw_bus_subr.c
  head/sys/dev/ofw/ofw_bus_subr.h
  head/sys/dev/pci/pci_host_generic.c
  head/sys/dev/pci/pci_host_generic.h
  head/sys/dev/pci/pci_if.m
  head/sys/dev/pci/pci_pci.c

Modified: head/share/man/man9/pci.9
==============================================================================
--- head/share/man/man9/pci.9	Mon May 16 09:25:56 2016	(r299931)
+++ head/share/man/man9/pci.9	Mon May 16 09:31:44 2016	(r299932)
@@ -369,6 +369,9 @@ The following flags are supported:
 .Bl -hang -width ".Dv PCI_ID_RID"
 .It Dv PCI_ID_RID
 Read the routing identifier for the device.
+.It Dv PCI_ID_MSI
+Read the MSI routing ID.
+This is needed by some interrupt controllers to route MSI and MSI-X interrupts.
 .El
 .Pp
 The

Modified: head/sys/arm64/arm64/gic_v3_its.c
==============================================================================
--- head/sys/arm64/arm64/gic_v3_its.c	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/arm64/arm64/gic_v3_its.c	Mon May 16 09:31:44 2016	(r299932)
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
 #define	GIC_V3_ITS_QUIRK_THUNDERX_PEM_BUS_OFFSET	88
 
 #include "pic_if.h"
+#include "pcib_if.h"
 
 /* Device and PIC methods */
 static int gic_v3_its_attach(device_t);
@@ -150,7 +151,6 @@ const char *its_ptab_type[] = {
 
 /* Cavium ThunderX PCI devid acquire function */
 static uint32_t its_get_devbits_thunder(device_t);
-static uint32_t its_get_devid_thunder(device_t);
 
 static const struct its_quirks its_quirks[] = {
 	{
@@ -160,7 +160,6 @@ static const struct its_quirks its_quirk
 		 */
 		.cpuid =	CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0),
 		.cpuid_mask =	CPU_IMPL_MASK | CPU_PART_MASK,
-		.devid_func =	its_get_devid_thunder,
 		.devbits_func =	its_get_devbits_thunder,
 	},
 };
@@ -1569,46 +1568,6 @@ its_device_asign_lpi_locked(struct gic_v
  * Add vendor specific PCI devid function here.
  */
 static uint32_t
-its_get_devid_thunder(device_t pci_dev)
-{
-	int bsf;
-	int pem;
-	uint32_t bus;
-
-	bus = pci_get_bus(pci_dev);
-	bsf = pci_get_rid(pci_dev);
-
-	/* Check if accessing internal PCIe (low bus numbers) */
-	if (bus < GIC_V3_ITS_QUIRK_THUNDERX_PEM_BUS_OFFSET) {
-		return ((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) |
-		    bsf);
-	/* PEM otherwise */
-	} else {
-		/* PEM (PCIe MAC/root complex) number is equal to domain */
-		pem = pci_get_domain(pci_dev);
-
-		/*
-		 * Set appropriate device ID (passed by the HW along with
-		 * the transaction to memory) for different root complex
-		 * numbers using hard-coded domain portion for each group.
-		 */
-		if (pem < 3)
-			return ((0x1 << PCI_RID_DOMAIN_SHIFT) | bsf);
-
-		if (pem < 6)
-			return ((0x3 << PCI_RID_DOMAIN_SHIFT) | bsf);
-
-		if (pem < 9)
-			return ((0x9 << PCI_RID_DOMAIN_SHIFT) | bsf);
-
-		if (pem < 12)
-			return ((0xB << PCI_RID_DOMAIN_SHIFT) | bsf);
-	}
-
-	return (0);
-}
-
-static uint32_t
 its_get_devbits_thunder(device_t dev)
 {
 	uint32_t devid_bits;
@@ -1670,28 +1629,15 @@ its_get_devbits(device_t dev)
 	return (its_get_devbits_default(dev));
 }
 
-static __inline uint32_t
-its_get_devid_default(device_t pci_dev)
-{
-
-	return (PCI_DEVID_GENERIC(pci_dev));
-}
-
 static uint32_t
 its_get_devid(device_t pci_dev)
 {
-	const struct its_quirks *quirk;
-	size_t i;
+	uintptr_t id;
 
-	for (i = 0; i < nitems(its_quirks); i++) {
-		quirk = &its_quirks[i];
-		if (CPU_MATCH_RAW(quirk->cpuid_mask, quirk->cpuid)) {
-			if (quirk->devid_func != NULL)
-				return ((*quirk->devid_func)(pci_dev));
-		}
-	}
+	if (pci_get_id(pci_dev, PCI_ID_MSI, &id) != 0)
+		panic("its_get_devid: Unable to get the MSI DeviceID");
 
-	return (its_get_devid_default(pci_dev));
+	return (id);
 }
 
 /*

Modified: head/sys/arm64/arm64/gic_v3_var.h
==============================================================================
--- head/sys/arm64/arm64/gic_v3_var.h	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/arm64/arm64/gic_v3_var.h	Mon May 16 09:31:44 2016	(r299932)
@@ -247,12 +247,10 @@ struct gic_v3_its_softc {
 
 /* Stuff that is specific to the vendor's implementation */
 typedef uint32_t (*its_devbits_func_t)(device_t);
-typedef uint32_t (*its_devid_func_t)(device_t);
 
 struct its_quirks {
 	uint64_t		cpuid;
 	uint64_t		cpuid_mask;
-	its_devid_func_t	devid_func;
 	its_devbits_func_t	devbits_func;
 };
 

Modified: head/sys/arm64/cavium/thunder_pcie_fdt.c
==============================================================================
--- head/sys/arm64/cavium/thunder_pcie_fdt.c	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/arm64/cavium/thunder_pcie_fdt.c	Mon May 16 09:31:44 2016	(r299932)
@@ -45,16 +45,24 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
 #include <dev/pci/pci_host_generic.h>
+#include <dev/pci/pcib_private.h>
 
 #include "thunder_pcie_common.h"
 
+#include "pcib_if.h"
+
 #ifdef THUNDERX_PASS_1_1_ERRATA
 static struct resource * thunder_pcie_fdt_alloc_resource(device_t, device_t,
     int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
 #endif
 static int thunder_pcie_fdt_attach(device_t);
 static int thunder_pcie_fdt_probe(device_t);
+static int thunder_pcie_fdt_get_id(device_t, device_t, enum pci_id_type,
+    uintptr_t *);
 
 static device_method_t thunder_pcie_fdt_methods[] = {
 	/* Device interface */
@@ -64,6 +72,9 @@ static device_method_t thunder_pcie_fdt_
 	DEVMETHOD(bus_alloc_resource,	thunder_pcie_fdt_alloc_resource),
 #endif
 
+	/* pcib interface */
+	DEVMETHOD(pcib_get_id,		thunder_pcie_fdt_get_id),
+
 	/* End */
 	DEVMETHOD_END
 };
@@ -112,6 +123,26 @@ thunder_pcie_fdt_attach(device_t dev)
 	return (pci_host_generic_attach(dev));
 }
 
+static int
+thunder_pcie_fdt_get_id(device_t pci, device_t child, enum pci_id_type type,
+    uintptr_t *id)
+{
+	phandle_t node;
+	int bsf;
+
+	if (type != PCI_ID_MSI)
+		return (pcib_get_id(pci, child, type, id));
+
+	node = ofw_bus_get_node(pci);
+	if (OF_hasprop(node, "msi-map"))
+		return (generic_pcie_get_id(pci, child, type, id));
+
+	bsf = pci_get_rid(child);
+	*id = (pci_get_domain(child) << PCI_RID_DOMAIN_SHIFT) | bsf;
+
+	return (0);
+}
+
 #ifdef THUNDERX_PASS_1_1_ERRATA
 static struct resource *
 thunder_pcie_fdt_alloc_resource(device_t dev, device_t child, int type, int *rid,

Modified: head/sys/arm64/cavium/thunder_pcie_pem.c
==============================================================================
--- head/sys/arm64/cavium/thunder_pcie_pem.c	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/arm64/cavium/thunder_pcie_pem.c	Mon May 16 09:31:44 2016	(r299932)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pci_host_generic.h>
+#include <dev/pci/pcib_private.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -131,6 +132,8 @@ static int thunder_pem_release_msi(devic
 static int thunder_pem_alloc_msix(device_t, device_t, int *);
 static int thunder_pem_release_msix(device_t, device_t, int);
 static int thunder_pem_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
+static int thunder_pem_get_id(device_t, device_t, enum pci_id_type,
+    uintptr_t *);
 static int thunder_pem_attach(device_t);
 static int thunder_pem_deactivate_resource(device_t, device_t, int, int,
     struct resource *);
@@ -182,6 +185,7 @@ static device_method_t thunder_pem_metho
 	DEVMETHOD(pcib_alloc_msi,		thunder_pem_alloc_msi),
 	DEVMETHOD(pcib_release_msi,		thunder_pem_release_msi),
 	DEVMETHOD(pcib_map_msi,			thunder_pem_map_msi),
+	DEVMETHOD(pcib_get_id,			thunder_pem_get_id),
 
 	DEVMETHOD_END
 };
@@ -372,6 +376,40 @@ thunder_pem_map_msi(device_t pci, device
 }
 
 static int
+thunder_pem_get_id(device_t pci, device_t child, enum pci_id_type type,
+    uintptr_t *id)
+{
+	int bsf;
+	int pem;
+
+	if (type != PCI_ID_MSI)
+		return (pcib_get_id(pci, child, type, id));
+
+	bsf = pci_get_rid(child);
+
+	/* PEM (PCIe MAC/root complex) number is equal to domain */
+	pem = pci_get_domain(child);
+
+	/*
+	 * Set appropriate device ID (passed by the HW along with
+	 * the transaction to memory) for different root complex
+	 * numbers using hard-coded domain portion for each group.
+	 */
+	if (pem < 3)
+		*id = (0x1 << PCI_RID_DOMAIN_SHIFT) | bsf;
+	else if (pem < 6)
+		*id = (0x3 << PCI_RID_DOMAIN_SHIFT) | bsf;
+	else if (pem < 9)
+		*id = (0x9 << PCI_RID_DOMAIN_SHIFT) | bsf;
+	else if (pem < 12)
+		*id = (0xB << PCI_RID_DOMAIN_SHIFT) | bsf;
+	else
+		return (ENXIO);
+
+	return (0);
+}
+
+static int
 thunder_pem_identify(device_t dev)
 {
 	struct thunder_pem_softc *sc;

Modified: head/sys/arm64/cavium/thunder_pcie_pem_fdt.c
==============================================================================
--- head/sys/arm64/cavium/thunder_pcie_pem_fdt.c	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/arm64/cavium/thunder_pcie_pem_fdt.c	Mon May 16 09:31:44 2016	(r299932)
@@ -65,6 +65,8 @@ static int thunder_pem_fdt_alloc_msi(dev
 static int thunder_pem_fdt_release_msi(device_t, device_t, int, int *);
 static int thunder_pem_fdt_map_msi(device_t, device_t, int, uint64_t *,
     uint32_t *);
+static int thunder_pem_fdt_get_id(device_t, device_t, enum pci_id_type,
+    uintptr_t *);
 
 static device_method_t thunder_pem_fdt_methods[] = {
 	/* Device interface */
@@ -76,6 +78,7 @@ static device_method_t thunder_pem_fdt_m
 	DEVMETHOD(pcib_alloc_msi,	thunder_pem_fdt_alloc_msi),
 	DEVMETHOD(pcib_release_msi,	thunder_pem_fdt_release_msi),
 	DEVMETHOD(pcib_map_msi,		thunder_pem_fdt_map_msi),
+	DEVMETHOD(pcib_get_id,		thunder_pem_fdt_get_id),
 
 	/* End */
 	DEVMETHOD_END
@@ -142,3 +145,23 @@ thunder_pem_fdt_map_msi(device_t pci, de
 
 	return (arm_map_msi(pci, child, irq, addr, data));
 }
+
+static int
+thunder_pem_fdt_get_id(device_t dev, device_t child, enum pci_id_type type,
+    uintptr_t *id)
+{
+	phandle_t node;
+	uint32_t rid;
+	uint16_t pci_rid;
+
+	if (type != PCI_ID_MSI)
+		return (pcib_get_id(dev, child, type, id));
+
+	node = ofw_bus_get_node(dev);
+	pci_rid = pci_get_rid(child);
+
+	ofw_bus_msimap(node, pci_rid, NULL, &rid);
+	*id = rid;
+
+	return (0);
+}

Modified: head/sys/dev/ofw/ofw_bus_subr.c
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.c	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/dev/ofw/ofw_bus_subr.c	Mon May 16 09:31:44 2016	(r299932)
@@ -397,6 +397,57 @@ ofw_bus_search_intrmap(void *intr, int i
 }
 
 int
+ofw_bus_msimap(phandle_t node, uint16_t pci_rid, phandle_t *msi_parent,
+    uint32_t *msi_rid)
+{
+	pcell_t *map, mask, msi_base, rid_base, rid_length;
+	ssize_t len;
+	uint32_t masked_rid, rid;
+	int err, i;
+
+	/* TODO: This should be OF_searchprop_alloc if we had it */
+	len = OF_getencprop_alloc(node, "msi-map", sizeof(*map), (void **)&map);
+	if (len < 0) {
+		if (msi_parent != NULL) {
+			*msi_parent = 0;
+			OF_getencprop(node, "msi-parent", msi_parent,
+			    sizeof(*msi_parent));
+		}
+		if (msi_rid != NULL)
+			*msi_rid = pci_rid;
+		return (0);
+	}
+
+	err = ENOENT;
+	rid = 0;
+	mask = 0xffffffff;
+	OF_getencprop(node, "msi-map-mask", &mask, sizeof(mask));
+
+	masked_rid = pci_rid & mask;
+	for (i = 0; i < len; i += 4) {
+		rid_base = map[i + 0];
+		rid_length = map[i + 3];
+
+		if (masked_rid < rid_base ||
+		    masked_rid >= (rid_base + rid_length))
+			continue;
+
+		msi_base = map[i + 2];
+
+		if (msi_parent != NULL)
+			*msi_parent = map[i + 1];
+		if (msi_rid != NULL)
+			*msi_rid = masked_rid - rid_base + msi_base;
+		err = 0;
+		break;
+	}
+
+	free(map, M_OFWPROP);
+
+	return (err);
+}
+
+int
 ofw_bus_reg_to_rl(device_t dev, phandle_t node, pcell_t acells, pcell_t scells,
     struct resource_list *rl)
 {

Modified: head/sys/dev/ofw/ofw_bus_subr.h
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.h	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/dev/ofw/ofw_bus_subr.h	Mon May 16 09:31:44 2016	(r299932)
@@ -76,6 +76,9 @@ int	ofw_bus_lookup_imap(phandle_t, struc
 int	ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
 	    void *, void *, int, phandle_t *);
 
+/* Routines for processing msi maps */
+int ofw_bus_msimap(phandle_t, uint16_t, phandle_t *, uint32_t *);
+
 /* Routines for parsing device-tree data into resource lists. */
 int ofw_bus_reg_to_rl(device_t, phandle_t, pcell_t, pcell_t,
     struct resource_list *);

Modified: head/sys/dev/pci/pci_host_generic.c
==============================================================================
--- head/sys/dev/pci/pci_host_generic.c	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/dev/pci/pci_host_generic.c	Mon May 16 09:31:44 2016	(r299932)
@@ -744,6 +744,26 @@ generic_pcie_release_msix(device_t pci, 
 #endif
 }
 
+int
+generic_pcie_get_id(device_t pci, device_t child, enum pci_id_type type,
+    uintptr_t *id)
+{
+	phandle_t node;
+	uint32_t rid;
+	uint16_t pci_rid;
+
+	if (type != PCI_ID_MSI)
+		return (pcib_get_id(pci, child, type, id));
+
+	node = ofw_bus_get_node(pci);
+	pci_rid = pci_get_rid(child);
+
+	ofw_bus_msimap(node, pci_rid, NULL, &rid);
+	*id = rid;
+
+	return (0);
+}
+
 static device_method_t generic_pcie_methods[] = {
 	DEVMETHOD(device_probe,			generic_pcie_probe),
 	DEVMETHOD(device_attach,		pci_host_generic_attach),
@@ -767,6 +787,7 @@ static device_method_t generic_pcie_meth
 	DEVMETHOD(pcib_alloc_msix,		generic_pcie_alloc_msix),
 	DEVMETHOD(pcib_release_msix,		generic_pcie_release_msix),
 	DEVMETHOD(pcib_map_msi,			generic_pcie_map_msi),
+	DEVMETHOD(pcib_get_id,			generic_pcie_get_id),
 
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_get_devinfo,		generic_pcie_ofw_get_devinfo),

Modified: head/sys/dev/pci/pci_host_generic.h
==============================================================================
--- head/sys/dev/pci/pci_host_generic.h	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/dev/pci/pci_host_generic.h	Mon May 16 09:31:44 2016	(r299932)
@@ -70,5 +70,6 @@ DECLARE_CLASS(generic_pcie_driver);
 struct resource *pci_host_generic_alloc_resource(device_t,
     device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
 int pci_host_generic_attach(device_t);
+int generic_pcie_get_id(device_t, device_t, enum pci_id_type, uintptr_t *);
 
 #endif /* __PCI_HOST_GENERIC_H_ */

Modified: head/sys/dev/pci/pci_if.m
==============================================================================
--- head/sys/dev/pci/pci_if.m	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/dev/pci/pci_if.m	Mon May 16 09:31:44 2016	(r299932)
@@ -58,6 +58,7 @@ HEADER {
 
 	enum pci_id_type {
 	    PCI_ID_RID,
+	    PCI_ID_MSI,
 	};
 }
 

Modified: head/sys/dev/pci/pci_pci.c
==============================================================================
--- head/sys/dev/pci/pci_pci.c	Mon May 16 09:25:56 2016	(r299931)
+++ head/sys/dev/pci/pci_pci.c	Mon May 16 09:31:44 2016	(r299932)
@@ -2580,10 +2580,13 @@ pcib_ari_get_id(device_t pcib, device_t 
     uintptr_t *id)
 {
 	struct pcib_softc *sc;
+	device_t bus_dev;
 	uint8_t bus, slot, func;
 
-	if (type != PCI_ID_RID)
-		return (ENXIO);
+	if (type != PCI_ID_RID) {
+		bus_dev = device_get_parent(pcib);
+		return (PCIB_GET_ID(device_get_parent(bus_dev), dev, type, id));
+	}
 
 	sc = device_get_softc(pcib);
 



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