Browse Source

Merge branch 'pm-opp' into pm-cpufreq

Rafael J. Wysocki 10 years ago
parent
commit
0ed537b5fd
100 changed files with 2090 additions and 861 deletions
  1. 1 1
      Documentation/devicetree/bindings/dma/apm-xgene-dma.txt
  2. 20 20
      Documentation/devicetree/bindings/opp/opp.txt
  3. 2 0
      Documentation/devicetree/bindings/sound/mt8173-max98090.txt
  4. 2 0
      Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
  5. 3 3
      Documentation/devicetree/bindings/spi/spi-ath79.txt
  6. 2 2
      Documentation/hwmon/nct7904
  7. 14 7
      Documentation/target/tcm_mod_builder.py
  8. 5 1
      MAINTAINERS
  9. 1 1
      Makefile
  10. 1 1
      arch/arm/boot/dts/exynos3250.dtsi
  11. 4 0
      arch/arm/boot/dts/exynos4210-origen.dts
  12. 4 0
      arch/arm/boot/dts/exynos4210-trats.dts
  13. 4 0
      arch/arm/boot/dts/exynos4210-universal_c210.dts
  14. 12 0
      arch/arm/boot/dts/exynos4210.dtsi
  15. 4 4
      arch/arm/boot/dts/imx35.dtsi
  16. 2 3
      arch/arm/boot/dts/k2e-clocks.dtsi
  17. 2 3
      arch/arm/boot/dts/k2hk-clocks.dtsi
  18. 2 3
      arch/arm/boot/dts/k2l-clocks.dtsi
  19. 1 0
      arch/arm/boot/dts/ste-nomadik-nhk15.dts
  20. 4 0
      arch/arm/boot/dts/ste-nomadik-s8815.dts
  21. 1 0
      arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
  22. 16 8
      arch/arm/mach-omap2/omap_hwmod.c
  23. 2 3
      arch/arm/mach-omap2/omap_hwmod_7xx_data.c
  24. 1 1
      arch/arm64/boot/dts/apm/apm-storm.dtsi
  25. 2 2
      arch/arm64/kernel/efi.c
  26. 19 1
      arch/avr32/mach-at32ap/clock.c
  27. 1 1
      arch/powerpc/platforms/powernv/eeh-powernv.c
  28. 6 5
      arch/powerpc/platforms/powernv/pci-ioda.c
  29. 2 0
      arch/s390/kernel/cache.c
  30. 7 7
      arch/s390/net/bpf_jit_comp.c
  31. 4 0
      arch/x86/boot/compressed/eboot.c
  32. 0 15
      arch/x86/include/asm/desc.h
  33. 1 2
      arch/x86/include/asm/mmu.h
  34. 49 5
      arch/x86/include/asm/mmu_context.h
  35. 1 1
      arch/x86/kernel/apic/io_apic.c
  36. 2 2
      arch/x86/kernel/cpu/common.c
  37. 8 4
      arch/x86/kernel/cpu/perf_event.c
  38. 142 120
      arch/x86/kernel/ldt.c
  39. 2 2
      arch/x86/kernel/process_64.c
  40. 4 2
      arch/x86/kernel/step.c
  41. 4 4
      arch/x86/net/bpf_jit_comp.c
  42. 5 0
      arch/x86/platform/efi/efi.c
  43. 2 1
      arch/x86/power/cpu.c
  44. 40 0
      arch/x86/xen/enlighten.c
  45. 1 1
      drivers/acpi/device_pm.c
  46. 868 227
      drivers/base/power/opp.c
  47. 62 11
      drivers/cpufreq/cpufreq-dt.c
  48. 48 20
      drivers/cpufreq/cpufreq.c
  49. 4 0
      drivers/cpufreq/cpufreq_opp.c
  50. 15 0
      drivers/cpufreq/freq_table.c
  51. 87 45
      drivers/dma/at_hdmac.c
  52. 1 2
      drivers/dma/at_hdmac_regs.h
  53. 14 12
      drivers/dma/at_xdmac.c
  54. 5 4
      drivers/dma/mv_xor.c
  55. 2 1
      drivers/dma/pl330.c
  56. 6 13
      drivers/dma/virt-dma.c
  57. 1 12
      drivers/dma/virt-dma.h
  58. 3 0
      drivers/dma/xgene-dma.c
  59. 5 0
      drivers/firmware/efi/efi.c
  60. 7 1
      drivers/gpu/drm/amd/amdgpu/amdgpu.h
  61. 22 16
      drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
  62. 5 3
      drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
  63. 8 8
      drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
  64. 3 3
      drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
  65. 35 11
      drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
  66. 36 11
      drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
  67. 5 3
      drivers/gpu/drm/drm_atomic_helper.c
  68. 8 9
      drivers/gpu/drm/i915/i915_drv.h
  69. 11 0
      drivers/gpu/drm/i915/i915_gem_gtt.c
  70. 4 1
      drivers/gpu/drm/i915/i915_gem_tiling.c
  71. 3 1
      drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
  72. 13 0
      drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
  73. 2 0
      drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
  74. 14 19
      drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
  75. 74 13
      drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
  76. 1 0
      drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
  77. 2 6
      drivers/gpu/drm/msm/msm_atomic.c
  78. 9 4
      drivers/gpu/drm/msm/msm_drv.c
  79. 2 2
      drivers/gpu/drm/msm/msm_drv.h
  80. 1 1
      drivers/gpu/drm/msm/msm_gem.c
  81. 6 2
      drivers/gpu/drm/msm/msm_gem_prime.c
  82. 3 0
      drivers/gpu/drm/nouveau/nouveau_drm.c
  83. 16 0
      drivers/gpu/drm/nouveau/nouveau_platform.c
  84. 9 0
      drivers/gpu/drm/nouveau/nouveau_ttm.c
  85. 1 1
      drivers/gpu/drm/nouveau/nv04_fbcon.c
  86. 1 1
      drivers/gpu/drm/nouveau/nv50_display.c
  87. 2 1
      drivers/gpu/drm/nouveau/nv50_fbcon.c
  88. 1 1
      drivers/gpu/drm/nouveau/nvc0_fbcon.c
  89. 1 1
      drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
  90. 21 8
      drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
  91. 38 1
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
  92. 1 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
  93. 8 6
      drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
  94. 40 0
      drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
  95. 2 1
      drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
  96. 8 0
      drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
  97. 8 0
      drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
  98. 1 2
      drivers/gpu/drm/radeon/atombios_encoders.c
  99. 28 34
      drivers/gpu/drm/radeon/dce6_afmt.c
  100. 97 107
      drivers/gpu/drm/radeon/radeon_audio.c

+ 1 - 1
Documentation/devicetree/bindings/dma/apm-xgene-dma.txt

@@ -35,7 +35,7 @@ Example:
 			device_type = "dma";
 			device_type = "dma";
 			reg = <0x0 0x1f270000 0x0 0x10000>,
 			reg = <0x0 0x1f270000 0x0 0x10000>,
 			      <0x0 0x1f200000 0x0 0x10000>,
 			      <0x0 0x1f200000 0x0 0x10000>,
-			      <0x0 0x1b008000 0x0 0x2000>,
+			      <0x0 0x1b000000 0x0 0x400000>,
 			      <0x0 0x1054a000 0x0 0x100>;
 			      <0x0 0x1054a000 0x0 0x100>;
 			interrupts = <0x0 0x82 0x4>,
 			interrupts = <0x0 0x82 0x4>,
 				     <0x0 0xb8 0x4>,
 				     <0x0 0xb8 0x4>,

+ 20 - 20
Documentation/devicetree/bindings/power/opp.txt → Documentation/devicetree/bindings/opp/opp.txt

@@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
 properties.
 properties.
 
 
 Required properties:
 Required properties:
-- opp-hz: Frequency in Hz
+- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
 
 
 Optional properties:
 Optional properties:
 - opp-microvolt: voltage in micro Volts.
 - opp-microvolt: voltage in micro Volts.
@@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
 		opp-shared;
 		opp-shared;
 
 
 		opp00 {
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 			opp-suspend;
 		};
 		};
 		opp01 {
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 			clock-latency-ns = <310000>;
 		};
 		};
 		opp02 {
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microvolt = <1025000>;
 			clock-latency-ns = <290000>;
 			clock-latency-ns = <290000>;
 			turbo-mode;
 			turbo-mode;
@@ -237,20 +237,20 @@ independently.
 		 */
 		 */
 
 
 		opp00 {
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 			opp-suspend;
 		};
 		};
 		opp01 {
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 			clock-latency-ns = <310000>;
 		};
 		};
 		opp02 {
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000;
 			opp-microamp = <90000;
 			lock-latency-ns = <290000>;
 			lock-latency-ns = <290000>;
@@ -313,20 +313,20 @@ DVFS state together.
 		opp-shared;
 		opp-shared;
 
 
 		opp00 {
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 			opp-suspend;
 		};
 		};
 		opp01 {
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 			clock-latency-ns = <310000>;
 		};
 		};
 		opp02 {
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000>;
 			opp-microamp = <90000>;
 			clock-latency-ns = <290000>;
 			clock-latency-ns = <290000>;
@@ -339,20 +339,20 @@ DVFS state together.
 		opp-shared;
 		opp-shared;
 
 
 		opp10 {
 		opp10 {
-			opp-hz = <1300000000>;
+			opp-hz = /bits/ 64 <1300000000>;
 			opp-microvolt = <1045000 1050000 1055000>;
 			opp-microvolt = <1045000 1050000 1055000>;
 			opp-microamp = <95000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
 			clock-latency-ns = <400000>;
 			opp-suspend;
 			opp-suspend;
 		};
 		};
 		opp11 {
 		opp11 {
-			opp-hz = <1400000000>;
+			opp-hz = /bits/ 64 <1400000000>;
 			opp-microvolt = <1075000>;
 			opp-microvolt = <1075000>;
 			opp-microamp = <100000>;
 			opp-microamp = <100000>;
 			clock-latency-ns = <400000>;
 			clock-latency-ns = <400000>;
 		};
 		};
 		opp12 {
 		opp12 {
-			opp-hz = <1500000000>;
+			opp-hz = /bits/ 64 <1500000000>;
 			opp-microvolt = <1010000 1100000 1110000>;
 			opp-microvolt = <1010000 1100000 1110000>;
 			opp-microamp = <95000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
 			clock-latency-ns = <400000>;
@@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
 		opp-shared;
 		opp-shared;
 
 
 		opp00 {
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000>, /* Supply 0 */
 			opp-microvolt = <970000>, /* Supply 0 */
 					<960000>, /* Supply 1 */
 					<960000>, /* Supply 1 */
 					<960000>; /* Supply 2 */
 					<960000>; /* Supply 2 */
@@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 		/* OR */
 
 
 		opp00 {
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 		/* OR */
 
 
 		opp00 {
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 		opp-shared;
 
 
 		opp00 {
 		opp00 {
-			opp-hz = <600000000>;
+			opp-hz = /bits/ 64 <600000000>;
 			...
 			...
 		};
 		};
 
 
 		opp01 {
 		opp01 {
-			opp-hz = <800000000>;
+			opp-hz = /bits/ 64 <800000000>;
 			...
 			...
 		};
 		};
 	};
 	};
@@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 		opp-shared;
 
 
 		opp10 {
 		opp10 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			...
 			...
 		};
 		};
 
 
 		opp11 {
 		opp11 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			...
 			...
 		};
 		};
 	};
 	};

+ 2 - 0
Documentation/devicetree/bindings/sound/mt8173-max98090.txt

@@ -3,11 +3,13 @@ MT8173 with MAX98090 CODEC
 Required properties:
 Required properties:
 - compatible : "mediatek,mt8173-max98090"
 - compatible : "mediatek,mt8173-max98090"
 - mediatek,audio-codec: the phandle of the MAX98090 audio codec
 - mediatek,audio-codec: the phandle of the MAX98090 audio codec
+- mediatek,platform: the phandle of MT8173 ASoC platform
 
 
 Example:
 Example:
 
 
 	sound {
 	sound {
 		compatible = "mediatek,mt8173-max98090";
 		compatible = "mediatek,mt8173-max98090";
 		mediatek,audio-codec = <&max98090>;
 		mediatek,audio-codec = <&max98090>;
+		mediatek,platform = <&afe>;
 	};
 	};
 
 

+ 2 - 0
Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt

@@ -3,11 +3,13 @@ MT8173 with RT5650 RT5676 CODECS
 Required properties:
 Required properties:
 - compatible : "mediatek,mt8173-rt5650-rt5676"
 - compatible : "mediatek,mt8173-rt5650-rt5676"
 - mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs
 - mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs
+- mediatek,platform: the phandle of MT8173 ASoC platform
 
 
 Example:
 Example:
 
 
 	sound {
 	sound {
 		compatible = "mediatek,mt8173-rt5650-rt5676";
 		compatible = "mediatek,mt8173-rt5650-rt5676";
 		mediatek,audio-codec = <&rt5650 &rt5676>;
 		mediatek,audio-codec = <&rt5650 &rt5676>;
+		mediatek,platform = <&afe>;
 	};
 	};
 
 

+ 3 - 3
Documentation/devicetree/bindings/spi/spi-ath79.txt

@@ -3,7 +3,7 @@ Binding for Qualcomm Atheros AR7xxx/AR9xxx SPI controller
 Required properties:
 Required properties:
 - compatible: has to be "qca,<soc-type>-spi", "qca,ar7100-spi" as fallback.
 - compatible: has to be "qca,<soc-type>-spi", "qca,ar7100-spi" as fallback.
 - reg: Base address and size of the controllers memory area
 - reg: Base address and size of the controllers memory area
-- clocks: phandle to the AHB clock.
+- clocks: phandle of the AHB clock.
 - clock-names: has to be "ahb".
 - clock-names: has to be "ahb".
 - #address-cells: <1>, as required by generic SPI binding.
 - #address-cells: <1>, as required by generic SPI binding.
 - #size-cells: <0>, also as required by generic SPI binding.
 - #size-cells: <0>, also as required by generic SPI binding.
@@ -12,9 +12,9 @@ Child nodes as per the generic SPI binding.
 
 
 Example:
 Example:
 
 
-	spi@1F000000 {
+	spi@1f000000 {
 		compatible = "qca,ar9132-spi", "qca,ar7100-spi";
 		compatible = "qca,ar9132-spi", "qca,ar7100-spi";
-		reg = <0x1F000000 0x10>;
+		reg = <0x1f000000 0x10>;
 
 
 		clocks = <&pll 2>;
 		clocks = <&pll 2>;
 		clock-names = "ahb";
 		clock-names = "ahb";

+ 2 - 2
Documentation/hwmon/nct7904

@@ -35,11 +35,11 @@ temp1_input		Local temperature (1/1000 degree,
 temp[2-9]_input		CPU temperatures (1/1000 degree,
 temp[2-9]_input		CPU temperatures (1/1000 degree,
 			0.125 degree resolution)
 			0.125 degree resolution)
 
 
-fan[1-4]_mode		R/W, 0/1 for manual or SmartFan mode
+pwm[1-4]_enable		R/W, 1/2 for manual or SmartFan mode
 			Setting SmartFan mode is supported only if it has been
 			Setting SmartFan mode is supported only if it has been
 			previously configured by BIOS (or configuration EEPROM)
 			previously configured by BIOS (or configuration EEPROM)
 
 
-fan[1-4]_pwm		R/O in SmartFan mode, R/W in manual control mode
+pwm[1-4]		R/O in SmartFan mode, R/W in manual control mode
 
 
 The driver checks sensor control registers and does not export the sensors
 The driver checks sensor control registers and does not export the sensors
 that are not enabled. Anyway, a sensor that is enabled may actually be not
 that are not enabled. Anyway, a sensor that is enabled may actually be not

+ 14 - 7
Documentation/target/tcm_mod_builder.py

@@ -199,7 +199,8 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "#include <linux/string.h>\n"
 	buf += "#include <linux/string.h>\n"
 	buf += "#include <linux/configfs.h>\n"
 	buf += "#include <linux/configfs.h>\n"
 	buf += "#include <linux/ctype.h>\n"
 	buf += "#include <linux/ctype.h>\n"
-	buf += "#include <asm/unaligned.h>\n\n"
+	buf += "#include <asm/unaligned.h>\n"
+	buf += "#include <scsi/scsi_proto.h>\n\n"
 	buf += "#include <target/target_core_base.h>\n"
 	buf += "#include <target/target_core_base.h>\n"
 	buf += "#include <target/target_core_fabric.h>\n"
 	buf += "#include <target/target_core_fabric.h>\n"
 	buf += "#include <target/target_core_fabric_configfs.h>\n"
 	buf += "#include <target/target_core_fabric_configfs.h>\n"
@@ -230,8 +231,14 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	}\n"
 	buf += "	}\n"
 	buf += "	tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
 	buf += "	tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
 	buf += "	tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
 	buf += "	tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
-	buf += "	ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n"
-	buf += "				&tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
+
+	if proto_ident == "FC":
+		buf += "	ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);\n"
+	elif proto_ident == "SAS":
+		buf += "	ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
+	elif proto_ident == "iSCSI":
+		buf += "	ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_ISCSI);\n"
+
 	buf += "	if (ret < 0) {\n"
 	buf += "	if (ret < 0) {\n"
 	buf += "		kfree(tpg);\n"
 	buf += "		kfree(tpg);\n"
 	buf += "		return NULL;\n"
 	buf += "		return NULL;\n"
@@ -292,7 +299,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 
 
 	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
 	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
 	buf += "	.module				= THIS_MODULE,\n"
 	buf += "	.module				= THIS_MODULE,\n"
-	buf += "	.name				= " + fabric_mod_name + ",\n"
+	buf += "	.name				= \"" + fabric_mod_name + "\",\n"
 	buf += "	.get_fabric_name		= " + fabric_mod_name + "_get_fabric_name,\n"
 	buf += "	.get_fabric_name		= " + fabric_mod_name + "_get_fabric_name,\n"
 	buf += "	.tpg_get_wwn			= " + fabric_mod_name + "_get_fabric_wwn,\n"
 	buf += "	.tpg_get_wwn			= " + fabric_mod_name + "_get_fabric_wwn,\n"
 	buf += "	.tpg_get_tag			= " + fabric_mod_name + "_get_tag,\n"
 	buf += "	.tpg_get_tag			= " + fabric_mod_name + "_get_tag,\n"
@@ -322,17 +329,17 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	.fabric_make_tpg		= " + fabric_mod_name + "_make_tpg,\n"
 	buf += "	.fabric_make_tpg		= " + fabric_mod_name + "_make_tpg,\n"
 	buf += "	.fabric_drop_tpg		= " + fabric_mod_name + "_drop_tpg,\n"
 	buf += "	.fabric_drop_tpg		= " + fabric_mod_name + "_drop_tpg,\n"
 	buf += "\n"
 	buf += "\n"
-	buf += "	.tfc_wwn_attrs			= " + fabric_mod_name + "_wwn_attrs;\n"
+	buf += "	.tfc_wwn_attrs			= " + fabric_mod_name + "_wwn_attrs,\n"
 	buf += "};\n\n"
 	buf += "};\n\n"
 
 
 	buf += "static int __init " + fabric_mod_name + "_init(void)\n"
 	buf += "static int __init " + fabric_mod_name + "_init(void)\n"
 	buf += "{\n"
 	buf += "{\n"
-	buf += "	return target_register_template(" + fabric_mod_name + "_ops);\n"
+	buf += "	return target_register_template(&" + fabric_mod_name + "_ops);\n"
 	buf += "};\n\n"
 	buf += "};\n\n"
 
 
 	buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
 	buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
 	buf += "{\n"
 	buf += "{\n"
-	buf += "	target_unregister_template(" + fabric_mod_name + "_ops);\n"
+	buf += "	target_unregister_template(&" + fabric_mod_name + "_ops);\n"
 	buf += "};\n\n"
 	buf += "};\n\n"
 
 
 	buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
 	buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"

+ 5 - 1
MAINTAINERS

@@ -5600,6 +5600,7 @@ F:	kernel/irq/
 IRQCHIP DRIVERS
 IRQCHIP DRIVERS
 M:	Thomas Gleixner <tglx@linutronix.de>
 M:	Thomas Gleixner <tglx@linutronix.de>
 M:	Jason Cooper <jason@lakedaemon.net>
 M:	Jason Cooper <jason@lakedaemon.net>
+M:	Marc Zyngier <marc.zyngier@arm.com>
 L:	linux-kernel@vger.kernel.org
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
@@ -5608,11 +5609,14 @@ F:	Documentation/devicetree/bindings/interrupt-controller/
 F:	drivers/irqchip/
 F:	drivers/irqchip/
 
 
 IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
 IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
-M:	Benjamin Herrenschmidt <benh@kernel.crashing.org>
+M:	Jiang Liu <jiang.liu@linux.intel.com>
+M:	Marc Zyngier <marc.zyngier@arm.com>
 S:	Maintained
 S:	Maintained
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
 F:	Documentation/IRQ-domain.txt
 F:	Documentation/IRQ-domain.txt
 F:	include/linux/irqdomain.h
 F:	include/linux/irqdomain.h
 F:	kernel/irq/irqdomain.c
 F:	kernel/irq/irqdomain.c
+F:	kernel/irq/msi.c
 
 
 ISAPNP
 ISAPNP
 M:	Jaroslav Kysela <perex@perex.cz>
 M:	Jaroslav Kysela <perex@perex.cz>

+ 1 - 1
Makefile

@@ -1,7 +1,7 @@
 VERSION = 4
 VERSION = 4
 PATCHLEVEL = 2
 PATCHLEVEL = 2
 SUBLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Hurr durr I'ma sheep
 NAME = Hurr durr I'ma sheep
 
 
 # *DOCUMENTATION*
 # *DOCUMENTATION*

+ 1 - 1
arch/arm/boot/dts/exynos3250.dtsi

@@ -138,8 +138,8 @@
 
 
 		mipi_phy: video-phy@10020710 {
 		mipi_phy: video-phy@10020710 {
 			compatible = "samsung,s5pv210-mipi-video-phy";
 			compatible = "samsung,s5pv210-mipi-video-phy";
-			reg = <0x10020710 8>;
 			#phy-cells = <1>;
 			#phy-cells = <1>;
+			syscon = <&pmu_system_controller>;
 		};
 		};
 
 
 		pd_cam: cam-power-domain@10023C00 {
 		pd_cam: cam-power-domain@10023C00 {

+ 4 - 0
arch/arm/boot/dts/exynos4210-origen.dts

@@ -127,6 +127,10 @@
 	};
 	};
 };
 };
 
 
+&cpu0 {
+	cpu0-supply = <&buck1_reg>;
+};
+
 &fimd {
 &fimd {
 	pinctrl-0 = <&lcd_en &lcd_clk &lcd_data24 &pwm0_out>;
 	pinctrl-0 = <&lcd_en &lcd_clk &lcd_data24 &pwm0_out>;
 	pinctrl-names = "default";
 	pinctrl-names = "default";

+ 4 - 0
arch/arm/boot/dts/exynos4210-trats.dts

@@ -188,6 +188,10 @@
 	};
 	};
 };
 };
 
 
+&cpu0 {
+	cpu0-supply = <&varm_breg>;
+};
+
 &dsi_0 {
 &dsi_0 {
 	vddcore-supply = <&vusb_reg>;
 	vddcore-supply = <&vusb_reg>;
 	vddio-supply = <&vmipi_reg>;
 	vddio-supply = <&vmipi_reg>;

+ 4 - 0
arch/arm/boot/dts/exynos4210-universal_c210.dts

@@ -548,6 +548,10 @@
 	};
 	};
 };
 };
 
 
+&cpu0 {
+	cpu0-supply = <&vdd_arm_reg>;
+};
+
 &pinctrl_1 {
 &pinctrl_1 {
 	hdmi_hpd: hdmi-hpd {
 	hdmi_hpd: hdmi-hpd {
 		samsung,pins = "gpx3-7";
 		samsung,pins = "gpx3-7";

+ 12 - 0
arch/arm/boot/dts/exynos4210.dtsi

@@ -40,6 +40,18 @@
 			device_type = "cpu";
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			compatible = "arm,cortex-a9";
 			reg = <0x900>;
 			reg = <0x900>;
+			clocks = <&clock CLK_ARM_CLK>;
+			clock-names = "cpu";
+			clock-latency = <160000>;
+
+			operating-points = <
+				1200000 1250000
+				1000000 1150000
+				800000	1075000
+				500000	975000
+				400000	975000
+				200000	950000
+			>;
 			cooling-min-level = <4>;
 			cooling-min-level = <4>;
 			cooling-max-level = <2>;
 			cooling-max-level = <2>;
 			#cooling-cells = <2>; /* min followed by max */
 			#cooling-cells = <2>; /* min followed by max */

+ 4 - 4
arch/arm/boot/dts/imx35.dtsi

@@ -286,8 +286,8 @@
 			can1: can@53fe4000 {
 			can1: can@53fe4000 {
 				compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
 				compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
 				reg = <0x53fe4000 0x1000>;
 				reg = <0x53fe4000 0x1000>;
-				clocks = <&clks 33>;
-				clock-names = "ipg";
+				clocks = <&clks 33>, <&clks 33>;
+				clock-names = "ipg", "per";
 				interrupts = <43>;
 				interrupts = <43>;
 				status = "disabled";
 				status = "disabled";
 			};
 			};
@@ -295,8 +295,8 @@
 			can2: can@53fe8000 {
 			can2: can@53fe8000 {
 				compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
 				compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
 				reg = <0x53fe8000 0x1000>;
 				reg = <0x53fe8000 0x1000>;
-				clocks = <&clks 34>;
-				clock-names = "ipg";
+				clocks = <&clks 34>, <&clks 34>;
+				clock-names = "ipg", "per";
 				interrupts = <44>;
 				interrupts = <44>;
 				status = "disabled";
 				status = "disabled";
 			};
 			};

+ 2 - 3
arch/arm/boot/dts/k2e-clocks.dtsi

@@ -13,9 +13,8 @@ clocks {
 		#clock-cells = <0>;
 		#clock-cells = <0>;
 		compatible = "ti,keystone,main-pll-clock";
 		compatible = "ti,keystone,main-pll-clock";
 		clocks = <&refclksys>;
 		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>;
-		reg-names = "control", "multiplier";
-		fixed-postdiv = <2>;
+		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+		reg-names = "control", "multiplier", "post-divider";
 	};
 	};
 
 
 	papllclk: papllclk@2620358 {
 	papllclk: papllclk@2620358 {

+ 2 - 3
arch/arm/boot/dts/k2hk-clocks.dtsi

@@ -22,9 +22,8 @@ clocks {
 		#clock-cells = <0>;
 		#clock-cells = <0>;
 		compatible = "ti,keystone,main-pll-clock";
 		compatible = "ti,keystone,main-pll-clock";
 		clocks = <&refclksys>;
 		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>;
-		reg-names = "control", "multiplier";
-		fixed-postdiv = <2>;
+		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+		reg-names = "control", "multiplier", "post-divider";
 	};
 	};
 
 
 	papllclk: papllclk@2620358 {
 	papllclk: papllclk@2620358 {

+ 2 - 3
arch/arm/boot/dts/k2l-clocks.dtsi

@@ -22,9 +22,8 @@ clocks {
 		#clock-cells = <0>;
 		#clock-cells = <0>;
 		compatible = "ti,keystone,main-pll-clock";
 		compatible = "ti,keystone,main-pll-clock";
 		clocks = <&refclksys>;
 		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>;
-		reg-names = "control", "multiplier";
-		fixed-postdiv = <2>;
+		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+		reg-names = "control", "multiplier", "post-divider";
 	};
 	};
 
 
 	papllclk: papllclk@2620358 {
 	papllclk: papllclk@2620358 {

+ 1 - 0
arch/arm/boot/dts/ste-nomadik-nhk15.dts

@@ -17,6 +17,7 @@
 	};
 	};
 
 
 	aliases {
 	aliases {
+		serial1 = &uart1;
 		stmpe-i2c0 = &stmpe0;
 		stmpe-i2c0 = &stmpe0;
 		stmpe-i2c1 = &stmpe1;
 		stmpe-i2c1 = &stmpe1;
 	};
 	};

+ 4 - 0
arch/arm/boot/dts/ste-nomadik-s8815.dts

@@ -15,6 +15,10 @@
 		bootargs = "root=/dev/ram0 console=ttyAMA1,115200n8 earlyprintk";
 		bootargs = "root=/dev/ram0 console=ttyAMA1,115200n8 earlyprintk";
 	};
 	};
 
 
+	aliases {
+		serial1 = &uart1;
+	};
+
 	src@101e0000 {
 	src@101e0000 {
 		/* These chrystal drivers are not used on this board */
 		/* These chrystal drivers are not used on this board */
 		disable-sxtalo;
 		disable-sxtalo;

+ 1 - 0
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi

@@ -757,6 +757,7 @@
 			clock-names = "uartclk", "apb_pclk";
 			clock-names = "uartclk", "apb_pclk";
 			pinctrl-names = "default";
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_default_mux>;
 			pinctrl-0 = <&uart0_default_mux>;
+			status = "disabled";
 		};
 		};
 
 
 		uart1: uart@101fb000 {
 		uart1: uart@101fb000 {

+ 16 - 8
arch/arm/mach-omap2/omap_hwmod.c

@@ -2373,6 +2373,9 @@ static int of_dev_hwmod_lookup(struct device_node *np,
  * registers.  This address is needed early so the OCP registers that
  * registers.  This address is needed early so the OCP registers that
  * are part of the device's address space can be ioremapped properly.
  * are part of the device's address space can be ioremapped properly.
  *
  *
+ * If SYSC access is not needed, the registers will not be remapped
+ * and non-availability of MPU access is not treated as an error.
+ *
  * Returns 0 on success, -EINVAL if an invalid hwmod is passed, and
  * Returns 0 on success, -EINVAL if an invalid hwmod is passed, and
  * -ENXIO on absent or invalid register target address space.
  * -ENXIO on absent or invalid register target address space.
  */
  */
@@ -2387,6 +2390,11 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
 
 
 	_save_mpu_port_index(oh);
 	_save_mpu_port_index(oh);
 
 
+	/* if we don't need sysc access we don't need to ioremap */
+	if (!oh->class->sysc)
+		return 0;
+
+	/* we can't continue without MPU PORT if we need sysc access */
 	if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
 	if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
 		return -ENXIO;
 		return -ENXIO;
 
 
@@ -2396,8 +2404,10 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
 			 oh->name);
 			 oh->name);
 
 
 		/* Extract the IO space from device tree blob */
 		/* Extract the IO space from device tree blob */
-		if (!np)
+		if (!np) {
+			pr_err("omap_hwmod: %s: no dt node\n", oh->name);
 			return -ENXIO;
 			return -ENXIO;
+		}
 
 
 		va_start = of_iomap(np, index + oh->mpu_rt_idx);
 		va_start = of_iomap(np, index + oh->mpu_rt_idx);
 	} else {
 	} else {
@@ -2456,13 +2466,11 @@ static int __init _init(struct omap_hwmod *oh, void *data)
 				oh->name, np->name);
 				oh->name, np->name);
 	}
 	}
 
 
-	if (oh->class->sysc) {
-		r = _init_mpu_rt_base(oh, NULL, index, np);
-		if (r < 0) {
-			WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
-			     oh->name);
-			return 0;
-		}
+	r = _init_mpu_rt_base(oh, NULL, index, np);
+	if (r < 0) {
+		WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
+		     oh->name);
+		return 0;
 	}
 	}
 
 
 	r = _init_clocks(oh, NULL);
 	r = _init_clocks(oh, NULL);

+ 2 - 3
arch/arm/mach-omap2/omap_hwmod_7xx_data.c

@@ -827,8 +827,7 @@ static struct omap_hwmod_class_sysconfig dra7xx_gpmc_sysc = {
 	.syss_offs	= 0x0014,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
 	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
 			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
 			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   SIDLE_SMART_WKUP),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 };
 
 
@@ -844,7 +843,7 @@ static struct omap_hwmod dra7xx_gpmc_hwmod = {
 	.class		= &dra7xx_gpmc_hwmod_class,
 	.class		= &dra7xx_gpmc_hwmod_class,
 	.clkdm_name	= "l3main1_clkdm",
 	.clkdm_name	= "l3main1_clkdm",
 	/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
 	/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
-	.flags		= HWMOD_SWSUP_SIDLE | DEBUG_OMAP_GPMC_HWMOD_FLAGS,
+	.flags		= DEBUG_OMAP_GPMC_HWMOD_FLAGS,
 	.main_clk	= "l3_iclk_div",
 	.main_clk	= "l3_iclk_div",
 	.prcm = {
 	.prcm = {
 		.omap4 = {
 		.omap4 = {

+ 1 - 1
arch/arm64/boot/dts/apm/apm-storm.dtsi

@@ -823,7 +823,7 @@
 			device_type = "dma";
 			device_type = "dma";
 			reg = <0x0 0x1f270000 0x0 0x10000>,
 			reg = <0x0 0x1f270000 0x0 0x10000>,
 			      <0x0 0x1f200000 0x0 0x10000>,
 			      <0x0 0x1f200000 0x0 0x10000>,
-			      <0x0 0x1b008000 0x0 0x2000>,
+			      <0x0 0x1b000000 0x0 0x400000>,
 			      <0x0 0x1054a000 0x0 0x100>;
 			      <0x0 0x1054a000 0x0 0x100>;
 			interrupts = <0x0 0x82 0x4>,
 			interrupts = <0x0 0x82 0x4>,
 				     <0x0 0xb8 0x4>,
 				     <0x0 0xb8 0x4>,

+ 2 - 2
arch/arm64/kernel/efi.c

@@ -122,12 +122,12 @@ static int __init uefi_init(void)
 
 
 	/* Show what we know for posterity */
 	/* Show what we know for posterity */
 	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
 	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
-			     sizeof(vendor));
+			     sizeof(vendor) * sizeof(efi_char16_t));
 	if (c16) {
 	if (c16) {
 		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
 		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = c16[i];
 			vendor[i] = c16[i];
 		vendor[i] = '\0';
 		vendor[i] = '\0';
-		early_memunmap(c16, sizeof(vendor));
+		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
 	}
 	}
 
 
 	pr_info("EFI v%u.%.02u by %s\n",
 	pr_info("EFI v%u.%.02u by %s\n",

+ 19 - 1
arch/avr32/mach-at32ap/clock.c

@@ -80,6 +80,9 @@ int clk_enable(struct clk *clk)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 
 
+	if (!clk)
+		return 0;
+
 	spin_lock_irqsave(&clk_lock, flags);
 	spin_lock_irqsave(&clk_lock, flags);
 	__clk_enable(clk);
 	__clk_enable(clk);
 	spin_unlock_irqrestore(&clk_lock, flags);
 	spin_unlock_irqrestore(&clk_lock, flags);
@@ -106,6 +109,9 @@ void clk_disable(struct clk *clk)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 
 
+	if (IS_ERR_OR_NULL(clk))
+		return;
+
 	spin_lock_irqsave(&clk_lock, flags);
 	spin_lock_irqsave(&clk_lock, flags);
 	__clk_disable(clk);
 	__clk_disable(clk);
 	spin_unlock_irqrestore(&clk_lock, flags);
 	spin_unlock_irqrestore(&clk_lock, flags);
@@ -117,6 +123,9 @@ unsigned long clk_get_rate(struct clk *clk)
 	unsigned long flags;
 	unsigned long flags;
 	unsigned long rate;
 	unsigned long rate;
 
 
+	if (!clk)
+		return 0;
+
 	spin_lock_irqsave(&clk_lock, flags);
 	spin_lock_irqsave(&clk_lock, flags);
 	rate = clk->get_rate(clk);
 	rate = clk->get_rate(clk);
 	spin_unlock_irqrestore(&clk_lock, flags);
 	spin_unlock_irqrestore(&clk_lock, flags);
@@ -129,6 +138,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 {
 	unsigned long flags, actual_rate;
 	unsigned long flags, actual_rate;
 
 
+	if (!clk)
+		return 0;
+
 	if (!clk->set_rate)
 	if (!clk->set_rate)
 		return -ENOSYS;
 		return -ENOSYS;
 
 
@@ -145,6 +157,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	unsigned long flags;
 	unsigned long flags;
 	long ret;
 	long ret;
 
 
+	if (!clk)
+		return 0;
+
 	if (!clk->set_rate)
 	if (!clk->set_rate)
 		return -ENOSYS;
 		return -ENOSYS;
 
 
@@ -161,6 +176,9 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	unsigned long flags;
 	unsigned long flags;
 	int ret;
 	int ret;
 
 
+	if (!clk)
+		return 0;
+
 	if (!clk->set_parent)
 	if (!clk->set_parent)
 		return -ENOSYS;
 		return -ENOSYS;
 
 
@@ -174,7 +192,7 @@ EXPORT_SYMBOL(clk_set_parent);
 
 
 struct clk *clk_get_parent(struct clk *clk)
 struct clk *clk_get_parent(struct clk *clk)
 {
 {
-	return clk->parent;
+	return !clk ? NULL : clk->parent;
 }
 }
 EXPORT_SYMBOL(clk_get_parent);
 EXPORT_SYMBOL(clk_get_parent);
 
 

+ 1 - 1
arch/powerpc/platforms/powernv/eeh-powernv.c

@@ -1478,7 +1478,7 @@ static int pnv_eeh_next_error(struct eeh_pe **pe)
 	}
 	}
 
 
 	/* Unmask the event */
 	/* Unmask the event */
-	if (eeh_enabled())
+	if (ret == EEH_NEXT_ERR_NONE && eeh_enabled())
 		enable_irq(eeh_event_irq);
 		enable_irq(eeh_event_irq);
 
 
 	return ret;
 	return ret;

+ 6 - 5
arch/powerpc/platforms/powernv/pci-ioda.c

@@ -2220,7 +2220,7 @@ static void pnv_pci_ioda_setup_opal_tce_kill(struct pnv_phb *phb)
 
 
 static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
 static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
 		unsigned levels, unsigned long limit,
 		unsigned levels, unsigned long limit,
-		unsigned long *current_offset)
+		unsigned long *current_offset, unsigned long *total_allocated)
 {
 {
 	struct page *tce_mem = NULL;
 	struct page *tce_mem = NULL;
 	__be64 *addr, *tmp;
 	__be64 *addr, *tmp;
@@ -2236,6 +2236,7 @@ static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
 	}
 	}
 	addr = page_address(tce_mem);
 	addr = page_address(tce_mem);
 	memset(addr, 0, allocated);
 	memset(addr, 0, allocated);
+	*total_allocated += allocated;
 
 
 	--levels;
 	--levels;
 	if (!levels) {
 	if (!levels) {
@@ -2245,7 +2246,7 @@ static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
 
 
 	for (i = 0; i < entries; ++i) {
 	for (i = 0; i < entries; ++i) {
 		tmp = pnv_pci_ioda2_table_do_alloc_pages(nid, shift,
 		tmp = pnv_pci_ioda2_table_do_alloc_pages(nid, shift,
-				levels, limit, current_offset);
+				levels, limit, current_offset, total_allocated);
 		if (!tmp)
 		if (!tmp)
 			break;
 			break;
 
 
@@ -2267,7 +2268,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
 		struct iommu_table *tbl)
 		struct iommu_table *tbl)
 {
 {
 	void *addr;
 	void *addr;
-	unsigned long offset = 0, level_shift;
+	unsigned long offset = 0, level_shift, total_allocated = 0;
 	const unsigned window_shift = ilog2(window_size);
 	const unsigned window_shift = ilog2(window_size);
 	unsigned entries_shift = window_shift - page_shift;
 	unsigned entries_shift = window_shift - page_shift;
 	unsigned table_shift = max_t(unsigned, entries_shift + 3, PAGE_SHIFT);
 	unsigned table_shift = max_t(unsigned, entries_shift + 3, PAGE_SHIFT);
@@ -2286,7 +2287,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
 
 
 	/* Allocate TCE table */
 	/* Allocate TCE table */
 	addr = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift,
 	addr = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift,
-			levels, tce_table_size, &offset);
+			levels, tce_table_size, &offset, &total_allocated);
 
 
 	/* addr==NULL means that the first level allocation failed */
 	/* addr==NULL means that the first level allocation failed */
 	if (!addr)
 	if (!addr)
@@ -2308,7 +2309,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
 			page_shift);
 			page_shift);
 	tbl->it_level_size = 1ULL << (level_shift - 3);
 	tbl->it_level_size = 1ULL << (level_shift - 3);
 	tbl->it_indirect_levels = levels - 1;
 	tbl->it_indirect_levels = levels - 1;
-	tbl->it_allocated_size = offset;
+	tbl->it_allocated_size = total_allocated;
 
 
 	pr_devel("Created TCE table: ws=%08llx ts=%lx @%08llx\n",
 	pr_devel("Created TCE table: ws=%08llx ts=%lx @%08llx\n",
 			window_size, tce_table_size, bus_offset);
 			window_size, tce_table_size, bus_offset);

+ 2 - 0
arch/s390/kernel/cache.c

@@ -138,6 +138,8 @@ int init_cache_level(unsigned int cpu)
 	union cache_topology ct;
 	union cache_topology ct;
 	enum cache_type ctype;
 	enum cache_type ctype;
 
 
+	if (!test_facility(34))
+		return -EOPNOTSUPP;
 	if (!this_cpu_ci)
 	if (!this_cpu_ci)
 		return -EINVAL;
 		return -EINVAL;
 	ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
 	ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);

+ 7 - 7
arch/s390/net/bpf_jit_comp.c

@@ -448,13 +448,13 @@ static void bpf_jit_prologue(struct bpf_jit *jit)
 		EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
 		EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
 			      BPF_REG_1, offsetof(struct sk_buff, data));
 			      BPF_REG_1, offsetof(struct sk_buff, data));
 	}
 	}
-	/* BPF compatibility: clear A (%b7) and X (%b8) registers */
-	if (REG_SEEN(BPF_REG_7))
-		/* lghi %b7,0 */
-		EMIT4_IMM(0xa7090000, BPF_REG_7, 0);
-	if (REG_SEEN(BPF_REG_8))
-		/* lghi %b8,0 */
-		EMIT4_IMM(0xa7090000, BPF_REG_8, 0);
+	/* BPF compatibility: clear A (%b0) and X (%b7) registers */
+	if (REG_SEEN(BPF_REG_A))
+		/* lghi %ba,0 */
+		EMIT4_IMM(0xa7090000, BPF_REG_A, 0);
+	if (REG_SEEN(BPF_REG_X))
+		/* lghi %bx,0 */
+		EMIT4_IMM(0xa7090000, BPF_REG_X, 0);
 }
 }
 
 
 /*
 /*

+ 4 - 0
arch/x86/boot/compressed/eboot.c

@@ -1193,6 +1193,10 @@ static efi_status_t setup_e820(struct boot_params *params,
 		unsigned int e820_type = 0;
 		unsigned int e820_type = 0;
 		unsigned long m = efi->efi_memmap;
 		unsigned long m = efi->efi_memmap;
 
 
+#ifdef CONFIG_X86_64
+		m |= (u64)efi->efi_memmap_hi << 32;
+#endif
+
 		d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size));
 		d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size));
 		switch (d->type) {
 		switch (d->type) {
 		case EFI_RESERVED_TYPE:
 		case EFI_RESERVED_TYPE:

+ 0 - 15
arch/x86/include/asm/desc.h

@@ -280,21 +280,6 @@ static inline void clear_LDT(void)
 	set_ldt(NULL, 0);
 	set_ldt(NULL, 0);
 }
 }
 
 
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
-	set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
-	preempt_disable();
-	load_LDT_nolock(pc);
-	preempt_enable();
-}
-
 static inline unsigned long get_desc_base(const struct desc_struct *desc)
 static inline unsigned long get_desc_base(const struct desc_struct *desc)
 {
 {
 	return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
 	return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));

+ 1 - 2
arch/x86/include/asm/mmu.h

@@ -9,8 +9,7 @@
  * we put the segment information here.
  * we put the segment information here.
  */
  */
 typedef struct {
 typedef struct {
-	void *ldt;
-	int size;
+	struct ldt_struct *ldt;
 
 
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_X86_64
 	/* True if mm supports a task running in 32 bit compatibility mode. */
 	/* True if mm supports a task running in 32 bit compatibility mode. */

+ 49 - 5
arch/x86/include/asm/mmu_context.h

@@ -33,6 +33,50 @@ static inline void load_mm_cr4(struct mm_struct *mm)
 static inline void load_mm_cr4(struct mm_struct *mm) {}
 static inline void load_mm_cr4(struct mm_struct *mm) {}
 #endif
 #endif
 
 
+/*
+ * ldt_structs can be allocated, used, and freed, but they are never
+ * modified while live.
+ */
+struct ldt_struct {
+	/*
+	 * Xen requires page-aligned LDTs with special permissions.  This is
+	 * needed to prevent us from installing evil descriptors such as
+	 * call gates.  On native, we could merge the ldt_struct and LDT
+	 * allocations, but it's not worth trying to optimize.
+	 */
+	struct desc_struct *entries;
+	int size;
+};
+
+static inline void load_mm_ldt(struct mm_struct *mm)
+{
+	struct ldt_struct *ldt;
+
+	/* lockless_dereference synchronizes with smp_store_release */
+	ldt = lockless_dereference(mm->context.ldt);
+
+	/*
+	 * Any change to mm->context.ldt is followed by an IPI to all
+	 * CPUs with the mm active.  The LDT will not be freed until
+	 * after the IPI is handled by all such CPUs.  This means that,
+	 * if the ldt_struct changes before we return, the values we see
+	 * will be safe, and the new values will be loaded before we run
+	 * any user code.
+	 *
+	 * NB: don't try to convert this to use RCU without extreme care.
+	 * We would still need IRQs off, because we don't want to change
+	 * the local LDT after an IPI loaded a newer value than the one
+	 * that we can see.
+	 */
+
+	if (unlikely(ldt))
+		set_ldt(ldt->entries, ldt->size);
+	else
+		clear_LDT();
+
+	DEBUG_LOCKS_WARN_ON(preemptible());
+}
+
 /*
 /*
  * Used for LDT copy/destruction.
  * Used for LDT copy/destruction.
  */
  */
@@ -78,12 +122,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 		 * was called and then modify_ldt changed
 		 * was called and then modify_ldt changed
 		 * prev->context.ldt but suppressed an IPI to this CPU.
 		 * prev->context.ldt but suppressed an IPI to this CPU.
 		 * In this case, prev->context.ldt != NULL, because we
 		 * In this case, prev->context.ldt != NULL, because we
-		 * never free an LDT while the mm still exists.  That
-		 * means that next->context.ldt != prev->context.ldt,
-		 * because mms never share an LDT.
+		 * never set context.ldt to NULL while the mm still
+		 * exists.  That means that next->context.ldt !=
+		 * prev->context.ldt, because mms never share an LDT.
 		 */
 		 */
 		if (unlikely(prev->context.ldt != next->context.ldt))
 		if (unlikely(prev->context.ldt != next->context.ldt))
-			load_LDT_nolock(&next->context);
+			load_mm_ldt(next);
 	}
 	}
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
 	  else {
 	  else {
@@ -106,7 +150,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			load_cr3(next->pgd);
 			load_cr3(next->pgd);
 			trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
 			trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
 			load_mm_cr4(next);
 			load_mm_cr4(next);
-			load_LDT_nolock(&next->context);
+			load_mm_ldt(next);
 		}
 		}
 	}
 	}
 #endif
 #endif

+ 1 - 1
arch/x86/kernel/apic/io_apic.c

@@ -943,7 +943,7 @@ static bool mp_check_pin_attr(int irq, struct irq_alloc_info *info)
 	 */
 	 */
 	if (irq < nr_legacy_irqs() && data->count == 1) {
 	if (irq < nr_legacy_irqs() && data->count == 1) {
 		if (info->ioapic_trigger != data->trigger)
 		if (info->ioapic_trigger != data->trigger)
-			mp_register_handler(irq, data->trigger);
+			mp_register_handler(irq, info->ioapic_trigger);
 		data->entry.trigger = data->trigger = info->ioapic_trigger;
 		data->entry.trigger = data->trigger = info->ioapic_trigger;
 		data->entry.polarity = data->polarity = info->ioapic_polarity;
 		data->entry.polarity = data->polarity = info->ioapic_polarity;
 	}
 	}

+ 2 - 2
arch/x86/kernel/cpu/common.c

@@ -1410,7 +1410,7 @@ void cpu_init(void)
 	load_sp0(t, &current->thread);
 	load_sp0(t, &current->thread);
 	set_tss_desc(cpu, t);
 	set_tss_desc(cpu, t);
 	load_TR_desc();
 	load_TR_desc();
-	load_LDT(&init_mm.context);
+	load_mm_ldt(&init_mm);
 
 
 	clear_all_debug_regs();
 	clear_all_debug_regs();
 	dbg_restore_debug_regs();
 	dbg_restore_debug_regs();
@@ -1459,7 +1459,7 @@ void cpu_init(void)
 	load_sp0(t, thread);
 	load_sp0(t, thread);
 	set_tss_desc(cpu, t);
 	set_tss_desc(cpu, t);
 	load_TR_desc();
 	load_TR_desc();
-	load_LDT(&init_mm.context);
+	load_mm_ldt(&init_mm);
 
 
 	t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
 	t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
 
 

+ 8 - 4
arch/x86/kernel/cpu/perf_event.c

@@ -2179,21 +2179,25 @@ static unsigned long get_segment_base(unsigned int segment)
 	int idx = segment >> 3;
 	int idx = segment >> 3;
 
 
 	if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
 	if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
+		struct ldt_struct *ldt;
+
 		if (idx > LDT_ENTRIES)
 		if (idx > LDT_ENTRIES)
 			return 0;
 			return 0;
 
 
-		if (idx > current->active_mm->context.size)
+		/* IRQs are off, so this synchronizes with smp_store_release */
+		ldt = lockless_dereference(current->active_mm->context.ldt);
+		if (!ldt || idx > ldt->size)
 			return 0;
 			return 0;
 
 
-		desc = current->active_mm->context.ldt;
+		desc = &ldt->entries[idx];
 	} else {
 	} else {
 		if (idx > GDT_ENTRIES)
 		if (idx > GDT_ENTRIES)
 			return 0;
 			return 0;
 
 
-		desc = raw_cpu_ptr(gdt_page.gdt);
+		desc = raw_cpu_ptr(gdt_page.gdt) + idx;
 	}
 	}
 
 
-	return get_desc_base(desc + idx);
+	return get_desc_base(desc);
 }
 }
 
 
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT

+ 142 - 120
arch/x86/kernel/ldt.c

@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
 
 
@@ -20,82 +21,82 @@
 #include <asm/mmu_context.h>
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
 #include <asm/syscalls.h>
 
 
-#ifdef CONFIG_SMP
+/* context.lock is held for us, so we don't need any locking. */
 static void flush_ldt(void *current_mm)
 static void flush_ldt(void *current_mm)
 {
 {
-	if (current->active_mm == current_mm)
-		load_LDT(&current->active_mm->context);
+	mm_context_t *pc;
+
+	if (current->active_mm != current_mm)
+		return;
+
+	pc = &current->active_mm->context;
+	set_ldt(pc->ldt->entries, pc->ldt->size);
 }
 }
-#endif
 
 
-static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+/* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */
+static struct ldt_struct *alloc_ldt_struct(int size)
 {
 {
-	void *oldldt, *newldt;
-	int oldsize;
-
-	if (mincount <= pc->size)
-		return 0;
-	oldsize = pc->size;
-	mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
-			(~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
-	if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
-		newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
+	struct ldt_struct *new_ldt;
+	int alloc_size;
+
+	if (size > LDT_ENTRIES)
+		return NULL;
+
+	new_ldt = kmalloc(sizeof(struct ldt_struct), GFP_KERNEL);
+	if (!new_ldt)
+		return NULL;
+
+	BUILD_BUG_ON(LDT_ENTRY_SIZE != sizeof(struct desc_struct));
+	alloc_size = size * LDT_ENTRY_SIZE;
+
+	/*
+	 * Xen is very picky: it requires a page-aligned LDT that has no
+	 * trailing nonzero bytes in any page that contains LDT descriptors.
+	 * Keep it simple: zero the whole allocation and never allocate less
+	 * than PAGE_SIZE.
+	 */
+	if (alloc_size > PAGE_SIZE)
+		new_ldt->entries = vzalloc(alloc_size);
 	else
 	else
-		newldt = (void *)__get_free_page(GFP_KERNEL);
-
-	if (!newldt)
-		return -ENOMEM;
+		new_ldt->entries = kzalloc(PAGE_SIZE, GFP_KERNEL);
 
 
-	if (oldsize)
-		memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE);
-	oldldt = pc->ldt;
-	memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
-	       (mincount - oldsize) * LDT_ENTRY_SIZE);
+	if (!new_ldt->entries) {
+		kfree(new_ldt);
+		return NULL;
+	}
 
 
-	paravirt_alloc_ldt(newldt, mincount);
+	new_ldt->size = size;
+	return new_ldt;
+}
 
 
-#ifdef CONFIG_X86_64
-	/* CHECKME: Do we really need this ? */
-	wmb();
-#endif
-	pc->ldt = newldt;
-	wmb();
-	pc->size = mincount;
-	wmb();
-
-	if (reload) {
-#ifdef CONFIG_SMP
-		preempt_disable();
-		load_LDT(pc);
-		if (!cpumask_equal(mm_cpumask(current->mm),
-				   cpumask_of(smp_processor_id())))
-			smp_call_function(flush_ldt, current->mm, 1);
-		preempt_enable();
-#else
-		load_LDT(pc);
-#endif
-	}
-	if (oldsize) {
-		paravirt_free_ldt(oldldt, oldsize);
-		if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
-			vfree(oldldt);
-		else
-			put_page(virt_to_page(oldldt));
-	}
-	return 0;
+/* After calling this, the LDT is immutable. */
+static void finalize_ldt_struct(struct ldt_struct *ldt)
+{
+	paravirt_alloc_ldt(ldt->entries, ldt->size);
 }
 }
 
 
-static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+/* context.lock is held */
+static void install_ldt(struct mm_struct *current_mm,
+			struct ldt_struct *ldt)
 {
 {
-	int err = alloc_ldt(new, old->size, 0);
-	int i;
+	/* Synchronizes with lockless_dereference in load_mm_ldt. */
+	smp_store_release(&current_mm->context.ldt, ldt);
+
+	/* Activate the LDT for all CPUs using current_mm. */
+	on_each_cpu_mask(mm_cpumask(current_mm), flush_ldt, current_mm, true);
+}
 
 
-	if (err < 0)
-		return err;
+static void free_ldt_struct(struct ldt_struct *ldt)
+{
+	if (likely(!ldt))
+		return;
 
 
-	for (i = 0; i < old->size; i++)
-		write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
-	return 0;
+	paravirt_free_ldt(ldt->entries, ldt->size);
+	if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
+		vfree(ldt->entries);
+	else
+		kfree(ldt->entries);
+	kfree(ldt);
 }
 }
 
 
 /*
 /*
@@ -104,17 +105,37 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
  */
  */
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
 {
+	struct ldt_struct *new_ldt;
 	struct mm_struct *old_mm;
 	struct mm_struct *old_mm;
 	int retval = 0;
 	int retval = 0;
 
 
 	mutex_init(&mm->context.lock);
 	mutex_init(&mm->context.lock);
-	mm->context.size = 0;
 	old_mm = current->mm;
 	old_mm = current->mm;
-	if (old_mm && old_mm->context.size > 0) {
-		mutex_lock(&old_mm->context.lock);
-		retval = copy_ldt(&mm->context, &old_mm->context);
-		mutex_unlock(&old_mm->context.lock);
+	if (!old_mm) {
+		mm->context.ldt = NULL;
+		return 0;
 	}
 	}
+
+	mutex_lock(&old_mm->context.lock);
+	if (!old_mm->context.ldt) {
+		mm->context.ldt = NULL;
+		goto out_unlock;
+	}
+
+	new_ldt = alloc_ldt_struct(old_mm->context.ldt->size);
+	if (!new_ldt) {
+		retval = -ENOMEM;
+		goto out_unlock;
+	}
+
+	memcpy(new_ldt->entries, old_mm->context.ldt->entries,
+	       new_ldt->size * LDT_ENTRY_SIZE);
+	finalize_ldt_struct(new_ldt);
+
+	mm->context.ldt = new_ldt;
+
+out_unlock:
+	mutex_unlock(&old_mm->context.lock);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -125,53 +146,47 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
  */
  */
 void destroy_context(struct mm_struct *mm)
 void destroy_context(struct mm_struct *mm)
 {
 {
-	if (mm->context.size) {
-#ifdef CONFIG_X86_32
-		/* CHECKME: Can this ever happen ? */
-		if (mm == current->active_mm)
-			clear_LDT();
-#endif
-		paravirt_free_ldt(mm->context.ldt, mm->context.size);
-		if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
-			vfree(mm->context.ldt);
-		else
-			put_page(virt_to_page(mm->context.ldt));
-		mm->context.size = 0;
-	}
+	free_ldt_struct(mm->context.ldt);
+	mm->context.ldt = NULL;
 }
 }
 
 
 static int read_ldt(void __user *ptr, unsigned long bytecount)
 static int read_ldt(void __user *ptr, unsigned long bytecount)
 {
 {
-	int err;
+	int retval;
 	unsigned long size;
 	unsigned long size;
 	struct mm_struct *mm = current->mm;
 	struct mm_struct *mm = current->mm;
 
 
-	if (!mm->context.size)
-		return 0;
+	mutex_lock(&mm->context.lock);
+
+	if (!mm->context.ldt) {
+		retval = 0;
+		goto out_unlock;
+	}
+
 	if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
 	if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
 		bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
 		bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
 
 
-	mutex_lock(&mm->context.lock);
-	size = mm->context.size * LDT_ENTRY_SIZE;
+	size = mm->context.ldt->size * LDT_ENTRY_SIZE;
 	if (size > bytecount)
 	if (size > bytecount)
 		size = bytecount;
 		size = bytecount;
 
 
-	err = 0;
-	if (copy_to_user(ptr, mm->context.ldt, size))
-		err = -EFAULT;
-	mutex_unlock(&mm->context.lock);
-	if (err < 0)
-		goto error_return;
+	if (copy_to_user(ptr, mm->context.ldt->entries, size)) {
+		retval = -EFAULT;
+		goto out_unlock;
+	}
+
 	if (size != bytecount) {
 	if (size != bytecount) {
-		/* zero-fill the rest */
-		if (clear_user(ptr + size, bytecount - size) != 0) {
-			err = -EFAULT;
-			goto error_return;
+		/* Zero-fill the rest and pretend we read bytecount bytes. */
+		if (clear_user(ptr + size, bytecount - size)) {
+			retval = -EFAULT;
+			goto out_unlock;
 		}
 		}
 	}
 	}
-	return bytecount;
-error_return:
-	return err;
+	retval = bytecount;
+
+out_unlock:
+	mutex_unlock(&mm->context.lock);
+	return retval;
 }
 }
 
 
 static int read_default_ldt(void __user *ptr, unsigned long bytecount)
 static int read_default_ldt(void __user *ptr, unsigned long bytecount)
@@ -195,6 +210,8 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
 	struct desc_struct ldt;
 	struct desc_struct ldt;
 	int error;
 	int error;
 	struct user_desc ldt_info;
 	struct user_desc ldt_info;
+	int oldsize, newsize;
+	struct ldt_struct *new_ldt, *old_ldt;
 
 
 	error = -EINVAL;
 	error = -EINVAL;
 	if (bytecount != sizeof(ldt_info))
 	if (bytecount != sizeof(ldt_info))
@@ -213,34 +230,39 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
 			goto out;
 			goto out;
 	}
 	}
 
 
-	mutex_lock(&mm->context.lock);
-	if (ldt_info.entry_number >= mm->context.size) {
-		error = alloc_ldt(&current->mm->context,
-				  ldt_info.entry_number + 1, 1);
-		if (error < 0)
-			goto out_unlock;
-	}
-
-	/* Allow LDTs to be cleared by the user. */
-	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
-		if (oldmode || LDT_empty(&ldt_info)) {
-			memset(&ldt, 0, sizeof(ldt));
-			goto install;
+	if ((oldmode && !ldt_info.base_addr && !ldt_info.limit) ||
+	    LDT_empty(&ldt_info)) {
+		/* The user wants to clear the entry. */
+		memset(&ldt, 0, sizeof(ldt));
+	} else {
+		if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
+			error = -EINVAL;
+			goto out;
 		}
 		}
+
+		fill_ldt(&ldt, &ldt_info);
+		if (oldmode)
+			ldt.avl = 0;
 	}
 	}
 
 
-	if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
-		error = -EINVAL;
+	mutex_lock(&mm->context.lock);
+
+	old_ldt = mm->context.ldt;
+	oldsize = old_ldt ? old_ldt->size : 0;
+	newsize = max((int)(ldt_info.entry_number + 1), oldsize);
+
+	error = -ENOMEM;
+	new_ldt = alloc_ldt_struct(newsize);
+	if (!new_ldt)
 		goto out_unlock;
 		goto out_unlock;
-	}
 
 
-	fill_ldt(&ldt, &ldt_info);
-	if (oldmode)
-		ldt.avl = 0;
+	if (old_ldt)
+		memcpy(new_ldt->entries, old_ldt->entries, oldsize * LDT_ENTRY_SIZE);
+	new_ldt->entries[ldt_info.entry_number] = ldt;
+	finalize_ldt_struct(new_ldt);
 
 
-	/* Install the new entry ...  */
-install:
-	write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
+	install_ldt(mm, new_ldt);
+	free_ldt_struct(old_ldt);
 	error = 0;
 	error = 0;
 
 
 out_unlock:
 out_unlock:

+ 2 - 2
arch/x86/kernel/process_64.c

@@ -121,11 +121,11 @@ void __show_regs(struct pt_regs *regs, int all)
 void release_thread(struct task_struct *dead_task)
 void release_thread(struct task_struct *dead_task)
 {
 {
 	if (dead_task->mm) {
 	if (dead_task->mm) {
-		if (dead_task->mm->context.size) {
+		if (dead_task->mm->context.ldt) {
 			pr_warn("WARNING: dead process %s still has LDT? <%p/%d>\n",
 			pr_warn("WARNING: dead process %s still has LDT? <%p/%d>\n",
 				dead_task->comm,
 				dead_task->comm,
 				dead_task->mm->context.ldt,
 				dead_task->mm->context.ldt,
-				dead_task->mm->context.size);
+				dead_task->mm->context.ldt->size);
 			BUG();
 			BUG();
 		}
 		}
 	}
 	}

+ 4 - 2
arch/x86/kernel/step.c

@@ -5,6 +5,7 @@
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/ptrace.h>
 #include <linux/ptrace.h>
 #include <asm/desc.h>
 #include <asm/desc.h>
+#include <asm/mmu_context.h>
 
 
 unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs)
 unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs)
 {
 {
@@ -30,10 +31,11 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re
 		seg &= ~7UL;
 		seg &= ~7UL;
 
 
 		mutex_lock(&child->mm->context.lock);
 		mutex_lock(&child->mm->context.lock);
-		if (unlikely((seg >> 3) >= child->mm->context.size))
+		if (unlikely(!child->mm->context.ldt ||
+			     (seg >> 3) >= child->mm->context.ldt->size))
 			addr = -1L; /* bogus selector, access would fault */
 			addr = -1L; /* bogus selector, access would fault */
 		else {
 		else {
-			desc = child->mm->context.ldt + seg;
+			desc = &child->mm->context.ldt->entries[seg];
 			base = get_desc_base(desc);
 			base = get_desc_base(desc);
 
 
 			/* 16-bit code segment? */
 			/* 16-bit code segment? */

+ 4 - 4
arch/x86/net/bpf_jit_comp.c

@@ -269,7 +269,7 @@ static void emit_bpf_tail_call(u8 **pprog)
 	EMIT4(0x48, 0x8B, 0x46,                   /* mov rax, qword ptr [rsi + 16] */
 	EMIT4(0x48, 0x8B, 0x46,                   /* mov rax, qword ptr [rsi + 16] */
 	      offsetof(struct bpf_array, map.max_entries));
 	      offsetof(struct bpf_array, map.max_entries));
 	EMIT3(0x48, 0x39, 0xD0);                  /* cmp rax, rdx */
 	EMIT3(0x48, 0x39, 0xD0);                  /* cmp rax, rdx */
-#define OFFSET1 44 /* number of bytes to jump */
+#define OFFSET1 47 /* number of bytes to jump */
 	EMIT2(X86_JBE, OFFSET1);                  /* jbe out */
 	EMIT2(X86_JBE, OFFSET1);                  /* jbe out */
 	label1 = cnt;
 	label1 = cnt;
 
 
@@ -278,15 +278,15 @@ static void emit_bpf_tail_call(u8 **pprog)
 	 */
 	 */
 	EMIT2_off32(0x8B, 0x85, -STACKSIZE + 36); /* mov eax, dword ptr [rbp - 516] */
 	EMIT2_off32(0x8B, 0x85, -STACKSIZE + 36); /* mov eax, dword ptr [rbp - 516] */
 	EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT);     /* cmp eax, MAX_TAIL_CALL_CNT */
 	EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT);     /* cmp eax, MAX_TAIL_CALL_CNT */
-#define OFFSET2 33
+#define OFFSET2 36
 	EMIT2(X86_JA, OFFSET2);                   /* ja out */
 	EMIT2(X86_JA, OFFSET2);                   /* ja out */
 	label2 = cnt;
 	label2 = cnt;
 	EMIT3(0x83, 0xC0, 0x01);                  /* add eax, 1 */
 	EMIT3(0x83, 0xC0, 0x01);                  /* add eax, 1 */
 	EMIT2_off32(0x89, 0x85, -STACKSIZE + 36); /* mov dword ptr [rbp - 516], eax */
 	EMIT2_off32(0x89, 0x85, -STACKSIZE + 36); /* mov dword ptr [rbp - 516], eax */
 
 
 	/* prog = array->prog[index]; */
 	/* prog = array->prog[index]; */
-	EMIT4(0x48, 0x8D, 0x44, 0xD6);            /* lea rax, [rsi + rdx * 8 + 0x50] */
-	EMIT1(offsetof(struct bpf_array, prog));
+	EMIT4_off32(0x48, 0x8D, 0x84, 0xD6,       /* lea rax, [rsi + rdx * 8 + offsetof(...)] */
+		    offsetof(struct bpf_array, prog));
 	EMIT3(0x48, 0x8B, 0x00);                  /* mov rax, qword ptr [rax] */
 	EMIT3(0x48, 0x8B, 0x00);                  /* mov rax, qword ptr [rax] */
 
 
 	/* if (prog == NULL)
 	/* if (prog == NULL)

+ 5 - 0
arch/x86/platform/efi/efi.c

@@ -972,6 +972,11 @@ u64 efi_mem_attributes(unsigned long phys_addr)
 
 
 static int __init arch_parse_efi_cmdline(char *str)
 static int __init arch_parse_efi_cmdline(char *str)
 {
 {
+	if (!str) {
+		pr_warn("need at least one option\n");
+		return -EINVAL;
+	}
+
 	if (parse_option_str(str, "old_map"))
 	if (parse_option_str(str, "old_map"))
 		set_bit(EFI_OLD_MEMMAP, &efi.flags);
 		set_bit(EFI_OLD_MEMMAP, &efi.flags);
 	if (parse_option_str(str, "debug"))
 	if (parse_option_str(str, "debug"))

+ 2 - 1
arch/x86/power/cpu.c

@@ -22,6 +22,7 @@
 #include <asm/fpu/internal.h>
 #include <asm/fpu/internal.h>
 #include <asm/debugreg.h>
 #include <asm/debugreg.h>
 #include <asm/cpu.h>
 #include <asm/cpu.h>
+#include <asm/mmu_context.h>
 
 
 #ifdef CONFIG_X86_32
 #ifdef CONFIG_X86_32
 __visible unsigned long saved_context_ebx;
 __visible unsigned long saved_context_ebx;
@@ -153,7 +154,7 @@ static void fix_processor_context(void)
 	syscall_init();				/* This sets MSR_*STAR and related */
 	syscall_init();				/* This sets MSR_*STAR and related */
 #endif
 #endif
 	load_TR_desc();				/* This does ltr */
 	load_TR_desc();				/* This does ltr */
-	load_LDT(&current->active_mm->context);	/* This does lldt */
+	load_mm_ldt(current->active_mm);	/* This does lldt */
 
 
 	fpu__resume_cpu();
 	fpu__resume_cpu();
 }
 }

+ 40 - 0
arch/x86/xen/enlighten.c

@@ -483,6 +483,7 @@ static void set_aliased_prot(void *v, pgprot_t prot)
 	pte_t pte;
 	pte_t pte;
 	unsigned long pfn;
 	unsigned long pfn;
 	struct page *page;
 	struct page *page;
+	unsigned char dummy;
 
 
 	ptep = lookup_address((unsigned long)v, &level);
 	ptep = lookup_address((unsigned long)v, &level);
 	BUG_ON(ptep == NULL);
 	BUG_ON(ptep == NULL);
@@ -492,6 +493,32 @@ static void set_aliased_prot(void *v, pgprot_t prot)
 
 
 	pte = pfn_pte(pfn, prot);
 	pte = pfn_pte(pfn, prot);
 
 
+	/*
+	 * Careful: update_va_mapping() will fail if the virtual address
+	 * we're poking isn't populated in the page tables.  We don't
+	 * need to worry about the direct map (that's always in the page
+	 * tables), but we need to be careful about vmap space.  In
+	 * particular, the top level page table can lazily propagate
+	 * entries between processes, so if we've switched mms since we
+	 * vmapped the target in the first place, we might not have the
+	 * top-level page table entry populated.
+	 *
+	 * We disable preemption because we want the same mm active when
+	 * we probe the target and when we issue the hypercall.  We'll
+	 * have the same nominal mm, but if we're a kernel thread, lazy
+	 * mm dropping could change our pgd.
+	 *
+	 * Out of an abundance of caution, this uses __get_user() to fault
+	 * in the target address just in case there's some obscure case
+	 * in which the target address isn't readable.
+	 */
+
+	preempt_disable();
+
+	pagefault_disable();	/* Avoid warnings due to being atomic. */
+	__get_user(dummy, (unsigned char __user __force *)v);
+	pagefault_enable();
+
 	if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
 	if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
 		BUG();
 		BUG();
 
 
@@ -503,6 +530,8 @@ static void set_aliased_prot(void *v, pgprot_t prot)
 				BUG();
 				BUG();
 	} else
 	} else
 		kmap_flush_unused();
 		kmap_flush_unused();
+
+	preempt_enable();
 }
 }
 
 
 static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
 static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
@@ -510,6 +539,17 @@ static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
 	const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
 	const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
 	int i;
 	int i;
 
 
+	/*
+	 * We need to mark the all aliases of the LDT pages RO.  We
+	 * don't need to call vm_flush_aliases(), though, since that's
+	 * only responsible for flushing aliases out the TLBs, not the
+	 * page tables, and Xen will flush the TLB for us if needed.
+	 *
+	 * To avoid confusing future readers: none of this is necessary
+	 * to load the LDT.  The hypervisor only checks this when the
+	 * LDT is faulted in due to subsequent descriptor access.
+	 */
+
 	for(i = 0; i < entries; i += entries_per_page)
 	for(i = 0; i < entries; i += entries_per_page)
 		set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
 		set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
 }
 }

+ 1 - 1
drivers/acpi/device_pm.c

@@ -231,7 +231,7 @@ int acpi_device_set_power(struct acpi_device *device, int state)
 		dev_warn(&device->dev, "Failed to change power state to %s\n",
 		dev_warn(&device->dev, "Failed to change power state to %s\n",
 			 acpi_power_state_string(state));
 			 acpi_power_state_string(state));
 	} else {
 	} else {
-		device->power.state = state;
+		device->power.state = target_state;
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Device [%s] transitioned to %s\n",
 				  "Device [%s] transitioned to %s\n",
 				  device->pnp.bus_id,
 				  device->pnp.bus_id,

+ 868 - 227
drivers/base/power/opp.c

@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  * published by the Free Software Foundation.
  */
  */
 
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/err.h>
@@ -51,10 +52,17 @@
  *		order.
  *		order.
  * @dynamic:	not-created from static DT entries.
  * @dynamic:	not-created from static DT entries.
  * @available:	true/false - marks if this OPP as available or not
  * @available:	true/false - marks if this OPP as available or not
+ * @turbo:	true if turbo (boost) OPP
  * @rate:	Frequency in hertz
  * @rate:	Frequency in hertz
- * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ * @u_volt:	Target voltage in microvolts corresponding to this OPP
+ * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
+ * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
+ * @u_amp:	Maximum current drawn by the device in microamperes
+ * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
+ *		frequency from any other OPP's frequency.
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @rcu_head:	RCU callback head used for deferred freeing
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @np:		OPP's device node.
  *
  *
  * This structure stores the OPP information for a given device.
  * This structure stores the OPP information for a given device.
  */
  */
@@ -63,11 +71,34 @@ struct dev_pm_opp {
 
 
 	bool available;
 	bool available;
 	bool dynamic;
 	bool dynamic;
+	bool turbo;
 	unsigned long rate;
 	unsigned long rate;
+
 	unsigned long u_volt;
 	unsigned long u_volt;
+	unsigned long u_volt_min;
+	unsigned long u_volt_max;
+	unsigned long u_amp;
+	unsigned long clock_latency_ns;
 
 
 	struct device_opp *dev_opp;
 	struct device_opp *dev_opp;
 	struct rcu_head rcu_head;
 	struct rcu_head rcu_head;
+
+	struct device_node *np;
+};
+
+/**
+ * struct device_list_opp - devices managed by 'struct device_opp'
+ * @node:	list node
+ * @dev:	device to which the struct object belongs
+ * @rcu_head:	RCU callback head used for deferred freeing
+ *
+ * This is an internal data structure maintaining the list of devices that are
+ * managed by 'struct device_opp'.
+ */
+struct device_list_opp {
+	struct list_head node;
+	const struct device *dev;
+	struct rcu_head rcu_head;
 };
 };
 
 
 /**
 /**
@@ -77,10 +108,12 @@ struct dev_pm_opp {
  *		list.
  *		list.
  *		RCU usage: nodes are not modified in the list of device_opp,
  *		RCU usage: nodes are not modified in the list of device_opp,
  *		however addition is possible and is secured by dev_opp_list_lock
  *		however addition is possible and is secured by dev_opp_list_lock
- * @dev:	device pointer
  * @srcu_head:	notifier head to notify the OPP availability changes.
  * @srcu_head:	notifier head to notify the OPP availability changes.
  * @rcu_head:	RCU callback head used for deferred freeing
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @dev_list:	list of devices that share these OPPs
  * @opp_list:	list of opps
  * @opp_list:	list of opps
+ * @np:		struct device_node pointer for opp's DT node.
+ * @shared_opp: OPP is shared between multiple devices.
  *
  *
  * This is an internal data structure maintaining the link to opps attached to
  * This is an internal data structure maintaining the link to opps attached to
  * a device. This structure is not meant to be shared to users as it is
  * a device. This structure is not meant to be shared to users as it is
@@ -93,10 +126,15 @@ struct dev_pm_opp {
 struct device_opp {
 struct device_opp {
 	struct list_head node;
 	struct list_head node;
 
 
-	struct device *dev;
 	struct srcu_notifier_head srcu_head;
 	struct srcu_notifier_head srcu_head;
 	struct rcu_head rcu_head;
 	struct rcu_head rcu_head;
+	struct list_head dev_list;
 	struct list_head opp_list;
 	struct list_head opp_list;
+
+	struct device_node *np;
+	unsigned long clock_latency_ns_max;
+	bool shared_opp;
+	struct dev_pm_opp *suspend_opp;
 };
 };
 
 
 /*
 /*
@@ -116,6 +154,38 @@ do {									\
 			   "dev_opp_list_lock protection");		\
 			   "dev_opp_list_lock protection");		\
 } while (0)
 } while (0)
 
 
+static struct device_list_opp *_find_list_dev(const struct device *dev,
+					      struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_for_each_entry(list_dev, &dev_opp->dev_list, node)
+		if (list_dev->dev == dev)
+			return list_dev;
+
+	return NULL;
+}
+
+static struct device_opp *_managed_opp(const struct device_node *np)
+{
+	struct device_opp *dev_opp;
+
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node) {
+		if (dev_opp->np == np) {
+			/*
+			 * Multiple devices can point to the same OPP table and
+			 * so will have same node-pointer, np.
+			 *
+			 * But the OPPs will be considered as shared only if the
+			 * OPP table contains a "opp-shared" property.
+			 */
+			return dev_opp->shared_opp ? dev_opp : NULL;
+		}
+	}
+
+	return NULL;
+}
+
 /**
 /**
  * _find_device_opp() - find device_opp struct using device pointer
  * _find_device_opp() - find device_opp struct using device pointer
  * @dev:	device pointer used to lookup device OPPs
  * @dev:	device pointer used to lookup device OPPs
@@ -132,21 +202,18 @@ do {									\
  */
  */
 static struct device_opp *_find_device_opp(struct device *dev)
 static struct device_opp *_find_device_opp(struct device *dev)
 {
 {
-	struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+	struct device_opp *dev_opp;
 
 
-	if (unlikely(IS_ERR_OR_NULL(dev))) {
+	if (IS_ERR_OR_NULL(dev)) {
 		pr_err("%s: Invalid parameters\n", __func__);
 		pr_err("%s: Invalid parameters\n", __func__);
 		return ERR_PTR(-EINVAL);
 		return ERR_PTR(-EINVAL);
 	}
 	}
 
 
-	list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
-		if (tmp_dev_opp->dev == dev) {
-			dev_opp = tmp_dev_opp;
-			break;
-		}
-	}
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node)
+		if (_find_list_dev(dev, dev_opp))
+			return dev_opp;
 
 
-	return dev_opp;
+	return ERR_PTR(-ENODEV);
 }
 }
 
 
 /**
 /**
@@ -172,7 +239,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
 	opp_rcu_lockdep_assert();
 	opp_rcu_lockdep_assert();
 
 
 	tmp_opp = rcu_dereference(opp);
 	tmp_opp = rcu_dereference(opp);
-	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+	if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available)
 		pr_err("%s: Invalid parameters\n", __func__);
 		pr_err("%s: Invalid parameters\n", __func__);
 	else
 	else
 		v = tmp_opp->u_volt;
 		v = tmp_opp->u_volt;
@@ -204,7 +271,7 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 	opp_rcu_lockdep_assert();
 	opp_rcu_lockdep_assert();
 
 
 	tmp_opp = rcu_dereference(opp);
 	tmp_opp = rcu_dereference(opp);
-	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+	if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available)
 		pr_err("%s: Invalid parameters\n", __func__);
 		pr_err("%s: Invalid parameters\n", __func__);
 	else
 	else
 		f = tmp_opp->rate;
 		f = tmp_opp->rate;
@@ -213,6 +280,66 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 }
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 
+/**
+ * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
+ * @opp: opp for which turbo mode is being verified
+ *
+ * Turbo OPPs are not for normal use, and can be enabled (under certain
+ * conditions) for short duration of times to finish high throughput work
+ * quickly. Running on them for longer times may overheat the chip.
+ *
+ * Return: true if opp is turbo opp, else false.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	struct dev_pm_opp *tmp_opp;
+
+	opp_rcu_lockdep_assert();
+
+	tmp_opp = rcu_dereference(opp);
+	if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return false;
+	}
+
+	return tmp_opp->turbo;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
+
+/**
+ * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
+ * @dev:	device for which we do this operation
+ *
+ * Return: This function returns the max clock latency in nanoseconds.
+ *
+ * Locking: This function takes rcu_read_lock().
+ */
+unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	unsigned long clock_latency_ns;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		clock_latency_ns = 0;
+	else
+		clock_latency_ns = dev_opp->clock_latency_ns_max;
+
+	rcu_read_unlock();
+	return clock_latency_ns;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
+
 /**
 /**
  * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
  * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
  * @dev:	device for which we do this operation
  * @dev:	device for which we do this operation
@@ -407,18 +534,57 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 }
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 
+/* List-dev Helpers */
+static void _kfree_list_dev_rcu(struct rcu_head *head)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = container_of(head, struct device_list_opp, rcu_head);
+	kfree_rcu(list_dev, rcu_head);
+}
+
+static void _remove_list_dev(struct device_list_opp *list_dev,
+			     struct device_opp *dev_opp)
+{
+	list_del(&list_dev->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
+		  _kfree_list_dev_rcu);
+}
+
+static struct device_list_opp *_add_list_dev(const struct device *dev,
+					     struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
+	if (!list_dev)
+		return NULL;
+
+	/* Initialize list-dev */
+	list_dev->dev = dev;
+	list_add_rcu(&list_dev->node, &dev_opp->dev_list);
+
+	return list_dev;
+}
+
 /**
 /**
- * _add_device_opp() - Allocate a new device OPP table
+ * _add_device_opp() - Find device OPP table or allocate a new one
  * @dev:	device for which we do this operation
  * @dev:	device for which we do this operation
  *
  *
- * New device node which uses OPPs - used when multiple devices with OPP tables
- * are maintained.
+ * It tries to find an existing table first, if it couldn't find one, it
+ * allocates a new OPP table and returns that.
  *
  *
  * Return: valid device_opp pointer if success, else NULL.
  * Return: valid device_opp pointer if success, else NULL.
  */
  */
 static struct device_opp *_add_device_opp(struct device *dev)
 static struct device_opp *_add_device_opp(struct device *dev)
 {
 {
 	struct device_opp *dev_opp;
 	struct device_opp *dev_opp;
+	struct device_list_opp *list_dev;
+
+	/* Check for existing list for 'dev' first */
+	dev_opp = _find_device_opp(dev);
+	if (!IS_ERR(dev_opp))
+		return dev_opp;
 
 
 	/*
 	/*
 	 * Allocate a new device OPP table. In the infrequent case where a new
 	 * Allocate a new device OPP table. In the infrequent case where a new
@@ -428,7 +594,14 @@ static struct device_opp *_add_device_opp(struct device *dev)
 	if (!dev_opp)
 	if (!dev_opp)
 		return NULL;
 		return NULL;
 
 
-	dev_opp->dev = dev;
+	INIT_LIST_HEAD(&dev_opp->dev_list);
+
+	list_dev = _add_list_dev(dev, dev_opp);
+	if (!list_dev) {
+		kfree(dev_opp);
+		return NULL;
+	}
+
 	srcu_init_notifier_head(&dev_opp->srcu_head);
 	srcu_init_notifier_head(&dev_opp->srcu_head);
 	INIT_LIST_HEAD(&dev_opp->opp_list);
 	INIT_LIST_HEAD(&dev_opp->opp_list);
 
 
@@ -438,136 +611,41 @@ static struct device_opp *_add_device_opp(struct device *dev)
 }
 }
 
 
 /**
 /**
- * _opp_add_dynamic() - Allocate a dynamic OPP.
- * @dev:	device for which we do this operation
- * @freq:	Frequency in Hz for this OPP
- * @u_volt:	Voltage in uVolts for this OPP
- * @dynamic:	Dynamically added OPPs.
- *
- * This function adds an opp definition to the opp list and returns status.
- * The opp is made available by default and it can be controlled using
- * dev_pm_opp_enable/disable functions and may be removed by dev_pm_opp_remove.
- *
- * NOTE: "dynamic" parameter impacts OPPs added by the of_init_opp_table and
- * freed by of_free_opp_table.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function internally uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
+ * _kfree_device_rcu() - Free device_opp RCU handler
+ * @head:	RCU head
  */
  */
-static int _opp_add_dynamic(struct device *dev, unsigned long freq,
-			    long u_volt, bool dynamic)
+static void _kfree_device_rcu(struct rcu_head *head)
 {
 {
-	struct device_opp *dev_opp = NULL;
-	struct dev_pm_opp *opp, *new_opp;
-	struct list_head *head;
-	int ret;
-
-	/* allocate new OPP node */
-	new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
-	if (!new_opp)
-		return -ENOMEM;
-
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	/* populate the opp table */
-	new_opp->rate = freq;
-	new_opp->u_volt = u_volt;
-	new_opp->available = true;
-	new_opp->dynamic = dynamic;
-
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		dev_opp = _add_device_opp(dev);
-		if (!dev_opp) {
-			ret = -ENOMEM;
-			goto free_opp;
-		}
-
-		head = &dev_opp->opp_list;
-		goto list_add;
-	}
-
-	/*
-	 * Insert new OPP in order of increasing frequency
-	 * and discard if already present
-	 */
-	head = &dev_opp->opp_list;
-	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
-		if (new_opp->rate <= opp->rate)
-			break;
-		else
-			head = &opp->node;
-	}
-
-	/* Duplicate OPPs ? */
-	if (new_opp->rate == opp->rate) {
-		ret = opp->available && new_opp->u_volt == opp->u_volt ?
-			0 : -EEXIST;
-
-		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
-			 __func__, opp->rate, opp->u_volt, opp->available,
-			 new_opp->rate, new_opp->u_volt, new_opp->available);
-		goto free_opp;
-	}
-
-list_add:
-	new_opp->dev_opp = dev_opp;
-	list_add_rcu(&new_opp->node, head);
-	mutex_unlock(&dev_opp_list_lock);
-
-	/*
-	 * Notify the changes in the availability of the operable
-	 * frequency/voltage list.
-	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
-	return 0;
+	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
 
 
-free_opp:
-	mutex_unlock(&dev_opp_list_lock);
-	kfree(new_opp);
-	return ret;
+	kfree_rcu(device_opp, rcu_head);
 }
 }
 
 
 /**
 /**
- * dev_pm_opp_add()  - Add an OPP table from a table definitions
- * @dev:	device for which we do this operation
- * @freq:	Frequency in Hz for this OPP
- * @u_volt:	Voltage in uVolts for this OPP
- *
- * This function adds an opp definition to the opp list and returns status.
- * The opp is made available by default and it can be controlled using
- * dev_pm_opp_enable/disable functions.
+ * _remove_device_opp() - Removes a device OPP table
+ * @dev_opp: device OPP table to be removed.
  *
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function internally uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
+ * Removes/frees device OPP table it it doesn't contain any OPPs.
  */
  */
-int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+static void _remove_device_opp(struct device_opp *dev_opp)
 {
 {
-	return _opp_add_dynamic(dev, freq, u_volt, true);
+	struct device_list_opp *list_dev;
+
+	if (!list_empty(&dev_opp->opp_list))
+		return;
+
+	list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp,
+				    node);
+
+	_remove_list_dev(list_dev, dev_opp);
+
+	/* dev_list must be empty now */
+	WARN_ON(!list_empty(&dev_opp->dev_list));
+
+	list_del_rcu(&dev_opp->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+		  _kfree_device_rcu);
 }
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 
 
 /**
 /**
  * _kfree_opp_rcu() - Free OPP RCU handler
  * _kfree_opp_rcu() - Free OPP RCU handler
@@ -580,21 +658,11 @@ static void _kfree_opp_rcu(struct rcu_head *head)
 	kfree_rcu(opp, rcu_head);
 	kfree_rcu(opp, rcu_head);
 }
 }
 
 
-/**
- * _kfree_device_rcu() - Free device_opp RCU handler
- * @head:	RCU head
- */
-static void _kfree_device_rcu(struct rcu_head *head)
-{
-	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
-
-	kfree_rcu(device_opp, rcu_head);
-}
-
 /**
 /**
  * _opp_remove()  - Remove an OPP from a table definition
  * _opp_remove()  - Remove an OPP from a table definition
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @opp:	pointer to the OPP to remove
  * @opp:	pointer to the OPP to remove
+ * @notify:	OPP_EVENT_REMOVE notification should be sent or not
  *
  *
  * This function removes an opp definition from the opp list.
  * This function removes an opp definition from the opp list.
  *
  *
@@ -603,21 +671,18 @@ static void _kfree_device_rcu(struct rcu_head *head)
  * strategy.
  * strategy.
  */
  */
 static void _opp_remove(struct device_opp *dev_opp,
 static void _opp_remove(struct device_opp *dev_opp,
-			struct dev_pm_opp *opp)
+			struct dev_pm_opp *opp, bool notify)
 {
 {
 	/*
 	/*
 	 * Notify the changes in the availability of the operable
 	 * Notify the changes in the availability of the operable
 	 * frequency/voltage list.
 	 * frequency/voltage list.
 	 */
 	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+	if (notify)
+		srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
 	list_del_rcu(&opp->node);
 	list_del_rcu(&opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
 
-	if (list_empty(&dev_opp->opp_list)) {
-		list_del_rcu(&dev_opp->node);
-		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
-			  _kfree_device_rcu);
-	}
+	_remove_device_opp(dev_opp);
 }
 }
 
 
 /**
 /**
@@ -659,51 +724,346 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 		goto unlock;
 		goto unlock;
 	}
 	}
 
 
-	_opp_remove(dev_opp, opp);
+	_opp_remove(dev_opp, opp, true);
 unlock:
 unlock:
 	mutex_unlock(&dev_opp_list_lock);
 	mutex_unlock(&dev_opp_list_lock);
 }
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
 
-/**
- * _opp_set_availability() - helper to set the availability of an opp
- * @dev:		device for which we do this operation
- * @freq:		OPP frequency to modify availability
- * @availability_req:	availability status requested for this opp
- *
- * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
- * share a common logic which is isolated here.
- *
- * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
- * copy operation, returns 0 if no modifcation was done OR modification was
- * successful.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function internally uses RCU updater strategy with mutex locks to
- * keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex locking or synchronize_rcu() blocking calls cannot be used.
- */
-static int _opp_set_availability(struct device *dev, unsigned long freq,
-				 bool availability_req)
+static struct dev_pm_opp *_allocate_opp(struct device *dev,
+					struct device_opp **dev_opp)
 {
 {
-	struct device_opp *dev_opp;
-	struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
-	int r = 0;
+	struct dev_pm_opp *opp;
 
 
-	/* keep the node allocated */
-	new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
-	if (!new_opp)
-		return -ENOMEM;
+	/* allocate new OPP node */
+	opp = kzalloc(sizeof(*opp), GFP_KERNEL);
+	if (!opp)
+		return NULL;
 
 
-	mutex_lock(&dev_opp_list_lock);
+	INIT_LIST_HEAD(&opp->node);
 
 
-	/* Find the device_opp */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		r = PTR_ERR(dev_opp);
-		dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
-		goto unlock;
+	*dev_opp = _add_device_opp(dev);
+	if (!*dev_opp) {
+		kfree(opp);
+		return NULL;
+	}
+
+	return opp;
+}
+
+static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
+		    struct device_opp *dev_opp)
+{
+	struct dev_pm_opp *opp;
+	struct list_head *head = &dev_opp->opp_list;
+
+	/*
+	 * Insert new OPP in order of increasing frequency and discard if
+	 * already present.
+	 *
+	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
+	 * loop, don't replace it with head otherwise it will become an infinite
+	 * loop.
+	 */
+	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+		if (new_opp->rate > opp->rate) {
+			head = &opp->node;
+			continue;
+		}
+
+		if (new_opp->rate < opp->rate)
+			break;
+
+		/* Duplicate OPPs */
+		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
+			 __func__, opp->rate, opp->u_volt, opp->available,
+			 new_opp->rate, new_opp->u_volt, new_opp->available);
+
+		return opp->available && new_opp->u_volt == opp->u_volt ?
+			0 : -EEXIST;
+	}
+
+	new_opp->dev_opp = dev_opp;
+	list_add_rcu(&new_opp->node, head);
+
+	return 0;
+}
+
+/**
+ * _opp_add_dynamic() - Allocate a dynamic OPP.
+ * @dev:	device for which we do this operation
+ * @freq:	Frequency in Hz for this OPP
+ * @u_volt:	Voltage in uVolts for this OPP
+ * @dynamic:	Dynamically added OPPs.
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * dev_pm_opp_enable/disable functions and may be removed by dev_pm_opp_remove.
+ *
+ * NOTE: "dynamic" parameter impacts OPPs added by the of_init_opp_table and
+ * freed by of_free_opp_table.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ */
+static int _opp_add_dynamic(struct device *dev, unsigned long freq,
+			    long u_volt, bool dynamic)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *new_opp;
+	int ret;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	/* populate the opp table */
+	new_opp->rate = freq;
+	new_opp->u_volt = u_volt;
+	new_opp->available = true;
+	new_opp->dynamic = dynamic;
+
+	ret = _opp_add(dev, new_opp, dev_opp);
+	if (ret)
+		goto free_opp;
+
+	mutex_unlock(&dev_opp_list_lock);
+
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
+	return 0;
+
+free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+	return ret;
+}
+
+/* TODO: Support multiple regulators */
+static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
+{
+	u32 microvolt[3] = {0};
+	int count, ret;
+
+	count = of_property_count_u32_elems(opp->np, "opp-microvolt");
+	if (!count)
+		return 0;
+
+	/* There can be one or three elements here */
+	if (count != 1 && count != 3) {
+		dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
+			__func__, count);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
+					 count);
+	if (ret) {
+		dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
+			ret);
+		return -EINVAL;
+	}
+
+	opp->u_volt = microvolt[0];
+	opp->u_volt_min = microvolt[1];
+	opp->u_volt_max = microvolt[2];
+
+	return 0;
+}
+
+/**
+ * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
+ * @dev:	device for which we do this operation
+ * @np:		device node
+ *
+ * This function adds an opp definition to the opp list and returns status. The
+ * opp can be controlled using dev_pm_opp_enable/disable functions and may be
+ * removed by dev_pm_opp_remove.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -EINVAL	Failed parsing the OPP node
+ */
+static int _opp_add_static_v2(struct device *dev, struct device_node *np)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *new_opp;
+	u64 rate;
+	u32 val;
+	int ret;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ret = of_property_read_u64(np, "opp-hz", &rate);
+	if (ret < 0) {
+		dev_err(dev, "%s: opp-hz not found\n", __func__);
+		goto free_opp;
+	}
+
+	/*
+	 * Rate is defined as an unsigned long in clk API, and so casting
+	 * explicitly to its type. Must be fixed once rate is 64 bit
+	 * guaranteed in clk API.
+	 */
+	new_opp->rate = (unsigned long)rate;
+	new_opp->turbo = of_property_read_bool(np, "turbo-mode");
+
+	new_opp->np = np;
+	new_opp->dynamic = false;
+	new_opp->available = true;
+
+	if (!of_property_read_u32(np, "clock-latency-ns", &val))
+		new_opp->clock_latency_ns = val;
+
+	ret = opp_get_microvolt(new_opp, dev);
+	if (ret)
+		goto free_opp;
+
+	if (!of_property_read_u32(new_opp->np, "opp-microamp", &val))
+		new_opp->u_amp = val;
+
+	ret = _opp_add(dev, new_opp, dev_opp);
+	if (ret)
+		goto free_opp;
+
+	/* OPP to select on device suspend */
+	if (of_property_read_bool(np, "opp-suspend")) {
+		if (dev_opp->suspend_opp)
+			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
+				 __func__, dev_opp->suspend_opp->rate,
+				 new_opp->rate);
+		else
+			dev_opp->suspend_opp = new_opp;
+	}
+
+	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
+		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
+
+	mutex_unlock(&dev_opp_list_lock);
+
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
+		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
+		 new_opp->u_volt_min, new_opp->u_volt_max,
+		 new_opp->clock_latency_ns);
+
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
+	return 0;
+
+free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+	return ret;
+}
+
+/**
+ * dev_pm_opp_add()  - Add an OPP table from a table definitions
+ * @dev:	device for which we do this operation
+ * @freq:	Frequency in Hz for this OPP
+ * @u_volt:	Voltage in uVolts for this OPP
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * dev_pm_opp_enable/disable functions.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ */
+int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+{
+	return _opp_add_dynamic(dev, freq, u_volt, true);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_add);
+
+/**
+ * _opp_set_availability() - helper to set the availability of an opp
+ * @dev:		device for which we do this operation
+ * @freq:		OPP frequency to modify availability
+ * @availability_req:	availability status requested for this opp
+ *
+ * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
+ * share a common logic which is isolated here.
+ *
+ * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+static int _opp_set_availability(struct device *dev, unsigned long freq,
+				 bool availability_req)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+	int r = 0;
+
+	/* keep the node allocated */
+	new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
+	if (!new_opp)
+		return -ENOMEM;
+
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Find the device_opp */
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		r = PTR_ERR(dev_opp);
+		dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+		goto unlock;
 	}
 	}
 
 
 	/* Do we have the frequency? */
 	/* Do we have the frequency? */
@@ -825,28 +1185,179 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
 
 
 #ifdef CONFIG_OF
 #ifdef CONFIG_OF
 /**
 /**
- * of_init_opp_table() - Initialize opp table from device tree
+ * of_free_opp_table() - Free OPP table entries created from static DT entries
  * @dev:	device pointer used to lookup device OPPs.
  * @dev:	device pointer used to lookup device OPPs.
  *
  *
- * Register the initial OPP table with the OPP library for given device.
+ * Free OPPs created using static entries present in DT.
  *
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function indirectly uses RCU updater strategy with mutex locks
  * Hence this function indirectly uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
  * that this function is *NOT* called under RCU protection or in contexts where
  * mutex cannot be locked.
  * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
- * -ENODEV	when 'operating-points' property is not found or is invalid data
- *		in device node.
- * -ENODATA	when empty 'operating-points' property is found
  */
  */
-int of_init_opp_table(struct device *dev)
+void of_free_opp_table(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *opp, *tmp;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Check for existing list for 'dev' */
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		int error = PTR_ERR(dev_opp);
+
+		if (error != -ENODEV)
+			WARN(1, "%s: dev_opp: %d\n",
+			     IS_ERR_OR_NULL(dev) ?
+					"Invalid device" : dev_name(dev),
+			     error);
+		goto unlock;
+	}
+
+	/* Find if dev_opp manages a single device */
+	if (list_is_singular(&dev_opp->dev_list)) {
+		/* Free static OPPs */
+		list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+			if (!opp->dynamic)
+				_opp_remove(dev_opp, opp, true);
+		}
+	} else {
+		_remove_list_dev(_find_list_dev(dev, dev_opp), dev_opp);
+	}
+
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(of_free_opp_table);
+
+void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		of_free_opp_table(cpu_dev);
+	}
+}
+EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table);
+
+/* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
+static struct device_node *
+_of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
+{
+	struct device_node *opp_np;
+
+	opp_np = of_find_node_by_phandle(be32_to_cpup(prop->value));
+	if (!opp_np) {
+		dev_err(dev, "%s: Prop: %s contains invalid opp desc phandle\n",
+			__func__, prop->name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return opp_np;
+}
+
+/* Returns opp descriptor node for a device. Caller must do of_node_put() */
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
+{
+	const struct property *prop;
+
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop)
+		return ERR_PTR(-ENODEV);
+	if (!prop->value)
+		return ERR_PTR(-ENODATA);
+
+	/*
+	 * TODO: Support for multiple OPP tables.
+	 *
+	 * There should be only ONE phandle present in "operating-points-v2"
+	 * property.
+	 */
+	if (prop->length != sizeof(__be32)) {
+		dev_err(dev, "%s: Invalid opp desc phandle\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return _of_get_opp_desc_node_from_prop(dev, prop);
+}
+
+/* Initializes OPP tables based on new bindings */
+static int _of_init_opp_table_v2(struct device *dev,
+				 const struct property *prop)
+{
+	struct device_node *opp_np, *np;
+	struct device_opp *dev_opp;
+	int ret = 0, count = 0;
+
+	if (!prop->value)
+		return -ENODATA;
+
+	/* Get opp node */
+	opp_np = _of_get_opp_desc_node_from_prop(dev, prop);
+	if (IS_ERR(opp_np))
+		return PTR_ERR(opp_np);
+
+	dev_opp = _managed_opp(opp_np);
+	if (dev_opp) {
+		/* OPPs are already managed */
+		if (!_add_list_dev(dev, dev_opp))
+			ret = -ENOMEM;
+		goto put_opp_np;
+	}
+
+	/* We have opp-list node now, iterate over it and add OPPs */
+	for_each_available_child_of_node(opp_np, np) {
+		count++;
+
+		ret = _opp_add_static_v2(dev, np);
+		if (ret) {
+			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
+				ret);
+			goto free_table;
+		}
+	}
+
+	/* There should be one of more OPP defined */
+	if (WARN_ON(!count)) {
+		ret = -ENOENT;
+		goto put_opp_np;
+	}
+
+	dev_opp = _find_device_opp(dev);
+	if (WARN_ON(IS_ERR(dev_opp))) {
+		ret = PTR_ERR(dev_opp);
+		goto free_table;
+	}
+
+	dev_opp->np = opp_np;
+	dev_opp->shared_opp = of_property_read_bool(opp_np, "opp-shared");
+
+	of_node_put(opp_np);
+	return 0;
+
+free_table:
+	of_free_opp_table(dev);
+put_opp_np:
+	of_node_put(opp_np);
+
+	return ret;
+}
+
+/* Initializes OPP tables based on old-deprecated bindings */
+static int _of_init_opp_table_v1(struct device *dev)
 {
 {
 	const struct property *prop;
 	const struct property *prop;
 	const __be32 *val;
 	const __be32 *val;
@@ -881,47 +1392,177 @@ int of_init_opp_table(struct device *dev)
 
 
 	return 0;
 	return 0;
 }
 }
-EXPORT_SYMBOL_GPL(of_init_opp_table);
 
 
 /**
 /**
- * of_free_opp_table() - Free OPP table entries created from static DT entries
+ * of_init_opp_table() - Initialize opp table from device tree
  * @dev:	device pointer used to lookup device OPPs.
  * @dev:	device pointer used to lookup device OPPs.
  *
  *
- * Free OPPs created using static entries present in DT.
+ * Register the initial OPP table with the OPP library for given device.
  *
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function indirectly uses RCU updater strategy with mutex locks
  * Hence this function indirectly uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
  * that this function is *NOT* called under RCU protection or in contexts where
  * mutex cannot be locked.
  * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -ENODEV	when 'operating-points' property is not found or is invalid data
+ *		in device node.
+ * -ENODATA	when empty 'operating-points' property is found
+ * -EINVAL	when invalid entries are found in opp-v2 table
  */
  */
-void of_free_opp_table(struct device *dev)
+int of_init_opp_table(struct device *dev)
 {
 {
+	const struct property *prop;
+
+	/*
+	 * OPPs have two version of bindings now. The older one is deprecated,
+	 * try for the new binding first.
+	 */
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop) {
+		/*
+		 * Try old-deprecated bindings for backward compatibility with
+		 * older dtbs.
+		 */
+		return _of_init_opp_table_v1(dev);
+	}
+
+	return _of_init_opp_table_v2(dev, prop);
+}
+EXPORT_SYMBOL_GPL(of_init_opp_table);
+
+int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu, ret = 0;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		ret = of_init_opp_table(cpu_dev);
+		if (ret) {
+			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+			       __func__, cpu, ret);
+
+			/* Free all other OPPs */
+			of_cpumask_free_opp_table(cpumask);
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table);
+
+/* Required only for V1 bindings, as v2 can manage it from DT itself */
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_list_opp *list_dev;
 	struct device_opp *dev_opp;
 	struct device_opp *dev_opp;
-	struct dev_pm_opp *opp, *tmp;
+	struct device *dev;
+	int cpu, ret = 0;
 
 
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(cpu_dev);
 	if (IS_ERR(dev_opp)) {
 	if (IS_ERR(dev_opp)) {
-		int error = PTR_ERR(dev_opp);
-		if (error != -ENODEV)
-			WARN(1, "%s: dev_opp: %d\n",
-			     IS_ERR_OR_NULL(dev) ?
-					"Invalid device" : dev_name(dev),
-			     error);
-		return;
+		ret = -EINVAL;
+		goto out_rcu_read_unlock;
 	}
 	}
 
 
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
+	for_each_cpu(cpu, cpumask) {
+		if (cpu == cpu_dev->id)
+			continue;
 
 
-	/* Free static OPPs */
-	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
-		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp);
+		dev = get_cpu_device(cpu);
+		if (!dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+
+		list_dev = _add_list_dev(dev, dev_opp);
+		if (!list_dev) {
+			dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
 	}
 	}
+out_rcu_read_unlock:
+	rcu_read_unlock();
 
 
-	mutex_unlock(&dev_opp_list_lock);
+	return 0;
 }
 }
-EXPORT_SYMBOL_GPL(of_free_opp_table);
+EXPORT_SYMBOL_GPL(set_cpus_sharing_opps);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * cpumask should be already set to mask of cpu_dev->id.
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_node *np, *tmp_np;
+	struct device *tcpu_dev;
+	int cpu, ret = 0;
+
+	/* Get OPP descriptor node */
+	np = _of_get_opp_desc_node(cpu_dev);
+	if (IS_ERR(np)) {
+		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
+			PTR_ERR(np));
+		return -ENOENT;
+	}
+
+	/* OPPs are shared ? */
+	if (!of_property_read_bool(np, "opp-shared"))
+		goto put_cpu_node;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			ret = -ENODEV;
+			goto put_cpu_node;
+		}
+
+		/* Get OPP descriptor node */
+		tmp_np = _of_get_opp_desc_node(tcpu_dev);
+		if (IS_ERR(tmp_np)) {
+			dev_err(tcpu_dev, "%s: Couldn't find opp node: %ld\n",
+				__func__, PTR_ERR(tmp_np));
+			ret = PTR_ERR(tmp_np);
+			goto put_cpu_node;
+		}
+
+		/* CPUs are sharing opp node */
+		if (np == tmp_np)
+			cpumask_set_cpu(cpu, cpumask);
+
+		of_node_put(tmp_np);
+	}
+
+put_cpu_node:
+	of_node_put(np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps);
 #endif
 #endif

+ 62 - 11
drivers/cpufreq/cpufreq-dt.c

@@ -36,6 +36,12 @@ struct private_data {
 	unsigned int voltage_tolerance; /* in percentage */
 	unsigned int voltage_tolerance; /* in percentage */
 };
 };
 
 
+static struct freq_attr *cpufreq_dt_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,   /* Extra space for boost-attr if required */
+	NULL,
+};
+
 static int set_target(struct cpufreq_policy *policy, unsigned int index)
 static int set_target(struct cpufreq_policy *policy, unsigned int index)
 {
 {
 	struct dev_pm_opp *opp;
 	struct dev_pm_opp *opp;
@@ -184,7 +190,6 @@ try_again:
 
 
 static int cpufreq_init(struct cpufreq_policy *policy)
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
 {
-	struct cpufreq_dt_platform_data *pd;
 	struct cpufreq_frequency_table *freq_table;
 	struct cpufreq_frequency_table *freq_table;
 	struct device_node *np;
 	struct device_node *np;
 	struct private_data *priv;
 	struct private_data *priv;
@@ -193,6 +198,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	struct clk *cpu_clk;
 	struct clk *cpu_clk;
 	unsigned long min_uV = ~0, max_uV = 0;
 	unsigned long min_uV = ~0, max_uV = 0;
 	unsigned int transition_latency;
 	unsigned int transition_latency;
+	bool need_update = false;
 	int ret;
 	int ret;
 
 
 	ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
 	ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
@@ -208,8 +214,47 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_put_reg_clk;
 		goto out_put_reg_clk;
 	}
 	}
 
 
-	/* OPPs might be populated at runtime, don't check for error here */
-	of_init_opp_table(cpu_dev);
+	/* Get OPP-sharing information from "operating-points-v2" bindings */
+	ret = of_get_cpus_sharing_opps(cpu_dev, policy->cpus);
+	if (ret) {
+		/*
+		 * operating-points-v2 not supported, fallback to old method of
+		 * finding shared-OPPs for backward compatibility.
+		 */
+		if (ret == -ENOENT)
+			need_update = true;
+		else
+			goto out_node_put;
+	}
+
+	/*
+	 * Initialize OPP tables for all policy->cpus. They will be shared by
+	 * all CPUs which have marked their CPUs shared with OPP bindings.
+	 *
+	 * For platforms not using operating-points-v2 bindings, we do this
+	 * before updating policy->cpus. Otherwise, we will end up creating
+	 * duplicate OPPs for policy->cpus.
+	 *
+	 * OPPs might be populated at runtime, don't check for error here
+	 */
+	of_cpumask_init_opp_table(policy->cpus);
+
+	if (need_update) {
+		struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
+
+		if (!pd || !pd->independent_clocks)
+			cpumask_setall(policy->cpus);
+
+		/*
+		 * OPP tables are initialized only for policy->cpu, do it for
+		 * others as well.
+		 */
+		set_cpus_sharing_opps(cpu_dev, policy->cpus);
+
+		of_property_read_u32(np, "clock-latency", &transition_latency);
+	} else {
+		transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev);
+	}
 
 
 	/*
 	/*
 	 * But we need OPP table to function so if it is not there let's
 	 * But we need OPP table to function so if it is not there let's
@@ -230,7 +275,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 
 	of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
 	of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
 
 
-	if (of_property_read_u32(np, "clock-latency", &transition_latency))
+	if (!transition_latency)
 		transition_latency = CPUFREQ_ETERNAL;
 		transition_latency = CPUFREQ_ETERNAL;
 
 
 	if (!IS_ERR(cpu_reg)) {
 	if (!IS_ERR(cpu_reg)) {
@@ -291,11 +336,16 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_free_cpufreq_table;
 		goto out_free_cpufreq_table;
 	}
 	}
 
 
-	policy->cpuinfo.transition_latency = transition_latency;
+	/* Support turbo/boost mode */
+	if (policy_has_boost_freq(policy)) {
+		/* This gets disabled by core on driver unregister */
+		ret = cpufreq_enable_boost_support();
+		if (ret)
+			goto out_free_cpufreq_table;
+		cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
+	}
 
 
-	pd = cpufreq_get_driver_data();
-	if (!pd || !pd->independent_clocks)
-		cpumask_setall(policy->cpus);
+	policy->cpuinfo.transition_latency = transition_latency;
 
 
 	of_node_put(np);
 	of_node_put(np);
 
 
@@ -306,7 +356,8 @@ out_free_cpufreq_table:
 out_free_priv:
 out_free_priv:
 	kfree(priv);
 	kfree(priv);
 out_free_opp:
 out_free_opp:
-	of_free_opp_table(cpu_dev);
+	of_cpumask_free_opp_table(policy->cpus);
+out_node_put:
 	of_node_put(np);
 	of_node_put(np);
 out_put_reg_clk:
 out_put_reg_clk:
 	clk_put(cpu_clk);
 	clk_put(cpu_clk);
@@ -322,7 +373,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
 
 
 	cpufreq_cooling_unregister(priv->cdev);
 	cpufreq_cooling_unregister(priv->cdev);
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-	of_free_opp_table(priv->cpu_dev);
+	of_cpumask_free_opp_table(policy->related_cpus);
 	clk_put(policy->clk);
 	clk_put(policy->clk);
 	if (!IS_ERR(priv->cpu_reg))
 	if (!IS_ERR(priv->cpu_reg))
 		regulator_put(priv->cpu_reg);
 		regulator_put(priv->cpu_reg);
@@ -367,7 +418,7 @@ static struct cpufreq_driver dt_cpufreq_driver = {
 	.exit = cpufreq_exit,
 	.exit = cpufreq_exit,
 	.ready = cpufreq_ready,
 	.ready = cpufreq_ready,
 	.name = "cpufreq-dt",
 	.name = "cpufreq-dt",
-	.attr = cpufreq_generic_attr,
+	.attr = cpufreq_dt_attr,
 };
 };
 
 
 static int dt_cpufreq_probe(struct platform_device *pdev)
 static int dt_cpufreq_probe(struct platform_device *pdev)

+ 48 - 20
drivers/cpufreq/cpufreq.c

@@ -2412,6 +2412,49 @@ int cpufreq_boost_supported(void)
 }
 }
 EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
 EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
 
 
+static int create_boost_sysfs_file(void)
+{
+	int ret;
+
+	if (!cpufreq_boost_supported())
+		return 0;
+
+	/*
+	 * Check if driver provides function to enable boost -
+	 * if not, use cpufreq_boost_set_sw as default
+	 */
+	if (!cpufreq_driver->set_boost)
+		cpufreq_driver->set_boost = cpufreq_boost_set_sw;
+
+	ret = cpufreq_sysfs_create_file(&boost.attr);
+	if (ret)
+		pr_err("%s: cannot register global BOOST sysfs file\n",
+		       __func__);
+
+	return ret;
+}
+
+static void remove_boost_sysfs_file(void)
+{
+	if (cpufreq_boost_supported())
+		cpufreq_sysfs_remove_file(&boost.attr);
+}
+
+int cpufreq_enable_boost_support(void)
+{
+	if (!cpufreq_driver)
+		return -EINVAL;
+
+	if (cpufreq_boost_supported())
+		return 0;
+
+	cpufreq_driver->boost_supported = true;
+
+	/* This will get removed on driver unregister */
+	return create_boost_sysfs_file();
+}
+EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support);
+
 int cpufreq_boost_enabled(void)
 int cpufreq_boost_enabled(void)
 {
 {
 	return cpufreq_driver->boost_enabled;
 	return cpufreq_driver->boost_enabled;
@@ -2465,21 +2508,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 	if (driver_data->setpolicy)
 	if (driver_data->setpolicy)
 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
 
 
-	if (cpufreq_boost_supported()) {
-		/*
-		 * Check if driver provides function to enable boost -
-		 * if not, use cpufreq_boost_set_sw as default
-		 */
-		if (!cpufreq_driver->set_boost)
-			cpufreq_driver->set_boost = cpufreq_boost_set_sw;
-
-		ret = cpufreq_sysfs_create_file(&boost.attr);
-		if (ret) {
-			pr_err("%s: cannot register global BOOST sysfs file\n",
-			       __func__);
-			goto err_null_driver;
-		}
-	}
+	ret = create_boost_sysfs_file();
+	if (ret)
+		goto err_null_driver;
 
 
 	ret = subsys_interface_register(&cpufreq_interface);
 	ret = subsys_interface_register(&cpufreq_interface);
 	if (ret)
 	if (ret)
@@ -2503,8 +2534,7 @@ out:
 err_if_unreg:
 err_if_unreg:
 	subsys_interface_unregister(&cpufreq_interface);
 	subsys_interface_unregister(&cpufreq_interface);
 err_boost_unreg:
 err_boost_unreg:
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
+	remove_boost_sysfs_file();
 err_null_driver:
 err_null_driver:
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
 	cpufreq_driver = NULL;
@@ -2533,9 +2563,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 	/* Protect against concurrent cpu hotplug */
 	/* Protect against concurrent cpu hotplug */
 	get_online_cpus();
 	get_online_cpus();
 	subsys_interface_unregister(&cpufreq_interface);
 	subsys_interface_unregister(&cpufreq_interface);
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
-
+	remove_boost_sysfs_file();
 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 
 
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	write_lock_irqsave(&cpufreq_driver_lock, flags);

+ 4 - 0
drivers/cpufreq/cpufreq_opp.c

@@ -75,6 +75,10 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
 		}
 		}
 		freq_table[i].driver_data = i;
 		freq_table[i].driver_data = i;
 		freq_table[i].frequency = rate / 1000;
 		freq_table[i].frequency = rate / 1000;
+
+		/* Is Boost/turbo opp ? */
+		if (dev_pm_opp_is_turbo(opp))
+			freq_table[i].flags = CPUFREQ_BOOST_FREQ;
 	}
 	}
 
 
 	freq_table[i].driver_data = i;
 	freq_table[i].driver_data = i;

+ 15 - 0
drivers/cpufreq/freq_table.c

@@ -18,6 +18,21 @@
  *                     FREQUENCY TABLE HELPERS                       *
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
  *********************************************************************/
 
 
+bool policy_has_boost_freq(struct cpufreq_policy *policy)
+{
+	struct cpufreq_frequency_table *pos, *table = policy->freq_table;
+
+	if (!table)
+		return false;
+
+	cpufreq_for_each_valid_entry(pos, table)
+		if (pos->flags & CPUFREQ_BOOST_FREQ)
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(policy_has_boost_freq);
+
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 				    struct cpufreq_frequency_table *table)
 				    struct cpufreq_frequency_table *table)
 {
 {

+ 87 - 45
drivers/dma/at_hdmac.c

@@ -48,6 +48,8 @@
 	BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\
 	BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\
 	BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
 	BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
 
 
+#define ATC_MAX_DSCR_TRIALS	10
+
 /*
 /*
  * Initial number of descriptors to allocate for each channel. This could
  * Initial number of descriptors to allocate for each channel. This could
  * be increased during dma usage.
  * be increased during dma usage.
@@ -285,28 +287,19 @@ static struct at_desc *atc_get_desc_by_cookie(struct at_dma_chan *atchan,
  *
  *
  * @current_len: the number of bytes left before reading CTRLA
  * @current_len: the number of bytes left before reading CTRLA
  * @ctrla: the value of CTRLA
  * @ctrla: the value of CTRLA
- * @desc: the descriptor containing the transfer width
  */
  */
-static inline int atc_calc_bytes_left(int current_len, u32 ctrla,
-					struct at_desc *desc)
+static inline int atc_calc_bytes_left(int current_len, u32 ctrla)
 {
 {
-	return current_len - ((ctrla & ATC_BTSIZE_MAX) << desc->tx_width);
-}
+	u32 btsize = (ctrla & ATC_BTSIZE_MAX);
+	u32 src_width = ATC_REG_TO_SRC_WIDTH(ctrla);
 
 
-/**
- * atc_calc_bytes_left_from_reg - calculates the number of bytes left according
- * to the current value of CTRLA.
- *
- * @current_len: the number of bytes left before reading CTRLA
- * @atchan: the channel to read CTRLA for
- * @desc: the descriptor containing the transfer width
- */
-static inline int atc_calc_bytes_left_from_reg(int current_len,
-			struct at_dma_chan *atchan, struct at_desc *desc)
-{
-	u32 ctrla = channel_readl(atchan, CTRLA);
-
-	return atc_calc_bytes_left(current_len, ctrla, desc);
+	/*
+	 * According to the datasheet, when reading the Control A Register
+	 * (ctrla), the Buffer Transfer Size (btsize) bitfield refers to the
+	 * number of transfers completed on the Source Interface.
+	 * So btsize is always a number of source width transfers.
+	 */
+	return current_len - (btsize << src_width);
 }
 }
 
 
 /**
 /**
@@ -320,7 +313,7 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
 	struct at_desc *desc_first = atc_first_active(atchan);
 	struct at_desc *desc_first = atc_first_active(atchan);
 	struct at_desc *desc;
 	struct at_desc *desc;
 	int ret;
 	int ret;
-	u32 ctrla, dscr;
+	u32 ctrla, dscr, trials;
 
 
 	/*
 	/*
 	 * If the cookie doesn't match to the currently running transfer then
 	 * If the cookie doesn't match to the currently running transfer then
@@ -346,15 +339,82 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
 		 * the channel's DSCR register and compare it against the value
 		 * the channel's DSCR register and compare it against the value
 		 * of the hardware linked list structure of each child
 		 * of the hardware linked list structure of each child
 		 * descriptor.
 		 * descriptor.
+		 *
+		 * The CTRLA register provides us with the amount of data
+		 * already read from the source for the current child
+		 * descriptor. So we can compute a more accurate residue by also
+		 * removing the number of bytes corresponding to this amount of
+		 * data.
+		 *
+		 * However, the DSCR and CTRLA registers cannot be read both
+		 * atomically. Hence a race condition may occur: the first read
+		 * register may refer to one child descriptor whereas the second
+		 * read may refer to a later child descriptor in the list
+		 * because of the DMA transfer progression inbetween the two
+		 * reads.
+		 *
+		 * One solution could have been to pause the DMA transfer, read
+		 * the DSCR and CTRLA then resume the DMA transfer. Nonetheless,
+		 * this approach presents some drawbacks:
+		 * - If the DMA transfer is paused, RX overruns or TX underruns
+		 *   are more likey to occur depending on the system latency.
+		 *   Taking the USART driver as an example, it uses a cyclic DMA
+		 *   transfer to read data from the Receive Holding Register
+		 *   (RHR) to avoid RX overruns since the RHR is not protected
+		 *   by any FIFO on most Atmel SoCs. So pausing the DMA transfer
+		 *   to compute the residue would break the USART driver design.
+		 * - The atc_pause() function masks interrupts but we'd rather
+		 *   avoid to do so for system latency purpose.
+		 *
+		 * Then we'd rather use another solution: the DSCR is read a
+		 * first time, the CTRLA is read in turn, next the DSCR is read
+		 * a second time. If the two consecutive read values of the DSCR
+		 * are the same then we assume both refers to the very same
+		 * child descriptor as well as the CTRLA value read inbetween
+		 * does. For cyclic tranfers, the assumption is that a full loop
+		 * is "not so fast".
+		 * If the two DSCR values are different, we read again the CTRLA
+		 * then the DSCR till two consecutive read values from DSCR are
+		 * equal or till the maxium trials is reach.
+		 * This algorithm is very unlikely not to find a stable value for
+		 * DSCR.
 		 */
 		 */
 
 
-		ctrla = channel_readl(atchan, CTRLA);
-		rmb(); /* ensure CTRLA is read before DSCR */
 		dscr = channel_readl(atchan, DSCR);
 		dscr = channel_readl(atchan, DSCR);
+		rmb(); /* ensure DSCR is read before CTRLA */
+		ctrla = channel_readl(atchan, CTRLA);
+		for (trials = 0; trials < ATC_MAX_DSCR_TRIALS; ++trials) {
+			u32 new_dscr;
+
+			rmb(); /* ensure DSCR is read after CTRLA */
+			new_dscr = channel_readl(atchan, DSCR);
+
+			/*
+			 * If the DSCR register value has not changed inside the
+			 * DMA controller since the previous read, we assume
+			 * that both the dscr and ctrla values refers to the
+			 * very same descriptor.
+			 */
+			if (likely(new_dscr == dscr))
+				break;
+
+			/*
+			 * DSCR has changed inside the DMA controller, so the
+			 * previouly read value of CTRLA may refer to an already
+			 * processed descriptor hence could be outdated.
+			 * We need to update ctrla to match the current
+			 * descriptor.
+			 */
+			dscr = new_dscr;
+			rmb(); /* ensure DSCR is read before CTRLA */
+			ctrla = channel_readl(atchan, CTRLA);
+		}
+		if (unlikely(trials >= ATC_MAX_DSCR_TRIALS))
+			return -ETIMEDOUT;
 
 
 		/* for the first descriptor we can be more accurate */
 		/* for the first descriptor we can be more accurate */
 		if (desc_first->lli.dscr == dscr)
 		if (desc_first->lli.dscr == dscr)
-			return atc_calc_bytes_left(ret, ctrla, desc_first);
+			return atc_calc_bytes_left(ret, ctrla);
 
 
 		ret -= desc_first->len;
 		ret -= desc_first->len;
 		list_for_each_entry(desc, &desc_first->tx_list, desc_node) {
 		list_for_each_entry(desc, &desc_first->tx_list, desc_node) {
@@ -365,16 +425,14 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
 		}
 		}
 
 
 		/*
 		/*
-		 * For the last descriptor in the chain we can calculate
+		 * For the current descriptor in the chain we can calculate
 		 * the remaining bytes using the channel's register.
 		 * the remaining bytes using the channel's register.
-		 * Note that the transfer width of the first and last
-		 * descriptor may differ.
 		 */
 		 */
-		if (!desc->lli.dscr)
-			ret = atc_calc_bytes_left_from_reg(ret, atchan, desc);
+		ret = atc_calc_bytes_left(ret, ctrla);
 	} else {
 	} else {
 		/* single transfer */
 		/* single transfer */
-		ret = atc_calc_bytes_left_from_reg(ret, atchan, desc_first);
+		ctrla = channel_readl(atchan, CTRLA);
+		ret = atc_calc_bytes_left(ret, ctrla);
 	}
 	}
 
 
 	return ret;
 	return ret;
@@ -726,7 +784,6 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
 
 
 	desc->txd.cookie = -EBUSY;
 	desc->txd.cookie = -EBUSY;
 	desc->total_len = desc->len = len;
 	desc->total_len = desc->len = len;
-	desc->tx_width = dwidth;
 
 
 	/* set end-of-link to the last link descriptor of list*/
 	/* set end-of-link to the last link descriptor of list*/
 	set_desc_eol(desc);
 	set_desc_eol(desc);
@@ -804,10 +861,6 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 	first->txd.cookie = -EBUSY;
 	first->txd.cookie = -EBUSY;
 	first->total_len = len;
 	first->total_len = len;
 
 
-	/* set transfer width for the calculation of the residue */
-	first->tx_width = src_width;
-	prev->tx_width = src_width;
-
 	/* set end-of-link to the last link descriptor of list*/
 	/* set end-of-link to the last link descriptor of list*/
 	set_desc_eol(desc);
 	set_desc_eol(desc);
 
 
@@ -956,10 +1009,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	first->txd.cookie = -EBUSY;
 	first->txd.cookie = -EBUSY;
 	first->total_len = total_len;
 	first->total_len = total_len;
 
 
-	/* set transfer width for the calculation of the residue */
-	first->tx_width = reg_width;
-	prev->tx_width = reg_width;
-
 	/* first link descriptor of list is responsible of flags */
 	/* first link descriptor of list is responsible of flags */
 	first->txd.flags = flags; /* client is in control of this ack */
 	first->txd.flags = flags; /* client is in control of this ack */
 
 
@@ -1077,12 +1126,6 @@ atc_prep_dma_sg(struct dma_chan *chan,
 		desc->txd.cookie = 0;
 		desc->txd.cookie = 0;
 		desc->len = len;
 		desc->len = len;
 
 
-		/*
-		 * Although we only need the transfer width for the first and
-		 * the last descriptor, its easier to set it to all descriptors.
-		 */
-		desc->tx_width = src_width;
-
 		atc_desc_chain(&first, &prev, desc);
 		atc_desc_chain(&first, &prev, desc);
 
 
 		/* update the lengths and addresses for the next loop cycle */
 		/* update the lengths and addresses for the next loop cycle */
@@ -1256,7 +1299,6 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 	/* First descriptor of the chain embedds additional information */
 	/* First descriptor of the chain embedds additional information */
 	first->txd.cookie = -EBUSY;
 	first->txd.cookie = -EBUSY;
 	first->total_len = buf_len;
 	first->total_len = buf_len;
-	first->tx_width = reg_width;
 
 
 	return &first->txd;
 	return &first->txd;
 
 

+ 1 - 2
drivers/dma/at_hdmac_regs.h

@@ -112,6 +112,7 @@
 #define		ATC_SRC_WIDTH_BYTE	(0x0 << 24)
 #define		ATC_SRC_WIDTH_BYTE	(0x0 << 24)
 #define		ATC_SRC_WIDTH_HALFWORD	(0x1 << 24)
 #define		ATC_SRC_WIDTH_HALFWORD	(0x1 << 24)
 #define		ATC_SRC_WIDTH_WORD	(0x2 << 24)
 #define		ATC_SRC_WIDTH_WORD	(0x2 << 24)
+#define		ATC_REG_TO_SRC_WIDTH(r)	(((r) >> 24) & 0x3)
 #define	ATC_DST_WIDTH_MASK	(0x3 << 28)	/* Destination Single Transfer Size */
 #define	ATC_DST_WIDTH_MASK	(0x3 << 28)	/* Destination Single Transfer Size */
 #define		ATC_DST_WIDTH(x)	((x) << 28)
 #define		ATC_DST_WIDTH(x)	((x) << 28)
 #define		ATC_DST_WIDTH_BYTE	(0x0 << 28)
 #define		ATC_DST_WIDTH_BYTE	(0x0 << 28)
@@ -182,7 +183,6 @@ struct at_lli {
  * @txd: support for the async_tx api
  * @txd: support for the async_tx api
  * @desc_node: node on the channed descriptors list
  * @desc_node: node on the channed descriptors list
  * @len: descriptor byte count
  * @len: descriptor byte count
- * @tx_width: transfer width
  * @total_len: total transaction byte count
  * @total_len: total transaction byte count
  */
  */
 struct at_desc {
 struct at_desc {
@@ -194,7 +194,6 @@ struct at_desc {
 	struct dma_async_tx_descriptor	txd;
 	struct dma_async_tx_descriptor	txd;
 	struct list_head		desc_node;
 	struct list_head		desc_node;
 	size_t				len;
 	size_t				len;
-	u32				tx_width;
 	size_t				total_len;
 	size_t				total_len;
 
 
 	/* Interleaved data */
 	/* Interleaved data */

+ 14 - 12
drivers/dma/at_xdmac.c

@@ -359,18 +359,19 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan,
 	 * descriptor view 2 since some fields of the configuration register
 	 * descriptor view 2 since some fields of the configuration register
 	 * depend on transfer size and src/dest addresses.
 	 * depend on transfer size and src/dest addresses.
 	 */
 	 */
-	if (at_xdmac_chan_is_cyclic(atchan)) {
+	if (at_xdmac_chan_is_cyclic(atchan))
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
-		at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg);
-	} else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3) {
+	else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3)
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV3;
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV3;
-	} else {
-		/*
-		 * No need to write AT_XDMAC_CC reg, it will be done when the
-		 * descriptor is fecthed.
-		 */
+	else
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV2;
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV2;
-	}
+	/*
+	 * Even if the register will be updated from the configuration in the
+	 * descriptor when using view 2 or higher, the PROT bit won't be set
+	 * properly. This bit can be modified only by using the channel
+	 * configuration register.
+	 */
+	at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg);
 
 
 	reg |= AT_XDMAC_CNDC_NDDUP
 	reg |= AT_XDMAC_CNDC_NDDUP
 	       | AT_XDMAC_CNDC_NDSUP
 	       | AT_XDMAC_CNDC_NDSUP
@@ -681,15 +682,16 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 			desc->lld.mbr_sa = mem;
 			desc->lld.mbr_sa = mem;
 			desc->lld.mbr_da = atchan->sconfig.dst_addr;
 			desc->lld.mbr_da = atchan->sconfig.dst_addr;
 		}
 		}
-		desc->lld.mbr_cfg = atchan->cfg;
-		dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
+		dwidth = at_xdmac_get_dwidth(atchan->cfg);
 		fixed_dwidth = IS_ALIGNED(len, 1 << dwidth)
 		fixed_dwidth = IS_ALIGNED(len, 1 << dwidth)
-			       ? at_xdmac_get_dwidth(desc->lld.mbr_cfg)
+			       ? dwidth
 			       : AT_XDMAC_CC_DWIDTH_BYTE;
 			       : AT_XDMAC_CC_DWIDTH_BYTE;
 		desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV2			/* next descriptor view */
 		desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV2			/* next descriptor view */
 			| AT_XDMAC_MBR_UBC_NDEN					/* next descriptor dst parameter update */
 			| AT_XDMAC_MBR_UBC_NDEN					/* next descriptor dst parameter update */
 			| AT_XDMAC_MBR_UBC_NSEN					/* next descriptor src parameter update */
 			| AT_XDMAC_MBR_UBC_NSEN					/* next descriptor src parameter update */
 			| (len >> fixed_dwidth);				/* microblock length */
 			| (len >> fixed_dwidth);				/* microblock length */
+		desc->lld.mbr_cfg = (atchan->cfg & ~AT_XDMAC_CC_DWIDTH_MASK) |
+				    AT_XDMAC_CC_DWIDTH(fixed_dwidth);
 		dev_dbg(chan2dev(chan),
 		dev_dbg(chan2dev(chan),
 			 "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
 			 "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
 			 __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc);
 			 __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc);

+ 5 - 4
drivers/dma/mv_xor.c

@@ -162,10 +162,11 @@ static void mv_chan_set_mode(struct mv_xor_chan *chan,
 	config &= ~0x7;
 	config &= ~0x7;
 	config |= op_mode;
 	config |= op_mode;
 
 
-	if (IS_ENABLED(__BIG_ENDIAN))
-		config |= XOR_DESCRIPTOR_SWAP;
-	else
-		config &= ~XOR_DESCRIPTOR_SWAP;
+#if defined(__BIG_ENDIAN)
+	config |= XOR_DESCRIPTOR_SWAP;
+#else
+	config &= ~XOR_DESCRIPTOR_SWAP;
+#endif
 
 
 	writel_relaxed(config, XOR_CONFIG(chan));
 	writel_relaxed(config, XOR_CONFIG(chan));
 	chan->current_type = type;
 	chan->current_type = type;

+ 2 - 1
drivers/dma/pl330.c

@@ -2328,7 +2328,7 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
 			desc->txd.callback = last->txd.callback;
 			desc->txd.callback = last->txd.callback;
 			desc->txd.callback_param = last->txd.callback_param;
 			desc->txd.callback_param = last->txd.callback_param;
 		}
 		}
-		last->last = false;
+		desc->last = false;
 
 
 		dma_cookie_assign(&desc->txd);
 		dma_cookie_assign(&desc->txd);
 
 
@@ -2623,6 +2623,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
 		desc->rqcfg.brst_len = 1;
 		desc->rqcfg.brst_len = 1;
 
 
 	desc->rqcfg.brst_len = get_burst_len(desc, len);
 	desc->rqcfg.brst_len = get_burst_len(desc, len);
+	desc->bytes_requested = len;
 
 
 	desc->txd.flags = flags;
 	desc->txd.flags = flags;
 
 

+ 6 - 13
drivers/dma/virt-dma.c

@@ -29,7 +29,7 @@ dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *tx)
 	spin_lock_irqsave(&vc->lock, flags);
 	spin_lock_irqsave(&vc->lock, flags);
 	cookie = dma_cookie_assign(tx);
 	cookie = dma_cookie_assign(tx);
 
 
-	list_move_tail(&vd->node, &vc->desc_submitted);
+	list_add_tail(&vd->node, &vc->desc_submitted);
 	spin_unlock_irqrestore(&vc->lock, flags);
 	spin_unlock_irqrestore(&vc->lock, flags);
 
 
 	dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: submitted\n",
 	dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: submitted\n",
@@ -83,10 +83,8 @@ static void vchan_complete(unsigned long arg)
 		cb_data = vd->tx.callback_param;
 		cb_data = vd->tx.callback_param;
 
 
 		list_del(&vd->node);
 		list_del(&vd->node);
-		if (async_tx_test_ack(&vd->tx))
-			list_add(&vd->node, &vc->desc_allocated);
-		else
-			vc->desc_free(vd);
+
+		vc->desc_free(vd);
 
 
 		if (cb)
 		if (cb)
 			cb(cb_data);
 			cb(cb_data);
@@ -98,13 +96,9 @@ void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head)
 	while (!list_empty(head)) {
 	while (!list_empty(head)) {
 		struct virt_dma_desc *vd = list_first_entry(head,
 		struct virt_dma_desc *vd = list_first_entry(head,
 			struct virt_dma_desc, node);
 			struct virt_dma_desc, node);
-		if (async_tx_test_ack(&vd->tx)) {
-			list_move_tail(&vd->node, &vc->desc_allocated);
-		} else {
-			dev_dbg(vc->chan.device->dev, "txd %p: freeing\n", vd);
-			list_del(&vd->node);
-			vc->desc_free(vd);
-		}
+		list_del(&vd->node);
+		dev_dbg(vc->chan.device->dev, "txd %p: freeing\n", vd);
+		vc->desc_free(vd);
 	}
 	}
 }
 }
 EXPORT_SYMBOL_GPL(vchan_dma_desc_free_list);
 EXPORT_SYMBOL_GPL(vchan_dma_desc_free_list);
@@ -114,7 +108,6 @@ void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev)
 	dma_cookie_init(&vc->chan);
 	dma_cookie_init(&vc->chan);
 
 
 	spin_lock_init(&vc->lock);
 	spin_lock_init(&vc->lock);
-	INIT_LIST_HEAD(&vc->desc_allocated);
 	INIT_LIST_HEAD(&vc->desc_submitted);
 	INIT_LIST_HEAD(&vc->desc_submitted);
 	INIT_LIST_HEAD(&vc->desc_issued);
 	INIT_LIST_HEAD(&vc->desc_issued);
 	INIT_LIST_HEAD(&vc->desc_completed);
 	INIT_LIST_HEAD(&vc->desc_completed);

+ 1 - 12
drivers/dma/virt-dma.h

@@ -29,7 +29,6 @@ struct virt_dma_chan {
 	spinlock_t lock;
 	spinlock_t lock;
 
 
 	/* protected by vc.lock */
 	/* protected by vc.lock */
-	struct list_head desc_allocated;
 	struct list_head desc_submitted;
 	struct list_head desc_submitted;
 	struct list_head desc_issued;
 	struct list_head desc_issued;
 	struct list_head desc_completed;
 	struct list_head desc_completed;
@@ -56,16 +55,11 @@ static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan
 	struct virt_dma_desc *vd, unsigned long tx_flags)
 	struct virt_dma_desc *vd, unsigned long tx_flags)
 {
 {
 	extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *);
 	extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *);
-	unsigned long flags;
 
 
 	dma_async_tx_descriptor_init(&vd->tx, &vc->chan);
 	dma_async_tx_descriptor_init(&vd->tx, &vc->chan);
 	vd->tx.flags = tx_flags;
 	vd->tx.flags = tx_flags;
 	vd->tx.tx_submit = vchan_tx_submit;
 	vd->tx.tx_submit = vchan_tx_submit;
 
 
-	spin_lock_irqsave(&vc->lock, flags);
-	list_add_tail(&vd->node, &vc->desc_allocated);
-	spin_unlock_irqrestore(&vc->lock, flags);
-
 	return &vd->tx;
 	return &vd->tx;
 }
 }
 
 
@@ -128,8 +122,7 @@ static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc)
 }
 }
 
 
 /**
 /**
- * vchan_get_all_descriptors - obtain all allocated, submitted and issued
- *                             descriptors
+ * vchan_get_all_descriptors - obtain all submitted and issued descriptors
  * vc: virtual channel to get descriptors from
  * vc: virtual channel to get descriptors from
  * head: list of descriptors found
  * head: list of descriptors found
  *
  *
@@ -141,7 +134,6 @@ static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc)
 static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc,
 static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc,
 	struct list_head *head)
 	struct list_head *head)
 {
 {
-	list_splice_tail_init(&vc->desc_allocated, head);
 	list_splice_tail_init(&vc->desc_submitted, head);
 	list_splice_tail_init(&vc->desc_submitted, head);
 	list_splice_tail_init(&vc->desc_issued, head);
 	list_splice_tail_init(&vc->desc_issued, head);
 	list_splice_tail_init(&vc->desc_completed, head);
 	list_splice_tail_init(&vc->desc_completed, head);
@@ -149,14 +141,11 @@ static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc,
 
 
 static inline void vchan_free_chan_resources(struct virt_dma_chan *vc)
 static inline void vchan_free_chan_resources(struct virt_dma_chan *vc)
 {
 {
-	struct virt_dma_desc *vd;
 	unsigned long flags;
 	unsigned long flags;
 	LIST_HEAD(head);
 	LIST_HEAD(head);
 
 
 	spin_lock_irqsave(&vc->lock, flags);
 	spin_lock_irqsave(&vc->lock, flags);
 	vchan_get_all_descriptors(vc, &head);
 	vchan_get_all_descriptors(vc, &head);
-	list_for_each_entry(vd, &head, node)
-		async_tx_clear_ack(&vd->tx);
 	spin_unlock_irqrestore(&vc->lock, flags);
 	spin_unlock_irqrestore(&vc->lock, flags);
 
 
 	vchan_dma_desc_free_list(vc, &head);
 	vchan_dma_desc_free_list(vc, &head);

+ 3 - 0
drivers/dma/xgene-dma.c

@@ -111,6 +111,7 @@
 #define XGENE_DMA_MEM_RAM_SHUTDOWN		0xD070
 #define XGENE_DMA_MEM_RAM_SHUTDOWN		0xD070
 #define XGENE_DMA_BLK_MEM_RDY			0xD074
 #define XGENE_DMA_BLK_MEM_RDY			0xD074
 #define XGENE_DMA_BLK_MEM_RDY_VAL		0xFFFFFFFF
 #define XGENE_DMA_BLK_MEM_RDY_VAL		0xFFFFFFFF
+#define XGENE_DMA_RING_CMD_SM_OFFSET		0x8000
 
 
 /* X-Gene SoC EFUSE csr register and bit defination */
 /* X-Gene SoC EFUSE csr register and bit defination */
 #define XGENE_SOC_JTAG1_SHADOW			0x18
 #define XGENE_SOC_JTAG1_SHADOW			0x18
@@ -1887,6 +1888,8 @@ static int xgene_dma_get_resources(struct platform_device *pdev,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
+	pdma->csr_ring_cmd += XGENE_DMA_RING_CMD_SM_OFFSET;
+
 	/* Get efuse csr region */
 	/* Get efuse csr region */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
 	if (!res) {
 	if (!res) {

+ 5 - 0
drivers/firmware/efi/efi.c

@@ -58,6 +58,11 @@ bool efi_runtime_disabled(void)
 
 
 static int __init parse_efi_cmdline(char *str)
 static int __init parse_efi_cmdline(char *str)
 {
 {
+	if (!str) {
+		pr_warn("need at least one option\n");
+		return -EINVAL;
+	}
+
 	if (parse_option_str(str, "noruntime"))
 	if (parse_option_str(str, "noruntime"))
 		disable_runtime = true;
 		disable_runtime = true;
 
 

+ 7 - 1
drivers/gpu/drm/amd/amdgpu/amdgpu.h

@@ -1866,6 +1866,12 @@ typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
 typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
 typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
 typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
 typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
 
 
+struct amdgpu_ip_block_status {
+	bool valid;
+	bool sw;
+	bool hw;
+};
+
 struct amdgpu_device {
 struct amdgpu_device {
 	struct device			*dev;
 	struct device			*dev;
 	struct drm_device		*ddev;
 	struct drm_device		*ddev;
@@ -2008,7 +2014,7 @@ struct amdgpu_device {
 
 
 	const struct amdgpu_ip_block_version *ip_blocks;
 	const struct amdgpu_ip_block_version *ip_blocks;
 	int				num_ip_blocks;
 	int				num_ip_blocks;
-	bool				*ip_block_enabled;
+	struct amdgpu_ip_block_status	*ip_block_status;
 	struct mutex	mn_lock;
 	struct mutex	mn_lock;
 	DECLARE_HASHTABLE(mn_hash, 7);
 	DECLARE_HASHTABLE(mn_hash, 7);
 
 

+ 22 - 16
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

@@ -1191,8 +1191,9 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	adev->ip_block_enabled = kcalloc(adev->num_ip_blocks, sizeof(bool), GFP_KERNEL);
-	if (adev->ip_block_enabled == NULL)
+	adev->ip_block_status = kcalloc(adev->num_ip_blocks,
+					sizeof(struct amdgpu_ip_block_status), GFP_KERNEL);
+	if (adev->ip_block_status == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	if (adev->ip_blocks == NULL) {
 	if (adev->ip_blocks == NULL) {
@@ -1203,18 +1204,18 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 		if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
 		if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
 			DRM_ERROR("disabled ip block: %d\n", i);
 			DRM_ERROR("disabled ip block: %d\n", i);
-			adev->ip_block_enabled[i] = false;
+			adev->ip_block_status[i].valid = false;
 		} else {
 		} else {
 			if (adev->ip_blocks[i].funcs->early_init) {
 			if (adev->ip_blocks[i].funcs->early_init) {
 				r = adev->ip_blocks[i].funcs->early_init((void *)adev);
 				r = adev->ip_blocks[i].funcs->early_init((void *)adev);
 				if (r == -ENOENT)
 				if (r == -ENOENT)
-					adev->ip_block_enabled[i] = false;
+					adev->ip_block_status[i].valid = false;
 				else if (r)
 				else if (r)
 					return r;
 					return r;
 				else
 				else
-					adev->ip_block_enabled[i] = true;
+					adev->ip_block_status[i].valid = true;
 			} else {
 			} else {
-				adev->ip_block_enabled[i] = true;
+				adev->ip_block_status[i].valid = true;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -1227,11 +1228,12 @@ static int amdgpu_init(struct amdgpu_device *adev)
 	int i, r;
 	int i, r;
 
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_enabled[i])
+		if (!adev->ip_block_status[i].valid)
 			continue;
 			continue;
 		r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
 		r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
 		if (r)
 		if (r)
 			return r;
 			return r;
+		adev->ip_block_status[i].sw = true;
 		/* need to do gmc hw init early so we can allocate gpu mem */
 		/* need to do gmc hw init early so we can allocate gpu mem */
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
 			r = amdgpu_vram_scratch_init(adev);
 			r = amdgpu_vram_scratch_init(adev);
@@ -1243,11 +1245,12 @@ static int amdgpu_init(struct amdgpu_device *adev)
 			r = amdgpu_wb_init(adev);
 			r = amdgpu_wb_init(adev);
 			if (r)
 			if (r)
 				return r;
 				return r;
+			adev->ip_block_status[i].hw = true;
 		}
 		}
 	}
 	}
 
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_enabled[i])
+		if (!adev->ip_block_status[i].sw)
 			continue;
 			continue;
 		/* gmc hw init is done early */
 		/* gmc hw init is done early */
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC)
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC)
@@ -1255,6 +1258,7 @@ static int amdgpu_init(struct amdgpu_device *adev)
 		r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
 		r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
 		if (r)
 		if (r)
 			return r;
 			return r;
+		adev->ip_block_status[i].hw = true;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -1265,7 +1269,7 @@ static int amdgpu_late_init(struct amdgpu_device *adev)
 	int i = 0, r;
 	int i = 0, r;
 
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_enabled[i])
+		if (!adev->ip_block_status[i].valid)
 			continue;
 			continue;
 		/* enable clockgating to save power */
 		/* enable clockgating to save power */
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
@@ -1287,7 +1291,7 @@ static int amdgpu_fini(struct amdgpu_device *adev)
 	int i, r;
 	int i, r;
 
 
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
-		if (!adev->ip_block_enabled[i])
+		if (!adev->ip_block_status[i].hw)
 			continue;
 			continue;
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
 			amdgpu_wb_fini(adev);
 			amdgpu_wb_fini(adev);
@@ -1300,14 +1304,16 @@ static int amdgpu_fini(struct amdgpu_device *adev)
 			return r;
 			return r;
 		r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
 		r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
 		/* XXX handle errors */
 		/* XXX handle errors */
+		adev->ip_block_status[i].hw = false;
 	}
 	}
 
 
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
-		if (!adev->ip_block_enabled[i])
+		if (!adev->ip_block_status[i].sw)
 			continue;
 			continue;
 		r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
 		r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
 		/* XXX handle errors */
 		/* XXX handle errors */
-		adev->ip_block_enabled[i] = false;
+		adev->ip_block_status[i].sw = false;
+		adev->ip_block_status[i].valid = false;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -1318,7 +1324,7 @@ static int amdgpu_suspend(struct amdgpu_device *adev)
 	int i, r;
 	int i, r;
 
 
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
-		if (!adev->ip_block_enabled[i])
+		if (!adev->ip_block_status[i].valid)
 			continue;
 			continue;
 		/* ungate blocks so that suspend can properly shut them down */
 		/* ungate blocks so that suspend can properly shut them down */
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
@@ -1336,7 +1342,7 @@ static int amdgpu_resume(struct amdgpu_device *adev)
 	int i, r;
 	int i, r;
 
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_enabled[i])
+		if (!adev->ip_block_status[i].valid)
 			continue;
 			continue;
 		r = adev->ip_blocks[i].funcs->resume(adev);
 		r = adev->ip_blocks[i].funcs->resume(adev);
 		if (r)
 		if (r)
@@ -1582,8 +1588,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
 	amdgpu_fence_driver_fini(adev);
 	amdgpu_fence_driver_fini(adev);
 	amdgpu_fbdev_fini(adev);
 	amdgpu_fbdev_fini(adev);
 	r = amdgpu_fini(adev);
 	r = amdgpu_fini(adev);
-	kfree(adev->ip_block_enabled);
-	adev->ip_block_enabled = NULL;
+	kfree(adev->ip_block_status);
+	adev->ip_block_status = NULL;
 	adev->accel_working = false;
 	adev->accel_working = false;
 	/* free i2c buses */
 	/* free i2c buses */
 	amdgpu_i2c_fini(adev);
 	amdgpu_i2c_fini(adev);

+ 5 - 3
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

@@ -449,7 +449,7 @@ out:
  * vital here, so they are not reported back to userspace.
  * vital here, so they are not reported back to userspace.
  */
  */
 static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
 static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
-				    struct amdgpu_bo_va *bo_va)
+				    struct amdgpu_bo_va *bo_va, uint32_t operation)
 {
 {
 	struct ttm_validate_buffer tv, *entry;
 	struct ttm_validate_buffer tv, *entry;
 	struct amdgpu_bo_list_entry *vm_bos;
 	struct amdgpu_bo_list_entry *vm_bos;
@@ -485,7 +485,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
 	if (r)
 	if (r)
 		goto error_unlock;
 		goto error_unlock;
 
 
-	r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem);
+
+	if (operation == AMDGPU_VA_OP_MAP)
+		r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem);
 
 
 error_unlock:
 error_unlock:
 	mutex_unlock(&bo_va->vm->mutex);
 	mutex_unlock(&bo_va->vm->mutex);
@@ -580,7 +582,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
 	}
 	}
 
 
 	if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
 	if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
-		amdgpu_gem_va_update_vm(adev, bo_va);
+		amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
 
 
 	drm_gem_object_unreference_unlocked(gobj);
 	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 	return r;

+ 8 - 8
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c

@@ -180,16 +180,16 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
 	if (vm) {
 	if (vm) {
 		/* do context switch */
 		/* do context switch */
 		amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update);
 		amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update);
-	}
 
 
-	if (vm && ring->funcs->emit_gds_switch)
-		amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id,
-					    ib->gds_base, ib->gds_size,
-					    ib->gws_base, ib->gws_size,
-					    ib->oa_base, ib->oa_size);
+		if (ring->funcs->emit_gds_switch)
+			amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id,
+						    ib->gds_base, ib->gds_size,
+						    ib->gws_base, ib->gws_size,
+						    ib->oa_base, ib->oa_size);
 
 
-	if (ring->funcs->emit_hdp_flush)
-		amdgpu_ring_emit_hdp_flush(ring);
+		if (ring->funcs->emit_hdp_flush)
+			amdgpu_ring_emit_hdp_flush(ring);
+	}
 
 
 	old_ctx = ring->current_ctx;
 	old_ctx = ring->current_ctx;
 	for (i = 0; i < num_ibs; ++i) {
 	for (i = 0; i < num_ibs; ++i) {

+ 3 - 3
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

@@ -235,7 +235,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
 
 
 		for (i = 0; i < adev->num_ip_blocks; i++) {
 		for (i = 0; i < adev->num_ip_blocks; i++) {
 			if (adev->ip_blocks[i].type == type &&
 			if (adev->ip_blocks[i].type == type &&
-			    adev->ip_block_enabled[i]) {
+			    adev->ip_block_status[i].valid) {
 				ip.hw_ip_version_major = adev->ip_blocks[i].major;
 				ip.hw_ip_version_major = adev->ip_blocks[i].major;
 				ip.hw_ip_version_minor = adev->ip_blocks[i].minor;
 				ip.hw_ip_version_minor = adev->ip_blocks[i].minor;
 				ip.capabilities_flags = 0;
 				ip.capabilities_flags = 0;
@@ -274,7 +274,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
 
 
 		for (i = 0; i < adev->num_ip_blocks; i++)
 		for (i = 0; i < adev->num_ip_blocks; i++)
 			if (adev->ip_blocks[i].type == type &&
 			if (adev->ip_blocks[i].type == type &&
-			    adev->ip_block_enabled[i] &&
+			    adev->ip_block_status[i].valid &&
 			    count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
 			    count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
 				count++;
 				count++;
 
 
@@ -416,7 +416,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
 		return n ? -EFAULT : 0;
 		return n ? -EFAULT : 0;
 	}
 	}
 	case AMDGPU_INFO_DEV_INFO: {
 	case AMDGPU_INFO_DEV_INFO: {
-		struct drm_amdgpu_info_device dev_info;
+		struct drm_amdgpu_info_device dev_info = {};
 		struct amdgpu_cu_info cu_info;
 		struct amdgpu_cu_info cu_info;
 
 
 		dev_info.device_id = dev->pdev->device;
 		dev_info.device_id = dev->pdev->device;

+ 35 - 11
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c

@@ -2561,7 +2561,7 @@ static bool gfx_v7_0_ring_emit_semaphore(struct amdgpu_ring *ring,
  * sheduling on the ring.  This function schedules the IB
  * sheduling on the ring.  This function schedules the IB
  * on the gfx ring for execution by the GPU.
  * on the gfx ring for execution by the GPU.
  */
  */
-static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
+static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 				  struct amdgpu_ib *ib)
 				  struct amdgpu_ib *ib)
 {
 {
 	bool need_ctx_switch = ring->current_ctx != ib->ctx;
 	bool need_ctx_switch = ring->current_ctx != ib->ctx;
@@ -2569,15 +2569,10 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
 	u32 next_rptr = ring->wptr + 5;
 	u32 next_rptr = ring->wptr + 5;
 
 
 	/* drop the CE preamble IB for the same context */
 	/* drop the CE preamble IB for the same context */
-	if ((ring->type == AMDGPU_RING_TYPE_GFX) &&
-	    (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
-	    !need_ctx_switch)
+	if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch)
 		return;
 		return;
 
 
-	if (ring->type == AMDGPU_RING_TYPE_COMPUTE)
-		control |= INDIRECT_BUFFER_VALID;
-
-	if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX)
+	if (need_ctx_switch)
 		next_rptr += 2;
 		next_rptr += 2;
 
 
 	next_rptr += 4;
 	next_rptr += 4;
@@ -2588,7 +2583,7 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
 	amdgpu_ring_write(ring, next_rptr);
 	amdgpu_ring_write(ring, next_rptr);
 
 
 	/* insert SWITCH_BUFFER packet before first IB in the ring frame */
 	/* insert SWITCH_BUFFER packet before first IB in the ring frame */
-	if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) {
+	if (need_ctx_switch) {
 		amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
 		amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
 		amdgpu_ring_write(ring, 0);
 		amdgpu_ring_write(ring, 0);
 	}
 	}
@@ -2611,6 +2606,35 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
 	amdgpu_ring_write(ring, control);
 	amdgpu_ring_write(ring, control);
 }
 }
 
 
+static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
+				  struct amdgpu_ib *ib)
+{
+	u32 header, control = 0;
+	u32 next_rptr = ring->wptr + 5;
+
+	control |= INDIRECT_BUFFER_VALID;
+	next_rptr += 4;
+	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+	amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM);
+	amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
+	amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff);
+	amdgpu_ring_write(ring, next_rptr);
+
+	header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
+
+	control |= ib->length_dw |
+			   (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0);
+
+	amdgpu_ring_write(ring, header);
+	amdgpu_ring_write(ring,
+#ifdef __BIG_ENDIAN
+					  (2 << 0) |
+#endif
+					  (ib->gpu_addr & 0xFFFFFFFC));
+	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
+	amdgpu_ring_write(ring, control);
+}
+
 /**
 /**
  * gfx_v7_0_ring_test_ib - basic ring IB test
  * gfx_v7_0_ring_test_ib - basic ring IB test
  *
  *
@@ -5555,7 +5579,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
 	.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
 	.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
 	.set_wptr = gfx_v7_0_ring_set_wptr_gfx,
 	.set_wptr = gfx_v7_0_ring_set_wptr_gfx,
 	.parse_cs = NULL,
 	.parse_cs = NULL,
-	.emit_ib = gfx_v7_0_ring_emit_ib,
+	.emit_ib = gfx_v7_0_ring_emit_ib_gfx,
 	.emit_fence = gfx_v7_0_ring_emit_fence_gfx,
 	.emit_fence = gfx_v7_0_ring_emit_fence_gfx,
 	.emit_semaphore = gfx_v7_0_ring_emit_semaphore,
 	.emit_semaphore = gfx_v7_0_ring_emit_semaphore,
 	.emit_vm_flush = gfx_v7_0_ring_emit_vm_flush,
 	.emit_vm_flush = gfx_v7_0_ring_emit_vm_flush,
@@ -5571,7 +5595,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
 	.get_wptr = gfx_v7_0_ring_get_wptr_compute,
 	.get_wptr = gfx_v7_0_ring_get_wptr_compute,
 	.set_wptr = gfx_v7_0_ring_set_wptr_compute,
 	.set_wptr = gfx_v7_0_ring_set_wptr_compute,
 	.parse_cs = NULL,
 	.parse_cs = NULL,
-	.emit_ib = gfx_v7_0_ring_emit_ib,
+	.emit_ib = gfx_v7_0_ring_emit_ib_compute,
 	.emit_fence = gfx_v7_0_ring_emit_fence_compute,
 	.emit_fence = gfx_v7_0_ring_emit_fence_compute,
 	.emit_semaphore = gfx_v7_0_ring_emit_semaphore,
 	.emit_semaphore = gfx_v7_0_ring_emit_semaphore,
 	.emit_vm_flush = gfx_v7_0_ring_emit_vm_flush,
 	.emit_vm_flush = gfx_v7_0_ring_emit_vm_flush,

+ 36 - 11
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c

@@ -3753,7 +3753,7 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 	amdgpu_ring_write(ring, 0x20); /* poll interval */
 	amdgpu_ring_write(ring, 0x20); /* poll interval */
 }
 }
 
 
-static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring,
+static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 				  struct amdgpu_ib *ib)
 				  struct amdgpu_ib *ib)
 {
 {
 	bool need_ctx_switch = ring->current_ctx != ib->ctx;
 	bool need_ctx_switch = ring->current_ctx != ib->ctx;
@@ -3761,15 +3761,10 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring,
 	u32 next_rptr = ring->wptr + 5;
 	u32 next_rptr = ring->wptr + 5;
 
 
 	/* drop the CE preamble IB for the same context */
 	/* drop the CE preamble IB for the same context */
-	if ((ring->type == AMDGPU_RING_TYPE_GFX) &&
-	    (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
-	    !need_ctx_switch)
+	if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch)
 		return;
 		return;
 
 
-	if (ring->type == AMDGPU_RING_TYPE_COMPUTE)
-		control |= INDIRECT_BUFFER_VALID;
-
-	if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX)
+	if (need_ctx_switch)
 		next_rptr += 2;
 		next_rptr += 2;
 
 
 	next_rptr += 4;
 	next_rptr += 4;
@@ -3780,7 +3775,7 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring,
 	amdgpu_ring_write(ring, next_rptr);
 	amdgpu_ring_write(ring, next_rptr);
 
 
 	/* insert SWITCH_BUFFER packet before first IB in the ring frame */
 	/* insert SWITCH_BUFFER packet before first IB in the ring frame */
-	if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) {
+	if (need_ctx_switch) {
 		amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
 		amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
 		amdgpu_ring_write(ring, 0);
 		amdgpu_ring_write(ring, 0);
 	}
 	}
@@ -3803,6 +3798,36 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring,
 	amdgpu_ring_write(ring, control);
 	amdgpu_ring_write(ring, control);
 }
 }
 
 
+static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
+				  struct amdgpu_ib *ib)
+{
+	u32 header, control = 0;
+	u32 next_rptr = ring->wptr + 5;
+
+	control |= INDIRECT_BUFFER_VALID;
+
+	next_rptr += 4;
+	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+	amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM);
+	amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
+	amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff);
+	amdgpu_ring_write(ring, next_rptr);
+
+	header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
+
+	control |= ib->length_dw |
+			   (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0);
+
+	amdgpu_ring_write(ring, header);
+	amdgpu_ring_write(ring,
+#ifdef __BIG_ENDIAN
+					  (2 << 0) |
+#endif
+					  (ib->gpu_addr & 0xFFFFFFFC));
+	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
+	amdgpu_ring_write(ring, control);
+}
+
 static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
 static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
 					 u64 seq, unsigned flags)
 					 u64 seq, unsigned flags)
 {
 {
@@ -4224,7 +4249,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
 	.get_wptr = gfx_v8_0_ring_get_wptr_gfx,
 	.get_wptr = gfx_v8_0_ring_get_wptr_gfx,
 	.set_wptr = gfx_v8_0_ring_set_wptr_gfx,
 	.set_wptr = gfx_v8_0_ring_set_wptr_gfx,
 	.parse_cs = NULL,
 	.parse_cs = NULL,
-	.emit_ib = gfx_v8_0_ring_emit_ib,
+	.emit_ib = gfx_v8_0_ring_emit_ib_gfx,
 	.emit_fence = gfx_v8_0_ring_emit_fence_gfx,
 	.emit_fence = gfx_v8_0_ring_emit_fence_gfx,
 	.emit_semaphore = gfx_v8_0_ring_emit_semaphore,
 	.emit_semaphore = gfx_v8_0_ring_emit_semaphore,
 	.emit_vm_flush = gfx_v8_0_ring_emit_vm_flush,
 	.emit_vm_flush = gfx_v8_0_ring_emit_vm_flush,
@@ -4240,7 +4265,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
 	.get_wptr = gfx_v8_0_ring_get_wptr_compute,
 	.get_wptr = gfx_v8_0_ring_get_wptr_compute,
 	.set_wptr = gfx_v8_0_ring_set_wptr_compute,
 	.set_wptr = gfx_v8_0_ring_set_wptr_compute,
 	.parse_cs = NULL,
 	.parse_cs = NULL,
-	.emit_ib = gfx_v8_0_ring_emit_ib,
+	.emit_ib = gfx_v8_0_ring_emit_ib_compute,
 	.emit_fence = gfx_v8_0_ring_emit_fence_compute,
 	.emit_fence = gfx_v8_0_ring_emit_fence_compute,
 	.emit_semaphore = gfx_v8_0_ring_emit_semaphore,
 	.emit_semaphore = gfx_v8_0_ring_emit_semaphore,
 	.emit_vm_flush = gfx_v8_0_ring_emit_vm_flush,
 	.emit_vm_flush = gfx_v8_0_ring_emit_vm_flush,

+ 5 - 3
drivers/gpu/drm/drm_atomic_helper.c

@@ -230,10 +230,12 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
 	}
 	}
 
 
 	connector_state->best_encoder = new_encoder;
 	connector_state->best_encoder = new_encoder;
-	idx = drm_crtc_index(connector_state->crtc);
+	if (connector_state->crtc) {
+		idx = drm_crtc_index(connector_state->crtc);
 
 
-	crtc_state = state->crtc_states[idx];
-	crtc_state->mode_changed = true;
+		crtc_state = state->crtc_states[idx];
+		crtc_state->mode_changed = true;
+	}
 
 
 	DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n",
 	DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n",
 			 connector->base.id,
 			 connector->base.id,

+ 8 - 9
drivers/gpu/drm/i915/i915_drv.h

@@ -3303,15 +3303,14 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
 #define I915_READ64(reg)	dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true)
 #define I915_READ64(reg)	dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true)
 
 
 #define I915_READ64_2x32(lower_reg, upper_reg) ({			\
 #define I915_READ64_2x32(lower_reg, upper_reg) ({			\
-		u32 upper = I915_READ(upper_reg);			\
-		u32 lower = I915_READ(lower_reg);			\
-		u32 tmp = I915_READ(upper_reg);				\
-		if (upper != tmp) {					\
-			upper = tmp;					\
-			lower = I915_READ(lower_reg);			\
-			WARN_ON(I915_READ(upper_reg) != upper);		\
-		}							\
-		(u64)upper << 32 | lower; })
+	u32 upper, lower, tmp;						\
+	tmp = I915_READ(upper_reg);					\
+	do {								\
+		upper = tmp;						\
+		lower = I915_READ(lower_reg);				\
+		tmp = I915_READ(upper_reg);				\
+	} while (upper != tmp);						\
+	(u64)upper << 32 | lower; })
 
 
 #define POSTING_READ(reg)	(void)I915_READ_NOTRACE(reg)
 #define POSTING_READ(reg)	(void)I915_READ_NOTRACE(reg)
 #define POSTING_READ16(reg)	(void)I915_READ16_NOTRACE(reg)
 #define POSTING_READ16(reg)	(void)I915_READ16_NOTRACE(reg)

+ 11 - 0
drivers/gpu/drm/i915/i915_gem_gtt.c

@@ -1923,6 +1923,17 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 		vma->vm->insert_entries(vma->vm, pages,
 		vma->vm->insert_entries(vma->vm, pages,
 					vma->node.start,
 					vma->node.start,
 					cache_level, pte_flags);
 					cache_level, pte_flags);
+
+		/* Note the inconsistency here is due to absence of the
+		 * aliasing ppgtt on gen4 and earlier. Though we always
+		 * request PIN_USER for execbuffer (translated to LOCAL_BIND),
+		 * without the appgtt, we cannot honour that request and so
+		 * must substitute it with a global binding. Since we do this
+		 * behind the upper layers back, we need to explicitly set
+		 * the bound flag ourselves.
+		 */
+		vma->bound |= GLOBAL_BIND;
+
 	}
 	}
 
 
 	if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {
 	if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {

+ 4 - 1
drivers/gpu/drm/i915/i915_gem_tiling.c

@@ -464,7 +464,10 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
 	}
 	}
 
 
 	/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
 	/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
-	args->phys_swizzle_mode = args->swizzle_mode;
+	if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
+		args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN;
+	else
+		args->phys_swizzle_mode = args->swizzle_mode;
 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
 		args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
 		args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)

+ 3 - 1
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c

@@ -220,13 +220,15 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 	uint32_t op_mode = 0;
 	uint32_t op_mode = 0;
 	uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
 	uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
 	uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
 	uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
-	enum mdp4_frame_format frame_type = mdp4_get_frame_format(fb);
+	enum mdp4_frame_format frame_type;
 
 
 	if (!(crtc && fb)) {
 	if (!(crtc && fb)) {
 		DBG("%s: disabled!", mdp4_plane->name);
 		DBG("%s: disabled!", mdp4_plane->name);
 		return 0;
 		return 0;
 	}
 	}
 
 
+	frame_type = mdp4_get_frame_format(fb);
+
 	/* src values are in Q16 fixed point, convert to integer: */
 	/* src values are in Q16 fixed point, convert to integer: */
 	src_x = src_x >> 16;
 	src_x = src_x >> 16;
 	src_y = src_y >> 16;
 	src_y = src_y >> 16;

+ 13 - 0
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c

@@ -76,7 +76,20 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st
 
 
 static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 {
 {
+	int i;
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+	int nplanes = mdp5_kms->dev->mode_config.num_total_plane;
+
+	for (i = 0; i < nplanes; i++) {
+		struct drm_plane *plane = state->planes[i];
+		struct drm_plane_state *plane_state = state->plane_states[i];
+
+		if (!plane)
+			continue;
+
+		mdp5_plane_complete_commit(plane, plane_state);
+	}
+
 	mdp5_disable(mdp5_kms);
 	mdp5_disable(mdp5_kms);
 }
 }
 
 

+ 2 - 0
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h

@@ -227,6 +227,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane,
 		struct drm_mode_object *obj);
 		struct drm_mode_object *obj);
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
 void mdp5_plane_complete_flip(struct drm_plane *plane);
 void mdp5_plane_complete_flip(struct drm_plane *plane);
+void mdp5_plane_complete_commit(struct drm_plane *plane,
+	struct drm_plane_state *state);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 		enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset);
 		enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset);

+ 14 - 19
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c

@@ -31,8 +31,6 @@ struct mdp5_plane {
 
 
 	uint32_t nformats;
 	uint32_t nformats;
 	uint32_t formats[32];
 	uint32_t formats[32];
-
-	bool enabled;
 };
 };
 #define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base)
 #define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base)
 
 
@@ -56,22 +54,6 @@ static bool plane_enabled(struct drm_plane_state *state)
 	return state->fb && state->crtc;
 	return state->fb && state->crtc;
 }
 }
 
 
-static int mdp5_plane_disable(struct drm_plane *plane)
-{
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-	struct mdp5_kms *mdp5_kms = get_kms(plane);
-	enum mdp5_pipe pipe = mdp5_plane->pipe;
-
-	DBG("%s: disable", mdp5_plane->name);
-
-	if (mdp5_kms) {
-		/* Release the memory we requested earlier from the SMP: */
-		mdp5_smp_release(mdp5_kms->smp, pipe);
-	}
-
-	return 0;
-}
-
 static void mdp5_plane_destroy(struct drm_plane *plane)
 static void mdp5_plane_destroy(struct drm_plane *plane)
 {
 {
 	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
 	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
@@ -224,7 +206,6 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane,
 
 
 	if (!plane_enabled(state)) {
 	if (!plane_enabled(state)) {
 		to_mdp5_plane_state(state)->pending = true;
 		to_mdp5_plane_state(state)->pending = true;
-		mdp5_plane_disable(plane);
 	} else if (to_mdp5_plane_state(state)->mode_changed) {
 	} else if (to_mdp5_plane_state(state)->mode_changed) {
 		int ret;
 		int ret;
 		to_mdp5_plane_state(state)->pending = true;
 		to_mdp5_plane_state(state)->pending = true;
@@ -602,6 +583,20 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
 	return mdp5_plane->flush_mask;
 	return mdp5_plane->flush_mask;
 }
 }
 
 
+/* called after vsync in thread context */
+void mdp5_plane_complete_commit(struct drm_plane *plane,
+	struct drm_plane_state *state)
+{
+	struct mdp5_kms *mdp5_kms = get_kms(plane);
+	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+	enum mdp5_pipe pipe = mdp5_plane->pipe;
+
+	if (!plane_enabled(plane->state)) {
+		DBG("%s: free SMP", mdp5_plane->name);
+		mdp5_smp_release(mdp5_kms->smp, pipe);
+	}
+}
+
 /* initialize plane */
 /* initialize plane */
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 		enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset)
 		enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset)

+ 74 - 13
drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c

@@ -34,22 +34,44 @@
  * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0).
  * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0).
  *
  *
  * For each block that can be dynamically allocated, it can be either
  * For each block that can be dynamically allocated, it can be either
- * free, or pending/in-use by a client. The updates happen in three steps:
+ *     free:
+ *     The block is free.
+ *
+ *     pending:
+ *     The block is allocated to some client and not free.
+ *
+ *     configured:
+ *     The block is allocated to some client, and assigned to that
+ *     client in MDP5_MDP_SMP_ALLOC registers.
+ *
+ *     inuse:
+ *     The block is being actively used by a client.
+ *
+ * The updates happen in the following steps:
  *
  *
  *  1) mdp5_smp_request():
  *  1) mdp5_smp_request():
  *     When plane scanout is setup, calculate required number of
  *     When plane scanout is setup, calculate required number of
- *     blocks needed per client, and request.  Blocks not inuse or
- *     pending by any other client are added to client's pending
- *     set.
+ *     blocks needed per client, and request. Blocks neither inuse nor
+ *     configured nor pending by any other client are added to client's
+ *     pending set.
+ *     For shrinking, blocks in pending but not in configured can be freed
+ *     directly, but those already in configured will be freed later by
+ *     mdp5_smp_commit.
  *
  *
  *  2) mdp5_smp_configure():
  *  2) mdp5_smp_configure():
  *     As hw is programmed, before FLUSH, MDP5_MDP_SMP_ALLOC registers
  *     As hw is programmed, before FLUSH, MDP5_MDP_SMP_ALLOC registers
  *     are configured for the union(pending, inuse)
  *     are configured for the union(pending, inuse)
+ *     Current pending is copied to configured.
+ *     It is assumed that mdp5_smp_request and mdp5_smp_configure not run
+ *     concurrently for the same pipe.
  *
  *
  *  3) mdp5_smp_commit():
  *  3) mdp5_smp_commit():
- *     After next vblank, copy pending -> inuse.  Optionally update
+ *     After next vblank, copy configured -> inuse.  Optionally update
  *     MDP5_SMP_ALLOC registers if there are newly unused blocks
  *     MDP5_SMP_ALLOC registers if there are newly unused blocks
  *
  *
+ *  4) mdp5_smp_release():
+ *     Must be called after the pipe is disabled and no longer uses any SMB
+ *
  * On the next vblank after changes have been committed to hw, the
  * On the next vblank after changes have been committed to hw, the
  * client's pending blocks become it's in-use blocks (and no-longer
  * client's pending blocks become it's in-use blocks (and no-longer
  * in-use blocks become available to other clients).
  * in-use blocks become available to other clients).
@@ -77,6 +99,9 @@ struct mdp5_smp {
 	struct mdp5_client_smp_state client_state[MAX_CLIENTS];
 	struct mdp5_client_smp_state client_state[MAX_CLIENTS];
 };
 };
 
 
+static void update_smp_state(struct mdp5_smp *smp,
+		u32 cid, mdp5_smp_state_t *assigned);
+
 static inline
 static inline
 struct mdp5_kms *get_kms(struct mdp5_smp *smp)
 struct mdp5_kms *get_kms(struct mdp5_smp *smp)
 {
 {
@@ -149,7 +174,12 @@ static int smp_request_block(struct mdp5_smp *smp,
 		for (i = cur_nblks; i > nblks; i--) {
 		for (i = cur_nblks; i > nblks; i--) {
 			int blk = find_first_bit(ps->pending, cnt);
 			int blk = find_first_bit(ps->pending, cnt);
 			clear_bit(blk, ps->pending);
 			clear_bit(blk, ps->pending);
-			/* don't clear in global smp_state until _commit() */
+
+			/* clear in global smp_state if not in configured
+			 * otherwise until _commit()
+			 */
+			if (!test_bit(blk, ps->configured))
+				clear_bit(blk, smp->state);
 		}
 		}
 	}
 	}
 
 
@@ -223,10 +253,33 @@ int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe, u32 fmt, u32 wid
 /* Release SMP blocks for all clients of the pipe */
 /* Release SMP blocks for all clients of the pipe */
 void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe)
 void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe)
 {
 {
-	int i, nblks;
+	int i;
+	unsigned long flags;
+	int cnt = smp->blk_cnt;
+
+	for (i = 0; i < pipe2nclients(pipe); i++) {
+		mdp5_smp_state_t assigned;
+		u32 cid = pipe2client(pipe, i);
+		struct mdp5_client_smp_state *ps = &smp->client_state[cid];
+
+		spin_lock_irqsave(&smp->state_lock, flags);
+
+		/* clear hw assignment */
+		bitmap_or(assigned, ps->inuse, ps->configured, cnt);
+		update_smp_state(smp, CID_UNUSED, &assigned);
+
+		/* free to global pool */
+		bitmap_andnot(smp->state, smp->state, ps->pending, cnt);
+		bitmap_andnot(smp->state, smp->state, assigned, cnt);
+
+		/* clear client's infor */
+		bitmap_zero(ps->pending, cnt);
+		bitmap_zero(ps->configured, cnt);
+		bitmap_zero(ps->inuse, cnt);
+
+		spin_unlock_irqrestore(&smp->state_lock, flags);
+	}
 
 
-	for (i = 0, nblks = 0; i < pipe2nclients(pipe); i++)
-		smp_request_block(smp, pipe2client(pipe, i), 0);
 	set_fifo_thresholds(smp, pipe, 0);
 	set_fifo_thresholds(smp, pipe, 0);
 }
 }
 
 
@@ -274,12 +327,20 @@ void mdp5_smp_configure(struct mdp5_smp *smp, enum mdp5_pipe pipe)
 		u32 cid = pipe2client(pipe, i);
 		u32 cid = pipe2client(pipe, i);
 		struct mdp5_client_smp_state *ps = &smp->client_state[cid];
 		struct mdp5_client_smp_state *ps = &smp->client_state[cid];
 
 
-		bitmap_or(assigned, ps->inuse, ps->pending, cnt);
+		/*
+		 * if vblank has not happened since last smp_configure
+		 * skip the configure for now
+		 */
+		if (!bitmap_equal(ps->inuse, ps->configured, cnt))
+			continue;
+
+		bitmap_copy(ps->configured, ps->pending, cnt);
+		bitmap_or(assigned, ps->inuse, ps->configured, cnt);
 		update_smp_state(smp, cid, &assigned);
 		update_smp_state(smp, cid, &assigned);
 	}
 	}
 }
 }
 
 
-/* step #3: after vblank, copy pending -> inuse: */
+/* step #3: after vblank, copy configured -> inuse: */
 void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe)
 void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe)
 {
 {
 	int cnt = smp->blk_cnt;
 	int cnt = smp->blk_cnt;
@@ -295,7 +356,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe)
 		 * using, which can be released and made available to other
 		 * using, which can be released and made available to other
 		 * clients:
 		 * clients:
 		 */
 		 */
-		if (bitmap_andnot(released, ps->inuse, ps->pending, cnt)) {
+		if (bitmap_andnot(released, ps->inuse, ps->configured, cnt)) {
 			unsigned long flags;
 			unsigned long flags;
 
 
 			spin_lock_irqsave(&smp->state_lock, flags);
 			spin_lock_irqsave(&smp->state_lock, flags);
@@ -306,7 +367,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe)
 			update_smp_state(smp, CID_UNUSED, &released);
 			update_smp_state(smp, CID_UNUSED, &released);
 		}
 		}
 
 
-		bitmap_copy(ps->inuse, ps->pending, cnt);
+		bitmap_copy(ps->inuse, ps->configured, cnt);
 	}
 	}
 }
 }
 
 

+ 1 - 0
drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h

@@ -23,6 +23,7 @@
 
 
 struct mdp5_client_smp_state {
 struct mdp5_client_smp_state {
 	mdp5_smp_state_t inuse;
 	mdp5_smp_state_t inuse;
+	mdp5_smp_state_t configured;
 	mdp5_smp_state_t pending;
 	mdp5_smp_state_t pending;
 };
 };
 
 

+ 2 - 6
drivers/gpu/drm/msm/msm_atomic.c

@@ -283,12 +283,8 @@ int msm_atomic_commit(struct drm_device *dev,
 
 
 	timeout = ktime_add_ms(ktime_get(), 1000);
 	timeout = ktime_add_ms(ktime_get(), 1000);
 
 
-	ret = msm_wait_fence_interruptable(dev, c->fence, &timeout);
-	if (ret) {
-		WARN_ON(ret);  // TODO unswap state back?  or??
-		commit_destroy(c);
-		return ret;
-	}
+	/* uninterruptible wait */
+	msm_wait_fence(dev, c->fence, &timeout, false);
 
 
 	complete_commit(c);
 	complete_commit(c);
 
 

+ 9 - 4
drivers/gpu/drm/msm/msm_drv.c

@@ -637,8 +637,8 @@ static void msm_debugfs_cleanup(struct drm_minor *minor)
  * Fences:
  * Fences:
  */
  */
 
 
-int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
-		ktime_t *timeout)
+int msm_wait_fence(struct drm_device *dev, uint32_t fence,
+		ktime_t *timeout , bool interruptible)
 {
 {
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_drm_private *priv = dev->dev_private;
 	int ret;
 	int ret;
@@ -667,7 +667,12 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
 			remaining_jiffies = timespec_to_jiffies(&ts);
 			remaining_jiffies = timespec_to_jiffies(&ts);
 		}
 		}
 
 
-		ret = wait_event_interruptible_timeout(priv->fence_event,
+		if (interruptible)
+			ret = wait_event_interruptible_timeout(priv->fence_event,
+				fence_completed(dev, fence),
+				remaining_jiffies);
+		else
+			ret = wait_event_timeout(priv->fence_event,
 				fence_completed(dev, fence),
 				fence_completed(dev, fence),
 				remaining_jiffies);
 				remaining_jiffies);
 
 
@@ -853,7 +858,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	return msm_wait_fence_interruptable(dev, args->fence, &timeout);
+	return msm_wait_fence(dev, args->fence, &timeout, true);
 }
 }
 
 
 static const struct drm_ioctl_desc msm_ioctls[] = {
 static const struct drm_ioctl_desc msm_ioctls[] = {

+ 2 - 2
drivers/gpu/drm/msm/msm_drv.h

@@ -164,8 +164,8 @@ int msm_atomic_commit(struct drm_device *dev,
 
 
 int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
 int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
 
 
-int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
-		ktime_t *timeout);
+int msm_wait_fence(struct drm_device *dev, uint32_t fence,
+		ktime_t *timeout, bool interruptible);
 int msm_queue_fence_cb(struct drm_device *dev,
 int msm_queue_fence_cb(struct drm_device *dev,
 		struct msm_fence_cb *cb, uint32_t fence);
 		struct msm_fence_cb *cb, uint32_t fence);
 void msm_update_fence(struct drm_device *dev, uint32_t fence);
 void msm_update_fence(struct drm_device *dev, uint32_t fence);

+ 1 - 1
drivers/gpu/drm/msm/msm_gem.c

@@ -460,7 +460,7 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 		if (op & MSM_PREP_NOSYNC)
 		if (op & MSM_PREP_NOSYNC)
 			timeout = NULL;
 			timeout = NULL;
 
 
-		ret = msm_wait_fence_interruptable(dev, fence, timeout);
+		ret = msm_wait_fence(dev, fence, timeout, true);
 	}
 	}
 
 
 	/* TODO cache maintenance */
 	/* TODO cache maintenance */

+ 6 - 2
drivers/gpu/drm/msm/msm_gem_prime.c

@@ -23,8 +23,12 @@
 struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
 struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
 {
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
-	BUG_ON(!msm_obj->sgt);  /* should have already pinned! */
-	return msm_obj->sgt;
+	int npages = obj->size >> PAGE_SHIFT;
+
+	if (WARN_ON(!msm_obj->pages))  /* should have already pinned! */
+		return NULL;
+
+	return drm_prime_pages_to_sg(msm_obj->pages, npages);
 }
 }
 
 
 void *msm_gem_prime_vmap(struct drm_gem_object *obj)
 void *msm_gem_prime_vmap(struct drm_gem_object *obj)

+ 3 - 0
drivers/gpu/drm/nouveau/nouveau_drm.c

@@ -128,6 +128,7 @@ nouveau_cli_destroy(struct nouveau_cli *cli)
 	nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL);
 	nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL);
 	nvif_client_fini(&cli->base);
 	nvif_client_fini(&cli->base);
 	usif_client_fini(cli);
 	usif_client_fini(cli);
+	kfree(cli);
 }
 }
 
 
 static void
 static void
@@ -865,8 +866,10 @@ nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv)
 
 
 	pm_runtime_get_sync(dev->dev);
 	pm_runtime_get_sync(dev->dev);
 
 
+	mutex_lock(&cli->mutex);
 	if (cli->abi16)
 	if (cli->abi16)
 		nouveau_abi16_fini(cli->abi16);
 		nouveau_abi16_fini(cli->abi16);
+	mutex_unlock(&cli->mutex);
 
 
 	mutex_lock(&drm->client.mutex);
 	mutex_lock(&drm->client.mutex);
 	list_del(&cli->head);
 	list_del(&cli->head);

+ 16 - 0
drivers/gpu/drm/nouveau/nouveau_platform.c

@@ -92,6 +92,8 @@ static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu)
 	return 0;
 	return 0;
 }
 }
 
 
+#if IS_ENABLED(CONFIG_IOMMU_API)
+
 static void nouveau_platform_probe_iommu(struct device *dev,
 static void nouveau_platform_probe_iommu(struct device *dev,
 					 struct nouveau_platform_gpu *gpu)
 					 struct nouveau_platform_gpu *gpu)
 {
 {
@@ -158,6 +160,20 @@ static void nouveau_platform_remove_iommu(struct device *dev,
 	}
 	}
 }
 }
 
 
+#else
+
+static void nouveau_platform_probe_iommu(struct device *dev,
+					 struct nouveau_platform_gpu *gpu)
+{
+}
+
+static void nouveau_platform_remove_iommu(struct device *dev,
+					  struct nouveau_platform_gpu *gpu)
+{
+}
+
+#endif
+
 static int nouveau_platform_probe(struct platform_device *pdev)
 static int nouveau_platform_probe(struct platform_device *pdev)
 {
 {
 	struct nouveau_platform_gpu *gpu;
 	struct nouveau_platform_gpu *gpu;

+ 9 - 0
drivers/gpu/drm/nouveau/nouveau_ttm.c

@@ -175,15 +175,24 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
 	node->page_shift = 12;
 	node->page_shift = 12;
 
 
 	switch (drm->device.info.family) {
 	switch (drm->device.info.family) {
+	case NV_DEVICE_INFO_V0_TNT:
+	case NV_DEVICE_INFO_V0_CELSIUS:
+	case NV_DEVICE_INFO_V0_KELVIN:
+	case NV_DEVICE_INFO_V0_RANKINE:
+	case NV_DEVICE_INFO_V0_CURIE:
+		break;
 	case NV_DEVICE_INFO_V0_TESLA:
 	case NV_DEVICE_INFO_V0_TESLA:
 		if (drm->device.info.chipset != 0x50)
 		if (drm->device.info.chipset != 0x50)
 			node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
 			node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
 		break;
 		break;
 	case NV_DEVICE_INFO_V0_FERMI:
 	case NV_DEVICE_INFO_V0_FERMI:
 	case NV_DEVICE_INFO_V0_KEPLER:
 	case NV_DEVICE_INFO_V0_KEPLER:
+	case NV_DEVICE_INFO_V0_MAXWELL:
 		node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
 		node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
 		break;
 		break;
 	default:
 	default:
+		NV_WARN(drm, "%s: unhandled family type %x\n", __func__,
+			drm->device.info.family);
 		break;
 		break;
 	}
 	}
 
 

+ 1 - 1
drivers/gpu/drm/nouveau/nv04_fbcon.c

@@ -203,7 +203,7 @@ nv04_fbcon_accel_init(struct fb_info *info)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	if (RING_SPACE(chan, 49)) {
+	if (RING_SPACE(chan, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) {
 		nouveau_fbcon_gpu_lockup(info);
 		nouveau_fbcon_gpu_lockup(info);
 		return 0;
 		return 0;
 	}
 	}

+ 1 - 1
drivers/gpu/drm/nouveau/nv50_display.c

@@ -979,7 +979,7 @@ nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update)
 {
 {
 	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
 	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
 
 
-	if (show && nv_crtc->cursor.nvbo)
+	if (show && nv_crtc->cursor.nvbo && nv_crtc->base.enabled)
 		nv50_crtc_cursor_show(nv_crtc);
 		nv50_crtc_cursor_show(nv_crtc);
 	else
 	else
 		nv50_crtc_cursor_hide(nv_crtc);
 		nv50_crtc_cursor_hide(nv_crtc);

+ 2 - 1
drivers/gpu/drm/nouveau/nv50_fbcon.c

@@ -188,7 +188,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	ret = RING_SPACE(chan, 59);
+	ret = RING_SPACE(chan, 58);
 	if (ret) {
 	if (ret) {
 		nouveau_fbcon_gpu_lockup(info);
 		nouveau_fbcon_gpu_lockup(info);
 		return ret;
 		return ret;
@@ -252,6 +252,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
 	OUT_RING(chan, info->var.yres_virtual);
 	OUT_RING(chan, info->var.yres_virtual);
 	OUT_RING(chan, upper_32_bits(fb->vma.offset));
 	OUT_RING(chan, upper_32_bits(fb->vma.offset));
 	OUT_RING(chan, lower_32_bits(fb->vma.offset));
 	OUT_RING(chan, lower_32_bits(fb->vma.offset));
+	FIRE_RING(chan);
 
 
 	return 0;
 	return 0;
 }
 }

+ 1 - 1
drivers/gpu/drm/nouveau/nvc0_fbcon.c

@@ -188,7 +188,7 @@ nvc0_fbcon_accel_init(struct fb_info *info)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	ret = RING_SPACE(chan, 60);
+	ret = RING_SPACE(chan, 58);
 	if (ret) {
 	if (ret) {
 		WARN_ON(1);
 		WARN_ON(1);
 		nouveau_fbcon_gpu_lockup(info);
 		nouveau_fbcon_gpu_lockup(info);

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c

@@ -809,7 +809,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
 		case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
 		case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
 		default:
 		default:
 			nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
 			nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
-			return 0x0000;
+			return NULL;
 		}
 		}
 	}
 	}
 
 

+ 21 - 8
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c

@@ -165,15 +165,31 @@ gk104_fifo_context_attach(struct nvkm_object *parent,
 	return 0;
 	return 0;
 }
 }
 
 
+static int
+gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
+{
+	struct nvkm_object *obj = (void *)chan;
+	struct gk104_fifo_priv *priv = (void *)obj->engine;
+
+	nv_wr32(priv, 0x002634, chan->base.chid);
+	if (!nv_wait(priv, 0x002634, 0x100000, 0x000000)) {
+		nv_error(priv, "channel %d [%s] kick timeout\n",
+			 chan->base.chid, nvkm_client_name(chan));
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
 static int
 static int
 gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
 gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
 			  struct nvkm_object *object)
 			  struct nvkm_object *object)
 {
 {
 	struct nvkm_bar *bar = nvkm_bar(parent);
 	struct nvkm_bar *bar = nvkm_bar(parent);
-	struct gk104_fifo_priv *priv = (void *)parent->engine;
 	struct gk104_fifo_base *base = (void *)parent->parent;
 	struct gk104_fifo_base *base = (void *)parent->parent;
 	struct gk104_fifo_chan *chan = (void *)parent;
 	struct gk104_fifo_chan *chan = (void *)parent;
 	u32 addr;
 	u32 addr;
+	int ret;
 
 
 	switch (nv_engidx(object->engine)) {
 	switch (nv_engidx(object->engine)) {
 	case NVDEV_ENGINE_SW    : return 0;
 	case NVDEV_ENGINE_SW    : return 0;
@@ -188,13 +204,9 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	nv_wr32(priv, 0x002634, chan->base.chid);
-	if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) {
-		nv_error(priv, "channel %d [%s] kick timeout\n",
-			 chan->base.chid, nvkm_client_name(chan));
-		if (suspend)
-			return -EBUSY;
-	}
+	ret = gk104_fifo_chan_kick(chan);
+	if (ret && suspend)
+		return ret;
 
 
 	if (addr) {
 	if (addr) {
 		nv_wo32(base, addr + 0x00, 0x00000000);
 		nv_wo32(base, addr + 0x00, 0x00000000);
@@ -319,6 +331,7 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
 		gk104_fifo_runlist_update(priv, chan->engine);
 		gk104_fifo_runlist_update(priv, chan->engine);
 	}
 	}
 
 
+	gk104_fifo_chan_kick(chan);
 	nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
 	nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
 	return nvkm_fifo_channel_fini(&chan->base, suspend);
 	return nvkm_fifo_channel_fini(&chan->base, suspend);
 }
 }

+ 38 - 1
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c

@@ -663,6 +663,37 @@ gf100_gr_zbc_init(struct gf100_gr_priv *priv)
 		gf100_gr_zbc_clear_depth(priv, index);
 		gf100_gr_zbc_clear_depth(priv, index);
 }
 }
 
 
+/**
+ * Wait until GR goes idle. GR is considered idle if it is disabled by the
+ * MC (0x200) register, or GR is not busy and a context switch is not in
+ * progress.
+ */
+int
+gf100_gr_wait_idle(struct gf100_gr_priv *priv)
+{
+	unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000);
+	bool gr_enabled, ctxsw_active, gr_busy;
+
+	do {
+		/*
+		 * required to make sure FIFO_ENGINE_STATUS (0x2640) is
+		 * up-to-date
+		 */
+		nv_rd32(priv, 0x400700);
+
+		gr_enabled = nv_rd32(priv, 0x200) & 0x1000;
+		ctxsw_active = nv_rd32(priv, 0x2640) & 0x8000;
+		gr_busy = nv_rd32(priv, 0x40060c) & 0x1;
+
+		if (!gr_enabled || (!gr_busy && !ctxsw_active))
+			return 0;
+	} while (time_before(jiffies, end_jiffies));
+
+	nv_error(priv, "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n",
+		 gr_enabled, ctxsw_active, gr_busy);
+	return -EAGAIN;
+}
+
 void
 void
 gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p)
 gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p)
 {
 {
@@ -699,7 +730,13 @@ gf100_gr_icmd(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p)
 
 
 		while (addr < next) {
 		while (addr < next) {
 			nv_wr32(priv, 0x400200, addr);
 			nv_wr32(priv, 0x400200, addr);
-			nv_wait(priv, 0x400700, 0x00000002, 0x00000000);
+			/**
+			 * Wait for GR to go idle after submitting a
+			 * GO_IDLE bundle
+			 */
+			if ((addr & 0xffff) == 0xe100)
+				gf100_gr_wait_idle(priv);
+			nv_wait(priv, 0x400700, 0x00000004, 0x00000000);
 			addr += init->pitch;
 			addr += init->pitch;
 		}
 		}
 	}
 	}

+ 1 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h

@@ -181,6 +181,7 @@ struct gf100_gr_oclass {
 	int ppc_nr;
 	int ppc_nr;
 };
 };
 
 
+int  gf100_gr_wait_idle(struct gf100_gr_priv *);
 void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *);
 void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *);
 void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *);
 void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *);
 void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *);
 void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *);

+ 8 - 6
drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c

@@ -332,9 +332,12 @@ static void
 nvkm_perfctx_dtor(struct nvkm_object *object)
 nvkm_perfctx_dtor(struct nvkm_object *object)
 {
 {
 	struct nvkm_pm *ppm = (void *)object->engine;
 	struct nvkm_pm *ppm = (void *)object->engine;
+	struct nvkm_perfctx *ctx = (void *)object;
+
 	mutex_lock(&nv_subdev(ppm)->mutex);
 	mutex_lock(&nv_subdev(ppm)->mutex);
-	nvkm_engctx_destroy(&ppm->context->base);
-	ppm->context = NULL;
+	nvkm_engctx_destroy(&ctx->base);
+	if (ppm->context == ctx)
+		ppm->context = NULL;
 	mutex_unlock(&nv_subdev(ppm)->mutex);
 	mutex_unlock(&nv_subdev(ppm)->mutex);
 }
 }
 
 
@@ -355,12 +358,11 @@ nvkm_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 	mutex_lock(&nv_subdev(ppm)->mutex);
 	mutex_lock(&nv_subdev(ppm)->mutex);
 	if (ppm->context == NULL)
 	if (ppm->context == NULL)
 		ppm->context = ctx;
 		ppm->context = ctx;
-	mutex_unlock(&nv_subdev(ppm)->mutex);
-
 	if (ctx != ppm->context)
 	if (ctx != ppm->context)
-		return -EBUSY;
+		ret = -EBUSY;
+	mutex_unlock(&nv_subdev(ppm)->mutex);
 
 
-	return 0;
+	return ret;
 }
 }
 
 
 struct nvkm_oclass
 struct nvkm_oclass

+ 40 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c

@@ -1284,6 +1284,44 @@ init_zm_reg_sequence(struct nvbios_init *init)
 	}
 	}
 }
 }
 
 
+/**
+ * INIT_PLL_INDIRECT - opcode 0x59
+ *
+ */
+static void
+init_pll_indirect(struct nvbios_init *init)
+{
+	struct nvkm_bios *bios = init->bios;
+	u32  reg = nv_ro32(bios, init->offset + 1);
+	u16 addr = nv_ro16(bios, init->offset + 5);
+	u32 freq = (u32)nv_ro16(bios, addr) * 1000;
+
+	trace("PLL_INDIRECT\tR[0x%06x] =PLL= VBIOS[%04x] = %dkHz\n",
+	      reg, addr, freq);
+	init->offset += 7;
+
+	init_prog_pll(init, reg, freq);
+}
+
+/**
+ * INIT_ZM_REG_INDIRECT - opcode 0x5a
+ *
+ */
+static void
+init_zm_reg_indirect(struct nvbios_init *init)
+{
+	struct nvkm_bios *bios = init->bios;
+	u32  reg = nv_ro32(bios, init->offset + 1);
+	u16 addr = nv_ro16(bios, init->offset + 5);
+	u32 data = nv_ro32(bios, addr);
+
+	trace("ZM_REG_INDIRECT\tR[0x%06x] = VBIOS[0x%04x] = 0x%08x\n",
+	      reg, addr, data);
+	init->offset += 7;
+
+	init_wr32(init, addr, data);
+}
+
 /**
 /**
  * INIT_SUB_DIRECT - opcode 0x5b
  * INIT_SUB_DIRECT - opcode 0x5b
  *
  *
@@ -2145,6 +2183,8 @@ static struct nvbios_init_opcode {
 	[0x56] = { init_condition_time },
 	[0x56] = { init_condition_time },
 	[0x57] = { init_ltime },
 	[0x57] = { init_ltime },
 	[0x58] = { init_zm_reg_sequence },
 	[0x58] = { init_zm_reg_sequence },
+	[0x59] = { init_pll_indirect },
+	[0x5a] = { init_zm_reg_indirect },
 	[0x5b] = { init_sub_direct },
 	[0x5b] = { init_sub_direct },
 	[0x5c] = { init_jump },
 	[0x5c] = { init_jump },
 	[0x5e] = { init_i2c_if },
 	[0x5e] = { init_i2c_if },

+ 2 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c

@@ -180,7 +180,8 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz,
 	       struct gt215_clk_info *info)
 	       struct gt215_clk_info *info)
 {
 {
 	struct gt215_clk_priv *priv = (void *)clock;
 	struct gt215_clk_priv *priv = (void *)clock;
-	u32 oclk, sclk, sdiv, diff;
+	u32 oclk, sclk, sdiv;
+	s32 diff;
 
 
 	info->clk = 0;
 	info->clk = 0;
 
 

+ 8 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c

@@ -38,6 +38,14 @@ gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv)
 	nv_wr32(priv, 0x12004c, 0x4);
 	nv_wr32(priv, 0x12004c, 0x4);
 	nv_wr32(priv, 0x122204, 0x2);
 	nv_wr32(priv, 0x122204, 0x2);
 	nv_rd32(priv, 0x122204);
 	nv_rd32(priv, 0x122204);
+
+	/*
+	 * Bug: increase clock timeout to avoid operation failure at high
+	 * gpcclk rate.
+	 */
+	nv_wr32(priv, 0x122354, 0x800);
+	nv_wr32(priv, 0x128328, 0x800);
+	nv_wr32(priv, 0x124320, 0x800);
 }
 }
 
 
 static void
 static void

+ 8 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c

@@ -50,7 +50,12 @@ nv04_instobj_dtor(struct nvkm_object *object)
 {
 {
 	struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object);
 	struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object);
 	struct nv04_instobj_priv *node = (void *)object;
 	struct nv04_instobj_priv *node = (void *)object;
+	struct nvkm_subdev *subdev = (void *)priv;
+
+	mutex_lock(&subdev->mutex);
 	nvkm_mm_free(&priv->heap, &node->mem);
 	nvkm_mm_free(&priv->heap, &node->mem);
+	mutex_unlock(&subdev->mutex);
+
 	nvkm_instobj_destroy(&node->base);
 	nvkm_instobj_destroy(&node->base);
 }
 }
 
 
@@ -62,6 +67,7 @@ nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 	struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent);
 	struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent);
 	struct nv04_instobj_priv *node;
 	struct nv04_instobj_priv *node;
 	struct nvkm_instobj_args *args = data;
 	struct nvkm_instobj_args *args = data;
+	struct nvkm_subdev *subdev = (void *)priv;
 	int ret;
 	int ret;
 
 
 	if (!args->align)
 	if (!args->align)
@@ -72,8 +78,10 @@ nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
+	mutex_lock(&subdev->mutex);
 	ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size,
 	ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size,
 			   args->align, &node->mem);
 			   args->align, &node->mem);
+	mutex_unlock(&subdev->mutex);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 

+ 1 - 2
drivers/gpu/drm/radeon/atombios_encoders.c

@@ -2299,8 +2299,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 	encoder_mode = atombios_get_encoder_mode(encoder);
 	encoder_mode = atombios_get_encoder_mode(encoder);
 	if (connector && (radeon_audio != 0) &&
 	if (connector && (radeon_audio != 0) &&
 	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
 	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
-	     (ENCODER_MODE_IS_DP(encoder_mode) &&
-	      drm_detect_monitor_audio(radeon_connector_edid(connector)))))
+	     ENCODER_MODE_IS_DP(encoder_mode)))
 		radeon_audio_mode_set(encoder, adjusted_mode);
 		radeon_audio_mode_set(encoder, adjusted_mode);
 }
 }
 
 

+ 28 - 34
drivers/gpu/drm/radeon/dce6_afmt.c

@@ -93,30 +93,26 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder)
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u32 offset;
 
 
-	if (!dig || !dig->afmt || !dig->afmt->pin)
+	if (!dig || !dig->afmt || !dig->pin)
 		return;
 		return;
 
 
-	offset = dig->afmt->offset;
-
-	WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
-	       AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
+	WREG32(AFMT_AUDIO_SRC_CONTROL +  dig->afmt->offset,
+	       AFMT_AUDIO_SRC_SELECT(dig->pin->id));
 }
 }
 
 
 void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
 void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
-		struct drm_connector *connector, struct drm_display_mode *mode)
+				    struct drm_connector *connector,
+				    struct drm_display_mode *mode)
 {
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u32 tmp = 0, offset;
+	u32 tmp = 0;
 
 
-	if (!dig || !dig->afmt || !dig->afmt->pin)
+	if (!dig || !dig->afmt || !dig->pin)
 		return;
 		return;
 
 
-	offset = dig->afmt->pin->offset;
-
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		if (connector->latency_present[1])
 		if (connector->latency_present[1])
 			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
 			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
@@ -130,24 +126,24 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
 		else
 		else
 			tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
 			tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
 	}
 	}
-	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
+	WREG32_ENDPOINT(dig->pin->offset,
+			AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
 }
 }
 
 
 void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
 void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
-	u8 *sadb, int sad_count)
+					     u8 *sadb, int sad_count)
 {
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u32 offset, tmp;
+	u32 tmp;
 
 
-	if (!dig || !dig->afmt || !dig->afmt->pin)
+	if (!dig || !dig->afmt || !dig->pin)
 		return;
 		return;
 
 
-	offset = dig->afmt->pin->offset;
-
 	/* program the speaker allocation */
 	/* program the speaker allocation */
-	tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+	tmp = RREG32_ENDPOINT(dig->pin->offset,
+			      AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	/* set HDMI mode */
 	/* set HDMI mode */
 	tmp |= HDMI_CONNECTION;
 	tmp |= HDMI_CONNECTION;
@@ -155,24 +151,24 @@ void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 	else
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
-	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
+	WREG32_ENDPOINT(dig->pin->offset,
+			AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
 }
 }
 
 
 void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
 void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
-	u8 *sadb, int sad_count)
+					   u8 *sadb, int sad_count)
 {
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u32 offset, tmp;
+	u32 tmp;
 
 
-	if (!dig || !dig->afmt || !dig->afmt->pin)
+	if (!dig || !dig->afmt || !dig->pin)
 		return;
 		return;
 
 
-	offset = dig->afmt->pin->offset;
-
 	/* program the speaker allocation */
 	/* program the speaker allocation */
-	tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+	tmp = RREG32_ENDPOINT(dig->pin->offset,
+			      AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
 	tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	/* set DP mode */
 	/* set DP mode */
 	tmp |= DP_CONNECTION;
 	tmp |= DP_CONNECTION;
@@ -180,13 +176,13 @@ void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 	else
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
-	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
+	WREG32_ENDPOINT(dig->pin->offset,
+			AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
 }
 }
 
 
 void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
 void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
-	struct cea_sad *sads, int sad_count)
+			      struct cea_sad *sads, int sad_count)
 {
 {
-	u32 offset;
 	int i;
 	int i;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
@@ -206,11 +202,9 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
 		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
 		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
 	};
 	};
 
 
-	if (!dig || !dig->afmt || !dig->afmt->pin)
+	if (!dig || !dig->afmt || !dig->pin)
 		return;
 		return;
 
 
-	offset = dig->afmt->pin->offset;
-
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 		u32 value = 0;
 		u32 value = 0;
 		u8 stereo_freqs = 0;
 		u8 stereo_freqs = 0;
@@ -237,7 +231,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
 
 
 		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
 		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
 
 
-		WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value);
+		WREG32_ENDPOINT(dig->pin->offset, eld_reg_to_type[i][0], value);
 	}
 	}
 }
 }
 
 
@@ -253,7 +247,7 @@ void dce6_audio_enable(struct radeon_device *rdev,
 }
 }
 
 
 void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
 void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
-	struct radeon_crtc *crtc, unsigned int clock)
+			     struct radeon_crtc *crtc, unsigned int clock)
 {
 {
 	/* Two dtos; generally use dto0 for HDMI */
 	/* Two dtos; generally use dto0 for HDMI */
 	u32 value = 0;
 	u32 value = 0;
@@ -272,7 +266,7 @@ void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
 }
 }
 
 
 void dce6_dp_audio_set_dto(struct radeon_device *rdev,
 void dce6_dp_audio_set_dto(struct radeon_device *rdev,
-	struct radeon_crtc *crtc, unsigned int clock)
+			   struct radeon_crtc *crtc, unsigned int clock)
 {
 {
 	/* Two dtos; generally use dto1 for DP */
 	/* Two dtos; generally use dto1 for DP */
 	u32 value = 0;
 	u32 value = 0;

+ 97 - 107
drivers/gpu/drm/radeon/radeon_audio.c

@@ -245,6 +245,28 @@ static struct radeon_audio_funcs dce6_dp_funcs = {
 static void radeon_audio_enable(struct radeon_device *rdev,
 static void radeon_audio_enable(struct radeon_device *rdev,
 				struct r600_audio_pin *pin, u8 enable_mask)
 				struct r600_audio_pin *pin, u8 enable_mask)
 {
 {
+	struct drm_encoder *encoder;
+	struct radeon_encoder *radeon_encoder;
+	struct radeon_encoder_atom_dig *dig;
+	int pin_count = 0;
+
+	if (!pin)
+		return;
+
+	if (rdev->mode_info.mode_config_initialized) {
+		list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
+			if (radeon_encoder_is_digital(encoder)) {
+				radeon_encoder = to_radeon_encoder(encoder);
+				dig = radeon_encoder->enc_priv;
+				if (dig->pin == pin)
+					pin_count++;
+			}
+		}
+
+		if ((pin_count > 1) && (enable_mask == 0))
+			return;
+	}
+
 	if (rdev->audio.funcs->enable)
 	if (rdev->audio.funcs->enable)
 		rdev->audio.funcs->enable(rdev, pin, enable_mask);
 		rdev->audio.funcs->enable(rdev, pin, enable_mask);
 }
 }
@@ -336,24 +358,13 @@ void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset,
 
 
 static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
 static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
 {
 {
-	struct radeon_encoder *radeon_encoder;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct cea_sad *sads;
 	struct cea_sad *sads;
 	int sad_count;
 	int sad_count;
 
 
-	list_for_each_entry(connector,
-		&encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
+	if (!connector)
 		return;
 		return;
-	}
 
 
 	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
 	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
 	if (sad_count <= 0) {
 	if (sad_count <= 0) {
@@ -362,8 +373,6 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
 	}
 	}
 	BUG_ON(!sads);
 	BUG_ON(!sads);
 
 
-	radeon_encoder = to_radeon_encoder(encoder);
-
 	if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs)
 	if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs)
 		radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count);
 		radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count);
 
 
@@ -372,27 +381,16 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
 
 
 static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
 static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
 {
 {
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u8 *sadb = NULL;
 	u8 *sadb = NULL;
 	int sad_count;
 	int sad_count;
 
 
-	list_for_each_entry(connector,
-			    &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
+	if (!connector)
 		return;
 		return;
-	}
 
 
-	sad_count = drm_edid_to_speaker_allocation(
-		radeon_connector_edid(connector), &sadb);
+	sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector),
+						   &sadb);
 	if (sad_count < 0) {
 	if (sad_count < 0) {
 		DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n",
 		DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n",
 			  sad_count);
 			  sad_count);
@@ -406,26 +404,13 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
 }
 }
 
 
 static void radeon_audio_write_latency_fields(struct drm_encoder *encoder,
 static void radeon_audio_write_latency_fields(struct drm_encoder *encoder,
-	struct drm_display_mode *mode)
+					      struct drm_display_mode *mode)
 {
 {
-	struct radeon_encoder *radeon_encoder;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = 0;
-
-	list_for_each_entry(connector,
-		&encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
 
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
+	if (!connector)
 		return;
 		return;
-	}
-
-	radeon_encoder = to_radeon_encoder(encoder);
 
 
 	if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields)
 	if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields)
 		radeon_encoder->audio->write_latency_fields(encoder, connector, mode);
 		radeon_encoder->audio->write_latency_fields(encoder, connector, mode);
@@ -451,29 +436,23 @@ static void radeon_audio_select_pin(struct drm_encoder *encoder)
 }
 }
 
 
 void radeon_audio_detect(struct drm_connector *connector,
 void radeon_audio_detect(struct drm_connector *connector,
+			 struct drm_encoder *encoder,
 			 enum drm_connector_status status)
 			 enum drm_connector_status status)
 {
 {
-	struct radeon_device *rdev;
-	struct radeon_encoder *radeon_encoder;
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig;
 	struct radeon_encoder_atom_dig *dig;
 
 
-	if (!connector || !connector->encoder)
+	if (!radeon_audio_chipset_supported(rdev))
 		return;
 		return;
 
 
-	rdev = connector->encoder->dev->dev_private;
-
-	if (!radeon_audio_chipset_supported(rdev))
+	if (!radeon_encoder_is_digital(encoder))
 		return;
 		return;
 
 
-	radeon_encoder = to_radeon_encoder(connector->encoder);
 	dig = radeon_encoder->enc_priv;
 	dig = radeon_encoder->enc_priv;
 
 
 	if (status == connector_status_connected) {
 	if (status == connector_status_connected) {
-		if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) {
-			radeon_encoder->audio = NULL;
-			return;
-		}
-
 		if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
 		if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
 			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
 
@@ -486,11 +465,17 @@ void radeon_audio_detect(struct drm_connector *connector,
 			radeon_encoder->audio = rdev->audio.hdmi_funcs;
 			radeon_encoder->audio = rdev->audio.hdmi_funcs;
 		}
 		}
 
 
-		dig->afmt->pin = radeon_audio_get_pin(connector->encoder);
-		radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+		if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+			if (!dig->pin)
+				dig->pin = radeon_audio_get_pin(encoder);
+			radeon_audio_enable(rdev, dig->pin, 0xf);
+		} else {
+			radeon_audio_enable(rdev, dig->pin, 0);
+			dig->pin = NULL;
+		}
 	} else {
 	} else {
-		radeon_audio_enable(rdev, dig->afmt->pin, 0);
-		dig->afmt->pin = NULL;
+		radeon_audio_enable(rdev, dig->pin, 0);
+		dig->pin = NULL;
 	}
 	}
 }
 }
 
 
@@ -518,29 +503,18 @@ static void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock
 }
 }
 
 
 static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
 static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
-	struct drm_display_mode *mode)
+				       struct drm_display_mode *mode)
 {
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
 	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
 	struct hdmi_avi_infoframe frame;
 	struct hdmi_avi_infoframe frame;
 	int err;
 	int err;
 
 
-	list_for_each_entry(connector,
-		&encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return -ENOENT;
-	}
+	if (!connector)
+		return -EINVAL;
 
 
 	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 	if (err < 0) {
 	if (err < 0) {
@@ -563,8 +537,8 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
 		return err;
 		return err;
 	}
 	}
 
 
-	if (dig && dig->afmt &&
-		radeon_encoder->audio && radeon_encoder->audio->set_avi_packet)
+	if (dig && dig->afmt && radeon_encoder->audio &&
+	    radeon_encoder->audio->set_avi_packet)
 		radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset,
 		radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset,
 			buffer, sizeof(buffer));
 			buffer, sizeof(buffer));
 
 
@@ -722,30 +696,41 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
 {
 {
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
 
 	if (!dig || !dig->afmt)
 	if (!dig || !dig->afmt)
 		return;
 		return;
 
 
-	radeon_audio_set_mute(encoder, true);
+	if (!connector)
+		return;
 
 
-	radeon_audio_write_speaker_allocation(encoder);
-	radeon_audio_write_sad_regs(encoder);
-	radeon_audio_write_latency_fields(encoder, mode);
-	radeon_audio_set_dto(encoder, mode->clock);
-	radeon_audio_set_vbi_packet(encoder);
-	radeon_hdmi_set_color_depth(encoder);
-	radeon_audio_update_acr(encoder, mode->clock);
-	radeon_audio_set_audio_packet(encoder);
-	radeon_audio_select_pin(encoder);
+	if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+		radeon_audio_set_mute(encoder, true);
 
 
-	if (radeon_audio_set_avi_packet(encoder, mode) < 0)
-		return;
+		radeon_audio_write_speaker_allocation(encoder);
+		radeon_audio_write_sad_regs(encoder);
+		radeon_audio_write_latency_fields(encoder, mode);
+		radeon_audio_set_dto(encoder, mode->clock);
+		radeon_audio_set_vbi_packet(encoder);
+		radeon_hdmi_set_color_depth(encoder);
+		radeon_audio_update_acr(encoder, mode->clock);
+		radeon_audio_set_audio_packet(encoder);
+		radeon_audio_select_pin(encoder);
+
+		if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+			return;
 
 
-	radeon_audio_set_mute(encoder, false);
+		radeon_audio_set_mute(encoder, false);
+	} else {
+		radeon_hdmi_set_color_depth(encoder);
+
+		if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+			return;
+	}
 }
 }
 
 
 static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
 static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
-	struct drm_display_mode *mode)
+				     struct drm_display_mode *mode)
 {
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_device *rdev = dev->dev_private;
@@ -759,22 +744,27 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
 	if (!dig || !dig->afmt)
 	if (!dig || !dig->afmt)
 		return;
 		return;
 
 
-	radeon_audio_write_speaker_allocation(encoder);
-	radeon_audio_write_sad_regs(encoder);
-	radeon_audio_write_latency_fields(encoder, mode);
-	if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev))
-		radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
-	else
-		radeon_audio_set_dto(encoder, dig_connector->dp_clock);
-	radeon_audio_set_audio_packet(encoder);
-	radeon_audio_select_pin(encoder);
-
-	if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+	if (!connector)
 		return;
 		return;
+
+	if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+		radeon_audio_write_speaker_allocation(encoder);
+		radeon_audio_write_sad_regs(encoder);
+		radeon_audio_write_latency_fields(encoder, mode);
+		if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev))
+			radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
+		else
+			radeon_audio_set_dto(encoder, dig_connector->dp_clock);
+		radeon_audio_set_audio_packet(encoder);
+		radeon_audio_select_pin(encoder);
+
+		if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+			return;
+	}
 }
 }
 
 
 void radeon_audio_mode_set(struct drm_encoder *encoder,
 void radeon_audio_mode_set(struct drm_encoder *encoder,
-	struct drm_display_mode *mode)
+			   struct drm_display_mode *mode)
 {
 {
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
 

Some files were not shown because too many files changed in this diff