]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Dec 2014 23:26:48 +0000 (15:26 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Dec 2014 23:26:48 +0000 (15:26 -0800)
Pull ARM updates from Russell King:
 "The major updates included in this update are:

   - Clang compatible stack pointer accesses by Behan Webster.
   - SA11x0 updates from Dmitry Eremin-Solenikov.
   - kgdb handling of breakpoints with read-only text/modules
   - Support for Privileged-no-execute feature on ARMv7 to prevent
     userspace code execution by the kernel.
   - AMBA primecell bus handling of irq-safe runtime PM
   - Unwinding support for memset/memzero/memmove/memcpy functions
   - VFP fixes for Krait CPUs and improvements in detecting the VFP
     architecture
   - A number of code cleanups (using pr_*, removing or reducing the
     severity of a couple of kernel messages, splitting ftrace asm code
     out to a separate file, etc.)
   - Add machine name to stack dump output"

* 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: (62 commits)
  ARM: 8247/2: pcmcia: sa1100: make use of device clock
  ARM: 8246/2: pcmcia: sa1111: provide device clock
  ARM: 8245/1: pcmcia: soc-common: enable/disable socket clocks
  ARM: 8244/1: fbdev: sa1100fb: make use of device clock
  ARM: 8243/1: sa1100: add a clock alias for sa1111 pcmcia device
  ARM: 8242/1: sa1100: add cpu clock
  ARM: 8221/1: PJ4: allow building in Thumb-2 mode
  ARM: 8234/1: sa1100: reorder IRQ handling code
  ARM: 8233/1: sa1100: switch to hwirq usage
  ARM: 8232/1: sa1100: merge GPIO multiplexer IRQ to "normal" irq domain
  ARM: 8231/1: sa1100: introduce irqdomains support
  ARM: 8230/1: sa1100: shift IRQs by one
  ARM: 8229/1: sa1100: replace irq numbers with names in irq driver
  ARM: 8228/1: sa1100: drop entry-macro.S
  ARM: 8227/1: sa1100: switch to MULTI_IRQ_HANDLER
  ARM: 8241/1: Update processor_modes for hyp and monitor mode
  ARM: 8240/1: MCPM: document mcpm_sync_init()
  ARM: 8239/1: Introduce {set,clear}_pte_bit
  ARM: 8238/1: mm: Refine set_memory_* functions
  ARM: 8237/1: fix flush_pfn_alias
  ...

1  2 
Documentation/power/runtime_pm.txt
arch/arm/Kconfig
arch/arm/kernel/Makefile
arch/arm/kernel/bios32.c
arch/arm/mm/Kconfig
arch/arm/mm/init.c
drivers/amba/bus.c
drivers/dma/pl330.c
include/linux/pm_runtime.h

index 0e5ea26b255a7df10a945477352a733f2241f8f1,397b8159314231bccd3c827dec1b4c31b3d47e4f..44fe1d28a16327d0cb04771f05a4df4f7f175e0d
@@@ -229,13 -229,13 +229,13 @@@ defined in include/linux/pm.h
      - if set, the value of child_count is ignored (but still updated)
  
    unsigned int disable_depth;
 -    - used for disabling the helper funcions (they work normally if this is
 +    - used for disabling the helper functions (they work normally if this is
        equal to zero); the initial value of it is 1 (i.e. runtime PM is
        initially disabled for all devices)
  
    int runtime_error;
      - if set, there was a fatal error (one of the callbacks returned error code
 -      as described in Section 2), so the helper funtions will not work until
 +      as described in Section 2), so the helper functions will not work until
        this flag is cleared; this is the error code returned by the failing
        callback
  
@@@ -468,6 -468,10 +468,10 @@@ drivers/base/power/runtime.c and includ
      - set the power.irq_safe flag for the device, causing the runtime-PM
        callbacks to be invoked with interrupts off
  
+   bool pm_runtime_is_irq_safe(struct device *dev);
+     - return true if power.irq_safe flag was set for the device, causing
+       the runtime-PM callbacks to be invoked with interrupts off
    void pm_runtime_mark_last_busy(struct device *dev);
      - set the power.last_busy field to the current time
  
@@@ -524,7 -528,7 +528,7 @@@ pm_runtime_put_sync_autosuspend(
  5. Runtime PM Initialization, Device Probing and Removal
  
  Initially, the runtime PM is disabled for all devices, which means that the
 -majority of the runtime PM helper funtions described in Section 4 will return
 +majority of the runtime PM helper functions described in Section 4 will return
  -EAGAIN until pm_runtime_enable() is called for the device.
  
  In addition to that, the initial runtime PM status of all devices is
diff --combined arch/arm/Kconfig
index c8424a85bc0453748103518743f3bab68f81d77b,622e364f7711abaed8b0c2ceb999731abc4ec668..0bee1fe209b10923a65197e63903e67ef197c29e
@@@ -320,6 -320,24 +320,6 @@@ config ARCH_MULTIPLATFOR
        select SPARSE_IRQ
        select USE_OF
  
 -config ARCH_INTEGRATOR
 -      bool "ARM Ltd. Integrator family"
 -      select ARM_AMBA
 -      select ARM_PATCH_PHYS_VIRT if MMU
 -      select AUTO_ZRELADDR
 -      select COMMON_CLK
 -      select COMMON_CLK_VERSATILE
 -      select GENERIC_CLOCKEVENTS
 -      select HAVE_TCM
 -      select ICST
 -      select MULTI_IRQ_HANDLER
 -      select PLAT_VERSATILE
 -      select SPARSE_IRQ
 -      select USE_OF
 -      select VERSATILE_FPGA_IRQ
 -      help
 -        Support for ARM's Integrator platform.
 -
  config ARCH_REALVIEW
        bool "ARM Ltd. RealView family"
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ICST
        select NEED_MACH_MEMORY_H
        select PLAT_VERSATILE
 +      select PLAT_VERSATILE_SCHED_CLOCK
        help
          This enables support for ARM Ltd RealView boards.
  
@@@ -348,7 -365,6 +348,7 @@@ config ARCH_VERSATIL
        select ICST
        select PLAT_VERSATILE
        select PLAT_VERSATILE_CLOCK
 +      select PLAT_VERSATILE_SCHED_CLOCK
        select VERSATILE_FPGA_IRQ
        help
          This enables support for ARM Ltd Versatile board.
@@@ -360,11 -376,10 +360,11 @@@ config ARCH_AT9
        select IRQ_DOMAIN
        select NEED_MACH_IO_H if PCCARD
        select PINCTRL
 -      select PINCTRL_AT91 if USE_OF
 +      select PINCTRL_AT91
 +      select USE_OF
        help
          This enables support for systems based on Atmel
 -        AT91RM9200 and AT91SAM9* processors.
 +        AT91RM9200, AT91SAM9 and SAMA5 processors.
  
  config ARCH_CLPS711X
        bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
@@@ -687,7 -702,9 +687,9 @@@ config ARCH_SA110
        select CPU_SA1100
        select GENERIC_CLOCKEVENTS
        select HAVE_IDE
+       select IRQ_DOMAIN
        select ISA
+       select MULTI_IRQ_HANDLER
        select NEED_MACH_MEMORY_H
        select SPARSE_IRQ
        help
@@@ -839,8 -856,6 +841,8 @@@ config ARCH_VIR
  #
  source "arch/arm/mach-mvebu/Kconfig"
  
 +source "arch/arm/mach-asm9260/Kconfig"
 +
  source "arch/arm/mach-at91/Kconfig"
  
  source "arch/arm/mach-axxia/Kconfig"
@@@ -1246,6 -1261,9 +1248,6 @@@ source "arch/arm/common/Kconfig
  
  menu "Bus support"
  
 -config ARM_AMBA
 -      bool
 -
  config ISA
        bool
        help
diff --combined arch/arm/kernel/Makefile
index 8dcbed5016ac2c3d18f3b3bbc2c30030c5c0a87e,2ac3920e17933b071a83d98b08f912fd146e74f0..f290ac892a95e804591e876cf4dd299d6e2768cf
@@@ -47,6 -47,7 +47,7 @@@ endi
  obj-$(CONFIG_HAVE_ARM_SCU)    += smp_scu.o
  obj-$(CONFIG_HAVE_ARM_TWD)    += smp_twd.o
  obj-$(CONFIG_ARM_ARCH_TIMER)  += arch_timer.o
+ obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
  obj-$(CONFIG_DYNAMIC_FTRACE)  += ftrace.o insn.o
  obj-$(CONFIG_FUNCTION_GRAPH_TRACER)   += ftrace.o insn.o
  obj-$(CONFIG_JUMP_LABEL)      += jump_label.o insn.o patch.o
@@@ -67,7 -68,7 +68,7 @@@ test-kprobes-objs             += kprobes-test-arm.
  endif
  obj-$(CONFIG_OABI_COMPAT)     += sys_oabi-compat.o
  obj-$(CONFIG_ARM_THUMBEE)     += thumbee.o
- obj-$(CONFIG_KGDB)            += kgdb.o
+ obj-$(CONFIG_KGDB)            += kgdb.o patch.o
  obj-$(CONFIG_ARM_UNWIND)      += unwind.o
  obj-$(CONFIG_HAVE_TCM)                += tcm.o
  obj-$(CONFIG_OF)              += devtree.o
@@@ -82,8 -83,9 +83,9 @@@ obj-$(CONFIG_CPU_MOHAWK)      += xscale-cp0.
  obj-$(CONFIG_CPU_PJ4)         += pj4-cp0.o
  obj-$(CONFIG_CPU_PJ4B)                += pj4-cp0.o
  obj-$(CONFIG_IWMMXT)          += iwmmxt.o
 -obj-$(CONFIG_PERF_EVENTS)     += perf_regs.o
 +obj-$(CONFIG_PERF_EVENTS)     += perf_regs.o perf_callchain.o
  obj-$(CONFIG_HW_PERF_EVENTS)  += perf_event.o perf_event_cpu.o
+ CFLAGS_pj4-cp0.o              := -marm
  AFLAGS_iwmmxt.o                       := -Wa,-mcpu=iwmmxt
  obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
  
diff --combined arch/arm/kernel/bios32.c
index daaff73bc776633ce6481273826f3cfe5a419357,391ffdfce57118eec21bc58928e62545b5f694bc..a4effd6d8f2f52aa3f3c82c1b7b98d650d2263ab
  
  static int debug_pci;
  
 +#ifdef CONFIG_PCI_MSI
 +struct msi_controller *pcibios_msi_controller(struct pci_dev *dev)
 +{
 +      struct pci_sys_data *sysdata = dev->bus->sysdata;
 +
 +      return sysdata->msi_ctrl;
 +}
 +#endif
 +
  /*
   * We can't use pci_get_device() here since we are
   * called from interrupt context.
@@@ -364,11 -355,25 +364,11 @@@ void pcibios_fixup_bus(struct pci_bus *
        /*
         * Report what we did for this bus
         */
-       printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
+       pr_info("PCI: bus%d: Fast back to back transfers %sabled\n",
                bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
  }
  EXPORT_SYMBOL(pcibios_fixup_bus);
  
 -void pcibios_add_bus(struct pci_bus *bus)
 -{
 -      struct pci_sys_data *sys = bus->sysdata;
 -      if (sys->add_bus)
 -              sys->add_bus(bus);
 -}
 -
 -void pcibios_remove_bus(struct pci_bus *bus)
 -{
 -      struct pci_sys_data *sys = bus->sysdata;
 -      if (sys->remove_bus)
 -              sys->remove_bus(bus);
 -}
 -
  /*
   * Swizzle the device pin each time we cross a bridge.  If a platform does
   * not provide a swizzle function, we perform the standard PCI swizzling.
@@@ -465,14 -470,13 +465,14 @@@ static void pcibios_init_hw(struct devi
  
  #ifdef CONFIG_PCI_DOMAINS
                sys->domain  = hw->domain;
 +#endif
 +#ifdef CONFIG_PCI_MSI
 +              sys->msi_ctrl = hw->msi_ctrl;
  #endif
                sys->busnr   = busnr;
                sys->swizzle = hw->swizzle;
                sys->map_irq = hw->map_irq;
                sys->align_resource = hw->align_resource;
 -              sys->add_bus = hw->add_bus;
 -              sys->remove_bus = hw->remove_bus;
                INIT_LIST_HEAD(&sys->resources);
  
                if (hw->private_data)
diff --combined arch/arm/mm/Kconfig
index ab906b8010470ad514081bc6901923a2c76f2f5d,bc219b303bc76648a02ca2b6314ef2aeeb562537..03823e784f63e7acf91fdda4d5f58927ccf527d9
@@@ -21,7 -21,7 +21,7 @@@ config CPU_ARM7TDM
  
  # ARM720T
  config CPU_ARM720T
 -      bool "Support ARM720T processor" if ARCH_INTEGRATOR
 +      bool "Support ARM720T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        select CPU_32v4T
        select CPU_ABRT_LV4T
        select CPU_CACHE_V4
@@@ -39,7 -39,7 +39,7 @@@
  
  # ARM740T
  config CPU_ARM740T
 -      bool "Support ARM740T processor" if ARCH_INTEGRATOR
 +      bool "Support ARM740T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_LV4T
@@@ -71,7 -71,7 +71,7 @@@ config CPU_ARM9TDM
  
  # ARM920T
  config CPU_ARM920T
 -      bool "Support ARM920T processor" if ARCH_INTEGRATOR
 +      bool "Support ARM920T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        select CPU_32v4T
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
@@@ -89,7 -89,7 +89,7 @@@
  
  # ARM922T
  config CPU_ARM922T
 -      bool "Support ARM922T processor" if ARCH_INTEGRATOR
 +      bool "Support ARM922T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        select CPU_32v4T
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
@@@ -127,7 -127,7 +127,7 @@@ config CPU_ARM925
  
  # ARM926T
  config CPU_ARM926T
 -      bool "Support ARM926T processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB
 +      bool "Support ARM926T processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V5) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB)
        select CPU_32v5
        select CPU_ABRT_EV5TJ
        select CPU_CACHE_VIVT
@@@ -163,7 -163,7 +163,7 @@@ config CPU_FA52
  
  # ARM940T
  config CPU_ARM940T
 -      bool "Support ARM940T processor" if ARCH_INTEGRATOR
 +      bool "Support ARM940T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_NOMMU
  
  # ARM946E-S
  config CPU_ARM946E
 -      bool "Support ARM946E-S processor" if ARCH_INTEGRATOR
 +      bool "Support ARM946E-S processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        depends on !MMU
        select CPU_32v5
        select CPU_ABRT_NOMMU
  
  # ARM1020 - needs validating
  config CPU_ARM1020
 -      bool "Support ARM1020T (rev 0) processor" if ARCH_INTEGRATOR
 +      bool "Support ARM1020T (rev 0) processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        select CPU_32v5
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
  
  # ARM1020E - needs validating
  config CPU_ARM1020E
 -      bool "Support ARM1020E processor" if ARCH_INTEGRATOR
 +      bool "Support ARM1020E processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        depends on n
        select CPU_32v5
        select CPU_ABRT_EV4T
  
  # ARM1022E
  config CPU_ARM1022
 -      bool "Support ARM1022E processor" if ARCH_INTEGRATOR
 +      bool "Support ARM1022E processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        select CPU_32v5
        select CPU_ABRT_EV4T
        select CPU_CACHE_VIVT
  
  # ARM1026EJ-S
  config CPU_ARM1026
 -      bool "Support ARM1026EJ-S processor" if ARCH_INTEGRATOR
 +      bool "Support ARM1026EJ-S processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        select CPU_32v5
        select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10
        select CPU_CACHE_VIVT
@@@ -358,7 -358,7 +358,7 @@@ config CPU_PJ4
  
  # ARMv6
  config CPU_V6
 -      bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
 +      bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX)
        select CPU_32v6
        select CPU_ABRT_EV6
        select CPU_CACHE_V6
  
  # ARMv6k
  config CPU_V6K
 -      bool "Support ARM V6K processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
 +      bool "Support ARM V6K processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX)
        select CPU_32v6
        select CPU_32v6K
        select CPU_ABRT_EV6
  
  # ARMv7
  config CPU_V7
 -      bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
 +      bool "Support ARM V7 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V7) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX)
        select CPU_32v6K
        select CPU_32v7
        select CPU_ABRT_EV7
@@@ -1009,3 -1009,24 +1009,24 @@@ config ARCH_SUPPORTS_BIG_ENDIA
        help
          This option specifies the architecture can support big endian
          operation.
+ config ARM_KERNMEM_PERMS
+       bool "Restrict kernel memory permissions"
+       help
+         If this is set, kernel memory other than kernel text (and rodata)
+         will be made non-executable. The tradeoff is that each region is
+         padded to section-size (1MiB) boundaries (because their permissions
+         are different and splitting the 1M pages into 4K ones causes TLB
+         performance problems), wasting memory.
+ config DEBUG_RODATA
+       bool "Make kernel text and rodata read-only"
+       depends on ARM_KERNMEM_PERMS
+       default y
+       help
+         If this is set, kernel text and rodata will be made read-only. This
+         is to help catch accidental or malicious attempts to change the
+         kernel's executable code. Additionally splits rodata from kernel
+         text so it can be made explicitly non-executable. This creates
+         another section-size padded region, so it can waste more memory
+         space while gaining the read-only protections.
diff --combined arch/arm/mm/init.c
index 9481f85c56e6fd0ed263401a3e71d0cfa541606c,ba87b1b3565f7d0d60ce1adc7a5bb6d9f0e64504..98ad9c79ea0e6a1e980a5f0c09e4c25389e060e2
@@@ -29,6 -29,7 +29,7 @@@
  #include <asm/prom.h>
  #include <asm/sections.h>
  #include <asm/setup.h>
+ #include <asm/system_info.h>
  #include <asm/tlb.h>
  #include <asm/fixmap.h>
  
@@@ -67,7 -68,7 +68,7 @@@ early_param("initrd", early_initrd)
  
  static int __init parse_tag_initrd(const struct tag *tag)
  {
-       printk(KERN_WARNING "ATAG_INITRD is deprecated; "
+       pr_warn("ATAG_INITRD is deprecated; "
                "please update your bootloader.\n");
        phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
        phys_initrd_size = tag->u.initrd.size;
@@@ -544,7 -545,7 +545,7 @@@ void __init mem_init(void
  #define MLM(b, t) b, t, ((t) - (b)) >> 20
  #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
  
-       printk(KERN_NOTICE "Virtual kernel memory layout:\n"
+       pr_notice("Virtual kernel memory layout:\n"
                        "    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
  #ifdef CONFIG_HAVE_TCM
                        "    DTCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
  #ifdef CONFIG_MODULES
                        "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
  #endif
 -                      "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
 -                      "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
 -                      "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
 -                      "       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n",
 +                      "      .text : 0x%p" " - 0x%p" "   (%4td kB)\n"
 +                      "      .init : 0x%p" " - 0x%p" "   (%4td kB)\n"
 +                      "      .data : 0x%p" " - 0x%p" "   (%4td kB)\n"
 +                      "       .bss : 0x%p" " - 0x%p" "   (%4td kB)\n",
  
                        MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
                                (PAGE_SIZE)),
                        MLK(DTCM_OFFSET, (unsigned long) dtcm_end),
                        MLK(ITCM_OFFSET, (unsigned long) itcm_end),
  #endif
-                       MLK(FIXADDR_START, FIXADDR_TOP),
+                       MLK(FIXADDR_START, FIXADDR_END),
                        MLM(VMALLOC_START, VMALLOC_END),
                        MLM(PAGE_OFFSET, (unsigned long)high_memory),
  #ifdef CONFIG_HIGHMEM
        }
  }
  
- void free_initmem(void)
+ #ifdef CONFIG_ARM_KERNMEM_PERMS
+ struct section_perm {
+       unsigned long start;
+       unsigned long end;
+       pmdval_t mask;
+       pmdval_t prot;
+       pmdval_t clear;
+ };
+ static struct section_perm nx_perms[] = {
+       /* Make pages tables, etc before _stext RW (set NX). */
+       {
+               .start  = PAGE_OFFSET,
+               .end    = (unsigned long)_stext,
+               .mask   = ~PMD_SECT_XN,
+               .prot   = PMD_SECT_XN,
+       },
+       /* Make init RW (set NX). */
+       {
+               .start  = (unsigned long)__init_begin,
+               .end    = (unsigned long)_sdata,
+               .mask   = ~PMD_SECT_XN,
+               .prot   = PMD_SECT_XN,
+       },
+ #ifdef CONFIG_DEBUG_RODATA
+       /* Make rodata NX (set RO in ro_perms below). */
+       {
+               .start  = (unsigned long)__start_rodata,
+               .end    = (unsigned long)__init_begin,
+               .mask   = ~PMD_SECT_XN,
+               .prot   = PMD_SECT_XN,
+       },
+ #endif
+ };
+ #ifdef CONFIG_DEBUG_RODATA
+ static struct section_perm ro_perms[] = {
+       /* Make kernel code and rodata RX (set RO). */
+       {
+               .start  = (unsigned long)_stext,
+               .end    = (unsigned long)__init_begin,
+ #ifdef CONFIG_ARM_LPAE
+               .mask   = ~PMD_SECT_RDONLY,
+               .prot   = PMD_SECT_RDONLY,
+ #else
+               .mask   = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE),
+               .prot   = PMD_SECT_APX | PMD_SECT_AP_WRITE,
+               .clear  = PMD_SECT_AP_WRITE,
+ #endif
+       },
+ };
+ #endif
+ /*
+  * Updates section permissions only for the current mm (sections are
+  * copied into each mm). During startup, this is the init_mm. Is only
+  * safe to be called with preemption disabled, as under stop_machine().
+  */
+ static inline void section_update(unsigned long addr, pmdval_t mask,
+                                 pmdval_t prot)
+ {
+       struct mm_struct *mm;
+       pmd_t *pmd;
+       mm = current->active_mm;
+       pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr);
+ #ifdef CONFIG_ARM_LPAE
+       pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot);
+ #else
+       if (addr & SECTION_SIZE)
+               pmd[1] = __pmd((pmd_val(pmd[1]) & mask) | prot);
+       else
+               pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot);
+ #endif
+       flush_pmd_entry(pmd);
+       local_flush_tlb_kernel_range(addr, addr + SECTION_SIZE);
+ }
+ /* Make sure extended page tables are in use. */
+ static inline bool arch_has_strict_perms(void)
+ {
+       if (cpu_architecture() < CPU_ARCH_ARMv6)
+               return false;
+       return !!(get_cr() & CR_XP);
+ }
+ #define set_section_perms(perms, field)       {                               \
+       size_t i;                                                       \
+       unsigned long addr;                                             \
+                                                                       \
+       if (!arch_has_strict_perms())                                   \
+               return;                                                 \
+                                                                       \
+       for (i = 0; i < ARRAY_SIZE(perms); i++) {                       \
+               if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||        \
+                   !IS_ALIGNED(perms[i].end, SECTION_SIZE)) {          \
+                       pr_err("BUG: section %lx-%lx not aligned to %lx\n", \
+                               perms[i].start, perms[i].end,           \
+                               SECTION_SIZE);                          \
+                       continue;                                       \
+               }                                                       \
+                                                                       \
+               for (addr = perms[i].start;                             \
+                    addr < perms[i].end;                               \
+                    addr += SECTION_SIZE)                              \
+                       section_update(addr, perms[i].mask,             \
+                                      perms[i].field);                 \
+       }                                                               \
+ }
+ static inline void fix_kernmem_perms(void)
+ {
+       set_section_perms(nx_perms, prot);
+ }
+ #ifdef CONFIG_DEBUG_RODATA
+ void mark_rodata_ro(void)
+ {
+       set_section_perms(ro_perms, prot);
+ }
+ void set_kernel_text_rw(void)
+ {
+       set_section_perms(ro_perms, clear);
+ }
+ void set_kernel_text_ro(void)
+ {
+       set_section_perms(ro_perms, prot);
+ }
+ #endif /* CONFIG_DEBUG_RODATA */
+ #else
+ static inline void fix_kernmem_perms(void) { }
+ #endif /* CONFIG_ARM_KERNMEM_PERMS */
+ void free_tcmmem(void)
  {
  #ifdef CONFIG_HAVE_TCM
        extern char __tcm_start, __tcm_end;
        poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start);
        free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link");
  #endif
+ }
+ void free_initmem(void)
+ {
+       fix_kernmem_perms();
+       free_tcmmem();
  
        poison_init_mem(__init_begin, __init_end - __init_begin);
        if (!machine_is_integrator() && !machine_is_cintegrator())
diff --combined drivers/amba/bus.c
index 973a3332a85f91681ec62a4e77ad719fc3c1da0b,f8e3bb44938e27bf619c05e81fb288f2a2775a35..80f4de729a863a91690cf9bd021f2b6c598eb18f
@@@ -95,8 -95,12 +95,12 @@@ static int amba_pm_runtime_suspend(stru
        struct amba_device *pcdev = to_amba_device(dev);
        int ret = pm_generic_runtime_suspend(dev);
  
-       if (ret == 0 && dev->driver)
-               clk_disable_unprepare(pcdev->pclk);
+       if (ret == 0 && dev->driver) {
+               if (pm_runtime_is_irq_safe(dev))
+                       clk_disable(pcdev->pclk);
+               else
+                       clk_disable_unprepare(pcdev->pclk);
+       }
  
        return ret;
  }
@@@ -107,7 -111,10 +111,10 @@@ static int amba_pm_runtime_resume(struc
        int ret;
  
        if (dev->driver) {
-               ret = clk_prepare_enable(pcdev->pclk);
+               if (pm_runtime_is_irq_safe(dev))
+                       ret = clk_enable(pcdev->pclk);
+               else
+                       ret = clk_prepare_enable(pcdev->pclk);
                /* Failure is probably fatal to the system, but... */
                if (ret)
                        return ret;
  
        return pm_generic_runtime_resume(dev);
  }
- #endif
+ #endif /* CONFIG_PM */
  
  static const struct dev_pm_ops amba_pm = {
        .suspend        = pm_generic_suspend,
        .thaw           = pm_generic_thaw,
        .poweroff       = pm_generic_poweroff,
        .restore        = pm_generic_restore,
 -      SET_PM_RUNTIME_PM_OPS(
 +      SET_RUNTIME_PM_OPS(
                amba_pm_runtime_suspend,
                amba_pm_runtime_resume,
                NULL
diff --combined drivers/dma/pl330.c
index 025b905f6db299fa5c172c1251e22f588ec942cd,2d324f780719162ca9d4f1286e917cd39d35cf6c..bdf40b5300328886f139801548542723330218c2
@@@ -27,6 -27,7 +27,7 @@@
  #include <linux/of.h>
  #include <linux/of_dma.h>
  #include <linux/err.h>
+ #include <linux/pm_runtime.h>
  
  #include "dmaengine.h"
  #define PL330_MAX_CHAN                8
@@@ -265,13 -266,16 +266,16 @@@ static unsigned cmd_line
  
  #define NR_DEFAULT_DESC       16
  
+ /* Delay for runtime PM autosuspend, ms */
+ #define PL330_AUTOSUSPEND_DELAY 20
  /* Populated by the PL330 core driver for DMA API driver's info */
  struct pl330_config {
        u32     periph_id;
  #define DMAC_MODE_NS  (1 << 0)
        unsigned int    mode;
        unsigned int    data_bus_width:10; /* In number of bits */
 -      unsigned int    data_buf_dep:10;
 +      unsigned int    data_buf_dep:11;
        unsigned int    num_chan:4;
        unsigned int    num_peri:6;
        u32             peri_ns;
@@@ -1958,6 -1962,7 +1962,7 @@@ static void pl330_tasklet(unsigned lon
        struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
        struct dma_pl330_desc *desc, *_dt;
        unsigned long flags;
+       bool power_down = false;
  
        spin_lock_irqsave(&pch->lock, flags);
  
        /* Try to submit a req imm. next to the last completed cookie */
        fill_queue(pch);
  
-       /* Make sure the PL330 Channel thread is active */
-       spin_lock(&pch->thread->dmac->lock);
-       _start(pch->thread);
-       spin_unlock(&pch->thread->dmac->lock);
+       if (list_empty(&pch->work_list)) {
+               spin_lock(&pch->thread->dmac->lock);
+               _stop(pch->thread);
+               spin_unlock(&pch->thread->dmac->lock);
+               power_down = true;
+       } else {
+               /* Make sure the PL330 Channel thread is active */
+               spin_lock(&pch->thread->dmac->lock);
+               _start(pch->thread);
+               spin_unlock(&pch->thread->dmac->lock);
+       }
  
        while (!list_empty(&pch->completed_list)) {
                dma_async_tx_callback callback;
                if (pch->cyclic) {
                        desc->status = PREP;
                        list_move_tail(&desc->node, &pch->work_list);
+                       if (power_down) {
+                               spin_lock(&pch->thread->dmac->lock);
+                               _start(pch->thread);
+                               spin_unlock(&pch->thread->dmac->lock);
+                               power_down = false;
+                       }
                } else {
                        desc->status = FREE;
                        list_move_tail(&desc->node, &pch->dmac->desc_pool);
                }
        }
        spin_unlock_irqrestore(&pch->lock, flags);
+       /* If work list empty, power down */
+       if (power_down) {
+               pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
+               pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
+       }
  }
  
  bool pl330_filter(struct dma_chan *chan, void *param)
@@@ -2073,6 -2097,7 +2097,7 @@@ static int pl330_control(struct dma_cha
  
        switch (cmd) {
        case DMA_TERMINATE_ALL:
+               pm_runtime_get_sync(pl330->ddma.dev);
                spin_lock_irqsave(&pch->lock, flags);
  
                spin_lock(&pl330->lock);
                        dma_cookie_complete(&desc->txd);
                }
  
+               if (!list_empty(&pch->work_list))
+                       pm_runtime_put(pl330->ddma.dev);
                list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool);
                list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
                list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
                spin_unlock_irqrestore(&pch->lock, flags);
+               pm_runtime_mark_last_busy(pl330->ddma.dev);
+               pm_runtime_put_autosuspend(pl330->ddma.dev);
                break;
        case DMA_SLAVE_CONFIG:
                slave_config = (struct dma_slave_config *)arg;
@@@ -2138,6 -2168,7 +2168,7 @@@ static void pl330_free_chan_resources(s
  
        tasklet_kill(&pch->task);
  
+       pm_runtime_get_sync(pch->dmac->ddma.dev);
        spin_lock_irqsave(&pch->lock, flags);
  
        pl330_release_channel(pch->thread);
                list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
  
        spin_unlock_irqrestore(&pch->lock, flags);
+       pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
+       pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
  }
  
  static enum dma_status
@@@ -2162,6 -2195,15 +2195,15 @@@ static void pl330_issue_pending(struct 
        unsigned long flags;
  
        spin_lock_irqsave(&pch->lock, flags);
+       if (list_empty(&pch->work_list)) {
+               /*
+                * Warn on nothing pending. Empty submitted_list may
+                * break our pm_runtime usage counter as it is
+                * updated on work_list emptiness status.
+                */
+               WARN_ON(list_empty(&pch->submitted_list));
+               pm_runtime_get_sync(pch->dmac->ddma.dev);
+       }
        list_splice_tail_init(&pch->submitted_list, &pch->work_list);
        spin_unlock_irqrestore(&pch->lock, flags);
  
@@@ -2336,7 -2378,7 +2378,7 @@@ static inline int get_burst_len(struct 
        int burst_len;
  
        burst_len = pl330->pcfg.data_bus_width / 8;
 -      burst_len *= pl330->pcfg.data_buf_dep;
 +      burst_len *= pl330->pcfg.data_buf_dep / pl330->pcfg.num_chan;
        burst_len >>= desc->rqcfg.brst_size;
  
        /* src/dst_burst_len can't be more than 16 */
@@@ -2459,25 -2501,16 +2501,25 @@@ pl330_prep_dma_memcpy(struct dma_chan *
        /* Select max possible burst size */
        burst = pl330->pcfg.data_bus_width / 8;
  
 -      while (burst > 1) {
 -              if (!(len % burst))
 -                      break;
 +      /*
 +       * Make sure we use a burst size that aligns with all the memcpy
 +       * parameters because our DMA programming algorithm doesn't cope with
 +       * transfers which straddle an entry in the DMA device's MFIFO.
 +       */
 +      while ((src | dst | len) & (burst - 1))
                burst /= 2;
 -      }
  
        desc->rqcfg.brst_size = 0;
        while (burst != (1 << desc->rqcfg.brst_size))
                desc->rqcfg.brst_size++;
  
 +      /*
 +       * If burst size is smaller than bus width then make sure we only
 +       * transfer one at a time to avoid a burst stradling an MFIFO entry.
 +       */
 +      if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width)
 +              desc->rqcfg.brst_len = 1;
 +
        desc->rqcfg.brst_len = get_burst_len(desc, len);
  
        desc->txd.flags = flags;
@@@ -2594,6 -2627,46 +2636,46 @@@ static int pl330_dma_device_slave_caps(
        return 0;
  }
  
+ /*
+  * Runtime PM callbacks are provided by amba/bus.c driver.
+  *
+  * It is assumed here that IRQ safe runtime PM is chosen in probe and amba
+  * bus driver will only disable/enable the clock in runtime PM callbacks.
+  */
+ static int __maybe_unused pl330_suspend(struct device *dev)
+ {
+       struct amba_device *pcdev = to_amba_device(dev);
+       pm_runtime_disable(dev);
+       if (!pm_runtime_status_suspended(dev)) {
+               /* amba did not disable the clock */
+               amba_pclk_disable(pcdev);
+       }
+       amba_pclk_unprepare(pcdev);
+       return 0;
+ }
+ static int __maybe_unused pl330_resume(struct device *dev)
+ {
+       struct amba_device *pcdev = to_amba_device(dev);
+       int ret;
+       ret = amba_pclk_prepare(pcdev);
+       if (ret)
+               return ret;
+       if (!pm_runtime_status_suspended(dev))
+               ret = amba_pclk_enable(pcdev);
+       pm_runtime_enable(dev);
+       return ret;
+ }
+ static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume);
  static int
  pl330_probe(struct amba_device *adev, const struct amba_id *id)
  {
                return -ENOMEM;
        }
  
 +      pd = &pl330->ddma;
 +      pd->dev = &adev->dev;
 +
        pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
  
        res = &adev->res;
        if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
                dev_warn(&adev->dev, "unable to allocate desc\n");
  
 -      pd = &pl330->ddma;
        INIT_LIST_HEAD(&pd->channels);
  
        /* Initialize channel parameters */
                list_add_tail(&pch->chan.device_node, &pd->channels);
        }
  
 -      pd->dev = &adev->dev;
        if (pdat) {
                pd->cap_mask = pdat->cap_mask;
        } else {
  
  
        dev_info(&adev->dev,
 -              "Loaded driver for PL330 DMAC-%d\n", adev->periphid);
 +              "Loaded driver for PL330 DMAC-%x\n", adev->periphid);
        dev_info(&adev->dev,
                "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
                pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
                pcfg->num_peri, pcfg->num_events);
  
+       pm_runtime_irq_safe(&adev->dev);
+       pm_runtime_use_autosuspend(&adev->dev);
+       pm_runtime_set_autosuspend_delay(&adev->dev, PL330_AUTOSUSPEND_DELAY);
+       pm_runtime_mark_last_busy(&adev->dev);
+       pm_runtime_put_autosuspend(&adev->dev);
        return 0;
  probe_err3:
        /* Idle the DMAC */
@@@ -2774,6 -2852,8 +2862,8 @@@ static int pl330_remove(struct amba_dev
        struct pl330_dmac *pl330 = amba_get_drvdata(adev);
        struct dma_pl330_chan *pch, *_p;
  
+       pm_runtime_get_noresume(pl330->ddma.dev);
        if (adev->dev.of_node)
                of_dma_controller_free(adev->dev.of_node);
  
@@@ -2812,6 -2892,7 +2902,7 @@@ static struct amba_driver pl330_driver 
        .drv = {
                .owner = THIS_MODULE,
                .name = "dma-pl330",
+               .pm = &pl330_pm,
        },
        .id_table = pl330_ids,
        .probe = pl330_probe,
  
  module_amba_driver(pl330_driver);
  
 -MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
 +MODULE_AUTHOR("Jaswinder Singh <jassisinghbrar@gmail.com>");
  MODULE_DESCRIPTION("API Driver for PL330 DMAC");
  MODULE_LICENSE("GPL");
index eda4feede04842d10faec6ce63014072d42c3bbe,44d74f0f182e3457bcbdbeee9e8323011d94f50b..30e84d48bfeaa8e40075f1d47bba6e0d49b310c6
@@@ -35,6 -35,16 +35,6 @@@ extern int pm_generic_runtime_suspend(s
  extern int pm_generic_runtime_resume(struct device *dev);
  extern int pm_runtime_force_suspend(struct device *dev);
  extern int pm_runtime_force_resume(struct device *dev);
 -#else
 -static inline bool queue_pm_work(struct work_struct *work) { return false; }
 -
 -static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
 -static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
 -static inline int pm_runtime_force_suspend(struct device *dev) { return 0; }
 -static inline int pm_runtime_force_resume(struct device *dev) { return 0; }
 -#endif
 -
 -#ifdef CONFIG_PM_RUNTIME
  
  extern int __pm_runtime_idle(struct device *dev, int rpmflags);
  extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
@@@ -118,14 -128,12 +118,19 @@@ static inline void pm_runtime_mark_last
        ACCESS_ONCE(dev->power.last_busy) = jiffies;
  }
  
 -#else /* !CONFIG_PM_RUNTIME */
+ static inline bool pm_runtime_is_irq_safe(struct device *dev)
+ {
+       return dev->power.irq_safe;
+ }
 +#else /* !CONFIG_PM */
 +
 +static inline bool queue_pm_work(struct work_struct *work) { return false; }
 +
 +static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
 +static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
 +static inline int pm_runtime_force_suspend(struct device *dev) { return 0; }
 +static inline int pm_runtime_force_resume(struct device *dev) { return 0; }
  
  static inline int __pm_runtime_idle(struct device *dev, int rpmflags)
  {
@@@ -164,6 -172,7 +169,7 @@@ static inline bool pm_runtime_enabled(s
  
  static inline void pm_runtime_no_callbacks(struct device *dev) {}
  static inline void pm_runtime_irq_safe(struct device *dev) {}
+ static inline bool pm_runtime_is_irq_safe(struct device *dev) { return false; }
  
  static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; }
  static inline void pm_runtime_mark_last_busy(struct device *dev) {}
@@@ -176,7 -185,7 +182,7 @@@ static inline unsigned long pm_runtime_
  static inline void pm_runtime_set_memalloc_noio(struct device *dev,
                                                bool enable){}
  
 -#endif /* !CONFIG_PM_RUNTIME */
 +#endif /* !CONFIG_PM */
  
  static inline int pm_runtime_idle(struct device *dev)
  {