Merge branch 'topic/ppc-kvm' into next
authorMichael Ellerman <mpe@ellerman.id.au>
Thu, 21 Feb 2019 13:09:56 +0000 (00:09 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 21 Feb 2019 13:09:56 +0000 (00:09 +1100)
Merge commits we're sharing with kvm-ppc tree.

110 files changed:
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/boot/dts/Makefile
arch/powerpc/boot/dts/wii.dts
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
arch/powerpc/include/asm/device.h
arch/powerpc/include/asm/dma-direct.h
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/hvsi.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/ipic.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/pci.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/powernv.h
arch/powerpc/include/asm/ppc-pci.h
arch/powerpc/include/asm/swiotlb.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/uapi/asm/perf_regs.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/dma-mask.c [new file with mode: 0644]
arch/powerpc/kernel/dma-swiotlb.c
arch/powerpc/kernel/dma.c [deleted file]
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/kernel/eeh_sysfs.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/stacktrace.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/trace/ftrace.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/kvm/Makefile
arch/powerpc/math-emu/Makefile
arch/powerpc/mm/dma-noncoherent.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable-book3s64.c
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/perf/perf_regs.c
arch/powerpc/perf/power9-events-list.h
arch/powerpc/perf/power9-pmu.c
arch/powerpc/platforms/44x/ppc476.c
arch/powerpc/platforms/44x/warp.c
arch/powerpc/platforms/4xx/ocm.c
arch/powerpc/platforms/85xx/corenet_generic.c
arch/powerpc/platforms/85xx/ge_imp3a.c
arch/powerpc/platforms/85xx/mpc8536_ds.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/p1010rdb.c
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/85xx/p1022_rdk.c
arch/powerpc/platforms/85xx/qemu_e500.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/spu_syscalls.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/pasemi/iommu.c
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powernv/npu-dma.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/ps3/device-init.c
arch/powerpc/platforms/ps3/os-area.c
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/platforms/pseries/pci.c
arch/powerpc/platforms/pseries/vio.c
arch/powerpc/sysdev/dart_iommu.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/ipic.c
arch/powerpc/sysdev/tsi108_dev.c
arch/powerpc/sysdev/xive/common.c
drivers/misc/cxl/guest.c
drivers/misc/cxl/pci.c
drivers/misc/cxl/vphb.c
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/vfio/vfio_spapr_eeh.c
include/linux/swiotlb.h
kernel/dma/Kconfig
kernel/dma/direct.c
kernel/dma/mapping.c
kernel/dma/swiotlb.c
kernel/resource.c
tools/arch/powerpc/include/uapi/asm/perf_regs.h
tools/perf/arch/powerpc/include/perf_regs.h
tools/perf/arch/powerpc/util/perf_regs.c
tools/testing/selftests/powerpc/include/reg.h
tools/testing/selftests/powerpc/include/utils.h
tools/testing/selftests/powerpc/tm/.gitignore
tools/testing/selftests/powerpc/tm/Makefile
tools/testing/selftests/powerpc/tm/tm-signal-context-force-tm.c [new file with mode: 0644]

index 2890d36eb53116e9237944db4fd1862e480e262c..8af6a7d931489ea5970a4914b9ec2f67b64f5b3c 100644 (file)
@@ -119,9 +119,6 @@ config GENERIC_HWEIGHT
        bool
        default y
 
-config ARCH_HAS_DMA_SET_COHERENT_MASK
-        bool
-
 config PPC
        bool
        default y
@@ -130,7 +127,6 @@ config PPC
        #
        select ARCH_HAS_DEBUG_VIRTUAL
        select ARCH_HAS_DEVMEM_IS_ALLOWED
-       select ARCH_HAS_DMA_SET_COHERENT_MASK
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_GCOV_PROFILE_ALL
@@ -201,7 +197,7 @@ config PPC
        select HAVE_IOREMAP_PROT
        select HAVE_IRQ_EXIT_ON_IRQ_STACK
        select HAVE_KERNEL_GZIP
-       select HAVE_KERNEL_XZ                   if PPC_BOOK3S
+       select HAVE_KERNEL_XZ                   if PPC_BOOK3S || 44x
        select HAVE_KPROBES
        select HAVE_KPROBES_ON_FTRACE
        select HAVE_KRETPROBES
@@ -220,7 +216,7 @@ config PPC
        select HAVE_PERF_USER_STACK_DUMP
        select HAVE_RCU_TABLE_FREE              if SMP
        select HAVE_REGS_AND_STACK_ACCESS_API
-       select HAVE_RELIABLE_STACKTRACE         if PPC64 && CPU_LITTLE_ENDIAN
+       select HAVE_RELIABLE_STACKTRACE         if PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_VIRT_CPU_ACCOUNTING
        select HAVE_IRQ_TIME_ACCOUNTING
@@ -478,9 +474,6 @@ config ARCH_CPU_PROBE_RELEASE
 config ARCH_ENABLE_MEMORY_HOTPLUG
        def_bool y
 
-config ARCH_HAS_WALK_MEMORY
-       def_bool y
-
 config ARCH_ENABLE_MEMORY_HOTREMOVE
        def_bool y
 
@@ -890,6 +883,7 @@ config FSL_SOC
 
 config FSL_PCI
        bool
+       select ARCH_HAS_DMA_SET_MASK
        select PPC_INDIRECT_PCI
        select PCI_QUIRKS
 
index 488c9edffa583e7de766262a515ecc1b93540f1e..ac033341ed55e62f8c2bd571901201f86cfe736c 100644 (file)
@@ -213,9 +213,9 @@ endif
 asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
 
 KBUILD_CPPFLAGS        += -Iarch/$(ARCH) $(asinstr)
-KBUILD_AFLAGS  += -Iarch/$(ARCH) $(AFLAGS-y)
+KBUILD_AFLAGS  += $(AFLAGS-y)
 KBUILD_CFLAGS  += $(call cc-option,-msoft-float)
-KBUILD_CFLAGS  += -pipe -Iarch/$(ARCH) $(CFLAGS-y)
+KBUILD_CFLAGS  += -pipe $(CFLAGS-y)
 CPP            = $(CC) -E $(KBUILD_CFLAGS)
 
 CHECKFLAGS     += -m$(BITS) -D__powerpc__ -D__powerpc$(BITS)__
index fb335d05aae8ff87655d56b99c42217650afacd7..1cbc0e4ce857ec252ae6ba06d5c04f35b721847e 100644 (file)
@@ -4,3 +4,4 @@ subdir-y += fsl
 
 dtstree                := $(srctree)/$(src)
 dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
+dtb-$(CONFIG_XILINX_VIRTEX440_GENERIC_BOARD) += virtex440-ml507.dtb virtex440-ml510.dtb
index 104b1d6d56951a49d0b6589541f0982660f1a358..c406bdb4f36fbd439f572e76dc286494d702fc5e 100644 (file)
@@ -14,6 +14,7 @@
 
 /dts-v1/;
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 
 /*
  * This is commented-out for now.
                                "DEBUG0", "DEBUG1", "DEBUG2", "DEBUG3",
                                "DEBUG4", "DEBUG5", "DEBUG6", "DEBUG7";
 
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       interrupts = <10>;
+                       interrupt-parent = <&PIC1>;
+
                        /*
                         * This is commented out while a standard binding
                         * for i2c over gpio is defined.
                        panic-indicator;
                };
        };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               power {
+                       label = "Power Button";
+                       gpios = <&GPIO 0 GPIO_ACTIVE_HIGH>;
+                       linux,code = <KEY_POWER>;
+               };
+
+               eject {
+                       label = "Eject Button";
+                       gpios = <&GPIO 6 GPIO_ACTIVE_HIGH>;
+                       linux,code = <KEY_EJECTCD>;
+               };
+       };
 };
 
index 2e6ada28da645fd6a122d153fedfdc2c62b7843e..404e0f48f3f385993ce22ed07b1da2baca2f622a 100644 (file)
@@ -811,7 +811,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
        return hash__set_pte_at(mm, addr, ptep, pte, percpu);
 }
 
-#define _PAGE_CACHE_CTL        (_PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT)
+#define _PAGE_CACHE_CTL        (_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT)
 
 #define pgprot_noncached pgprot_noncached
 static inline pgprot_t pgprot_noncached(pgprot_t prot)
@@ -904,7 +904,7 @@ static inline int pud_none(pud_t pud)
 
 static inline int pud_present(pud_t pud)
 {
-       return (pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 extern struct page *pud_page(pud_t pud);
@@ -951,7 +951,7 @@ static inline int pgd_none(pgd_t pgd)
 
 static inline int pgd_present(pgd_t pgd)
 {
-       return (pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 static inline pte_t pgd_pte(pgd_t pgd)
@@ -1258,21 +1258,13 @@ extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 
 #define pmd_move_must_withdraw pmd_move_must_withdraw
 struct spinlock;
-static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
-                                        struct spinlock *old_pmd_ptl,
-                                        struct vm_area_struct *vma)
-{
-       if (radix_enabled())
-               return false;
-       /*
-        * Archs like ppc64 use pgtable to store per pmd
-        * specific information. So when we switch the pmd,
-        * we should also withdraw and deposit the pgtable
-        */
-       return true;
-}
-
-
+extern int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                                 struct spinlock *old_pmd_ptl,
+                                 struct vm_area_struct *vma);
+/*
+ * Hash translation mode use the deposited table to store hash pte
+ * slot information.
+ */
 #define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
 static inline bool arch_needs_pgtable_deposit(void)
 {
index 671316f9e95d289c3ea74e553c1e95e672c4940e..05147cecb8df1c367978dacc9567b1e9fbcef91b 100644 (file)
@@ -13,8 +13,32 @@ static inline int mmu_get_ap(int psize)
 
 #ifdef CONFIG_PPC_RADIX_MMU
 extern void radix__tlbiel_all(unsigned int action);
+extern void radix__flush_tlb_lpid_page(unsigned int lpid,
+                                       unsigned long addr,
+                                       unsigned long page_size);
+extern void radix__flush_pwc_lpid(unsigned int lpid);
+extern void radix__flush_tlb_lpid(unsigned int lpid);
+extern void radix__local_flush_tlb_lpid_guest(unsigned int lpid);
 #else
 static inline void radix__tlbiel_all(unsigned int action) { WARN_ON(1); };
+static inline void radix__flush_tlb_lpid_page(unsigned int lpid,
+                                       unsigned long addr,
+                                       unsigned long page_size)
+{
+       WARN_ON(1);
+}
+static inline void radix__flush_pwc_lpid(unsigned int lpid)
+{
+       WARN_ON(1);
+}
+static inline void radix__flush_tlb_lpid(unsigned int lpid)
+{
+       WARN_ON(1);
+}
+static inline void radix__local_flush_tlb_lpid_guest(unsigned int lpid)
+{
+       WARN_ON(1);
+}
 #endif
 
 extern void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma,
@@ -49,12 +73,6 @@ extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
 extern void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr);
 extern void radix__flush_tlb_all(void);
 
-extern void radix__flush_tlb_lpid_page(unsigned int lpid,
-                                       unsigned long addr,
-                                       unsigned long page_size);
-extern void radix__flush_pwc_lpid(unsigned int lpid);
-extern void radix__flush_tlb_lpid(unsigned int lpid);
 extern void radix__local_flush_tlb_lpid(unsigned int lpid);
-extern void radix__local_flush_tlb_lpid_guest(unsigned int lpid);
 
 #endif
index 0245bfcaac324c4ed0f42af59f8c25ab486a2b5e..a130be13ee83b9945b6b0052a80487063ebd1ede 100644 (file)
@@ -19,6 +19,11 @@ struct iommu_table;
  * drivers/macintosh/macio_asic.c
  */
 struct dev_archdata {
+       /*
+        * Set to %true if the dma_iommu_ops are requested to use a direct
+        * window instead of dynamically mapping memory.
+        */
+       bool                    iommu_bypass : 1;
        /*
         * These two used to be a union. However, with the hybrid ops we need
         * both so here we store both a DMA offset for direct mappings and
@@ -33,9 +38,6 @@ struct dev_archdata {
 #ifdef CONFIG_IOMMU_API
        void                    *iommu_domain;
 #endif
-#ifdef CONFIG_SWIOTLB
-       dma_addr_t              max_direct_dma_addr;
-#endif
 #ifdef CONFIG_PPC64
        struct pci_dn           *pci_data;
 #endif
@@ -54,6 +56,4 @@ struct pdev_archdata {
        u64 dma_mask;
 };
 
-#define ARCH_HAS_DMA_GET_REQUIRED_MASK
-
 #endif /* _ASM_POWERPC_DEVICE_H */
index 7702875aabb77d67b634ae5364af71b851cfbc9d..a2912b47102cf3a1f410726e116d060c739f44d7 100644 (file)
@@ -4,26 +4,24 @@
 
 static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 {
-#ifdef CONFIG_SWIOTLB
-       struct dev_archdata *sd = &dev->archdata;
-
-       if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
-               return false;
-#endif
-
        if (!dev->dma_mask)
                return false;
 
-       return addr + size - 1 <= *dev->dma_mask;
+       return addr + size - 1 <=
+               min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
 }
 
 static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-       return paddr + get_dma_offset(dev);
+       if (!dev)
+               return paddr + PCI_DRAM_OFFSET;
+       return paddr + dev->archdata.dma_offset;
 }
 
 static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-       return daddr - get_dma_offset(dev);
+       if (!dev)
+               return daddr - PCI_DRAM_OFFSET;
+       return daddr - dev->archdata.dma_offset;
 }
 #endif /* ASM_POWERPC_DMA_DIRECT_H */
index ebf66809f2d35b257d7cdece75ff0e120b45cd88..565d6f74b189cc23dc5b985915da97aedf2c6c09 100644 (file)
@@ -1,74 +1,9 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2004 IBM
- *
- * Implements the generic device dma API for powerpc.
- * the pci and vio busses
  */
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
-#ifdef __KERNEL__
-
-#include <linux/types.h>
-#include <linux/cache.h>
-/* need struct page definitions */
-#include <linux/mm.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-debug.h>
-#include <asm/io.h>
-#include <asm/swiotlb.h>
-
-/* Some dma direct funcs must be visible for use in other dma_ops */
-extern void *__dma_nommu_alloc_coherent(struct device *dev, size_t size,
-                                        dma_addr_t *dma_handle, gfp_t flag,
-                                        unsigned long attrs);
-extern void __dma_nommu_free_coherent(struct device *dev, size_t size,
-                                      void *vaddr, dma_addr_t dma_handle,
-                                      unsigned long attrs);
-extern int dma_nommu_mmap_coherent(struct device *dev,
-                                   struct vm_area_struct *vma,
-                                   void *cpu_addr, dma_addr_t handle,
-                                   size_t size, unsigned long attrs);
-
-#ifdef CONFIG_NOT_COHERENT_CACHE
-/*
- * DMA-consistent mapping functions for PowerPCs that don't support
- * cache snooping.  These allocate/free a region of uncached mapped
- * memory space for use with DMA devices.  Alternatively, you could
- * allocate the space "normally" and use the cache management functions
- * to ensure it is consistent.
- */
-struct device;
-extern void __dma_sync(void *vaddr, size_t size, int direction);
-extern void __dma_sync_page(struct page *page, unsigned long offset,
-                                size_t size, int direction);
-extern unsigned long __dma_get_coherent_pfn(unsigned long cpu_addr);
-
-#else /* ! CONFIG_NOT_COHERENT_CACHE */
-/*
- * Cache coherent cores.
- */
-
-#define __dma_sync(addr, size, rw)             ((void)0)
-#define __dma_sync_page(pg, off, sz, rw)       ((void)0)
-
-#endif /* ! CONFIG_NOT_COHERENT_CACHE */
-
-static inline unsigned long device_to_mask(struct device *dev)
-{
-       if (dev->dma_mask && *dev->dma_mask)
-               return *dev->dma_mask;
-       /* Assume devices without mask can take 32 bit addresses */
-       return 0xfffffffful;
-}
-
-/*
- * Available generic sets of operations
- */
-#ifdef CONFIG_PPC64
-extern struct dma_map_ops dma_iommu_ops;
-#endif
-extern const struct dma_map_ops dma_nommu_ops;
 
 static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 {
@@ -80,31 +15,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
        return NULL;
 }
 
-/*
- * get_dma_offset()
- *
- * Get the dma offset on configurations where the dma address can be determined
- * from the physical address by looking at a simple offset.  Direct dma and
- * swiotlb use this function, but it is typically not used by implementations
- * with an iommu.
- */
-static inline dma_addr_t get_dma_offset(struct device *dev)
-{
-       if (dev)
-               return dev->archdata.dma_offset;
-
-       return PCI_DRAM_OFFSET;
-}
-
-static inline void set_dma_offset(struct device *dev, dma_addr_t off)
-{
-       if (dev)
-               dev->archdata.dma_offset = off;
-}
-
-#define HAVE_ARCH_DMA_SET_MASK 1
-
-extern u64 __dma_get_required_mask(struct device *dev);
-
-#endif /* __KERNEL__ */
 #endif /* _ASM_DMA_MAPPING_H */
index 8b596d096ebef7c1ec70c99aed2709b10390034d..0b655810f32d3380f32672838f6433a90d5b7a49 100644 (file)
@@ -293,14 +293,14 @@ void eeh_add_device_late(struct pci_dev *);
 void eeh_add_device_tree_late(struct pci_bus *);
 void eeh_add_sysfs_files(struct pci_bus *);
 void eeh_remove_device(struct pci_dev *);
-int eeh_unfreeze_pe(struct eeh_pe *pe, bool sw_state);
+int eeh_unfreeze_pe(struct eeh_pe *pe);
 int eeh_pe_reset_and_recover(struct eeh_pe *pe);
 int eeh_dev_open(struct pci_dev *pdev);
 void eeh_dev_release(struct pci_dev *pdev);
 struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group);
 int eeh_pe_set_option(struct eeh_pe *pe, int option);
 int eeh_pe_get_state(struct eeh_pe *pe);
-int eeh_pe_reset(struct eeh_pe *pe, int option);
+int eeh_pe_reset(struct eeh_pe *pe, int option, bool include_passed);
 int eeh_pe_configure(struct eeh_pe *pe);
 int eeh_pe_inject_err(struct eeh_pe *pe, int type, int func,
                      unsigned long addr, unsigned long mask);
index 3fdc54df63c91654c6d0d027195924578d9c9bb4..464a7519ed6443ef40f9eda29ce738c98d0b6138 100644 (file)
@@ -64,7 +64,7 @@ struct hvsi_priv {
        unsigned int    inbuf_len;      /* data in input buffer */
        unsigned char   inbuf[HVSI_INBUF_SIZE];
        unsigned int    inbuf_cur;      /* Cursor in input buffer */
-       unsigned int    inbuf_pktlen;   /* packet lenght from cursor */
+       unsigned int    inbuf_pktlen;   /* packet length from cursor */
        atomic_t        seqno;          /* packet sequence number */
        unsigned int    opened:1;       /* driver opened */
        unsigned int    established:1;  /* protocol established */
index 17524d222a7b6760c2d785d7c314485c544654ae..0ac52392ed99d021af872f8a23a4527e2418576b 100644 (file)
@@ -237,6 +237,7 @@ static inline void iommu_del_device(struct device *dev)
 }
 #endif /* !CONFIG_IOMMU_API */
 
+u64 dma_iommu_get_required_mask(struct device *dev);
 #else
 
 static inline void *get_iommu_table_base(struct device *dev)
@@ -318,5 +319,21 @@ extern void iommu_release_ownership(struct iommu_table *tbl);
 extern enum dma_data_direction iommu_tce_direction(unsigned long tce);
 extern unsigned long iommu_direction_to_tce_perm(enum dma_data_direction dir);
 
+#ifdef CONFIG_PPC_CELL_NATIVE
+extern bool iommu_fixed_is_weak;
+#else
+#define iommu_fixed_is_weak false
+#endif
+
+extern const struct dma_map_ops dma_iommu_ops;
+
+static inline unsigned long device_to_mask(struct device *dev)
+{
+       if (dev->dma_mask && *dev->dma_mask)
+               return *dev->dma_mask;
+       /* Assume devices without mask can take 32 bit addresses */
+       return 0xfffffffful;
+}
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_IOMMU_H */
index 3dbd47f2bffeceff929284293bc0ebeffb88f617..abad50a745db46cc326c33bc684fbc1ee6d336f5 100644 (file)
@@ -69,10 +69,7 @@ enum ipic_mcp_irq {
        IPIC_MCP_MU   = 7,
 };
 
-extern void ipic_set_highest_priority(unsigned int irq);
 extern void ipic_set_default_priority(void);
-extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq);
-extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq);
 extern u32 ipic_get_mcp_status(void);
 extern void ipic_clear_mcp_status(u32 mask);
 
index 8311869005fa8d4769020c7aebdddf1335da415d..2f0ca6560e47c8ff7445c998de2e376fc4f93fb3 100644 (file)
@@ -47,9 +47,7 @@ struct machdep_calls {
 #endif
 #endif /* CONFIG_PPC64 */
 
-       /* Platform set_dma_mask and dma_get_required_mask overrides */
-       int             (*dma_set_mask)(struct device *dev, u64 dma_mask);
-       u64             (*dma_get_required_mask)(struct device *dev);
+       void            (*dma_set_mask)(struct device *dev, u64 dma_mask);
 
        int             (*probe)(void);
        void            (*setup_arch)(void); /* Optional, may be NULL */
index 5c5ea24134133bcbb84f78a33ae1bfc304aedf8e..aa4497175bd3edd80ba79324e81df2e4be7688cb 100644 (file)
@@ -326,7 +326,6 @@ struct page;
 extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
 extern void copy_user_page(void *to, void *from, unsigned long vaddr,
                struct page *p);
-extern int page_is_ram(unsigned long pfn);
 extern int devmem_is_allowed(unsigned long pfn);
 
 #ifdef CONFIG_PPC_SMLPAR
index aee4fcc2499021b7ac268fcfc13ae33b61bf225c..98e8b46aff97629c2938f0b749841f069eba632e 100644 (file)
@@ -19,6 +19,8 @@ struct device_node;
 struct pci_controller_ops {
        void            (*dma_dev_setup)(struct pci_dev *pdev);
        void            (*dma_bus_setup)(struct pci_bus *bus);
+       bool            (*iommu_bypass_supported)(struct pci_dev *pdev,
+                               u64 mask);
 
        int             (*probe_mode)(struct pci_bus *bus);
 
@@ -43,9 +45,6 @@ struct pci_controller_ops {
        void            (*teardown_msi_irqs)(struct pci_dev *pdev);
 #endif
 
-       int             (*dma_set_mask)(struct pci_dev *pdev, u64 dma_mask);
-       u64             (*dma_get_required_mask)(struct pci_dev *pdev);
-
        void            (*shutdown)(struct pci_controller *hose);
 };
 
index 0c72f1897063662caf1d1416a881e079badd0a32..6a1861a6301e4361f64e6eaa2275afcfe5e596c4 100644 (file)
@@ -52,10 +52,8 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 
 #ifdef CONFIG_PCI
 extern void set_pci_dma_ops(const struct dma_map_ops *dma_ops);
-extern const struct dma_map_ops *get_pci_dma_ops(void);
 #else  /* CONFIG_PCI */
 #define set_pci_dma_ops(d)
-#define get_pci_dma_ops()      NULL
 #endif
 
 #ifdef CONFIG_PPC64
index dad1d27e196d92f0e1a5ca5a2194e91af70197ed..505550fb293566d76c0fddebcc2ecf0c5ed0fc05 100644 (file)
@@ -66,7 +66,6 @@ extern unsigned long empty_zero_page[];
 
 extern pgd_t swapper_pg_dir[];
 
-int dma_pfn_limit_to_zone(u64 pfn_limit);
 extern void paging_init(void);
 
 /*
index 2f3ff7a278815a131f9ebec73bffcdaedf0abab3..362ea12a45011833973f45eb42a7997aa731eacf 100644 (file)
@@ -40,7 +40,6 @@ static inline int pnv_npu2_handle_fault(struct npu_context *context,
 }
 
 static inline void pnv_tm_init(void) { }
-static inline void pnv_power9_force_smt4(void) { }
 #endif
 
 #endif /* _ASM_POWERNV_H */
index f67da277d6526635eea2e34436a5fbe995b1b7a6..f191ef0d2a0a5ce48c161613760581ef0f0eda7e 100644 (file)
@@ -53,13 +53,13 @@ void eeh_addr_cache_rmv_dev(struct pci_dev *dev);
 struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr);
 void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
 int eeh_pci_enable(struct eeh_pe *pe, int function);
-int eeh_pe_reset_full(struct eeh_pe *pe);
+int eeh_pe_reset_full(struct eeh_pe *pe, bool include_passed);
 void eeh_save_bars(struct eeh_dev *edev);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
 void eeh_pe_state_mark(struct eeh_pe *pe, int state);
 void eeh_pe_mark_isolated(struct eeh_pe *pe);
-void eeh_pe_state_clear(struct eeh_pe *pe, int state);
+void eeh_pe_state_clear(struct eeh_pe *pe, int state, bool include_passed);
 void eeh_pe_state_mark_with_cfg(struct eeh_pe *pe, int state);
 void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode);
 
index f65ecf57b66c0a6feaaca6708daab0087a25b94c..b7d082c0ec25f7eadd5664cd36a190ac98659ad2 100644 (file)
 
 #include <linux/swiotlb.h>
 
-extern const struct dma_map_ops powerpc_swiotlb_dma_ops;
-
 extern unsigned int ppc_swiotlb_enable;
-int __init swiotlb_setup_bus_notifier(void);
-
-extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
 
 #ifdef CONFIG_SWIOTLB
 void swiotlb_detect_4g(void);
index a4a718dbfec6e0e4dbcfbf80b020f54689258290..f85e2b01c3df2b686cba72440b4b55415d8dbfc3 100644 (file)
@@ -132,6 +132,8 @@ static inline void shared_proc_topology_init(void) {}
 #define topology_sibling_cpumask(cpu)  (per_cpu(cpu_sibling_map, cpu))
 #define topology_core_cpumask(cpu)     (per_cpu(cpu_core_map, cpu))
 #define topology_core_id(cpu)          (cpu_to_core_id(cpu))
+
+int dlpar_cpu_readd(int cpu);
 #endif
 #endif
 
index ff91192407d1b3c027257b5e32ac9b6956f8bb13..f599064dd8dc8431fbe705320d9afc7f862f1207 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
index cb7f0bb9ee7122a7f08a6d83ad957e511899527a..8809e287b80d2890a50242a6b461f7e69135ae42 100644 (file)
@@ -36,7 +36,7 @@ obj-y                         := cputable.o ptrace.o syscalls.o \
                                   process.o systbl.o idle.o \
                                   signal.o sysfs.o cacheinfo.o time.o \
                                   prom.o traps.o setup-common.o \
-                                  udbg.o misc.o io.o dma.o misc_$(BITS).o \
+                                  udbg.o misc.o io.o misc_$(BITS).o \
                                   of_platform.o prom_parse.o
 obj-$(CONFIG_PPC64)            += setup_64.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
@@ -105,6 +105,7 @@ obj-$(CONFIG_UPROBES)               += uprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)   += legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_SWIOTLB)          += dma-swiotlb.o
+obj-$(CONFIG_ARCH_HAS_DMA_SET_MASK) += dma-mask.o
 
 pci64-$(CONFIG_PPC64)          += pci_dn.o pci-hotplug.o isa-bridge.o
 obj-$(CONFIG_PCI)              += pci_$(BITS).o $(pci64-y) \
index 9c9bcaae2f759921569001ad7b4474a5f66faecc..09231ef06d01e71645cd92722646b56621c42b9c 100644 (file)
@@ -6,12 +6,31 @@
  * busses using the iommu infrastructure
  */
 
+#include <linux/dma-direct.h>
+#include <linux/pci.h>
 #include <asm/iommu.h>
 
 /*
  * Generic iommu implementation
  */
 
+/*
+ * The coherent mask may be smaller than the real mask, check if we can
+ * really use a direct window.
+ */
+static inline bool dma_iommu_alloc_bypass(struct device *dev)
+{
+       return dev->archdata.iommu_bypass && !iommu_fixed_is_weak &&
+               dma_direct_supported(dev, dev->coherent_dma_mask);
+}
+
+static inline bool dma_iommu_map_bypass(struct device *dev,
+               unsigned long attrs)
+{
+       return dev->archdata.iommu_bypass &&
+               (!iommu_fixed_is_weak || (attrs & DMA_ATTR_WEAK_ORDERING));
+}
+
 /* Allocates a contiguous real buffer and creates mappings over it.
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
@@ -20,6 +39,8 @@ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
                                      dma_addr_t *dma_handle, gfp_t flag,
                                      unsigned long attrs)
 {
+       if (dma_iommu_alloc_bypass(dev))
+               return dma_direct_alloc(dev, size, dma_handle, flag, attrs);
        return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
                                    dma_handle, dev->coherent_dma_mask, flag,
                                    dev_to_node(dev));
@@ -29,7 +50,11 @@ static void dma_iommu_free_coherent(struct device *dev, size_t size,
                                    void *vaddr, dma_addr_t dma_handle,
                                    unsigned long attrs)
 {
-       iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle);
+       if (dma_iommu_alloc_bypass(dev))
+               dma_direct_free(dev, size, vaddr, dma_handle, attrs);
+       else
+               iommu_free_coherent(get_iommu_table_base(dev), size, vaddr,
+                               dma_handle);
 }
 
 /* Creates TCEs for a user provided buffer.  The user buffer must be
@@ -42,6 +67,9 @@ static dma_addr_t dma_iommu_map_page(struct device *dev, struct page *page,
                                     enum dma_data_direction direction,
                                     unsigned long attrs)
 {
+       if (dma_iommu_map_bypass(dev, attrs))
+               return dma_direct_map_page(dev, page, offset, size, direction,
+                               attrs);
        return iommu_map_page(dev, get_iommu_table_base(dev), page, offset,
                              size, device_to_mask(dev), direction, attrs);
 }
@@ -51,8 +79,9 @@ static void dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
                                 size_t size, enum dma_data_direction direction,
                                 unsigned long attrs)
 {
-       iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size, direction,
-                        attrs);
+       if (!dma_iommu_map_bypass(dev, attrs))
+               iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size,
+                               direction,  attrs);
 }
 
 
@@ -60,6 +89,8 @@ static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
                            int nelems, enum dma_data_direction direction,
                            unsigned long attrs)
 {
+       if (dma_iommu_map_bypass(dev, attrs))
+               return dma_direct_map_sg(dev, sglist, nelems, direction, attrs);
        return ppc_iommu_map_sg(dev, get_iommu_table_base(dev), sglist, nelems,
                                device_to_mask(dev), direction, attrs);
 }
@@ -68,10 +99,20 @@ static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
                int nelems, enum dma_data_direction direction,
                unsigned long attrs)
 {
-       ppc_iommu_unmap_sg(get_iommu_table_base(dev), sglist, nelems,
+       if (!dma_iommu_map_bypass(dev, attrs))
+               ppc_iommu_unmap_sg(get_iommu_table_base(dev), sglist, nelems,
                           direction, attrs);
 }
 
+static bool dma_iommu_bypass_supported(struct device *dev, u64 mask)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct pci_controller *phb = pci_bus_to_host(pdev->bus);
+
+       return phb->controller_ops.iommu_bypass_supported &&
+               phb->controller_ops.iommu_bypass_supported(pdev, mask);
+}
+
 /* We support DMA to/from any memory page via the iommu */
 int dma_iommu_dma_supported(struct device *dev, u64 mask)
 {
@@ -83,32 +124,48 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask)
                return 0;
        }
 
+       if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) {
+               dev->archdata.iommu_bypass = true;
+               dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
+               return 1;
+       }
+
        if (tbl->it_offset > (mask >> tbl->it_page_shift)) {
                dev_info(dev, "Warning: IOMMU offset too big for device mask\n");
                dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n",
                                mask, tbl->it_offset << tbl->it_page_shift);
                return 0;
-       } else
-               return 1;
+       }
+
+       dev_dbg(dev, "iommu: not 64-bit, using default ops\n");
+       dev->archdata.iommu_bypass = false;
+       return 1;
 }
 
-static u64 dma_iommu_get_required_mask(struct device *dev)
+u64 dma_iommu_get_required_mask(struct device *dev)
 {
        struct iommu_table *tbl = get_iommu_table_base(dev);
        u64 mask;
+
        if (!tbl)
                return 0;
 
+       if (dev_is_pci(dev)) {
+               u64 bypass_mask = dma_direct_get_required_mask(dev);
+
+               if (dma_iommu_bypass_supported(dev, bypass_mask))
+                       return bypass_mask;
+       }
+
        mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
        mask += mask - 1;
 
        return mask;
 }
 
-struct dma_map_ops dma_iommu_ops = {
+const struct dma_map_ops dma_iommu_ops = {
        .alloc                  = dma_iommu_alloc_coherent,
        .free                   = dma_iommu_free_coherent,
-       .mmap                   = dma_nommu_mmap_coherent,
        .map_sg                 = dma_iommu_map_sg,
        .unmap_sg               = dma_iommu_unmap_sg,
        .dma_supported          = dma_iommu_dma_supported,
diff --git a/arch/powerpc/kernel/dma-mask.c b/arch/powerpc/kernel/dma-mask.c
new file mode 100644 (file)
index 0000000..ffbbbc4
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <asm/machdep.h>
+
+void arch_dma_set_mask(struct device *dev, u64 dma_mask)
+{
+       if (ppc_md.dma_set_mask)
+               ppc_md.dma_set_mask(dev, dma_mask);
+}
+EXPORT_SYMBOL(arch_dma_set_mask);
index 7d5fc9751622323984a53eee4b17f95620d11b1a..132d61c91629e35608db3cb70c495dcedfcd81e0 100644 (file)
  * option) any later version.
  *
  */
-
-#include <linux/dma-direct.h>
 #include <linux/memblock.h>
-#include <linux/pfn.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
-
 #include <asm/machdep.h>
 #include <asm/swiotlb.h>
-#include <asm/dma.h>
 
 unsigned int ppc_swiotlb_enable;
 
-static u64 swiotlb_powerpc_get_required(struct device *dev)
-{
-       u64 end, mask, max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
-
-       end = memblock_end_of_DRAM();
-       if (max_direct_dma_addr && end > max_direct_dma_addr)
-               end = max_direct_dma_addr;
-       end += get_dma_offset(dev);
-
-       mask = 1ULL << (fls64(end) - 1);
-       mask += mask - 1;
-
-       return mask;
-}
-
-/*
- * At the moment, all platforms that use this code only require
- * swiotlb to be used if we're operating on HIGHMEM.  Since
- * we don't ever call anything other than map_sg, unmap_sg,
- * map_page, and unmap_page on highmem, use normal dma_ops
- * for everything else.
- */
-const struct dma_map_ops powerpc_swiotlb_dma_ops = {
-       .alloc = __dma_nommu_alloc_coherent,
-       .free = __dma_nommu_free_coherent,
-       .mmap = dma_nommu_mmap_coherent,
-       .map_sg = dma_direct_map_sg,
-       .unmap_sg = dma_direct_unmap_sg,
-       .dma_supported = swiotlb_dma_supported,
-       .map_page = dma_direct_map_page,
-       .unmap_page = dma_direct_unmap_page,
-       .sync_single_for_cpu = dma_direct_sync_single_for_cpu,
-       .sync_single_for_device = dma_direct_sync_single_for_device,
-       .sync_sg_for_cpu = dma_direct_sync_sg_for_cpu,
-       .sync_sg_for_device = dma_direct_sync_sg_for_device,
-       .get_required_mask = swiotlb_powerpc_get_required,
-};
-
-void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
-{
-       struct pci_controller *hose;
-       struct dev_archdata *sd;
-
-       hose = pci_bus_to_host(pdev->bus);
-       sd = &pdev->dev.archdata;
-       sd->max_direct_dma_addr =
-               hose->dma_window_base_cur + hose->dma_window_size;
-}
-
-static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
-                                 unsigned long action, void *data)
-{
-       struct device *dev = data;
-       struct dev_archdata *sd;
-
-       /* We are only intereted in device addition */
-       if (action != BUS_NOTIFY_ADD_DEVICE)
-               return 0;
-
-       sd = &dev->archdata;
-       sd->max_direct_dma_addr = 0;
-
-       /* May need to bounce if the device can't address all of DRAM */
-       if ((dma_get_mask(dev) + 1) < memblock_end_of_DRAM())
-               set_dma_ops(dev, &powerpc_swiotlb_dma_ops);
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block ppc_swiotlb_plat_bus_notifier = {
-       .notifier_call = ppc_swiotlb_bus_notify,
-       .priority = 0,
-};
-
-int __init swiotlb_setup_bus_notifier(void)
-{
-       bus_register_notifier(&platform_bus_type,
-                             &ppc_swiotlb_plat_bus_notifier);
-       return 0;
-}
-
 void __init swiotlb_detect_4g(void)
 {
        if ((memblock_end_of_DRAM() - 1) > 0xffffffff)
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
deleted file mode 100644 (file)
index b1903eb..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
- *
- * Provide default implementations of the DMA mapping callbacks for
- * directly mapped busses.
- */
-
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/dma-debug.h>
-#include <linux/gfp.h>
-#include <linux/memblock.h>
-#include <linux/export.h>
-#include <linux/pci.h>
-#include <asm/vio.h>
-#include <asm/bug.h>
-#include <asm/machdep.h>
-#include <asm/swiotlb.h>
-#include <asm/iommu.h>
-
-/*
- * Generic direct DMA implementation
- *
- * This implementation supports a per-device offset that can be applied if
- * the address at which memory is visible to devices is not 0. Platform code
- * can set archdata.dma_data to an unsigned long holding the offset. By
- * default the offset is PCI_DRAM_OFFSET.
- */
-
-static u64 __maybe_unused get_pfn_limit(struct device *dev)
-{
-       u64 pfn = (dev->coherent_dma_mask >> PAGE_SHIFT) + 1;
-       struct dev_archdata __maybe_unused *sd = &dev->archdata;
-
-#ifdef CONFIG_SWIOTLB
-       if (sd->max_direct_dma_addr && dev->dma_ops == &powerpc_swiotlb_dma_ops)
-               pfn = min_t(u64, pfn, sd->max_direct_dma_addr >> PAGE_SHIFT);
-#endif
-
-       return pfn;
-}
-
-static int dma_nommu_dma_supported(struct device *dev, u64 mask)
-{
-#ifdef CONFIG_PPC64
-       u64 limit = get_dma_offset(dev) + (memblock_end_of_DRAM() - 1);
-
-       /* Limit fits in the mask, we are good */
-       if (mask >= limit)
-               return 1;
-
-#ifdef CONFIG_FSL_SOC
-       /*
-        * Freescale gets another chance via ZONE_DMA, however
-        * that will have to be refined if/when they support iommus
-        */
-       return 1;
-#endif
-       /* Sorry ... */
-       return 0;
-#else
-       return 1;
-#endif
-}
-
-#ifndef CONFIG_NOT_COHERENT_CACHE
-void *__dma_nommu_alloc_coherent(struct device *dev, size_t size,
-                                 dma_addr_t *dma_handle, gfp_t flag,
-                                 unsigned long attrs)
-{
-       void *ret;
-       struct page *page;
-       int node = dev_to_node(dev);
-#ifdef CONFIG_FSL_SOC
-       u64 pfn = get_pfn_limit(dev);
-       int zone;
-
-       /*
-        * This code should be OK on other platforms, but we have drivers that
-        * don't set coherent_dma_mask. As a workaround we just ifdef it. This
-        * whole routine needs some serious cleanup.
-        */
-
-       zone = dma_pfn_limit_to_zone(pfn);
-       if (zone < 0) {
-               dev_err(dev, "%s: No suitable zone for pfn %#llx\n",
-                       __func__, pfn);
-               return NULL;
-       }
-
-       switch (zone) {
-#ifdef CONFIG_ZONE_DMA
-       case ZONE_DMA:
-               flag |= GFP_DMA;
-               break;
-#endif
-       };
-#endif /* CONFIG_FSL_SOC */
-
-       page = alloc_pages_node(node, flag, get_order(size));
-       if (page == NULL)
-               return NULL;
-       ret = page_address(page);
-       memset(ret, 0, size);
-       *dma_handle = __pa(ret) + get_dma_offset(dev);
-
-       return ret;
-}
-
-void __dma_nommu_free_coherent(struct device *dev, size_t size,
-                               void *vaddr, dma_addr_t dma_handle,
-                               unsigned long attrs)
-{
-       free_pages((unsigned long)vaddr, get_order(size));
-}
-#endif /* !CONFIG_NOT_COHERENT_CACHE */
-
-static void *dma_nommu_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag,
-                                      unsigned long attrs)
-{
-       struct iommu_table *iommu;
-
-       /* The coherent mask may be smaller than the real mask, check if
-        * we can really use the direct ops
-        */
-       if (dma_nommu_dma_supported(dev, dev->coherent_dma_mask))
-               return __dma_nommu_alloc_coherent(dev, size, dma_handle,
-                                                  flag, attrs);
-
-       /* Ok we can't ... do we have an iommu ? If not, fail */
-       iommu = get_iommu_table_base(dev);
-       if (!iommu)
-               return NULL;
-
-       /* Try to use the iommu */
-       return iommu_alloc_coherent(dev, iommu, size, dma_handle,
-                                   dev->coherent_dma_mask, flag,
-                                   dev_to_node(dev));
-}
-
-static void dma_nommu_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t dma_handle,
-                                    unsigned long attrs)
-{
-       struct iommu_table *iommu;
-
-       /* See comments in dma_nommu_alloc_coherent() */
-       if (dma_nommu_dma_supported(dev, dev->coherent_dma_mask))
-               return __dma_nommu_free_coherent(dev, size, vaddr, dma_handle,
-                                                 attrs);
-       /* Maybe we used an iommu ... */
-       iommu = get_iommu_table_base(dev);
-
-       /* If we hit that we should have never allocated in the first
-        * place so how come we are freeing ?
-        */
-       if (WARN_ON(!iommu))
-               return;
-       iommu_free_coherent(iommu, size, vaddr, dma_handle);
-}
-
-int dma_nommu_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
-                            void *cpu_addr, dma_addr_t handle, size_t size,
-                            unsigned long attrs)
-{
-       unsigned long pfn;
-
-#ifdef CONFIG_NOT_COHERENT_CACHE
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       pfn = __dma_get_coherent_pfn((unsigned long)cpu_addr);
-#else
-       pfn = page_to_pfn(virt_to_page(cpu_addr));
-#endif
-       return remap_pfn_range(vma, vma->vm_start,
-                              pfn + vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot);
-}
-
-static int dma_nommu_map_sg(struct device *dev, struct scatterlist *sgl,
-                            int nents, enum dma_data_direction direction,
-                            unsigned long attrs)
-{
-       struct scatterlist *sg;
-       int i;
-
-       for_each_sg(sgl, sg, nents, i) {
-               sg->dma_address = sg_phys(sg) + get_dma_offset(dev);
-               sg->dma_length = sg->length;
-
-               if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
-                       continue;
-
-               __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
-       }
-
-       return nents;
-}
-
-static void dma_nommu_unmap_sg(struct device *dev, struct scatterlist *sgl,
-                               int nents, enum dma_data_direction direction,
-                               unsigned long attrs)
-{
-       struct scatterlist *sg;
-       int i;
-
-       for_each_sg(sgl, sg, nents, i)
-               __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
-}
-
-static u64 dma_nommu_get_required_mask(struct device *dev)
-{
-       u64 end, mask;
-
-       end = memblock_end_of_DRAM() + get_dma_offset(dev);
-
-       mask = 1ULL << (fls64(end) - 1);
-       mask += mask - 1;
-
-       return mask;
-}
-
-static inline dma_addr_t dma_nommu_map_page(struct device *dev,
-                                            struct page *page,
-                                            unsigned long offset,
-                                            size_t size,
-                                            enum dma_data_direction dir,
-                                            unsigned long attrs)
-{
-       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-               __dma_sync_page(page, offset, size, dir);
-
-       return page_to_phys(page) + offset + get_dma_offset(dev);
-}
-
-static inline void dma_nommu_unmap_page(struct device *dev,
-                                        dma_addr_t dma_address,
-                                        size_t size,
-                                        enum dma_data_direction direction,
-                                        unsigned long attrs)
-{
-       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-               __dma_sync(bus_to_virt(dma_address), size, direction);
-}
-
-#ifdef CONFIG_NOT_COHERENT_CACHE
-static inline void dma_nommu_sync_sg(struct device *dev,
-               struct scatterlist *sgl, int nents,
-               enum dma_data_direction direction)
-{
-       struct scatterlist *sg;
-       int i;
-
-       for_each_sg(sgl, sg, nents, i)
-               __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
-}
-
-static inline void dma_nommu_sync_single(struct device *dev,
-                                         dma_addr_t dma_handle, size_t size,
-                                         enum dma_data_direction direction)
-{
-       __dma_sync(bus_to_virt(dma_handle), size, direction);
-}
-#endif
-
-const struct dma_map_ops dma_nommu_ops = {
-       .alloc                          = dma_nommu_alloc_coherent,
-       .free                           = dma_nommu_free_coherent,
-       .mmap                           = dma_nommu_mmap_coherent,
-       .map_sg                         = dma_nommu_map_sg,
-       .unmap_sg                       = dma_nommu_unmap_sg,
-       .dma_supported                  = dma_nommu_dma_supported,
-       .map_page                       = dma_nommu_map_page,
-       .unmap_page                     = dma_nommu_unmap_page,
-       .get_required_mask              = dma_nommu_get_required_mask,
-#ifdef CONFIG_NOT_COHERENT_CACHE
-       .sync_single_for_cpu            = dma_nommu_sync_single,
-       .sync_single_for_device         = dma_nommu_sync_single,
-       .sync_sg_for_cpu                = dma_nommu_sync_sg,
-       .sync_sg_for_device             = dma_nommu_sync_sg,
-#endif
-};
-EXPORT_SYMBOL(dma_nommu_ops);
-
-int dma_set_coherent_mask(struct device *dev, u64 mask)
-{
-       if (!dma_supported(dev, mask)) {
-               /*
-                * We need to special case the direct DMA ops which can
-                * support a fallback for coherent allocations. There
-                * is no dma_op->set_coherent_mask() so we have to do
-                * things the hard way:
-                */
-               if (get_dma_ops(dev) != &dma_nommu_ops ||
-                   get_iommu_table_base(dev) == NULL ||
-                   !dma_iommu_dma_supported(dev, mask))
-                       return -EIO;
-       }
-       dev->coherent_dma_mask = mask;
-       return 0;
-}
-EXPORT_SYMBOL(dma_set_coherent_mask);
-
-int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-       if (ppc_md.dma_set_mask)
-               return ppc_md.dma_set_mask(dev, dma_mask);
-
-       if (dev_is_pci(dev)) {
-               struct pci_dev *pdev = to_pci_dev(dev);
-               struct pci_controller *phb = pci_bus_to_host(pdev->bus);
-               if (phb->controller_ops.dma_set_mask)
-                       return phb->controller_ops.dma_set_mask(pdev, dma_mask);
-       }
-
-       if (!dev->dma_mask || !dma_supported(dev, dma_mask))
-               return -EIO;
-       *dev->dma_mask = dma_mask;
-       return 0;
-}
-EXPORT_SYMBOL(dma_set_mask);
-
-u64 __dma_get_required_mask(struct device *dev)
-{
-       const struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
-       if (unlikely(dma_ops == NULL))
-               return 0;
-
-       if (dma_ops->get_required_mask)
-               return dma_ops->get_required_mask(dev);
-
-       return DMA_BIT_MASK(8 * sizeof(dma_addr_t));
-}
-
-u64 dma_get_required_mask(struct device *dev)
-{
-       if (ppc_md.dma_get_required_mask)
-               return ppc_md.dma_get_required_mask(dev);
-
-       if (dev_is_pci(dev)) {
-               struct pci_dev *pdev = to_pci_dev(dev);
-               struct pci_controller *phb = pci_bus_to_host(pdev->bus);
-               if (phb->controller_ops.dma_get_required_mask)
-                       return phb->controller_ops.dma_get_required_mask(pdev);
-       }
-
-       return __dma_get_required_mask(dev);
-}
-EXPORT_SYMBOL_GPL(dma_get_required_mask);
-
-static int __init dma_init(void)
-{
-#ifdef CONFIG_IBMVIO
-       dma_debug_add_bus(&vio_bus_type);
-#endif
-
-       return 0;
-}
-fs_initcall(dma_init);
-
index ae05203eb4de67ef69e5673d4111ac646049c348..98d8755ac4c84f866ccdd819c4c7361b096fdddd 100644 (file)
@@ -823,15 +823,15 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
        switch (state) {
        case pcie_deassert_reset:
                eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
-               eeh_unfreeze_pe(pe, false);
+               eeh_unfreeze_pe(pe);
                if (!(pe->type & EEH_PE_VF))
-                       eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
+                       eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED, true);
                eeh_pe_dev_traverse(pe, eeh_restore_dev_state, dev);
-               eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
+               eeh_pe_state_clear(pe, EEH_PE_ISOLATED, true);
                break;
        case pcie_hot_reset:
                eeh_pe_mark_isolated(pe);
-               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED, true);
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
                eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev);
                if (!(pe->type & EEH_PE_VF))
@@ -840,7 +840,7 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
                break;
        case pcie_warm_reset:
                eeh_pe_mark_isolated(pe);
-               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED, true);
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
                eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev);
                if (!(pe->type & EEH_PE_VF))
@@ -848,7 +848,7 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
                eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
                break;
        default:
-               eeh_pe_state_clear(pe, EEH_PE_ISOLATED | EEH_PE_CFG_BLOCKED);
+               eeh_pe_state_clear(pe, EEH_PE_ISOLATED | EEH_PE_CFG_BLOCKED, true);
                return -EINVAL;
        };
 
@@ -877,6 +877,24 @@ static void *eeh_set_dev_freset(struct eeh_dev *edev, void *flag)
        return NULL;
 }
 
+static void eeh_pe_refreeze_passed(struct eeh_pe *root)
+{
+       struct eeh_pe *pe;
+       int state;
+
+       eeh_for_each_pe(root, pe) {
+               if (eeh_pe_passed(pe)) {
+                       state = eeh_ops->get_state(pe, NULL);
+                       if (state &
+                          (EEH_STATE_MMIO_ACTIVE | EEH_STATE_MMIO_ENABLED)) {
+                               pr_info("EEH: Passed-through PE PHB#%x-PE#%x was thawed by reset, re-freezing for safety.\n",
+                                       pe->phb->global_number, pe->addr);
+                               eeh_pe_set_option(pe, EEH_OPT_FREEZE_PE);
+                       }
+               }
+       }
+}
+
 /**
  * eeh_pe_reset_full - Complete a full reset process on the indicated PE
  * @pe: EEH PE
@@ -889,12 +907,12 @@ static void *eeh_set_dev_freset(struct eeh_dev *edev, void *flag)
  *
  * This function will attempt to reset a PE three times before failing.
  */
-int eeh_pe_reset_full(struct eeh_pe *pe)
+int eeh_pe_reset_full(struct eeh_pe *pe, bool include_passed)
 {
        int reset_state = (EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
        int type = EEH_RESET_HOT;
        unsigned int freset = 0;
-       int i, state, ret;
+       int i, state = 0, ret;
 
        /*
         * Determine the type of reset to perform - hot or fundamental.
@@ -911,32 +929,42 @@ int eeh_pe_reset_full(struct eeh_pe *pe)
 
        /* Make three attempts at resetting the bus */
        for (i = 0; i < 3; i++) {
-               ret = eeh_pe_reset(pe, type);
-               if (ret)
-                       break;
-
-               ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
-               if (ret)
-                       break;
+               ret = eeh_pe_reset(pe, type, include_passed);
+               if (!ret)
+                       ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE,
+                                          include_passed);
+               if (ret) {
+                       ret = -EIO;
+                       pr_warn("EEH: Failure %d resetting PHB#%x-PE#%x (attempt %d)\n\n",
+                               state, pe->phb->global_number, pe->addr, i + 1);
+                       continue;
+               }
+               if (i)
+                       pr_warn("EEH: PHB#%x-PE#%x: Successful reset (attempt %d)\n",
+                               pe->phb->global_number, pe->addr, i + 1);
 
                /* Wait until the PE is in a functioning state */
                state = eeh_wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
                if (state < 0) {
-                       pr_warn("%s: Unrecoverable slot failure on PHB#%x-PE#%x",
-                               __func__, pe->phb->global_number, pe->addr);
+                       pr_warn("EEH: Unrecoverable slot failure on PHB#%x-PE#%x",
+                               pe->phb->global_number, pe->addr);
                        ret = -ENOTRECOVERABLE;
                        break;
                }
                if (eeh_state_active(state))
                        break;
-
-               /* Set error in case this is our last attempt */
-               ret = -EIO;
-               pr_warn("%s: Failure %d resetting PHB#%x-PE#%x\n (%d)\n",
-                       __func__, state, pe->phb->global_number, pe->addr, (i + 1));
+               else
+                       pr_warn("EEH: PHB#%x-PE#%x: Slot inactive after reset: 0x%x (attempt %d)\n",
+                               pe->phb->global_number, pe->addr, state, i + 1);
        }
 
-       eeh_pe_state_clear(pe, reset_state);
+       /* Resetting the PE may have unfrozen child PEs. If those PEs have been
+        * (potentially) passed through to a guest, re-freeze them:
+        */
+       if (!include_passed)
+               eeh_pe_refreeze_passed(pe);
+
+       eeh_pe_state_clear(pe, reset_state, true);
        return ret;
 }
 
@@ -1309,7 +1337,7 @@ void eeh_remove_device(struct pci_dev *dev)
        edev->mode &= ~EEH_DEV_SYSFS;
 }
 
-int eeh_unfreeze_pe(struct eeh_pe *pe, bool sw_state)
+int eeh_unfreeze_pe(struct eeh_pe *pe)
 {
        int ret;
 
@@ -1327,10 +1355,6 @@ int eeh_unfreeze_pe(struct eeh_pe *pe, bool sw_state)
                return ret;
        }
 
-       /* Clear software isolated state */
-       if (sw_state && (pe->state & EEH_PE_ISOLATED))
-               eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
-
        return ret;
 }
 
@@ -1382,7 +1406,10 @@ static int eeh_pe_change_owner(struct eeh_pe *pe)
                }
        }
 
-       return eeh_unfreeze_pe(pe, true);
+       ret = eeh_unfreeze_pe(pe);
+       if (!ret)
+               eeh_pe_state_clear(pe, EEH_PE_ISOLATED, true);
+       return ret;
 }
 
 /**
@@ -1612,13 +1639,12 @@ int eeh_pe_get_state(struct eeh_pe *pe)
 }
 EXPORT_SYMBOL_GPL(eeh_pe_get_state);
 
-static int eeh_pe_reenable_devices(struct eeh_pe *pe)
+static int eeh_pe_reenable_devices(struct eeh_pe *pe, bool include_passed)
 {
        struct eeh_dev *edev, *tmp;
        struct pci_dev *pdev;
        int ret = 0;
 
-       /* Restore config space */
        eeh_pe_restore_bars(pe);
 
        /*
@@ -1639,7 +1665,14 @@ static int eeh_pe_reenable_devices(struct eeh_pe *pe)
        }
 
        /* The PE is still in frozen state */
-       return eeh_unfreeze_pe(pe, true);
+       if (include_passed || !eeh_pe_passed(pe)) {
+               ret = eeh_unfreeze_pe(pe);
+       } else
+               pr_info("EEH: Note: Leaving passthrough PHB#%x-PE#%x frozen.\n",
+                       pe->phb->global_number, pe->addr);
+       if (!ret)
+               eeh_pe_state_clear(pe, EEH_PE_ISOLATED, include_passed);
+       return ret;
 }
 
 
@@ -1652,7 +1685,7 @@ static int eeh_pe_reenable_devices(struct eeh_pe *pe)
  * indicated type, either fundamental reset or hot reset.
  * PE reset is the most important part for error recovery.
  */
-int eeh_pe_reset(struct eeh_pe *pe, int option)
+int eeh_pe_reset(struct eeh_pe *pe, int option, bool include_passed)
 {
        int ret = 0;
 
@@ -1666,11 +1699,11 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
        switch (option) {
        case EEH_RESET_DEACTIVATE:
                ret = eeh_ops->reset(pe, option);
-               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED, include_passed);
                if (ret)
                        break;
 
-               ret = eeh_pe_reenable_devices(pe);
+               ret = eeh_pe_reenable_devices(pe, include_passed);
                break;
        case EEH_RESET_HOT:
        case EEH_RESET_FUNDAMENTAL:
index 99eab7bc7edc64d20e79130ba0176b4d97aedf57..89623962c7275235db369f3bf28581e13ec019cb 100644 (file)
@@ -510,22 +510,11 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata)
         * support EEH. So we just care about PCI devices for
         * simplicity here.
         */
-       if (!dev || (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
-               return NULL;
-
-       /*
-        * We rely on count-based pcibios_release_device() to
-        * detach permanently offlined PEs. Unfortunately, that's
-        * not reliable enough. We might have the permanently
-        * offlined PEs attached, but we needn't take care of
-        * them and their child devices.
-        */
-       if (eeh_dev_removed(edev))
+       if (!eeh_edev_actionable(edev) ||
+           (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
                return NULL;
 
        if (rmv_data) {
-               if (eeh_pe_passed(edev->pe))
-                       return NULL;
                driver = eeh_pcid_get(dev);
                if (driver) {
                        if (driver->err_handler &&
@@ -539,8 +528,8 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata)
        }
 
        /* Remove it from PCI subsystem */
-       pr_debug("EEH: Removing %s without EEH sensitive driver\n",
-                pci_name(dev));
+       pr_info("EEH: Removing %s without EEH sensitive driver\n",
+               pci_name(dev));
        edev->mode |= EEH_DEV_DISCONNECTED;
        if (rmv_data)
                rmv_data->removed_dev_count++;
@@ -591,34 +580,22 @@ static void *eeh_pe_detach_dev(struct eeh_pe *pe, void *userdata)
  * PE reset (for 3 times), we try to clear the frozen state
  * for 3 times as well.
  */
-static void *__eeh_clear_pe_frozen_state(struct eeh_pe *pe, void *flag)
+static int eeh_clear_pe_frozen_state(struct eeh_pe *root, bool include_passed)
 {
-       bool clear_sw_state = *(bool *)flag;
-       int i, rc = 1;
-
-       for (i = 0; rc && i < 3; i++)
-               rc = eeh_unfreeze_pe(pe, clear_sw_state);
+       struct eeh_pe *pe;
+       int i;
 
-       /* Stop immediately on any errors */
-       if (rc) {
-               pr_warn("%s: Failure %d unfreezing PHB#%x-PE#%x\n",
-                       __func__, rc, pe->phb->global_number, pe->addr);
-               return (void *)pe;
+       eeh_for_each_pe(root, pe) {
+               if (include_passed || !eeh_pe_passed(pe)) {
+                       for (i = 0; i < 3; i++)
+                               if (!eeh_unfreeze_pe(pe))
+                                       break;
+                       if (i >= 3)
+                               return -EIO;
+               }
        }
-
-       return NULL;
-}
-
-static int eeh_clear_pe_frozen_state(struct eeh_pe *pe,
-                                    bool clear_sw_state)
-{
-       void *rc;
-
-       rc = eeh_pe_traverse(pe, __eeh_clear_pe_frozen_state, &clear_sw_state);
-       if (!rc)
-               eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
-
-       return rc ? -EIO : 0;
+       eeh_pe_state_clear(root, EEH_PE_ISOLATED, include_passed);
+       return 0;
 }
 
 int eeh_pe_reset_and_recover(struct eeh_pe *pe)
@@ -636,16 +613,16 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
        eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
 
        /* Issue reset */
-       ret = eeh_pe_reset_full(pe);
+       ret = eeh_pe_reset_full(pe, true);
        if (ret) {
-               eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
+               eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true);
                return ret;
        }
 
        /* Unfreeze the PE */
        ret = eeh_clear_pe_frozen_state(pe, true);
        if (ret) {
-               eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
+               eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true);
                return ret;
        }
 
@@ -653,7 +630,7 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
        eeh_pe_dev_traverse(pe, eeh_dev_restore_state, NULL);
 
        /* Clear recovery mode */
-       eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
+       eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true);
 
        return 0;
 }
@@ -676,6 +653,11 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
        time64_t tstamp;
        int cnt, rc;
        struct eeh_dev *edev;
+       struct eeh_pe *tmp_pe;
+       bool any_passed = false;
+
+       eeh_for_each_pe(pe, tmp_pe)
+               any_passed |= eeh_pe_passed(tmp_pe);
 
        /* pcibios will clear the counter; save the value */
        cnt = pe->freeze_count;
@@ -688,7 +670,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
         * into pci_hp_add_devices().
         */
        eeh_pe_state_mark(pe, EEH_PE_KEEP);
-       if (driver_eeh_aware || (pe->type & EEH_PE_VF)) {
+       if (any_passed || driver_eeh_aware || (pe->type & EEH_PE_VF)) {
                eeh_pe_dev_traverse(pe, eeh_rmv_device, rmv_data);
        } else {
                pci_lock_rescan_remove();
@@ -705,7 +687,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
         * config accesses. So we prefer to block them. However, controlled
         * PCI config accesses initiated from EEH itself are allowed.
         */
-       rc = eeh_pe_reset_full(pe);
+       rc = eeh_pe_reset_full(pe, false);
        if (rc)
                return rc;
 
@@ -744,11 +726,11 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
                        eeh_add_virt_device(edev);
                } else {
                        if (!driver_eeh_aware)
-                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
                        pci_hp_add_devices(bus);
                }
        }
-       eeh_pe_state_clear(pe, EEH_PE_KEEP);
+       eeh_pe_state_clear(pe, EEH_PE_KEEP, true);
 
        pe->tstamp = tstamp;
        pe->freeze_count = cnt;
@@ -900,7 +882,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe)
                         * is still in frozen state. Clear it before
                         * resuming the PE.
                         */
-                       eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
+                       eeh_pe_state_clear(pe, EEH_PE_ISOLATED, true);
                        result = PCI_ERS_RESULT_RECOVERED;
                }
        }
@@ -977,7 +959,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe)
                        eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
                        eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
                } else {
-                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
                        eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
 
                        pci_lock_rescan_remove();
@@ -987,7 +969,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe)
                        return;
                }
        }
-       eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
+       eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true);
 }
 
 /**
@@ -1069,7 +1051,7 @@ void eeh_handle_special_event(void)
                                        continue;
 
                                /* Notify all devices to be down */
-                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
                                eeh_set_channel_state(pe, pci_channel_io_perm_failure);
                                eeh_pe_report(
                                        "error_detected(permanent failure)", pe,
index 6fa2032e05945e1fd5f858e0d37bc3040b0316e7..8b578891f27c2f237c85ad2c0381209203b80a86 100644 (file)
@@ -657,62 +657,52 @@ void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode)
 }
 
 /**
- * __eeh_pe_state_clear - Clear state for the PE
+ * eeh_pe_state_clear - Clear state for the PE
  * @data: EEH PE
- * @flag: state
+ * @state: state
+ * @include_passed: include passed-through devices?
  *
  * The function is used to clear the indicated state from the
  * given PE. Besides, we also clear the check count of the PE
  * as well.
  */
-static void *__eeh_pe_state_clear(struct eeh_pe *pe, void *flag)
+void eeh_pe_state_clear(struct eeh_pe *root, int state, bool include_passed)
 {
-       int state = *((int *)flag);
+       struct eeh_pe *pe;
        struct eeh_dev *edev, *tmp;
        struct pci_dev *pdev;
 
-       /* Keep the state of permanently removed PE intact */
-       if (pe->state & EEH_PE_REMOVED)
-               return NULL;
+       eeh_for_each_pe(root, pe) {
+               /* Keep the state of permanently removed PE intact */
+               if (pe->state & EEH_PE_REMOVED)
+                       continue;
 
-       pe->state &= ~state;
+               if (!include_passed && eeh_pe_passed(pe))
+                       continue;
 
-       /*
-        * Special treatment on clearing isolated state. Clear
-        * check count since last isolation and put all affected
-        * devices to normal state.
-        */
-       if (!(state & EEH_PE_ISOLATED))
-               return NULL;
+               pe->state &= ~state;
 
-       pe->check_count = 0;
-       eeh_pe_for_each_dev(pe, edev, tmp) {
-               pdev = eeh_dev_to_pci_dev(edev);
-               if (!pdev)
+               /*
+                * Special treatment on clearing isolated state. Clear
+                * check count since last isolation and put all affected
+                * devices to normal state.
+                */
+               if (!(state & EEH_PE_ISOLATED))
                        continue;
 
-               pdev->error_state = pci_channel_io_normal;
-       }
-
-       /* Unblock PCI config access if required */
-       if (pe->state & EEH_PE_CFG_RESTRICTED)
-               pe->state &= ~EEH_PE_CFG_BLOCKED;
+               pe->check_count = 0;
+               eeh_pe_for_each_dev(pe, edev, tmp) {
+                       pdev = eeh_dev_to_pci_dev(edev);
+                       if (!pdev)
+                               continue;
 
-       return NULL;
-}
+                       pdev->error_state = pci_channel_io_normal;
+               }
 
-/**
- * eeh_pe_state_clear - Clear state for the PE and its children
- * @pe: PE
- * @state: state to be cleared
- *
- * When the PE and its children has been recovered from error,
- * we need clear the error state for that. The function is used
- * for the purpose.
- */
-void eeh_pe_state_clear(struct eeh_pe *pe, int state)
-{
-       eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
+               /* Unblock PCI config access if required */
+               if (pe->state & EEH_PE_CFG_RESTRICTED)
+                       pe->state &= ~EEH_PE_CFG_BLOCKED;
+       }
 }
 
 /*
index deed906dd8f1200e55e3d3ef65d48b37ec9dfb20..3fa04dda17371ad257164a52b2e951a37e54416f 100644 (file)
@@ -82,8 +82,9 @@ static ssize_t eeh_pe_state_store(struct device *dev,
        if (!(edev->pe->state & EEH_PE_ISOLATED))
                return count;
 
-       if (eeh_unfreeze_pe(edev->pe, true))
+       if (eeh_unfreeze_pe(edev->pe))
                return -EIO;
+       eeh_pe_state_clear(edev->pe, EEH_PE_ISOLATED, true);
 
        return count;
 }
index 435927f549c438614ae680d31775911b3600b417..a2c168b395d2cb726b66405d3326a6d8bcbc4916 100644 (file)
@@ -1002,6 +1002,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
        ld      r2,_NIP(r1)
        mtspr   SPRN_SRR0,r2
 
+       /*
+        * Leaving a stale exception_marker on the stack can confuse
+        * the reliable stack unwinder later on. Clear it.
+        */
+       li      r2,0
+       std     r2,STACK_FRAME_OVERHEAD-16(r1)
+
        ld      r0,GPR0(r1)
        ld      r2,GPR2(r1)
        ld      r3,GPR3(r1)
index 57deb1e9ffea7a70e4f71c4a2457abb7534147fa..20cc816b3508d3f689a11ebefebaf9fc2a711ae2 100644 (file)
@@ -852,11 +852,12 @@ start_here:
 
        /* set up the PTE pointers for the Abatron bdiGDB.
        */
-       tovirt(r6,r6)
        lis     r5, abatron_pteptrs@h
        ori     r5, r5, abatron_pteptrs@l
        stw     r5, 0xf0(0)     /* Must match your Abatron config file */
        tophys(r5,r5)
+       lis     r6, swapper_pg_dir@h
+       ori     r6, r6, swapper_pg_dir@l
        stw     r6, 0(r5)
 
 /* Now turn on the MMU for real! */
index 916ddc4aac443985da55fc38997d75a146401182..bb299613a462cdccf02d20c697fa1c112a31e0a5 100644 (file)
@@ -827,11 +827,6 @@ int irq_choose_cpu(const struct cpumask *mask)
 }
 #endif
 
-int arch_early_irq_init(void)
-{
-       return 0;
-}
-
 #ifdef CONFIG_PPC64
 static int __init setup_noirqdistrib(char *str)
 {
index 88e4f69a09e52624dd75c6e6aaa0d1f894d18758..cbdf13d8622774a9f0a41369a4a77179ceb05d5b 100644 (file)
@@ -62,19 +62,13 @@ resource_size_t isa_mem_base;
 EXPORT_SYMBOL(isa_mem_base);
 
 
-static const struct dma_map_ops *pci_dma_ops = &dma_nommu_ops;
+static const struct dma_map_ops *pci_dma_ops;
 
 void set_pci_dma_ops(const struct dma_map_ops *dma_ops)
 {
        pci_dma_ops = dma_ops;
 }
 
-const struct dma_map_ops *get_pci_dma_ops(void)
-{
-       return pci_dma_ops;
-}
-EXPORT_SYMBOL(get_pci_dma_ops);
-
 /*
  * This function should run under locking protection, specifically
  * hose_spinlock.
@@ -972,7 +966,7 @@ static void pcibios_setup_device(struct pci_dev *dev)
 
        /* Hook up default DMA ops */
        set_dma_ops(&dev->dev, pci_dma_ops);
-       set_dma_offset(&dev->dev, PCI_DRAM_OFFSET);
+       dev->dev.archdata.dma_offset = PCI_DRAM_OFFSET;
 
        /* Additional platform DMA/iommu setup */
        phb = pci_bus_to_host(dev->bus);
index cdd5d1d3ae412114045704aed483497590063e8e..7535f89e08cd2091f32bba708004f820f6ee2fe5 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/perf_event.h>
 #include <linux/context_tracking.h>
+#include <linux/nospec.h>
 
 #include <linux/uaccess.h>
 #include <linux/pkeys.h>
@@ -274,6 +275,8 @@ static int set_user_trap(struct task_struct *task, unsigned long trap)
  */
 int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
 {
+       unsigned int regs_max;
+
        if ((task->thread.regs == NULL) || !data)
                return -EIO;
 
@@ -297,7 +300,9 @@ int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
        }
 #endif
 
-       if (regno < (sizeof(struct user_pt_regs) / sizeof(unsigned long))) {
+       regs_max = sizeof(struct user_pt_regs) / sizeof(unsigned long);
+       if (regno < regs_max) {
+               regno = array_index_nospec(regno, regs_max);
                *data = ((unsigned long *)task->thread.regs)[regno];
                return 0;
        }
@@ -321,6 +326,7 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
                return set_user_dscr(task, data);
 
        if (regno <= PT_MAX_PUT_REG) {
+               regno = array_index_nospec(regno, PT_MAX_PUT_REG + 1);
                ((unsigned long *)task->thread.regs)[regno] = data;
                return 0;
        }
index ca00fbb97cf898966f5f053ce8e7dc300e7c4bc9..fa606aa98f6db5ab58ea74e26ae7aee0822a763e 100644 (file)
@@ -791,7 +791,6 @@ void arch_setup_pdev_archdata(struct platform_device *pdev)
 {
        pdev->archdata.dma_mask = DMA_BIT_MASK(32);
        pdev->dev.dma_mask = &pdev->archdata.dma_mask;
-       set_dma_ops(&pdev->dev, &dma_nommu_ops);
 }
 
 static __init void print_system_info(void)
index bd5e6834ca6928c54a627a470dd1932fd4f91497..6794466f64200b4dae247b8997d530e0b2030cdc 100644 (file)
@@ -755,11 +755,12 @@ SYSCALL_DEFINE0(rt_sigreturn)
                if (restore_tm_sigcontexts(current, &uc->uc_mcontext,
                                           &uc_transact->uc_mcontext))
                        goto badframe;
-       }
+       } else
 #endif
-       /* Fall through, for non-TM restore */
-       if (!MSR_TM_ACTIVE(msr)) {
+       {
                /*
+                * Fall through, for non-TM restore
+                *
                 * Unset MSR[TS] on the thread regs since MSR from user
                 * context does not have MSR active, and recheckpoint was
                 * not called since restore_tm_sigcontexts() was not called
index e2c50b55138f8ab52eecace4c6aad72c382e6bcd..cf31ce6c1f53df272d44768be8de14f0733143e6 100644 (file)
@@ -84,25 +84,22 @@ save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
 EXPORT_SYMBOL_GPL(save_stack_trace_regs);
 
 #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
+/*
+ * This function returns an error if it detects any unreliable features of the
+ * stack.  Otherwise it guarantees that the stack trace is reliable.
+ *
+ * If the task is not 'current', the caller *must* ensure the task is inactive.
+ */
 int
 save_stack_trace_tsk_reliable(struct task_struct *tsk,
                                struct stack_trace *trace)
 {
        unsigned long sp;
+       unsigned long newsp;
        unsigned long stack_page = (unsigned long)task_stack_page(tsk);
        unsigned long stack_end;
        int graph_idx = 0;
-
-       /*
-        * The last frame (unwinding first) may not yet have saved
-        * its LR onto the stack.
-        */
-       int firstframe = 1;
-
-       if (tsk == current)
-               sp = current_stack_pointer();
-       else
-               sp = tsk->thread.ksp;
+       bool firstframe;
 
        stack_end = stack_page + THREAD_SIZE;
        if (!is_idle_task(tsk)) {
@@ -129,40 +126,53 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
                stack_end -= STACK_FRAME_OVERHEAD;
        }
 
+       if (tsk == current)
+               sp = current_stack_pointer();
+       else
+               sp = tsk->thread.ksp;
+
        if (sp < stack_page + sizeof(struct thread_struct) ||
            sp > stack_end - STACK_FRAME_MIN_SIZE) {
-               return 1;
+               return -EINVAL;
        }
 
-       for (;;) {
+       for (firstframe = true; sp != stack_end;
+            firstframe = false, sp = newsp) {
                unsigned long *stack = (unsigned long *) sp;
-               unsigned long newsp, ip;
+               unsigned long ip;
 
                /* sanity check: ABI requires SP to be aligned 16 bytes. */
                if (sp & 0xF)
-                       return 1;
-
-               /* Mark stacktraces with exception frames as unreliable. */
-               if (sp <= stack_end - STACK_INT_FRAME_SIZE &&
-                   stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
-                       return 1;
-               }
+                       return -EINVAL;
 
                newsp = stack[0];
                /* Stack grows downwards; unwinder may only go up. */
                if (newsp <= sp)
-                       return 1;
+                       return -EINVAL;
 
                if (newsp != stack_end &&
                    newsp > stack_end - STACK_FRAME_MIN_SIZE) {
-                       return 1; /* invalid backlink, too far up. */
+                       return -EINVAL; /* invalid backlink, too far up. */
+               }
+
+               /*
+                * We can only trust the bottom frame's backlink, the
+                * rest of the frame may be uninitialized, continue to
+                * the next.
+                */
+               if (firstframe)
+                       continue;
+
+               /* Mark stacktraces with exception frames as unreliable. */
+               if (sp <= stack_end - STACK_INT_FRAME_SIZE &&
+                   stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
+                       return -EINVAL;
                }
 
                /* Examine the saved LR: it must point into kernel code. */
                ip = stack[STACK_FRAME_LR_SAVE];
-               if (!firstframe && !__kernel_text_address(ip))
-                       return 1;
-               firstframe = 0;
+               if (!__kernel_text_address(ip))
+                       return -EINVAL;
 
                /*
                 * FIXME: IMHO these tests do not belong in
@@ -175,21 +185,15 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
                 * as unreliable.
                 */
                if (ip == (unsigned long)kretprobe_trampoline)
-                       return 1;
+                       return -EINVAL;
 #endif
 
+               if (trace->nr_entries >= trace->max_entries)
+                       return -E2BIG;
                if (!trace->skip)
                        trace->entries[trace->nr_entries++] = ip;
                else
                        trace->skip--;
-
-               if (newsp == stack_end)
-                       break;
-
-               if (trace->nr_entries >= trace->max_entries)
-                       return -E2BIG;
-
-               sp = newsp;
        }
        return 0;
 }
index 3646affae963fec23ae64a26350adce79c5a4879..bc0503ef9c9ceb74d0dd38a6c00650f87bdec420 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/irq_work.h>
 #include <linux/clk-provider.h>
 #include <linux/suspend.h>
-#include <linux/rtc.h>
 #include <linux/sched/cputime.h>
 #include <linux/processor.h>
 #include <asm/trace.h>
index 29746dc28df5286187f97afad9d8c1008663143b..517662a56bdc937e1e7dd98d72ec17404c297565 100644 (file)
@@ -967,13 +967,6 @@ out:
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
-#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64)
-unsigned long __init arch_syscall_addr(int nr)
-{
-       return sys_call_table[nr*2];
-}
-#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
-
 #ifdef PPC64_ELF_ABI_v1
 char *arch_ftrace_match_adjust(char *str, const char *search)
 {
index 64936b60d5216e185670ebbb3424be395fe740d9..040b602936132ecf10bed914dcb428669f90a9bc 100644 (file)
@@ -257,24 +257,17 @@ static int __die(const char *str, struct pt_regs *regs, long err)
 {
        printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
 
-       if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
-               printk("LE ");
-       else
-               printk("BE ");
-
-       if (IS_ENABLED(CONFIG_PREEMPT))
-               pr_cont("PREEMPT ");
-
-       if (IS_ENABLED(CONFIG_SMP))
-               pr_cont("SMP NR_CPUS=%d ", NR_CPUS);
-
-       if (debug_pagealloc_enabled())
-               pr_cont("DEBUG_PAGEALLOC ");
-
-       if (IS_ENABLED(CONFIG_NUMA))
-               pr_cont("NUMA ");
-
-       pr_cont("%s\n", ppc_md.name ? ppc_md.name : "");
+       printk("%s PAGE_SIZE=%luK%s%s%s%s%s%s%s %s\n",
+              IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) ? "LE" : "BE",
+              PAGE_SIZE / 1024,
+              early_radix_enabled() ? " MMU=Radix" : "",
+              early_mmu_has_feature(MMU_FTR_HPTE_TABLE) ? " MMU=Hash" : "",
+              IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "",
+              IS_ENABLED(CONFIG_SMP) ? " SMP" : "",
+              IS_ENABLED(CONFIG_SMP) ? (" NR_CPUS=" __stringify(NR_CPUS)) : "",
+              debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "",
+              IS_ENABLED(CONFIG_NUMA) ? " NUMA" : "",
+              ppc_md.name ? ppc_md.name : "");
 
        if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV) == NOTIFY_STOP)
                return 1;
@@ -1542,8 +1535,8 @@ bail:
 
 void StackOverflow(struct pt_regs *regs)
 {
-       printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
-              current, regs->gpr[1]);
+       pr_crit("Kernel stack overflow in process %s[%d], r1=%lx\n",
+               current->comm, task_pid_nr(current), regs->gpr[1]);
        debugger(regs);
        show_regs(regs);
        panic("kernel stack overflow");
index 7cc38b5b58bce600d578a4e500a400b510572589..8db4891acdafebcd2b8f85c57f53c73627850017 100644 (file)
@@ -74,7 +74,7 @@ void __init udbg_early_init(void)
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
-       console_loglevel = 10;
+       console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
 
        register_early_udbg_console();
 #endif
index ad1c77f71f5474e91219c36fa827b5079b60be62..c3efb972c8c1cbc0e39b0a9618058b673ed76d0a 100644 (file)
@@ -86,11 +86,11 @@ SECTIONS
 
 #ifdef CONFIG_PPC64
        /*
-        * BLOCK(0) overrides the default output section alignment because
+        * ALIGN(0) overrides the default output section alignment because
         * this needs to start right after .head.text in order for fixed
         * section placement to work.
         */
-       .text BLOCK(0) : AT(ADDR(.text) - LOAD_OFFSET) {
+       .text ALIGN(0) : AT(ADDR(.text) - LOAD_OFFSET) {
 #ifdef CONFIG_LD_HEAD_STUB_CATCH
                KEEP(*(.linker_stub_catch));
                . = . ;
@@ -319,6 +319,7 @@ SECTIONS
                *(.sdata2)
                *(.got.plt) *(.got)
                *(.plt)
+               *(.branch_lt)
        }
 #else
        .data : AT(ADDR(.data) - LOAD_OFFSET) {
index 64f1135e77323b180cfdb34e3d42a01cde13803c..3223aec88b2cc314c0f0b0485c1b9049f278d3d7 100644 (file)
@@ -10,11 +10,6 @@ common-objs-y = $(KVM)/kvm_main.o $(KVM)/eventfd.o
 common-objs-$(CONFIG_KVM_VFIO) += $(KVM)/vfio.o
 common-objs-$(CONFIG_KVM_MMIO) += $(KVM)/coalesced_mmio.o
 
-CFLAGS_e500_mmu.o := -I.
-CFLAGS_e500_mmu_host.o := -I.
-CFLAGS_emulate.o  := -I.
-CFLAGS_emulate_loadstore.o  := -I.
-
 common-objs-y += powerpc.o emulate_loadstore.o
 obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o
 obj-$(CONFIG_KVM_BOOK3S_HANDLER) += book3s_exports.o
index 494df26c59885b97fd648ccc2e26a921570d6b69..a8794032f15ff35419b2ca25bd94009d18667662 100644 (file)
@@ -17,4 +17,4 @@ obj-$(CONFIG_SPE)             += math_efp.o
 CFLAGS_fabs.o = -fno-builtin-fabs
 CFLAGS_math.o = -fno-builtin-fabs
 
-ccflags-y = -I. -Iinclude/math-emu -w
+ccflags-y = -w
index e955539686a41e0fa5c89cc79671c170c35f6d66..b5d2658c26afb783d9e2900f8f09d7be0d36f500 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/highmem.h>
 #include <linux/dma-direct.h>
+#include <linux/dma-noncoherent.h>
 #include <linux/export.h>
 
 #include <asm/tlbflush.h>
@@ -151,8 +152,8 @@ static struct ppc_vm_region *ppc_vm_region_find(struct ppc_vm_region *head, unsi
  * Allocate DMA-coherent memory space and return both the kernel remapped
  * virtual and bus address for that space.
  */
-void *__dma_nommu_alloc_coherent(struct device *dev, size_t size,
-               dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+               gfp_t gfp, unsigned long attrs)
 {
        struct page *page;
        struct ppc_vm_region *c;
@@ -253,7 +254,7 @@ void *__dma_nommu_alloc_coherent(struct device *dev, size_t size,
 /*
  * free a page as defined by the above mapping.
  */
-void __dma_nommu_free_coherent(struct device *dev, size_t size, void *vaddr,
+void arch_dma_free(struct device *dev, size_t size, void *vaddr,
                dma_addr_t dma_handle, unsigned long attrs)
 {
        struct ppc_vm_region *c;
@@ -313,7 +314,7 @@ void __dma_nommu_free_coherent(struct device *dev, size_t size, void *vaddr,
 /*
  * make an area consistent.
  */
-void __dma_sync(void *vaddr, size_t size, int direction)
+static void __dma_sync(void *vaddr, size_t size, int direction)
 {
        unsigned long start = (unsigned long)vaddr;
        unsigned long end   = start + size;
@@ -339,7 +340,6 @@ void __dma_sync(void *vaddr, size_t size, int direction)
                break;
        }
 }
-EXPORT_SYMBOL(__dma_sync);
 
 #ifdef CONFIG_HIGHMEM
 /*
@@ -386,28 +386,42 @@ static inline void __dma_sync_page_highmem(struct page *page,
  * __dma_sync_page makes memory consistent. identical to __dma_sync, but
  * takes a struct page instead of a virtual address
  */
-void __dma_sync_page(struct page *page, unsigned long offset,
-       size_t size, int direction)
+static void __dma_sync_page(phys_addr_t paddr, size_t size, int dir)
 {
+       struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
+       unsigned offset = paddr & ~PAGE_MASK;
+
 #ifdef CONFIG_HIGHMEM
-       __dma_sync_page_highmem(page, offset, size, direction);
+       __dma_sync_page_highmem(page, offset, size, dir);
 #else
        unsigned long start = (unsigned long)page_address(page) + offset;
-       __dma_sync((void *)start, size, direction);
+       __dma_sync((void *)start, size, dir);
 #endif
 }
-EXPORT_SYMBOL(__dma_sync_page);
+
+void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_sync_page(paddr, size, dir);
+}
+
+void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_sync_page(paddr, size, dir);
+}
 
 /*
- * Return the PFN for a given cpu virtual address returned by
- * __dma_nommu_alloc_coherent. This is used by dma_mmap_coherent()
+ * Return the PFN for a given cpu virtual address returned by arch_dma_alloc.
  */
-unsigned long __dma_get_coherent_pfn(unsigned long cpu_addr)
+long arch_dma_coherent_to_pfn(struct device *dev, void *vaddr,
+               dma_addr_t dma_addr)
 {
        /* This should always be populated, so we don't test every
         * level. If that fails, we'll have a nice crash which
         * will be as good as a BUG_ON()
         */
+       unsigned long cpu_addr = (unsigned long)vaddr;
        pgd_t *pgd = pgd_offset_k(cpu_addr);
        pud_t *pud = pud_offset(pgd, cpu_addr);
        pmd_t *pmd = pmd_offset(pud, cpu_addr);
index 0cc7fbc3bd1c76d3b786979332a059d303726555..4aa0797000f7fcab00d75c93e393915c81aa4841 100644 (file)
@@ -1889,12 +1889,12 @@ static int hpt_order_set(void *data, u64 val)
        return mmu_hash_ops.resize_hpt(val);
 }
 
-DEFINE_SIMPLE_ATTRIBUTE(fops_hpt_order, hpt_order_get, hpt_order_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_hpt_order, hpt_order_get, hpt_order_set, "%llu\n");
 
 static int __init hash64_debugfs(void)
 {
-       if (!debugfs_create_file("hpt_order", 0600, powerpc_debugfs_root,
-                                NULL, &fops_hpt_order)) {
+       if (!debugfs_create_file_unsafe("hpt_order", 0600, powerpc_debugfs_root,
+                                       NULL, &fops_hpt_order)) {
                pr_err("lpar: unable to create hpt_order debugsfs file\n");
        }
 
index 33cc6f676fa6224b76fe0f37399a30b2d852b449..f6787f90e1585bb735e38ee85a869e865486f9af 100644 (file)
@@ -69,22 +69,14 @@ pte_t *kmap_pte;
 EXPORT_SYMBOL(kmap_pte);
 pgprot_t kmap_prot;
 EXPORT_SYMBOL(kmap_prot);
-#define TOP_ZONE ZONE_HIGHMEM
 
 static inline pte_t *virt_to_kpte(unsigned long vaddr)
 {
        return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
                        vaddr), vaddr), vaddr);
 }
-#else
-#define TOP_ZONE ZONE_NORMAL
 #endif
 
-int page_is_ram(unsigned long pfn)
-{
-       return memblock_is_memory(__pfn_to_phys(pfn));
-}
-
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                              unsigned long size, pgprot_t vma_prot)
 {
@@ -176,34 +168,6 @@ int __meminit arch_remove_memory(int nid, u64 start, u64 size,
 #endif
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
-/*
- * walk_memory_resource() needs to make sure there is no holes in a given
- * memory range.  PPC64 does not maintain the memory layout in /proc/iomem.
- * Instead it maintains it in memblock.memory structures.  Walk through the
- * memory regions, find holes and callback for contiguous regions.
- */
-int
-walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
-               void *arg, int (*func)(unsigned long, unsigned long, void *))
-{
-       struct memblock_region *reg;
-       unsigned long end_pfn = start_pfn + nr_pages;
-       unsigned long tstart, tend;
-       int ret = -1;
-
-       for_each_memblock(memory, reg) {
-               tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
-               tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
-               if (tstart >= tend)
-                       continue;
-               ret = (*func)(tstart, tend - tstart, arg);
-               if (ret)
-                       break;
-       }
-       return ret;
-}
-EXPORT_SYMBOL_GPL(walk_system_ram_range);
-
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 void __init mem_topology_setup(void)
 {
@@ -261,25 +225,6 @@ static int __init mark_nonram_nosave(void)
  */
 static unsigned long max_zone_pfns[MAX_NR_ZONES];
 
-/*
- * Find the least restrictive zone that is entirely below the
- * specified pfn limit.  Returns < 0 if no suitable zone is found.
- *
- * pfn_limit must be u64 because it can exceed 32 bits even on 32-bit
- * systems -- the DMA limit can be higher than any possible real pfn.
- */
-int dma_pfn_limit_to_zone(u64 pfn_limit)
-{
-       int i;
-
-       for (i = TOP_ZONE; i >= 0; i--) {
-               if (max_zone_pfns[i] <= pfn_limit)
-                       return i;
-       }
-
-       return -EPERM;
-}
-
 /*
  * paging_init() sets up the page tables - in fact we've already done this.
  */
@@ -585,3 +530,9 @@ int devmem_is_allowed(unsigned long pfn)
        return 0;
 }
 #endif /* CONFIG_STRICT_DEVMEM */
+
+/*
+ * This is defined in kernel/resource.c but only powerpc needs to export it, for
+ * the EHEA driver. Drop this when drivers/net/ethernet/ibm/ehea is removed.
+ */
+EXPORT_SYMBOL_GPL(walk_system_ram_range);
index 87f0dd004295761b321216adf333f1eab1ca09df..b5d1c45c14758001e9b61849d31eeb36c82c264c 100644 (file)
@@ -1460,13 +1460,6 @@ static void reset_topology_timer(void)
 
 #ifdef CONFIG_SMP
 
-static void stage_topology_update(int core_id)
-{
-       cpumask_or(&cpu_associativity_changes_mask,
-               &cpu_associativity_changes_mask, cpu_sibling_mask(core_id));
-       reset_topology_timer();
-}
-
 static int dt_update_callback(struct notifier_block *nb,
                                unsigned long action, void *data)
 {
@@ -1479,7 +1472,7 @@ static int dt_update_callback(struct notifier_block *nb,
                    !of_prop_cmp(update->prop->name, "ibm,associativity")) {
                        u32 core_id;
                        of_property_read_u32(update->dn, "reg", &core_id);
-                       stage_topology_update(core_id);
+                       rc = dlpar_cpu_readd(core_id);
                        rc = NOTIFY_OK;
                }
                break;
index f3c31f5e1026fca9f2e01da261e1319dccbceaf0..ecd31569a120a716d30d1f030b6732e0298a172b 100644 (file)
@@ -400,3 +400,25 @@ void arch_report_meminfo(struct seq_file *m)
                   atomic_long_read(&direct_pages_count[MMU_PAGE_1G]) << 20);
 }
 #endif /* CONFIG_PROC_FS */
+
+/*
+ * For hash translation mode, we use the deposited table to store hash slot
+ * information and they are stored at PTRS_PER_PMD offset from related pmd
+ * location. Hence a pmd move requires deposit and withdraw.
+ *
+ * For radix translation with split pmd ptl, we store the deposited table in the
+ * pmd page. Hence if we have different pmd page we need to withdraw during pmd
+ * move.
+ *
+ * With hash we use deposited table always irrespective of anon or not.
+ * With radix we use deposited table only for anonymous mapping.
+ */
+int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                          struct spinlock *old_pmd_ptl,
+                          struct vm_area_struct *vma)
+{
+       if (radix_enabled())
+               return (new_pmd_ptl != old_pmd_ptl) && vma_is_anonymous(vma);
+
+       return true;
+}
index ae5d568e267f681d43367b19e9b21f7307debfe3..ac23dc1c653520d3e152e9807919f5080c408819 100644 (file)
@@ -302,7 +302,7 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
         * This function as well as __local_flush_tlb_page() must only be called
         * for user contexts.
         */
-       if (unlikely(WARN_ON(!mm)))
+       if (WARN_ON(!mm))
                return;
 
        preempt_disable();
index 5c36b3a8d47aba640d5136dcdfca30469375a3a6..3349f3f8fe840ae52de297d59822f103726259ff 100644 (file)
@@ -70,6 +70,7 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
        PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar),
        PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr),
        PT_REGS_OFFSET(PERF_REG_POWERPC_SIER, dar),
+       PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr),
 };
 
 u64 perf_reg_value(struct pt_regs *regs, int idx)
@@ -83,6 +84,11 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
            !is_sier_available()))
                return 0;
 
+       if (idx == PERF_REG_POWERPC_MMCRA &&
+          (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
+           IS_ENABLED(CONFIG_PPC32)))
+               return 0;
+
        return regs_get_register(regs, pt_regs_offset[idx]);
 }
 
index 7de344b7d9cc262472db1c3b3d068ad37e5d556d..063c9d9f25162c025c7d727ee9492511848b6b5c 100644 (file)
@@ -97,3 +97,27 @@ EVENT(PM_MRK_DTLB_MISS_64K,                  0x3d156)
 EVENT(PM_DTLB_MISS_16M,                                0x4c056)
 EVENT(PM_DTLB_MISS_1G,                         0x4c05a)
 EVENT(PM_MRK_DTLB_MISS_16M,                    0x4c15e)
+
+/*
+ * Memory Access Events
+ *
+ * Primary PMU event used here is PM_MRK_INST_CMPL (0x401e0)
+ * To enable capturing of memory profiling, these MMCRA bits
+ * needs to be programmed and corresponding raw event format
+ * encoding.
+ *
+ * MMCRA bits encoding needed are
+ *     SM (Sampling Mode)
+ *     EM (Eligibility for Random Sampling)
+ *     TECE (Threshold Event Counter Event)
+ *     TS (Threshold Start Event)
+ *     TE (Threshold End Event)
+ *
+ * Corresponding Raw Encoding bits:
+ *     sample [EM,SM]
+ *     thresh_sel (TECE)
+ *     thresh start (TS)
+ *     thresh end (TE)
+ */
+EVENT(MEM_LOADS,                               0x34340401e0)
+EVENT(MEM_STORES,                              0x343c0401e0)
index 0ff9c43733e97179bacbe9ca406e834c37e9cc7a..030544e35959fe494536617df31d92a4dd0f79bc 100644 (file)
@@ -160,6 +160,8 @@ GENERIC_EVENT_ATTR(branch-instructions,             PM_BR_CMPL);
 GENERIC_EVENT_ATTR(branch-misses,              PM_BR_MPRED_CMPL);
 GENERIC_EVENT_ATTR(cache-references,           PM_LD_REF_L1);
 GENERIC_EVENT_ATTR(cache-misses,               PM_LD_MISS_L1_FIN);
+GENERIC_EVENT_ATTR(mem-loads,                  MEM_LOADS);
+GENERIC_EVENT_ATTR(mem-stores,                 MEM_STORES);
 
 CACHE_EVENT_ATTR(L1-dcache-load-misses,                PM_LD_MISS_L1_FIN);
 CACHE_EVENT_ATTR(L1-dcache-loads,              PM_LD_REF_L1);
@@ -185,6 +187,8 @@ static struct attribute *power9_events_attr[] = {
        GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
        GENERIC_EVENT_PTR(PM_LD_REF_L1),
        GENERIC_EVENT_PTR(PM_LD_MISS_L1_FIN),
+       GENERIC_EVENT_PTR(MEM_LOADS),
+       GENERIC_EVENT_PTR(MEM_STORES),
        CACHE_EVENT_PTR(PM_LD_MISS_L1_FIN),
        CACHE_EVENT_PTR(PM_LD_REF_L1),
        CACHE_EVENT_PTR(PM_L1_PREF),
index e55933f9cd55f9e6576cf6ff8c838bb949a47145..a5e61e5c16e27db4b9633c4058b0858f22f91821 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/ppc4xx.h>
 #include <asm/mpic.h>
 #include <asm/mmu.h>
+#include <asm/swiotlb.h>
 
 #include <linux/pci.h>
 #include <linux/i2c.h>
index f467247fd1c45033b49a673caffb3917e1b19a1e..18422dbd061adcec2247a1a7ac468f154546db3c 100644 (file)
@@ -47,7 +47,7 @@ static int __init warp_probe(void)
        if (!of_machine_is_compatible("pika,warp"))
                return 0;
 
-       /* For __dma_nommu_alloc_coherent */
+       /* For arch_dma_alloc */
        ISA_DMA_THRESHOLD = ~0L;
 
        return 1;
index a1aaa1569d7ce63793398610b4abdb8a0f38ebe1..f0e488d975678eaca40e7ab8baa4d1a04e41d7f0 100644 (file)
@@ -237,12 +237,12 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                        continue;
 
                seq_printf(m, "PPC4XX OCM   : %d\n", ocm->index);
-               seq_printf(m, "PhysAddr     : %pa[p]\n", &(ocm->phys));
+               seq_printf(m, "PhysAddr     : %pa\n", &(ocm->phys));
                seq_printf(m, "MemTotal     : %d Bytes\n", ocm->memtotal);
                seq_printf(m, "MemTotal(NC) : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "MemTotal(C)  : %d Bytes\n\n", ocm->c.memtotal);
 
-               seq_printf(m, "NC.PhysAddr  : %pa[p]\n", &(ocm->nc.phys));
+               seq_printf(m, "NC.PhysAddr  : %pa\n", &(ocm->nc.phys));
                seq_printf(m, "NC.VirtAddr  : 0x%p\n", ocm->nc.virt);
                seq_printf(m, "NC.MemTotal  : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "NC.MemFree   : %d Bytes\n", ocm->nc.memfree);
@@ -252,7 +252,7 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                                                        blk->size, blk->owner);
                }
 
-               seq_printf(m, "\nC.PhysAddr   : %pa[p]\n", &(ocm->c.phys));
+               seq_printf(m, "\nC.PhysAddr   : %pa\n", &(ocm->c.phys));
                seq_printf(m, "C.VirtAddr   : 0x%p\n", ocm->c.virt);
                seq_printf(m, "C.MemTotal   : %d Bytes\n", ocm->c.memtotal);
                seq_printf(m, "C.MemFree    : %d Bytes\n", ocm->c.memfree);
index b0dac307bebf9cb96d30bfd38c84a38113498548..785e9641220da1dce6ca2fcec5a6fcf9343f65c7 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/udbg.h>
 #include <asm/mpic.h>
 #include <asm/ehv_pic.h>
+#include <asm/swiotlb.h>
 #include <soc/fsl/qe/qe_ic.h>
 
 #include <linux/of_platform.h>
@@ -223,7 +224,3 @@ define_machine(corenet_generic) {
 };
 
 machine_arch_initcall(corenet_generic, corenet_gen_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(corenet_generic, swiotlb_setup_bus_notifier);
-#endif
index f29c6f0909f354b089b31f3f4773bbc3fa411e10..c64fa2483ea973ec98ddbcfdeec11d28581ea84b 100644 (file)
@@ -202,8 +202,6 @@ static int __init ge_imp3a_probe(void)
 
 machine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices);
 
-machine_arch_initcall(ge_imp3a, swiotlb_setup_bus_notifier);
-
 define_machine(ge_imp3a) {
        .name                   = "GE_IMP3A",
        .probe                  = ge_imp3a_probe,
index 94a7f92c858ffee2c41903f16f82a5cd492522fe..94194bad4954e1636af2322d096d4b5f63053b39 100644 (file)
@@ -57,8 +57,6 @@ static void __init mpc8536_ds_setup_arch(void)
 
 machine_arch_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
 
-machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier);
-
 /*
  * Called very early, device-tree isn't unflattened
  */
index dc9e035cc637a749061a2b25e1a44d93998f8289..b7e29ce1f266f58a120ef247366ff3ddd1d9a6d0 100644 (file)
@@ -174,10 +174,6 @@ machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
 machine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
 machine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices);
 
-machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
-machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
-machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier);
-
 /*
  * Called very early, device-tree isn't unflattened
  */
index d7e440e6dba3d3d45615e26f26894bf09bb1615c..80939a425de594d9be79fd9f52efaeb2c9b3282a 100644 (file)
@@ -367,10 +367,6 @@ machine_arch_initcall(mpc8568_mds, mpc85xx_publish_devices);
 machine_arch_initcall(mpc8569_mds, mpc85xx_publish_devices);
 machine_arch_initcall(p1021_mds, mpc85xx_common_publish_devices);
 
-machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
-machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
-machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier);
-
 static void __init mpc85xx_mds_pic_init(void)
 {
        struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
index 78d13b364cd631e6c4b2863171fc8382796c4490..33ca373322e18f66a9a252011516e36425d41dea 100644 (file)
@@ -55,7 +55,6 @@ static void __init p1010_rdb_setup_arch(void)
 }
 
 machine_arch_initcall(p1010_rdb, mpc85xx_common_publish_devices);
-machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
 
 /*
  * Called very early, device-tree isn't unflattened
index 9fb57f78cdbe37f08a3d5f2ddef7b06696e04aa2..1f1af0557470feb924448adc98653552d1066209 100644 (file)
@@ -548,8 +548,6 @@ static void __init p1022_ds_setup_arch(void)
 
 machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices);
 
-machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
-
 /*
  * Called very early, device-tree isn't unflattened
  */
index 276e00ab3dde97a766b6652d7f9dd714a6ea302f..fd9e3e7ef23475f7c9887a4338c981f546f52301 100644 (file)
@@ -128,8 +128,6 @@ static void __init p1022_rdk_setup_arch(void)
 
 machine_arch_initcall(p1022_rdk, mpc85xx_common_publish_devices);
 
-machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier);
-
 /*
  * Called very early, device-tree isn't unflattened
  */
index 27631c607f3d9a48308593ecfd4fceec873e57b6..c52c8f9e83852bf1c2ed55d3bb017daf0a71b64f 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/time.h>
 #include <asm/udbg.h>
 #include <asm/mpic.h>
+#include <asm/swiotlb.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include "smp.h"
index 17c6cd3d02e6727bb13abb419ef13d72661d749d..775a92353c8329e2f6377937db6037283d99150e 100644 (file)
@@ -121,7 +121,6 @@ static int __init declare_of_platform_devices(void)
        return 0;
 }
 machine_arch_initcall(mpc86xx_hpcn, declare_of_platform_devices);
-machine_arch_initcall(mpc86xx_hpcn, swiotlb_setup_bus_notifier);
 
 define_machine(mpc86xx_hpcn) {
        .name                   = "MPC86xx HPCN",
index 8c7464c3f27fee422df6790b4c7cff2504361333..842b2c7e156aba4cb2a04d8897fb7aa6128c3b4d 100644 (file)
@@ -153,6 +153,11 @@ config E300C3_CPU
        bool "e300c3 (831x)"
        depends on PPC_BOOK3S_32
 
+config G4_CPU
+       bool "G4 (74xx)"
+       depends on PPC_BOOK3S_32
+       select ALTIVEC
+
 endchoice
 
 config TARGET_CPU_BOOL
@@ -171,6 +176,7 @@ config TARGET_CPU
        default "860" if 860_CPU
        default "e300c2" if E300C2_CPU
        default "e300c3" if E300C3_CPU
+       default "G4" if G4_CPU
 
 config PPC_BOOK3S
        def_bool y
@@ -402,6 +408,9 @@ config NOT_COHERENT_CACHE
        bool
        depends on 4xx || PPC_8xx || E200 || PPC_MPC512x || \
                GAMECUBE_COMMON || AMIGAONE
+       select ARCH_HAS_DMA_COHERENT_TO_PFN
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE
+       select ARCH_HAS_SYNC_DMA_FOR_CPU
        default n if PPC_47x
        default y
 
index af2a3c15e0ecc2cf7e6eedafd9a828738b0f353b..54e012e1f720e8d8b2208d81a18d433ccb99a74d 100644 (file)
@@ -544,9 +544,10 @@ static struct cbe_iommu *cell_iommu_for_node(int nid)
 static unsigned long cell_dma_nommu_offset;
 
 static unsigned long dma_iommu_fixed_base;
+static bool cell_iommu_enabled;
 
 /* iommu_fixed_is_weak is set if booted with iommu_fixed=weak */
-static int iommu_fixed_is_weak;
+bool iommu_fixed_is_weak;
 
 static struct iommu_table *cell_get_iommu_table(struct device *dev)
 {
@@ -568,102 +569,19 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
        return &window->table;
 }
 
-/* A coherent allocation implies strong ordering */
-
-static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
-                                     dma_addr_t *dma_handle, gfp_t flag,
-                                     unsigned long attrs)
-{
-       if (iommu_fixed_is_weak)
-               return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
-                                           size, dma_handle,
-                                           device_to_mask(dev), flag,
-                                           dev_to_node(dev));
-       else
-               return dma_nommu_ops.alloc(dev, size, dma_handle, flag,
-                                           attrs);
-}
-
-static void dma_fixed_free_coherent(struct device *dev, size_t size,
-                                   void *vaddr, dma_addr_t dma_handle,
-                                   unsigned long attrs)
-{
-       if (iommu_fixed_is_weak)
-               iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
-                                   dma_handle);
-       else
-               dma_nommu_ops.free(dev, size, vaddr, dma_handle, attrs);
-}
-
-static dma_addr_t dma_fixed_map_page(struct device *dev, struct page *page,
-                                    unsigned long offset, size_t size,
-                                    enum dma_data_direction direction,
-                                    unsigned long attrs)
-{
-       if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
-               return dma_nommu_ops.map_page(dev, page, offset, size,
-                                              direction, attrs);
-       else
-               return iommu_map_page(dev, cell_get_iommu_table(dev), page,
-                                     offset, size, device_to_mask(dev),
-                                     direction, attrs);
-}
-
-static void dma_fixed_unmap_page(struct device *dev, dma_addr_t dma_addr,
-                                size_t size, enum dma_data_direction direction,
-                                unsigned long attrs)
-{
-       if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
-               dma_nommu_ops.unmap_page(dev, dma_addr, size, direction,
-                                         attrs);
-       else
-               iommu_unmap_page(cell_get_iommu_table(dev), dma_addr, size,
-                                direction, attrs);
-}
-
-static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
-                          int nents, enum dma_data_direction direction,
-                          unsigned long attrs)
-{
-       if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
-               return dma_nommu_ops.map_sg(dev, sg, nents, direction, attrs);
-       else
-               return ppc_iommu_map_sg(dev, cell_get_iommu_table(dev), sg,
-                                       nents, device_to_mask(dev),
-                                       direction, attrs);
-}
-
-static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
-                              int nents, enum dma_data_direction direction,
-                              unsigned long attrs)
-{
-       if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
-               dma_nommu_ops.unmap_sg(dev, sg, nents, direction, attrs);
-       else
-               ppc_iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents,
-                                  direction, attrs);
-}
-
-static int dma_suported_and_switch(struct device *dev, u64 dma_mask);
-
-static const struct dma_map_ops dma_iommu_fixed_ops = {
-       .alloc          = dma_fixed_alloc_coherent,
-       .free           = dma_fixed_free_coherent,
-       .map_sg         = dma_fixed_map_sg,
-       .unmap_sg       = dma_fixed_unmap_sg,
-       .dma_supported  = dma_suported_and_switch,
-       .map_page       = dma_fixed_map_page,
-       .unmap_page     = dma_fixed_unmap_page,
-};
+static u64 cell_iommu_get_fixed_address(struct device *dev);
 
 static void cell_dma_dev_setup(struct device *dev)
 {
-       if (get_pci_dma_ops() == &dma_iommu_ops)
+       if (cell_iommu_enabled) {
+               u64 addr = cell_iommu_get_fixed_address(dev);
+
+               if (addr != OF_BAD_ADDR)
+                       dev->archdata.dma_offset = addr + dma_iommu_fixed_base;
                set_iommu_table_base(dev, cell_get_iommu_table(dev));
-       else if (get_pci_dma_ops() == &dma_nommu_ops)
-               set_dma_offset(dev, cell_dma_nommu_offset);
-       else
-               BUG();
+       } else {
+               dev->archdata.dma_offset = cell_dma_nommu_offset;
+       }
 }
 
 static void cell_pci_dma_dev_setup(struct pci_dev *dev)
@@ -680,11 +598,9 @@ static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action,
        if (action != BUS_NOTIFY_ADD_DEVICE)
                return 0;
 
-       /* We use the PCI DMA ops */
-       dev->dma_ops = get_pci_dma_ops();
-
+       if (cell_iommu_enabled)
+               dev->dma_ops = &dma_iommu_ops;
        cell_dma_dev_setup(dev);
-
        return 0;
 }
 
@@ -809,7 +725,6 @@ static int __init cell_iommu_init_disabled(void)
        unsigned long base = 0, size;
 
        /* When no iommu is present, we use direct DMA ops */
-       set_pci_dma_ops(&dma_nommu_ops);
 
        /* First make sure all IOC translation is turned off */
        cell_disable_iommus();
@@ -894,7 +809,11 @@ static u64 cell_iommu_get_fixed_address(struct device *dev)
        const u32 *ranges = NULL;
        int i, len, best, naddr, nsize, pna, range_size;
 
+       /* We can be called for platform devices that have no of_node */
        np = of_node_get(dev->of_node);
+       if (!np)
+               goto out;
+
        while (1) {
                naddr = of_n_addr_cells(np);
                nsize = of_n_size_cells(np);
@@ -945,27 +864,10 @@ out:
        return dev_addr;
 }
 
-static int dma_suported_and_switch(struct device *dev, u64 dma_mask)
+static bool cell_pci_iommu_bypass_supported(struct pci_dev *pdev, u64 mask)
 {
-       if (dma_mask == DMA_BIT_MASK(64) &&
-           cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR) {
-               u64 addr = cell_iommu_get_fixed_address(dev) +
-                       dma_iommu_fixed_base;
-               dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
-               dev_dbg(dev, "iommu: fixed addr = %llx\n", addr);
-               set_dma_ops(dev, &dma_iommu_fixed_ops);
-               set_dma_offset(dev, addr);
-               return 1;
-       }
-
-       if (dma_iommu_dma_supported(dev, dma_mask)) {
-               dev_dbg(dev, "iommu: not 64-bit, using default ops\n");
-               set_dma_ops(dev, get_pci_dma_ops());
-               cell_dma_dev_setup(dev);
-               return 1;
-       }
-
-       return 0;
+       return mask == DMA_BIT_MASK(64) &&
+               cell_iommu_get_fixed_address(&pdev->dev) != OF_BAD_ADDR;
 }
 
 static void insert_16M_pte(unsigned long addr, unsigned long *ptab,
@@ -1119,9 +1021,8 @@ static int __init cell_iommu_fixed_mapping_init(void)
                cell_iommu_setup_window(iommu, np, dbase, dsize, 0);
        }
 
-       dma_iommu_ops.dma_supported = dma_suported_and_switch;
-       set_pci_dma_ops(&dma_iommu_ops);
-
+       cell_pci_controller_ops.iommu_bypass_supported =
+               cell_pci_iommu_bypass_supported;
        return 0;
 }
 
@@ -1142,7 +1043,7 @@ static int __init setup_iommu_fixed(char *str)
        pciep = of_find_node_by_type(NULL, "pcie-endpoint");
 
        if (strcmp(str, "weak") == 0 || (pciep && strcmp(str, "strong") != 0))
-               iommu_fixed_is_weak = DMA_ATTR_WEAK_ORDERING;
+               iommu_fixed_is_weak = true;
 
        of_node_put(pciep);
 
@@ -1150,26 +1051,6 @@ static int __init setup_iommu_fixed(char *str)
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
 
-static u64 cell_dma_get_required_mask(struct device *dev)
-{
-       const struct dma_map_ops *dma_ops;
-
-       if (!dev->dma_mask)
-               return 0;
-
-       if (!iommu_fixed_disabled &&
-                       cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR)
-               return DMA_BIT_MASK(64);
-
-       dma_ops = get_dma_ops(dev);
-       if (dma_ops->get_required_mask)
-               return dma_ops->get_required_mask(dev);
-
-       WARN_ONCE(1, "no get_required_mask in %p ops", dma_ops);
-
-       return DMA_BIT_MASK(64);
-}
-
 static int __init cell_iommu_init(void)
 {
        struct device_node *np;
@@ -1186,10 +1067,9 @@ static int __init cell_iommu_init(void)
 
        /* Setup various callbacks */
        cell_pci_controller_ops.dma_dev_setup = cell_pci_dma_dev_setup;
-       ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
 
        if (!iommu_fixed_disabled && cell_iommu_fixed_mapping_init() == 0)
-               goto bail;
+               goto done;
 
        /* Create an iommu for each /axon node.  */
        for_each_node_by_name(np, "axon") {
@@ -1206,10 +1086,10 @@ static int __init cell_iommu_init(void)
                        continue;
                cell_iommu_init_one(np, SPIDER_DMA_OFFSET);
        }
-
+ done:
        /* Setup default PCI iommu ops */
        set_pci_dma_ops(&dma_iommu_ops);
-
+       cell_iommu_enabled = true;
  bail:
        /* Register callbacks on OF platform device addition/removal
         * to handle linking them to the right DMA operations
index 263413a3482300e0116d8c68f49298408725ba56..b95d6afc39b579eae115718ea3dab4413f5b2544 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/syscalls.h>
 #include <linux/rcupdate.h>
 #include <linux/binfmts.h>
-#include <linux/syscalls.h>
 
 #include <asm/spu.h>
 
index ae8123edddc670ed2b413129ee8a97aade121200..48c2477e7e2a2c462bafc022a6ad53ade37cdde3 100644 (file)
@@ -2338,9 +2338,8 @@ static int spufs_switch_log_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       ctx->switch_log = kmalloc(sizeof(struct switch_log) +
-               SWITCH_LOG_BUFSIZE * sizeof(struct switch_log_entry),
-               GFP_KERNEL);
+       ctx->switch_log = kmalloc(struct_size(ctx->switch_log, log,
+                                 SWITCH_LOG_BUFSIZE), GFP_KERNEL);
 
        if (!ctx->switch_log) {
                rc = -ENOMEM;
index f2971522fb4aa842cb9128b5c7ccc46c6e8d47a5..bbeb6a1b03938fa73fc03096307aa2bef89f9bd1 100644 (file)
@@ -186,7 +186,7 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev)
         */
        if (dev->vendor == 0x1959 && dev->device == 0xa007 &&
            !firmware_has_feature(FW_FEATURE_LPAR)) {
-               dev->dev.dma_ops = &dma_nommu_ops;
+               dev->dev.dma_ops = NULL;
                /*
                 * Set the coherent DMA mask to prevent the iommu
                 * being used unnecessarily
index c0532999f8540806b695f730d3583b1e2c45bf46..46dd463faaa78ad2c7c4d498eca3a864dfa43b95 100644 (file)
@@ -411,55 +411,6 @@ out:
        return !!(srr1 & 0x2);
 }
 
-#ifdef CONFIG_PCMCIA
-static int pcmcia_notify(struct notifier_block *nb, unsigned long action,
-                        void *data)
-{
-       struct device *dev = data;
-       struct device *parent;
-       struct pcmcia_device *pdev = to_pcmcia_dev(dev);
-
-       /* We are only intereted in device addition */
-       if (action != BUS_NOTIFY_ADD_DEVICE)
-               return 0;
-
-       parent = pdev->socket->dev.parent;
-
-       /* We know electra_cf devices will always have of_node set, since
-        * electra_cf is an of_platform driver.
-        */
-       if (!parent->of_node)
-               return 0;
-
-       if (!of_device_is_compatible(parent->of_node, "electra-cf"))
-               return 0;
-
-       /* We use the direct ops for localbus */
-       dev->dma_ops = &dma_nommu_ops;
-
-       return 0;
-}
-
-static struct notifier_block pcmcia_notifier = {
-       .notifier_call = pcmcia_notify,
-};
-
-static inline void pasemi_pcmcia_init(void)
-{
-       extern struct bus_type pcmcia_bus_type;
-
-       bus_register_notifier(&pcmcia_bus_type, &pcmcia_notifier);
-}
-
-#else
-
-static inline void pasemi_pcmcia_init(void)
-{
-}
-
-#endif
-
-
 static const struct of_device_id pasemi_bus_ids[] = {
        /* Unfortunately needed for legacy firmwares */
        { .type = "localbus", },
@@ -472,8 +423,6 @@ static const struct of_device_id pasemi_bus_ids[] = {
 
 static int __init pasemi_publish_devices(void)
 {
-       pasemi_pcmcia_init();
-
        /* Publish OF platform devices for SDC and other non-PCI devices */
        of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
 
index d7f742ed48ba4bb3b002f23daf2ffa576f055dfb..ccf186bb60ec4d27cedc52fc46bcff92459f662f 100644 (file)
  */
 static DEFINE_SPINLOCK(npu_context_lock);
 
-/*
- * Other types of TCE cache invalidation are not functional in the
- * hardware.
- */
 static struct pci_dev *get_pci_dev(struct device_node *dn)
 {
        struct pci_dn *pdn = PCI_DN(dn);
@@ -220,7 +216,7 @@ static void pnv_npu_dma_set_32(struct pnv_ioda_pe *npe)
         * their parent device so drivers shouldn't be doing DMA
         * operations directly on these devices.
         */
-       set_dma_ops(&npe->pdev->dev, NULL);
+       set_dma_ops(&npe->pdev->dev, &dma_dummy_ops);
 }
 
 /*
@@ -564,7 +560,7 @@ struct iommu_table_group *pnv_try_setup_npu_table_group(struct pnv_ioda_pe *pe)
                }
        } else {
                /* Create a group for 1 GPU and attached NPUs for POWER8 */
-               pe->npucomp = kzalloc(sizeof(pe->npucomp), GFP_KERNEL);
+               pe->npucomp = kzalloc(sizeof(*pe->npucomp), GFP_KERNEL);
                table_group = &pe->npucomp->table_group;
                table_group->ops = &pnv_npu_peers_ops;
                iommu_register_group(table_group, hose->global_number,
index 05c85be0370f95b147db897665dc6c633e0e8eb5..2ca3ba95f8aaf1e4e50ddf8518edea390ed7b757 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/memblock.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <linux/printk.h>
 #include <linux/kmsg_dump.h>
 #include <linux/console.h>
 #include <linux/sched/debug.h>
index 1d6406a051f1216782094ee5bfcf9a662de9e0f1..e9986c9f779d1465dcb60afc09c5346a395635c7 100644 (file)
@@ -1746,7 +1746,7 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
 
        pe = &phb->ioda.pe_array[pdn->pe_number];
        WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops);
-       set_dma_offset(&pdev->dev, pe->tce_bypass_base);
+       pdev->dev.archdata.dma_offset = pe->tce_bypass_base;
        set_iommu_table_base(&pdev->dev, pe->table_group.tables[0]);
        /*
         * Note: iommu_add_device() will fail here as
@@ -1756,31 +1756,6 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
         */
 }
 
-static bool pnv_pci_ioda_pe_single_vendor(struct pnv_ioda_pe *pe)
-{
-       unsigned short vendor = 0;
-       struct pci_dev *pdev;
-
-       if (pe->device_count == 1)
-               return true;
-
-       /* pe->pdev should be set if it's a single device, pe->pbus if not */
-       if (!pe->pbus)
-               return true;
-
-       list_for_each_entry(pdev, &pe->pbus->devices, bus_list) {
-               if (!vendor) {
-                       vendor = pdev->vendor;
-                       continue;
-               }
-
-               if (pdev->vendor != vendor)
-                       return false;
-       }
-
-       return true;
-}
-
 /*
  * Reconfigure TVE#0 to be usable as 64-bit DMA space.
  *
@@ -1850,88 +1825,45 @@ err:
        return -EIO;
 }
 
-static int pnv_pci_ioda_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
+static bool pnv_pci_ioda_iommu_bypass_supported(struct pci_dev *pdev,
+               u64 dma_mask)
 {
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        struct pnv_phb *phb = hose->private_data;
        struct pci_dn *pdn = pci_get_pdn(pdev);
        struct pnv_ioda_pe *pe;
-       uint64_t top;
-       bool bypass = false;
-       s64 rc;
 
        if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
                return -ENODEV;
 
        pe = &phb->ioda.pe_array[pdn->pe_number];
        if (pe->tce_bypass_enabled) {
-               top = pe->tce_bypass_base + memblock_end_of_DRAM() - 1;
-               bypass = (dma_mask >= top);
+               u64 top = pe->tce_bypass_base + memblock_end_of_DRAM() - 1;
+               if (dma_mask >= top)
+                       return true;
        }
 
-       if (bypass) {
-               dev_info(&pdev->dev, "Using 64-bit DMA iommu bypass\n");
-               set_dma_ops(&pdev->dev, &dma_nommu_ops);
-       } else {
-               /*
-                * If the device can't set the TCE bypass bit but still wants
-                * to access 4GB or more, on PHB3 we can reconfigure TVE#0 to
-                * bypass the 32-bit region and be usable for 64-bit DMAs.
-                * The device needs to be able to address all of this space.
-                */
-               if (dma_mask >> 32 &&
-                   dma_mask > (memory_hotplug_max() + (1ULL << 32)) &&
-                   pnv_pci_ioda_pe_single_vendor(pe) &&
-                   phb->model == PNV_PHB_MODEL_PHB3) {
-                       /* Configure the bypass mode */
-                       rc = pnv_pci_ioda_dma_64bit_bypass(pe);
-                       if (rc)
-                               return rc;
-                       /* 4GB offset bypasses 32-bit space */
-                       set_dma_offset(&pdev->dev, (1ULL << 32));
-                       set_dma_ops(&pdev->dev, &dma_nommu_ops);
-               } else if (dma_mask >> 32 && dma_mask != DMA_BIT_MASK(64)) {
-                       /*
-                        * Fail the request if a DMA mask between 32 and 64 bits
-                        * was requested but couldn't be fulfilled. Ideally we
-                        * would do this for 64-bits but historically we have
-                        * always fallen back to 32-bits.
-                        */
-                       return -ENOMEM;
-               } else {
-                       dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n");
-                       set_dma_ops(&pdev->dev, &dma_iommu_ops);
-               }
+       /*
+        * If the device can't set the TCE bypass bit but still wants
+        * to access 4GB or more, on PHB3 we can reconfigure TVE#0 to
+        * bypass the 32-bit region and be usable for 64-bit DMAs.
+        * The device needs to be able to address all of this space.
+        */
+       if (dma_mask >> 32 &&
+           dma_mask > (memory_hotplug_max() + (1ULL << 32)) &&
+           /* pe->pdev should be set if it's a single device, pe->pbus if not */
+           (pe->device_count == 1 || !pe->pbus) &&
+           phb->model == PNV_PHB_MODEL_PHB3) {
+               /* Configure the bypass mode */
+               s64 rc = pnv_pci_ioda_dma_64bit_bypass(pe);
+               if (rc)
+                       return rc;
+               /* 4GB offset bypasses 32-bit space */
+               pdev->dev.archdata.dma_offset = (1ULL << 32);
+               return true;
        }
-       *pdev->dev.dma_mask = dma_mask;
-
-       /* Update peer npu devices */
-       pnv_npu_try_dma_set_bypass(pdev, bypass);
-
-       return 0;
-}
-
-static u64 pnv_pci_ioda_dma_get_required_mask(struct pci_dev *pdev)
-{
-       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-       struct pnv_phb *phb = hose->private_data;
-       struct pci_dn *pdn = pci_get_pdn(pdev);
-       struct pnv_ioda_pe *pe;
-       u64 end, mask;
-
-       if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
-               return 0;
-
-       pe = &phb->ioda.pe_array[pdn->pe_number];
-       if (!pe->tce_bypass_enabled)
-               return __dma_get_required_mask(&pdev->dev);
-
 
-       end = pe->tce_bypass_base + memblock_end_of_DRAM();
-       mask = 1ULL << (fls64(end) - 1);
-       mask += mask - 1;
-
-       return mask;
+       return false;
 }
 
 static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
@@ -1940,7 +1872,7 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                set_iommu_table_base(&dev->dev, pe->table_group.tables[0]);
-               set_dma_offset(&dev->dev, pe->tce_bypass_base);
+               dev->dev.archdata.dma_offset = pe->tce_bypass_base;
 
                if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
                        pnv_ioda_setup_bus_dma(pe, dev->subordinate);
@@ -2681,7 +2613,8 @@ static void pnv_pci_ioda_setup_iommu_api(void)
        list_for_each_entry(hose, &hose_list, list_node) {
                phb = hose->private_data;
 
-               if (phb->type == PNV_PHB_NPU_NVLINK)
+               if (phb->type == PNV_PHB_NPU_NVLINK ||
+                   phb->type == PNV_PHB_NPU_OCAPI)
                        continue;
 
                list_for_each_entry(pe, &phb->ioda.pe_list, list) {
@@ -3658,6 +3591,7 @@ static void pnv_pci_ioda_shutdown(struct pci_controller *hose)
 static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
        .dma_dev_setup          = pnv_pci_dma_dev_setup,
        .dma_bus_setup          = pnv_pci_dma_bus_setup,
+       .iommu_bypass_supported = pnv_pci_ioda_iommu_bypass_supported,
        .setup_msi_irqs         = pnv_setup_msi_irqs,
        .teardown_msi_irqs      = pnv_teardown_msi_irqs,
        .enable_device_hook     = pnv_pci_enable_device_hook,
@@ -3665,19 +3599,9 @@ static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
        .window_alignment       = pnv_pci_window_alignment,
        .setup_bridge           = pnv_pci_setup_bridge,
        .reset_secondary_bus    = pnv_pci_reset_secondary_bus,
-       .dma_set_mask           = pnv_pci_ioda_dma_set_mask,
-       .dma_get_required_mask  = pnv_pci_ioda_dma_get_required_mask,
        .shutdown               = pnv_pci_ioda_shutdown,
 };
 
-static int pnv_npu_dma_set_mask(struct pci_dev *npdev, u64 dma_mask)
-{
-       dev_err_once(&npdev->dev,
-                       "%s operation unsupported for NVLink devices\n",
-                       __func__);
-       return -EPERM;
-}
-
 static const struct pci_controller_ops pnv_npu_ioda_controller_ops = {
        .dma_dev_setup          = pnv_pci_dma_dev_setup,
        .setup_msi_irqs         = pnv_setup_msi_irqs,
@@ -3685,7 +3609,6 @@ static const struct pci_controller_ops pnv_npu_ioda_controller_ops = {
        .enable_device_hook     = pnv_pci_enable_device_hook,
        .window_alignment       = pnv_pci_window_alignment,
        .reset_secondary_bus    = pnv_pci_reset_secondary_bus,
-       .dma_set_mask           = pnv_npu_dma_set_mask,
        .shutdown               = pnv_pci_ioda_shutdown,
        .disable_device         = pnv_npu_disable_device,
 };
@@ -3943,9 +3866,12 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
         * shutdown PCI devices correctly. We already got IODA table
         * cleaned out. So we have to issue PHB reset to stop all PCI
         * transactions from previous kernel. The ppc_pci_reset_phbs
-        * kernel parameter will force this reset too.
+        * kernel parameter will force this reset too. Additionally,
+        * if the IODA reset above failed then use a bigger hammer.
+        * This can happen if we get a PHB fatal error in very early
+        * boot.
         */
-       if (is_kdump_kernel() || pci_reset_phbs) {
+       if (is_kdump_kernel() || pci_reset_phbs || rc) {
                pr_info("  Issue PHB reset ...\n");
                pnv_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
                pnv_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE);
index e7075aaff1bb62094f8d8f1df706c7d5157496e3..59587b75493db977142b33502cf02a58218a1009 100644 (file)
@@ -354,9 +354,7 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
                 repo->dev_index, repo->dev_type, port, blk_size, num_blocks,
                 num_regions);
 
-       p = kzalloc(sizeof(struct ps3_storage_device) +
-                   num_regions * sizeof(struct ps3_storage_region),
-                   GFP_KERNEL);
+       p = kzalloc(struct_size(p, regions, num_regions), GFP_KERNEL);
        if (!p) {
                result = -ENOMEM;
                goto fail_malloc;
index f5387ad822798125402d76a530a6d7cc2c1733f5..4d65c538002063045950ed03a2fb3c20e572edd4 100644 (file)
@@ -205,11 +205,11 @@ static const struct os_area_db_id os_area_db_id_rtc_diff = {
  *  3) The number of seconds from 1970 to 2000.
  */
 
-struct saved_params {
+static struct saved_params {
        unsigned int valid;
        s64 rtc_diff;
        unsigned int av_multi_out;
-} static saved_params;
+} saved_params;
 
 static struct property property_rtc_diff = {
        .name = "linux,rtc_diff",
index 5cc35d6b94b6c8627527d2232ebf879f73b8e0d6..7c227e784247c0df26da431e512a685ca1cc9ecf 100644 (file)
@@ -37,12 +37,12 @@ static struct device ps3_system_bus = {
 };
 
 /* FIXME: need device usage counters! */
-struct {
+static struct {
        struct mutex mutex;
        int sb_11; /* usb 0 */
        int sb_12; /* usb 0 */
        int gpu;
-} static usage_hack;
+} usage_hack;
 
 static int ps3_is_device(struct ps3_system_bus_device *dev, u64 bus_id,
                         u64 dev_id)
index 2f8e62163602bbaa125a7b1f03d06bce9cee05e6..97feb6e79f1a707f9002371d9d4e98bb95589f07 100644 (file)
@@ -802,6 +802,25 @@ static int dlpar_cpu_add_by_count(u32 cpus_to_add)
        return rc;
 }
 
+int dlpar_cpu_readd(int cpu)
+{
+       struct device_node *dn;
+       struct device *dev;
+       u32 drc_index;
+       int rc;
+
+       dev = get_cpu_device(cpu);
+       dn = dev->of_node;
+
+       rc = of_property_read_u32(dn, "ibm,my-drc-index", &drc_index);
+
+       rc = dlpar_cpu_remove_by_index(drc_index);
+       if (!rc)
+               rc = dlpar_cpu_add(drc_index);
+
+       return rc;
+}
+
 int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
 {
        u32 count, drc_index;
index 8fc8fe0b9848536e0ee3334bc9f81efa27848695..36eb1ddbac69546355c0d7b7ebb04709cb4f0f45 100644 (file)
@@ -978,7 +978,7 @@ static phys_addr_t ddw_memory_hotplug_max(void)
  * pdn: the parent pe node with the ibm,dma_window property
  * Future: also check if we can remap the base window for our base page size
  *
- * returns the dma offset for use by dma_set_mask
+ * returns the dma offset for use by the direct mapped DMA code.
  */
 static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
 {
@@ -1198,87 +1198,37 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
        iommu_add_device(pci->table_group, &dev->dev);
 }
 
-static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
+static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
 {
-       bool ddw_enabled = false;
-       struct device_node *pdn, *dn;
-       struct pci_dev *pdev;
+       struct device_node *dn = pci_device_to_OF_node(pdev), *pdn;
        const __be32 *dma_window = NULL;
-       u64 dma_offset;
-
-       if (!dev->dma_mask)
-               return -EIO;
-
-       if (!dev_is_pci(dev))
-               goto check_mask;
-
-       pdev = to_pci_dev(dev);
 
        /* only attempt to use a new window if 64-bit DMA is requested */
-       if (!disable_ddw && dma_mask == DMA_BIT_MASK(64)) {
-               dn = pci_device_to_OF_node(pdev);
-               dev_dbg(dev, "node is %pOF\n", dn);
+       if (dma_mask < DMA_BIT_MASK(64))
+               return false;
 
-               /*
-                * the device tree might contain the dma-window properties
-                * per-device and not necessarily for the bus. So we need to
-                * search upwards in the tree until we either hit a dma-window
-                * property, OR find a parent with a table already allocated.
-                */
-               for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->table_group;
-                               pdn = pdn->parent) {
-                       dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
-                       if (dma_window)
-                               break;
-               }
-               if (pdn && PCI_DN(pdn)) {
-                       dma_offset = enable_ddw(pdev, pdn);
-                       if (dma_offset != 0) {
-                               dev_info(dev, "Using 64-bit direct DMA at offset %llx\n", dma_offset);
-                               set_dma_offset(dev, dma_offset);
-                               set_dma_ops(dev, &dma_nommu_ops);
-                               ddw_enabled = true;
-                       }
-               }
-       }
+       dev_dbg(&pdev->dev, "node is %pOF\n", dn);
 
-       /* fall back on iommu ops */
-       if (!ddw_enabled && get_dma_ops(dev) != &dma_iommu_ops) {
-               dev_info(dev, "Restoring 32-bit DMA via iommu\n");
-               set_dma_ops(dev, &dma_iommu_ops);
+       /*
+        * the device tree might contain the dma-window properties
+        * per-device and not necessarily for the bus. So we need to
+        * search upwards in the tree until we either hit a dma-window
+        * property, OR find a parent with a table already allocated.
+        */
+       for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->table_group;
+                       pdn = pdn->parent) {
+               dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
+               if (dma_window)
+                       break;
        }
 
-check_mask:
-       if (!dma_supported(dev, dma_mask))
-               return -EIO;
-
-       *dev->dma_mask = dma_mask;
-       return 0;
-}
-
-static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
-{
-       if (!dev->dma_mask)
-               return 0;
-
-       if (!disable_ddw && dev_is_pci(dev)) {
-               struct pci_dev *pdev = to_pci_dev(dev);
-               struct device_node *dn;
-
-               dn = pci_device_to_OF_node(pdev);
-
-               /* search upwards for ibm,dma-window */
-               for (; dn && PCI_DN(dn) && !PCI_DN(dn)->table_group;
-                               dn = dn->parent)
-                       if (of_get_property(dn, "ibm,dma-window", NULL))
-                               break;
-               /* if there is a ibm,ddw-applicable property require 64 bits */
-               if (dn && PCI_DN(dn) &&
-                               of_get_property(dn, "ibm,ddw-applicable", NULL))
-                       return DMA_BIT_MASK(64);
+       if (pdn && PCI_DN(pdn)) {
+               pdev->dev.archdata.dma_offset = enable_ddw(pdev, pdn);
+               if (pdev->dev.archdata.dma_offset)
+                       return true;
        }
 
-       return dma_iommu_ops.get_required_mask(dev);
+       return false;
 }
 
 static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1373,8 +1323,9 @@ void iommu_init_early_pSeries(void)
        if (firmware_has_feature(FW_FEATURE_LPAR)) {
                pseries_pci_controller_ops.dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
                pseries_pci_controller_ops.dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
-               ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
-               ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
+               if (!disable_ddw)
+                       pseries_pci_controller_ops.iommu_bypass_supported =
+                               iommu_bypass_supported_pSeriesLP;
        } else {
                pseries_pci_controller_ops.dma_bus_setup = pci_dma_bus_setup_pSeries;
                pseries_pci_controller_ops.dma_dev_setup = pci_dma_dev_setup_pSeries;
index 7d6457ab5d3450f0db4d6cc25e2067c80db59f13..bba281b1fe1b0730f8a0d31fc469f324118a8933 100644 (file)
@@ -43,6 +43,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
 {
        unsigned long ret[PLPAR_HCALL_BUFSIZE];
        uint64_t rc, token;
+       uint64_t saved = 0;
 
        /*
         * When the hypervisor cannot map all the requested memory in a single
@@ -56,6 +57,8 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0,
                                p->blocks, BIND_ANY_ADDR, token);
                token = ret[0];
+               if (!saved)
+                       saved = ret[1];
                cond_resched();
        } while (rc == H_BUSY);
 
@@ -64,7 +67,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                return -ENXIO;
        }
 
-       p->bound_addr = ret[1];
+       p->bound_addr = saved;
 
        dev_dbg(&p->pdev->dev, "bound drc %x to %pR\n", p->drc_index, &p->res);
 
index 7725825d887d32903a699fdc2e26134f9b101100..37a77e57893eda7cda4dd58ceefcb837d71bc978 100644 (file)
@@ -264,7 +264,9 @@ void __init pSeries_final_fixup(void)
                        if (!of_device_is_compatible(nvdn->parent,
                                                "ibm,power9-npu"))
                                continue;
+#ifdef CONFIG_PPC_POWERNV
                        WARN_ON_ONCE(pnv_npu2_init(hose));
+#endif
                        break;
                }
        }
index 1fad4649735bde3b1a7480e90c935b00e41c9f5a..141795275ccb19bf66da2dc9bcff88684d135df5 100644 (file)
@@ -492,7 +492,9 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
                return NULL;
        }
 
-       ret = dma_iommu_ops.alloc(dev, size, dma_handle, flag, attrs);
+       ret = iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
+                                   dma_handle, dev->coherent_dma_mask, flag,
+                                   dev_to_node(dev));
        if (unlikely(ret == NULL)) {
                vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
                atomic_inc(&viodev->cmo.allocs_failed);
@@ -507,8 +509,7 @@ static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
 {
        struct vio_dev *viodev = to_vio_dev(dev);
 
-       dma_iommu_ops.free(dev, size, vaddr, dma_handle, attrs);
-
+       iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle);
        vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
 }
 
@@ -518,22 +519,22 @@ static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
                                          unsigned long attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
-       struct iommu_table *tbl;
+       struct iommu_table *tbl = get_iommu_table_base(dev);
        dma_addr_t ret = DMA_MAPPING_ERROR;
 
-       tbl = get_iommu_table_base(dev);
-       if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)))) {
-               atomic_inc(&viodev->cmo.allocs_failed);
-               return ret;
-       }
-
-       ret = dma_iommu_ops.map_page(dev, page, offset, size, direction, attrs);
-       if (unlikely(dma_mapping_error(dev, ret))) {
-               vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
-               atomic_inc(&viodev->cmo.allocs_failed);
-       }
-
+       if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl))))
+               goto out_fail;
+       ret = iommu_map_page(dev, tbl, page, offset, size, device_to_mask(dev),
+                       direction, attrs);
+       if (unlikely(ret == DMA_MAPPING_ERROR))
+               goto out_deallocate;
        return ret;
+
+out_deallocate:
+       vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
+out_fail:
+       atomic_inc(&viodev->cmo.allocs_failed);
+       return DMA_MAPPING_ERROR;
 }
 
 static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
@@ -542,11 +543,9 @@ static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
                                     unsigned long attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
-       struct iommu_table *tbl;
-
-       tbl = get_iommu_table_base(dev);
-       dma_iommu_ops.unmap_page(dev, dma_handle, size, direction, attrs);
+       struct iommu_table *tbl = get_iommu_table_base(dev);
 
+       iommu_unmap_page(tbl, dma_handle, size, direction, attrs);
        vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
 }
 
@@ -555,34 +554,32 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
                                 unsigned long attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
-       struct iommu_table *tbl;
+       struct iommu_table *tbl = get_iommu_table_base(dev);
        struct scatterlist *sgl;
        int ret, count;
        size_t alloc_size = 0;
 
-       tbl = get_iommu_table_base(dev);
        for_each_sg(sglist, sgl, nelems, count)
                alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE(tbl));
 
-       if (vio_cmo_alloc(viodev, alloc_size)) {
-               atomic_inc(&viodev->cmo.allocs_failed);
-               return 0;
-       }
-
-       ret = dma_iommu_ops.map_sg(dev, sglist, nelems, direction, attrs);
-
-       if (unlikely(!ret)) {
-               vio_cmo_dealloc(viodev, alloc_size);
-               atomic_inc(&viodev->cmo.allocs_failed);
-               return ret;
-       }
+       if (vio_cmo_alloc(viodev, alloc_size))
+               goto out_fail;
+       ret = ppc_iommu_map_sg(dev, tbl, sglist, nelems, device_to_mask(dev),
+                       direction, attrs);
+       if (unlikely(!ret))
+               goto out_deallocate;
 
        for_each_sg(sglist, sgl, ret, count)
                alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
        if (alloc_size)
                vio_cmo_dealloc(viodev, alloc_size);
-
        return ret;
+
+out_deallocate:
+       vio_cmo_dealloc(viodev, alloc_size);
+out_fail:
+       atomic_inc(&viodev->cmo.allocs_failed);
+       return 0;
 }
 
 static void vio_dma_iommu_unmap_sg(struct device *dev,
@@ -591,40 +588,27 @@ static void vio_dma_iommu_unmap_sg(struct device *dev,
                unsigned long attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
-       struct iommu_table *tbl;
+       struct iommu_table *tbl = get_iommu_table_base(dev);
        struct scatterlist *sgl;
        size_t alloc_size = 0;
        int count;
 
-       tbl = get_iommu_table_base(dev);
        for_each_sg(sglist, sgl, nelems, count)
                alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
 
-       dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs);
-
+       ppc_iommu_unmap_sg(tbl, sglist, nelems, direction, attrs);
        vio_cmo_dealloc(viodev, alloc_size);
 }
 
-static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
-{
-        return dma_iommu_ops.dma_supported(dev, mask);
-}
-
-static u64 vio_dma_get_required_mask(struct device *dev)
-{
-        return dma_iommu_ops.get_required_mask(dev);
-}
-
 static const struct dma_map_ops vio_dma_mapping_ops = {
        .alloc             = vio_dma_iommu_alloc_coherent,
        .free              = vio_dma_iommu_free_coherent,
-       .mmap              = dma_nommu_mmap_coherent,
        .map_sg            = vio_dma_iommu_map_sg,
        .unmap_sg          = vio_dma_iommu_unmap_sg,
        .map_page          = vio_dma_iommu_map_page,
        .unmap_page        = vio_dma_iommu_unmap_page,
-       .dma_supported     = vio_dma_iommu_dma_supported,
-       .get_required_mask = vio_dma_get_required_mask,
+       .dma_supported     = dma_iommu_dma_supported,
+       .get_required_mask = dma_iommu_get_required_mask,
 };
 
 /**
@@ -1715,3 +1699,10 @@ int vio_disable_interrupts(struct vio_dev *dev)
 }
 EXPORT_SYMBOL(vio_disable_interrupts);
 #endif /* CONFIG_PPC_PSERIES */
+
+static int __init vio_init(void)
+{
+       dma_debug_add_bus(&vio_bus_type);
+       return 0;
+}
+fs_initcall(vio_init);
index a5b40d1460f1a007df88ff75e63356778d76345d..809797dbe16908869f4de34b1b899e55da9a248b 100644 (file)
@@ -360,13 +360,6 @@ static void iommu_table_dart_setup(void)
        set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
 }
 
-static void pci_dma_dev_setup_dart(struct pci_dev *dev)
-{
-       if (dart_is_u4)
-               set_dma_offset(&dev->dev, DART_U4_BYPASS_BASE);
-       set_iommu_table_base(&dev->dev, &iommu_table_dart);
-}
-
 static void pci_dma_bus_setup_dart(struct pci_bus *bus)
 {
        if (!iommu_table_dart_inited) {
@@ -390,27 +383,18 @@ static bool dart_device_on_pcie(struct device *dev)
        return false;
 }
 
-static int dart_dma_set_mask(struct device *dev, u64 dma_mask)
+static void pci_dma_dev_setup_dart(struct pci_dev *dev)
 {
-       if (!dev->dma_mask || !dma_supported(dev, dma_mask))
-               return -EIO;
-
-       /* U4 supports a DART bypass, we use it for 64-bit capable
-        * devices to improve performances. However, that only works
-        * for devices connected to U4 own PCIe interface, not bridged
-        * through hypertransport. We need the device to support at
-        * least 40 bits of addresses.
-        */
-       if (dart_device_on_pcie(dev) && dma_mask >= DMA_BIT_MASK(40)) {
-               dev_info(dev, "Using 64-bit DMA iommu bypass\n");
-               set_dma_ops(dev, &dma_nommu_ops);
-       } else {
-               dev_info(dev, "Using 32-bit DMA via iommu\n");
-               set_dma_ops(dev, &dma_iommu_ops);
-       }
+       if (dart_is_u4 && dart_device_on_pcie(&dev->dev))
+               dev->dev.archdata.dma_offset = DART_U4_BYPASS_BASE;
+       set_iommu_table_base(&dev->dev, &iommu_table_dart);
+}
 
-       *dev->dma_mask = dma_mask;
-       return 0;
+static bool iommu_bypass_supported_dart(struct pci_dev *dev, u64 mask)
+{
+       return dart_is_u4 &&
+               dart_device_on_pcie(&dev->dev) &&
+               mask >= DMA_BIT_MASK(40);
 }
 
 void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops)
@@ -428,26 +412,20 @@ void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops)
 
        /* Initialize the DART HW */
        if (dart_init(dn) != 0)
-               goto bail;
-
-       /* Setup bypass if supported */
-       if (dart_is_u4)
-               ppc_md.dma_set_mask = dart_dma_set_mask;
+               return;
 
+       /*
+        * U4 supports a DART bypass, we use it for 64-bit capable devices to
+        * improve performance.  However, that only works for devices connected
+        * to the U4 own PCIe interface, not bridged through hypertransport.
+        * We need the device to support at least 40 bits of addresses.
+        */
        controller_ops->dma_dev_setup = pci_dma_dev_setup_dart;
        controller_ops->dma_bus_setup = pci_dma_bus_setup_dart;
+       controller_ops->iommu_bypass_supported = iommu_bypass_supported_dart;
 
        /* Setup pci_dma ops */
        set_pci_dma_ops(&dma_iommu_ops);
-       return;
-
- bail:
-       /* If init failed, use direct iommu and null setup functions */
-       controller_ops->dma_dev_setup = NULL;
-       controller_ops->dma_bus_setup = NULL;
-
-       /* Setup pci_dma ops */
-       set_pci_dma_ops(&dma_nommu_ops);
 }
 
 #ifdef CONFIG_PM
index 918be816b0977c5feba2a9ef79b57111de1901c3..f49aec251a5a0e7753dfa395f76f1e83b3797047 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/mpc85xx.h>
 #include <asm/disassemble.h>
 #include <asm/ppc-opcode.h>
+#include <asm/swiotlb.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 
@@ -114,33 +115,33 @@ static struct pci_ops fsl_indirect_pcie_ops =
 static u64 pci64_dma_offset;
 
 #ifdef CONFIG_SWIOTLB
+static void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+       pdev->dev.bus_dma_mask =
+               hose->dma_window_base_cur + hose->dma_window_size;
+}
+
 static void setup_swiotlb_ops(struct pci_controller *hose)
 {
-       if (ppc_swiotlb_enable) {
+       if (ppc_swiotlb_enable)
                hose->controller_ops.dma_dev_setup = pci_dma_dev_setup_swiotlb;
-               set_pci_dma_ops(&powerpc_swiotlb_dma_ops);
-       }
 }
 #else
 static inline void setup_swiotlb_ops(struct pci_controller *hose) {}
 #endif
 
-static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
+static void fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
 {
-       if (!dev->dma_mask || !dma_supported(dev, dma_mask))
-               return -EIO;
-
        /*
         * Fix up PCI devices that are able to DMA to the large inbound
         * mapping that allows addressing any RAM address from across PCI.
         */
        if (dev_is_pci(dev) && dma_mask >= pci64_dma_offset * 2 - 1) {
-               set_dma_ops(dev, &dma_nommu_ops);
-               set_dma_offset(dev, pci64_dma_offset);
+               dev->bus_dma_mask = 0;
+               dev->archdata.dma_offset = pci64_dma_offset;
        }
-
-       *dev->dma_mask = dma_mask;
-       return 0;
 }
 
 static int setup_one_atmu(struct ccsr_pci __iomem *pci,
index 8030a0f55e966bd5d1dab67eb12e268fc5963e7e..fd129c8ecceb85d27911806a7f560eb7d22ab155 100644 (file)
@@ -771,21 +771,6 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
        return ipic;
 }
 
-void ipic_set_highest_priority(unsigned int virq)
-{
-       struct ipic *ipic = ipic_from_irq(virq);
-       unsigned int src = virq_to_hw(virq);
-       u32 temp;
-
-       temp = ipic_read(ipic->regs, IPIC_SICFR);
-
-       /* clear and set HPI */
-       temp &= 0x7f000000;
-       temp |= (src & 0x7f) << 24;
-
-       ipic_write(ipic->regs, IPIC_SICFR, temp);
-}
-
 void ipic_set_default_priority(void)
 {
        ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
@@ -796,26 +781,6 @@ void ipic_set_default_priority(void)
        ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
 }
 
-void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
-{
-       struct ipic *ipic = primary_ipic;
-       u32 temp;
-
-       temp = ipic_read(ipic->regs, IPIC_SERMR);
-       temp |= (1 << (31 - mcp_irq));
-       ipic_write(ipic->regs, IPIC_SERMR, temp);
-}
-
-void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
-{
-       struct ipic *ipic = primary_ipic;
-       u32 temp;
-
-       temp = ipic_read(ipic->regs, IPIC_SERMR);
-       temp &= (1 << (31 - mcp_irq));
-       ipic_write(ipic->regs, IPIC_SERMR, temp);
-}
-
 u32 ipic_get_mcp_status(void)
 {
        return primary_ipic ? ipic_read(primary_ipic->regs, IPIC_SERSR) : 0;
index 1fd0717ade02dd2049800ef0c0bc51cbbac28a71..1f1af12f23e22325855b4ec2fd8af99efd969c91 100644 (file)
@@ -51,7 +51,7 @@ phys_addr_t get_csrbase(void)
                const void *prop = of_get_property(tsi, "reg", &size);
                tsi108_csr_base = of_translate_address(tsi, prop);
                of_node_put(tsi);
-       };
+       }
        return tsi108_csr_base;
 }
 
index 94a69a62f5db868a3c97367b64c3e2a3ae9754d3..70a8f9e31a2dc79a7b1db4c0dd63d1ea46793019 100644 (file)
@@ -442,7 +442,7 @@ static void xive_dec_target_count(int cpu)
        struct xive_cpu *xc = per_cpu(xive_cpu, cpu);
        struct xive_q *q = &xc->queue[xive_irq_priority];
 
-       if (unlikely(WARN_ON(cpu < 0 || !xc))) {
+       if (WARN_ON(cpu < 0 || !xc)) {
                pr_err("%s: cpu=%d xc=%p\n", __func__, cpu, xc);
                return;
        }
index 5d28d9e454f5299bd3113c30807679cfebe2c6b6..08f4a512afad204b4798b8b6b7ee8ccff5167db1 100644 (file)
@@ -267,6 +267,7 @@ static int guest_reset(struct cxl *adapter)
        int i, rc;
 
        pr_devel("Adapter reset request\n");
+       spin_lock(&adapter->afu_list_lock);
        for (i = 0; i < adapter->slices; i++) {
                if ((afu = adapter->afu[i])) {
                        pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT,
@@ -283,6 +284,7 @@ static int guest_reset(struct cxl *adapter)
                        pci_error_handlers(afu, CXL_RESUME_EVENT, 0);
                }
        }
+       spin_unlock(&adapter->afu_list_lock);
        return rc;
 }
 
index c79ba1c699ad1005973474b705065f4c5f8773c7..300531d6136f2efacb9964ebf2daea262a20289b 100644 (file)
@@ -1805,7 +1805,7 @@ static pci_ers_result_t cxl_vphb_error_detected(struct cxl_afu *afu,
        /* There should only be one entry, but go through the list
         * anyway
         */
-       if (afu->phb == NULL)
+       if (afu == NULL || afu->phb == NULL)
                return result;
 
        list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) {
@@ -1832,7 +1832,8 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev,
 {
        struct cxl *adapter = pci_get_drvdata(pdev);
        struct cxl_afu *afu;
-       pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET, afu_result;
+       pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET;
+       pci_ers_result_t afu_result = PCI_ERS_RESULT_NEED_RESET;
        int i;
 
        /* At this point, we could still have an interrupt pending.
@@ -1843,6 +1844,7 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev,
 
        /* If we're permanently dead, give up. */
        if (state == pci_channel_io_perm_failure) {
+               spin_lock(&adapter->afu_list_lock);
                for (i = 0; i < adapter->slices; i++) {
                        afu = adapter->afu[i];
                        /*
@@ -1851,6 +1853,7 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev,
                         */
                        cxl_vphb_error_detected(afu, state);
                }
+               spin_unlock(&adapter->afu_list_lock);
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
@@ -1932,11 +1935,17 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev,
         *     * In slot_reset, free the old resources and allocate new ones.
         *     * In resume, clear the flag to allow things to start.
         */
+
+       /* Make sure no one else changes the afu list */
+       spin_lock(&adapter->afu_list_lock);
+
        for (i = 0; i < adapter->slices; i++) {
                afu = adapter->afu[i];
 
-               afu_result = cxl_vphb_error_detected(afu, state);
+               if (afu == NULL)
+                       continue;
 
+               afu_result = cxl_vphb_error_detected(afu, state);
                cxl_context_detach_all(afu);
                cxl_ops->afu_deactivate_mode(afu, afu->current_mode);
                pci_deconfigure_afu(afu);
@@ -1948,6 +1957,7 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev,
                         (result == PCI_ERS_RESULT_NEED_RESET))
                        result = PCI_ERS_RESULT_NONE;
        }
+       spin_unlock(&adapter->afu_list_lock);
 
        /* should take the context lock here */
        if (cxl_adapter_context_lock(adapter) != 0)
@@ -1980,14 +1990,18 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev)
         */
        cxl_adapter_context_unlock(adapter);
 
+       spin_lock(&adapter->afu_list_lock);
        for (i = 0; i < adapter->slices; i++) {
                afu = adapter->afu[i];
 
+               if (afu == NULL)
+                       continue;
+
                if (pci_configure_afu(afu, adapter, pdev))
-                       goto err;
+                       goto err_unlock;
 
                if (cxl_afu_select_best_mode(afu))
-                       goto err;
+                       goto err_unlock;
 
                if (afu->phb == NULL)
                        continue;
@@ -1999,16 +2013,16 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev)
                        ctx = cxl_get_context(afu_dev);
 
                        if (ctx && cxl_release_context(ctx))
-                               goto err;
+                               goto err_unlock;
 
                        ctx = cxl_dev_context_init(afu_dev);
                        if (IS_ERR(ctx))
-                               goto err;
+                               goto err_unlock;
 
                        afu_dev->dev.archdata.cxl_ctx = ctx;
 
                        if (cxl_ops->afu_check_and_enable(afu))
-                               goto err;
+                               goto err_unlock;
 
                        afu_dev->error_state = pci_channel_io_normal;
 
@@ -2029,8 +2043,13 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev)
                                result = PCI_ERS_RESULT_DISCONNECT;
                }
        }
+
+       spin_unlock(&adapter->afu_list_lock);
        return result;
 
+err_unlock:
+       spin_unlock(&adapter->afu_list_lock);
+
 err:
        /* All the bits that happen in both error_detected and cxl_remove
         * should be idempotent, so we don't need to worry about leaving a mix
@@ -2051,10 +2070,11 @@ static void cxl_pci_resume(struct pci_dev *pdev)
         * This is not the place to be checking if everything came back up
         * properly, because there's no return value: do that in slot_reset.
         */
+       spin_lock(&adapter->afu_list_lock);
        for (i = 0; i < adapter->slices; i++) {
                afu = adapter->afu[i];
 
-               if (afu->phb == NULL)
+               if (afu == NULL || afu->phb == NULL)
                        continue;
 
                list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) {
@@ -2063,6 +2083,7 @@ static void cxl_pci_resume(struct pci_dev *pdev)
                                afu_dev->driver->err_handler->resume(afu_dev);
                }
        }
+       spin_unlock(&adapter->afu_list_lock);
 }
 
 static const struct pci_error_handlers cxl_err_handler = {
index 49da2f744bbf1b8ee8a775d7192f7742188c9136..631c5df246d4384e3187a366b3c64a309ec58a5b 100644 (file)
@@ -43,8 +43,7 @@ static bool cxl_pci_enable_device_hook(struct pci_dev *dev)
                return false;
        }
 
-       set_dma_ops(&dev->dev, &dma_nommu_ops);
-       set_dma_offset(&dev->dev, PAGE_OFFSET);
+       dev->dev.archdata.dma_offset = PAGE_OFFSET;
 
        /*
         * Allocate a context to do cxl things too.  If we eventually do real
index d21041554507139415a23b61fb1d857bb1ca862f..a5bf46310f60dc314b5ac5684f7ac9ac23ad15f1 100644 (file)
@@ -1716,6 +1716,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                err = -ENODEV;
                goto out;
        }
+       dma_set_mask(&mac->dma_pdev->dev, DMA_BIT_MASK(64));
 
        mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
        if (!mac->iob_pdev) {
index 38edeb4729a9d475445bffab51c25ead9c6ae5bb..1a742fe8f6dbf4bdd4ad013b26df6f741279fc4b 100644 (file)
@@ -74,13 +74,13 @@ long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group,
                        ret = eeh_pe_get_state(pe);
                        break;
                case VFIO_EEH_PE_RESET_DEACTIVATE:
-                       ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
+                       ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE, true);
                        break;
                case VFIO_EEH_PE_RESET_HOT:
-                       ret = eeh_pe_reset(pe, EEH_RESET_HOT);
+                       ret = eeh_pe_reset(pe, EEH_RESET_HOT, true);
                        break;
                case VFIO_EEH_PE_RESET_FUNDAMENTAL:
-                       ret = eeh_pe_reset(pe, EEH_RESET_FUNDAMENTAL);
+                       ret = eeh_pe_reset(pe, EEH_RESET_FUNDAMENTAL, true);
                        break;
                case VFIO_EEH_PE_CONFIGURE:
                        ret = eeh_pe_configure(pe);
index 7c007ed7505f947eab77d85722ba79200c55afcc..54254388899e589431f80b29ab7f387f44822fe6 100644 (file)
@@ -60,9 +60,6 @@ extern void swiotlb_tbl_sync_single(struct device *hwdev,
                                    size_t size, enum dma_data_direction dir,
                                    enum dma_sync_target target);
 
-extern int
-swiotlb_dma_supported(struct device *hwdev, u64 mask);
-
 #ifdef CONFIG_SWIOTLB
 extern enum swiotlb_force swiotlb_force;
 extern phys_addr_t io_tlb_start, io_tlb_end;
index ca88b867e7fea00bec11fb43c9448c367a17adfe..0711d18645de3d666ee4d52a8b4411b33593a92f 100644 (file)
@@ -16,6 +16,9 @@ config ARCH_DMA_ADDR_T_64BIT
 config ARCH_HAS_DMA_COHERENCE_H
        bool
 
+config ARCH_HAS_DMA_SET_MASK
+       bool
+
 config HAVE_GENERIC_DMA_COHERENT
        bool
 
index 355d16acee6dd17aa7998d1ea55a6abcb3e01e92..d5bb51cf27c6543102265123e9887e42722e4fa1 100644 (file)
@@ -132,8 +132,7 @@ again:
                        goto again;
                }
 
-               if (IS_ENABLED(CONFIG_ZONE_DMA) &&
-                   phys_mask < DMA_BIT_MASK(32) && !(gfp & GFP_DMA)) {
+               if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
                        gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
                        goto again;
                }
index a11006b6d8e87d5f64db77e777da08355a32ad8d..ef2aba503467efcf91fcc60c124893c308d03e75 100644 (file)
@@ -207,7 +207,6 @@ int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 }
 EXPORT_SYMBOL(dma_mmap_attrs);
 
-#ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK
 static u64 dma_default_get_required_mask(struct device *dev)
 {
        u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
@@ -238,7 +237,6 @@ u64 dma_get_required_mask(struct device *dev)
        return dma_default_get_required_mask(dev);
 }
 EXPORT_SYMBOL_GPL(dma_get_required_mask);
-#endif
 
 #ifndef arch_dma_alloc_attrs
 #define arch_dma_alloc_attrs(dev)      (true)
@@ -318,18 +316,23 @@ int dma_supported(struct device *dev, u64 mask)
 }
 EXPORT_SYMBOL(dma_supported);
 
-#ifndef HAVE_ARCH_DMA_SET_MASK
+#ifdef CONFIG_ARCH_HAS_DMA_SET_MASK
+void arch_dma_set_mask(struct device *dev, u64 mask);
+#else
+#define arch_dma_set_mask(dev, mask)   do { } while (0)
+#endif
+
 int dma_set_mask(struct device *dev, u64 mask)
 {
        if (!dev->dma_mask || !dma_supported(dev, mask))
                return -EIO;
 
+       arch_dma_set_mask(dev, mask);
        dma_check_mask(dev, mask);
        *dev->dma_mask = mask;
        return 0;
 }
 EXPORT_SYMBOL(dma_set_mask);
-#endif
 
 #ifndef CONFIG_ARCH_HAS_DMA_SET_COHERENT_MASK
 int dma_set_coherent_mask(struct device *dev, u64 mask)
index d6361776dc5cea40ac830fb6e3940d986dd13841..cbf3498a46f95abdefefdbffe5c143a151336867 100644 (file)
@@ -648,15 +648,3 @@ bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
 
        return true;
 }
-
-/*
- * Return whether the given device DMA address mask can be supported
- * properly.  For example, if your device can only drive the low 24-bits
- * during bus mastering, then you would pass 0x00ffffff as the mask to
- * this function.
- */
-int
-swiotlb_dma_supported(struct device *hwdev, u64 mask)
-{
-       return __phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
-}
index 915c02e8e5dd28ff36e7555be769b6e5fa77e309..e81b17b53fa53aa025ccb8f12c236158cb2e61b2 100644 (file)
@@ -448,8 +448,6 @@ int walk_mem_res(u64 start, u64 end, void *arg,
                                     arg, func);
 }
 
-#if !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
-
 /*
  * This function calls the @func callback against all memory ranges of type
  * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
@@ -481,8 +479,6 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
        return ret;
 }
 
-#endif
-
 static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
 {
        return 1;
index ff91192407d1b3c027257b5e32ac9b6956f8bb13..f599064dd8dc8431fbe705320d9afc7f862f1207 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
index 1076393e6f43e2ef1d694918ba433ea625339263..e18a3556f5e315849854bc9fe6a8f42c52cd64f6 100644 (file)
@@ -63,7 +63,8 @@ static const char *reg_names[] = {
        [PERF_REG_POWERPC_TRAP] = "trap",
        [PERF_REG_POWERPC_DAR] = "dar",
        [PERF_REG_POWERPC_DSISR] = "dsisr",
-       [PERF_REG_POWERPC_SIER] = "sier"
+       [PERF_REG_POWERPC_SIER] = "sier",
+       [PERF_REG_POWERPC_MMCRA] = "mmcra"
 };
 
 static inline const char *perf_reg_name(int id)
index 07fcd977d93e4e713c3492274c77f4b70606fa08..34d5134681d96c9716ed1937f835a3b125d6dfa5 100644 (file)
@@ -53,6 +53,7 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(dar, PERF_REG_POWERPC_DAR),
        SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
        SMPL_REG(sier, PERF_REG_POWERPC_SIER),
+       SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
        SMPL_REG_END
 };
 
index 52b4710469d23a840813fa5fc5751fd967e436a2..96043b9b9829e996a610af3c0708312ccc8d39be 100644 (file)
 #define TEXASR_TE      0x0000000004000000
 #define TEXASR_ROT     0x0000000002000000
 
+/* MSR register bits */
+#define MSR_TS_S_LG     33              /* Trans Mem state: Suspended */
+
+#define __MASK(X)       (1UL<<(X))
+
+/* macro to check TM MSR bits */
+#define MSR_TS_S        __MASK(MSR_TS_S_LG)   /* Transaction Suspended */
+
 /* Vector Instructions */
 #define VSX_XX1(xs, ra, rb)    (((xs) & 0x1f) << 21 | ((ra) << 16) |  \
                                 ((rb) << 11) | (((xs) >> 5)))
index ae43a614835de78756efdc60db92668575361adf..7636bf45d5d5eb0bab70dbbd7d50d508a40498c2 100644 (file)
@@ -102,8 +102,10 @@ do {                                                               \
 
 #if defined(__powerpc64__)
 #define UCONTEXT_NIA(UC)       (UC)->uc_mcontext.gp_regs[PT_NIP]
+#define UCONTEXT_MSR(UC)       (UC)->uc_mcontext.gp_regs[PT_MSR]
 #elif defined(__powerpc__)
 #define UCONTEXT_NIA(UC)       (UC)->uc_mcontext.uc_regs->gregs[PT_NIP]
+#define UCONTEXT_MSR(UC)       (UC)->uc_mcontext.uc_regs->gregs[PT_MSR]
 #else
 #error implement UCONTEXT_NIA
 #endif
index 208452a93e2ca8c2567a29b9873812b66dc08fac..951fe855f7cd465a03dc1f03b344bbaa0d8f9264 100644 (file)
@@ -11,6 +11,7 @@ tm-signal-context-chk-fpu
 tm-signal-context-chk-gpr
 tm-signal-context-chk-vmx
 tm-signal-context-chk-vsx
+tm-signal-context-force-tm
 tm-signal-sigreturn-nt
 tm-vmx-unavail
 tm-unavailable
index 75a6853591294d3fe07f0cc85029389b567b7698..c0734ed0ef56bb67ed9330ff2f84462759aca97a 100644 (file)
@@ -4,7 +4,8 @@ SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu
 
 TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
        tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail tm-unavailable tm-trap \
-       $(SIGNAL_CONTEXT_CHK_TESTS) tm-sigreturn tm-signal-sigreturn-nt
+       $(SIGNAL_CONTEXT_CHK_TESTS) tm-sigreturn tm-signal-sigreturn-nt \
+       tm-signal-context-force-tm
 
 top_srcdir = ../../../../..
 include ../../lib.mk
@@ -20,6 +21,7 @@ $(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
 $(OUTPUT)/tm-resched-dscr: ../pmu/lib.c
 $(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx
 $(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64
+$(OUTPUT)/tm-signal-context-force-tm: CFLAGS += -pthread -m64
 
 SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
 $(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-force-tm.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-force-tm.c
new file mode 100644 (file)
index 0000000..3171762
--- /dev/null
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018, Breno Leitao, Gustavo Romero, IBM Corp.
+ *
+ * This test raises a SIGUSR1 signal, and toggle the MSR[TS]
+ * fields at the signal handler. With MSR[TS] being set, the kernel will
+ * force a recheckpoint, which may cause a segfault when returning to
+ * user space. Since the test needs to re-run, the segfault needs to be
+ * caught and handled.
+ *
+ * In order to continue the test even after a segfault, the context is
+ * saved prior to the signal being raised, and it is restored when there is
+ * a segmentation fault. This happens for COUNT_MAX times.
+ *
+ * This test never fails (as returning EXIT_FAILURE). It either succeeds,
+ * or crash the kernel (on a buggy kernel).
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <ucontext.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "tm.h"
+#include "utils.h"
+#include "reg.h"
+
+#define COUNT_MAX       5000           /* Number of interactions */
+
+/*
+ * This test only runs on 64 bits system. Unsetting MSR_TS_S to avoid
+ * compilation issue on 32 bits system. There is no side effect, since the
+ * whole test will be skipped if it is not running on 64 bits system.
+ */
+#ifndef __powerpc64__
+#undef  MSR_TS_S
+#define MSR_TS_S       0
+#endif
+
+/* Setting contexts because the test will crash and we want to recover */
+ucontext_t init_context, main_context;
+
+static int count, first_time;
+
+void usr_signal_handler(int signo, siginfo_t *si, void *uc)
+{
+       ucontext_t *ucp = uc;
+       int ret;
+
+       /*
+        * Allocating memory in a signal handler, and never freeing it on
+        * purpose, forcing the heap increase, so, the memory leak is what
+        * we want here.
+        */
+       ucp->uc_link = mmap(NULL, sizeof(ucontext_t),
+                           PROT_READ | PROT_WRITE,
+                           MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+       if (ucp->uc_link == (void *)-1) {
+               perror("Mmap failed");
+               exit(-1);
+       }
+
+       /* Forcing the page to be allocated in a page fault */
+       ret = madvise(ucp->uc_link, sizeof(ucontext_t), MADV_DONTNEED);
+       if (ret) {
+               perror("madvise failed");
+               exit(-1);
+       }
+
+       memcpy(&ucp->uc_link->uc_mcontext, &ucp->uc_mcontext,
+               sizeof(ucp->uc_mcontext));
+
+       /* Forcing to enable MSR[TM] */
+       UCONTEXT_MSR(ucp) |= MSR_TS_S;
+
+       /*
+        * A fork inside a signal handler seems to be more efficient than a
+        * fork() prior to the signal being raised.
+        */
+       if (fork() == 0) {
+               /*
+                * Both child and parent will return, but, child returns
+                * with count set so it will exit in the next segfault.
+                * Parent will continue to loop.
+                */
+               count = COUNT_MAX;
+       }
+
+       /*
+        * If the change above does not hit the bug, it will cause a
+        * segmentation fault, since the ck structures are NULL.
+        */
+}
+
+void seg_signal_handler(int signo, siginfo_t *si, void *uc)
+{
+       if (count == COUNT_MAX) {
+               /* Return to tm_signal_force_msr() and exit */
+               setcontext(&main_context);
+       }
+
+       count++;
+
+       /* Reexecute the test */
+       setcontext(&init_context);
+}
+
+void tm_trap_test(void)
+{
+       struct sigaction usr_sa, seg_sa;
+       stack_t ss;
+
+       usr_sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+       usr_sa.sa_sigaction = usr_signal_handler;
+
+       seg_sa.sa_flags = SA_SIGINFO;
+       seg_sa.sa_sigaction = seg_signal_handler;
+
+       /*
+        * Set initial context. Will get back here from
+        * seg_signal_handler()
+        */
+       getcontext(&init_context);
+
+       /* Allocated an alternative signal stack area */
+       ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
+                       MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+       ss.ss_size = SIGSTKSZ;
+       ss.ss_flags = 0;
+
+       if (ss.ss_sp == (void *)-1) {
+               perror("mmap error\n");
+               exit(-1);
+       }
+
+       /* Force the allocation through a page fault */
+       if (madvise(ss.ss_sp, SIGSTKSZ, MADV_DONTNEED)) {
+               perror("madvise\n");
+               exit(-1);
+       }
+
+       /* Setting an alternative stack to generate a page fault when
+        * the signal is raised.
+        */
+       if (sigaltstack(&ss, NULL)) {
+               perror("sigaltstack\n");
+               exit(-1);
+       }
+
+       /* The signal handler will enable MSR_TS */
+       sigaction(SIGUSR1, &usr_sa, NULL);
+       /* If it does not crash, it will segfault, avoid it to retest */
+       sigaction(SIGSEGV, &seg_sa, NULL);
+
+       raise(SIGUSR1);
+}
+
+int tm_signal_context_force_tm(void)
+{
+       SKIP_IF(!have_htm());
+       /*
+        * Skipping if not running on 64 bits system, since I think it is
+        * not possible to set mcontext's [MSR] with TS, due to it being 32
+        * bits.
+        */
+       SKIP_IF(!is_ppc64le());
+
+       /* Will get back here after COUNT_MAX interactions */
+       getcontext(&main_context);
+
+       if (!first_time++)
+               tm_trap_test();
+
+       return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+       test_harness(tm_signal_context_force_tm, "tm_signal_context_force_tm");
+}