From owner-svn-src-all@freebsd.org Mon May 16 09:31:46 2016 Return-Path: Delivered-To: svn-src-all@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 A5B5CB3B3FC; Mon, 16 May 2016 09:31:46 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::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 69C6E19B8; Mon, 16 May 2016 09:31:46 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4G9Vj2M019218; Mon, 16 May 2016 09:31:45 GMT (envelope-from andrew@FreeBSD.org) Received: (from andrew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4G9ViUB019204; Mon, 16 May 2016 09:31:44 GMT (envelope-from andrew@FreeBSD.org) Message-Id: <201605160931.u4G9ViUB019204@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: andrew set sender to andrew@FreeBSD.org using -f From: Andrew Turner Date: Mon, 16 May 2016 09:31:44 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 May 2016 09:31:46 -0000 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 #include #include + +#include +#include #include +#include #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 #include #include +#include #include #include @@ -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);