From owner-svn-src-head@freebsd.org Tue Jul 21 14:47:25 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5E8919A75FA; Tue, 21 Jul 2015 14:47:25 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 42174101A; Tue, 21 Jul 2015 14:47:25 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t6LElPQ9098033; Tue, 21 Jul 2015 14:47:25 GMT (envelope-from zbb@FreeBSD.org) Received: (from zbb@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t6LElO3r098030; Tue, 21 Jul 2015 14:47:24 GMT (envelope-from zbb@FreeBSD.org) Message-Id: <201507211447.t6LElO3r098030@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: zbb set sender to zbb@FreeBSD.org using -f From: Zbigniew Bodek Date: Tue, 21 Jul 2015 14:47:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r285752 - in head/sys: arm64/arm64 dev/pci X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 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: Tue, 21 Jul 2015 14:47:25 -0000 Author: zbb Date: Tue Jul 21 14:47:23 2015 New Revision: 285752 URL: https://svnweb.freebsd.org/changeset/base/285752 Log: Add support for vendor specific function for PCI devid acquisition in ITS 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. Obtained from: Semihalf Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D3118 Modified: head/sys/arm64/arm64/gic_v3_its.c head/sys/arm64/arm64/gic_v3_var.h head/sys/dev/pci/pcireg.h Modified: head/sys/arm64/arm64/gic_v3_its.c ============================================================================== --- head/sys/arm64/arm64/gic_v3_its.c Tue Jul 21 14:39:34 2015 (r285751) +++ head/sys/arm64/arm64/gic_v3_its.c Tue Jul 21 14:47:23 2015 (r285752) @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -89,6 +90,7 @@ static void its_free_tables(struct gic_v static void its_init_commandq(struct gic_v3_its_softc *); static int its_init_cpu(struct gic_v3_its_softc *); static void its_init_cpu_collection(struct gic_v3_its_softc *); +static uint32_t its_get_devid(device_t); static int its_cmd_send(struct gic_v3_its_softc *, struct its_cmd_desc *); @@ -133,6 +135,23 @@ const char *its_ptab_type[] = { [GITS_BASER_TYPE_RES7] = "Reserved (7)", }; +/* + * Vendor specific quirks. + * One needs to add appropriate entry to its_quirks[] + * table if the imlementation varies from the generic ARM ITS. + */ + +/* Cavium ThunderX PCI devid acquire function */ +static uint32_t its_get_devid_thunder(device_t); + +static const 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_get_devid_thunder, + }, +}; + static struct gic_v3_its_softc *its_sc; #define gic_its_read(sc, len, reg) \ @@ -1300,7 +1319,7 @@ its_device_alloc_locked(struct gic_v3_it 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)); @@ -1353,6 +1372,73 @@ its_device_asign_lpi_locked(struct gic_v its_dev->lpis.lpi_free); its_dev->lpis.lpi_free--; } + +/* + * ITS quirks. + * 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_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 { + /* 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) +{ + const struct its_quirks *quirk; + size_t i; + + 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)); + } + } + + return (its_get_devid_default(pci_dev)); +} + /* * Message signalled interrupts handling. */ Modified: head/sys/arm64/arm64/gic_v3_var.h ============================================================================== --- head/sys/arm64/arm64/gic_v3_var.h Tue Jul 21 14:39:34 2015 (r285751) +++ head/sys/arm64/arm64/gic_v3_var.h Tue Jul 21 14:47:23 2015 (r285752) @@ -234,6 +234,15 @@ struct gic_v3_its_softc { struct mtx its_spin_mtx; }; +/* Stuff that is specific to the vendor's implementation */ +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; +}; + extern devclass_t gic_v3_its_devclass; int gic_v3_its_detach(device_t); @@ -277,13 +286,12 @@ void lpi_mask_irq(device_t, uint32_t); reg, val); \ }) -#define PCI_DEVID(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)); \ +#define PCI_DEVID_GENERIC(pci_dev) \ +({ \ + ((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)); \ }) /* Modified: head/sys/dev/pci/pcireg.h ============================================================================== --- head/sys/dev/pci/pcireg.h Tue Jul 21 14:39:34 2015 (r285751) +++ head/sys/dev/pci/pcireg.h Tue Jul 21 14:47:23 2015 (r285752) @@ -51,6 +51,7 @@ #define PCIE_ARI_SLOTMAX 0 #define PCIE_ARI_FUNCMAX 255 +#define PCI_RID_DOMAIN_SHIFT 16 #define PCI_RID_BUS_SHIFT 8 #define PCI_RID_SLOT_SHIFT 3 #define PCI_RID_FUNC_SHIFT 0