diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-05 09:53:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-05 09:53:37 -0700 |
commit | 04759194dc447ff0b9ef35bc641ce3bb076c2930 (patch) | |
tree | 92eca3b7aa1e0d5013db254ae9f5bc130bd7e735 /drivers | |
parent | 9e85ae6af6e907975f68d82ff127073ec024cb05 (diff) | |
parent | d1be5c99a0341249bf6f74eb1cbc3d5fc4ef2be7 (diff) |
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 updates from Catalin Marinas:
- VMAP_STACK support, allowing the kernel stacks to be allocated in the
vmalloc space with a guard page for trapping stack overflows. One of
the patches introduces THREAD_ALIGN and changes the generic
alloc_thread_stack_node() to use this instead of THREAD_SIZE (no
functional change for other architectures)
- Contiguous PTE hugetlb support re-enabled (after being reverted a
couple of times). We now have the semantics agreed in the generic mm
layer together with API improvements so that the architecture code
can detect between contiguous and non-contiguous huge PTEs
- Initial support for persistent memory on ARM: DC CVAP instruction
exposed to user space (HWCAP) and the in-kernel pmem API implemented
- raid6 improvements for arm64: faster algorithm for the delta syndrome
and implementation of the recovery routines using Neon
- FP/SIMD refactoring and removal of support for Neon in interrupt
context. This is in preparation for full SVE support
- PTE accessors converted from inline asm to cmpxchg so that we can use
LSE atomics if available (ARMv8.1)
- Perf support for Cortex-A35 and A73
- Non-urgent fixes and cleanups
* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (75 commits)
arm64: cleanup {COMPAT_,}SET_PERSONALITY() macro
arm64: introduce separated bits for mm_context_t flags
arm64: hugetlb: Cleanup setup_hugepagesz
arm64: Re-enable support for contiguous hugepages
arm64: hugetlb: Override set_huge_swap_pte_at() to support contiguous hugepages
arm64: hugetlb: Override huge_pte_clear() to support contiguous hugepages
arm64: hugetlb: Handle swap entries in huge_pte_offset() for contiguous hugepages
arm64: hugetlb: Add break-before-make logic for contiguous entries
arm64: hugetlb: Spring clean huge pte accessors
arm64: hugetlb: Introduce pte_pgprot helper
arm64: hugetlb: set_huge_pte_at Add WARN_ON on !pte_present
arm64: kexec: have own crash_smp_send_stop() for crash dump for nonpanic cores
arm64: dma-mapping: Mark atomic_pool as __ro_after_init
arm64: dma-mapping: Do not pass data to gen_pool_set_algo()
arm64: Remove the !CONFIG_ARM64_HW_AFDBM alternative code paths
arm64: Ignore hardware dirty bit updates in ptep_set_wrprotect()
arm64: Move PTE_RDONLY bit handling out of set_pte_at()
kvm: arm64: Convert kvm_set_s2pte_readonly() from inline asm to cmpxchg()
arm64: Convert pte handling from inline asm to using (cmp)xchg
arm64: neon/efi: Make EFI fpsimd save/restore variables static
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/arm64/iort.c | 140 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm64-stub.c | 6 | ||||
-rw-r--r-- | drivers/perf/arm_pmu.c | 6 | ||||
-rw-r--r-- | drivers/perf/xgene_pmu.c | 74 |
4 files changed, 119 insertions, 107 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index a3215ee671c1..736783c67ea0 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -588,7 +588,8 @@ void acpi_configure_pmsi_domain(struct device *dev) dev_set_msi_domain(dev, msi_domain); } -static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data) +static int __maybe_unused __get_pci_rid(struct pci_dev *pdev, u16 alias, + void *data) { u32 *rid = data; @@ -633,8 +634,7 @@ int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev) { int err = 0; - if (!IS_ERR_OR_NULL(ops) && ops->add_device && dev->bus && - !dev->iommu_group) + if (ops->add_device && dev->bus && !dev->iommu_group) err = ops->add_device(dev); return err; @@ -648,36 +648,49 @@ int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev) { return 0; } #endif -static const struct iommu_ops *iort_iommu_xlate(struct device *dev, - struct acpi_iort_node *node, - u32 streamid) +static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node, + u32 streamid) { - const struct iommu_ops *ops = NULL; - int ret = -ENODEV; + const struct iommu_ops *ops; struct fwnode_handle *iort_fwnode; - if (node) { - iort_fwnode = iort_get_fwnode(node); - if (!iort_fwnode) - return NULL; + if (!node) + return -ENODEV; - ops = iommu_ops_from_fwnode(iort_fwnode); - /* - * If the ops look-up fails, this means that either - * the SMMU drivers have not been probed yet or that - * the SMMU drivers are not built in the kernel; - * Depending on whether the SMMU drivers are built-in - * in the kernel or not, defer the IOMMU configuration - * or just abort it. - */ - if (!ops) - return iort_iommu_driver_enabled(node->type) ? - ERR_PTR(-EPROBE_DEFER) : NULL; + iort_fwnode = iort_get_fwnode(node); + if (!iort_fwnode) + return -ENODEV; - ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops); - } + /* + * If the ops look-up fails, this means that either + * the SMMU drivers have not been probed yet or that + * the SMMU drivers are not built in the kernel; + * Depending on whether the SMMU drivers are built-in + * in the kernel or not, defer the IOMMU configuration + * or just abort it. + */ + ops = iommu_ops_from_fwnode(iort_fwnode); + if (!ops) + return iort_iommu_driver_enabled(node->type) ? + -EPROBE_DEFER : -ENODEV; - return ret ? NULL : ops; + return arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops); +} + +struct iort_pci_alias_info { + struct device *dev; + struct acpi_iort_node *node; +}; + +static int iort_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data) +{ + struct iort_pci_alias_info *info = data; + struct acpi_iort_node *parent; + u32 streamid; + + parent = iort_node_map_id(info->node, alias, &streamid, + IORT_IOMMU_TYPE); + return iort_iommu_xlate(info->dev, parent, streamid); } /** @@ -713,9 +726,9 @@ void iort_set_dma_mask(struct device *dev) const struct iommu_ops *iort_iommu_configure(struct device *dev) { struct acpi_iort_node *node, *parent; - const struct iommu_ops *ops = NULL; + const struct iommu_ops *ops; u32 streamid = 0; - int err; + int err = -ENODEV; /* * If we already translated the fwspec there @@ -727,21 +740,16 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev) if (dev_is_pci(dev)) { struct pci_bus *bus = to_pci_dev(dev)->bus; - u32 rid; - - pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid, - &rid); + struct iort_pci_alias_info info = { .dev = dev }; node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX, iort_match_node_callback, &bus->dev); if (!node) return NULL; - parent = iort_node_map_id(node, rid, &streamid, - IORT_IOMMU_TYPE); - - ops = iort_iommu_xlate(dev, parent, streamid); - + info.node = node; + err = pci_for_each_dma_alias(to_pci_dev(dev), + iort_pci_iommu_init, &info); } else { int i = 0; @@ -750,31 +758,30 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev) if (!node) return NULL; - parent = iort_node_map_platform_id(node, &streamid, - IORT_IOMMU_TYPE, i++); - - while (parent) { - ops = iort_iommu_xlate(dev, parent, streamid); - if (IS_ERR_OR_NULL(ops)) - return ops; - + do { parent = iort_node_map_platform_id(node, &streamid, IORT_IOMMU_TYPE, i++); - } + + if (parent) + err = iort_iommu_xlate(dev, parent, streamid); + } while (parent && !err); } /* * If we have reason to believe the IOMMU driver missed the initial * add_device callback for dev, replay it to get things in order. */ - err = iort_add_device_replay(ops, dev); - if (err) - ops = ERR_PTR(err); + if (!err) { + ops = iort_fwspec_iommu_ops(dev->iommu_fwspec); + err = iort_add_device_replay(ops, dev); + } /* Ignore all other errors apart from EPROBE_DEFER */ - if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) { - dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops)); + if (err == -EPROBE_DEFER) { + ops = ERR_PTR(err); + } else if (err) { + dev_dbg(dev, "Adding to IOMMU failed: %d\n", err); ops = NULL; } @@ -908,6 +915,27 @@ static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node) return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE; } +#if defined(CONFIG_ACPI_NUMA) && defined(ACPI_IORT_SMMU_V3_PXM_VALID) +/* + * set numa proximity domain for smmuv3 device + */ +static void __init arm_smmu_v3_set_proximity(struct device *dev, + struct acpi_iort_node *node) +{ + struct acpi_iort_smmu_v3 *smmu; + + smmu = (struct acpi_iort_smmu_v3 *)node->node_data; + if (smmu->flags & ACPI_IORT_SMMU_V3_PXM_VALID) { + set_dev_node(dev, acpi_map_pxm_to_node(smmu->pxm)); + pr_info("SMMU-v3[%llx] Mapped to Proximity domain %d\n", + smmu->base_address, + smmu->pxm); + } +} +#else +#define arm_smmu_v3_set_proximity NULL +#endif + static int __init arm_smmu_count_resources(struct acpi_iort_node *node) { struct acpi_iort_smmu *smmu; @@ -977,13 +1005,16 @@ struct iort_iommu_config { int (*iommu_count_resources)(struct acpi_iort_node *node); void (*iommu_init_resources)(struct resource *res, struct acpi_iort_node *node); + void (*iommu_set_proximity)(struct device *dev, + struct acpi_iort_node *node); }; static const struct iort_iommu_config iort_arm_smmu_v3_cfg __initconst = { .name = "arm-smmu-v3", .iommu_is_coherent = arm_smmu_v3_is_coherent, .iommu_count_resources = arm_smmu_v3_count_resources, - .iommu_init_resources = arm_smmu_v3_init_resources + .iommu_init_resources = arm_smmu_v3_init_resources, + .iommu_set_proximity = arm_smmu_v3_set_proximity, }; static const struct iort_iommu_config iort_arm_smmu_cfg __initconst = { @@ -1028,6 +1059,9 @@ static int __init iort_add_smmu_platform_device(struct acpi_iort_node *node) if (!pdev) return -ENOMEM; + if (ops->iommu_set_proximity) + ops->iommu_set_proximity(&pdev->dev, node); + count = ops->iommu_count_resources(node); r = kcalloc(count, sizeof(*r), GFP_KERNEL); diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index b4c2589d7c91..af6ae95a5e34 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -11,6 +11,7 @@ */ #include <linux/efi.h> #include <asm/efi.h> +#include <asm/memory.h> #include <asm/sections.h> #include <asm/sysreg.h> @@ -81,9 +82,10 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg, /* * If CONFIG_DEBUG_ALIGN_RODATA is not set, produce a * displacement in the interval [0, MIN_KIMG_ALIGN) that - * is a multiple of the minimal segment alignment (SZ_64K) + * doesn't violate this kernel's de-facto alignment + * constraints. */ - u32 mask = (MIN_KIMG_ALIGN - 1) & ~(SZ_64K - 1); + u32 mask = (MIN_KIMG_ALIGN - 1) & ~(EFI_KIMG_ALIGN - 1); u32 offset = !IS_ENABLED(CONFIG_DEBUG_ALIGN_RODATA) ? (phys_seed >> 32) & mask : TEXT_OFFSET; diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 1c5e0f333779..d14fc2e67f93 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -47,6 +47,9 @@ armpmu_map_cache_event(const unsigned (*cache_map) if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) return -EINVAL; + if (!cache_map) + return -ENOENT; + ret = (int)(*cache_map)[cache_type][cache_op][cache_result]; if (ret == CACHE_OP_UNSUPPORTED) @@ -63,6 +66,9 @@ armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) if (config >= PERF_COUNT_HW_MAX) return -EINVAL; + if (!event_map) + return -ENOENT; + mapping = (*event_map)[config]; return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; } diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c index e841282d690c..eb23311bc70c 100644 --- a/drivers/perf/xgene_pmu.c +++ b/drivers/perf/xgene_pmu.c @@ -1147,7 +1147,6 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx) { struct device *dev = xgene_pmu->dev; struct xgene_pmu_dev *pmu; - int rc; pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL); if (!pmu) @@ -1159,7 +1158,7 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx) switch (pmu->inf->type) { case PMU_TYPE_L3C: if (!(xgene_pmu->l3c_active_mask & pmu->inf->enable_mask)) - goto dev_err; + return -ENODEV; if (xgene_pmu->version == PCP_PMU_V3) pmu->attr_groups = l3c_pmu_v3_attr_groups; else @@ -1177,7 +1176,7 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx) break; case PMU_TYPE_MCB: if (!(xgene_pmu->mcb_active_mask & pmu->inf->enable_mask)) - goto dev_err; + return -ENODEV; if (xgene_pmu->version == PCP_PMU_V3) pmu->attr_groups = mcb_pmu_v3_attr_groups; else @@ -1185,7 +1184,7 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx) break; case PMU_TYPE_MC: if (!(xgene_pmu->mc_active_mask & pmu->inf->enable_mask)) - goto dev_err; + return -ENODEV; if (xgene_pmu->version == PCP_PMU_V3) pmu->attr_groups = mc_pmu_v3_attr_groups; else @@ -1195,19 +1194,14 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx) return -EINVAL; } - rc = xgene_init_perf(pmu, ctx->name); - if (rc) { + if (xgene_init_perf(pmu, ctx->name)) { dev_err(dev, "%s PMU: Failed to init perf driver\n", ctx->name); - goto dev_err; + return -ENODEV; } dev_info(dev, "%s PMU registered\n", ctx->name); - return rc; - -dev_err: - devm_kfree(dev, pmu); - return -ENODEV; + return 0; } static void _xgene_pmu_isr(int irq, struct xgene_pmu_dev *pmu_dev) @@ -1515,13 +1509,13 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu, acpi_dev_free_resource_list(&resource_list); if (rc < 0) { dev_err(dev, "PMU type %d: No resource address found\n", type); - goto err; + return NULL; } dev_csr = devm_ioremap_resource(dev, &res); if (IS_ERR(dev_csr)) { dev_err(dev, "PMU type %d: Fail to map resource\n", type); - goto err; + return NULL; } /* A PMU device node without enable-bit-index is always enabled */ @@ -1535,7 +1529,7 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu, ctx->name = xgene_pmu_dev_name(dev, type, enable_bit); if (!ctx->name) { dev_err(dev, "PMU type %d: Fail to get device name\n", type); - goto err; + return NULL; } inf = &ctx->inf; inf->type = type; @@ -1543,9 +1537,6 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu, inf->enable_mask = 1 << enable_bit; return ctx; -err: - devm_kfree(dev, ctx); - return NULL; } static const struct acpi_device_id xgene_pmu_acpi_type_match[] = { @@ -1663,20 +1654,20 @@ xgene_pmu_dev_ctx *fdt_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu, void __iomem *dev_csr; struct resource res; int enable_bit; - int rc; ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return NULL; - rc = of_address_to_resource(np, 0, &res); - if (rc < 0) { + + if (of_address_to_resource(np, 0, &res) < 0) { dev_err(dev, "PMU type %d: No resource address found\n", type); - goto err; + return NULL; } + dev_csr = devm_ioremap_resource(dev, &res); if (IS_ERR(dev_csr)) { dev_err(dev, "PMU type %d: Fail to map resource\n", type); - goto err; + return NULL; } /* A PMU device node without enable-bit-index is always enabled */ @@ -1686,17 +1677,15 @@ xgene_pmu_dev_ctx *fdt_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu, ctx->name = xgene_pmu_dev_name(dev, type, enable_bit); if (!ctx->name) { dev_err(dev, "PMU type %d: Fail to get device name\n", type); - goto err; + return NULL; } + inf = &ctx->inf; inf->type = type; inf->csr = dev_csr; inf->enable_mask = 1 << enable_bit; return ctx; -err: - devm_kfree(dev, ctx); - return NULL; } static int fdt_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu, @@ -1868,22 +1857,20 @@ static int xgene_pmu_probe(struct platform_device *pdev) xgene_pmu->pcppmu_csr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(xgene_pmu->pcppmu_csr)) { dev_err(&pdev->dev, "ioremap failed for PCP PMU resource\n"); - rc = PTR_ERR(xgene_pmu->pcppmu_csr); - goto err; + return PTR_ERR(xgene_pmu->pcppmu_csr); } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "No IRQ resource\n"); - rc = -EINVAL; - goto err; + return -EINVAL; } rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr, IRQF_NOBALANCING | IRQF_NO_THREAD, dev_name(&pdev->dev), xgene_pmu); if (rc) { dev_err(&pdev->dev, "Could not request IRQ %d\n", irq); - goto err; + return rc; } raw_spin_lock_init(&xgene_pmu->lock); @@ -1903,42 +1890,29 @@ static int xgene_pmu_probe(struct platform_device *pdev) rc = irq_set_affinity(irq, &xgene_pmu->cpu); if (rc) { dev_err(&pdev->dev, "Failed to set interrupt affinity!\n"); - goto err; + return rc; } /* Walk through the tree for all PMU perf devices */ rc = xgene_pmu_probe_pmu_dev(xgene_pmu, pdev); if (rc) { dev_err(&pdev->dev, "No PMU perf devices found!\n"); - goto err; + return rc; } /* Enable interrupt */ xgene_pmu->ops->unmask_int(xgene_pmu); return 0; - -err: - if (xgene_pmu->pcppmu_csr) - devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr); - devm_kfree(&pdev->dev, xgene_pmu); - - return rc; } static void xgene_pmu_dev_cleanup(struct xgene_pmu *xgene_pmu, struct list_head *pmus) { struct xgene_pmu_dev_ctx *ctx; - struct device *dev = xgene_pmu->dev; - struct xgene_pmu_dev *pmu_dev; list_for_each_entry(ctx, pmus, next) { - pmu_dev = ctx->pmu_dev; - if (pmu_dev->inf->csr) - devm_iounmap(dev, pmu_dev->inf->csr); - devm_kfree(dev, ctx); - devm_kfree(dev, pmu_dev); + perf_pmu_unregister(&ctx->pmu_dev->pmu); } } @@ -1951,10 +1925,6 @@ static int xgene_pmu_remove(struct platform_device *pdev) xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcbpmus); xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcpmus); - if (xgene_pmu->pcppmu_csr) - devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr); - devm_kfree(&pdev->dev, xgene_pmu); - return 0; } |