Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Jul 2015 13:01:50 +0000
From:      "wma_semihalf.com (Wojciech Macek)" <phabric-noreply@FreeBSD.org>
To:        freebsd-arm@freebsd.org
Subject:   [Differential] [Request, 100 lines] D3118: Add support for external function for PCI devid acquisition
Message-ID:  <differential-rev-PHID-DREV-olj5aqn6fnfrdtjspc5q-req@FreeBSD.org>

index | next in thread | raw e-mail

[-- Attachment #1 --]
wma_semihalf.com created this revision.
wma_semihalf.com added reviewers: zbb, emaste, andrew.
wma_semihalf.com added a subscriber: freebsd-arm-list.
wma_semihalf.com set the repository for this revision to rS FreeBSD src repository.
Herald added subscribers: emaste, andrew, imp.

REVISION SUMMARY
      It is possible that some HW will use different PCI devids,
      hence allow to replace the default domain:bus:slot:func schema
      by implementing and registering custom function.

REPOSITORY
  rS FreeBSD src repository

REVISION DETAIL
  https://reviews.freebsd.org/D3118

AFFECTED FILES
  sys/arm64/arm64/gic_v3_its.c
  sys/arm64/arm64/gic_v3_var.h

EMAIL PREFERENCES
  https://reviews.freebsd.org/settings/panel/emailpreferences/

To: wma_semihalf.com, zbb, emaste, andrew
Cc: imp, andrew, freebsd-arm-list, emaste

[-- Attachment #2 --]
diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -277,13 +277,14 @@
 	    reg, val);				\
 })
 
-#define	PCI_DEVID(pci_dev)				\
+#define	PCI_RID_DOMAIN_SHIFT		16
+
+#define	PCI_DEVID_GENERIC(pci_dev)				\
 ({								\
-	(((pci_get_domain(pci_dev) >> 2) << 19) |	\
-	 ((pci_get_domain(pci_dev) % 4) << 16) |	\
-	 (pci_get_bus(pci_dev) << 8) |			\
-	 (pci_get_slot(pci_dev) << 3) |			\
-	 (pci_get_function(pci_dev) << 0));		\
+	((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) |	\
+	(pci_get_bus(pci_dev) << PCI_RID_BUS_SHIFT) |		\
+	(pci_get_slot(pci_dev) << PCI_RID_SLOT_SHIFT) |		\
+	(pci_get_function(pci_dev) << PCI_RID_FUNC_SHIFT));	\
 })
 
 /*
diff --git a/sys/arm64/arm64/gic_v3_its.c b/sys/arm64/arm64/gic_v3_its.c
--- a/sys/arm64/arm64/gic_v3_its.c
+++ b/sys/arm64/arm64/gic_v3_its.c
@@ -44,6 +44,7 @@
 #include <sys/lock.h>
 #include <sys/mutex.h>
 
+#include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 
 #include <vm/vm.h>
@@ -84,6 +85,8 @@
 
 MALLOC_DEFINE(M_GIC_V3_ITS, "GICv3 ITS", GIC_V3_ITS_DEVSTR);
 
+typedef uint32_t (*its_devid_func_t)(device_t);
+
 static int its_alloc_tables(struct gic_v3_its_softc *);
 static void its_free_tables(struct gic_v3_its_softc *);
 static void its_init_commandq(struct gic_v3_its_softc *);
@@ -98,12 +101,19 @@
 static void its_cmd_mapi(struct gic_v3_its_softc *, struct its_dev *, uint32_t);
 static void its_cmd_inv(struct gic_v3_its_softc *, struct its_dev *, uint32_t);
 static void its_cmd_invall(struct gic_v3_its_softc *, struct its_col *);
+static uint32_t its_quirk_devid_thunder(device_t);
 
 static void lpi_init_conftable(struct gic_v3_its_softc *);
 static void lpi_bitmap_init(struct gic_v3_its_softc *);
 static void lpi_init_cpu(struct gic_v3_its_softc *);
 static int lpi_config_cpu(struct gic_v3_its_softc *);
 
+struct its_quirks {
+	uint64_t		cpuid;
+	uint64_t		cpuid_mask;
+	its_devid_func_t	devid_func;
+};
+
 const char *its_ptab_cache[] = {
 	[GITS_BASER_CACHE_NCNB] = "(NC,NB)",
 	[GITS_BASER_CACHE_NC] = "(NC)",
@@ -133,14 +143,89 @@
 	[GITS_BASER_TYPE_RES7] = "Reserved (7)",
 };
 
+static struct its_quirks its_quirks[] = {
+	{
+		.cpuid = 	CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0),
+		.cpuid_mask = 	CPU_IMPL_MASK | CPU_PART_MASK,
+		.devid_func = 	its_quirk_devid_thunder,
+	},
+	{
+		.cpuid = 	0,
+		.cpuid_mask = 	0,
+		.devid_func = 	NULL,
+	}
+};
+
 static struct gic_v3_its_softc *its_sc;
 
 #define	gic_its_read(sc, len, reg)		\
     bus_read_##len(&sc->its_res[0], reg)
 
 #define	gic_its_write(sc, len, reg, val)	\
     bus_write_##len(&sc->its_res[0], reg, val)
 
+static uint32_t
+its_quirk_devid_thunder(device_t pci_dev)
+{
+	int bsf;
+	uint32_t bus;
+
+	bus = pci_get_bus(pci_dev);
+
+	bsf = PCI_RID(pci_get_bus(pci_dev), pci_get_slot(pci_dev),
+	    pci_get_function(pci_dev));
+
+	/* ECAM is on bus=0 */
+	if (bus == 0) {
+		return ((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) |
+		    bsf);
+	/* PEM otherwise */
+	} else {
+		int pem;
+
+		/* PEM number is equal to domain */
+		pem = pci_get_domain(pci_dev);
+
+		/* Hardcode appropriate PEM numbers */
+		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 __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)
+{
+	struct its_quirks *quirk = &its_quirks[0];
+
+	while (quirk->cpuid != 0) {
+		if (CPU_MATCH_RAW(quirk->cpuid_mask, quirk->cpuid)) {
+			if (quirk->devid_func != NULL)
+				return ((*quirk->devid_func)(pci_dev));
+		}
+		quirk++;
+	}
+
+	return (its_get_devid_default(pci_dev));
+}
+
 static int
 gic_v3_its_attach(device_t dev)
 {
@@ -1300,7 +1385,7 @@
 	if (newdev != NULL)
 		return (newdev);
 
-	devid = PCI_DEVID(pci_dev);
+	devid = its_get_devid(pci_dev);
 
 	/* There was no previously created device. Create one now */
 	newdev = malloc(sizeof(*newdev), M_GIC_V3_ITS, (M_WAITOK | M_ZERO));

help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?differential-rev-PHID-DREV-olj5aqn6fnfrdtjspc5q-req>